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

View File

@ -187,10 +187,17 @@ clutter_backend_glx_dispose (GObject *gobject)
if (backend_glx->gl_context)
{
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context);
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);
}
@ -231,59 +238,15 @@ static ClutterFeatureFlags
clutter_backend_glx_get_features (ClutterBackend *backend)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
const gchar *glx_extensions = NULL;
ClutterFeatureFlags flags;
Window dummy_xwin, root_xwin;
XSetWindowAttributes attrs;
XVisualInfo *xvisinfo;
Display *xdisplay;
flags = clutter_backend_x11_get_features (backend);
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
/* this will make sure that the GL context exists */
g_assert (backend_glx->gl_context != 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;
}
g_assert (glXGetCurrentDrawable () != None);
CLUTTER_NOTE (BACKEND,
"Checking features\n"
@ -395,13 +358,6 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
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;
}
@ -516,47 +472,82 @@ 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;
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))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to find suitable fbconfig for GL context");
return FALSE;
}
CLUTTER_NOTE (GL, "Creating GL Context (display: %p)", xdisplay);
backend_glx->gl_context = glXCreateNewContext (xdisplay,
config,
GLX_RGBA_TYPE,
NULL,
True);
if (backend_glx->gl_context == None)
{
GLXFBConfig config;
gboolean is_direct;
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to create suitable GL context");
return FALSE;
}
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to find a suitable GLXFBConfig for "
"the GLX context");
return FALSE;
}
is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
CLUTTER_NOTE (GL, "Creating GLX Context (display: %p)",
backend_x11->xdpy);
CLUTTER_NOTE (GL, "Setting %s context",
is_direct ? "direct"
: "indirect");
_cogl_set_indirect_context (!is_direct);
backend_glx->gl_context =
glXCreateNewContext (backend_x11->xdpy,
config,
GLX_RGBA_TYPE,
NULL,
True);
/* 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;
}
if (backend_glx->gl_context == None)
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to create suitable GL context");
return FALSE;
}
clutter_x11_trap_x_errors ();
is_direct = glXIsDirect (backend_x11->xdpy,
backend_glx->gl_context);
attrs.override_redirect = True;
backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
-100, -100, 1, 1,
0,
xvisinfo->depth,
CopyFromParent,
xvisinfo->visual,
CWOverrideRedirect,
&attrs);
CLUTTER_NOTE (GL,
"Setting %s context",
is_direct ? "direct" : "indirect");
_cogl_set_indirect_context (!is_direct);
glXMakeContextCurrent (xdisplay,
backend_glx->dummy_xwin,
backend_glx->dummy_xwin,
backend_glx->gl_context);
if (clutter_x11_untrap_x_errors ())
{
g_critical ("Unable to retrieve the GLX features");
return FALSE;
}
return TRUE;
@ -615,7 +606,15 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
CLUTTER_NOTE (BACKEND,
"Received a stale stage, clearing all context");
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
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);
}
else
{

View File

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