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.
This commit is contained in:
Robert Bragg 2010-01-14 14:03:23 +00:00
parent ca3ab41a1b
commit 848db1ee4c
4 changed files with 86 additions and 16 deletions

View File

@ -192,6 +192,12 @@ clutter_backend_glx_dispose (GObject *gobject)
backend_glx->gl_context = None; 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) if (backend_glx->dummy_xwin)
{ {
XDestroyWindow (backend_x11->xdpy, 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) GError **error)
{ {
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
GLXFBConfig config; GLXFBConfig config;
gboolean is_direct; gboolean is_direct;
Window root_xwin; Window root_xwin;
XSetWindowAttributes attrs; XSetWindowAttributes attrs;
XVisualInfo *xvisinfo; XVisualInfo *xvisinfo;
Display *xdisplay; Display *xdisplay;
int major;
int minor;
GLXDrawable dummy_drawable;
if (backend_glx->gl_context != None) if (backend_glx->gl_context != None)
return TRUE; return TRUE;
@ -552,12 +562,29 @@ clutter_backend_glx_create_context (ClutterBackend *backend,
CWOverrideRedirect | CWColormap, CWOverrideRedirect | CWColormap,
&attrs); &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", CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context",
(unsigned int) backend_glx->dummy_xwin); (unsigned int) dummy_drawable);
glXMakeContextCurrent (xdisplay, glXMakeContextCurrent (xdisplay,
backend_glx->dummy_xwin, dummy_drawable,
backend_glx->dummy_xwin, dummy_drawable,
backend_glx->gl_context); backend_glx->gl_context);
XFree (xvisinfo); XFree (xvisinfo);
@ -599,6 +626,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
ClutterBackendX11 *backend_x11; ClutterBackendX11 *backend_x11;
ClutterStageGLX *stage_glx; ClutterStageGLX *stage_glx;
ClutterStageX11 *stage_x11; ClutterStageX11 *stage_x11;
GLXDrawable drawable;
g_assert (impl != NULL); g_assert (impl != NULL);
@ -607,10 +635,12 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
backend_glx = CLUTTER_BACKEND_GLX (backend); backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend); backend_x11 = CLUTTER_BACKEND_X11 (backend);
drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"Setting context for stage of type %s, window: 0x%x", "Setting context for stage of type %s, window: 0x%x",
G_OBJECT_TYPE_NAME (impl), G_OBJECT_TYPE_NAME (impl),
(unsigned int) stage_x11->xwin); (unsigned int) drawable);
/* no GL context to set */ /* no GL context to set */
if (backend_glx->gl_context == None) 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 /* we might get here inside the final dispose cycle, so we
* need to handle this gracefully * need to handle this gracefully
*/ */
if (stage_x11->xwin == None) if (drawable == None)
{ {
GLXDrawable dummy_drawable;
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"Received a stale stage, clearing all context"); "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, glXMakeContextCurrent (backend_x11->xdpy,
backend_glx->dummy_xwin, dummy_drawable,
backend_glx->dummy_xwin, dummy_drawable,
backend_glx->gl_context); backend_glx->gl_context);
} }
else
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
} }
else else
{ {
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p", "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
backend_x11->xdpy, backend_x11->xdpy,
(unsigned int) stage_x11->xwin, (unsigned int) drawable,
stage_x11->is_foreign_xwin ? "foreign" : "native", stage_x11->is_foreign_xwin ? "foreign" : "native",
backend_glx->gl_context); backend_glx->gl_context);
glXMakeContextCurrent (backend_x11->xdpy, glXMakeContextCurrent (backend_x11->xdpy,
stage_x11->xwin, drawable,
stage_x11->xwin, drawable,
backend_glx->gl_context); backend_glx->gl_context);
} }
if (clutter_x11_untrap_x_errors ()) if (clutter_x11_untrap_x_errors ())
g_critical ("Unable to make the stage window 0x%x the current " g_critical ("Unable to make the stage window 0x%x the current "
"GLX drawable", "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) if (stage_x11->xwin != None)
{ {
GLXDrawable drawable =
stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
/* wait for the next vblank */ /* wait for the next vblank */
CLUTTER_NOTE (BACKEND, "Waiting for vblank"); CLUTTER_NOTE (BACKEND, "Waiting for vblank");
glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend)); glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
@ -764,10 +804,10 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
/* push on the screen */ /* push on the screen */
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)", CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
backend_x11->xdpy, backend_x11->xdpy,
(unsigned long) stage_x11->xwin); (unsigned long) drawable);
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer); 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); CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
} }
} }

View File

@ -67,6 +67,7 @@ struct _ClutterBackendGLX
GLXFBConfig fbconfig; GLXFBConfig fbconfig;
GLXContext gl_context; GLXContext gl_context;
Window dummy_xwin; Window dummy_xwin;
GLXWindow dummy_glxwin;
/* Vblank stuff */ /* Vblank stuff */
GetVideoSyncProc get_video_sync; GetVideoSyncProc get_video_sync;

View File

@ -63,12 +63,19 @@ clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
ClutterBackend *backend = clutter_get_default_backend (); ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); 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 */ /* Note unrealize should free up any backend stage related resources */
CLUTTER_NOTE (BACKEND, "Unrealizing stage"); CLUTTER_NOTE (BACKEND, "Unrealizing stage");
clutter_x11_trap_x_errors (); 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) if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{ {
XDestroyWindow (backend_x11->xdpy, stage_x11->xwin); XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
@ -88,6 +95,7 @@ static gboolean
clutter_stage_glx_realize (ClutterStageWindow *stage_window) clutter_stage_glx_realize (ClutterStageWindow *stage_window)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
ClutterBackend *backend; ClutterBackend *backend;
ClutterBackendGLX *backend_glx; ClutterBackendGLX *backend_glx;
ClutterBackendX11 *backend_x11; ClutterBackendX11 *backend_x11;
@ -143,6 +151,26 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
XFree (xvisinfo); 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_event_retrieval ())
{ {
if (clutter_x11_has_xinput ()) if (clutter_x11_has_xinput ())

View File

@ -49,6 +49,7 @@ struct _ClutterStageGLX
ClutterStageX11 parent_instance; ClutterStageX11 parent_instance;
GLXPixmap glxpixmap; GLXPixmap glxpixmap;
GLXWindow glxwin;
}; };
struct _ClutterStageGLXClass struct _ClutterStageGLXClass