From 848db1ee4cc910542435bbcd3a57933bdf70269e Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 14 Jan 2010 14:03:23 +0000 Subject: [PATCH] glx backend: when running with GLX 1.3 then create GLXWindows for stages Some extensions only support GLX versions > 1.3 and may not support old style X Windows as GLXDrawables, so we now create GLXWindows for stages when possible. --- clutter/glx/clutter-backend-glx.c | 72 ++++++++++++++++++++++++------- clutter/glx/clutter-backend-glx.h | 1 + clutter/glx/clutter-stage-glx.c | 28 ++++++++++++ clutter/glx/clutter-stage-glx.h | 1 + 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c index cafeeaf95..13203bff2 100644 --- a/clutter/glx/clutter-backend-glx.c +++ b/clutter/glx/clutter-backend-glx.c @@ -192,6 +192,12 @@ clutter_backend_glx_dispose (GObject *gobject) backend_glx->gl_context = None; } + if (backend_glx->dummy_glxwin) + { + glXDestroyWindow (backend_x11->xdpy, backend_glx->dummy_glxwin); + backend_glx->dummy_glxwin = None; + } + if (backend_glx->dummy_xwin) { XDestroyWindow (backend_x11->xdpy, backend_glx->dummy_xwin); @@ -472,12 +478,16 @@ clutter_backend_glx_create_context (ClutterBackend *backend, GError **error) { ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); GLXFBConfig config; gboolean is_direct; Window root_xwin; XSetWindowAttributes attrs; XVisualInfo *xvisinfo; Display *xdisplay; + int major; + int minor; + GLXDrawable dummy_drawable; if (backend_glx->gl_context != None) return TRUE; @@ -552,12 +562,29 @@ clutter_backend_glx_create_context (ClutterBackend *backend, CWOverrideRedirect | CWColormap, &attrs); + /* Try and create a GLXWindow to use with extensions dependent on + * GLX versions >= 1.3 that don't accept regular X Windows as GLX + * drawables. */ + if (glXQueryVersion (backend_x11->xdpy, &major, &minor) && + major == 1 && minor >= 3) + { + backend_glx->dummy_glxwin = glXCreateWindow (backend_x11->xdpy, + config, + backend_glx->dummy_xwin, + NULL); + } + + if (backend_glx->dummy_glxwin) + dummy_drawable = backend_glx->dummy_glxwin; + else + dummy_drawable = backend_glx->dummy_xwin; + CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context", - (unsigned int) backend_glx->dummy_xwin); + (unsigned int) dummy_drawable); glXMakeContextCurrent (xdisplay, - backend_glx->dummy_xwin, - backend_glx->dummy_xwin, + dummy_drawable, + dummy_drawable, backend_glx->gl_context); XFree (xvisinfo); @@ -599,6 +626,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend, ClutterBackendX11 *backend_x11; ClutterStageGLX *stage_glx; ClutterStageX11 *stage_x11; + GLXDrawable drawable; g_assert (impl != NULL); @@ -607,10 +635,12 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend, backend_glx = CLUTTER_BACKEND_GLX (backend); backend_x11 = CLUTTER_BACKEND_X11 (backend); + drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; + CLUTTER_NOTE (BACKEND, "Setting context for stage of type %s, window: 0x%x", G_OBJECT_TYPE_NAME (impl), - (unsigned int) stage_x11->xwin); + (unsigned int) drawable); /* no GL context to set */ if (backend_glx->gl_context == None) @@ -621,40 +651,47 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend, /* we might get here inside the final dispose cycle, so we * need to handle this gracefully */ - if (stage_x11->xwin == None) + if (drawable == None) { + GLXDrawable dummy_drawable; + CLUTTER_NOTE (BACKEND, "Received a stale stage, clearing all context"); - if (backend_glx->dummy_xwin != None) + if (backend_glx->dummy_glxwin) + dummy_drawable = backend_glx->dummy_glxwin; + else + dummy_drawable = backend_glx->dummy_xwin; + + if (dummy_drawable == None) + glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL); + else { glXMakeContextCurrent (backend_x11->xdpy, - backend_glx->dummy_xwin, - backend_glx->dummy_xwin, + dummy_drawable, + dummy_drawable, backend_glx->gl_context); } - else - glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL); } else { CLUTTER_NOTE (BACKEND, "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p", backend_x11->xdpy, - (unsigned int) stage_x11->xwin, + (unsigned int) drawable, stage_x11->is_foreign_xwin ? "foreign" : "native", backend_glx->gl_context); glXMakeContextCurrent (backend_x11->xdpy, - stage_x11->xwin, - stage_x11->xwin, + drawable, + drawable, backend_glx->gl_context); } if (clutter_x11_untrap_x_errors ()) g_critical ("Unable to make the stage window 0x%x the current " "GLX drawable", - (unsigned int) stage_x11->xwin); + (unsigned int) drawable); } } @@ -757,6 +794,9 @@ clutter_backend_glx_redraw (ClutterBackend *backend, if (stage_x11->xwin != None) { + GLXDrawable drawable = + stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; + /* wait for the next vblank */ CLUTTER_NOTE (BACKEND, "Waiting for vblank"); glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend)); @@ -764,10 +804,10 @@ clutter_backend_glx_redraw (ClutterBackend *backend, /* push on the screen */ CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)", backend_x11->xdpy, - (unsigned long) stage_x11->xwin); + (unsigned long) drawable); CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer); - glXSwapBuffers (backend_x11->xdpy, stage_x11->xwin); + glXSwapBuffers (backend_x11->xdpy, drawable); CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer); } } diff --git a/clutter/glx/clutter-backend-glx.h b/clutter/glx/clutter-backend-glx.h index 97ddb6fd0..f14d6bbcc 100644 --- a/clutter/glx/clutter-backend-glx.h +++ b/clutter/glx/clutter-backend-glx.h @@ -67,6 +67,7 @@ struct _ClutterBackendGLX GLXFBConfig fbconfig; GLXContext gl_context; Window dummy_xwin; + GLXWindow dummy_glxwin; /* Vblank stuff */ GetVideoSyncProc get_video_sync; diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index 3764d3a8f..db5856ae9 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -63,12 +63,19 @@ clutter_stage_glx_unrealize (ClutterStageWindow *stage_window) ClutterBackend *backend = clutter_get_default_backend (); ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); /* Note unrealize should free up any backend stage related resources */ CLUTTER_NOTE (BACKEND, "Unrealizing stage"); clutter_x11_trap_x_errors (); + if (stage_glx->glxwin != None) + { + glXDestroyWindow (backend_x11->xdpy, stage_glx->glxwin); + stage_glx->glxwin = None; + } + if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None) { XDestroyWindow (backend_x11->xdpy, stage_x11->xwin); @@ -88,6 +95,7 @@ static gboolean clutter_stage_glx_realize (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); ClutterBackend *backend; ClutterBackendGLX *backend_glx; ClutterBackendX11 *backend_x11; @@ -143,6 +151,26 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window) XFree (xvisinfo); } + if (stage_glx->glxwin == None) + { + int major; + int minor; + GLXFBConfig config; + + /* Try and create a GLXWindow to use with extensions dependent on + * GLX versions >= 1.3 that don't accept regular X Windows as GLX + * drawables. */ + if (glXQueryVersion (backend_x11->xdpy, &major, &minor) && + major == 1 && minor >= 3 && + _clutter_backend_glx_get_fbconfig (backend_glx, &config)) + { + stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy, + config, + stage_x11->xwin, + NULL); + } + } + if (clutter_x11_has_event_retrieval ()) { if (clutter_x11_has_xinput ()) diff --git a/clutter/glx/clutter-stage-glx.h b/clutter/glx/clutter-stage-glx.h index bd1646abc..7f3fa7b91 100644 --- a/clutter/glx/clutter-stage-glx.h +++ b/clutter/glx/clutter-stage-glx.h @@ -49,6 +49,7 @@ struct _ClutterStageGLX ClutterStageX11 parent_instance; GLXPixmap glxpixmap; + GLXWindow glxwin; }; struct _ClutterStageGLXClass