diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index 54c7fa963..7a2170fe7 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -425,6 +425,14 @@ _clutter_backend_get_features (ClutterBackend *backend) g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0); 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) return klass->get_features (backend); diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index b73a9a6e8..c1401085a 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -1505,40 +1505,9 @@ clutter_init_real (GError **error) if (!_clutter_backend_post_parse (backend, error)) return CLUTTER_INIT_ERROR_BACKEND; - /* Stage will give us a GL Context etc */ - 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; - } - - /* Now we can safely assume we have a valid GL context and can - * start issueing cogl commands - */ - /* - will call to backend and cogl */ + /* this will create the GL context and query it for features and + * state setup + */ _clutter_feature_init (); #ifdef CLUTTER_ENABLE_PROFILE @@ -1587,6 +1556,36 @@ clutter_init_real (GError **error) /* Initiate event collection */ _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; ctx->is_initialized = TRUE; diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index a9f9b938f..d9764113a 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -332,8 +332,8 @@ clutter_stage_realize (ClutterActor *self) */ if (is_realized) { - GError *error = NULL; ClutterBackend *backend = clutter_get_default_backend (); + GError *error = NULL; /* We want to select the context without calling 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 */ if (!_cogl_check_driver_valid (&error)) { - g_warning ("The GL driver is not supported: %s", - error->message); + g_critical ("The GL driver is not supported: %s", + error->message); g_clear_error (&error); CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); } diff --git a/clutter/cogl/cogl/cogl-journal.c b/clutter/cogl/cogl/cogl-journal.c index 96fe3e5c7..0d8b09173 100644 --- a/clutter/cogl/cogl/cogl-journal.c +++ b/clutter/cogl/cogl/cogl-journal.c @@ -164,6 +164,9 @@ batch_and_call (CoglJournalEntry *entries, int batch_len = 1; CoglJournalEntry *batch_start = entries; + if (n_entries < 1) + return; + for (i = 1; i < n_entries; i++) { CoglJournalEntry *entry0 = &entries[i - 1]; diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c index 7d8d417b9..05ff61ca1 100644 --- a/clutter/glx/clutter-backend-glx.c +++ b/clutter/glx/clutter-backend-glx.c @@ -230,24 +230,67 @@ check_vblank_env (const char *name) static ClutterFeatureFlags clutter_backend_glx_get_features (ClutterBackend *backend) { - ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); - const gchar *glx_extensions = NULL; + 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 and - * it's bound to a drawable - */ + /* this will make sure that the GL context exists */ g_assert (backend_glx->gl_context != None); - g_assert (glXGetCurrentDrawable () != None); - CLUTTER_NOTE (BACKEND, "Checking features\n" - "GL_VENDOR: %s\n" - "GL_RENDERER: %s\n" - "GL_VERSION: %s\n" - "GL_EXTENSIONS: %s\n", + /* 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, + "Checking features\n" + " GL_VENDOR: %s\n" + " GL_RENDERER: %s\n" + " GL_VERSION: %s\n" + " GL_EXTENSIONS: %s\n", glGetString (GL_VENDOR), glGetString (GL_RENDERER), glGetString (GL_VERSION), @@ -260,7 +303,7 @@ clutter_backend_glx_get_features (ClutterBackend *backend) CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions); /* 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"); } @@ -277,7 +320,7 @@ clutter_backend_glx_get_features (ClutterBackend *backend) * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have * no effect. - */ + */ if (!check_vblank_env ("dri") && 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)) CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed"); } + #ifdef __linux__ /* * DRI is really an extreme fallback -rumoured to work with Via chipsets - */ + */ if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) { 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"); } #endif + 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; } @@ -542,15 +591,16 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend, 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_x11 = CLUTTER_STAGE_X11 (impl); backend_glx = CLUTTER_BACKEND_GLX (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 */ if (backend_glx->gl_context == None) return; @@ -562,7 +612,7 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend, */ if (stage_x11->xwin == None) { - CLUTTER_NOTE (MULTISTAGE, + CLUTTER_NOTE (BACKEND, "Received a stale stage, clearing all context"); glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL); diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index f770c88d3..a99d5f645 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -135,6 +135,11 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window) InputOutput, xvisinfo->visual, mask, &xattr); + + CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x", + stage_window, + (unsigned int) stage_x11->xwin); + XFree (xvisinfo); }