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:
parent
5eb6fb74b6
commit
d2c091e62d
@ -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 ();
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ struct _ClutterBackendGLX
|
||||
gboolean found_fbconfig;
|
||||
GLXFBConfig fbconfig;
|
||||
GLXContext gl_context;
|
||||
Window dummy_xwin;
|
||||
|
||||
/* Vblank stuff */
|
||||
GetVideoSyncProc get_video_sync;
|
||||
|
Loading…
Reference in New Issue
Block a user