Delay default stage creation
authorEmmanuele Bassi <ebassi@linux.intel.com>
Thu, 3 Dec 2009 17:13:44 +0000 (17:13 +0000)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 3 Feb 2010 16:34:27 +0000 (16:34 +0000)
The default stage creation should be delayed as much as possible,
ideally at the end of the init() process.

clutter/clutter-backend.c
clutter/clutter-main.c
clutter/clutter-stage.c
clutter/cogl/cogl/cogl-journal.c
clutter/glx/clutter-backend-glx.c
clutter/glx/clutter-stage-glx.c

index 54c7fa9..7a2170f 100644 (file)
@@ -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);
   
index b73a9a6..c140108 100644 (file)
@@ -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;
 
index a9f9b93..d976411 100644 (file)
@@ -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);
         }
index 96fe3e5..0d8b091 100644 (file)
@@ -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];
index 7d8d417..05ff61c 100644 (file)
@@ -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);
index f770c88..a99d5f6 100644 (file)
@@ -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);
     }