X-Git-Url: http://pileus.org/git/?p=grits;a=blobdiff_plain;f=src%2Fgtkgl.c;h=19f3219043273e18f82be3b976acf83d911b80ae;hp=6812d33bc6f870086d5017a84a61fb36cb295d94;hb=5c17e7d79895982036139dcffb5c17cefb1d4d9f;hpb=6c98281f93edb654fdf1586f8c3cfed811457e3e diff --git a/src/gtkgl.c b/src/gtkgl.c index 6812d33..19f3219 100644 --- a/src/gtkgl.c +++ b/src/gtkgl.c @@ -1,9 +1,26 @@ +/* + * Copyright (C) 2009-2011 Andy Spencer + * + * 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 3 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, see . + */ + #include /*************************** * GtkGlExt implementation * ***************************/ -#if defined(USE_GTKGLEXT) +#if defined(SYS_GTKGLEXT) #include void gtk_gl_enable(GtkWidget *widget) { @@ -36,9 +53,29 @@ void gtk_gl_disable(GtkWidget *widget) /********************** * X11 implementation * **********************/ -#elif defined(USE_GLX) +#elif defined(SYS_X11) #include #include +static gboolean gtk_gl_errors; +static int gtk_gl_handler(Display *xdisplay, XErrorEvent *xerror) +{ + gtk_gl_errors = TRUE; + return 0; +} +static GLXContext gtk_gl_create_context(Display *xdisplay, XVisualInfo *xvinfo, + GLXContext shared, Bool direct) +{ + gtk_gl_errors = FALSE; + XSync(xdisplay, False); + void *handler = XSetErrorHandler(gtk_gl_handler); + GLXContext context = glXCreateContext(xdisplay, xvinfo, shared, direct); + XSync(xdisplay, False); + XSetErrorHandler(handler); + + if (gtk_gl_errors) + return 0; + return context; +} void gtk_gl_enable(GtkWidget *widget) { g_debug("GtkGl: enable"); @@ -55,14 +92,33 @@ void gtk_gl_enable(GtkWidget *widget) GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None}; + XVisualInfo *xvinfo = glXChooseVisual(xdisplay, nscreen, attribs); - GLXContext context = glXCreateContext(xdisplay, xvinfo, NULL, False); + if (!xvinfo) + g_error("GtkGl: enable - unable to get valid OpenGL Visual"); + GLXContext context = 0; + if (!context) + context = gtk_gl_create_context(xdisplay, xvinfo, NULL, True); + if (!context) + context = gtk_gl_create_context(xdisplay, xvinfo, NULL, False); + if (!context) + g_error("Unable to create OpenGL context," + "possible graphics driver problem?"); + g_debug("GtkGl: direct rendering = %d\n", glXIsDirect(xdisplay, context)); + g_object_set_data(G_OBJECT(widget), "glcontext", context); - /* Fix up colormap */ + /* Fix up visual/colormap */ +#if GTK_CHECK_VERSION(3,0,0) + GdkVisual *visual = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid); + gtk_widget_set_visual(widget, visual); +#else GdkVisual *visual = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid); GdkColormap *cmap = gdk_colormap_new(visual, FALSE); gtk_widget_set_colormap(widget, cmap); + g_object_unref(cmap); +#endif + XFree(xvinfo); /* Disable GTK double buffering */ gtk_widget_set_double_buffered(widget, FALSE); @@ -97,9 +153,45 @@ void gtk_gl_disable(GtkWidget *widget) /************************ * Win32 implementation * ************************/ -#elif defined(USE_WGL) +#elif defined(SYS_WIN) #include #include +#include + +/* Windows doens't define OpenGL extensions */ +static void APIENTRY (*glMultiTexCoord2dvPtr)(int target, const double *v); +static void APIENTRY (*glActiveTexturePtr)(int texture); + +void APIENTRY glMultiTexCoord2dv(int target, const double *v) +{ + glMultiTexCoord2dvPtr(target, v); +} + +void APIENTRY glActiveTexture(int texture) +{ + glActiveTexturePtr(texture); +} + +static void init_extensions(void) +{ + static gboolean init_done = FALSE; + if (init_done) + return; + init_done = TRUE; + + g_debug("GtkGl: init_extensions"); + const guchar *exts = NULL; + if (!(exts = glGetString(GL_EXTENSIONS))) + g_error("GtkGl: Unable to query extensions"); + if (!(glMultiTexCoord2dvPtr = (void*)wglGetProcAddress("glMultiTexCoord2dvARB"))) + g_error("GtkGl: Unable to load glMultiTexCoord2dv extension:\n%s", exts); + if (!(glActiveTexturePtr = (void*)wglGetProcAddress("glActiveTextureARB"))) + g_error("GtkGl: Unable to load glActiveTexture extension\n%s", exts); + g_debug("GtkGl: extensions - glMultiTexCoord2dvPtr=%p glActiveTexturePtr=%p", + glMultiTexCoord2dvPtr, glActiveTexturePtr); +} + +/* gtkgl implementation */ static void on_realize(GtkWidget *widget, gpointer _) { g_debug("GtkGl: on_realize"); @@ -148,6 +240,7 @@ void gtk_gl_begin(GtkWidget *widget) HGLRC hRC = g_object_get_data(G_OBJECT(widget), "glcontext"); if (!wglMakeCurrent(hDC, hRC)) g_error("GtkGl: wglMakeCurrent failed"); + init_extensions(); } void gtk_gl_end(GtkWidget *widget) @@ -167,46 +260,64 @@ void gtk_gl_disable(GtkWidget *widget) } - /************************** * Mac OSX implementation * **************************/ -#elif defined(USE_CGL) +#elif defined(SYS_MAC) +#include void gtk_gl_enable(GtkWidget *widget) { - CGDisplayCapture( kCGDirectMainDisplay ); - CGLPixelFormatAttribute attribs[] = - { - kCGLPFANoRecovery, - kCGLPFADoubleBuffer, - kCGLPFAFullScreen, - kCGLPFAStencilSize, ( CGLPixelFormatAttribute ) 8, - kCGLPFADisplayMask, ( CGLPixelFormatAttribute ) CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ), - ( CGLPixelFormatAttribute ) NULL - }; - - CGLPixelFormatObj pixelFormatObj; - GLint numPixelFormats; - CGLChoosePixelFormat( attribs, &pixelFormatObj, &numPixelFormats ); + g_debug("GtkGl: enable"); - CGLCreateContext( pixelFormatObj, NULL, &contextObj ); + /* Create context */ + NSOpenGLPixelFormatAttribute attribs[] = { + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 1, + NSOpenGLPFADoubleBuffer, + 0 + }; + NSOpenGLPixelFormat *pix = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:pix shareContext:nil]; - CGLDestroyPixelFormat( pixelFormatObj ); + /* Attach to widget */ + gtk_widget_set_double_buffered(widget, FALSE); - CGLSetCurrentContext( contextObj ); - CGLSetFullScreen( contextObj ); + /* Save context */ + g_object_set_data(G_OBJECT(widget), "glcontext", ctx); } void gtk_gl_begin(GtkWidget *widget) { + g_debug("GtkGl: begin"); + GtkAllocation alloc; + gdk_window_ensure_native(gtk_widget_get_window(widget)); + gtk_widget_get_allocation(widget, &alloc); + gtk_widget_translate_coordinates(widget, gtk_widget_get_toplevel(widget), + 0, 0, &alloc.x, &alloc.y); + + NSOpenGLContext *ctx = g_object_get_data(G_OBJECT(widget), "glcontext"); + GdkWindow *win = gtk_widget_get_window(widget); + NSView *view = gdk_quartz_window_get_nsview(win); + NSRect rect = NSMakeRect(alloc.x, alloc.y, alloc.width, alloc.height); + + [ctx setView:view]; + [ctx makeCurrentContext]; + [ctx update]; + [view setFrame:rect]; + [view setWantsBestResolutionOpenGLSurface:YES]; } void gtk_gl_end(GtkWidget *widget) { + g_debug("GtkGl: end"); + NSOpenGLContext *ctx = g_object_get_data(G_OBJECT(widget), "glcontext"); + [ctx flushBuffer]; } void gtk_gl_disable(GtkWidget *widget) { + g_debug("GtkGl: disable"); }