mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 02:20:43 -05:00
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)
|
if (!ctx->options_parsed)
|
||||||
{
|
{
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
if (error)
|
||||||
CLUTTER_INIT_ERROR_INTERNAL,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
"When using clutter_get_option_group_without_init() "
|
CLUTTER_INIT_ERROR_INTERNAL,
|
||||||
"you must parse options before calling clutter_init()");
|
"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;
|
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 ();
|
||||||
|
|
||||||
|
@ -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,47 +472,82 @@ 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;
|
||||||
|
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)
|
if (backend_glx->gl_context == None)
|
||||||
{
|
{
|
||||||
GLXFBConfig config;
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
gboolean is_direct;
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
|
"Unable to create suitable GL context");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
|
is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to find a suitable GLXFBConfig for "
|
|
||||||
"the GLX context");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (GL, "Creating GLX Context (display: %p)",
|
CLUTTER_NOTE (GL, "Setting %s context",
|
||||||
backend_x11->xdpy);
|
is_direct ? "direct"
|
||||||
|
: "indirect");
|
||||||
|
_cogl_set_indirect_context (!is_direct);
|
||||||
|
|
||||||
backend_glx->gl_context =
|
/* in order to query the GL and GLX implementation we
|
||||||
glXCreateNewContext (backend_x11->xdpy,
|
* need to bind the GLX context to a Drawable; we create
|
||||||
config,
|
* a simple, off-screen override-redirect window that we
|
||||||
GLX_RGBA_TYPE,
|
* then destroy at the end of this function
|
||||||
NULL,
|
*/
|
||||||
True);
|
xvisinfo = glXGetVisualFromFBConfig (xdisplay, config);
|
||||||
|
if (xvisinfo == None)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to retrieve the X11 visual");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (backend_glx->gl_context == None)
|
clutter_x11_trap_x_errors ();
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to create suitable GL context");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_direct = glXIsDirect (backend_x11->xdpy,
|
attrs.override_redirect = True;
|
||||||
backend_glx->gl_context);
|
backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
|
||||||
|
-100, -100, 1, 1,
|
||||||
|
0,
|
||||||
|
xvisinfo->depth,
|
||||||
|
CopyFromParent,
|
||||||
|
xvisinfo->visual,
|
||||||
|
CWOverrideRedirect,
|
||||||
|
&attrs);
|
||||||
|
|
||||||
CLUTTER_NOTE (GL,
|
glXMakeContextCurrent (xdisplay,
|
||||||
"Setting %s context",
|
backend_glx->dummy_xwin,
|
||||||
is_direct ? "direct" : "indirect");
|
backend_glx->dummy_xwin,
|
||||||
_cogl_set_indirect_context (!is_direct);
|
backend_glx->gl_context);
|
||||||
|
|
||||||
|
if (clutter_x11_untrap_x_errors ())
|
||||||
|
{
|
||||||
|
g_critical ("Unable to retrieve the GLX features");
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -615,7 +606,15 @@ 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");
|
||||||
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user