From 08f207a930ea0591f733ac4a87ea787a65dfa07c Mon Sep 17 00:00:00 2001 From: "edwin.zhai" Date: Fri, 9 Nov 2012 08:37:05 +0800 Subject: [PATCH] GL: enable HW GL acceleration on Mac Signed-off-by: Gao, Fengqian Signed-off-by: Zhai, Edwin --- configure | 4 +- hw/virtio-pci.c | 4 +- tizen/emulator_configure.sh | 2 +- tizen/src/Makefile.tizen | 10 +- tizen/src/hw/gloffscreen_agl.c | 353 ++++++++++++++++++++++++++++++++++ tizen/src/hw/gloffscreen_xcomposite.c | 2 +- tizen/src/hw/helper_opengl.c | 6 + vl.c | 8 +- 8 files changed, 375 insertions(+), 14 deletions(-) create mode 100644 tizen/src/hw/gloffscreen_agl.c diff --git a/configure b/configure index 5bebb8d..823d122 100755 --- a/configure +++ b/configure @@ -4057,10 +4057,12 @@ if test "$hax" = "yes" ; then fi if test "$gl" = "yes" ; then case "$target_arch2" in - i386|x86_64) + i386|x86_64|arm) echo "CONFIG_GL=y" >> $config_target_mak if test "$mingw32" = "yes" ; then echo "LIBS+=-lopengl32 -lglu32" >> $config_target_mak + elif test "$darwin" = "yes" ; then + echo "LIBS+=-framework OpenGL -framework AGL " >> $config_target_mak else echo "LIBS+=-lGLU -ldl" >> $config_target_mak fi diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 579d05b..d8b41bb 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -886,7 +886,7 @@ static void virtio_balloon_exit_pci(PCIDevice *pci_dev) } #ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) static int virtio_gl_init_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); @@ -1137,7 +1137,7 @@ static TypeInfo virtio_scsi_info = { .class_init = virtio_scsi_class_init, }; -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) #ifdef CONFIG_GL_BACKEND static void virtio_gl_class_init(ObjectClass *klass, void *data) { diff --git a/tizen/emulator_configure.sh b/tizen/emulator_configure.sh index 0ab2a4c..deaee48 100755 --- a/tizen/emulator_configure.sh +++ b/tizen/emulator_configure.sh @@ -280,7 +280,7 @@ echo "##### QEMU configure append:" $CONFIGURE_APPEND --enable-hax \ --disable-vnc \ --disable-cocoa \ - --disable-gl \ + --enable-gl \ --disable-sdl $1 ;; esac diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen index d00bcb0..ede2c29 100755 --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -35,7 +35,7 @@ else GL_CFLAGS := -Wall -g -O2 -fno-strict-aliasing endif -ifndef CONFIG_DARWIN +#ifndef CONFIG_DARWIN ########################################################### ## Build openGL # i386 @@ -82,7 +82,7 @@ obj-y += gl_mangled.o endif #CONFIG_OPENGLES ########################################################### -endif #!CONFIG_DARWIN +#endif #!CONFIG_DARWIN # maru loader obj-y += emulator.o emul_state.o option.o maru_err_table.o @@ -129,12 +129,12 @@ obj-y += maruskin_client.o maruskin_server.o maruskin_operation.o maruskin_keyma # guest server obj-y += guest_server.o -ifndef CONFIG_DARWIN +#ifndef CONFIG_DARWIN ########################################################### ## opengl library for i386 obj-$(CONFIG_GL) += virtio-gl.o obj-$(CONFIG_GL) += helper_opengl.o opengl_exec.o mesa_mipmap.o obj-$(CONFIG_NO_GL) += virtio-gl-stub.o -obj-y += gloffscreen_test.o gloffscreen_xcomposite.o gloffscreen_common.o gloffscreen_wgl.o +obj-y += gloffscreen_test.o gloffscreen_xcomposite.o gloffscreen_common.o gloffscreen_wgl.o gloffscreen_agl.o ########################################################### -endif +#endif diff --git a/tizen/src/hw/gloffscreen_agl.c b/tizen/src/hw/gloffscreen_agl.c new file mode 100644 index 0000000..80577a3 --- /dev/null +++ b/tizen/src/hw/gloffscreen_agl.c @@ -0,0 +1,353 @@ +/*Offscreen OpenGL abstraction layer - AGL specific +* +* Copyright (c) 2010 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifdef __APPLE__ + +#include +#include +#include +#include +#include +/*hack due to conflicting typedefs in qemu's softfloat.h*/ +#define __SECURITYHI__ 1 + +#include +#include +#include "gloffscreen.h" + +#ifdef GL_DEBUG +#define TRACE(fmt, ...) printf("%s@%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(...) +#endif + +struct _GloContext +{ + GLuint formatFlags; + AGLPixelFormat pixelFormat; + AGLContext context; + }; + +struct _GloSurface +{ + GLuint width; + GLuint height; + GloContext *context; + AGLPbuffer pbuffer; + }; + +extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, + int bpp, int width, int height, + void *data); + + + +/* Initialise gloffscreen */ +int glo_init(void) +{ + int major, minor; + aglGetVersion(&major, &minor); + fprintf(stdout, "%s----AGL version %d.%d\n",__FUNCTION__, major, minor); + return 0; + } + +/* Uninitialise gloffscreen */ +void glo_kill(void) +{ + +} + +const char *glo_glXQueryExtensionsString(void) +{ + return ""; + } + +/* Like wglGetProcAddress/glxGetProcAddress */ + void *glo_getprocaddress(const char *procName) + { + void *ret = NULL; + + if (procName) + { + if (!strncmp(procName, "glX", 3)) + ret = (void *)1; + else + ret = dlsym(RTLD_NEXT, procName); + } + +#if 0//standard code for mac to look up procaddress, but seems slow that above. + NSSymbol symbol; + char *symbolname; + symbolname = malloc(strlen(procName) +2); + strcpy(symbolname +1, procName); + symbolname[0] = '_'; + symbol = NULL; + if(NSIsSymbolNameDefined(symbolname)) + symbol = NSLookupAndBindSymbol(symbolname); + free(symbolname); + ret = symbol ? NSAddressOfSymbol (symbol) : NULL; +#endif + TRACE("'%s' --> %p", procName, ret); + return ret; +} + +/* Create an OpenGL context for a certain pixel format. +* formatflags are from the GLO_ constants +*/ + +GloContext *__glo_context_create(int formatFlags) +{ + int rgba[4]; + glo_flags_get_rgba_bits(formatFlags, rgba); + const int attribs[] = { + AGL_RGBA, + AGL_MINIMUM_POLICY, + AGL_PIXEL_SIZE, glo_flags_get_bytes_per_pixel(formatFlags) * 8, + AGL_RED_SIZE, rgba[0], + AGL_GREEN_SIZE, rgba[1], + AGL_BLUE_SIZE, rgba[2], + AGL_ALPHA_SIZE, rgba[3], + AGL_DEPTH_SIZE, glo_flags_get_depth_bits(formatFlags), + AGL_STENCIL_SIZE, glo_flags_get_stencil_bits(formatFlags), + AGL_ACCELERATED, + AGL_NO_RECOVERY, + AGL_NONE + }; + + TRACE("req %dbpp %d-%d-%d-%d depth %d stencil %d", + glo_flags_get_bytes_per_pixel(formatFlags) * 8, + rgba[0], rgba[1], rgba[2], rgba[3], + glo_flags_get_depth_bits(formatFlags), + glo_flags_get_stencil_bits(formatFlags)); + + AGLPixelFormat pf = aglChoosePixelFormat(NULL, 0, attribs); + if (pf == NULL) + fprintf(stderr, "No matching pixelformat found."); + else + { + GLint bpp = 0, a = 0, d = 0, s = 0; + aglDescribePixelFormat(pf, AGL_PIXEL_SIZE, &bpp); + aglDescribePixelFormat(pf, AGL_ALPHA_SIZE, &a); + aglDescribePixelFormat(pf, AGL_DEPTH_SIZE, &d); + aglDescribePixelFormat(pf, AGL_STENCIL_SIZE, &s); + + formatFlags &= ~(GLO_FF_ALPHA_MASK | GLO_FF_BITS_MASK | GLO_FF_DEPTH_MASK | GLO_FF_STENCIL_MASK); + switch (bpp) { + case 16: formatFlags |= GLO_FF_BITS_16; break; + case 24: formatFlags |= GLO_FF_BITS_24; break; + case 32: formatFlags |= GLO_FF_BITS_32; break; + default: fprintf(stderr, "got unsupported bpp %d", bpp); break; + } + + if (a > 0) + { + formatFlags |= GLO_FF_ALPHA; + } + + switch (d) { + case 0: break; + case 16: formatFlags |= GLO_FF_DEPTH_16; break; + case 24: formatFlags |= GLO_FF_DEPTH_24; break; + case 32: formatFlags |= GLO_FF_DEPTH_32; break; + default: fprintf(stderr, "got unsupported depth %d", d); break; + } + + switch (s) { + case 0: break; + case 8: formatFlags |= GLO_FF_STENCIL_8; break; + default: fprintf(stderr, "got unsupported stencil %d", s); break; + } + } + GloContext *context = (GloContext *)malloc(sizeof(*context)); + memset(context, 0, sizeof(*context)); + context->formatFlags = formatFlags; + context->pixelFormat = pf; + + return context; + +} + +GloContext *glo_context_create(int formatFlags, GloContext *shareLists) +{ + GloContext *context = __glo_context_create(formatFlags); + if(!context) + return NULL; + + context->context = aglCreateContext(context->pixelFormat, shareLists ? shareLists->context : NULL); + if (context->context == NULL) + { + fprintf(stderr, "aglCreateContext failed: %s", aglErrorString(aglGetError())); + } + + TRACE("context=%p", context); + return context; +} + +/* Destroy a previously created OpenGL context */ +void glo_context_destroy(GloContext *context) +{ + TRACE("context=%p", context); + if (context) + { + aglDestroyContext(context->context); + aglDestroyPixelFormat(context->pixelFormat); + context->context = NULL; + context->pixelFormat = NULL; + free(context); + } + } + +int glo_surface_update_context(GloSurface *surface, GloContext *context) +{ + + int prev_context_valid = 0; + + if ( surface->context ) + { + prev_context_valid = (surface->context->context != 0); + if ( !prev_context_valid ) /* light-weight context */ + g_free(surface->context); + } + surface->context = context; + + return prev_context_valid; +} + + + +/* Create a surface with given width and height, formatflags are from the + * GLO_ constants */ +GloSurface *glo_surface_create(int width, int height, GloContext *context) +{ + GloSurface *surface = NULL; + if (context) + { + surface = (GloSurface *)malloc(sizeof(*surface)); + memset(surface, 0, sizeof(*surface)); + surface->width = width; + surface->height = height; + surface->context = context; + + TRACE("%dx%d", surface->width, surface->height); + if (aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &surface->pbuffer) == GL_FALSE) + fprintf(stderr, "aglCreatePbuffer failed: %s", aglErrorString(aglGetError())); + + } + TRACE("surface=%p", surface); + return surface; +} + +/* Destroy the given surface */ +void glo_surface_destroy(GloSurface *surface) +{ + TRACE("surface=%p", surface); + if (surface) + { + aglDestroyPBuffer(surface->pbuffer); + surface->pbuffer = NULL; + free(surface); + } +} + +/* Make the given surface current */ +int glo_surface_makecurrent(GloSurface *surface) +{ + int ret = GL_FALSE; + TRACE("surface=%p", surface); + if (surface) + { + if (aglSetPBuffer(surface->context->context, surface->pbuffer, 0, 0, 0) == GL_FALSE) + fprintf(stderr, "aglSetPbuffer failed: %s", aglErrorString(aglGetError())); + ret = aglSetCurrentContext(surface->context->context); + } else + { + ret = aglSetCurrentContext(NULL); + } + + if (ret == GL_FALSE) + fprintf(stderr, "aglSetCurrentContext failed: %s", aglErrorString(aglGetError())); + + TRACE("Return ret=%d\n", ret); + return ret; + } + +void glo_surface_updatecontents(GloSurface *surface) +{ + const GLint swap_interval = 1; + + if(!surface) + return; + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); +} + + +/* Get the contents of the given surface */ +void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, + void *data) +{ + const GLint swap_interval = 1; + if (surface) + { + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); + glo_surface_getcontents_readpixels(surface->context->formatFlags, stride, bpp, surface->width, surface->height, data); + } +} + +/* Return the width and height of the given surface */ +void glo_surface_get_size(GloSurface *surface, int *width, int *height) +{ + if (width) + { + *width = surface->width; + } + + if (height) + { + *height = surface->height; + } +} + +/* Bind the surface as texture */ +void glo_surface_as_texture(GloSurface *surface) +{ + //Not QUit sure about this function; + int glFormat, glType; + glo_surface_updatecontents(surface); + /*XXX: changet the fixed target: GL_TEXTURE_2D*/ + glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, &glType); + fprintf(stderr, "surface_as_texture:teximage:width=%d,height=%d, glFormat=0x%x, glType=0x%x.\n", surface->width, surface->height, glFormat, glType); + /* glTexImage2D use different RGB order than the contexts in the pixmap surface */ +/* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->image->data);*/ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, glFormat, glType, surface->pbuffer); + + +} + +void glo_surface_release_texture(GloSurface *surface) +{ + +} + +#endif + diff --git a/tizen/src/hw/gloffscreen_xcomposite.c b/tizen/src/hw/gloffscreen_xcomposite.c index c7a221f..a396468 100644 --- a/tizen/src/hw/gloffscreen_xcomposite.c +++ b/tizen/src/hw/gloffscreen_xcomposite.c @@ -24,7 +24,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef _WIN32 +#if (!defined _WIN32) && (!defined __APPLE__) #include "gloffscreen.h" #include diff --git a/tizen/src/hw/helper_opengl.c b/tizen/src/hw/helper_opengl.c index fa0d810..83a0f4f 100644 --- a/tizen/src/hw/helper_opengl.c +++ b/tizen/src/hw/helper_opengl.c @@ -65,6 +65,7 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int char *argptr, *tmp; static void* args[50]; int func_number; + char temp4mac[256]; if(!args_len) return 0; @@ -136,7 +137,12 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int if (args_size == 0) { *(int*)r_buffer = 0; r_buffer += 4; +#ifdef __APPLE__ +/*On MAC OS, GL call glGetProgramInfoLog and glGetShaderInfoLog will crash if ouput pointer is NULL*/ + args[i] = temp4mac; +#else args[i] = NULL; +#endif } else if(*(int*)argptr) { *(int*)r_buffer = args_size; r_buffer+=4; diff --git a/vl.c b/vl.c index 1200298..10fff6a 100644 --- a/vl.c +++ b/vl.c @@ -262,7 +262,7 @@ uint8_t qemu_extra_params_fw[2]; //virtio-gl #define VIRTIOGL_DEV_NAME "virtio-gl-pci" -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) extern int gl_acceleration_capability_check(void); int enable_gl = 0; int capability_check_gl = 0; @@ -1978,7 +1978,7 @@ static int device_init_func(QemuOpts *opts, void *opaque) DeviceState *dev; #ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) // virtio-gl pci device if (!enable_gl) { // ignore virtio-gl-pci device, even if users set it in option. @@ -3202,7 +3202,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_enable_gl: #ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) enable_gl = 1; #endif #else @@ -3504,7 +3504,7 @@ int main(int argc, char **argv, char **envp) } #ifdef CONFIG_GL_BACKEND -#if defined(CONFIG_MARU) && (!defined(CONFIG_DARWIN)) +#if defined(CONFIG_MARU) if (enable_gl) { capability_check_gl = gl_acceleration_capability_check(); -- 2.7.4