[backends] Remove the idea of offscreen stages from all backends

The only backend that tried to implement offscreen stages was the GLX backend
and even this has apparently be broken for some time without anyone noticing.

The property still remains and since the property already clearly states that
it may not work I don't expect anyone to notice.

This simplifies quite a bit of the GLX code which is very desireable from the
POV that we want to start migrating window system code down to Cogl and the
simpler the code is the more straight forward this work will be.

In the future when Cogl has a nicely designed API for framebuffer objects then
re-implementing offscreen stages cleanly for *all* backends should be quite
straightforward.
This commit is contained in:
Robert Bragg 2009-07-31 18:34:51 +01:00
parent 35f11d863c
commit 15d7a86621
15 changed files with 487 additions and 707 deletions

View File

@ -308,7 +308,6 @@ _clutter_backend_redraw (ClutterBackend *backend,
gboolean
_clutter_backend_create_context (ClutterBackend *backend,
gboolean is_offscreen,
GError **error)
{
ClutterBackendClass *klass;
@ -317,7 +316,7 @@ _clutter_backend_create_context (ClutterBackend *backend,
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->create_context)
return klass->create_context (backend, is_offscreen, error);
return klass->create_context (backend, error);
return TRUE;
}

View File

@ -79,7 +79,6 @@ struct _ClutterBackendClass
void (* redraw) (ClutterBackend *backend,
ClutterStage *stage);
gboolean (* create_context) (ClutterBackend *backend,
gboolean is_offscreen,
GError **error);
void (* ensure_context) (ClutterBackend *backend,
ClutterStage *stage);

View File

@ -194,7 +194,6 @@ ClutterStageWindow *_clutter_backend_create_stage (ClutterBackend *backend,
void _clutter_backend_ensure_context (ClutterBackend *backend,
ClutterStage *stage);
gboolean _clutter_backend_create_context (ClutterBackend *backend,
gboolean is_offscreen,
GError **error);
void _clutter_backend_add_options (ClutterBackend *backend,

View File

@ -91,7 +91,6 @@ struct _ClutterStagePrivate
guint redraw_pending : 1;
guint is_fullscreen : 1;
guint is_offscreen : 1;
guint is_cursor_visible : 1;
guint is_user_resizable : 1;
guint use_fog : 1;
@ -581,13 +580,6 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
CLUTTER_CONTEXT ()->redraw_count += 1;
}
static void
set_offscreen_while_unrealized (ClutterActor *actor,
void *data)
{
CLUTTER_STAGE (actor)->priv->is_offscreen = GPOINTER_TO_INT (data);
}
static void
clutter_stage_set_property (GObject *object,
guint prop_id,
@ -609,26 +601,8 @@ clutter_stage_set_property (GObject *object,
break;
case PROP_OFFSCREEN:
{
gboolean was_showing;
if (priv->is_offscreen == g_value_get_boolean (value))
return;
was_showing = CLUTTER_ACTOR_IS_VISIBLE (actor);
/* Backend needs to check this prop and handle accordingly
* in realise.
* FIXME: More 'obvious' implementation needed?
*/
_clutter_actor_rerealize (actor,
set_offscreen_while_unrealized,
GINT_TO_POINTER (g_value_get_boolean (value)));
if (was_showing &&
!CLUTTER_ACTOR_IS_REALIZED (actor))
priv->is_offscreen = ~g_value_get_boolean (value);
}
if (g_value_get_boolean (value))
g_warning ("Offscreen stages are currently not supported\n");
break;
case PROP_CURSOR_VISIBLE:
@ -679,7 +653,7 @@ clutter_stage_get_property (GObject *gobject,
break;
case PROP_OFFSCREEN:
g_value_set_boolean (value, priv->is_offscreen);
g_value_set_boolean (value, FALSE);
break;
case PROP_FULLSCREEN_SET:
@ -1020,7 +994,6 @@ clutter_stage_init (ClutterStage *self)
priv->event_queue = g_queue_new ();
priv->is_offscreen = FALSE;
priv->is_fullscreen = FALSE;
priv->is_user_resizable = FALSE;
priv->is_cursor_visible = TRUE;

View File

@ -67,155 +67,142 @@ clutter_stage_egl_realize (ClutterActor *actor)
EGLConfig configs[2];
EGLint config_count;
EGLBoolean status;
gboolean is_offscreen;
EGLint cfg_attribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 16,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, 2,
#ifdef HAVE_COGL_GLES2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else /* HAVE_COGL_GLES2 */
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif /* HAVE_COGL_GLES2 */
EGL_NONE };
CLUTTER_NOTE (BACKEND, "Realizing main stage");
g_object_get (stage_egl->wrapper, "offscreen", &is_offscreen, NULL);
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
if (G_LIKELY (!is_offscreen))
status = eglGetConfigs (backend_egl->edpy,
configs,
2,
&config_count);
if (status != EGL_TRUE)
{
EGLint cfg_attribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 16,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, 2,
#ifdef HAVE_COGL_GLES2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else /* HAVE_COGL_GLES2 */
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif /* HAVE_COGL_GLES2 */
EGL_NONE };
status = eglGetConfigs (backend_egl->edpy,
configs,
2,
&config_count);
if (status != EGL_TRUE)
{
g_critical ("eglGetConfigs failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
status = eglChooseConfig (backend_egl->edpy,
cfg_attribs,
configs,
G_N_ELEMENTS (configs),
&config_count);
if (status != EGL_TRUE)
{
g_critical ("eglChooseConfig failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_NOTE (BACKEND, "Got %i configs", config_count);
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
backend_egl->egl_context = NULL;
}
stage_egl->egl_surface =
eglCreateWindowSurface (backend_egl->edpy,
configs[0],
NULL,
NULL);
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_WIDTH,
&stage_egl->surface_width);
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_HEIGHT,
&stage_egl->surface_height);
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
stage_egl->surface_width,
stage_egl->surface_height);
if (G_UNLIKELY (backend_egl->egl_context == NULL))
{
#ifdef HAVE_COGL_GLES2
static const EGLint attribs[3]
= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
attribs);
#else
/* Seems some GLES implementations 1.x do not like attribs... */
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
#endif
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_NOTE (GL, "Created EGL Context");
}
CLUTTER_NOTE (BACKEND, "Setting context");
/* eglnative can have only one stage */
status = eglMakeCurrent (backend_egl->edpy,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (status != EGL_TRUE)
{
g_critical ("eglMakeCurrent failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
/* since we only have one size and it cannot change, we
* just need to update the GL viewport now that we have
* been realized
*/
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES);
}
else
{
g_warning ("EGL Backend does not yet support offscreen rendering\n");
g_critical ("eglGetConfigs failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
status = eglChooseConfig (backend_egl->edpy,
cfg_attribs,
configs,
G_N_ELEMENTS (configs),
&config_count);
if (status != EGL_TRUE)
{
g_critical ("eglChooseConfig failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_NOTE (BACKEND, "Got %i configs", config_count);
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
backend_egl->egl_context = NULL;
}
stage_egl->egl_surface =
eglCreateWindowSurface (backend_egl->edpy,
configs[0],
NULL,
NULL);
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_WIDTH,
&stage_egl->surface_width);
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_HEIGHT,
&stage_egl->surface_height);
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
stage_egl->surface_width,
stage_egl->surface_height);
if (G_UNLIKELY (backend_egl->egl_context == NULL))
{
#ifdef HAVE_COGL_GLES2
static const EGLint attribs[3]
= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
attribs);
#else
/* Seems some GLES implementations 1.x do not like attribs... */
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
#endif
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
CLUTTER_NOTE (GL, "Created EGL Context");
}
CLUTTER_NOTE (BACKEND, "Setting context");
/* eglnative can have only one stage */
status = eglMakeCurrent (backend_egl->edpy,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (status != EGL_TRUE)
{
g_critical ("eglMakeCurrent failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
/* since we only have one size and it cannot change, we
* just need to update the GL viewport now that we have
* been realized
*/
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void

View File

@ -263,8 +263,7 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
}
static XVisualInfo *
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11,
gboolean for_offscreen)
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend_x11);
EGLint visualid;

View File

@ -34,28 +34,18 @@ clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
gboolean was_offscreen;
CLUTTER_NOTE (BACKEND, "Unrealizing stage");
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
clutter_x11_trap_x_errors ();
if (G_UNLIKELY (was_offscreen))
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
/* No support as yet for this */
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
{
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
stage_x11->xwin = None;
}
stage_x11->xwin = None;
if (stage_egl->egl_surface)
{
@ -79,188 +69,169 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
EGLConfig configs[2];
EGLint config_count;
EGLBoolean status;
gboolean is_offscreen = FALSE;
int c;
int num_configs;
EGLConfig *all_configs;
EGLint cfg_attribs[] = {
EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_STENCIL_SIZE, 8,
#ifdef HAVE_COGL_GLES2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else /* HAVE_COGL_GLES2 */
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif /* HAVE_COGL_GLES2 */
EGL_NONE
};
EGLDisplay edpy;
CLUTTER_NOTE (BACKEND, "Realizing main stage");
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
backend = clutter_get_default_backend ();
backend_egl = CLUTTER_BACKEND_EGL (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (G_LIKELY (!is_offscreen))
edpy = clutter_eglx_display ();
eglGetConfigs (edpy, NULL, 0, &num_configs);
all_configs = g_malloc (num_configs * sizeof (EGLConfig));
eglGetConfigs (clutter_eglx_display (),
all_configs,
num_configs,
&num_configs);
for (c = 0; c < num_configs; ++c)
{
Display *xdpy = clutter_eglx_display ();
int c;
int num_configs;
EGLConfig *all_configs;
EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
EGLint cfg_attribs[] = {
EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_STENCIL_SIZE, 8,
#ifdef HAVE_COGL_GLES2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else /* HAVE_COGL_GLES2 */
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#endif /* HAVE_COGL_GLES2 */
EGL_NONE
};
status = eglGetConfigs (xdpy,
configs,
2,
&config_count);
eglGetConfigs (xdpy, NULL, 0, &num_configs);
all_configs = g_malloc (num_configs * sizeof (EGLConfig));
eglGetConfigs (xdpy,
all_configs,
num_configs,
&num_configs);
for (c = 0; c < num_configs; ++c)
{
EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
eglGetConfigAttrib (xdpy,
all_configs[c],
EGL_RED_SIZE, &red);
eglGetConfigAttrib (xdpy,
all_configs[c],
EGL_GREEN_SIZE, &green);
eglGetConfigAttrib (xdpy,
all_configs[c],
EGL_BLUE_SIZE, &blue);
eglGetConfigAttrib (xdpy,
all_configs[c],
EGL_ALPHA_SIZE, &alpha);
eglGetConfigAttrib (xdpy,
all_configs[c],
EGL_STENCIL_SIZE, &stencil);
CLUTTER_NOTE (BACKEND,
"EGLConfig == R:%d G:%d B:%d A:%d S:%d",
red, green, blue, alpha, stencil);
}
g_free (all_configs);
if (status != EGL_TRUE)
{
g_critical ("eglGetConfigs failed");
goto fail;
}
status = eglChooseConfig (xdpy,
cfg_attribs,
configs, G_N_ELEMENTS (configs),
&config_count);
if (status != EGL_TRUE)
{
g_critical ("eglChooseConfig failed");
goto fail;
}
if (stage_x11->xwin == None)
{
stage_x11->xwin =
XCreateSimpleWindow (xdpy,
stage_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0, 0,
WhitePixel (stage_x11->xdpy,
stage_x11->xscreen));
}
if (clutter_x11_has_event_retrieval ())
{
if (clutter_x11_has_xinput ())
{
XSelectInput (xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
#ifdef USE_XINPUT
_clutter_x11_select_events (stage_x11->xwin);
#endif
}
else
XSelectInput (xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
PointerMotionMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
}
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
clutter_stage_x11_set_wm_protocols (stage_x11);
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (xdpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
stage_egl->egl_surface =
eglCreateWindowSurface (xdpy,
configs[0],
(NativeWindowType) stage_x11->xwin,
NULL);
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
goto fail;
}
if (G_UNLIKELY (backend_egl->egl_context == None))
{
#ifdef HAVE_COGL_GLES2
static const EGLint attribs[3]
= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
backend_egl->egl_context = eglCreateContext (xdpy,
configs[0],
EGL_NO_CONTEXT,
attribs);
#else
/* Seems some GLES implementations 1.x do not like attribs... */
backend_egl->egl_context = eglCreateContext (xdpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
#endif
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
goto fail;
}
backend_egl->egl_config = configs[0];
CLUTTER_NOTE (GL, "Created EGL Context");
}
eglGetConfigAttrib (edpy,
all_configs[c],
EGL_RED_SIZE, &red);
eglGetConfigAttrib (edpy,
all_configs[c],
EGL_GREEN_SIZE, &green);
eglGetConfigAttrib (edpy,
all_configs[c],
EGL_BLUE_SIZE, &blue);
eglGetConfigAttrib (edpy,
all_configs[c],
EGL_ALPHA_SIZE, &alpha);
eglGetConfigAttrib (edpy,
all_configs[c],
EGL_STENCIL_SIZE, &stencil);
CLUTTER_NOTE (BACKEND, "EGLConfig == R:%d G:%d B:%d A:%d S:%d \n",
red, green, blue, alpha, stencil);
}
else
g_free (all_configs);
if (status != EGL_TRUE)
{
g_critical ("EGLX Backend does not support offscreen rendering");
g_critical ("eglGetConfigs failed");
goto fail;
}
status = eglChooseConfig (edpy,
cfg_attribs,
configs, G_N_ELEMENTS (configs),
&config_count);
if (status != EGL_TRUE)
{
g_critical ("eglChooseConfig failed");
goto fail;
}
if (stage_x11->xwin == None)
stage_x11->xwin =
XCreateSimpleWindow (stage_x11->xdpy,
stage_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0, 0,
WhitePixel (stage_x11->xdpy,
stage_x11->xscreen));
if (clutter_x11_has_event_retrieval ())
{
if (clutter_x11_has_xinput ())
{
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
#ifdef USE_XINPUT
_clutter_x11_select_events (stage_x11->xwin);
#endif
}
else
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
PointerMotionMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
}
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
clutter_stage_x11_set_wm_protocols (stage_x11);
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (edpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
stage_egl->egl_surface =
eglCreateWindowSurface (edpy,
configs[0],
(NativeWindowType) stage_x11->xwin,
NULL);
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
goto fail;
}
if (G_UNLIKELY (backend_egl->egl_context == None))
{
#ifdef HAVE_COGL_GLES2
static const EGLint attribs[3]
= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
backend_egl->egl_context = eglCreateContext (edpy,
configs[0],
EGL_NO_CONTEXT,
attribs);
#else
/* Seems some GLES implementations 1.x do not like attribs... */
backend_egl->egl_context = eglCreateContext (edpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
#endif
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
goto fail;
}
backend_egl->egl_config = configs[0];
CLUTTER_NOTE (GL, "Created EGL Context");
}
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
return clutter_stage_egl_parent_iface->realize (stage_window);

View File

@ -63,127 +63,116 @@ clutter_stage_egl_realize (ClutterActor *actor)
EGLConfig configs[2];
EGLint config_count;
EGLBoolean status;
gboolean is_offscreen;
EGLint cfg_attribs[] = {
EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 16,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, 2,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE };
CLUTTER_NOTE (BACKEND, "Realizing main stage");
g_object_get (stage_egl->wrapper, "offscreen", &is_offscreen, NULL);
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
if (G_LIKELY (!is_offscreen))
status = eglGetConfigs (backend_egl->edpy,
configs,
2,
&config_count);
if (status != EGL_TRUE)
g_warning ("eglGetConfigs failed");
status = eglChooseConfig (backend_egl->edpy,
cfg_attribs,
configs,
G_N_ELEMENTS (configs),
&config_count);
if (status != EGL_TRUE)
{
EGLint cfg_attribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 16,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, 2,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE };
g_critical ("eglChooseConfig failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
status = eglGetConfigs (backend_egl->edpy,
configs,
2,
&config_count);
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
if (status != EGL_TRUE)
g_warning ("eglGetConfigs failed");
if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
backend_egl->egl_context = NULL;
}
status = eglChooseConfig (backend_egl->edpy,
cfg_attribs,
configs,
G_N_ELEMENTS (configs),
&config_count);
stage_egl->egl_surface =
eglCreateWindowSurface (backend_egl->edpy,
configs[0],
NULL,
NULL);
if (status != EGL_TRUE)
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_WIDTH,
&stage_egl->surface_width);
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_HEIGHT,
&stage_egl->surface_height);
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
stage_egl->surface_width,
stage_egl->surface_height);
if (G_UNLIKELY (backend_egl->egl_context == NULL))
{
CLUTTER_NOTE (GL, "Creating EGL Context");
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("eglChooseConfig failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
g_critical ("Unable to create a suitable EGL context");
if (stage_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
stage_egl->egl_surface = EGL_NO_SURFACE;
}
if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
backend_egl->egl_context = NULL;
}
stage_egl->egl_surface =
eglCreateWindowSurface (backend_egl->edpy,
configs[0],
NULL,
NULL);
if (stage_egl->egl_surface == EGL_NO_SURFACE)
{
g_critical ("Unable to create an EGL surface");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_WIDTH,
&stage_egl->surface_width);
eglQuerySurface (backend_egl->edpy,
stage_egl->egl_surface,
EGL_HEIGHT,
&stage_egl->surface_height);
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
stage_egl->surface_width,
stage_egl->surface_height);
if (G_UNLIKELY (backend_egl->egl_context == NULL))
{
CLUTTER_NOTE (GL, "Creating EGL Context");
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
configs[0],
EGL_NO_CONTEXT,
NULL);
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
g_critical ("Unable to create a suitable EGL context");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
}
/* this will make sure to set the current context */
CLUTTER_NOTE (BACKEND, "Setting context");
/* this should be done in ClutterBackend::ensure_context */
status = eglMakeCurrent (backend_egl->edpy,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (status != EGL_TRUE)
{
g_critical ("eglMakeCurrent failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
}
else
/* this will make sure to set the current context */
CLUTTER_NOTE (BACKEND, "Setting context");
/* this should be done in ClutterBackend::ensure_context */
status = eglMakeCurrent (backend_egl->edpy,
stage_egl->egl_surface,
stage_egl->egl_surface,
backend_egl->egl_context);
if (status != EGL_TRUE)
{
g_warning("EGL Backend does not yet support offscreen rendering\n");
g_critical ("eglMakeCurrent failed");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
}

View File

@ -356,7 +356,6 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
static gboolean
clutter_backend_glx_create_context (ClutterBackend *backend,
gboolean is_offscreen,
GError **error)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
@ -365,18 +364,17 @@ clutter_backend_glx_create_context (ClutterBackend *backend,
if (backend_glx->gl_context == None)
{
XVisualInfo *xvisinfo;
gboolean is_direct;
xvisinfo =
clutter_backend_x11_get_visual_info (backend_x11, is_offscreen);
xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
CLUTTER_NOTE (GL, "Creating GL Context (display: %p, %s)",
backend_x11->xdpy,
is_offscreen ? "offscreen" : "onscreen");
CLUTTER_NOTE (GL, "Creating GL Context (display: %p)",
backend_x11->xdpy);
backend_glx->gl_context = glXCreateContext (backend_x11->xdpy,
xvisinfo,
0,
is_offscreen ? False : True);
True);
XFree (xvisinfo);
@ -384,22 +382,16 @@ clutter_backend_glx_create_context (ClutterBackend *backend,
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to create suitable %s GL context",
is_offscreen ? "offscreen" : "onscreen");
"Unable to create suitable GL context");
return FALSE;
}
if (!is_offscreen)
{
gboolean is_direct;
is_direct = glXIsDirect (backend_x11->xdpy,
backend_glx->gl_context);
is_direct = glXIsDirect (backend_x11->xdpy,
backend_glx->gl_context);
CLUTTER_NOTE (GL, "Setting %s context",
is_direct ? "direct" : "indirect");
_cogl_set_indirect_context (!is_direct);
}
CLUTTER_NOTE (GL, "Setting %s context",
is_direct ? "direct" : "indirect");
_cogl_set_indirect_context (!is_direct);
}
return TRUE;
@ -576,13 +568,6 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
(unsigned long) stage_x11->xwin);
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
}
else
{
/* offscreen */
glXWaitGL ();
CLUTTER_GLERR ();
}
}
static ClutterStageWindow *
@ -619,11 +604,10 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
}
static XVisualInfo *
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11,
gboolean for_offscreen)
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
{
XVisualInfo *xvisinfo;
int onscreen_gl_attributes[] = {
int attributes[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
@ -634,32 +618,19 @@ clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11,
GLX_DEPTH_SIZE, 1,
0
};
int offscreen_gl_attributes[] = {
GLX_RGBA,
GLX_USE_GL,
GLX_DEPTH_SIZE, 0,
GLX_ALPHA_SIZE, 0,
GLX_STENCIL_SIZE, 1,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
0
};
if (backend_x11->xdpy == None || backend_x11->xscreen == None)
return NULL;
CLUTTER_NOTE (BACKEND,
"Retrieving GL visual (for %s use), dpy: %p, xscreen; %p (%d)",
for_offscreen ? "offscreen" : "onscreen",
"Retrieving GL visual, dpy: %p, xscreen; %p (%d)",
backend_x11->xdpy,
backend_x11->xscreen,
backend_x11->xscreen_num);
xvisinfo = glXChooseVisual (backend_x11->xdpy,
backend_x11->xscreen_num,
for_offscreen ? offscreen_gl_attributes
: onscreen_gl_attributes);
attributes);
return xvisinfo;
}

View File

@ -61,40 +61,19 @@ static void
clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
gboolean was_offscreen;
/* Note unrealize should free up any backend stage related resources */
CLUTTER_NOTE (BACKEND, "Unrealizing stage");
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
clutter_x11_trap_x_errors ();
if (G_UNLIKELY (was_offscreen))
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
if (stage_glx->glxpixmap)
{
glXDestroyGLXPixmap (stage_x11->xdpy,stage_glx->glxpixmap);
stage_glx->glxpixmap = None;
}
if (stage_x11->xpixmap)
{
XFreePixmap (stage_x11->xdpy, stage_x11->xpixmap);
stage_x11->xpixmap = None;
}
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
{
if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
{
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
stage_x11->xwin = None;
}
else
stage_x11->xwin = None;
}
stage_x11->xwin = None;
if (stage_x11->xvisinfo != None)
{
@ -113,155 +92,98 @@ static gboolean
clutter_stage_glx_realize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
ClutterBackend *backend;
ClutterBackendGLX *backend_glx;
ClutterBackendX11 *backend_x11;
gboolean is_offscreen;
GError *error;
CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
G_OBJECT_TYPE_NAME (stage_window),
stage_window);
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
backend = clutter_get_default_backend ();
backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
if (G_LIKELY (!is_offscreen))
stage_x11->xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
if (stage_x11->xvisinfo == None)
{
GError *error;
g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
stage_x11->xvisinfo =
clutter_backend_x11_get_visual_info (backend_x11, FALSE);
if (stage_x11->xwin == None)
{
XSetWindowAttributes xattr;
unsigned long mask;
if (stage_x11->xvisinfo == None)
CLUTTER_NOTE (MISC, "Creating stage X window");
/* window attributes */
xattr.background_pixel = WhitePixel (stage_x11->xdpy,
stage_x11->xscreen);
xattr.border_pixel = 0;
xattr.colormap = XCreateColormap (stage_x11->xdpy,
stage_x11->xwin_root,
stage_x11->xvisinfo->visual,
AllocNone);
mask = CWBorderPixel | CWColormap;
stage_x11->xwin = XCreateWindow (stage_x11->xdpy,
stage_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0,
stage_x11->xvisinfo->depth,
InputOutput,
stage_x11->xvisinfo->visual,
mask, &xattr);
}
if (clutter_x11_has_event_retrieval())
{
if (clutter_x11_has_xinput())
{
g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
if (stage_x11->xwin == None)
{
XSetWindowAttributes xattr;
unsigned long mask;
CLUTTER_NOTE (MISC, "Creating stage X window");
/* window attributes */
xattr.background_pixel = WhitePixel (stage_x11->xdpy,
stage_x11->xscreen);
xattr.border_pixel = 0;
xattr.colormap = XCreateColormap (stage_x11->xdpy,
stage_x11->xwin_root,
stage_x11->xvisinfo->visual,
AllocNone);
mask = CWBorderPixel | CWColormap;
stage_x11->xwin = XCreateWindow (stage_x11->xdpy,
stage_x11->xwin_root,
0, 0,
stage_x11->xwin_width,
stage_x11->xwin_height,
0,
stage_x11->xvisinfo->depth,
InputOutput,
stage_x11->xvisinfo->visual,
mask, &xattr);
}
if (clutter_x11_has_event_retrieval())
{
if (clutter_x11_has_xinput())
{
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
KeyPressMask | KeyReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
KeyPressMask | KeyReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
#ifdef HAVE_XINPUT
_clutter_x11_select_events (stage_x11->xwin);
_clutter_x11_select_events (stage_x11->xwin);
#endif
}
else
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
PointerMotionMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
}
/* no user resize.. */
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
clutter_stage_x11_set_wm_protocols (stage_x11);
/* ask for a context; a no-op, if a context already exists */
error = NULL;
_clutter_backend_create_context (backend, FALSE, &error);
if (error)
{
g_critical ("Unable to realize stage: %s", error->message);
g_error_free (error);
return FALSE;
}
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
else
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
StructureNotifyMask |
FocusChangeMask |
ExposureMask |
PointerMotionMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask);
}
else
/* no user resize.. */
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
clutter_stage_x11_set_wm_protocols (stage_x11);
/* ask for a context; a no-op, if a context already exists */
error = NULL;
_clutter_backend_create_context (backend, &error);
if (error)
{
GError *error;
if (stage_x11->xvisinfo != None)
{
XFree (stage_x11->xvisinfo);
stage_x11->xvisinfo = None;
}
stage_x11->xvisinfo =
clutter_backend_x11_get_visual_info (backend_x11, TRUE);
if (stage_x11->xvisinfo == None)
{
g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy,
stage_x11->xwin_root,
stage_x11->xwin_width,
stage_x11->xwin_height,
DefaultDepth (stage_x11->xdpy,
stage_x11->xscreen));
stage_glx->glxpixmap = glXCreateGLXPixmap (stage_x11->xdpy,
stage_x11->xvisinfo,
stage_x11->xpixmap);
/* ask for a context; a no-op, if a context already exists
*
* FIXME: we probably need a seperate offscreen context here
* - though it likely makes most sense to drop offscreen stages
* and rely on FBO's instead and GLXPixmaps seems mostly broken
* anyway..
*/
error = NULL;
_clutter_backend_create_context (backend, TRUE, &error);
if (error)
{
g_critical ("Unable to realize stage: %s", error->message);
g_error_free (error);
return FALSE;
}
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
g_critical ("Unable to realize stage: %s", error->message);
g_error_free (error);
return FALSE;
}
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
/* chain up to the StageX11 implementation */
return clutter_stage_glx_parent_iface->realize (stage_window);
}

View File

@ -259,7 +259,6 @@ clutter_stage_osx_realize (ClutterActor *actor)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
ClutterBackendOSX *backend_osx;
gboolean offscreen;
CLUTTER_NOTE (BACKEND, "[%p] realize", self);
@ -268,15 +267,6 @@ clutter_stage_osx_realize (ClutterActor *actor)
CLUTTER_OSX_POOL_ALLOC();
g_object_get (self->wrapper, "offscreen", &offscreen, NULL);
if (offscreen)
{
g_warning("OSX Backend does not yet support offscreen rendering\n");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
backend_osx = CLUTTER_BACKEND_OSX (self->backend);
NSRect rect = NSMakeRect(0, 0, self->requisition_width, self->requisition_height);

View File

@ -54,42 +54,29 @@ static gboolean
clutter_stage_sdl_realize (ClutterStageWindow *stage_window)
{
ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (stage_window);
gboolean is_offscreen, is_fullscreen;
gboolean is_fullscreen = FALSE;
gint flags = SDL_OPENGL;
CLUTTER_NOTE (BACKEND, "Realizing main stage");
is_offscreen = is_fullscreen = FALSE;
g_object_get (stage_sdl->wrapper,
"offscreen", &is_offscreen,
"fullscreen-set", &is_fullscreen,
NULL);
if (G_LIKELY (!is_offscreen))
if (is_fullscreen)
flags |= SDL_FULLSCREEN;
SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
if (SDL_SetVideoMode (stage_sdl->win_width,
stage_sdl->win_height,
0, flags) == NULL)
{
gint flags = SDL_OPENGL;
if (is_fullscreen)
flags |= SDL_FULLSCREEN;
SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
if (SDL_SetVideoMode (stage_sdl->win_width,
stage_sdl->win_height,
0, flags) == NULL)
{
CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s",
SDL_GetError ());
return FALSE;
}
}
else
{
/* FIXME */
g_critical ("SDL Backend does not yet support offscreen rendering");
CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s",
SDL_GetError ());
return FALSE;
}

View File

@ -981,8 +981,7 @@ clutter_x11_has_composite_extension (void)
}
XVisualInfo *
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11,
gboolean for_offscreen)
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendX11Class *klass;
@ -990,7 +989,7 @@ clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11,
klass = CLUTTER_BACKEND_X11_GET_CLASS (backend_x11);
if (klass->get_visual_info)
return klass->get_visual_info (backend_x11, for_offscreen);
return klass->get_visual_info (backend_x11);
return NULL;
}

View File

@ -86,8 +86,7 @@ struct _ClutterBackendX11Class
{
ClutterBackendClass parent_class;
XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend,
gboolean for_offscreen);
XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend);
};
void _clutter_backend_x11_events_init (ClutterBackend *backend);
@ -119,8 +118,7 @@ ClutterFeatureFlags
clutter_backend_x11_get_features (ClutterBackend *backend);
XVisualInfo *
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11,
gboolean for_offscreen);
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11);
void
_clutter_x11_register_xinput (void);

View File

@ -714,12 +714,9 @@ clutter_x11_get_stage_visual (ClutterStage *stage)
{
ClutterStageWindow *impl;
ClutterStageX11 *stage_x11;
gboolean is_offscreen = FALSE;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
g_object_get (G_OBJECT (stage), "offscreen", &is_offscreen, NULL);
impl = _clutter_stage_get_window (stage);
g_assert (CLUTTER_IS_STAGE_X11 (impl));
@ -730,7 +727,7 @@ clutter_x11_get_stage_visual (ClutterStage *stage)
ClutterBackendX11 *backend_x11 = stage_x11->backend;
stage_x11->xvisinfo =
clutter_backend_x11_get_visual_info (backend_x11, is_offscreen);
clutter_backend_x11_get_visual_info (backend_x11);
}
return stage_x11->xvisinfo;