Delay default stage creation

The default stage creation should be delayed as much as possible,
ideally at the end of the init() process.
This commit is contained in:
Emmanuele Bassi 2009-12-03 17:13:44 +00:00
parent 3191ea1195
commit 6fbed66add
6 changed files with 126 additions and 61 deletions

View File

@ -425,6 +425,14 @@ _clutter_backend_get_features (ClutterBackend *backend)
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0); g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0);
klass = CLUTTER_BACKEND_GET_CLASS (backend); klass = CLUTTER_BACKEND_GET_CLASS (backend);
/* we need to have a context here; so we create the
* GL context first and the ask for features. if the
* context already exists this should be a no-op
*/
if (klass->create_context)
klass->create_context (backend, NULL);
if (klass->get_features) if (klass->get_features)
return klass->get_features (backend); return klass->get_features (backend);

View File

@ -1505,40 +1505,9 @@ 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;
/* Stage will give us a GL Context etc */ /* this will create the GL context and query it for features and
stage = clutter_stage_get_default (); * state setup
if (!stage) */
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to create the default stage");
else
g_critical ("Unable to create the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the default stage");
else
g_critical ("Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
/* Now we can safely assume we have a valid GL context and can
* start issueing cogl commands
*/
/* - will call to backend and cogl */
_clutter_feature_init (); _clutter_feature_init ();
#ifdef CLUTTER_ENABLE_PROFILE #ifdef CLUTTER_ENABLE_PROFILE
@ -1587,6 +1556,36 @@ clutter_init_real (GError **error)
/* Initiate event collection */ /* Initiate event collection */
_clutter_backend_init_events (ctx->backend); _clutter_backend_init_events (ctx->backend);
/* Create the default stage and realize it */
stage = clutter_stage_get_default ();
if (!stage)
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to create the default stage");
else
g_critical ("Unable to create the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the default stage");
else
g_critical ("Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_is_initialized = TRUE; clutter_is_initialized = TRUE;
ctx->is_initialized = TRUE; ctx->is_initialized = TRUE;

View File

@ -332,8 +332,8 @@ clutter_stage_realize (ClutterActor *self)
*/ */
if (is_realized) if (is_realized)
{ {
GError *error = NULL;
ClutterBackend *backend = clutter_get_default_backend (); ClutterBackend *backend = clutter_get_default_backend ();
GError *error = NULL;
/* We want to select the context without calling /* We want to select the context without calling
clutter_backend_ensure_context so that it doesn't call any clutter_backend_ensure_context so that it doesn't call any
@ -345,8 +345,8 @@ clutter_stage_realize (ClutterActor *self)
/* Make sure Cogl can support the driver */ /* Make sure Cogl can support the driver */
if (!_cogl_check_driver_valid (&error)) if (!_cogl_check_driver_valid (&error))
{ {
g_warning ("The GL driver is not supported: %s", g_critical ("The GL driver is not supported: %s",
error->message); error->message);
g_clear_error (&error); g_clear_error (&error);
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
} }

View File

@ -164,6 +164,9 @@ batch_and_call (CoglJournalEntry *entries,
int batch_len = 1; int batch_len = 1;
CoglJournalEntry *batch_start = entries; CoglJournalEntry *batch_start = entries;
if (n_entries < 1)
return;
for (i = 1; i < n_entries; i++) for (i = 1; i < n_entries; i++)
{ {
CoglJournalEntry *entry0 = &entries[i - 1]; CoglJournalEntry *entry0 = &entries[i - 1];

View File

@ -230,24 +230,67 @@ check_vblank_env (const char *name)
static ClutterFeatureFlags 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);
const gchar *glx_extensions = NULL; ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
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 and /* this will make sure that the GL context exists */
* it's bound to a drawable
*/
g_assert (backend_glx->gl_context != None); g_assert (backend_glx->gl_context != None);
g_assert (glXGetCurrentDrawable () != None);
CLUTTER_NOTE (BACKEND, "Checking features\n" /* in order to query the GL and GLX implementation we
"GL_VENDOR: %s\n" * need to bind the GLX context to a Drawable; we create
"GL_RENDERER: %s\n" * a simple, off-screen override-redirect window that we
"GL_VERSION: %s\n" * then destroy at the end of this function
"GL_EXTENSIONS: %s\n", */
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,
"Checking features\n"
" GL_VENDOR: %s\n"
" GL_RENDERER: %s\n"
" GL_VERSION: %s\n"
" GL_EXTENSIONS: %s\n",
glGetString (GL_VENDOR), glGetString (GL_VENDOR),
glGetString (GL_RENDERER), glGetString (GL_RENDERER),
glGetString (GL_VERSION), glGetString (GL_VERSION),
@ -260,7 +303,7 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions); CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions);
/* First check for explicit disabling or it set elsewhere (eg NVIDIA) */ /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none")) if (getenv ("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none"))
{ {
CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request"); CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request");
} }
@ -277,7 +320,7 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
* How well glXGetVideoSyncSGI works with other driver (ATI etc) needs * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
* to be investigated. glXGetVideoSyncSGI on ATI at least seems to have * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
* no effect. * no effect.
*/ */
if (!check_vblank_env ("dri") && if (!check_vblank_env ("dri") &&
cogl_check_extension ("GLX_SGI_swap_control", glx_extensions)) cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
{ {
@ -325,10 +368,11 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed"); CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
} }
#ifdef __linux__ #ifdef __linux__
/* /*
* DRI is really an extreme fallback -rumoured to work with Via chipsets * DRI is really an extreme fallback -rumoured to work with Via chipsets
*/ */
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
{ {
CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup"); CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");
@ -344,14 +388,19 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
CLUTTER_NOTE (BACKEND, "DRI vblank setup failed"); CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
} }
#endif #endif
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
{ CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
CLUTTER_NOTE (BACKEND,
"no use-able vblank mechanism found");
}
} }
CLUTTER_NOTE (MISC, "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;
} }
@ -542,15 +591,16 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
g_assert (impl != NULL); g_assert (impl != NULL);
CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
g_type_name (G_OBJECT_TYPE (impl)),
impl);
stage_glx = CLUTTER_STAGE_GLX (impl); stage_glx = CLUTTER_STAGE_GLX (impl);
stage_x11 = CLUTTER_STAGE_X11 (impl); stage_x11 = CLUTTER_STAGE_X11 (impl);
backend_glx = CLUTTER_BACKEND_GLX (backend); backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend); backend_x11 = CLUTTER_BACKEND_X11 (backend);
CLUTTER_NOTE (BACKEND,
"Setting context for stage of type %s, window: 0x%x",
G_OBJECT_TYPE_NAME (impl),
(int) stage_x11->xwin);
/* no GL context to set */ /* no GL context to set */
if (backend_glx->gl_context == None) if (backend_glx->gl_context == None)
return; return;
@ -562,7 +612,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
*/ */
if (stage_x11->xwin == None) if (stage_x11->xwin == None)
{ {
CLUTTER_NOTE (MULTISTAGE, CLUTTER_NOTE (BACKEND,
"Received a stale stage, clearing all context"); "Received a stale stage, clearing all context");
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL); glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);

View File

@ -135,6 +135,11 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
InputOutput, InputOutput,
xvisinfo->visual, xvisinfo->visual,
mask, &xattr); mask, &xattr);
CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x",
stage_window,
(unsigned int) stage_x11->xwin);
XFree (xvisinfo); XFree (xvisinfo);
} }