[mutter] compositor: Handle GL video memory purged errors



commit 7f6bcea3313b00580704258fb453b203a6b6b1a9
Author: Rui Matos <tiagomatos gmail com>
Date:   Fri May 20 19:22:23 2016 +0200

    compositor: Handle GL video memory purged errors
    
    Emit a signal so that interested parties can recreate their FBOs and
    queue a full scene graph redraw to ensure we don't end up showing
    graphical artifacts.
    
    This relies on the GL driver supporting the
    NV_robustness_video_memory_purge extension and cogl creating a
    suitable GL context. For now we only make use of it with the X backend
    since the only driver with which this is useful is NVIDIA.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=739178

 src/backends/x11/meta-backend-x11.c |    2 ++
 src/compositor/compositor-private.h |    1 +
 src/compositor/compositor.c         |   28 ++++++++++++++++++++++++++--
 src/core/display.c                  |    9 +++++++++
 4 files changed, 38 insertions(+), 2 deletions(-)
---
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index a645bbd..0890996 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -884,6 +884,8 @@ meta_backend_x11_init (MetaBackendX11 *x11)
 {
   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 
+  clutter_x11_request_reset_on_video_memory_purge ();
+
   /* We do X11 event retrieval ourselves */
   clutter_x11_disable_event_retrieval ();
 
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 65fcec2..c534926 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -31,6 +31,7 @@ struct _MetaCompositor
 
   CoglOnscreen          *onscreen;
   CoglFrameClosure      *frame_closure;
+  CoglContext           *context;
 
   /* Used for unredirecting fullscreen windows */
   guint                  disable_unredirect_count;
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 30504ac..b2f4f93 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1021,8 +1021,7 @@ frame_callback (CoglOnscreen  *onscreen,
            * is fairly fast, so calling it twice and subtracting to get a
            * nearly-zero number is acceptable, if a litle ugly.
            */
-          CoglContext *context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (onscreen));
-          gint64 current_cogl_time = cogl_get_clock_time (context);
+          gint64 current_cogl_time = cogl_get_clock_time (compositor->context);
           gint64 current_monotonic_time = g_get_monotonic_time ();
 
           presentation_time =
@@ -1052,6 +1051,7 @@ meta_pre_paint_func (gpointer data)
                                                                     frame_callback,
                                                                     compositor,
                                                                     NULL);
+      compositor->context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (compositor->onscreen));
     }
 
   if (compositor->windows == NULL)
@@ -1105,6 +1105,7 @@ static gboolean
 meta_post_paint_func (gpointer data)
 {
   MetaCompositor *compositor = data;
+  CoglGraphicsResetStatus status;
 
   if (compositor->frame_has_updated_xsurfaces)
     {
@@ -1114,6 +1115,29 @@ meta_post_paint_func (gpointer data)
       compositor->frame_has_updated_xsurfaces = FALSE;
     }
 
+  status = cogl_get_graphics_reset_status (compositor->context);
+  switch (status)
+    {
+    case COGL_GRAPHICS_RESET_STATUS_NO_ERROR:
+      break;
+
+    case COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET:
+      g_signal_emit_by_name (compositor->display, "gl-video-memory-purged");
+      clutter_actor_queue_redraw (CLUTTER_ACTOR (compositor->stage));
+      break;
+
+    default:
+      /* The ARB_robustness spec says that, on error, the application
+         should destroy the old context and create a new one. Since we
+         don't have the necessary plumbing to do this we'll simply
+         restart the process. Obviously we can't do this when we are
+         a wayland compositor but in that case we shouldn't get here
+         since we don't enable robustness in that case. */
+      g_assert (!meta_is_wayland_compositor ());
+      meta_restart (NULL);
+      break;
+    }
+
   return TRUE;
 }
 
diff --git a/src/core/display.c b/src/core/display.c
index 4c7a00e..a0a4b36 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -125,6 +125,7 @@ enum
   SHOW_RESTART_MESSAGE,
   RESTART,
   SHOW_RESIZE_POPUP,
+  GL_VIDEO_MEMORY_PURGED,
   LAST_SIGNAL
 };
 
@@ -342,6 +343,14 @@ meta_display_class_init (MetaDisplayClass *klass)
                   G_TYPE_BOOLEAN, 4,
                   G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT);
 
+  display_signals[GL_VIDEO_MEMORY_PURGED] =
+    g_signal_new ("gl-video-memory-purged",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   g_object_class_install_property (object_class,
                                    PROP_FOCUS_WINDOW,
                                    g_param_spec_object ("focus-window",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]