From: Patrick Porlan Date: Fri, 6 Sep 2013 15:05:13 +0000 (+0200) Subject: Initial version of YaGL Mac support module X-Git-Tag: TizenStudio_2.0_p2.3~633 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b9ca27b72b82177137c2dad4250171638307d4c4;p=sdk%2Femulator%2Fqemu.git Initial version of YaGL Mac support module This adds a preliminary AGL based implementation of YaGL platform-specific routines, as well as a few additional changes: - base EGL types suitables of OS X in eglplatform.h - changes to both configure and makefiles to enable YaGL and VIGS - an empty VIGS support module Both YaGL and VIGS files compile and link, however only YaGL runs for now. To try it, replace -enable-gl by enable-yagl in the qemu command line, after installing adequate emulator-yagl and libdrm packages in the root FS. /etc/virtgl.sh should detect that YaGL is enabled and switch the EGL libs to the YaGL version --- diff --git a/Makefile.target b/Makefile.target old mode 100755 new mode 100644 index ecfe538..6b20d09 --- a/Makefile.target +++ b/Makefile.target @@ -168,6 +168,7 @@ $(call set-vpath, $(SRC_PATH)/hw/yagl_apis/egl: \ $(SRC_PATH)/hw/yagl_backends/egl_onscreen: \ $(SRC_PATH)/hw/yagl_drivers/egl_glx: \ $(SRC_PATH)/hw/yagl_drivers/egl_wgl: \ + $(SRC_PATH)/hw/yagl_drivers/egl_agl: \ $(SRC_PATH)/hw/yagl_drivers/gles_ogl: \ $(SRC_PATH)/hw/yagl_drivers/gles_onscreen: \ $(SRC_PATH)/hw/yagl_drivers/gles1_ogl: \ @@ -278,6 +279,11 @@ endif ifdef CONFIG_WIN32 obj-y += yagl_egl_wgl.o endif +# EGL AGL driver +ifdef CONFIG_DARWIN +QEMU_CFLAGS += -Wno-comment +obj-y += yagl_egl_agl.o +endif # GLES OpenGL common driver obj-y += yagl_gles_ogl.o # GLESv1_CM OpenGL driver @@ -317,6 +323,10 @@ endif ifdef CONFIG_WIN32 obj-y += vigs_gl_backend_wgl.o endif +# GL AGL backend +ifdef CONFIG_DARWIN +obj-y += vigs_gl_backend_agl.o +endif endif diff --git a/configure b/configure old mode 100755 new mode 100644 index 4263e07..eaee473 --- a/configure +++ b/configure @@ -3973,7 +3973,8 @@ if test "$yagl" = "yes" ; then echo -n; elif test "$mingw32" = "yes" ; then echo -n; - else + elif test "$darwin" = "yes" ; then + echo -n; else echo "ERROR: YaGL is not available on $targetos" exit 1 fi diff --git a/hw/vigs_gl_backend_agl.c b/hw/vigs_gl_backend_agl.c new file mode 100644 index 0000000..19c5815 --- /dev/null +++ b/hw/vigs_gl_backend_agl.c @@ -0,0 +1,12 @@ +#include "vigs_gl_backend.h" +#include "vigs_log.h" + +struct vigs_gl_backend_agl +{ + struct vigs_gl_backend base; +} + +struct vigs_backend *vigs_gl_backend_create(void *display) +{ + return NULL; +} diff --git a/hw/yagl_drivers/egl_agl/yagl_egl_agl.c b/hw/yagl_drivers/egl_agl/yagl_egl_agl.c new file mode 100644 index 0000000..19d613f --- /dev/null +++ b/hw/yagl_drivers/egl_agl/yagl_egl_agl.c @@ -0,0 +1,396 @@ +#include +#include +#include +#include "yagl_egl_driver.h" +#include "yagl_dyn_lib.h" +#include "yagl_log.h" +#include "yagl_egl_native_config.h" +#include "yagl_egl_surface_attribs.h" +#include "yagl_process.h" +#include "yagl_tls.h" +#include "yagl_thread.h" + +#define LIBGL_IMAGE_NAME \ +"/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" + +#define YAGL_LOG_AGL_STATUS() \ + YAGL_LOG_ERROR("AGL status: %s", aglErrorString(aglGetError())) + +typedef struct YaglEglAglContext { + AGLContext context; +} YaglEglAglContext; + +typedef struct YaglEglAglDriver { + struct yagl_egl_driver base; +} YaglEglAglDriver; + + +static EGLNativeDisplayType +yagl_egl_agl_display_open(struct yagl_egl_driver *driver) +{ + void* dpy = (void*) 0x1; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_display_open, NULL); + + YAGL_LOG_FUNC_EXIT("Display created: %p", dpy); + + return (EGLNativeDisplayType) dpy; +} + + +static void yagl_egl_agl_display_close(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_display_close, "%p", egl_dpy); + + YAGL_LOG_FUNC_EXIT(NULL); +} + + +static struct yagl_egl_native_config + *yagl_egl_agl_config_enum(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + int *num_configs) +{ + struct yagl_egl_native_config *egl_configs = NULL; + struct yagl_egl_native_config *cur_config; + int usable_configs = 0; + + const int attrib_list[] = { + AGL_RGBA, + AGL_ACCELERATED, + AGL_MINIMUM_POLICY, + AGL_BUFFER_SIZE, 32, + AGL_RED_SIZE, 8, + AGL_GREEN_SIZE, 8, + AGL_BLUE_SIZE, 8, + AGL_ALPHA_SIZE, 8, + AGL_DEPTH_SIZE, 24, + AGL_STENCIL_SIZE, 8, + AGL_NO_RECOVERY, + AGL_DOUBLEBUFFER, + AGL_PBUFFER, + AGL_NONE + }; + AGLPixelFormat pixfmt; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_config_enum, "display %p", egl_dpy); + + + /* Enumerate AGL pixel formats matching our constraints */ + + pixfmt = aglChoosePixelFormat(NULL, 0, attrib_list); + + while (pixfmt) { + egl_configs = g_renew(struct yagl_egl_native_config, + egl_configs, + usable_configs+1); + + cur_config = &egl_configs[usable_configs]; + + /* Initialize fields */ + yagl_egl_native_config_init(cur_config); + + cur_config->transparent_type = EGL_NONE; + cur_config->config_id = usable_configs; + + aglDescribePixelFormat(pixfmt, AGL_BUFFER_SIZE, &cur_config->buffer_size); + aglDescribePixelFormat(pixfmt, AGL_RED_SIZE, &cur_config->red_size); + aglDescribePixelFormat(pixfmt, AGL_GREEN_SIZE,&cur_config->green_size); + aglDescribePixelFormat(pixfmt, AGL_BLUE_SIZE, &cur_config->blue_size); + aglDescribePixelFormat(pixfmt, AGL_ALPHA_SIZE, &cur_config->alpha_size); + aglDescribePixelFormat(pixfmt, AGL_DEPTH_SIZE, &cur_config->depth_size); + aglDescribePixelFormat(pixfmt, AGL_STENCIL_SIZE, &cur_config->stencil_size); + + cur_config->max_pbuffer_width = 4096; + cur_config->max_pbuffer_height = 4096; + cur_config->max_pbuffer_size = 4096*4096; + cur_config->native_visual_type = EGL_NONE; + cur_config->native_visual_id = 0; + cur_config->caveat = EGL_NONE; + cur_config->frame_buffer_level = 0; + cur_config->samples_per_pixel = 0; + cur_config->max_swap_interval = 1000; + cur_config->min_swap_interval = 0; + + cur_config->driver_data = (void*) pixfmt; + + usable_configs++; + + pixfmt = aglNextPixelFormat(pixfmt); + } + + YAGL_LOG_FUNC_EXIT("Enumerated %d configs", usable_configs); + + /* It's up to the caller to call config_cleanup on each + of the returned entries, as well as call g_free on the array */ + + *num_configs = usable_configs; + return egl_configs; +} + + +static void yagl_egl_agl_config_cleanup(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + const struct yagl_egl_native_config *cfg) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_config_cleanup, + "dpy = %p, cfg = %d", + egl_dpy, cfg->config_id); + + aglDestroyPixelFormat(cfg->driver_data); + + YAGL_LOG_FUNC_EXIT(NULL); +} + + +static EGLContext yagl_egl_agl_context_create(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + const struct yagl_egl_native_config *cfg, + yagl_client_api client_api, + EGLContext share_context) +{ + YaglEglAglContext *egl_glc; + AGLContext agl_share_glc; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_context_create, + "dpy = %p, api = %u, share_context = %p, cfgid=%d", + egl_dpy, client_api, share_context, cfg->config_id); + + egl_glc = g_new0(YaglEglAglContext, 1); + + if (share_context != EGL_NO_CONTEXT) { + agl_share_glc = ((YaglEglAglContext*)share_context)->context; + } + else + agl_share_glc = NULL; + + egl_glc->context = aglCreateContext(cfg->driver_data, agl_share_glc); + + if (!egl_glc->context) + goto fail; + + YAGL_LOG_FUNC_EXIT("Context created: %p", egl_glc); + + return (EGLContext)egl_glc; + +fail: + g_free(egl_glc); + + YAGL_LOG_AGL_STATUS(); + YAGL_LOG_FUNC_EXIT("Failed to create new context"); + + return EGL_NO_CONTEXT; +} + + +static bool yagl_egl_agl_make_current(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + EGLSurface egl_draw_surf, + EGLSurface egl_read_surf, + EGLContext egl_glc) +{ + AGLContext context = NULL; + AGLPbuffer draw_buf = NULL; + AGLPbuffer read_buf = NULL; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_make_current, + "dpy = %p, draw = %p, read = %p, ctx = %p", + egl_dpy, + egl_draw_surf, + egl_read_surf, + egl_glc); + + if (egl_glc != EGL_NO_CONTEXT) { + context = ((YaglEglAglContext*) egl_glc)->context; + } + + if (egl_read_surf != EGL_NO_SURFACE) { + read_buf = (AGLPbuffer) egl_read_surf; + + if (aglSetPBuffer(context, read_buf, 0, 0, 0) == GL_FALSE) { + goto fail; + } + } + + if (egl_draw_surf != EGL_NO_SURFACE) { + draw_buf = (AGLPbuffer) egl_draw_surf; + + if (aglSetPBuffer(context, draw_buf, 0, 0, 0) == GL_FALSE) { + goto fail; + } + } + + if (aglSetCurrentContext(context) == GL_FALSE) { + goto fail; + } + + YAGL_LOG_FUNC_EXIT("context %p was made current", context); + + return true; + +fail: + YAGL_LOG_AGL_STATUS(); + + YAGL_LOG_FUNC_EXIT("Failed to make context %p current", context); + + return false; +} + + +static void yagl_egl_agl_context_destroy(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + EGLContext egl_glc) +{ + AGLContext context; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_context_destroy, + "dpy = %p, ctx = %p", + egl_dpy, egl_glc); + + if (egl_glc != EGL_NO_CONTEXT) { + context = ((YaglEglAglContext*) egl_glc)->context; + + if (aglDestroyContext(context) == GL_TRUE) { + g_free(egl_glc); + YAGL_LOG_FUNC_EXIT("Context destroyed"); + return; + } + + g_free(egl_glc); + YAGL_LOG_AGL_STATUS(); + } + + YAGL_LOG_FUNC_EXIT("Could not destroy context"); +} + + +static EGLSurface yagl_egl_agl_pbuffer_surface_create(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + const struct yagl_egl_native_config *cfg, + EGLint width, + EGLint height, + const struct yagl_egl_pbuffer_attribs *attribs) +{ + AGLPbuffer pbuffer = NULL; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_pbuffer_surface_create, + "dpy = %p, width = %d, height = %d, cfgid=%d", + egl_dpy, + width, + height, + cfg->config_id); + + if (aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &pbuffer) == GL_FALSE) + goto fail; + + YAGL_LOG_FUNC_EXIT("Surface created: %p", pbuffer); + + return (EGLSurface)pbuffer; + +fail: + YAGL_LOG_AGL_STATUS(); + YAGL_LOG_FUNC_EXIT("Surface creation failed"); + + return EGL_NO_SURFACE; +} + + +static void yagl_egl_agl_pbuffer_surface_destroy(struct yagl_egl_driver *driver, + EGLNativeDisplayType egl_dpy, + EGLSurface surf) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_pbuffer_surface_destroy, + "dpy = %p, sfc = %p", + egl_dpy, + (AGLPbuffer)surf); + + if (aglDestroyPBuffer((AGLPbuffer)surf) == GL_FALSE) { + YAGL_LOG_AGL_STATUS(); + YAGL_LOG_FUNC_EXIT("Failed to destroy surface"); + } else { + YAGL_LOG_FUNC_EXIT("Surface destroyed"); + } +} + + +static void yagl_egl_agl_destroy(struct yagl_egl_driver *driver) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_destroy, NULL); + + yagl_egl_driver_cleanup(driver); + + g_free(driver); + + YAGL_LOG_FUNC_EXIT(NULL); +} + + +struct yagl_egl_driver *yagl_egl_driver_create(void *display) +{ + YaglEglAglDriver *egl_agl; + struct yagl_egl_driver *egl_driver; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_create, NULL); + + egl_agl = g_try_new0(YaglEglAglDriver, 1); + + if (!egl_agl) + goto inconceivable; + + egl_driver = &egl_agl->base; + + /* Initialize portable YaGL machinery */ + yagl_egl_driver_init(egl_driver); + + egl_driver->display_open = &yagl_egl_agl_display_open; + egl_driver->display_close = &yagl_egl_agl_display_close; + egl_driver->config_enum = &yagl_egl_agl_config_enum; + egl_driver->config_cleanup = &yagl_egl_agl_config_cleanup; + egl_driver->pbuffer_surface_create = &yagl_egl_agl_pbuffer_surface_create; + egl_driver->pbuffer_surface_destroy = &yagl_egl_agl_pbuffer_surface_destroy; + egl_driver->context_create = &yagl_egl_agl_context_create; + egl_driver->context_destroy = &yagl_egl_agl_context_destroy; + egl_driver->make_current = &yagl_egl_agl_make_current; + egl_driver->destroy = &yagl_egl_agl_destroy; + + egl_driver->dyn_lib = yagl_dyn_lib_create(); + + if (!yagl_dyn_lib_load(egl_driver->dyn_lib, LIBGL_IMAGE_NAME)) { + YAGL_LOG_ERROR("Loading %s failed with error: %s", + LIBGL_IMAGE_NAME, + yagl_dyn_lib_get_error(egl_driver->dyn_lib)); + goto fail; + } + + YAGL_LOG_FUNC_EXIT("EGL AGL driver created (%p)", egl_driver); + + return egl_driver; + +fail: + yagl_egl_driver_cleanup(egl_driver); + g_free(egl_agl); + +inconceivable: + YAGL_LOG_AGL_STATUS(); + YAGL_LOG_FUNC_EXIT("EGL_AGL driver creation failed"); + + return NULL; +} + + +void *yagl_dyn_lib_get_ogl_procaddr(struct yagl_dyn_lib *dyn_lib, + const char *sym) +{ + void *proc; + + YAGL_LOG_FUNC_ENTER(yagl_egl_agl_get_procaddr, + "Retrieving %s address", sym); + + /* The dlsym code path is shared by Linux and Mac builds */ + proc = yagl_dyn_lib_get_sym(dyn_lib, sym); + + YAGL_LOG_FUNC_EXIT("%s address: %p", sym, proc); + + return proc; +} diff --git a/hw/yagl_inc/EGL/eglplatform.h b/hw/yagl_inc/EGL/eglplatform.h index 17fdc61..19d38d9 100644 --- a/hw/yagl_inc/EGL/eglplatform.h +++ b/hw/yagl_inc/EGL/eglplatform.h @@ -104,6 +104,12 @@ typedef struct ANativeWindow *EGLNativeWindowType; typedef struct egl_native_pixmap_t *EGLNativePixmapType; typedef void *EGLNativeDisplayType; +#elif defined(__APPLE__) && defined (__MACH__) /* Mac OS X */ + +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + #elif defined(__unix__) #ifdef MESA_EGL_NO_X11_HEADERS diff --git a/tizen/emulator_configure.sh b/tizen/emulator_configure.sh old mode 100755 new mode 100644 index e95eea9..abf23b8 --- a/tizen/emulator_configure.sh +++ b/tizen/emulator_configure.sh @@ -102,10 +102,10 @@ set_target() { if [ -z "$VIRTIOGL_EN" ] ; then virtgl_enable yes fi - if [ -z "$YAGL_EN" ] && [ "$targetos" != "Darwin" ] ; then + if [ -z "$YAGL_EN" ] ; then yagl_enable yes fi - if [ -z "$VIGS_EN" ] && [ "$targetos" != "Darwin" ] ; then + if [ -z "$VIGS_EN" ] ; then vigs_enable yes fi ;; @@ -124,10 +124,10 @@ set_target() { if [ -z "$VIRTIOGL_EN" ] ; then virtgl_enable yes fi - if [ -z "$YAGL_EN" ] && [ "$targetos" != "Darwin" ] ; then - yagl_enable yes + if [ -z "$YAGL_EN" ] ; then + yagl_enable yes fi - if [ -z "$VIGS_EN" ] && [ "$targetos" != "Darwin" ] ; then + if [ -z "$VIGS_EN" ] ; then vigs_enable yes fi ;; diff --git a/vl.c b/vl.c index 9262c6a..7ca6769 100644 --- a/vl.c +++ b/vl.c @@ -3666,7 +3666,7 @@ int main(int argc, char **argv, char **envp) #endif break; case QEMU_OPTION_enable_yagl: -#if defined(CONFIG_YAGL) && !defined(CONFIG_DARWIN) +#if defined(CONFIG_YAGL) enable_yagl = 1; #else fprintf(stderr, "YaGL openGLES passthrough support is disabled," @@ -3674,7 +3674,7 @@ int main(int argc, char **argv, char **envp) #endif break; case QEMU_OPTION_yagl_backend: -#if defined(CONFIG_YAGL) && !defined(CONFIG_DARWIN) +#if defined(CONFIG_YAGL) yagl_backend = optarg; #else fprintf(stderr, "YaGL openGLES passthrough support is disabled," @@ -3682,7 +3682,7 @@ int main(int argc, char **argv, char **envp) #endif break; case QEMU_OPTION_enable_vigs: -#if defined(CONFIG_VIGS) && !defined(CONFIG_DARWIN) +#if defined(CONFIG_VIGS) enable_vigs = 1; #else fprintf(stderr, "VIGS support is disabled," @@ -3690,7 +3690,7 @@ int main(int argc, char **argv, char **envp) #endif break; case QEMU_OPTION_vigs_backend: -#if defined(CONFIG_VIGS) && !defined(CONFIG_DARWIN) +#if defined(CONFIG_VIGS) vigs_backend = g_strdup(optarg); #else fprintf(stderr, "VIGS support is disabled,"