From 6e60ad204cfdba76c4d118b0ea4cb3c7af16cf2e Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Fri, 28 Mar 2014 18:25:30 +0400 Subject: [PATCH] check-gl: updated for YaGL/VIGS Change-Id: Ie6421de6ccb0b9a3a2460d114950a9fb190f4d95 Signed-off-by: Stanislav Vorobiov --- Makefile.target | 24 ++- tizen/src/check_gl.c | 221 +++++++++++++++++++++++- tizen/src/check_gl.h | 61 +++++++ tizen/src/check_gl_cgl.c | 182 ++++++++++++++++++++ tizen/src/check_gl_glx.c | 259 ++++++++++++++++++++++++++++ tizen/src/check_gl_wgl.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1160 insertions(+), 13 deletions(-) create mode 100644 tizen/src/check_gl.h create mode 100644 tizen/src/check_gl_cgl.c create mode 100644 tizen/src/check_gl_glx.c create mode 100644 tizen/src/check_gl_wgl.c diff --git a/Makefile.target b/Makefile.target index 3fa46ab..df09d20 100644 --- a/Makefile.target +++ b/Makefile.target @@ -178,31 +178,37 @@ $(QEMU_PROG): $(all-obj-y) ../libqemuutil.a ../libqemustub.a $(call LINK,$^) endif -CHECK_GL_OBJS = check_gl.o gloffscreen_test.o gloffscreen_common.o +CHECK_GL_OBJS = check_gl.o CHECK_GL_LDFLAGS = CHECK_GL_TARGET = ifdef CONFIG_LINUX -CHECK_GL_OBJS += gloffscreen_xcomposite.o +CHECK_GL_OBJS += check_gl_glx.o #CHECK_GL_LDFLAGS += -lGL -lXcomposite -lXext -lglib-2.0 # Fix linking error on Ubuntu 13.04 -CHECK_GL_LDFLAGS += -lGL -lXcomposite -lX11 -lXext -lglib-2.0 +CHECK_GL_LDFLAGS += -lX11 -lXext -lglib-2.0 CHECK_GL_TARGET = check-gl endif ifdef CONFIG_WIN32 -CHECK_GL_OBJS += gloffscreen_wgl.o -CHECK_GL_LDFLAGS += -fstack-protector `pkg-config --libs glib-2.0` -lopengl32 -lglu32 -lgdi32 +CHECK_GL_OBJS += check_gl_wgl.o +CHECK_GL_LDFLAGS += -fstack-protector `pkg-config --libs glib-2.0` -lgdi32 CHECK_GL_TARGET = check-gl.exe endif ifdef CONFIG_DARWIN -CHECK_GL_OBJS += gloffscreen_agl.o -CHECK_GL_LDFLAGS += -mmacosx-version-min=10.4 `pkg-config --cflags --libs glib-2.0` -framework GLUT -framework OpenGL -framework AGL +CHECK_GL_OBJS += check_gl_cgl.o +CHECK_GL_LDFLAGS += -mmacosx-version-min=10.4 `pkg-config --cflags --libs glib-2.0` -framework OpenGL CHECK_GL_TARGET = check-gl endif -check-gl: check_gl.o +check-gl: $(CHECK_GL_OBJS) gcc -o $(CHECK_GL_TARGET) $(CHECK_GL_OBJS) $(CHECK_GL_LDFLAGS) check_gl.o: check_gl.c - gcc -c ../tizen/src/check_gl.c + gcc -c ../tizen/src/check_gl.c -I../hw/yagl/yagl_inc +check_gl_glx.o: check_gl_glx.c + gcc -c ../tizen/src/check_gl_glx.c -I../hw/yagl/yagl_inc +check_gl_wgl.o: check_gl_wgl.c + gcc -c ../tizen/src/check_gl_wgl.c -I../hw/yagl/yagl_inc +check_gl_cgl.o: check_gl_cgl.c + gcc -c ../tizen/src/check_gl_cgl.c -I../hw/yagl/yagl_inc gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@") diff --git a/tizen/src/check_gl.c b/tizen/src/check_gl.c index 1d83edb..a2815b3 100644 --- a/tizen/src/check_gl.c +++ b/tizen/src/check_gl.c @@ -1,7 +1,220 @@ -#include "hw/gloffscreen_test.h" -#include "debug_ch.h" +/* + * Copyright (c) 2011 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 + * + */ -int main (int argc, char** argv) +#include "check_gl.h" +#include +#include +#include +#include +#include + +static const char *log_level_str[gl_error + 1] = +{ + "INFO", + "WARN", + "ERROR" +}; + +static const char *gl_version_str[gl_3_2 + 1] = +{ + "2.1", + "3.1", + "3.2" +}; + +void check_gl_log(gl_log_level level, const char *format, ...) +{ + va_list args; + + fprintf(stderr, "%-5s", log_level_str[level]); + + va_start(args, format); + fprintf(stderr, " - "); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, "\n"); +} + +static const GLubyte *(GLAPIENTRY *get_string)(GLenum); +static const GLubyte *(GLAPIENTRY *get_stringi)(GLenum, GLuint); +static void (GLAPIENTRY *get_integerv)(GLenum, GLint*); + +static struct gl_context *check_gl_version(gl_version version) { - return gl_acceleration_capability_check(); + struct gl_context *ctx = NULL; + int hw = 1; + + ctx = check_gl_context_create(NULL, version); + + if (!ctx) { + goto fail; + } + + if (!check_gl_make_current(ctx)) { + goto fail; + } + + if ((strstr((const char*)get_string(GL_RENDERER), "Software") != NULL)) { + check_gl_log(gl_warn, + "Host OpenGL %s - software", + gl_version_str[version]); + hw = 0; + } else if (strncmp((const char*)get_string(GL_VERSION), + "1.4", strlen("1.4")) == 0) { + /* + * Handle LIBGL_ALWAYS_INDIRECT=1 case. + */ + check_gl_log(gl_warn, + "Host OpenGL %s - NOT supported", + gl_version_str[version]); + hw = 0; + } else { + check_gl_log(gl_info, + "Host OpenGL %s - supported", + gl_version_str[version]); + } + + check_gl_log(gl_info, "+ GL_VENDOR = %s", (const char*)get_string(GL_VENDOR)); + check_gl_log(gl_info, "+ GL_RENDERER = %s", (const char*)get_string(GL_RENDERER)); + check_gl_log(gl_info, "+ GL_VERSION = %s", (const char*)get_string(GL_VERSION)); + + if (!hw) { + check_gl_context_destroy(ctx); + ctx = NULL; + } + + check_gl_make_current(NULL); + + return ctx; + +fail: + if (ctx) { + check_gl_context_destroy(ctx); + } + + check_gl_log(gl_info, + "Host OpenGL %s - NOT supported", + gl_version_str[version]); + + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct gl_context *ctx_2; + struct gl_context *ctx_3_1; + struct gl_context *ctx_3_2; + int have_es3 = 0; + int have_es1 = 0; + + if (!check_gl_init()) { + return 1; + } + + if (!check_gl_procaddr((void**)&get_string, "glGetString", 0) || + !check_gl_procaddr((void**)&get_stringi, "glGetStringi", 1) || + !check_gl_procaddr((void**)&get_integerv, "glGetIntegerv", 0)) { + return 1; + } + + ctx_2 = check_gl_version(gl_2); + ctx_3_1 = check_gl_version(gl_3_1); + ctx_3_2 = check_gl_version(gl_3_2); + + if (!ctx_2 && !ctx_3_1 && !ctx_3_2) { + check_gl_log(gl_info, "Host does not have hardware GL acceleration!"); + return 1; + } + + have_es1 = (ctx_2 != NULL); + have_es3 = (ctx_3_2 != NULL); + + /* + * Check if GL_ARB_ES3_compatibility is supported within + * OpenGL 3.1 context. + */ + + if (ctx_3_1 && get_stringi && check_gl_make_current(ctx_3_1)) { + GLint i, num_extensions = 0; + + get_integerv(GL_NUM_EXTENSIONS, &num_extensions); + + for (i = 0; i < num_extensions; ++i) { + const char *tmp; + + tmp = (const char*)get_stringi(GL_EXTENSIONS, i); + + if (strcmp(tmp, "GL_ARB_ES3_compatibility") == 0) { + have_es3 = 1; + break; + } + } + + check_gl_make_current(NULL); + } + + /* + * Check if OpenGL 2.1 contexts can be shared with OpenGL 3.x contexts + */ + + if (ctx_2 && ((ctx_3_1 && have_es3) || ctx_3_2)) { + struct gl_context *ctx = NULL; + + ctx = check_gl_context_create(((ctx_3_1 && have_es3) ? ctx_3_1 + : ctx_3_2), + gl_2); + + if (ctx) { + if (check_gl_make_current(ctx)) { + check_gl_make_current(NULL); + } else { + have_es1 = 0; + } + check_gl_context_destroy(ctx); + } else { + have_es1 = 0; + } + } + + if (have_es1) { + check_gl_log(gl_info, "Guest OpenGL ES v1_CM - supported"); + } else { + check_gl_log(gl_warn, "Guest OpenGL ES v1_CM - NOT supported"); + } + check_gl_log(gl_info, "Guest OpenGL ES 2.0 - supported"); + if (have_es3) { + check_gl_log(gl_info, "Guest OpenGL ES 3.0 - supported"); + } else { + check_gl_log(gl_warn, "Guest OpenGL ES 3.0 - NOT supported"); + } + + check_gl_log(gl_info, "Host has hardware GL acceleration!"); + + return 0; } diff --git a/tizen/src/check_gl.h b/tizen/src/check_gl.h new file mode 100644 index 0000000..3e761be --- /dev/null +++ b/tizen/src/check_gl.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 + * + */ + +#ifndef __CHECK_GL_H__ +#define __CHECK_GL_H__ + +struct gl_context; + +typedef enum +{ + gl_info = 0, + gl_warn = 1, + gl_error = 2 +} gl_log_level; + +typedef enum +{ + gl_2 = 0, + gl_3_1 = 1, + gl_3_2 = 2 +} gl_version; + +void check_gl_log(gl_log_level level, const char *format, ...); + +int check_gl_init(void); + +struct gl_context *check_gl_context_create(struct gl_context *share_ctx, + gl_version version); + +int check_gl_make_current(struct gl_context *ctx); + +void check_gl_context_destroy(struct gl_context *ctx); + +int check_gl_procaddr(void **func, const char *sym, int opt); + +#endif diff --git a/tizen/src/check_gl_cgl.c b/tizen/src/check_gl_cgl.c new file mode 100644 index 0000000..c776325 --- /dev/null +++ b/tizen/src/check_gl_cgl.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2011 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 "check_gl.h" +#include +#include +#include +#include + +#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 + +struct gl_context +{ + CGLContextObj base; +}; + +static void *handle; + +int check_gl_init(void) +{ + handle = dlopen(LIBGL_IMAGE_NAME, RTLD_NOW | RTLD_GLOBAL); + + if (!handle) { + check_gl_log(gl_error, "%s", dlerror()); + return 0; + } + + return 1; +} + +struct gl_context *check_gl_context_create(struct gl_context *share_ctx, + gl_version version) +{ + 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 + }; + CGLError error; + CGLPixelFormatObj pixel_format; + int n; + CGLContextObj base = NULL; + struct gl_context *ctx; + + switch (version) { + case gl_2: + error = CGLChoosePixelFormat(pixel_format_legacy_attrs, + &pixel_format, + &n); + + if (error || !pixel_format) { + break; + } + + error = CGLCreateContext(pixel_format, + (share_ctx ? share_ctx->base : NULL), + &base); + + CGLDestroyPixelFormat(pixel_format); + + if (error) { + base = NULL; + } + + break; + case gl_3_1: + break; + case gl_3_2: + error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs, + &pixel_format, + &n); + + if (error || !pixel_format) { + break; + } + + error = CGLCreateContext(pixel_format, + (share_ctx ? share_ctx->base : NULL), + &base); + + CGLDestroyPixelFormat(pixel_format); + + if (error) { + base = NULL; + } + + break; + default: + assert(0); + return NULL; + } + + if (!base) { + return NULL; + } + + ctx = malloc(sizeof(*ctx)); + + if (!ctx) { + CGLDestroyContext(base); + return NULL; + } + + ctx->base = base; + + return ctx; +} + +int check_gl_make_current(struct gl_context *ctx) +{ + return !CGLSetCurrentContext(ctx ? ctx->base : NULL); +} + +void check_gl_context_destroy(struct gl_context *ctx) +{ + CGLDestroyContext(ctx->base); + free(ctx); +} + +int check_gl_procaddr(void **func, const char *sym, int opt) +{ + *func = dlsym(handle, sym); + + if (!*func && !opt) { + check_gl_log(gl_error, "Unable to find symbol \"%s\"", sym); + return 0; + } + + return 1; +} diff --git a/tizen/src/check_gl_glx.c b/tizen/src/check_gl_glx.c new file mode 100644 index 0000000..f8c13a8 --- /dev/null +++ b/tizen/src/check_gl_glx.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2011 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 "check_gl.h" +#include +#include +#include +#include + +#ifndef GLX_VERSION_1_4 +#error GL/glx.h must be equal to or greater than GLX 1.4 +#endif + +#define GLX_GET_PROC(func, sym) \ + do { \ + *(void**)(&func) = (void*)get_proc_address((const GLubyte*)#sym); \ + if (!func) { \ + check_gl_log(gl_error, "%s", dlerror()); \ + return 0; \ + } \ + } while (0) + +struct gl_context +{ + GLXContext base; + GLXPbuffer sfc; +}; + +typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display *dpy, GLXContext ctx); + +static void *handle; +static Display *x_dpy; +static GLXFBConfig x_config; +static PFNGLXGETPROCADDRESSPROC get_proc_address; +static PFNGLXCHOOSEFBCONFIGPROC choose_fb_config; +static PFNGLXCREATEPBUFFERPROC create_pbuffer; +static PFNGLXDESTROYPBUFFERPROC destroy_pbuffer; +static PFNGLXCREATENEWCONTEXTPROC create_context; +static PFNGLXDESTROYCONTEXTPROC destroy_context; +static PFNGLXMAKECONTEXTCURRENTPROC make_current; + +/* GLX_ARB_create_context */ +static PFNGLXCREATECONTEXTATTRIBSARBPROC create_context_attribs; + +static int check_gl_error_handler(Display *dpy, XErrorEvent *e) +{ + return 0; +} + +int check_gl_init(void) +{ + static const int config_attribs[] = + { + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_BUFFER_SIZE, 32, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + None + }; + int n = 0; + GLXFBConfig *configs; + + x_dpy = XOpenDisplay(NULL); + + if (!x_dpy) { + check_gl_log(gl_error, "Unable to open X display"); + return 0; + } + + XSetErrorHandler(check_gl_error_handler); + + handle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); + + if (!handle) { + check_gl_log(gl_error, "%s", dlerror()); + return 0; + } + + get_proc_address = dlsym(handle, "glXGetProcAddress"); + + if (!get_proc_address) { + get_proc_address = dlsym(handle, "glXGetProcAddressARB"); + } + + if (!get_proc_address) { + check_gl_log(gl_error, "%s", dlerror()); + return 0; + } + + GLX_GET_PROC(choose_fb_config, glXChooseFBConfig); + GLX_GET_PROC(create_pbuffer, glXCreatePbuffer); + GLX_GET_PROC(destroy_pbuffer, glXDestroyPbuffer); + GLX_GET_PROC(create_context, glXCreateNewContext); + GLX_GET_PROC(destroy_context, glXDestroyContext); + GLX_GET_PROC(make_current, glXMakeContextCurrent); + GLX_GET_PROC(create_context_attribs, glXCreateContextAttribsARB); + + configs = choose_fb_config(x_dpy, + DefaultScreen(x_dpy), + config_attribs, + &n); + + if (!configs || (n <= 0)) { + check_gl_log(gl_error, "Unable to find suitable FB config"); + return 0; + } + + x_config = configs[0]; + + XFree(configs); + + return 1; +} + +struct gl_context *check_gl_context_create(struct gl_context *share_ctx, + gl_version version) +{ + static const int ctx_attribs_3_1[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_RENDER_TYPE, GLX_RGBA_TYPE, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + static const int ctx_attribs_3_2[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_RENDER_TYPE, GLX_RGBA_TYPE, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + static const int surface_attribs[] = + { + GLX_PBUFFER_WIDTH, 1, + GLX_PBUFFER_HEIGHT, 1, + GLX_LARGEST_PBUFFER, False, + None + }; + GLXContext base; + GLXPbuffer sfc; + struct gl_context *ctx; + + switch (version) { + case gl_2: + base = create_context(x_dpy, + x_config, + GLX_RGBA_TYPE, + (share_ctx ? share_ctx->base : NULL), + True); + break; + case gl_3_1: + base = create_context_attribs(x_dpy, + x_config, + (share_ctx ? share_ctx->base : NULL), + True, + ctx_attribs_3_1); + break; + case gl_3_2: + base = create_context_attribs(x_dpy, + x_config, + (share_ctx ? share_ctx->base : NULL), + True, + ctx_attribs_3_2); + break; + default: + assert(0); + return NULL; + } + + if (!base) { + return NULL; + } + + sfc = create_pbuffer(x_dpy, + x_config, + surface_attribs); + + if (!sfc) { + destroy_context(x_dpy, base); + return NULL; + } + + ctx = malloc(sizeof(*ctx)); + + if (!ctx) { + destroy_pbuffer(x_dpy, sfc); + destroy_context(x_dpy, base); + return NULL; + } + + ctx->base = base; + ctx->sfc = sfc; + + return ctx; +} + +int check_gl_make_current(struct gl_context *ctx) +{ + return make_current(x_dpy, + (ctx ? ctx->sfc : None), + (ctx ? ctx->sfc : None), + (ctx ? ctx->base : NULL)); +} + +void check_gl_context_destroy(struct gl_context *ctx) +{ + destroy_pbuffer(x_dpy, ctx->sfc); + destroy_context(x_dpy, ctx->base); + free(ctx); +} + +int check_gl_procaddr(void **func, const char *sym, int opt) +{ + *func = (void*)get_proc_address((const GLubyte*)sym); + + if (!*func) { + *func = dlsym(handle, sym); + } + + if (!*func && !opt) { + check_gl_log(gl_error, "Unable to find symbol \"%s\"", sym); + return 0; + } + + return 1; +} diff --git a/tizen/src/check_gl_wgl.c b/tizen/src/check_gl_wgl.c new file mode 100644 index 0000000..f447c5a --- /dev/null +++ b/tizen/src/check_gl_wgl.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2011 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 "check_gl.h" +#include +#include +#include +#include +#include + +#define WGL_GET_PROC(func, sym) \ + do { \ + *(void**)(&func) = (void*)GetProcAddress(handle, #sym); \ + if (!func) { \ + check_gl_log(gl_error, "Unable to load %s symbol", #sym); \ + goto fail; \ + } \ + } while (0) + +#define WGL_GET_EXT_PROC(func, ext, sym) \ + do { \ + if ((strstr(ext_str, #ext " ") == NULL)) { \ + check_gl_log(gl_error, "Extension %s not supported", #ext); \ + goto fail; \ + } \ + *(void**)(&func) = (void*)get_proc_address((LPCSTR)#sym); \ + if (!func) { \ + check_gl_log(gl_error, "Unable to load %s symbol", #sym); \ + goto fail; \ + } \ + } while (0) + +struct gl_context +{ + HGLRC base; + HPBUFFERARB sfc; + HDC sfc_dc; +}; + +typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTPROC)(HDC hdl); +typedef BOOL (WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC hdl); +typedef PROC (WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR sym); +typedef BOOL (WINAPI *PFNWGLMAKECURRENTPROC)(HDC dev_ctx, HGLRC rend_ctx); +typedef BOOL (WINAPI *PFNWGLSHARELISTSPROC)(HGLRC ctx1, HGLRC ctx2); + +static HINSTANCE handle = NULL; +static HWND init_win = NULL; +static HDC init_dc = NULL; +static HGLRC init_ctx = NULL; +static HWND win = NULL; +static HDC dc = NULL; +static int config_id = 0; +static struct gl_context *current = NULL; +static PFNWGLCREATECONTEXTPROC create_context; +static PFNWGLDELETECONTEXTPROC delete_context; +static PFNWGLGETPROCADDRESSPROC get_proc_address; +static PFNWGLMAKECURRENTPROC make_current; +static PFNWGLSHARELISTSPROC share_lists; + +/* WGL extensions */ +static PFNWGLGETEXTENSIONSSTRINGEXTPROC get_extensions_string_ext; +static PFNWGLGETEXTENSIONSSTRINGARBPROC get_extensions_string_arb; +static PFNWGLCHOOSEPIXELFORMATARBPROC choose_pixel_format; +static PFNWGLCREATEPBUFFERARBPROC create_pbuffer; +static PFNWGLGETPBUFFERDCARBPROC get_pbuffer_dc; +static PFNWGLRELEASEPBUFFERDCARBPROC release_pbuffer_dc; +static PFNWGLDESTROYPBUFFERARBPROC destroy_pbuffer; + +/* WGL_ARB_create_context */ +static PFNWGLCREATECONTEXTATTRIBSARBPROC create_context_attribs; + +int check_gl_init(void) +{ + WNDCLASSEXA win_class; + PIXELFORMATDESCRIPTOR init_pixfmt = + { + .nSize = sizeof(PIXELFORMATDESCRIPTOR), + .nVersion = 1, + .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + .iPixelType = PFD_TYPE_RGBA, + .cColorBits = 32, + .cDepthBits = 24, + .cStencilBits = 8, + .iLayerType = PFD_MAIN_PLANE, + }; + int init_config_id = 0; + const char *ext_str = NULL; + const int config_attribs[] = + { + WGL_SUPPORT_OPENGL_ARB, TRUE, + WGL_DOUBLE_BUFFER_ARB, TRUE, + WGL_DRAW_TO_PBUFFER_ARB, TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_RED_BITS_ARB, 8, + WGL_GREEN_BITS_ARB, 8, + WGL_BLUE_BITS_ARB, 8, + WGL_ALPHA_BITS_ARB, 8, + WGL_COLOR_BITS_ARB, 32, + WGL_DEPTH_BITS_ARB, 24, + WGL_STENCIL_BITS_ARB, 8, + 0, + }; + UINT n = 0; + PIXELFORMATDESCRIPTOR pixfmt; + + win_class.cbSize = sizeof(WNDCLASSEXA); + win_class.style = 0; + win_class.lpfnWndProc = &DefWindowProcA; + win_class.cbClsExtra = 0; + win_class.cbWndExtra = 0; + win_class.hInstance = NULL; + win_class.hIcon = NULL; + win_class.hCursor = NULL; + win_class.hbrBackground = NULL; + win_class.lpszMenuName = NULL; + win_class.lpszClassName = "CheckGLWinClass"; + win_class.hIconSm = NULL; + + if (!RegisterClassExA(&win_class)) { + check_gl_log(gl_error, "Unable to register window class"); + return 0; + } + + handle = LoadLibraryA("opengl32"); + + if (!handle) { + check_gl_log(gl_error, "Unable to load opengl32.dll"); + goto fail; + } + + WGL_GET_PROC(create_context, wglCreateContext); + WGL_GET_PROC(delete_context, wglDeleteContext); + WGL_GET_PROC(get_proc_address, wglGetProcAddress); + WGL_GET_PROC(make_current, wglMakeCurrent); + WGL_GET_PROC(share_lists, wglShareLists); + + init_win = CreateWindow("CheckGLWinClass", "CheckGLWin", + WS_DISABLED | WS_POPUP, + 0, 0, 1, 1, NULL, NULL, 0, 0); + + if (!init_win) { + check_gl_log(gl_error, "Unable to create window"); + goto fail; + } + + init_dc = GetDC(init_win); + + if (!init_dc) { + check_gl_log(gl_error, "Unable to get window DC"); + goto fail; + } + + init_config_id = ChoosePixelFormat(init_dc, &init_pixfmt); + + if (!init_config_id) { + check_gl_log(gl_error, "ChoosePixelFormat failed"); + goto fail; + } + + if (!SetPixelFormat(init_dc, init_config_id, &init_pixfmt)) { + check_gl_log(gl_error, "SetPixelFormat failed"); + goto fail; + } + + init_ctx = create_context(init_dc); + if (!init_ctx) { + check_gl_log(gl_error, "wglCreateContext failed"); + goto fail; + } + + if (!make_current(init_dc, init_ctx)) { + check_gl_log(gl_error, "wglMakeCurrent failed"); + goto fail; + } + + /* + * WGL extensions couldn't be queried by glGetString(), we need to use + * wglGetExtensionsStringARB or wglGetExtensionsStringEXT for this, which + * themselves are extensions + */ + get_extensions_string_arb = (PFNWGLGETEXTENSIONSSTRINGARBPROC) + get_proc_address((LPCSTR)"wglGetExtensionsStringARB"); + get_extensions_string_ext = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) + get_proc_address((LPCSTR)"wglGetExtensionsStringEXT"); + + if (get_extensions_string_arb) { + ext_str = get_extensions_string_arb(init_dc); + } else if (get_extensions_string_ext) { + ext_str = get_extensions_string_ext(); + } + + if (!ext_str) { + check_gl_log(gl_error, "Unable to obtain WGL extension string"); + goto fail; + } + + WGL_GET_EXT_PROC(create_pbuffer, WGL_ARB_pbuffer, wglCreatePbufferARB); + WGL_GET_EXT_PROC(get_pbuffer_dc, WGL_ARB_pbuffer, wglGetPbufferDCARB); + WGL_GET_EXT_PROC(release_pbuffer_dc, WGL_ARB_pbuffer, wglReleasePbufferDCARB); + WGL_GET_EXT_PROC(destroy_pbuffer, WGL_ARB_pbuffer, wglDestroyPbufferARB); + WGL_GET_EXT_PROC(choose_pixel_format, WGL_ARB_pixel_format, wglChoosePixelFormatARB); + WGL_GET_EXT_PROC(create_context_attribs, WGL_ARB_create_context, wglCreateContextAttribsARB); + + make_current(NULL, NULL); + + win = CreateWindow("CheckGLWinClass", "CheckGLWin2", + WS_DISABLED | WS_POPUP, + 0, 0, 1, 1, NULL, NULL, 0, 0); + + if (!win) { + check_gl_log(gl_error, "Unable to create window"); + goto fail; + } + + dc = GetDC(win); + + if (!dc) { + check_gl_log(gl_error, "Unable to get window DC"); + goto fail; + } + + if (!choose_pixel_format(dc, + config_attribs, + NULL, + 1, + &config_id, + &n) || (n == 0)) { + check_gl_log(gl_error, "wglChoosePixelFormat failed"); + goto fail; + } + + if (!DescribePixelFormat(dc, + config_id, + sizeof(PIXELFORMATDESCRIPTOR), + &pixfmt)) { + check_gl_log(gl_error, "DescribePixelFormat failed"); + goto fail; + } + + if (!SetPixelFormat(dc, + config_id, + &pixfmt)) { + check_gl_log(gl_error, "SetPixelFormat failed"); + goto fail; + } + + return 1; + +fail: + if (dc) { + ReleaseDC(win, dc); + } + if (win) { + DestroyWindow(win); + } + if (init_ctx) { + make_current(NULL, NULL); + delete_context(init_ctx); + } + if (init_dc) { + ReleaseDC(init_win, init_dc); + } + if (init_win) { + DestroyWindow(init_win); + } + if (handle) { + FreeLibrary(handle); + } + + UnregisterClassA((LPCTSTR)"CheckGLWinClass", NULL); + + return 0; +} + +struct gl_context *check_gl_context_create(struct gl_context *share_ctx, + gl_version version) +{ + static const int ctx_attribs_3_1[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 1, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 + }; + static const int ctx_attribs_3_2[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 2, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 + }; + static const int surface_attribs[] = + { + WGL_PBUFFER_LARGEST_ARB, FALSE, + WGL_TEXTURE_TARGET_ARB, WGL_NO_TEXTURE_ARB, + WGL_TEXTURE_FORMAT_ARB, WGL_NO_TEXTURE_ARB, + 0 + }; + HGLRC base; + HPBUFFERARB sfc; + HDC sfc_dc; + struct gl_context *ctx; + + switch (version) { + case gl_2: + base = create_context(dc); + if (share_ctx && !share_lists(share_ctx->base, base)) { + delete_context(base); + base = NULL; + } + break; + case gl_3_1: + base = create_context_attribs(dc, + (share_ctx ? share_ctx->base : NULL), + ctx_attribs_3_1); + break; + case gl_3_2: + base = create_context_attribs(dc, + (share_ctx ? share_ctx->base : NULL), + ctx_attribs_3_2); + break; + default: + assert(0); + return NULL; + } + + if (!base) { + return NULL; + } + + sfc = create_pbuffer(dc, + config_id, 1, 1, + surface_attribs); + + if (!sfc) { + delete_context(base); + return NULL; + } + + sfc_dc = get_pbuffer_dc(sfc); + + if (!sfc_dc) { + destroy_pbuffer(sfc); + delete_context(base); + return NULL; + } + + ctx = malloc(sizeof(*ctx)); + + if (!ctx) { + release_pbuffer_dc(sfc, sfc_dc); + destroy_pbuffer(sfc); + delete_context(base); + return NULL; + } + + ctx->base = base; + ctx->sfc = sfc; + ctx->sfc_dc = sfc_dc; + + return ctx; +} + +int check_gl_make_current(struct gl_context *ctx) +{ + current = ctx; + return make_current((ctx ? ctx->sfc_dc : NULL), + (ctx ? ctx->base : NULL)); +} + +void check_gl_context_destroy(struct gl_context *ctx) +{ + release_pbuffer_dc(ctx->sfc, ctx->sfc_dc); + destroy_pbuffer(ctx->sfc); + delete_context(ctx->base); + free(ctx); +} + +int check_gl_procaddr(void **func, const char *sym, int opt) +{ + if (!make_current(init_dc, init_ctx)) { + return 0; + } + + *func = (void*)get_proc_address((LPCSTR)sym); + + if (!*func) { + *func = GetProcAddress(handle, sym); + } + + make_current((current ? current->sfc_dc : NULL), + (current ? current->base : NULL)); + + if (!*func && !opt) { + check_gl_log(gl_error, "Unable to find symbol \"%s\"", sym); + return 0; + } + + return 1; +} -- 2.7.4