glx: Create the dummy Window with the GLX context

Since we must guarantee that Cogl has a GL context to query, it is too
late to use the "dummy Window" trick from within the get_features()
virtual function implementation.

Instead, we can create a dummy Window from create_context() itself and
leave it around - basically trading a default stage with a dummy X
window.

We need to have the dummy X window around all the time so that the
GLX context can be selected and made current.
This commit is contained in:
Emmanuele Bassi 2009-12-03 20:49:54 +00:00
parent 5eb6fb74b6
commit d2c091e62d
3 changed files with 95 additions and 91 deletions

View File

@ -1503,10 +1503,14 @@ clutter_init_real (GError **error)
if (!ctx->options_parsed) if (!ctx->options_parsed)
{ {
if (error)
g_set_error (error, CLUTTER_INIT_ERROR, g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL, CLUTTER_INIT_ERROR_INTERNAL,
"When using clutter_get_option_group_without_init() " "When using clutter_get_option_group_without_init() "
"you must parse options before calling clutter_init()"); "you must parse options before calling clutter_init()");
else
g_critical ("When using clutter_get_option_group_without_init() "
"you must parse options before calling clutter_init()");
return CLUTTER_INIT_ERROR_INTERNAL; return CLUTTER_INIT_ERROR_INTERNAL;
} }
@ -1517,8 +1521,8 @@ clutter_init_real (GError **error)
if (!_clutter_backend_post_parse (backend, error)) if (!_clutter_backend_post_parse (backend, error))
return CLUTTER_INIT_ERROR_BACKEND; return CLUTTER_INIT_ERROR_BACKEND;
/* this will create the GL context and query it for features and /* this will take care of initializing Cogl's state and
* state setup * query the GL machinery for features
*/ */
_clutter_feature_init (); _clutter_feature_init ();

View File

@ -187,10 +187,17 @@ clutter_backend_glx_dispose (GObject *gobject)
if (backend_glx->gl_context) if (backend_glx->gl_context)
{ {
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context); glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context);
backend_glx->gl_context = None; backend_glx->gl_context = None;
} }
if (backend_glx->dummy_xwin)
{
XDestroyWindow (backend_x11->xdpy, backend_glx->dummy_xwin);
backend_glx->dummy_xwin = None;
}
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject); G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
} }
@ -231,59 +238,15 @@ static ClutterFeatureFlags
clutter_backend_glx_get_features (ClutterBackend *backend) clutter_backend_glx_get_features (ClutterBackend *backend)
{ {
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
const gchar *glx_extensions = NULL; const gchar *glx_extensions = NULL;
ClutterFeatureFlags flags; ClutterFeatureFlags flags;
Window dummy_xwin, root_xwin;
XSetWindowAttributes attrs;
XVisualInfo *xvisinfo;
Display *xdisplay;
flags = clutter_backend_x11_get_features (backend); flags = clutter_backend_x11_get_features (backend);
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE; flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
/* this will make sure that the GL context exists */ /* this will make sure that the GL context exists */
g_assert (backend_glx->gl_context != None); g_assert (backend_glx->gl_context != None);
g_assert (glXGetCurrentDrawable () != None);
/* in order to query the GL and GLX implementation we
* need to bind the GLX context to a Drawable; we create
* a simple, off-screen override-redirect window that we
* then destroy at the end of this function
*/
xdisplay = clutter_x11_get_default_display ();
root_xwin = clutter_x11_get_root_window ();
xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
if (xvisinfo == None)
{
g_critical ("Unable to retrieve the X11 visual");
return flags;
}
clutter_x11_trap_x_errors ();
attrs.override_redirect = True;
attrs.colormap = XCreateColormap (xdisplay, root_xwin,
xvisinfo->visual,
AllocNone);
dummy_xwin = XCreateWindow (xdisplay, root_xwin,
-100, -100, 1, 1,
0,
xvisinfo->depth,
CopyFromParent,
xvisinfo->visual,
CWOverrideRedirect | CWColormap,
&attrs);
glXMakeContextCurrent (xdisplay,
dummy_xwin, dummy_xwin,
backend_glx->gl_context);
if (clutter_x11_untrap_x_errors ())
{
g_critical ("Unable to retrieve the GLX features");
goto out;
}
CLUTTER_NOTE (BACKEND, CLUTTER_NOTE (BACKEND,
"Checking features\n" "Checking features\n"
@ -395,13 +358,6 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
CLUTTER_NOTE (BACKEND, "backend features checked"); CLUTTER_NOTE (BACKEND, "backend features checked");
out:
/* unset the GLX context */
glXMakeContextCurrent (xdisplay, None, None, NULL);
/* destroy the dummy Window */
XDestroyWindow (xdisplay, dummy_xwin);
return flags; return flags;
} }
@ -516,32 +472,34 @@ 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);
if (backend_glx->gl_context == None)
{
GLXFBConfig config; GLXFBConfig config;
gboolean is_direct; gboolean is_direct;
Window root_xwin;
XSetWindowAttributes attrs;
XVisualInfo *xvisinfo;
Display *xdisplay;
if (backend_glx->gl_context != None)
return TRUE;
xdisplay = clutter_x11_get_default_display ();
root_xwin = clutter_x11_get_root_window ();
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config)) if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{ {
g_set_error (error, CLUTTER_INIT_ERROR, g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND, CLUTTER_INIT_ERROR_BACKEND,
"Unable to find a suitable GLXFBConfig for " "Unable to find suitable fbconfig for GL context");
"the GLX context");
return FALSE; return FALSE;
} }
CLUTTER_NOTE (GL, "Creating GLX Context (display: %p)", CLUTTER_NOTE (GL, "Creating GL Context (display: %p)", xdisplay);
backend_x11->xdpy);
backend_glx->gl_context = backend_glx->gl_context = glXCreateNewContext (xdisplay,
glXCreateNewContext (backend_x11->xdpy,
config, config,
GLX_RGBA_TYPE, GLX_RGBA_TYPE,
NULL, NULL,
True); True);
if (backend_glx->gl_context == None) if (backend_glx->gl_context == None)
{ {
g_set_error (error, CLUTTER_INIT_ERROR, g_set_error (error, CLUTTER_INIT_ERROR,
@ -550,13 +508,46 @@ clutter_backend_glx_create_context (ClutterBackend *backend,
return FALSE; return FALSE;
} }
is_direct = glXIsDirect (backend_x11->xdpy, is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
CLUTTER_NOTE (GL, "Setting %s context",
is_direct ? "direct"
: "indirect");
_cogl_set_indirect_context (!is_direct);
/* in order to query the GL and GLX implementation we
* need to bind the GLX context to a Drawable; we create
* a simple, off-screen override-redirect window that we
* then destroy at the end of this function
*/
xvisinfo = glXGetVisualFromFBConfig (xdisplay, config);
if (xvisinfo == None)
{
g_critical ("Unable to retrieve the X11 visual");
return FALSE;
}
clutter_x11_trap_x_errors ();
attrs.override_redirect = True;
backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
-100, -100, 1, 1,
0,
xvisinfo->depth,
CopyFromParent,
xvisinfo->visual,
CWOverrideRedirect,
&attrs);
glXMakeContextCurrent (xdisplay,
backend_glx->dummy_xwin,
backend_glx->dummy_xwin,
backend_glx->gl_context); backend_glx->gl_context);
CLUTTER_NOTE (GL, if (clutter_x11_untrap_x_errors ())
"Setting %s context", {
is_direct ? "direct" : "indirect"); g_critical ("Unable to retrieve the GLX features");
_cogl_set_indirect_context (!is_direct); return FALSE;
} }
return TRUE; return TRUE;
@ -615,6 +606,14 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
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)
{
glXMakeContextCurrent (backend_x11->xdpy,
backend_glx->dummy_xwin,
backend_glx->dummy_xwin,
backend_glx->gl_context);
}
else
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL); glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
} }
else else

View File

@ -66,6 +66,7 @@ struct _ClutterBackendGLX
gboolean found_fbconfig; gboolean found_fbconfig;
GLXFBConfig fbconfig; GLXFBConfig fbconfig;
GLXContext gl_context; GLXContext gl_context;
Window dummy_xwin;
/* Vblank stuff */ /* Vblank stuff */
GetVideoSyncProc get_video_sync; GetVideoSyncProc get_video_sync;