diff options
author | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-02-22 17:39:08 +0400 |
---|---|---|
committer | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-02-22 17:40:50 +0400 |
commit | 45cdbe450359cead30da060e5a89e45818d856e9 (patch) | |
tree | d4335d6e9647c7e347d7dbc53c70dd180501b14e /hw | |
parent | b07dd0fc1d12de73337896a5a8aa3287d17b9a25 (diff) | |
download | qemu-45cdbe450359cead30da060e5a89e45818d856e9.tar.gz qemu-45cdbe450359cead30da060e5a89e45818d856e9.tar.bz2 qemu-45cdbe450359cead30da060e5a89e45818d856e9.zip |
VIGS/YaGL: Use CGL instead of AGL
AGL is a deprecated API and it doesn't
allow one to create OpenGL 3.2 contexts, so
use CGL instead
Change-Id: Iaa63fee0aeda7348c256f177b3a96b10142870d4
Diffstat (limited to 'hw')
-rw-r--r-- | hw/vigs/Makefile.objs | 4 | ||||
-rw-r--r-- | hw/vigs/vigs_gl_backend_agl.c | 364 | ||||
-rw-r--r-- | hw/vigs/vigs_gl_backend_cgl.c | 378 | ||||
-rw-r--r-- | hw/yagl/yagl_drivers/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/yagl/yagl_drivers/egl_agl/Makefile.objs | 3 | ||||
-rw-r--r-- | hw/yagl/yagl_drivers/egl_agl/yagl_egl_agl.c | 408 | ||||
-rw-r--r-- | hw/yagl/yagl_drivers/egl_cgl/Makefile.objs | 3 | ||||
-rw-r--r-- | hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c | 507 |
8 files changed, 891 insertions, 778 deletions
diff --git a/hw/vigs/Makefile.objs b/hw/vigs/Makefile.objs index b227b1c913..93f7e3b8d9 100644 --- a/hw/vigs/Makefile.objs +++ b/hw/vigs/Makefile.objs @@ -21,7 +21,7 @@ endif ifdef CONFIG_WIN32 obj-y += vigs_gl_backend_wgl.o endif -# GL AGL backend +# GL CGL backend ifdef CONFIG_DARWIN -obj-y += vigs_gl_backend_agl.o +obj-y += vigs_gl_backend_cgl.o endif diff --git a/hw/vigs/vigs_gl_backend_agl.c b/hw/vigs/vigs_gl_backend_agl.c deleted file mode 100644 index 9ee6c05e8f..0000000000 --- a/hw/vigs/vigs_gl_backend_agl.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * vigs - * - * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * Stanislav Vorobiov <s.vorobiov@samsung.com> - * Jinhyung Jo <jinhyung.jo@samsung.com> - * YeongKyoon Lee <yeongkyoon.lee@samsung.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#include "vigs_gl_backend.h" -#include "vigs_log.h" -#include <OpenGL/OpenGL.h> -#include <AGL/agl.h> -#include <glib.h> -#include <dlfcn.h> - -#define LIBGL_IMAGE_NAME \ -"/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" - -#define VIGS_GL_GET_PROC(func, proc_name) \ - do { \ - *(void**)(&gl_backend_agl->base.func) = dlsym(gl_backend_agl->handle, #proc_name); \ - if (!gl_backend_agl->base.func) { \ - VIGS_LOG_CRITICAL("Unable to load " #proc_name " symbol"); \ - goto fail; \ - } \ - } while (0) - -struct vigs_gl_backend_agl { - struct vigs_gl_backend base; - - void *handle; - AGLContext read_pixels_context; - AGLPbuffer read_pixels_surface; - AGLContext context; - AGLPbuffer surface; - AGLPixelFormat pixfmt; -}; - -static int vigs_gl_backend_agl_choose_config(struct vigs_gl_backend_agl - *gl_backend_agl) -{ - 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; - - /* Select first AGL pixel format matching our constraints */ - - pixfmt = aglChoosePixelFormat(NULL, 0, attrib_list); - - gl_backend_agl->pixfmt = pixfmt; - - return (pixfmt != NULL); -} - -static bool vigs_gl_backend_agl_create_surface(struct vigs_gl_backend_agl - *gl_backend_agl, int config_id, - AGLPbuffer *surface) -{ - aglCreatePBuffer(1, 1, GL_TEXTURE_2D, GL_RGBA, 0, - surface); - - if (!*surface) { - VIGS_LOG_CRITICAL("aglCreatePBuffer failed"); - return false; - } - - return true; -} - -static bool vigs_gl_backend_agl_create_context(struct vigs_gl_backend_agl - *gl_backend_agl, - AGLContext share_context, - AGLContext *context) -{ - *context = aglCreateContext(gl_backend_agl->pixfmt, share_context); - - if (!*context) { - VIGS_LOG_CRITICAL("aglCreateContext failed"); - return false; - } - - return true; -} - -static void vigs_gl_backend_agl_destroy(struct vigs_backend *backend) -{ - struct vigs_gl_backend_agl *gl_backend_agl = - (struct vigs_gl_backend_agl *)backend; - - vigs_gl_backend_cleanup(&gl_backend_agl->base); - - if (gl_backend_agl->surface) { - aglDestroyPBuffer(gl_backend_agl->surface); - } - - if (gl_backend_agl->read_pixels_surface) { - aglDestroyPBuffer(gl_backend_agl->read_pixels_surface); - } - - if (gl_backend_agl->context) { - aglDestroyContext(gl_backend_agl->context); - } - - if (gl_backend_agl->read_pixels_context) { - aglDestroyContext(gl_backend_agl->read_pixels_context); - } - - if (gl_backend_agl->handle) { - dlclose(gl_backend_agl->handle); - } - - vigs_backend_cleanup(&gl_backend_agl->base.base); - - g_free(gl_backend_agl); - - VIGS_LOG_DEBUG("destroyed"); -} - -static bool vigs_gl_backend_agl_has_current(struct vigs_gl_backend *gl_backend) -{ - return aglGetCurrentContext() != NULL; -} - -static bool vigs_gl_backend_agl_make_current(struct vigs_gl_backend *gl_backend, - bool enable) -{ - struct vigs_gl_backend_agl *gl_backend_agl = - (struct vigs_gl_backend_agl *)gl_backend; - AGLPbuffer buf = NULL; - AGLContext context = gl_backend_agl->context; - - if (enable) { - buf = gl_backend_agl->surface; - - if (!buf) { - VIGS_LOG_CRITICAL("surface retrieval failed"); - return false; - } - - if (aglSetPBuffer(context, buf, 0, 0, 0) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetPBuffer failed"); - return false; - } - - if (aglSetCurrentContext(context) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetCurrentContext failed"); - aglSetPBuffer(context, NULL, 0, 0, 0); - return false; - } - } else { - if (aglSetCurrentContext(NULL) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetCurrentContext(NULL) failed"); - return false; - } - } - - return true; -} - -static bool vigs_gl_backend_agl_read_pixels_make_current(struct vigs_gl_backend *gl_backend, - bool enable) -{ - struct vigs_gl_backend_agl *gl_backend_agl = - (struct vigs_gl_backend_agl *)gl_backend; - AGLPbuffer buf = NULL; - AGLContext context = gl_backend_agl->read_pixels_context; - - if (enable) { - buf = gl_backend_agl->read_pixels_surface; - - if (aglSetPBuffer(context, buf, 0, 0, 0) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetPBuffer failed"); - return false; - } - - if (aglSetCurrentContext(context) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetCurrentContext failed"); - aglSetPBuffer(context, NULL, 0, 0, 0); - return false; - } - } else { - if (aglSetCurrentContext(NULL) == GL_FALSE) { - VIGS_LOG_CRITICAL("aglSetCurrentContext(NULL) failed"); - return false; - } - } - - return true; -} - -struct vigs_backend *vigs_gl_backend_create(void *display) -{ - struct vigs_gl_backend_agl *gl_backend_agl; - int config_id; - - gl_backend_agl = g_malloc0(sizeof(*gl_backend_agl)); - - vigs_backend_init(&gl_backend_agl->base.base, - &gl_backend_agl->base.ws_info.base); - - gl_backend_agl->handle = dlopen(LIBGL_IMAGE_NAME, RTLD_GLOBAL); - - VIGS_GL_GET_PROC(GenTextures, glGenTextures); - VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures); - VIGS_GL_GET_PROC(BindTexture, glBindTexture); - VIGS_GL_GET_PROC(CullFace, glCullFace); - VIGS_GL_GET_PROC(TexParameterf, glTexParameterf); - VIGS_GL_GET_PROC(TexParameterfv, glTexParameterfv); - VIGS_GL_GET_PROC(TexParameteri, glTexParameteri); - VIGS_GL_GET_PROC(TexParameteriv, glTexParameteriv); - VIGS_GL_GET_PROC(TexImage2D, glTexImage2D); - VIGS_GL_GET_PROC(TexSubImage2D, glTexSubImage2D); - VIGS_GL_GET_PROC(Clear, glClear); - VIGS_GL_GET_PROC(ClearColor, glClearColor); - VIGS_GL_GET_PROC(Disable, glDisable); - VIGS_GL_GET_PROC(Enable, glEnable); - VIGS_GL_GET_PROC(Finish, glFinish); - VIGS_GL_GET_PROC(Flush, glFlush); - VIGS_GL_GET_PROC(PixelStorei, glPixelStorei); - VIGS_GL_GET_PROC(ReadPixels, glReadPixels); - VIGS_GL_GET_PROC(Viewport, glViewport); - VIGS_GL_GET_PROC(GenFramebuffers, glGenFramebuffersEXT); - VIGS_GL_GET_PROC(GenRenderbuffers, glGenRenderbuffersEXT); - VIGS_GL_GET_PROC(DeleteFramebuffers, glDeleteFramebuffersEXT); - VIGS_GL_GET_PROC(DeleteRenderbuffers, glDeleteRenderbuffersEXT); - VIGS_GL_GET_PROC(BindFramebuffer, glBindFramebufferEXT); - VIGS_GL_GET_PROC(BindRenderbuffer, glBindRenderbufferEXT); - VIGS_GL_GET_PROC(RenderbufferStorage, glRenderbufferStorageEXT); - VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT); - VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT); - VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv); - VIGS_GL_GET_PROC(DrawArrays, glDrawArrays); - VIGS_GL_GET_PROC(GenBuffers, glGenBuffers); - VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers); - VIGS_GL_GET_PROC(BindBuffer, glBindBuffer); - VIGS_GL_GET_PROC(BufferData, glBufferData); - VIGS_GL_GET_PROC(BufferSubData, glBufferSubData); - VIGS_GL_GET_PROC(MapBuffer, glMapBuffer); - VIGS_GL_GET_PROC(UnmapBuffer, glUnmapBuffer); - VIGS_GL_GET_PROC(CreateProgram, glCreateProgram); - VIGS_GL_GET_PROC(CreateShader, glCreateShader); - VIGS_GL_GET_PROC(CompileShader, glCompileShader); - VIGS_GL_GET_PROC(AttachShader, glAttachShader); - VIGS_GL_GET_PROC(LinkProgram, glLinkProgram); - VIGS_GL_GET_PROC(GetProgramiv, glGetProgramiv); - VIGS_GL_GET_PROC(GetProgramInfoLog, glGetProgramInfoLog); - VIGS_GL_GET_PROC(GetShaderiv, glGetShaderiv); - VIGS_GL_GET_PROC(GetShaderInfoLog, glGetShaderInfoLog); - VIGS_GL_GET_PROC(DetachShader, glDetachShader); - VIGS_GL_GET_PROC(DeleteProgram, glDeleteProgram); - VIGS_GL_GET_PROC(DeleteShader, glDeleteShader); - VIGS_GL_GET_PROC(DisableVertexAttribArray, glDisableVertexAttribArray); - VIGS_GL_GET_PROC(EnableVertexAttribArray, glEnableVertexAttribArray); - VIGS_GL_GET_PROC(ShaderSource, glShaderSource); - VIGS_GL_GET_PROC(UseProgram, glUseProgram); - VIGS_GL_GET_PROC(GetAttribLocation, glGetAttribLocation); - VIGS_GL_GET_PROC(GetUniformLocation, glGetUniformLocation); - VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer); - VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv); - VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv); - - config_id = vigs_gl_backend_agl_choose_config(gl_backend_agl); - - if (!config_id) { - goto fail; - } - - if (!vigs_gl_backend_agl_create_surface(gl_backend_agl, config_id, - &gl_backend_agl->surface)) { - goto fail; - } - - if (!vigs_gl_backend_agl_create_surface(gl_backend_agl, config_id, - &gl_backend_agl->read_pixels_surface)) { - goto fail; - } - - if (!vigs_gl_backend_agl_create_context(gl_backend_agl, NULL, - &gl_backend_agl->context)) { - goto fail; - } - - if (!vigs_gl_backend_agl_create_context(gl_backend_agl, gl_backend_agl->context, - &gl_backend_agl->read_pixels_context)) { - goto fail; - } - - gl_backend_agl->base.base.destroy = &vigs_gl_backend_agl_destroy; - gl_backend_agl->base.has_current = &vigs_gl_backend_agl_has_current; - gl_backend_agl->base.make_current = &vigs_gl_backend_agl_make_current; - gl_backend_agl->base.read_pixels_make_current = &vigs_gl_backend_agl_read_pixels_make_current; - gl_backend_agl->base.ws_info.context = &gl_backend_agl->context; - - if (!vigs_gl_backend_init(&gl_backend_agl->base)) { - goto fail; - } - - VIGS_LOG_DEBUG("created"); - - return &gl_backend_agl->base.base; - - fail: - - if (gl_backend_agl->handle) { - dlclose(gl_backend_agl->handle); - } - - if (gl_backend_agl->surface) { - aglDestroyPBuffer(gl_backend_agl->surface); - } - - if (gl_backend_agl->read_pixels_surface) { - aglDestroyPBuffer(gl_backend_agl->read_pixels_surface); - } - - if (gl_backend_agl->context) { - aglDestroyContext(gl_backend_agl->context); - } - - if (gl_backend_agl->read_pixels_context) { - aglDestroyContext(gl_backend_agl->read_pixels_context); - } - - vigs_backend_cleanup(&gl_backend_agl->base.base); - - g_free(gl_backend_agl); - - return NULL; -} diff --git a/hw/vigs/vigs_gl_backend_cgl.c b/hw/vigs/vigs_gl_backend_cgl.c new file mode 100644 index 0000000000..2112138333 --- /dev/null +++ b/hw/vigs/vigs_gl_backend_cgl.c @@ -0,0 +1,378 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov <s.vorobiov@samsung.com> + * Jinhyung Jo <jinhyung.jo@samsung.com> + * YeongKyoon Lee <yeongkyoon.lee@samsung.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "vigs_gl_backend.h" +#include "vigs_log.h" +#include <OpenGL/OpenGL.h> +#include <dlfcn.h> + +#define LIBGL_IMAGE_NAME \ +"/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" + +#ifndef kCGLPFAOpenGLProfile +# define kCGLPFAOpenGLProfile 99 +# define kCGLOGLPVersion_3_2_Core 0x3200 +# define kCGLOGLPVersion_Legacy 0x1000 +#endif + +#define VIGS_GL_GET_PROC(func, proc_name) \ + do { \ + *(void**)(&gl_backend_cgl->base.func) = dlsym(gl_backend_cgl->handle, #proc_name); \ + if (!gl_backend_cgl->base.func) { \ + VIGS_LOG_CRITICAL("Unable to load " #proc_name " symbol"); \ + goto fail2; \ + } \ + } while (0) + +static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = +{ + kCGLPFAAccelerated, + kCGLPFAMinimumPolicy, + kCGLPFAColorSize, 32, + kCGLPFAAlphaSize, 8, + kCGLPFADepthSize, 24, + kCGLPFAStencilSize, 8, + kCGLPFANoRecovery, + kCGLPFAPBuffer, + 0 +}; + +static const CGLPixelFormatAttribute pixel_format_3_2_core_attrs[] = +{ + kCGLPFAAccelerated, + kCGLPFAMinimumPolicy, + kCGLPFAColorSize, 32, + kCGLPFAAlphaSize, 8, + kCGLPFADepthSize, 24, + kCGLPFAStencilSize, 8, + kCGLPFANoRecovery, + kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, + 0 +}; + +struct vigs_gl_backend_cgl +{ + struct vigs_gl_backend base; + + void *handle; + CGLContextObj read_pixels_context; + CGLContextObj context; +}; + +static bool vigs_gl_backend_cgl_check_gl_version(struct vigs_gl_backend_cgl *gl_backend_cgl, + bool *is_gl_2) +{ + CGLError error; + bool res = false; + const char *tmp; + CGLPixelFormatObj pixel_format; + int n; + + tmp = getenv("GL_VERSION"); + + if (tmp) { + if (strcmp(tmp, "2") == 0) { + VIGS_LOG_INFO("GL_VERSION forces OpenGL version to 2.1"); + *is_gl_2 = true; + res = true; + } else if (strcmp(tmp, "3_2") == 0) { + VIGS_LOG_INFO("GL_VERSION forces OpenGL version to 3.2"); + *is_gl_2 = false; + res = true; + } else { + VIGS_LOG_CRITICAL("Bad GL_VERSION value = %s", tmp); + } + + goto out; + } + + error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs, + &pixel_format, + &n); + + if (error) { + VIGS_LOG_INFO("CGLChoosePixelFormat failed for 3_2_core attrs: %s, using OpenGL 2.1", CGLErrorString(error)); + *is_gl_2 = true; + res = true; + goto out; + } + + if (!pixel_format) { + VIGS_LOG_INFO("CGLChoosePixelFormat failed to find formats for 3_2_core attrs, using OpenGL 2.1"); + *is_gl_2 = true; + res = true; + goto out; + } + + CGLDestroyPixelFormat(pixel_format); + + VIGS_LOG_INFO("Using OpenGL 3.2"); + *is_gl_2 = false; + res = true; + +out: + return res; +} + +static bool vigs_gl_backend_cgl_create_context(struct vigs_gl_backend_cgl *gl_backend_cgl, + CGLPixelFormatObj pixel_format, + CGLContextObj share_context, + CGLContextObj *ctx) +{ + CGLError error; + + error = CGLCreateContext(pixel_format, share_context, ctx); + + if (error) { + VIGS_LOG_CRITICAL("CGLCreateContext failed: %s", CGLErrorString(error)); + return false; + } + + return true; +} + +static bool vigs_gl_backend_cgl_has_current(struct vigs_gl_backend *gl_backend) +{ + return CGLGetCurrentContext() != NULL; +} + +static bool vigs_gl_backend_cgl_make_current(struct vigs_gl_backend *gl_backend, + bool enable) +{ + struct vigs_gl_backend_cgl *gl_backend_cgl = + (struct vigs_gl_backend_cgl*)gl_backend; + CGLError error; + + error = CGLSetCurrentContext(enable ? gl_backend_cgl->context : NULL); + + if (error) { + VIGS_LOG_CRITICAL("CGLSetCurrentContext failed: %s", CGLErrorString(error)); + return false; + } + + return true; +} + +static bool vigs_gl_backend_cgl_read_pixels_make_current(struct vigs_gl_backend *gl_backend, + bool enable) +{ + struct vigs_gl_backend_cgl *gl_backend_cgl = + (struct vigs_gl_backend_cgl*)gl_backend; + CGLError error; + + error = CGLSetCurrentContext(enable ? gl_backend_cgl->read_pixels_context : NULL); + + if (error) { + VIGS_LOG_CRITICAL("CGLSetCurrentContext failed: %s", CGLErrorString(error)); + return false; + } + + return true; +} + +static void vigs_gl_backend_cgl_destroy(struct vigs_backend *backend) +{ + struct vigs_gl_backend_cgl *gl_backend_cgl = (struct vigs_gl_backend_cgl*)backend; + CGLError error; + + vigs_gl_backend_cleanup(&gl_backend_cgl->base); + + error = CGLDestroyContext(gl_backend_cgl->context); + + if (error) { + VIGS_LOG_ERROR("CGLDestroyContext failed: %s", CGLErrorString(error)); + } + + error = CGLDestroyContext(gl_backend_cgl->read_pixels_context); + + if (error) { + VIGS_LOG_ERROR("CGLDestroyContext failed: %s", CGLErrorString(error)); + } + + dlclose(gl_backend_cgl->handle); + + vigs_backend_cleanup(&gl_backend_cgl->base.base); + + g_free(gl_backend_cgl); + + VIGS_LOG_DEBUG("destroyed"); +} + +struct vigs_backend *vigs_gl_backend_create(void *display) +{ + struct vigs_gl_backend_cgl *gl_backend_cgl; + CGLError error; + CGLPixelFormatObj pixel_format; + int n; + + gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl)); + + vigs_backend_init(&gl_backend_cgl->base.base, + &gl_backend_cgl->base.ws_info.base); + + gl_backend_cgl->handle = dlopen(LIBGL_IMAGE_NAME, RTLD_NOW | RTLD_GLOBAL); + + if (!gl_backend_cgl->handle) { + VIGS_LOG_CRITICAL("Unable to load " LIBGL_IMAGE_NAME ": %s", dlerror()); + goto fail1; + } + + VIGS_GL_GET_PROC(GenTextures, glGenTextures); + VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures); + VIGS_GL_GET_PROC(BindTexture, glBindTexture); + VIGS_GL_GET_PROC(CullFace, glCullFace); + VIGS_GL_GET_PROC(TexParameterf, glTexParameterf); + VIGS_GL_GET_PROC(TexParameterfv, glTexParameterfv); + VIGS_GL_GET_PROC(TexParameteri, glTexParameteri); + VIGS_GL_GET_PROC(TexParameteriv, glTexParameteriv); + VIGS_GL_GET_PROC(TexImage2D, glTexImage2D); + VIGS_GL_GET_PROC(TexSubImage2D, glTexSubImage2D); + VIGS_GL_GET_PROC(Clear, glClear); + VIGS_GL_GET_PROC(ClearColor, glClearColor); + VIGS_GL_GET_PROC(Disable, glDisable); + VIGS_GL_GET_PROC(Enable, glEnable); + VIGS_GL_GET_PROC(Finish, glFinish); + VIGS_GL_GET_PROC(Flush, glFlush); + VIGS_GL_GET_PROC(PixelStorei, glPixelStorei); + VIGS_GL_GET_PROC(ReadPixels, glReadPixels); + VIGS_GL_GET_PROC(Viewport, glViewport); + VIGS_GL_GET_PROC(GenFramebuffers, glGenFramebuffersEXT); + VIGS_GL_GET_PROC(GenRenderbuffers, glGenRenderbuffersEXT); + VIGS_GL_GET_PROC(DeleteFramebuffers, glDeleteFramebuffersEXT); + VIGS_GL_GET_PROC(DeleteRenderbuffers, glDeleteRenderbuffersEXT); + VIGS_GL_GET_PROC(BindFramebuffer, glBindFramebufferEXT); + VIGS_GL_GET_PROC(BindRenderbuffer, glBindRenderbufferEXT); + VIGS_GL_GET_PROC(RenderbufferStorage, glRenderbufferStorageEXT); + VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT); + VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT); + VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv); + VIGS_GL_GET_PROC(DrawArrays, glDrawArrays); + VIGS_GL_GET_PROC(GenBuffers, glGenBuffers); + VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers); + VIGS_GL_GET_PROC(BindBuffer, glBindBuffer); + VIGS_GL_GET_PROC(BufferData, glBufferData); + VIGS_GL_GET_PROC(BufferSubData, glBufferSubData); + VIGS_GL_GET_PROC(MapBuffer, glMapBuffer); + VIGS_GL_GET_PROC(UnmapBuffer, glUnmapBuffer); + VIGS_GL_GET_PROC(CreateProgram, glCreateProgram); + VIGS_GL_GET_PROC(CreateShader, glCreateShader); + VIGS_GL_GET_PROC(CompileShader, glCompileShader); + VIGS_GL_GET_PROC(AttachShader, glAttachShader); + VIGS_GL_GET_PROC(LinkProgram, glLinkProgram); + VIGS_GL_GET_PROC(GetProgramiv, glGetProgramiv); + VIGS_GL_GET_PROC(GetProgramInfoLog, glGetProgramInfoLog); + VIGS_GL_GET_PROC(GetShaderiv, glGetShaderiv); + VIGS_GL_GET_PROC(GetShaderInfoLog, glGetShaderInfoLog); + VIGS_GL_GET_PROC(DetachShader, glDetachShader); + VIGS_GL_GET_PROC(DeleteProgram, glDeleteProgram); + VIGS_GL_GET_PROC(DeleteShader, glDeleteShader); + VIGS_GL_GET_PROC(DisableVertexAttribArray, glDisableVertexAttribArray); + VIGS_GL_GET_PROC(EnableVertexAttribArray, glEnableVertexAttribArray); + VIGS_GL_GET_PROC(ShaderSource, glShaderSource); + VIGS_GL_GET_PROC(UseProgram, glUseProgram); + VIGS_GL_GET_PROC(GetAttribLocation, glGetAttribLocation); + VIGS_GL_GET_PROC(GetUniformLocation, glGetUniformLocation); + VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer); + VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv); + VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv); + + if (!vigs_gl_backend_cgl_check_gl_version(gl_backend_cgl, + &gl_backend_cgl->base.is_gl_2)) { + goto fail2; + } + + if (gl_backend_cgl->base.is_gl_2) { + error = CGLChoosePixelFormat(pixel_format_legacy_attrs, + &pixel_format, + &n); + } else { + VIGS_GL_GET_PROC(GenVertexArrays, glGenVertexArrays); + VIGS_GL_GET_PROC(BindVertexArray, glBindVertexArray); + VIGS_GL_GET_PROC(DeleteVertexArrays, glDeleteVertexArrays); + + error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs, + &pixel_format, + &n); + } + + if (error) { + VIGS_LOG_INFO("CGLChoosePixelFormat failed for 3_2_core attrs: %s, using OpenGL 2.1", CGLErrorString(error)); + goto fail2; + } + + if (!pixel_format) { + VIGS_LOG_INFO("CGLChoosePixelFormat failed to find formats for 3_2_core attrs, using OpenGL 2.1"); + goto fail2; + } + + if (!vigs_gl_backend_cgl_create_context(gl_backend_cgl, + pixel_format, + NULL, + &gl_backend_cgl->context)) { + goto fail3; + } + + if (!vigs_gl_backend_cgl_create_context(gl_backend_cgl, + pixel_format, + gl_backend_cgl->context, + &gl_backend_cgl->read_pixels_context)) { + goto fail4; + } + + gl_backend_cgl->base.base.destroy = &vigs_gl_backend_cgl_destroy; + gl_backend_cgl->base.has_current = &vigs_gl_backend_cgl_has_current; + gl_backend_cgl->base.make_current = &vigs_gl_backend_cgl_make_current; + gl_backend_cgl->base.read_pixels_make_current = &vigs_gl_backend_cgl_read_pixels_make_current; + gl_backend_cgl->base.ws_info.context = &gl_backend_cgl->context; + + if (!vigs_gl_backend_init(&gl_backend_cgl->base)) { + goto fail5; + } + + VIGS_LOG_DEBUG("created"); + + CGLDestroyPixelFormat(pixel_format); + + return &gl_backend_cgl->base.base; + +fail5: + CGLDestroyContext(gl_backend_cgl->read_pixels_context); +fail4: + CGLDestroyContext(gl_backend_cgl->context); +fail3: + CGLDestroyPixelFormat(pixel_format); +fail2: + dlclose(gl_backend_cgl->handle); +fail1: + vigs_backend_cleanup(&gl_backend_cgl->base.base); + + g_free(gl_backend_cgl); + + return NULL; +} diff --git a/hw/yagl/yagl_drivers/Makefile.objs b/hw/yagl/yagl_drivers/Makefile.objs index f3544e70aa..773972b341 100644 --- a/hw/yagl/yagl_drivers/Makefile.objs +++ b/hw/yagl/yagl_drivers/Makefile.objs @@ -1,6 +1,6 @@ obj-$(CONFIG_LINUX) += egl_glx/ obj-$(CONFIG_WIN32) += egl_wgl/ -obj-$(CONFIG_DARWIN) += egl_agl/ +obj-$(CONFIG_DARWIN) += egl_cgl/ obj-y += gles_ogl/ obj-y += gles_onscreen/ diff --git a/hw/yagl/yagl_drivers/egl_agl/Makefile.objs b/hw/yagl/yagl_drivers/egl_agl/Makefile.objs deleted file mode 100644 index 61fc900f32..0000000000 --- a/hw/yagl/yagl_drivers/egl_agl/Makefile.objs +++ /dev/null @@ -1,3 +0,0 @@ -# EGL AGL driver -QEMU_CFLAGS += -Wno-comment -obj-y += yagl_egl_agl.o diff --git a/hw/yagl/yagl_drivers/egl_agl/yagl_egl_agl.c b/hw/yagl/yagl_drivers/egl_agl/yagl_egl_agl.c deleted file mode 100644 index 8fc1af323c..0000000000 --- a/hw/yagl/yagl_drivers/egl_agl/yagl_egl_agl.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * yagl - * - * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * Stanislav Vorobiov <s.vorobiov@samsung.com> - * Jinhyung Jo <jinhyung.jo@samsung.com> - * YeongKyoon Lee <yeongkyoon.lee@samsung.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#include <OpenGL/OpenGL.h> -#include <AGL/agl.h> -#include <glib.h> -#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, - EGLContext share_context, - int version) -{ - YaglEglAglContext *egl_glc; - AGLContext agl_share_glc; - - YAGL_LOG_FUNC_ENTER(yagl_egl_agl_context_create, - "dpy = %p, share_context = %p, cfgid=%d", - egl_dpy, 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/yagl_drivers/egl_cgl/Makefile.objs b/hw/yagl/yagl_drivers/egl_cgl/Makefile.objs new file mode 100644 index 0000000000..4dce0c752e --- /dev/null +++ b/hw/yagl/yagl_drivers/egl_cgl/Makefile.objs @@ -0,0 +1,3 @@ +# EGL CGL driver +QEMU_CFLAGS += -Wno-comment +obj-y += yagl_egl_cgl.o diff --git a/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c b/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c new file mode 100644 index 0000000000..32839a6d7f --- /dev/null +++ b/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c @@ -0,0 +1,507 @@ +/* + * yagl + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov <s.vorobiov@samsung.com> + * Jinhyung Jo <jinhyung.jo@samsung.com> + * YeongKyoon Lee <yeongkyoon.lee@samsung.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include <GL/gl.h> +#include <OpenGL/OpenGL.h> +#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" + +#ifndef kCGLPFAOpenGLProfile +# define kCGLPFAOpenGLProfile 99 +# define kCGLOGLPVersion_3_2_Core 0x3200 +# define kCGLOGLPVersion_Legacy 0x1000 +#endif + +static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = +{ + kCGLPFAAccelerated, + kCGLPFAMinimumPolicy, + kCGLPFAColorSize, 32, + kCGLPFAAlphaSize, 8, + kCGLPFADepthSize, 24, + kCGLPFAStencilSize, 8, + kCGLPFANoRecovery, + kCGLPFAPBuffer, + 0 +}; + +static const CGLPixelFormatAttribute pixel_format_3_2_core_attrs[] = +{ + kCGLPFAAccelerated, + kCGLPFAMinimumPolicy, + kCGLPFAColorSize, 32, + kCGLPFAAlphaSize, 8, + kCGLPFADepthSize, 24, + kCGLPFAStencilSize, 8, + kCGLPFANoRecovery, + kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, + 0 +}; + +struct yagl_egl_cgl +{ + struct yagl_egl_driver base; + + CGLPixelFormatObj pixel_format_legacy; + CGLPixelFormatObj pixel_format_3_2_core; +}; + +struct yagl_egl_cgl_context +{ + CGLContextObj base; + + bool is_3_2_core; +}; + +static bool yagl_egl_cgl_get_gl_version(struct yagl_egl_cgl *egl_cgl, + yagl_gl_version *version) +{ + CGLError error; + bool res = false; + const char *tmp; + CGLPixelFormatObj pixel_format; + int n; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_get_gl_version, NULL); + + tmp = getenv("GL_VERSION"); + + if (tmp) { + if (strcmp(tmp, "2") == 0) { + YAGL_LOG_INFO("GL_VERSION forces OpenGL version to 2.1"); + *version = yagl_gl_2; + res = true; + } else if (strcmp(tmp, "3_2") == 0) { + YAGL_LOG_INFO("GL_VERSION forces OpenGL version to 3.2"); + *version = yagl_gl_3_2; + res = true; + } else { + YAGL_LOG_CRITICAL("Bad GL_VERSION value = %s", tmp); + } + + goto out; + } + + error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs, + &pixel_format, + &n); + + if (error) { + YAGL_LOG_INFO("CGLChoosePixelFormat failed for 3_2_core attrs: %s, using OpenGL 2.1", CGLErrorString(error)); + *version = yagl_gl_2; + res = true; + goto out; + } + + if (!pixel_format) { + YAGL_LOG_INFO("CGLChoosePixelFormat failed to find formats for 3_2_core attrs, using OpenGL 2.1"); + *version = yagl_gl_2; + res = true; + goto out; + } + + CGLDestroyPixelFormat(pixel_format); + + YAGL_LOG_INFO("Using OpenGL 3.2"); + *version = yagl_gl_3_2; + res = true; + +out: + if (res) { + YAGL_LOG_FUNC_EXIT("%d, version = %u", res, *version); + } else { + YAGL_LOG_FUNC_EXIT("%d", res); + } + + return res; +} + +static EGLNativeDisplayType yagl_egl_cgl_display_open(struct yagl_egl_driver *driver) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_display_open, NULL); + + YAGL_LOG_FUNC_EXIT("%p", (void*)1); + + return (EGLNativeDisplayType)1; +} + +static void yagl_egl_cgl_display_close(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_display_close, "%p", dpy); + + YAGL_LOG_FUNC_EXIT(NULL); +} + +static struct yagl_egl_native_config + *yagl_egl_cgl_config_enum(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + int *num_configs) +{ + struct yagl_egl_native_config *cfg = NULL; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_config_enum, "%p", dpy); + + YAGL_LOG_TRACE("got 1 config"); + + cfg = g_malloc0(sizeof(*cfg)); + + yagl_egl_native_config_init(cfg); + + cfg->red_size = 8; + cfg->green_size = 8; + cfg->blue_size = 8; + cfg->alpha_size = 8; + cfg->buffer_size = 32; + cfg->caveat = EGL_NONE; + cfg->config_id = 1; + cfg->frame_buffer_level = 0; + cfg->depth_size = 24; + cfg->max_pbuffer_width = 4096; + cfg->max_pbuffer_height = 4096; + cfg->max_pbuffer_size = 4096 * 4096; + cfg->max_swap_interval = 1000; + cfg->min_swap_interval = 0; + cfg->native_visual_id = 0; + cfg->native_visual_type = EGL_NONE; + cfg->samples_per_pixel = 0; + cfg->stencil_size = 8; + cfg->transparent_type = EGL_NONE; + cfg->trans_red_val = 0; + cfg->trans_green_val = 0; + cfg->trans_blue_val = 0; + cfg->driver_data = NULL; + + *num_configs = 1; + + YAGL_LOG_FUNC_EXIT(NULL); + + return cfg; +} + +static void yagl_egl_cgl_config_cleanup(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + const struct yagl_egl_native_config *cfg) +{ + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_config_cleanup, + "dpy = %p, cfg = %d", + dpy, + cfg->config_id); + + YAGL_LOG_FUNC_EXIT(NULL); +} + +static EGLSurface yagl_egl_cgl_pbuffer_surface_create(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + const struct yagl_egl_native_config *cfg, + EGLint width, + EGLint height, + const struct yagl_egl_pbuffer_attribs *attribs) +{ + CGLPBufferObj pbuffer = NULL; + CGLError error; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_pbuffer_surface_create, + "dpy = %p, width = %d, height = %d", + dpy, + width, + height); + + error = CGLCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, + 0, &pbuffer); + + if (error) { + YAGL_LOG_ERROR("CGLCreatePBuffer failed: %s", CGLErrorString(error)); + pbuffer = NULL; + } + + YAGL_LOG_FUNC_EXIT("%p", pbuffer); + + return pbuffer; +} + +static void yagl_egl_cgl_pbuffer_surface_destroy(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + EGLSurface sfc) +{ + CGLError error; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_pbuffer_surface_destroy, + "dpy = %p, sfc = %p", + dpy, + sfc); + + error = CGLDestroyPBuffer((CGLPBufferObj)sfc); + + if (error) { + YAGL_LOG_ERROR("CGLDestroyPBuffer failed: %s", CGLErrorString(error)); + } + + YAGL_LOG_FUNC_EXIT(NULL); +} + +static EGLContext yagl_egl_cgl_context_create(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + const struct yagl_egl_native_config *cfg, + EGLContext share_context, + int version) +{ + struct yagl_egl_cgl *egl_cgl = (struct yagl_egl_cgl*)driver; + struct yagl_egl_cgl_context *ctx = NULL; + CGLContextObj share_ctx; + CGLError error; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_context_create, + "dpy = %p, share_context = %p, version = %d", + dpy, + share_context, + version); + + ctx = g_malloc0(sizeof(*ctx)); + + if (share_context != EGL_NO_CONTEXT) { + share_ctx = ((struct yagl_egl_cgl_context*)share_context)->base; + } else { + share_ctx = NULL; + } + + if ((egl_cgl->base.gl_version > yagl_gl_2) && (version != 1)) { + error = CGLCreateContext(egl_cgl->pixel_format_3_2_core, + share_ctx, + &ctx->base); + ctx->is_3_2_core = true; + } else { + error = CGLCreateContext(egl_cgl->pixel_format_legacy, + share_ctx, + &ctx->base); + ctx->is_3_2_core = false; + } + + if (error) { + YAGL_LOG_ERROR("CGLCreateContext failed: %s", CGLErrorString(error)); + g_free(ctx); + ctx = NULL; + } + + YAGL_LOG_FUNC_EXIT("%p", ctx); + + return (EGLContext)ctx; +} + +static void yagl_egl_cgl_context_destroy(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + EGLContext ctx) +{ + CGLError error; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_context_destroy, + "dpy = %p, ctx = %p", + dpy, + ctx); + + error = CGLDestroyContext(((struct yagl_egl_cgl_context*)ctx)->base); + + if (error) { + YAGL_LOG_ERROR("CGLDestroyContext failed: %s", CGLErrorString(error)); + } + + g_free(ctx); + + YAGL_LOG_FUNC_EXIT(NULL); +} + +static bool yagl_egl_cgl_make_current(struct yagl_egl_driver *driver, + EGLNativeDisplayType dpy, + EGLSurface draw, + EGLSurface read, + EGLContext ctx) +{ + struct yagl_egl_cgl_context *cgl_ctx = (struct yagl_egl_cgl_context*)ctx; + CGLPBufferObj draw_pbuffer = (CGLPBufferObj)draw; + CGLPBufferObj read_pbuffer = (CGLPBufferObj)read; + CGLError error; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_make_current, + "dpy = %p, draw = %p, read = %p, ctx = %p", + dpy, + draw, + read, + ctx); + + if (cgl_ctx && !cgl_ctx->is_3_2_core) { + if (read_pbuffer) { + error = CGLSetPBuffer(cgl_ctx->base, read_pbuffer, 0, 0, 0); + + if (error) { + YAGL_LOG_ERROR("CGLSetPBuffer failed for read: %s", CGLErrorString(error)); + goto fail; + } + } + + if (draw_pbuffer) { + error = CGLSetPBuffer(cgl_ctx->base, draw_pbuffer, 0, 0, 0); + + if (error) { + YAGL_LOG_ERROR("CGLSetPBuffer failed for draw: %s", CGLErrorString(error)); + goto fail; + } + } + } + + error = CGLSetCurrentContext(cgl_ctx ? cgl_ctx->base : NULL); + + if (error) { + YAGL_LOG_ERROR("CGLSetCurrentContext failed: %s", CGLErrorString(error)); + goto fail; + } + + YAGL_LOG_FUNC_EXIT("context %p was made current", cgl_ctx); + + return true; + +fail: + YAGL_LOG_FUNC_EXIT("Failed to make context %p current", cgl_ctx); + + return false; +} + +static void yagl_egl_cgl_destroy(struct yagl_egl_driver *driver) +{ + struct yagl_egl_cgl *egl_cgl = (struct yagl_egl_cgl*)driver; + + YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_destroy, NULL); + + CGLDestroyPixelFormat(egl_cgl->pixel_format_legacy); + if (egl_cgl->pixel_format_3_2_core) { + CGLDestroyPixelFormat(egl_cgl->pixel_format_3_2_core); + } + + yagl_egl_driver_cleanup(&egl_cgl->base); + + g_free(egl_cgl); + + YAGL_LOG_FUNC_EXIT(NULL); +} + +struct yagl_egl_driver *yagl_egl_driver_create(void *display) +{ + CGLError error; + struct yagl_egl_cgl *egl_cgl; + int n; + + YAGL_LOG_FUNC_ENTER(yagl_egl_driver_create, NULL); + + egl_cgl = g_malloc0(sizeof(*egl_cgl)); + + yagl_egl_driver_init(&egl_cgl->base); + + egl_cgl->base.dyn_lib = yagl_dyn_lib_create(); + + if (!egl_cgl->base.dyn_lib) { + goto fail; + } + + if (!yagl_dyn_lib_load(egl_cgl->base.dyn_lib, LIBGL_IMAGE_NAME)) { + YAGL_LOG_ERROR("Unable to load " LIBGL_IMAGE_NAME ": %s", + yagl_dyn_lib_get_error(egl_cgl->base.dyn_lib)); + goto fail; + } + + if (!yagl_egl_cgl_get_gl_version(egl_cgl, &egl_cgl->base.gl_version)) { + goto fail; + } + + error = CGLChoosePixelFormat(pixel_format_legacy_attrs, + &egl_cgl->pixel_format_legacy, + &n); + + if (error) { + YAGL_LOG_ERROR("CGLChoosePixelFormat failed for legacy attrs: %s", CGLErrorString(error)); + goto fail; + } + + if (!egl_cgl->pixel_format_legacy) { + YAGL_LOG_ERROR("CGLChoosePixelFormat failed to find formats for legacy attrs"); + goto fail; + } + + if (egl_cgl->base.gl_version >= yagl_gl_3_2) { + error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs, + &egl_cgl->pixel_format_3_2_core, + &n); + + if (error) { + YAGL_LOG_ERROR("CGLChoosePixelFormat failed for 3_2_core attrs: %s", CGLErrorString(error)); + goto fail; + } + + if (!egl_cgl->pixel_format_3_2_core) { + YAGL_LOG_ERROR("CGLChoosePixelFormat failed to find formats for 3_2_core attrs"); + goto fail; + } + } + + egl_cgl->base.display_open = &yagl_egl_cgl_display_open; + egl_cgl->base.display_close = &yagl_egl_cgl_display_close; + egl_cgl->base.config_enum = &yagl_egl_cgl_config_enum; + egl_cgl->base.config_cleanup = &yagl_egl_cgl_config_cleanup; + egl_cgl->base.pbuffer_surface_create = &yagl_egl_cgl_pbuffer_surface_create; + egl_cgl->base.pbuffer_surface_destroy = &yagl_egl_cgl_pbuffer_surface_destroy; + egl_cgl->base.context_create = &yagl_egl_cgl_context_create; + egl_cgl->base.context_destroy = &yagl_egl_cgl_context_destroy; + egl_cgl->base.make_current = &yagl_egl_cgl_make_current; + egl_cgl->base.destroy = &yagl_egl_cgl_destroy; + + YAGL_LOG_FUNC_EXIT(NULL); + + return &egl_cgl->base; + +fail: + yagl_egl_driver_cleanup(&egl_cgl->base); + g_free(egl_cgl); + + YAGL_LOG_FUNC_EXIT(NULL); + + return NULL; +} + +void *yagl_dyn_lib_get_ogl_procaddr(struct yagl_dyn_lib *dyn_lib, + const char *sym_name) +{ + return yagl_dyn_lib_get_sym(dyn_lib, sym_name); +} |