1725f0
From e42c4e83283787062fb446a2aa698f227fe2db5f Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 29 Apr 2020 16:26:52 +0200
1725f0
Subject: [PATCH 01/20] cogl/dma-buf-handle: Pass more metadata to handle
1725f0
 constructor
1725f0
1725f0
Could be useful would one want to mmap the dmabuf and deal with its
1725f0
content manually in CPU space.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit e656d0caf01d8b012d2b458676e5658c540525dc)
1725f0
---
1725f0
 cogl/cogl/cogl-dma-buf-handle.c            | 45 +++++++++++++++++++++
1725f0
 cogl/cogl/cogl-dma-buf-handle.h            | 46 +++++++++++++++++++++-
1725f0
 src/backends/native/meta-renderer-native.c | 14 +++++--
1725f0
 3 files changed, 101 insertions(+), 4 deletions(-)
1725f0
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.c b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
index 4a8f709f2c..d8b4e57c55 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.c
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
@@ -40,6 +40,11 @@ struct _CoglDmaBufHandle
1725f0
 {
1725f0
   CoglFramebuffer *framebuffer;
1725f0
   int dmabuf_fd;
1725f0
+  int width;
1725f0
+  int height;
1725f0
+  int stride;
1725f0
+  int offset;
1725f0
+  int bpp;
1725f0
   gpointer user_data;
1725f0
   GDestroyNotify destroy_func;
1725f0
 };
1725f0
@@ -47,6 +52,11 @@ struct _CoglDmaBufHandle
1725f0
 CoglDmaBufHandle *
1725f0
 cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
1725f0
                          int              dmabuf_fd,
1725f0
+                         int              width,
1725f0
+                         int              height,
1725f0
+                         int              stride,
1725f0
+                         int              offset,
1725f0
+                         int              bpp,
1725f0
                          gpointer         user_data,
1725f0
                          GDestroyNotify   destroy_func)
1725f0
 {
1725f0
@@ -61,6 +71,12 @@ cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
1725f0
   dmabuf_handle->user_data = user_data;
1725f0
   dmabuf_handle->destroy_func = destroy_func;
1725f0
 
1725f0
+  dmabuf_handle->width = width;
1725f0
+  dmabuf_handle->height = height;
1725f0
+  dmabuf_handle->stride = stride;
1725f0
+  dmabuf_handle->offset = offset;
1725f0
+  dmabuf_handle->bpp = bpp;
1725f0
+
1725f0
   return dmabuf_handle;
1725f0
 }
1725f0
 
1725f0
@@ -92,3 +108,32 @@ cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle)
1725f0
   return dmabuf_handle->dmabuf_fd;
1725f0
 }
1725f0
 
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_width (CoglDmaBufHandle *dmabuf_handle)
1725f0
+{
1725f0
+  return dmabuf_handle->width;
1725f0
+}
1725f0
+
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_height (CoglDmaBufHandle *dmabuf_handle)
1725f0
+{
1725f0
+  return dmabuf_handle->height;
1725f0
+}
1725f0
+
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_stride (CoglDmaBufHandle *dmabuf_handle)
1725f0
+{
1725f0
+  return dmabuf_handle->stride;
1725f0
+}
1725f0
+
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_offset (CoglDmaBufHandle *dmabuf_handle)
1725f0
+{
1725f0
+  return dmabuf_handle->offset;
1725f0
+}
1725f0
+
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_bpp (CoglDmaBufHandle *dmabuf_handle)
1725f0
+{
1725f0
+  return dmabuf_handle->bpp;
1725f0
+}
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.h b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
index 25b9b0ccb5..f64a20678d 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.h
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
@@ -46,7 +46,12 @@
1725f0
 CoglDmaBufHandle *
1725f0
 cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
1725f0
                          int              dmabuf_fd,
1725f0
-                         gpointer         data,
1725f0
+                         int              width,
1725f0
+                         int              height,
1725f0
+                         int              stride,
1725f0
+                         int              offset,
1725f0
+                         int              bpp,
1725f0
+                         gpointer         user_data,
1725f0
                          GDestroyNotify   destroy_func);
1725f0
 
1725f0
 /**
1725f0
@@ -79,5 +84,44 @@ cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle);
1725f0
 int
1725f0
 cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle);
1725f0
 
1725f0
+/**
1725f0
+ * cogl_dmabuf_handle_get_width: (skip)
1725f0
+ *
1725f0
+ * Returns: the buffer width
1725f0
+ */
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_width (CoglDmaBufHandle *dmabuf_handle);
1725f0
+
1725f0
+/**
1725f0
+ * cogl_dmabuf_handle_get_height: (skip)
1725f0
+ *
1725f0
+ * Returns: the buffer height
1725f0
+ */
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_height (CoglDmaBufHandle *dmabuf_handle);
1725f0
+
1725f0
+/**
1725f0
+ * cogl_dmabuf_handle_get_stride: (skip)
1725f0
+ *
1725f0
+ * Returns: the buffer stride
1725f0
+ */
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_stride (CoglDmaBufHandle *dmabuf_handle);
1725f0
+
1725f0
+/**
1725f0
+ * cogl_dmabuf_handle_get_offset: (skip)
1725f0
+ *
1725f0
+ * Returns: the buffer offset
1725f0
+ */
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_offset (CoglDmaBufHandle *dmabuf_handle);
1725f0
+
1725f0
+/**
1725f0
+ * cogl_dmabuf_handle_get_bpp: (skip)
1725f0
+ *
1725f0
+ * Returns: the number of bytes per pixel
1725f0
+ */
1725f0
+int
1725f0
+cogl_dma_buf_handle_get_bpp (CoglDmaBufHandle *dmabuf_handle);
1725f0
 
1725f0
 #endif /* __COGL_DMA_BUF_HANDLE_H__ */
1725f0
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
1725f0
index 25833b6cf6..c14cb5acda 100644
1725f0
--- a/src/backends/native/meta-renderer-native.c
1725f0
+++ b/src/backends/native/meta-renderer-native.c
1725f0
@@ -2641,6 +2641,9 @@ meta_renderer_native_create_dma_buf (CoglRenderer  *cogl_renderer,
1725f0
         CoglFramebuffer *dmabuf_fb;
1725f0
         CoglDmaBufHandle *dmabuf_handle;
1725f0
         struct gbm_bo *new_bo;
1725f0
+        int stride;
1725f0
+        int offset;
1725f0
+        int bpp;
1725f0
         int dmabuf_fd = -1;
1725f0
 
1725f0
         new_bo = gbm_bo_create (renderer_gpu_data->gbm.device,
1725f0
@@ -2664,11 +2667,14 @@ meta_renderer_native_create_dma_buf (CoglRenderer  *cogl_renderer,
1725f0
             return NULL;
1725f0
           }
1725f0
 
1725f0
+        stride = gbm_bo_get_stride (new_bo);
1725f0
+        offset = gbm_bo_get_offset (new_bo, 0);
1725f0
+        bpp = 4;
1725f0
         dmabuf_fb = create_dma_buf_framebuffer (renderer_native,
1725f0
                                                 dmabuf_fd,
1725f0
                                                 width, height,
1725f0
-                                                gbm_bo_get_stride (new_bo),
1725f0
-                                                gbm_bo_get_offset (new_bo, 0),
1725f0
+                                                stride,
1725f0
+                                                offset,
1725f0
                                                 DRM_FORMAT_MOD_LINEAR,
1725f0
                                                 DRM_FORMAT_XRGB8888,
1725f0
                                                 error);
1725f0
@@ -2677,7 +2683,9 @@ meta_renderer_native_create_dma_buf (CoglRenderer  *cogl_renderer,
1725f0
           return NULL;
1725f0
 
1725f0
         dmabuf_handle =
1725f0
-          cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
1725f0
+          cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd,
1725f0
+                                   width, height, stride, offset, bpp,
1725f0
+                                   new_bo,
1725f0
                                    (GDestroyNotify) gbm_bo_destroy);
1725f0
         cogl_object_unref (dmabuf_fb);
1725f0
         return dmabuf_handle;
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 2270f6dcf7b1e70386f5b4242f92bf5735bb88ba Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Thu, 30 Apr 2020 10:42:30 +0200
1725f0
Subject: [PATCH 02/20] clutter/stage-view: Add name property
1725f0
1725f0
Will be used for logging to identify what view a log entry concerns. For
1725f0
the native and nested backend this is the name of the output the CRTC is
1725f0
assigned to drive; for X11 it's just "X11 screen", and for the legacy
1725f0
"X11 screen" emulation mode of the nested backend it's called "legacy
1725f0
nested".
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit c86367199febdee10ecd7ba24c69b6dda52cb896)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c           | 18 ++++++++++++++++++
1725f0
 src/backends/native/meta-renderer-native.c     |  3 +++
1725f0
 .../x11/nested/meta-renderer-x11-nested.c      |  4 ++++
1725f0
 3 files changed, 25 insertions(+)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 0fad6fc446..6b543b5d51 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -27,6 +27,7 @@ enum
1725f0
 {
1725f0
   PROP_0,
1725f0
 
1725f0
+  PROP_NAME,
1725f0
   PROP_LAYOUT,
1725f0
   PROP_FRAMEBUFFER,
1725f0
   PROP_OFFSCREEN,
1725f0
@@ -40,6 +41,8 @@ static GParamSpec *obj_props[PROP_LAST];
1725f0
 
1725f0
 typedef struct _ClutterStageViewPrivate
1725f0
 {
1725f0
+  char *name;
1725f0
+
1725f0
   cairo_rectangle_int_t layout;
1725f0
   float scale;
1725f0
   CoglFramebuffer *framebuffer;
1725f0
@@ -339,6 +342,9 @@ clutter_stage_view_get_property (GObject    *object,
1725f0
 
1725f0
   switch (prop_id)
1725f0
     {
1725f0
+    case PROP_NAME:
1725f0
+      g_value_set_string (value, priv->name);
1725f0
+      break;
1725f0
     case PROP_LAYOUT:
1725f0
       g_value_set_boxed (value, &priv->layout);
1725f0
       break;
1725f0
@@ -372,6 +378,9 @@ clutter_stage_view_set_property (GObject      *object,
1725f0
 
1725f0
   switch (prop_id)
1725f0
     {
1725f0
+    case PROP_NAME:
1725f0
+      priv->name = g_value_dup_string (value);
1725f0
+      break;
1725f0
     case PROP_LAYOUT:
1725f0
       layout = g_value_get_boxed (value);
1725f0
       priv->layout = *layout;
1725f0
@@ -414,6 +423,7 @@ clutter_stage_view_dispose (GObject *object)
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
 
1725f0
+  g_clear_pointer (&priv->name, g_free);
1725f0
   g_clear_pointer (&priv->framebuffer, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->shadowfb, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen, cogl_object_unref);
1725f0
@@ -446,6 +456,14 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
1725f0
   object_class->set_property = clutter_stage_view_set_property;
1725f0
   object_class->dispose = clutter_stage_view_dispose;
1725f0
 
1725f0
+  obj_props[PROP_NAME] =
1725f0
+    g_param_spec_string ("name",
1725f0
+                         "Name",
1725f0
+                         "Name of view",
1725f0
+                         NULL,
1725f0
+                         G_PARAM_READWRITE |
1725f0
+                         G_PARAM_CONSTRUCT_ONLY |
1725f0
+                         G_PARAM_STATIC_STRINGS);
1725f0
   obj_props[PROP_LAYOUT] =
1725f0
     g_param_spec_boxed ("layout",
1725f0
                         "View layout",
1725f0
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
1725f0
index c14cb5acda..d3fb5b3c55 100644
1725f0
--- a/src/backends/native/meta-renderer-native.c
1725f0
+++ b/src/backends/native/meta-renderer-native.c
1725f0
@@ -3679,6 +3679,7 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
1725f0
   CoglContext *cogl_context =
1725f0
     cogl_context_from_renderer_native (renderer_native);
1725f0
   CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
1725f0
+  MetaMonitor *monitor;
1725f0
   CoglDisplayEGL *cogl_display_egl;
1725f0
   CoglOnscreenEGL *onscreen_egl;
1725f0
   MetaMonitorTransform view_transform;
1725f0
@@ -3742,7 +3743,9 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
1725f0
         g_error ("Failed to allocate shadow buffer texture: %s", error->message);
1725f0
     }
1725f0
 
1725f0
+  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
1725f0
   view = g_object_new (META_TYPE_RENDERER_VIEW,
1725f0
+                       "name", meta_monitor_get_connector (monitor),
1725f0
                        "layout", &logical_monitor->rect,
1725f0
                        "scale", scale,
1725f0
                        "framebuffer", onscreen,
1725f0
diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c
1725f0
index 5000bf3579..f3a5547dbb 100644
1725f0
--- a/src/backends/x11/nested/meta-renderer-x11-nested.c
1725f0
+++ b/src/backends/x11/nested/meta-renderer-x11-nested.c
1725f0
@@ -163,6 +163,7 @@ meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11
1725f0
     .height = height
1725f0
   };
1725f0
   legacy_view = g_object_new (META_TYPE_RENDERER_VIEW,
1725f0
+                              "name", "legacy nested",
1725f0
                               "layout", &view_layout,
1725f0
                               "framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
1725f0
                               NULL);
1725f0
@@ -179,6 +180,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
1725f0
     meta_backend_get_monitor_manager (backend);
1725f0
   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
1725f0
   CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
1725f0
+  MetaMonitor *monitor;
1725f0
   MetaMonitorTransform view_transform;
1725f0
   float view_scale;
1725f0
   int width, height;
1725f0
@@ -212,7 +214,9 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
1725f0
   else
1725f0
     offscreen = NULL;
1725f0
 
1725f0
+  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
1725f0
   return g_object_new (META_TYPE_RENDERER_VIEW,
1725f0
+                       "name", meta_monitor_get_connector (monitor),
1725f0
                        "layout", &logical_monitor->rect,
1725f0
                        "framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
1725f0
                        "offscreen", COGL_FRAMEBUFFER (offscreen),
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 6716fde14c5b1a00a02a80b46db67d3f236a87c1 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Thu, 30 Apr 2020 17:53:30 +0200
1725f0
Subject: [PATCH 03/20] renderer-native: Move shadow fb construction to the
1725f0
 stage view
1725f0
1725f0
The stage view will need a more involved approach to shadow buffers, in
1725f0
order to implement things such double buffered shadow buffers and damage
1725f0
detection.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 3ab89be574f0e02dc67e1b1f538bb24f94612bcf)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c       | 115 ++++++++++++++++++---
1725f0
 src/backends/native/meta-renderer-native.c |  25 +----
1725f0
 2 files changed, 106 insertions(+), 34 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 6b543b5d51..db0067297c 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -31,7 +31,7 @@ enum
1725f0
   PROP_LAYOUT,
1725f0
   PROP_FRAMEBUFFER,
1725f0
   PROP_OFFSCREEN,
1725f0
-  PROP_SHADOWFB,
1725f0
+  PROP_USE_SHADOWFB,
1725f0
   PROP_SCALE,
1725f0
 
1725f0
   PROP_LAST
1725f0
@@ -50,6 +50,7 @@ typedef struct _ClutterStageViewPrivate
1725f0
   CoglOffscreen *offscreen;
1725f0
   CoglPipeline *offscreen_pipeline;
1725f0
 
1725f0
+  gboolean use_shadowfb;
1725f0
   CoglOffscreen *shadowfb;
1725f0
   CoglPipeline *shadowfb_pipeline;
1725f0
 
1725f0
@@ -206,6 +207,80 @@ clutter_stage_view_copy_to_framebuffer (ClutterStageView            *view,
1725f0
   cogl_framebuffer_pop_matrix (dst_framebuffer);
1725f0
 }
1725f0
 
1725f0
+static CoglOffscreen *
1725f0
+create_offscreen_framebuffer (CoglContext  *context,
1725f0
+                              int           width,
1725f0
+                              int           height,
1725f0
+                              GError      **error)
1725f0
+{
1725f0
+  CoglOffscreen *framebuffer;
1725f0
+  CoglTexture2D *texture;
1725f0
+
1725f0
+  texture = cogl_texture_2d_new_with_size (context, width, height);
1725f0
+  cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
1725f0
+                                          FALSE);
1725f0
+
1725f0
+  if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
1725f0
+    {
1725f0
+      cogl_object_unref (texture);
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  framebuffer = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
1725f0
+  cogl_object_unref (texture);
1725f0
+  if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (framebuffer), error))
1725f0
+    {
1725f0
+      cogl_object_unref (framebuffer);
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  return framebuffer;
1725f0
+}
1725f0
+
1725f0
+static gboolean
1725f0
+init_offscreen_shadowfb (ClutterStageView  *view,
1725f0
+                         CoglContext       *cogl_context,
1725f0
+                         int                width,
1725f0
+                         int                height,
1725f0
+                         GError           **error)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  CoglOffscreen *offscreen;
1725f0
+
1725f0
+  offscreen = create_offscreen_framebuffer (cogl_context, width, height, error);
1725f0
+  if (!offscreen)
1725f0
+    return FALSE;
1725f0
+
1725f0
+  priv->shadowfb = offscreen;
1725f0
+  return TRUE;
1725f0
+}
1725f0
+
1725f0
+static void
1725f0
+init_shadowfb (ClutterStageView *view)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  g_autoptr (GError) error = NULL;
1725f0
+  int width;
1725f0
+  int height;
1725f0
+  CoglContext *cogl_context;
1725f0
+
1725f0
+  width = cogl_framebuffer_get_width (priv->framebuffer);
1725f0
+  height = cogl_framebuffer_get_height (priv->framebuffer);
1725f0
+  cogl_context = cogl_framebuffer_get_context (priv->framebuffer);
1725f0
+
1725f0
+  if (!init_offscreen_shadowfb (view, cogl_context, width, height, &error))
1725f0
+    {
1725f0
+      g_warning ("Failed to initialize single buffered shadow fb for %s: %s",
1725f0
+                 priv->name, error->message);
1725f0
+    }
1725f0
+  else
1725f0
+    {
1725f0
+      g_message ("Initialized single buffered shadow fb for %s", priv->name);
1725f0
+    }
1725f0
+}
1725f0
+
1725f0
 void
1725f0
 clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
                                    const cairo_rectangle_int_t *rect)
1725f0
@@ -354,8 +429,8 @@ clutter_stage_view_get_property (GObject    *object,
1725f0
     case PROP_OFFSCREEN:
1725f0
       g_value_set_boxed (value, priv->offscreen);
1725f0
       break;
1725f0
-    case PROP_SHADOWFB:
1725f0
-      g_value_set_boxed (value, priv->shadowfb);
1725f0
+    case PROP_USE_SHADOWFB:
1725f0
+      g_value_set_boolean (value, priv->use_shadowfb);
1725f0
       break;
1725f0
     case PROP_SCALE:
1725f0
       g_value_set_float (value, priv->scale);
1725f0
@@ -405,8 +480,8 @@ clutter_stage_view_set_property (GObject      *object,
1725f0
     case PROP_OFFSCREEN:
1725f0
       priv->offscreen = g_value_dup_boxed (value);
1725f0
       break;
1725f0
-    case PROP_SHADOWFB:
1725f0
-      priv->shadowfb = g_value_dup_boxed (value);
1725f0
+    case PROP_USE_SHADOWFB:
1725f0
+      priv->use_shadowfb = g_value_get_boolean (value);
1725f0
       break;
1725f0
     case PROP_SCALE:
1725f0
       priv->scale = g_value_get_float (value);
1725f0
@@ -416,6 +491,19 @@ clutter_stage_view_set_property (GObject      *object,
1725f0
     }
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+clutter_stage_view_constructed (GObject *object)
1725f0
+{
1725f0
+  ClutterStageView *view = CLUTTER_STAGE_VIEW (object);
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+
1725f0
+  if (priv->use_shadowfb)
1725f0
+    init_shadowfb (view);
1725f0
+
1725f0
+  G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object);
1725f0
+}
1725f0
+
1725f0
 static void
1725f0
 clutter_stage_view_dispose (GObject *object)
1725f0
 {
1725f0
@@ -454,6 +542,7 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
1725f0
 
1725f0
   object_class->get_property = clutter_stage_view_get_property;
1725f0
   object_class->set_property = clutter_stage_view_set_property;
1725f0
+  object_class->constructed = clutter_stage_view_constructed;
1725f0
   object_class->dispose = clutter_stage_view_dispose;
1725f0
 
1725f0
   obj_props[PROP_NAME] =
1725f0
@@ -491,14 +580,14 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
1725f0
                         G_PARAM_CONSTRUCT_ONLY |
1725f0
                         G_PARAM_STATIC_STRINGS);
1725f0
 
1725f0
-  obj_props[PROP_SHADOWFB] =
1725f0
-    g_param_spec_boxed ("shadowfb",
1725f0
-                        "Shadow framebuffer",
1725f0
-                        "Framebuffer used as intermediate shadow buffer",
1725f0
-                        COGL_TYPE_HANDLE,
1725f0
-                        G_PARAM_READWRITE |
1725f0
-                        G_PARAM_CONSTRUCT_ONLY |
1725f0
-                        G_PARAM_STATIC_STRINGS);
1725f0
+  obj_props[PROP_USE_SHADOWFB] =
1725f0
+    g_param_spec_boolean ("use-shadowfb",
1725f0
+                          "Use shadowfb",
1725f0
+                          "Whether to use one or more shadow framebuffers",
1725f0
+                          FALSE,
1725f0
+                          G_PARAM_READWRITE |
1725f0
+                          G_PARAM_CONSTRUCT_ONLY |
1725f0
+                          G_PARAM_STATIC_STRINGS);
1725f0
 
1725f0
   obj_props[PROP_SCALE] =
1725f0
     g_param_spec_float ("scale",
1725f0
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
1725f0
index d3fb5b3c55..463dddd3a7 100644
1725f0
--- a/src/backends/native/meta-renderer-native.c
1725f0
+++ b/src/backends/native/meta-renderer-native.c
1725f0
@@ -3685,7 +3685,7 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
1725f0
   MetaMonitorTransform view_transform;
1725f0
   CoglOnscreen *onscreen = NULL;
1725f0
   CoglOffscreen *offscreen = NULL;
1725f0
-  CoglOffscreen *shadowfb = NULL;
1725f0
+  gboolean use_shadowfb;
1725f0
   float scale;
1725f0
   int width, height;
1725f0
   MetaRendererView *view;
1725f0
@@ -3724,24 +3724,8 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
1725f0
 
1725f0
     }
1725f0
 
1725f0
-  if (should_force_shadow_fb (renderer_native,
1725f0
-                              renderer_native->primary_gpu_kms))
1725f0
-    {
1725f0
-      int shadow_width;
1725f0
-      int shadow_height;
1725f0
-
1725f0
-      /* The shadowfb must be the same size as the on-screen framebuffer */
1725f0
-      shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen));
1725f0
-      shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen));
1725f0
-
1725f0
-      shadowfb = meta_renderer_native_create_offscreen (renderer_native,
1725f0
-                                                        cogl_context,
1725f0
-                                                        shadow_width,
1725f0
-                                                        shadow_height,
1725f0
-                                                        &error);
1725f0
-      if (!shadowfb)
1725f0
-        g_error ("Failed to allocate shadow buffer texture: %s", error->message);
1725f0
-    }
1725f0
+  use_shadowfb = should_force_shadow_fb (renderer_native,
1725f0
+                                         renderer_native->primary_gpu_kms);
1725f0
 
1725f0
   monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
1725f0
   view = g_object_new (META_TYPE_RENDERER_VIEW,
1725f0
@@ -3750,12 +3734,11 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
1725f0
                        "scale", scale,
1725f0
                        "framebuffer", onscreen,
1725f0
                        "offscreen", offscreen,
1725f0
-                       "shadowfb", shadowfb,
1725f0
+                       "use-shadowfb", use_shadowfb,
1725f0
                        "logical-monitor", logical_monitor,
1725f0
                        "transform", view_transform,
1725f0
                        NULL);
1725f0
   g_clear_pointer (&offscreen, cogl_object_unref);
1725f0
-  g_clear_pointer (&shadowfb, cogl_object_unref);
1725f0
 
1725f0
   meta_onscreen_native_set_view (onscreen, view);
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From f79b37583e575d34edb4b7965cb0e48eb2736749 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Thu, 30 Apr 2020 18:19:30 +0200
1725f0
Subject: [PATCH 04/20] clutter/stage-view: Move shadowfb struct fields into
1725f0
 anonymous struct
1725f0
1725f0
With the aim to collect shadow buffer related things in one place, place
1725f0
them in an anonymous struct.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 310ca695d90b48074a06327e87bd7e924f49cb7f)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c | 32 +++++++++++++++-------------
1725f0
 1 file changed, 17 insertions(+), 15 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index db0067297c..9bbe158f36 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -51,8 +51,10 @@ typedef struct _ClutterStageViewPrivate
1725f0
   CoglPipeline *offscreen_pipeline;
1725f0
 
1725f0
   gboolean use_shadowfb;
1725f0
-  CoglOffscreen *shadowfb;
1725f0
-  CoglPipeline *shadowfb_pipeline;
1725f0
+  struct {
1725f0
+    CoglOffscreen *framebuffer;
1725f0
+    CoglPipeline *pipeline;
1725f0
+  } shadow;
1725f0
 
1725f0
   guint dirty_viewport   : 1;
1725f0
   guint dirty_projection : 1;
1725f0
@@ -86,8 +88,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
1725f0
 
1725f0
   if (priv->offscreen)
1725f0
     return priv->offscreen;
1725f0
-  else if (priv->shadowfb)
1725f0
-    return priv->shadowfb;
1725f0
+  else if (priv->shadow.framebuffer)
1725f0
+    return priv->shadow.framebuffer;
1725f0
   else
1725f0
     return priv->framebuffer;
1725f0
 }
1725f0
@@ -153,11 +155,11 @@ clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
 
1725f0
-  if (priv->shadowfb_pipeline)
1725f0
+  if (priv->shadow.pipeline)
1725f0
     return;
1725f0
 
1725f0
-  priv->shadowfb_pipeline =
1725f0
-    clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
1725f0
+  priv->shadow.pipeline =
1725f0
+    clutter_stage_view_create_framebuffer_pipeline (priv->shadow.framebuffer);
1725f0
 }
1725f0
 
1725f0
 void
1725f0
@@ -252,7 +254,7 @@ init_offscreen_shadowfb (ClutterStageView  *view,
1725f0
   if (!offscreen)
1725f0
     return FALSE;
1725f0
 
1725f0
-  priv->shadowfb = offscreen;
1725f0
+  priv->shadow.framebuffer = offscreen;
1725f0
   return TRUE;
1725f0
 }
1725f0
 
1725f0
@@ -297,13 +299,13 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
       clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
1725f0
       can_blit = cogl_matrix_is_identity (&matrix);
1725f0
 
1725f0
-      if (priv->shadowfb)
1725f0
+      if (priv->shadow.framebuffer)
1725f0
         {
1725f0
           clutter_stage_view_copy_to_framebuffer (view,
1725f0
                                                   rect,
1725f0
                                                   priv->offscreen_pipeline,
1725f0
                                                   priv->offscreen,
1725f0
-                                                  priv->shadowfb,
1725f0
+                                                  priv->shadow.framebuffer,
1725f0
                                                   can_blit);
1725f0
         }
1725f0
       else
1725f0
@@ -317,13 +319,13 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
         }
1725f0
     }
1725f0
 
1725f0
-  if (priv->shadowfb)
1725f0
+  if (priv->shadow.framebuffer)
1725f0
     {
1725f0
       clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
1725f0
       clutter_stage_view_copy_to_framebuffer (view,
1725f0
                                               rect,
1725f0
-                                              priv->shadowfb_pipeline,
1725f0
-                                              priv->shadowfb,
1725f0
+                                              priv->shadow.pipeline,
1725f0
+                                              priv->shadow.framebuffer,
1725f0
                                               priv->framebuffer,
1725f0
                                               TRUE);
1725f0
     }
1725f0
@@ -513,10 +515,10 @@ clutter_stage_view_dispose (GObject *object)
1725f0
 
1725f0
   g_clear_pointer (&priv->name, g_free);
1725f0
   g_clear_pointer (&priv->framebuffer, cogl_object_unref);
1725f0
-  g_clear_pointer (&priv->shadowfb, cogl_object_unref);
1725f0
+  g_clear_pointer (&priv->shadow.framebuffer, cogl_object_unref);
1725f0
+  g_clear_pointer (&priv->shadow.pipeline, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
1725f0
-  g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
1725f0
 
1725f0
   G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
1725f0
 }
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 7bf71e7b5f39fcf34c4a636640636f9452b4b06c Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Thu, 30 Apr 2020 21:51:10 +0200
1725f0
Subject: [PATCH 05/20] clutter/stage-view: Move fb viewport and projection
1725f0
 setting to here
1725f0
1725f0
The stage would fetch the front framebuffer and set the viewport and
1725f0
projection matrix, but if we are going to more than one front buffer,
1725f0
that won't work, so let the stage just pass the viewport and projection
1725f0
matrix to the view and have the view deal with the framebuffer(s).
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit c79bcf0d7e35cf9e85864cf72ea53659a6b8d8a7)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view-private.h |  8 ++++++
1725f0
 clutter/clutter/clutter-stage-view.c         | 29 ++++++++++++++++++++
1725f0
 clutter/clutter/clutter-stage.c              | 16 ++++-------
1725f0
 3 files changed, 42 insertions(+), 11 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
1725f0
index 89c42599fc..78aa37c9f4 100644
1725f0
--- a/clutter/clutter/clutter-stage-view-private.h
1725f0
+++ b/clutter/clutter/clutter-stage-view-private.h
1725f0
@@ -28,10 +28,18 @@ gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
1725f0
 void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
1725f0
                                             gboolean          dirty);
1725f0
 
1725f0
+void clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
+                                      float             x,
1725f0
+                                      float             y,
1725f0
+                                      float             width,
1725f0
+                                      float             height);
1725f0
+
1725f0
 gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
1725f0
 
1725f0
 void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
1725f0
                                               gboolean          dirty);
1725f0
 
1725f0
+void clutter_stage_view_set_projection (ClutterStageView *view,
1725f0
+                                        const CoglMatrix *matrix);
1725f0
 
1725f0
 #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 9bbe158f36..4d8bbddc9d 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -359,6 +359,22 @@ clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
1725f0
   priv->dirty_viewport = dirty;
1725f0
 }
1725f0
 
1725f0
+void
1725f0
+clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
+                                 float             x,
1725f0
+                                 float             y,
1725f0
+                                 float             width,
1725f0
+                                 float             height)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  CoglFramebuffer *framebuffer;
1725f0
+
1725f0
+  priv->dirty_viewport = FALSE;
1725f0
+  framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
+  cogl_framebuffer_set_viewport (framebuffer, x, y, width, height);
1725f0
+}
1725f0
+
1725f0
 gboolean
1725f0
 clutter_stage_view_is_dirty_projection (ClutterStageView *view)
1725f0
 {
1725f0
@@ -378,6 +394,19 @@ clutter_stage_view_set_dirty_projection (ClutterStageView *view,
1725f0
   priv->dirty_projection = dirty;
1725f0
 }
1725f0
 
1725f0
+void
1725f0
+clutter_stage_view_set_projection (ClutterStageView *view,
1725f0
+                                   const CoglMatrix *matrix)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  CoglFramebuffer *framebuffer;
1725f0
+
1725f0
+  priv->dirty_projection = FALSE;
1725f0
+  framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
+  cogl_framebuffer_set_projection_matrix (framebuffer, matrix);
1725f0
+}
1725f0
+
1725f0
 void
1725f0
 clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
1725f0
                                                         CoglMatrix       *matrix)
1725f0
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
1725f0
index 34c4e0119a..4bde234dbf 100644
1725f0
--- a/clutter/clutter/clutter-stage.c
1725f0
+++ b/clutter/clutter/clutter-stage.c
1725f0
@@ -3687,7 +3687,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
1725f0
                                      ClutterStageView *view)
1725f0
 {
1725f0
   ClutterStagePrivate *priv = stage->priv;
1725f0
-  CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
1725f0
 
1725f0
   if (clutter_stage_view_is_dirty_viewport (view))
1725f0
     {
1725f0
@@ -3716,9 +3715,10 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
1725f0
       viewport_y = roundf (priv->viewport[1] * fb_scale - viewport_offset_y);
1725f0
       viewport_width = roundf (priv->viewport[2] * fb_scale);
1725f0
       viewport_height = roundf (priv->viewport[3] * fb_scale);
1725f0
-      cogl_framebuffer_set_viewport (fb,
1725f0
-                                     viewport_x, viewport_y,
1725f0
-                                     viewport_width, viewport_height);
1725f0
+
1725f0
+      clutter_stage_view_set_viewport (view,
1725f0
+                                       viewport_x, viewport_y,
1725f0
+                                       viewport_width, viewport_height);
1725f0
 
1725f0
       perspective = priv->perspective;
1725f0
 
1725f0
@@ -3751,16 +3751,10 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
1725f0
                                           z_2d,
1725f0
                                           priv->viewport[2],
1725f0
                                           priv->viewport[3]);
1725f0
-
1725f0
-      clutter_stage_view_set_dirty_viewport (view, FALSE);
1725f0
     }
1725f0
 
1725f0
   if (clutter_stage_view_is_dirty_projection (view))
1725f0
-    {
1725f0
-      cogl_framebuffer_set_projection_matrix (fb, &priv->projection);
1725f0
-
1725f0
-      clutter_stage_view_set_dirty_projection (view, FALSE);
1725f0
-    }
1725f0
+    clutter_stage_view_set_projection (view, &priv->projection);
1725f0
 }
1725f0
 
1725f0
 #undef _DEG_TO_RAD
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 0b345dc3a108f12ebc00e831692b43291c84cd07 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Thu, 30 Apr 2020 21:59:49 +0200
1725f0
Subject: [PATCH 06/20] clutter/stage-view: Change set_dirty..() API to
1725f0
 invalidate..()
1725f0
1725f0
The manual "cleaning" of the viewport and projection state is removed,
1725f0
and we only ever try to invalidate the state so that it'll be updated
1725f0
next time. Change the API used to reflect this.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 3080ee672a366a3a52d9f43523c40e3afd08e874)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view-private.h |  6 ++----
1725f0
 clutter/clutter/clutter-stage-view.c         | 10 ++++------
1725f0
 clutter/clutter/clutter-stage.c              |  4 ++--
1725f0
 3 files changed, 8 insertions(+), 12 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
1725f0
index 78aa37c9f4..e27f140b8a 100644
1725f0
--- a/clutter/clutter/clutter-stage-view-private.h
1725f0
+++ b/clutter/clutter/clutter-stage-view-private.h
1725f0
@@ -25,8 +25,7 @@ void clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
 
1725f0
 gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
1725f0
 
1725f0
-void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
1725f0
-                                            gboolean          dirty);
1725f0
+void clutter_stage_view_invalidate_viewport (ClutterStageView *view);
1725f0
 
1725f0
 void clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
                                       float             x,
1725f0
@@ -36,8 +35,7 @@ void clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
 
1725f0
 gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
1725f0
 
1725f0
-void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
1725f0
-                                              gboolean          dirty);
1725f0
+void clutter_stage_view_invalidate_projection (ClutterStageView *view);
1725f0
 
1725f0
 void clutter_stage_view_set_projection (ClutterStageView *view,
1725f0
                                         const CoglMatrix *matrix);
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 4d8bbddc9d..40edfad6e1 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -350,13 +350,12 @@ clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
1725f0
 }
1725f0
 
1725f0
 void
1725f0
-clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
1725f0
-                                       gboolean          dirty)
1725f0
+clutter_stage_view_invalidate_viewport (ClutterStageView *view)
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
 
1725f0
-  priv->dirty_viewport = dirty;
1725f0
+  priv->dirty_viewport = TRUE;
1725f0
 }
1725f0
 
1725f0
 void
1725f0
@@ -385,13 +384,12 @@ clutter_stage_view_is_dirty_projection (ClutterStageView *view)
1725f0
 }
1725f0
 
1725f0
 void
1725f0
-clutter_stage_view_set_dirty_projection (ClutterStageView *view,
1725f0
-                                         gboolean          dirty)
1725f0
+clutter_stage_view_invalidate_projection (ClutterStageView *view)
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
 
1725f0
-  priv->dirty_projection = dirty;
1725f0
+  priv->dirty_projection = TRUE;
1725f0
 }
1725f0
 
1725f0
 void
1725f0
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
1725f0
index 4bde234dbf..aaa77d9ede 100644
1725f0
--- a/clutter/clutter/clutter-stage.c
1725f0
+++ b/clutter/clutter/clutter-stage.c
1725f0
@@ -2636,7 +2636,7 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
1725f0
     {
1725f0
       ClutterStageView *view = l->data;
1725f0
 
1725f0
-      clutter_stage_view_set_dirty_projection (view, TRUE);
1725f0
+      clutter_stage_view_invalidate_projection (view);
1725f0
     }
1725f0
 }
1725f0
 
1725f0
@@ -2725,7 +2725,7 @@ _clutter_stage_dirty_viewport (ClutterStage *stage)
1725f0
     {
1725f0
       ClutterStageView *view = l->data;
1725f0
 
1725f0
-      clutter_stage_view_set_dirty_viewport (view, TRUE);
1725f0
+      clutter_stage_view_invalidate_viewport (view);
1725f0
     }
1725f0
 }
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 32da7b5c31277c56089e4b3b8ccf43bc552e8974 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 17:05:36 +0200
1725f0
Subject: [PATCH 07/20] cogl: Make private BLIT_FRAMEBUFFER feature public
1725f0
1725f0
Will be a requirement for enabling shadow buffers.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit b3153760bf81af07f5328ba07b0ff3009bd8305b)
1725f0
---
1725f0
 cogl/cogl/cogl-blit.c                       | 2 +-
1725f0
 cogl/cogl/cogl-context.h                    | 3 +++
1725f0
 cogl/cogl/cogl-framebuffer.c                | 2 +-
1725f0
 cogl/cogl/cogl-framebuffer.h                | 2 +-
1725f0
 cogl/cogl/cogl-private.h                    | 1 -
1725f0
 cogl/cogl/driver/gl/cogl-framebuffer-gl.c   | 4 ++--
1725f0
 cogl/cogl/driver/gl/gl/cogl-driver-gl.c     | 4 ++--
1725f0
 cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 4 ++--
1725f0
 8 files changed, 12 insertions(+), 10 deletions(-)
1725f0
1725f0
diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c
1725f0
index ae5a8a345d..dd5fffff37 100644
1725f0
--- a/cogl/cogl/cogl-blit.c
1725f0
+++ b/cogl/cogl/cogl-blit.c
1725f0
@@ -158,7 +158,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
1725f0
      supported. */
1725f0
   if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) !=
1725f0
       (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) ||
1725f0
-      !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
1725f0
+      !cogl_has_feature (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
1725f0
     return FALSE;
1725f0
 
1725f0
   dst_offscreen = _cogl_offscreen_new_with_texture_full
1725f0
diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h
1725f0
index d4104625e6..ec90491e94 100644
1725f0
--- a/cogl/cogl/cogl-context.h
1725f0
+++ b/cogl/cogl/cogl-context.h
1725f0
@@ -227,6 +227,8 @@ cogl_is_context (void *object);
1725f0
  *     the depth buffer to a texture.
1725f0
  * @COGL_FEATURE_ID_PRESENTATION_TIME: Whether frame presentation
1725f0
  *    time stamps will be recorded in #CoglFrameInfo objects.
1725f0
+ * @COGL_FEATURE_ID_BLIT_FRAMEBUFFER: Whether blitting using
1725f0
+ *    cogl_blit_framebuffer() is supported.
1725f0
  *
1725f0
  * All the capabilities that can vary between different GPUs supported
1725f0
  * by Cogl. Applications that depend on any of these features should explicitly
1725f0
@@ -261,6 +263,7 @@ typedef enum _CoglFeatureID
1725f0
   COGL_FEATURE_ID_TEXTURE_RG,
1725f0
   COGL_FEATURE_ID_BUFFER_AGE,
1725f0
   COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
1725f0
+  COGL_FEATURE_ID_BLIT_FRAMEBUFFER,
1725f0
 
1725f0
   /*< private >*/
1725f0
   _COGL_N_FEATURE_IDS   /*< skip >*/
1725f0
diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
1725f0
index d64fc89fb6..fffac3f685 100644
1725f0
--- a/cogl/cogl/cogl-framebuffer.c
1725f0
+++ b/cogl/cogl/cogl-framebuffer.c
1725f0
@@ -1464,7 +1464,7 @@ cogl_blit_framebuffer (CoglFramebuffer *src,
1725f0
   int src_x1, src_y1, src_x2, src_y2;
1725f0
   int dst_x1, dst_y1, dst_x2, dst_y2;
1725f0
 
1725f0
-  if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
1725f0
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
1725f0
     {
1725f0
       g_set_error_literal (error, COGL_SYSTEM_ERROR,
1725f0
                            COGL_SYSTEM_ERROR_UNSUPPORTED,
1725f0
diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h
1725f0
index 38ada9feb7..c347076919 100644
1725f0
--- a/cogl/cogl/cogl-framebuffer.h
1725f0
+++ b/cogl/cogl/cogl-framebuffer.h
1725f0
@@ -1863,7 +1863,7 @@ cogl_is_framebuffer (void *object);
1725f0
  *
1725f0
  * This blits a region of the color buffer of the source buffer
1725f0
  * to the destination buffer. This function should only be
1725f0
- * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is
1725f0
+ * called if the COGL_FEATURE_ID_BLIT_FRAMEBUFFER feature is
1725f0
  * advertised.
1725f0
  *
1725f0
  * The source and destination rectangles are defined in offscreen
1725f0
diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h
1725f0
index d9fbe68c76..07ac7eb2d8 100644
1725f0
--- a/cogl/cogl/cogl-private.h
1725f0
+++ b/cogl/cogl/cogl-private.h
1725f0
@@ -42,7 +42,6 @@ typedef enum
1725f0
 {
1725f0
   COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE,
1725f0
   COGL_PRIVATE_FEATURE_MESA_PACK_INVERT,
1725f0
-  COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER,
1725f0
   COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES,
1725f0
   COGL_PRIVATE_FEATURE_PBOS,
1725f0
   COGL_PRIVATE_FEATURE_VBOS,
1725f0
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
1725f0
index 6466fd6bcf..2c0613462f 100644
1725f0
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
1725f0
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
1725f0
@@ -401,8 +401,8 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
1725f0
         {
1725f0
           /* NB: Currently we only take advantage of binding separate
1725f0
            * read/write buffers for framebuffer blit purposes. */
1725f0
-          _COGL_RETURN_IF_FAIL (_cogl_has_private_feature
1725f0
-                                (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER));
1725f0
+          _COGL_RETURN_IF_FAIL (cogl_has_feature
1725f0
+                                (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER));
1725f0
 
1725f0
           _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
1725f0
           _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
1725f0
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
1725f0
index 716617b54b..f905267c53 100644
1725f0
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
1725f0
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
1725f0
@@ -466,8 +466,8 @@ _cogl_driver_update_features (CoglContext *ctx,
1725f0
     }
1725f0
 
1725f0
   if (ctx->glBlitFramebuffer)
1725f0
-    COGL_FLAGS_SET (private_features,
1725f0
-                    COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
1725f0
+    COGL_FLAGS_SET (ctx->features,
1725f0
+                    COGL_FEATURE_ID_BLIT_FRAMEBUFFER, TRUE);
1725f0
 
1725f0
   if (ctx->glRenderbufferStorageMultisampleIMG)
1725f0
     {
1725f0
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
1725f0
index 902bd0bd3a..e55bb302c4 100644
1725f0
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
1725f0
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
1725f0
@@ -325,8 +325,8 @@ _cogl_driver_update_features (CoglContext *context,
1725f0
     }
1725f0
 
1725f0
   if (context->glBlitFramebuffer)
1725f0
-    COGL_FLAGS_SET (private_features,
1725f0
-                    COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
1725f0
+    COGL_FLAGS_SET (context->features,
1725f0
+                    COGL_FEATURE_ID_BLIT_FRAMEBUFFER, TRUE);
1725f0
 
1725f0
   if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions))
1725f0
     {
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 32aa92e50a12a5fd9652866937750a3c86c4845f Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 17:06:35 +0200
1725f0
Subject: [PATCH 08/20] renderer/native: Only enable shadowfbs if we can blit
1725f0
1725f0
There is no point in enabling shadow buffers if we can't as that'd be
1725f0
even slower than not having them at all.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit f191c3b74f572547707fcb6522db76a88689eae2)
1725f0
---
1725f0
 src/backends/native/meta-renderer-native.c | 3 +++
1725f0
 1 file changed, 3 insertions(+)
1725f0
1725f0
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
1725f0
index 463dddd3a7..62ca4bcbd4 100644
1725f0
--- a/src/backends/native/meta-renderer-native.c
1725f0
+++ b/src/backends/native/meta-renderer-native.c
1725f0
@@ -3649,6 +3649,9 @@ should_force_shadow_fb (MetaRendererNative *renderer_native,
1725f0
       break;
1725f0
     }
1725f0
 
1725f0
+  if (!cogl_has_feature (cogl_context, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
1725f0
+    return FALSE;
1725f0
+
1725f0
   kms_fd = meta_gpu_kms_get_fd (primary_gpu);
1725f0
   if (drmGetCap (kms_fd, DRM_CAP_DUMB_PREFER_SHADOW, &prefer_shadow) == 0)
1725f0
     {
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 5f247503e261f5bbb6baedc40c737c96b8144218 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 18:55:03 +0200
1725f0
Subject: [PATCH 09/20] clutter/stage-view: Always use cogl_blit_framebuffer()
1725f0
 from shadowfb
1725f0
1725f0
It should only be used when direct blitting is supported, so there is no
1725f0
reason we should have to deal with pipelines etc when blitting from the
1725f0
shadow buffer to the onscreen.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 130f696f303a01d6d666ac967c53b4b5dc372f08)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c | 37 +++++++++++-----------------
1725f0
 1 file changed, 15 insertions(+), 22 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 40edfad6e1..e7e33963a6 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -53,7 +53,6 @@ typedef struct _ClutterStageViewPrivate
1725f0
   gboolean use_shadowfb;
1725f0
   struct {
1725f0
     CoglOffscreen *framebuffer;
1725f0
-    CoglPipeline *pipeline;
1725f0
   } shadow;
1725f0
 
1725f0
   guint dirty_viewport   : 1;
1725f0
@@ -149,19 +148,6 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
1725f0
     view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
1725f0
 }
1725f0
 
1725f0
-static void
1725f0
-clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
1725f0
-{
1725f0
-  ClutterStageViewPrivate *priv =
1725f0
-    clutter_stage_view_get_instance_private (view);
1725f0
-
1725f0
-  if (priv->shadow.pipeline)
1725f0
-    return;
1725f0
-
1725f0
-  priv->shadow.pipeline =
1725f0
-    clutter_stage_view_create_framebuffer_pipeline (priv->shadow.framebuffer);
1725f0
-}
1725f0
-
1725f0
 void
1725f0
 clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
1725f0
 {
1725f0
@@ -321,13 +307,21 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
 
1725f0
   if (priv->shadow.framebuffer)
1725f0
     {
1725f0
-      clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
1725f0
-      clutter_stage_view_copy_to_framebuffer (view,
1725f0
-                                              rect,
1725f0
-                                              priv->shadow.pipeline,
1725f0
-                                              priv->shadow.framebuffer,
1725f0
-                                              priv->framebuffer,
1725f0
-                                              TRUE);
1725f0
+      int width, height;
1725f0
+      g_autoptr (GError) error = NULL;
1725f0
+
1725f0
+      width = cogl_framebuffer_get_width (priv->framebuffer);
1725f0
+      height = cogl_framebuffer_get_height (priv->framebuffer);
1725f0
+      if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
1725f0
+                                  priv->framebuffer,
1725f0
+                                  0, 0,
1725f0
+                                  0, 0,
1725f0
+                                  width, height,
1725f0
+                                  &error))
1725f0
+        {
1725f0
+          g_warning ("Failed to blit shadow buffer: %s", error->message);
1725f0
+          return;
1725f0
+        }
1725f0
     }
1725f0
 }
1725f0
 
1725f0
@@ -543,7 +537,6 @@ clutter_stage_view_dispose (GObject *object)
1725f0
   g_clear_pointer (&priv->name, g_free);
1725f0
   g_clear_pointer (&priv->framebuffer, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->shadow.framebuffer, cogl_object_unref);
1725f0
-  g_clear_pointer (&priv->shadow.pipeline, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From d20008aa8630c87d8607e64ff77188fc67b3d22a Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 18:59:32 +0200
1725f0
Subject: [PATCH 10/20] clutter/stage-view: Simplify painting of offscreen
1725f0
 slightly
1725f0
1725f0
We will only ever have an "offscreen" if we're painting transformed in
1725f0
some way, so the 'can_blit' checking is unnecessary. Remove it.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 32d5e7d3d77c7ba29b8a7da45731aa31bd486056)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c | 49 +++++++---------------------
1725f0
 1 file changed, 12 insertions(+), 37 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index e7e33963a6..64fb20cb00 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -158,29 +158,13 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
1725f0
 }
1725f0
 
1725f0
 static void
1725f0
-clutter_stage_view_copy_to_framebuffer (ClutterStageView            *view,
1725f0
-                                        const cairo_rectangle_int_t *rect,
1725f0
-                                        CoglPipeline                *pipeline,
1725f0
-                                        CoglFramebuffer             *src_framebuffer,
1725f0
-                                        CoglFramebuffer             *dst_framebuffer,
1725f0
-                                        gboolean                     can_blit)
1725f0
+paint_transformed_framebuffer (ClutterStageView *view,
1725f0
+                               CoglPipeline     *pipeline,
1725f0
+                               CoglFramebuffer  *src_framebuffer,
1725f0
+                               CoglFramebuffer  *dst_framebuffer)
1725f0
 {
1725f0
   CoglMatrix matrix;
1725f0
 
1725f0
-  /* First, try with blit */
1725f0
-  if (can_blit)
1725f0
-    {
1725f0
-      if (cogl_blit_framebuffer (src_framebuffer,
1725f0
-                                 dst_framebuffer,
1725f0
-                                 0, 0,
1725f0
-                                 0, 0,
1725f0
-                                 cogl_framebuffer_get_width (dst_framebuffer),
1725f0
-                                 cogl_framebuffer_get_height (dst_framebuffer),
1725f0
-                                 NULL))
1725f0
-        return;
1725f0
-    }
1725f0
-
1725f0
-  /* If blit fails, fallback to the slower painting method */
1725f0
   cogl_framebuffer_push_matrix (dst_framebuffer);
1725f0
 
1725f0
   cogl_matrix_init_identity (&matrix);
1725f0
@@ -278,30 +262,21 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
 
1725f0
   if (priv->offscreen)
1725f0
     {
1725f0
-      gboolean can_blit;
1725f0
-      CoglMatrix matrix;
1725f0
-
1725f0
       clutter_stage_view_ensure_offscreen_blit_pipeline (view);
1725f0
-      clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
1725f0
-      can_blit = cogl_matrix_is_identity (&matrix);
1725f0
 
1725f0
       if (priv->shadow.framebuffer)
1725f0
         {
1725f0
-          clutter_stage_view_copy_to_framebuffer (view,
1725f0
-                                                  rect,
1725f0
-                                                  priv->offscreen_pipeline,
1725f0
-                                                  priv->offscreen,
1725f0
-                                                  priv->shadow.framebuffer,
1725f0
-                                                  can_blit);
1725f0
+          paint_transformed_framebuffer (view,
1725f0
+                                         priv->offscreen_pipeline,
1725f0
+                                         priv->offscreen,
1725f0
+                                         priv->shadow.framebuffer);
1725f0
         }
1725f0
       else
1725f0
         {
1725f0
-          clutter_stage_view_copy_to_framebuffer (view,
1725f0
-                                                  rect,
1725f0
-                                                  priv->offscreen_pipeline,
1725f0
-                                                  priv->offscreen,
1725f0
-                                                  priv->framebuffer,
1725f0
-                                                  can_blit);
1725f0
+          paint_transformed_framebuffer (view,
1725f0
+                                         priv->offscreen_pipeline,
1725f0
+                                         priv->offscreen,
1725f0
+                                         priv->framebuffer);
1725f0
         }
1725f0
     }
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 8fca65cc3ff989529bf08a47f20b80691f91f95f Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 19:08:03 +0200
1725f0
Subject: [PATCH 11/20] region-utils: Make transform util const correct
1725f0
1725f0
The input should be const, as it will not be altered.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 761bc64cdd4746389625173454b8861cf211cd79)
1725f0
---
1725f0
 src/compositor/region-utils.c | 2 +-
1725f0
 src/compositor/region-utils.h | 2 +-
1725f0
 2 files changed, 2 insertions(+), 2 deletions(-)
1725f0
1725f0
diff --git a/src/compositor/region-utils.c b/src/compositor/region-utils.c
1725f0
index 752af85c5c..8edb89322c 100644
1725f0
--- a/src/compositor/region-utils.c
1725f0
+++ b/src/compositor/region-utils.c
1725f0
@@ -376,7 +376,7 @@ meta_make_border_region (cairo_region_t *region,
1725f0
 }
1725f0
 
1725f0
 cairo_region_t *
1725f0
-meta_region_transform (cairo_region_t       *region,
1725f0
+meta_region_transform (const cairo_region_t *region,
1725f0
                        MetaMonitorTransform  transform,
1725f0
                        int                   width,
1725f0
                        int                   height)
1725f0
diff --git a/src/compositor/region-utils.h b/src/compositor/region-utils.h
1725f0
index 84e4d83bc2..ca1b8b7b45 100644
1725f0
--- a/src/compositor/region-utils.h
1725f0
+++ b/src/compositor/region-utils.h
1725f0
@@ -106,7 +106,7 @@ cairo_region_t * meta_make_border_region (cairo_region_t *region,
1725f0
                                           int             y_amount,
1725f0
                                           gboolean        flip);
1725f0
 
1725f0
-cairo_region_t * meta_region_transform (cairo_region_t       *region,
1725f0
+cairo_region_t * meta_region_transform (const cairo_region_t *region,
1725f0
                                         MetaMonitorTransform  transform,
1725f0
                                         int                   width,
1725f0
                                         int                   height);
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 58331ff2f10aad87f537e3ebdaa5707c13c9e41b Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 19:05:36 +0200
1725f0
Subject: [PATCH 12/20] clutter/stage-cogl: Use buffer age when view monitor is
1725f0
 rotated
1725f0
1725f0
We failed to use the buffer age when monitors were rotated, as when they
1725f0
are, we first composite to an offscreen framebuffer, then later again to
1725f0
the onscreen. The buffer age checking happened on the offscreen, and an
1725f0
offscreen being single buffered, they can't possible support buffer
1725f0
ages.
1725f0
1725f0
Instead, move the buffer age check to check the actual onscreen
1725f0
framebuffer. The offscreen to onscreen painting is still always full
1725f0
frame, but that will be fixed in a later commit.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 41c2c2c7d72a0bc8ac1970d35183345424642cf1)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view-private.h |  6 +++
1725f0
 clutter/clutter/clutter-stage-view.c         | 29 ++++++-----
1725f0
 clutter/clutter/clutter-stage-view.h         | 11 ++--
1725f0
 clutter/clutter/cogl/clutter-stage-cogl.c    | 54 +++++++-------------
1725f0
 src/backends/meta-renderer-view.c            | 22 ++++++++
1725f0
 5 files changed, 68 insertions(+), 54 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
1725f0
index e27f140b8a..10f9847b70 100644
1725f0
--- a/clutter/clutter/clutter-stage-view-private.h
1725f0
+++ b/clutter/clutter/clutter-stage-view-private.h
1725f0
@@ -40,4 +40,10 @@ void clutter_stage_view_invalidate_projection (ClutterStageView *view);
1725f0
 void clutter_stage_view_set_projection (ClutterStageView *view,
1725f0
                                         const CoglMatrix *matrix);
1725f0
 
1725f0
+void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView            *view,
1725f0
+                                                    const cairo_rectangle_int_t *src_rect,
1725f0
+                                                    int                          dst_width,
1725f0
+                                                    int                          dst_height,
1725f0
+                                                    cairo_rectangle_int_t       *dst_rect);
1725f0
+
1725f0
 #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 64fb20cb00..080bfd6669 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -157,6 +157,22 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
1725f0
   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
1725f0
 }
1725f0
 
1725f0
+void
1725f0
+clutter_stage_view_transform_rect_to_onscreen (ClutterStageView            *view,
1725f0
+                                               const cairo_rectangle_int_t *src_rect,
1725f0
+                                               int                          dst_width,
1725f0
+                                               int                          dst_height,
1725f0
+                                               cairo_rectangle_int_t       *dst_rect)
1725f0
+{
1725f0
+  ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
1725f0
+
1725f0
+  return view_class->transform_rect_to_onscreen (view,
1725f0
+                                                 src_rect,
1725f0
+                                                 dst_width,
1725f0
+                                                 dst_height,
1725f0
+                                                 dst_rect);
1725f0
+}
1725f0
+
1725f0
 static void
1725f0
 paint_transformed_framebuffer (ClutterStageView *view,
1725f0
                                CoglPipeline     *pipeline,
1725f0
@@ -383,19 +399,6 @@ clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
1725f0
   view_class->get_offscreen_transformation_matrix (view, matrix);
1725f0
 }
1725f0
 
1725f0
-void
1725f0
-clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
1725f0
-                                          gfloat           *x,
1725f0
-                                          gfloat           *y)
1725f0
-{
1725f0
-  gfloat z = 0, w = 1;
1725f0
-  CoglMatrix matrix;
1725f0
-
1725f0
-  clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
1725f0
-  cogl_matrix_get_inverse (&matrix, &matrix);
1725f0
-  cogl_matrix_transform_point (&matrix, x, y, &z, &w);
1725f0
-}
1725f0
-
1725f0
 static void
1725f0
 clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view,
1725f0
                                                            CoglMatrix       *matrix)
1725f0
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
1725f0
index 26bf10e798..eb0184e9ab 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.h
1725f0
+++ b/clutter/clutter/clutter-stage-view.h
1725f0
@@ -43,6 +43,12 @@ struct _ClutterStageViewClass
1725f0
 
1725f0
   void (* get_offscreen_transformation_matrix) (ClutterStageView *view,
1725f0
                                                 CoglMatrix       *matrix);
1725f0
+
1725f0
+  void (* transform_rect_to_onscreen) (ClutterStageView            *view,
1725f0
+                                       const cairo_rectangle_int_t *src_rect,
1725f0
+                                       int                          dst_width,
1725f0
+                                       int                          dst_height,
1725f0
+                                       cairo_rectangle_int_t       *dst_rect);
1725f0
 };
1725f0
 
1725f0
 CLUTTER_EXPORT
1725f0
@@ -56,11 +62,6 @@ CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view);
1725f0
 CLUTTER_EXPORT
1725f0
 void             clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view);
1725f0
 
1725f0
-CLUTTER_EXPORT
1725f0
-void             clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
1725f0
-                                                           gfloat           *x,
1725f0
-                                                           gfloat           *y);
1725f0
-
1725f0
 CLUTTER_EXPORT
1725f0
 float clutter_stage_view_get_scale (ClutterStageView *view);
1725f0
 
1725f0
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
index 005c6f6922..821f78ee7c 100644
1725f0
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
@@ -509,36 +509,17 @@ static void
1725f0
 transform_swap_region_to_onscreen (ClutterStageView      *view,
1725f0
                                    cairo_rectangle_int_t *swap_region)
1725f0
 {
1725f0
-  CoglFramebuffer *framebuffer;
1725f0
-  cairo_rectangle_int_t layout;
1725f0
-  gfloat x1, y1, x2, y2;
1725f0
-  gint width, height;
1725f0
-
1725f0
-  framebuffer = clutter_stage_view_get_onscreen (view);
1725f0
-  clutter_stage_view_get_layout (view, &layout);
1725f0
-
1725f0
-  x1 = (float) swap_region->x / layout.width;
1725f0
-  y1 = (float) swap_region->y / layout.height;
1725f0
-  x2 = (float) (swap_region->x + swap_region->width) / layout.width;
1725f0
-  y2 = (float) (swap_region->y + swap_region->height) / layout.height;
1725f0
-
1725f0
-  clutter_stage_view_transform_to_onscreen (view, &x1, &y1;;
1725f0
-  clutter_stage_view_transform_to_onscreen (view, &x2, &y2;;
1725f0
-
1725f0
-  width = cogl_framebuffer_get_width (framebuffer);
1725f0
-  height = cogl_framebuffer_get_height (framebuffer);
1725f0
-
1725f0
-  x1 = floor (x1 * width);
1725f0
-  y1 = floor (height - (y1 * height));
1725f0
-  x2 = ceil (x2 * width);
1725f0
-  y2 = ceil (height - (y2 * height));
1725f0
-
1725f0
-  *swap_region = (cairo_rectangle_int_t) {
1725f0
-    .x = x1,
1725f0
-    .y = y1,
1725f0
-    .width = x2 - x1,
1725f0
-    .height = y2 - y1
1725f0
-  };
1725f0
+  CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
1725f0
+  int width, height;
1725f0
+
1725f0
+  width = cogl_framebuffer_get_width (onscreen);
1725f0
+  height = cogl_framebuffer_get_height (onscreen);
1725f0
+
1725f0
+  clutter_stage_view_transform_rect_to_onscreen (view,
1725f0
+                                                 swap_region,
1725f0
+                                                 width,
1725f0
+                                                 height,
1725f0
+                                                 swap_region);
1725f0
 }
1725f0
 
1725f0
 static void
1725f0
@@ -593,6 +574,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
   ClutterStageViewCoglPrivate *view_priv =
1725f0
     clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
   CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
1725f0
+  CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
1725f0
   cairo_rectangle_int_t view_rect;
1725f0
   gboolean have_clip;
1725f0
   gboolean may_use_clipped_redraw;
1725f0
@@ -618,10 +600,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
   fb_height = cogl_framebuffer_get_height (fb);
1725f0
 
1725f0
   can_blit_sub_buffer =
1725f0
-    cogl_is_onscreen (fb) &&
1725f0
+    cogl_is_onscreen (onscreen) &&
1725f0
     cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION);
1725f0
 
1725f0
-  has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
1725f0
+  has_buffer_age = cogl_is_onscreen (onscreen) && is_buffer_age_enabled ();
1725f0
 
1725f0
   /* NB: a zero width redraw clip == full stage redraw */
1725f0
   if (stage_cogl->bounding_redraw_clip.width == 0)
1725f0
@@ -645,7 +627,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
       have_clip &&
1725f0
       /* some drivers struggle to get going and produce some junk
1725f0
        * frames when starting up... */
1725f0
-      cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
1725f0
+      cogl_onscreen_get_frame_counter (COGL_ONSCREEN (onscreen)) > 3)
1725f0
     {
1725f0
       ClutterRect rect;
1725f0
 
1725f0
@@ -686,7 +668,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
           cairo_rectangle_int_t *current_fb_damage =
1725f0
             &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)];
1725f0
 
1725f0
-          age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb));
1725f0
+          age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen));
1725f0
 
1725f0
           if (valid_buffer_age (view_cogl, age))
1725f0
             {
1725f0
@@ -961,9 +943,9 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
1725f0
                                     int                *x,
1725f0
                                     int                *y)
1725f0
 {
1725f0
-  CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
+  CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
1725f0
   gboolean has_buffer_age =
1725f0
-    cogl_is_onscreen (framebuffer) &&
1725f0
+    cogl_is_onscreen (onscreen) &&
1725f0
     is_buffer_age_enabled ();
1725f0
   float fb_scale;
1725f0
   gboolean scale_is_fractional;
1725f0
diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c
1725f0
index cab1f5f483..4e45f2ef02 100644
1725f0
--- a/src/backends/meta-renderer-view.c
1725f0
+++ b/src/backends/meta-renderer-view.c
1725f0
@@ -34,6 +34,7 @@
1725f0
 
1725f0
 #include "backends/meta-renderer.h"
1725f0
 #include "clutter/clutter-mutter.h"
1725f0
+#include "compositor/region-utils.h"
1725f0
 
1725f0
 enum
1725f0
 {
1725f0
@@ -125,6 +126,25 @@ meta_renderer_view_setup_offscreen_blit_pipeline (ClutterStageView *view,
1725f0
   cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+meta_renderer_view_transform_rect_to_onscreen (ClutterStageView            *view,
1725f0
+                                               const cairo_rectangle_int_t *src_rect,
1725f0
+                                               int                          dst_width,
1725f0
+                                               int                          dst_height,
1725f0
+                                               cairo_rectangle_int_t       *dst_rect)
1725f0
+{
1725f0
+  MetaRendererView *renderer_view = META_RENDERER_VIEW (view);
1725f0
+  MetaMonitorTransform inverted_transform;
1725f0
+
1725f0
+  inverted_transform =
1725f0
+    meta_monitor_transform_invert (renderer_view->transform);
1725f0
+  return meta_rectangle_transform (src_rect,
1725f0
+                                   inverted_transform,
1725f0
+                                   dst_width,
1725f0
+                                   dst_height,
1725f0
+                                   dst_rect);
1725f0
+}
1725f0
+
1725f0
 static void
1725f0
 meta_renderer_view_set_transform (MetaRendererView     *view,
1725f0
                                   MetaMonitorTransform  transform)
1725f0
@@ -195,6 +215,8 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
1725f0
     meta_renderer_view_setup_offscreen_blit_pipeline;
1725f0
   view_class->get_offscreen_transformation_matrix =
1725f0
     meta_renderer_view_get_offscreen_transformation_matrix;
1725f0
+  view_class->transform_rect_to_onscreen =
1725f0
+    meta_renderer_view_transform_rect_to_onscreen;
1725f0
 
1725f0
   object_class->get_property = meta_renderer_view_get_property;
1725f0
   object_class->set_property = meta_renderer_view_set_property;
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 6fc1da9dd3ac2753771bb68adb780d1d55494cba Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 19:22:10 +0200
1725f0
Subject: [PATCH 13/20] clutter/stage-view: Only paint redraw clip from
1725f0
 offscreen
1725f0
1725f0
The rest didn't change, so only actually paint the part of the offscreen
1725f0
that was composited as part of the stage painting. In practice, this
1725f0
means that, unless a shadow buffer is used, we now only paint the
1725f0
damaged part of the stage, and copy the damage part of the offscreen to
1725f0
the onscreen.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit acf6b79e3a5b9d8d285886c471961e8c0bec48ce)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view.c | 85 ++++++++++++++++++++++++----
1725f0
 1 file changed, 73 insertions(+), 12 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 080bfd6669..b686272db0 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -19,6 +19,7 @@
1725f0
 
1725f0
 #include "clutter/clutter-stage-view.h"
1725f0
 #include "clutter/clutter-stage-view-private.h"
1725f0
+#include "clutter/clutter-private.h"
1725f0
 
1725f0
 #include <cairo-gobject.h>
1725f0
 #include <math.h>
1725f0
@@ -174,23 +175,81 @@ clutter_stage_view_transform_rect_to_onscreen (ClutterStageView            *view
1725f0
 }
1725f0
 
1725f0
 static void
1725f0
-paint_transformed_framebuffer (ClutterStageView *view,
1725f0
-                               CoglPipeline     *pipeline,
1725f0
-                               CoglFramebuffer  *src_framebuffer,
1725f0
-                               CoglFramebuffer  *dst_framebuffer)
1725f0
+paint_transformed_framebuffer (ClutterStageView            *view,
1725f0
+                               CoglPipeline                *pipeline,
1725f0
+                               CoglFramebuffer             *src_framebuffer,
1725f0
+                               CoglFramebuffer             *dst_framebuffer,
1725f0
+                               const cairo_rectangle_int_t *redraw_clip)
1725f0
 {
1725f0
   CoglMatrix matrix;
1725f0
+  int dst_width, dst_height;
1725f0
+  cairo_rectangle_int_t view_layout;
1725f0
+  cairo_rectangle_int_t onscreen_layout;
1725f0
+  float view_scale;
1725f0
+  float *coordinates;
1725f0
+  cairo_rectangle_int_t src_rect;
1725f0
+  cairo_rectangle_int_t dst_rect;
1725f0
+
1725f0
+  dst_width = cogl_framebuffer_get_width (dst_framebuffer);
1725f0
+  dst_height = cogl_framebuffer_get_height (dst_framebuffer);
1725f0
+  clutter_stage_view_get_layout (view, &view_layout);
1725f0
+  clutter_stage_view_transform_rect_to_onscreen (view,
1725f0
+                                                 &(cairo_rectangle_int_t) {
1725f0
+                                                   .width = view_layout.width,
1725f0
+                                                   .height = view_layout.height,
1725f0
+                                                 },
1725f0
+                                                 view_layout.width,
1725f0
+                                                 view_layout.height,
1725f0
+                                                 &onscreen_layout);
1725f0
+  view_scale = clutter_stage_view_get_scale (view);
1725f0
 
1725f0
   cogl_framebuffer_push_matrix (dst_framebuffer);
1725f0
 
1725f0
   cogl_matrix_init_identity (&matrix);
1725f0
-  cogl_matrix_translate (&matrix, -1, 1, 0);
1725f0
-  cogl_matrix_scale (&matrix, 2, -2, 0);
1725f0
+  cogl_matrix_scale (&matrix,
1725f0
+                     1.0 / (dst_width / 2.0),
1725f0
+                     -1.0 / (dst_height / 2.0), 0);
1725f0
+  cogl_matrix_translate (&matrix,
1725f0
+                         -(dst_width / 2.0),
1725f0
+                         -(dst_height / 2.0), 0);
1725f0
   cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
1725f0
-
1725f0
-  cogl_framebuffer_draw_rectangle (dst_framebuffer,
1725f0
-                                   pipeline,
1725f0
-                                   0, 0, 1, 1);
1725f0
+  cogl_framebuffer_set_viewport (dst_framebuffer,
1725f0
+                                 0, 0, dst_width, dst_height);
1725f0
+
1725f0
+  coordinates = g_newa (float, 2 * 4);
1725f0
+
1725f0
+  src_rect = *redraw_clip;
1725f0
+  _clutter_util_rectangle_offset (&src_rect,
1725f0
+                                  -view_layout.x,
1725f0
+                                  -view_layout.y,
1725f0
+                                  &src_rect);
1725f0
+
1725f0
+  clutter_stage_view_transform_rect_to_onscreen (view,
1725f0
+                                                 &src_rect,
1725f0
+                                                 onscreen_layout.width,
1725f0
+                                                 onscreen_layout.height,
1725f0
+                                                 &dst_rect);
1725f0
+
1725f0
+  coordinates[0] = (float) dst_rect.x * view_scale;
1725f0
+  coordinates[1] = (float) dst_rect.y * view_scale;
1725f0
+  coordinates[2] = ((float) (dst_rect.x + dst_rect.width) *
1725f0
+                    view_scale);
1725f0
+  coordinates[3] = ((float) (dst_rect.y + dst_rect.height) *
1725f0
+                    view_scale);
1725f0
+
1725f0
+  coordinates[4] = (((float) dst_rect.x / (float) dst_width) *
1725f0
+                    view_scale);
1725f0
+  coordinates[5] = (((float) dst_rect.y / (float) dst_height) *
1725f0
+                    view_scale);
1725f0
+  coordinates[6] = ((float) (dst_rect.x + dst_rect.width) /
1725f0
+                    (float) dst_width) * view_scale;
1725f0
+  coordinates[7] = ((float) (dst_rect.y + dst_rect.height) /
1725f0
+                    (float) dst_height) * view_scale;
1725f0
+
1725f0
+  cogl_framebuffer_draw_textured_rectangles (dst_framebuffer,
1725f0
+                                             pipeline,
1725f0
+                                             coordinates,
1725f0
+                                             1);
1725f0
 
1725f0
   cogl_framebuffer_pop_matrix (dst_framebuffer);
1725f0
 }
1725f0
@@ -285,14 +344,16 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
           paint_transformed_framebuffer (view,
1725f0
                                          priv->offscreen_pipeline,
1725f0
                                          priv->offscreen,
1725f0
-                                         priv->shadow.framebuffer);
1725f0
+                                         priv->shadow.framebuffer,
1725f0
+                                         rect);
1725f0
         }
1725f0
       else
1725f0
         {
1725f0
           paint_transformed_framebuffer (view,
1725f0
                                          priv->offscreen_pipeline,
1725f0
                                          priv->offscreen,
1725f0
-                                         priv->framebuffer);
1725f0
+                                         priv->framebuffer,
1725f0
+                                         rect);
1725f0
         }
1725f0
     }
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From ff3164440e6bbb3e845a1d4a23843a5792afc16f Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 13 May 2020 17:18:50 +0200
1725f0
Subject: [PATCH 14/20] clutter/stage-cogl: Only construct damage array if
1725f0
 it'll be used
1725f0
1725f0
It's only used when we actually swap buffers, which we only do if the
1725f0
target framebuffer is an onscreen.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 95a80c442b6300ce5b41b4b3975a372f1eabd166)
1725f0
---
1725f0
 clutter/clutter/cogl/clutter-stage-cogl.c | 22 +++++++++++-----------
1725f0
 1 file changed, 11 insertions(+), 11 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
index 821f78ee7c..fc6d0d031d 100644
1725f0
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
@@ -413,17 +413,6 @@ swap_framebuffer (ClutterStageWindow    *stage_window,
1725f0
                   gboolean               swap_with_damage)
1725f0
 {
1725f0
   CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
1725f0
-  int damage[4], ndamage;
1725f0
-
1725f0
-  damage[0] = swap_region->x;
1725f0
-  damage[1] = swap_region->y;
1725f0
-  damage[2] = swap_region->width;
1725f0
-  damage[3] = swap_region->height;
1725f0
-
1725f0
-  if (swap_region->width != 0)
1725f0
-    ndamage = 1;
1725f0
-  else
1725f0
-    ndamage = 0;
1725f0
 
1725f0
   if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
1725f0
     paint_damage_region (stage_window, view, swap_region);
1725f0
@@ -431,6 +420,17 @@ swap_framebuffer (ClutterStageWindow    *stage_window,
1725f0
   if (cogl_is_onscreen (framebuffer))
1725f0
     {
1725f0
       CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
1725f0
+      int damage[4], ndamage;
1725f0
+
1725f0
+      damage[0] = swap_region->x;
1725f0
+      damage[1] = swap_region->y;
1725f0
+      damage[2] = swap_region->width;
1725f0
+      damage[3] = swap_region->height;
1725f0
+
1725f0
+      if (swap_region->width != 0)
1725f0
+        ndamage = 1;
1725f0
+      else
1725f0
+        ndamage = 0;
1725f0
 
1725f0
       /* push on the screen */
1725f0
       if (ndamage == 1 && !swap_with_damage)
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From f946746f5938e7d6c48b688827fb991f22dc1364 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Tue, 5 May 2020 19:25:23 +0200
1725f0
Subject: [PATCH 15/20] clutter/stage-view: Only blit the damage part of the
1725f0
 shadow buffer
1725f0
1725f0
This fixes the last "copy everything" paths when clutter doesn't
1725f0
directly paint onto the onscreen framebuffer. It adds a new hook into
1725f0
the stage view called before the swap buffer, as at this point, we have
1725f0
the swap buffer damag regions ready, which corresponds to the regions we
1725f0
must blit according to the damage reported to clutter.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 851e7727ec6f3719139ab562ac2524cdc1bd64ae)
1725f0
---
1725f0
 clutter/clutter/clutter-stage-view-private.h |  3 +++
1725f0
 clutter/clutter/clutter-stage-view.c         | 25 ++++++++++++++++++--
1725f0
 clutter/clutter/cogl/clutter-stage-cogl.c    |  2 ++
1725f0
 3 files changed, 28 insertions(+), 2 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
1725f0
index 10f9847b70..bddc38ded6 100644
1725f0
--- a/clutter/clutter/clutter-stage-view-private.h
1725f0
+++ b/clutter/clutter/clutter-stage-view-private.h
1725f0
@@ -23,6 +23,9 @@
1725f0
 void clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
                                         const cairo_rectangle_int_t *clip);
1725f0
 
1725f0
+void clutter_stage_view_before_swap_buffer (ClutterStageView            *view,
1725f0
+                                            const cairo_rectangle_int_t *swap_region);
1725f0
+
1725f0
 gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
1725f0
 
1725f0
 void clutter_stage_view_invalidate_viewport (ClutterStageView *view);
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index b686272db0..21ab02c97b 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -356,11 +356,22 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
                                          rect);
1725f0
         }
1725f0
     }
1725f0
+}
1725f0
+
1725f0
+void
1725f0
+clutter_stage_view_before_swap_buffer (ClutterStageView            *view,
1725f0
+                                       const cairo_rectangle_int_t *swap_region)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  g_autoptr (GError) error = NULL;
1725f0
 
1725f0
-  if (priv->shadow.framebuffer)
1725f0
+  if (!priv->shadow.framebuffer)
1725f0
+    return;
1725f0
+
1725f0
+  if (swap_region->width == 0 || swap_region->height == 0)
1725f0
     {
1725f0
       int width, height;
1725f0
-      g_autoptr (GError) error = NULL;
1725f0
 
1725f0
       width = cogl_framebuffer_get_width (priv->framebuffer);
1725f0
       height = cogl_framebuffer_get_height (priv->framebuffer);
1725f0
@@ -370,6 +381,16 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
                                   0, 0,
1725f0
                                   width, height,
1725f0
                                   &error))
1725f0
+        g_warning ("Failed to blit shadow buffer: %s", error->message);
1725f0
+    }
1725f0
+  else
1725f0
+    {
1725f0
+      if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
1725f0
+                                  priv->framebuffer,
1725f0
+                                  swap_region->x, swap_region->y,
1725f0
+                                  swap_region->x, swap_region->y,
1725f0
+                                  swap_region->width, swap_region->height,
1725f0
+                                  &error))
1725f0
         {
1725f0
           g_warning ("Failed to blit shadow buffer: %s", error->message);
1725f0
           return;
1725f0
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
index fc6d0d031d..884819ebd3 100644
1725f0
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
@@ -417,6 +417,8 @@ swap_framebuffer (ClutterStageWindow    *stage_window,
1725f0
   if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
1725f0
     paint_damage_region (stage_window, view, swap_region);
1725f0
 
1725f0
+  clutter_stage_view_before_swap_buffer (view, swap_region);
1725f0
+
1725f0
   if (cogl_is_onscreen (framebuffer))
1725f0
     {
1725f0
       CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 757dd09dc9b76a7654f087679db1c7f005b7653c Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 6 May 2020 09:11:34 +0200
1725f0
Subject: [PATCH 16/20] clutter/stage-cogl: Extract damage history logic
1725f0
1725f0
Move the damage history tracking to a new ClutterDamageHistory helper
1725f0
type. The aim is to be able to track damage history elsewhere without
1725f0
reimplementing the data structure and tracking logic.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 09271bcfef8889022f15a3b2949843e55f3df9da)
1725f0
---
1725f0
 clutter/clutter/clutter-damage-history.c  |  89 +++++++++++++++++
1725f0
 clutter/clutter/clutter-damage-history.h  |  42 ++++++++
1725f0
 clutter/clutter/cogl/clutter-stage-cogl.c | 116 ++++++++++++----------
1725f0
 clutter/clutter/meson.build               |   2 +
1725f0
 4 files changed, 195 insertions(+), 54 deletions(-)
1725f0
 create mode 100644 clutter/clutter/clutter-damage-history.c
1725f0
 create mode 100644 clutter/clutter/clutter-damage-history.h
1725f0
1725f0
diff --git a/clutter/clutter/clutter-damage-history.c b/clutter/clutter/clutter-damage-history.c
1725f0
new file mode 100644
1725f0
index 0000000000..78ab0f7b5e
1725f0
--- /dev/null
1725f0
+++ b/clutter/clutter/clutter-damage-history.c
1725f0
@@ -0,0 +1,89 @@
1725f0
+/*
1725f0
+ * Copyright (C) 2007,2008,2009,2010,2011  Intel Corporation.
1725f0
+ * Copyright (C) 2020 Red Hat Inc
1725f0
+ *
1725f0
+ * This library is free software; you can redistribute it and/or
1725f0
+ * modify it under the terms of the GNU Lesser General Public
1725f0
+ * License as published by the Free Software Foundation; either
1725f0
+ * version 2 of the License, or (at your option) any later version.
1725f0
+ *
1725f0
+ * This library is distributed in the hope that it will be useful,
1725f0
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1725f0
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1725f0
+ * Lesser General Public License for more details.
1725f0
+ *
1725f0
+ * You should have received a copy of the GNU Lesser General Public
1725f0
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
1725f0
+ */
1725f0
+
1725f0
+#include "clutter-build-config.h"
1725f0
+
1725f0
+#include "clutter-damage-history.h"
1725f0
+
1725f0
+#define DAMAGE_HISTORY_LENGTH 0x10
1725f0
+
1725f0
+struct _ClutterDamageHistory
1725f0
+{
1725f0
+  cairo_rectangle_int_t damages[DAMAGE_HISTORY_LENGTH];
1725f0
+  int index;
1725f0
+};
1725f0
+
1725f0
+ClutterDamageHistory *
1725f0
+clutter_damage_history_new (void)
1725f0
+{
1725f0
+  ClutterDamageHistory *history;
1725f0
+
1725f0
+  history = g_new0 (ClutterDamageHistory, 1);
1725f0
+
1725f0
+  return history;
1725f0
+}
1725f0
+
1725f0
+void
1725f0
+clutter_damage_history_free (ClutterDamageHistory *history)
1725f0
+{
1725f0
+  g_free (history);
1725f0
+}
1725f0
+
1725f0
+gboolean
1725f0
+clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
1725f0
+                                     int                   age)
1725f0
+{
1725f0
+  const cairo_rectangle_int_t *damage;
1725f0
+
1725f0
+  if (age >= DAMAGE_HISTORY_LENGTH ||
1725f0
+      age < 1)
1725f0
+    return FALSE;
1725f0
+
1725f0
+  damage = clutter_damage_history_lookup (history, age);
1725f0
+  if (damage->width == 0 || damage->height == 0)
1725f0
+    return FALSE;
1725f0
+
1725f0
+  return TRUE;
1725f0
+}
1725f0
+
1725f0
+void
1725f0
+clutter_damage_history_record (ClutterDamageHistory        *history,
1725f0
+                               const cairo_rectangle_int_t *damage)
1725f0
+{
1725f0
+  history->damages[history->index] = *damage;
1725f0
+}
1725f0
+
1725f0
+static inline int
1725f0
+step_damage_index (int current,
1725f0
+                   int diff)
1725f0
+{
1725f0
+  return (current + diff) & (DAMAGE_HISTORY_LENGTH - 1);
1725f0
+}
1725f0
+
1725f0
+void
1725f0
+clutter_damage_history_step (ClutterDamageHistory *history)
1725f0
+{
1725f0
+  history->index = step_damage_index (history->index, 1);
1725f0
+}
1725f0
+
1725f0
+const cairo_rectangle_int_t *
1725f0
+clutter_damage_history_lookup (ClutterDamageHistory *history,
1725f0
+                               int                   age)
1725f0
+{
1725f0
+  return &history->damages[step_damage_index (history->index, -age)];
1725f0
+}
1725f0
diff --git a/clutter/clutter/clutter-damage-history.h b/clutter/clutter/clutter-damage-history.h
1725f0
new file mode 100644
1725f0
index 0000000000..6c483acab7
1725f0
--- /dev/null
1725f0
+++ b/clutter/clutter/clutter-damage-history.h
1725f0
@@ -0,0 +1,42 @@
1725f0
+/*
1725f0
+ * Copyright (C) 2007,2008,2009,2010,2011  Intel Corporation.
1725f0
+ * Copyright (C) 2020 Red Hat Inc
1725f0
+ *
1725f0
+ * This library is free software; you can redistribute it and/or
1725f0
+ * modify it under the terms of the GNU Lesser General Public
1725f0
+ * License as published by the Free Software Foundation; either
1725f0
+ * version 2 of the License, or (at your option) any later version.
1725f0
+ *
1725f0
+ * This library is distributed in the hope that it will be useful,
1725f0
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1725f0
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1725f0
+ * Lesser General Public License for more details.
1725f0
+ *
1725f0
+ * You should have received a copy of the GNU Lesser General Public
1725f0
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
1725f0
+ */
1725f0
+
1725f0
+#ifndef CLUTTER_DAMAGE_HISTORY_H
1725f0
+#define CLUTTER_DAMAGE_HISTORY_H
1725f0
+
1725f0
+#include <cairo.h>
1725f0
+#include <glib.h>
1725f0
+
1725f0
+typedef struct _ClutterDamageHistory ClutterDamageHistory;
1725f0
+
1725f0
+ClutterDamageHistory * clutter_damage_history_new (void);
1725f0
+
1725f0
+void clutter_damage_history_free (ClutterDamageHistory *history);
1725f0
+
1725f0
+gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
1725f0
+                                              int                   age);
1725f0
+
1725f0
+void clutter_damage_history_record (ClutterDamageHistory        *history,
1725f0
+                                    const cairo_rectangle_int_t *damage);
1725f0
+
1725f0
+void clutter_damage_history_step (ClutterDamageHistory *history);
1725f0
+
1725f0
+const cairo_rectangle_int_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
1725f0
+                                                             int                   age);
1725f0
+
1725f0
+#endif /* CLUTTER_DAMAGE_HISTORY_H */
1725f0
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
index 884819ebd3..11273ec894 100644
1725f0
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
@@ -38,6 +38,7 @@
1725f0
 
1725f0
 #include "clutter-actor-private.h"
1725f0
 #include "clutter-backend-private.h"
1725f0
+#include "clutter-damage-history.h"
1725f0
 #include "clutter-debug.h"
1725f0
 #include "clutter-event.h"
1725f0
 #include "clutter-enum-types.h"
1725f0
@@ -49,13 +50,9 @@
1725f0
 
1725f0
 typedef struct _ClutterStageViewCoglPrivate
1725f0
 {
1725f0
-  /*
1725f0
-   * List of previous damaged areas in stage view framebuffer coordinate space.
1725f0
+  /* Damage history, in stage view render target framebuffer coordinate space.
1725f0
    */
1725f0
-#define DAMAGE_HISTORY_MAX 16
1725f0
-#define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1))
1725f0
-  cairo_rectangle_int_t damage_history[DAMAGE_HISTORY_MAX];
1725f0
-  unsigned int damage_index;
1725f0
+  ClutterDamageHistory *damage_history;
1725f0
 } ClutterStageViewCoglPrivate;
1725f0
 
1725f0
 G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl,
1725f0
@@ -348,10 +345,7 @@ valid_buffer_age (ClutterStageViewCogl *view_cogl,
1725f0
   ClutterStageViewCoglPrivate *view_priv =
1725f0
     clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
 
1725f0
-  if (age <= 0)
1725f0
-    return FALSE;
1725f0
-
1725f0
-  return age < MIN (view_priv->damage_index, DAMAGE_HISTORY_MAX);
1725f0
+  return clutter_damage_history_is_age_valid (view_priv->damage_history, age);
1725f0
 }
1725f0
 
1725f0
 static void
1725f0
@@ -483,30 +477,6 @@ paint_stage (ClutterStageCogl            *stage_cogl,
1725f0
   clutter_stage_view_blit_offscreen (view, clip);
1725f0
 }
1725f0
 
1725f0
-static void
1725f0
-fill_current_damage_history_and_step (ClutterStageView *view)
1725f0
-{
1725f0
-  ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
1725f0
-  ClutterStageViewCoglPrivate *view_priv =
1725f0
-    clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
-  cairo_rectangle_int_t view_rect;
1725f0
-  float fb_scale;
1725f0
-  cairo_rectangle_int_t *current_fb_damage;
1725f0
-
1725f0
-  current_fb_damage =
1725f0
-    &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)];
1725f0
-  clutter_stage_view_get_layout (view, &view_rect);
1725f0
-  fb_scale = clutter_stage_view_get_scale (view);
1725f0
-
1725f0
-  *current_fb_damage = (cairo_rectangle_int_t) {
1725f0
-    .x = 0,
1725f0
-    .y = 0,
1725f0
-    .width = view_rect.width * fb_scale,
1725f0
-    .height = view_rect.height * fb_scale
1725f0
-  };
1725f0
-  view_priv->damage_index++;
1725f0
-}
1725f0
-
1725f0
 static void
1725f0
 transform_swap_region_to_onscreen (ClutterStageView      *view,
1725f0
                                    cairo_rectangle_int_t *swap_region)
1725f0
@@ -567,6 +537,24 @@ scale_and_clamp_rect (const ClutterRect     *rect,
1725f0
   _clutter_util_rectangle_int_extents (&tmp, dest);
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+record_full_damage (ClutterStageView *view)
1725f0
+{
1725f0
+  ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
1725f0
+  ClutterStageViewCoglPrivate *view_priv =
1725f0
+    clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
+  CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
1725f0
+  int fb_width, fb_height;
1725f0
+
1725f0
+  fb_width = cogl_framebuffer_get_width (fb);
1725f0
+  fb_height = cogl_framebuffer_get_height (fb);
1725f0
+  clutter_damage_history_record (view_priv->damage_history,
1725f0
+                                 &(cairo_rectangle_int_t) {
1725f0
+                                   .width = fb_width,
1725f0
+                                   .height = fb_height
1725f0
+                                 });
1725f0
+}
1725f0
+
1725f0
 static gboolean
1725f0
 clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
                                 ClutterStageView   *view)
1725f0
@@ -666,9 +654,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
     {
1725f0
       if (use_clipped_redraw && !clip_region_empty)
1725f0
         {
1725f0
-          int age, i;
1725f0
-          cairo_rectangle_int_t *current_fb_damage =
1725f0
-            &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)];
1725f0
+          int age;
1725f0
 
1725f0
           age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen));
1725f0
 
1725f0
@@ -676,16 +662,20 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
             {
1725f0
               ClutterRect rect;
1725f0
               cairo_rectangle_int_t damage_region;
1725f0
+              int i;
1725f0
 
1725f0
-              *current_fb_damage = fb_clip_region;
1725f0
+              clutter_damage_history_record (view_priv->damage_history,
1725f0
+                                             &fb_clip_region);
1725f0
 
1725f0
               for (i = 1; i <= age; i++)
1725f0
                 {
1725f0
-                  cairo_rectangle_int_t *fb_damage =
1725f0
-                    &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
1725f0
+                  const cairo_rectangle_int_t *old_damage;
1725f0
+
1725f0
+                  old_damage =
1725f0
+                    clutter_damage_history_lookup (view_priv->damage_history, i);
1725f0
 
1725f0
                   _clutter_util_rectangle_union (&fb_clip_region,
1725f0
-                                                 fb_damage,
1725f0
+                                                 old_damage,
1725f0
                                                  &fb_clip_region);
1725f0
                 }
1725f0
 
1725f0
@@ -713,18 +703,15 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
1725f0
             {
1725f0
               CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age);
1725f0
               use_clipped_redraw = FALSE;
1725f0
-              *current_fb_damage = (cairo_rectangle_int_t) {
1725f0
-                .x = 0,
1725f0
-                .y = 0,
1725f0
-                .width = view_rect.width * fb_scale,
1725f0
-                .height = view_rect.height * fb_scale
1725f0
-              };
1725f0
+              record_full_damage (view);
1725f0
             }
1725f0
         }
1725f0
       else if (!use_clipped_redraw)
1725f0
         {
1725f0
-          fill_current_damage_history_and_step (view);
1725f0
+          record_full_damage (view);
1725f0
         }
1725f0
+
1725f0
+      clutter_damage_history_step (view_priv->damage_history);
1725f0
     }
1725f0
 
1725f0
   cogl_push_framebuffer (fb);
1725f0
@@ -946,6 +933,9 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
1725f0
                                     int                *y)
1725f0
 {
1725f0
   CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
1725f0
+  ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
1725f0
+  ClutterStageViewCoglPrivate *view_priv =
1725f0
+    clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
   gboolean has_buffer_age =
1725f0
     cogl_is_onscreen (onscreen) &&
1725f0
     is_buffer_age_enabled ();
1725f0
@@ -967,22 +957,21 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
1725f0
    * For now, always use the (0, 0) pixel for picking when using fractional
1725f0
    * framebuffer scaling.
1725f0
    */
1725f0
-  if (!has_buffer_age || scale_is_fractional)
1725f0
+  if (!has_buffer_age ||
1725f0
+      scale_is_fractional ||
1725f0
+      !clutter_damage_history_is_age_valid (view_priv->damage_history, 0))
1725f0
     {
1725f0
       *x = 0;
1725f0
       *y = 0;
1725f0
     }
1725f0
   else
1725f0
     {
1725f0
-      ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
1725f0
-      ClutterStageViewCoglPrivate *view_priv =
1725f0
-        clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
       cairo_rectangle_int_t view_layout;
1725f0
-      cairo_rectangle_int_t *fb_damage;
1725f0
+      const cairo_rectangle_int_t *fb_damage;
1725f0
 
1725f0
       clutter_stage_view_get_layout (view, &view_layout);
1725f0
 
1725f0
-      fb_damage = &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)];
1725f0
+      fb_damage = clutter_damage_history_lookup (view_priv->damage_history, 0);
1725f0
       *x = fb_damage->x / fb_scale;
1725f0
       *y = fb_damage->y / fb_scale;
1725f0
     }
1725f0
@@ -1052,12 +1041,31 @@ _clutter_stage_cogl_init (ClutterStageCogl *stage)
1725f0
   stage->update_time = -1;
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+clutter_stage_view_cogl_finalize (GObject *object)
1725f0
+{
1725f0
+  ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (object);
1725f0
+  ClutterStageViewCoglPrivate *view_priv =
1725f0
+    clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
+
1725f0
+  clutter_damage_history_free (view_priv->damage_history);
1725f0
+
1725f0
+  G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->finalize (object);
1725f0
+}
1725f0
+
1725f0
 static void
1725f0
 clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl)
1725f0
 {
1725f0
+  ClutterStageViewCoglPrivate *view_priv =
1725f0
+    clutter_stage_view_cogl_get_instance_private (view_cogl);
1725f0
+
1725f0
+  view_priv->damage_history = clutter_damage_history_new ();
1725f0
 }
1725f0
 
1725f0
 static void
1725f0
 clutter_stage_view_cogl_class_init (ClutterStageViewCoglClass *klass)
1725f0
 {
1725f0
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
1725f0
+
1725f0
+  object_class->finalize = clutter_stage_view_cogl_finalize;
1725f0
 }
1725f0
diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build
1725f0
index 8e0484453d..c9eab96d29 100644
1725f0
--- a/clutter/clutter/meson.build
1725f0
+++ b/clutter/clutter/meson.build
1725f0
@@ -116,6 +116,7 @@ clutter_sources = [
1725f0
   'clutter-constraint.c',
1725f0
   'clutter-container.c',
1725f0
   'clutter-content.c',
1725f0
+  'clutter-damage-history.c',
1725f0
   'clutter-deform-effect.c',
1725f0
   'clutter-desaturate-effect.c',
1725f0
   'clutter-device-manager.c',
1725f0
@@ -186,6 +187,7 @@ clutter_private_headers = [
1725f0
   'clutter-bezier.h',
1725f0
   'clutter-constraint-private.h',
1725f0
   'clutter-content-private.h',
1725f0
+  'clutter-damage-history.h',
1725f0
   'clutter-debug.h',
1725f0
   'clutter-device-manager-private.h',
1725f0
   'clutter-easing.h',
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 5da1c8083784a351a7763a0c9a9ce4c8359522a4 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 6 May 2020 21:40:40 +0200
1725f0
Subject: [PATCH 17/20] cogl/dma-buf: Add API to synchronize reading
1725f0
1725f0
Used before and after accessing DMA buffer content using mmap().
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 2d972fc761b9e39f78e66dd84eab57309cdc8658)
1725f0
---
1725f0
 cogl/cogl/cogl-dma-buf-handle.c | 51 +++++++++++++++++++++++++++++++++
1725f0
 cogl/cogl/cogl-dma-buf-handle.h |  8 ++++++
1725f0
 cogl/meson.build                |  1 +
1725f0
 3 files changed, 60 insertions(+)
1725f0
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.c b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
index d8b4e57c55..7e86e2267b 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.c
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
@@ -34,6 +34,10 @@
1725f0
 #include "cogl-dma-buf-handle.h"
1725f0
 #include "cogl-object.h"
1725f0
 
1725f0
+#include <errno.h>
1725f0
+#include <gio/gio.h>
1725f0
+#include <linux/dma-buf.h>
1725f0
+#include <sys/ioctl.h>
1725f0
 #include <unistd.h>
1725f0
 
1725f0
 struct _CoglDmaBufHandle
1725f0
@@ -96,6 +100,53 @@ cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle)
1725f0
   g_free (dmabuf_handle);
1725f0
 }
1725f0
 
1725f0
+static gboolean
1725f0
+sync_read (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+           uint64_t           start_or_end,
1725f0
+           GError           **error)
1725f0
+{
1725f0
+  struct dma_buf_sync sync = { 0 };
1725f0
+
1725f0
+  sync.flags = start_or_end | DMA_BUF_SYNC_READ;
1725f0
+
1725f0
+  while (TRUE)
1725f0
+    {
1725f0
+      int ret;
1725f0
+
1725f0
+      ret = ioctl (dmabuf_handle->dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync);
1725f0
+      if (ret == -1 && errno == EINTR)
1725f0
+        {
1725f0
+          continue;
1725f0
+        }
1725f0
+      else if (ret == -1)
1725f0
+        {
1725f0
+          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
1725f0
+                       "ioctl: %s", g_strerror (errno));
1725f0
+          return FALSE;
1725f0
+        }
1725f0
+      else
1725f0
+        {
1725f0
+          break;
1725f0
+        }
1725f0
+    }
1725f0
+
1725f0
+  return TRUE;
1725f0
+}
1725f0
+
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_sync_read_start (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                                     GError           **error)
1725f0
+{
1725f0
+  return sync_read (dmabuf_handle, DMA_BUF_SYNC_START, error);
1725f0
+}
1725f0
+
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                                   GError           **error)
1725f0
+{
1725f0
+  return sync_read (dmabuf_handle, DMA_BUF_SYNC_END, error);
1725f0
+}
1725f0
+
1725f0
 CoglFramebuffer *
1725f0
 cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle)
1725f0
 {
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.h b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
index f64a20678d..63c5bab7b7 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.h
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
@@ -63,6 +63,14 @@ cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
1725f0
 void
1725f0
 cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle);
1725f0
 
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_sync_read_start (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                                     GError           **error);
1725f0
+
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                                   GError           **error);
1725f0
+
1725f0
 /**
1725f0
  * cogl_dma_buf_handle_get_framebuffer: (skip)
1725f0
  *
1725f0
diff --git a/cogl/meson.build b/cogl/meson.build
1725f0
index 356d596f56..47e6a3e0da 100644
1725f0
--- a/cogl/meson.build
1725f0
+++ b/cogl/meson.build
1725f0
@@ -23,6 +23,7 @@ cogl_mutter_config_h = configure_file(
1725f0
 
1725f0
 cogl_pkg_deps = [
1725f0
   glib_dep,
1725f0
+  gio_dep,
1725f0
   gobject_dep,
1725f0
 ]
1725f0
 
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 360a397c19046c6a914ee27e3e5104da3ad0c1c6 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 6 May 2020 22:12:46 +0200
1725f0
Subject: [PATCH 18/20] cogl/dma-buf: Add mmap/munmap helpers
1725f0
1725f0
Avoids dealing directly with mmap() and munmap().
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit e05a1a6c0b2526146c85ec9c381bb2b49d19b4b2)
1725f0
---
1725f0
 cogl/cogl/cogl-dma-buf-handle.c | 41 +++++++++++++++++++++++++++++++++
1725f0
 cogl/cogl/cogl-dma-buf-handle.h |  9 ++++++++
1725f0
 2 files changed, 50 insertions(+)
1725f0
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.c b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
index 7e86e2267b..9724ac9c95 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.c
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.c
1725f0
@@ -38,6 +38,7 @@
1725f0
 #include <gio/gio.h>
1725f0
 #include <linux/dma-buf.h>
1725f0
 #include <sys/ioctl.h>
1725f0
+#include <sys/mman.h>
1725f0
 #include <unistd.h>
1725f0
 
1725f0
 struct _CoglDmaBufHandle
1725f0
@@ -147,6 +148,46 @@ cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle  *dmabuf_handle,
1725f0
   return sync_read (dmabuf_handle, DMA_BUF_SYNC_END, error);
1725f0
 }
1725f0
 
1725f0
+gpointer
1725f0
+cogl_dma_buf_handle_mmap (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                          GError           **error)
1725f0
+{
1725f0
+  size_t size;
1725f0
+  gpointer data;
1725f0
+
1725f0
+  size = dmabuf_handle->height * dmabuf_handle->stride;
1725f0
+
1725f0
+  data = mmap (NULL, size, PROT_READ, MAP_PRIVATE,
1725f0
+               dmabuf_handle->dmabuf_fd,
1725f0
+               dmabuf_handle->offset);
1725f0
+  if (data == MAP_FAILED)
1725f0
+    {
1725f0
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
1725f0
+                   "mmap failed: %s", g_strerror (errno));
1725f0
+      return NULL;
1725f0
+    }
1725f0
+
1725f0
+  return data;
1725f0
+}
1725f0
+
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_munmap (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                            gpointer           data,
1725f0
+                            GError           **error)
1725f0
+{
1725f0
+  size_t size;
1725f0
+
1725f0
+  size = dmabuf_handle->height * dmabuf_handle->stride;
1725f0
+  if (munmap (data, size) != 0)
1725f0
+    {
1725f0
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
1725f0
+                   "munmap failed: %s", g_strerror (errno));
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  return TRUE;
1725f0
+}
1725f0
+
1725f0
 CoglFramebuffer *
1725f0
 cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle)
1725f0
 {
1725f0
diff --git a/cogl/cogl/cogl-dma-buf-handle.h b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
index 63c5bab7b7..08f307c1db 100644
1725f0
--- a/cogl/cogl/cogl-dma-buf-handle.h
1725f0
+++ b/cogl/cogl/cogl-dma-buf-handle.h
1725f0
@@ -71,6 +71,15 @@ gboolean
1725f0
 cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle  *dmabuf_handle,
1725f0
                                    GError           **error);
1725f0
 
1725f0
+gpointer
1725f0
+cogl_dma_buf_handle_mmap (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                          GError           **error);
1725f0
+
1725f0
+gboolean
1725f0
+cogl_dma_buf_handle_munmap (CoglDmaBufHandle  *dmabuf_handle,
1725f0
+                            gpointer           data,
1725f0
+                            GError           **error);
1725f0
+
1725f0
 /**
1725f0
  * cogl_dma_buf_handle_get_framebuffer: (skip)
1725f0
  *
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From ff8a80137047a91ed27d90467b004d691428bac4 Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1725f0
Date: Wed, 6 May 2020 22:14:17 +0200
1725f0
Subject: [PATCH 19/20] clutter/stage-view: Add tile based shadow damage
1725f0
 detection
1725f0
1725f0
Compare, tile by tile, whether actual damage actually changed any
1725f0
pixels. While this requires mmap():ing DMA buffers and comparing their
1725f0
content, we should only ever use shadow buffers when we're using the
1725f0
software renderer, meaning mmap() is cheap as it doesn't involve any
1725f0
downloading.
1725f0
1725f0
This works by making the shadow framebuffer double buffered, while
1725f0
keeping track of damage history. When we're about to swap the onscreen
1725f0
buffer, we compare what part of the posted damage actually changed,
1725f0
records that into a damage history, then given the onscreen buffer age,
1725f0
collect all actual damage for that age. The intersection of these tiles,
1725f0
and the actual damage, is then used when blitting the shadow buffer to
1725f0
the onscreen framebuffer.
1725f0
1725f0
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1157
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 068385df3a0cf545e5110378b59db56cbd1bdef3)
1725f0
---
1725f0
 clutter/clutter/clutter-private.h    |   3 +
1725f0
 clutter/clutter/clutter-stage-view.c | 472 +++++++++++++++++++++++++--
1725f0
 clutter/clutter/clutter-util.c       |  22 ++
1725f0
 3 files changed, 465 insertions(+), 32 deletions(-)
1725f0
1725f0
diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h
1725f0
index a5cd1fa197..5a0fed85c9 100644
1725f0
--- a/clutter/clutter/clutter-private.h
1725f0
+++ b/clutter/clutter/clutter-private.h
1725f0
@@ -265,6 +265,9 @@ gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1
1725f0
                                                const cairo_rectangle_int_t *src2,
1725f0
                                                cairo_rectangle_int_t       *dest);
1725f0
 
1725f0
+gboolean _clutter_util_rectangle_contains (const cairo_rectangle_int_t *src1,
1725f0
+                                           const cairo_rectangle_int_t *src2);
1725f0
+
1725f0
 
1725f0
 struct _ClutterVertex4
1725f0
 {
1725f0
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
1725f0
index 21ab02c97b..5e5966d06e 100644
1725f0
--- a/clutter/clutter/clutter-stage-view.c
1725f0
+++ b/clutter/clutter/clutter-stage-view.c
1725f0
@@ -17,6 +17,7 @@
1725f0
 
1725f0
 #include "clutter-build-config.h"
1725f0
 
1725f0
+#include "clutter/clutter-damage-history.h"
1725f0
 #include "clutter/clutter-stage-view.h"
1725f0
 #include "clutter/clutter-stage-view-private.h"
1725f0
 #include "clutter/clutter-private.h"
1725f0
@@ -53,6 +54,12 @@ typedef struct _ClutterStageViewPrivate
1725f0
 
1725f0
   gboolean use_shadowfb;
1725f0
   struct {
1725f0
+    struct {
1725f0
+      CoglDmaBufHandle *handles[2];
1725f0
+      int current_idx;
1725f0
+      ClutterDamageHistory *damage_history;
1725f0
+    } dma_buf;
1725f0
+
1725f0
     CoglOffscreen *framebuffer;
1725f0
   } shadow;
1725f0
 
1725f0
@@ -254,6 +261,66 @@ paint_transformed_framebuffer (ClutterStageView            *view,
1725f0
   cogl_framebuffer_pop_matrix (dst_framebuffer);
1725f0
 }
1725f0
 
1725f0
+static gboolean
1725f0
+is_shadowfb_double_buffered (ClutterStageView *view)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+
1725f0
+  return priv->shadow.dma_buf.handles[0] && priv->shadow.dma_buf.handles[1];
1725f0
+}
1725f0
+
1725f0
+static gboolean
1725f0
+init_dma_buf_shadowfbs (ClutterStageView  *view,
1725f0
+                        CoglContext       *cogl_context,
1725f0
+                        int                width,
1725f0
+                        int                height,
1725f0
+                        GError           **error)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
1725f0
+  CoglFramebuffer *initial_shadowfb;
1725f0
+
1725f0
+  if (!cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE))
1725f0
+    {
1725f0
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1725f0
+                   "Buffer age not supported");
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  if (!cogl_is_onscreen (priv->framebuffer))
1725f0
+    {
1725f0
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1725f0
+                   "Tried to use shadow buffer without onscreen");
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  priv->shadow.dma_buf.handles[0] = cogl_renderer_create_dma_buf (cogl_renderer,
1725f0
+                                                                  width, height,
1725f0
+                                                                  error);
1725f0
+  if (!priv->shadow.dma_buf.handles[0])
1725f0
+    return FALSE;
1725f0
+
1725f0
+  priv->shadow.dma_buf.handles[1] = cogl_renderer_create_dma_buf (cogl_renderer,
1725f0
+                                                                  width, height,
1725f0
+                                                                  error);
1725f0
+  if (!priv->shadow.dma_buf.handles[1])
1725f0
+    {
1725f0
+      g_clear_pointer (&priv->shadow.dma_buf.handles[0],
1725f0
+                       cogl_dma_buf_handle_free);
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+
1725f0
+  priv->shadow.dma_buf.damage_history = clutter_damage_history_new ();
1725f0
+
1725f0
+  initial_shadowfb =
1725f0
+    cogl_dma_buf_handle_get_framebuffer (priv->shadow.dma_buf.handles[0]);
1725f0
+  priv->shadow.framebuffer = cogl_object_ref (initial_shadowfb);
1725f0
+
1725f0
+  return TRUE;
1725f0
+}
1725f0
+
1725f0
 static CoglOffscreen *
1725f0
 create_offscreen_framebuffer (CoglContext  *context,
1725f0
                               int           width,
1725f0
@@ -285,11 +352,11 @@ create_offscreen_framebuffer (CoglContext  *context,
1725f0
 }
1725f0
 
1725f0
 static gboolean
1725f0
-init_offscreen_shadowfb (ClutterStageView  *view,
1725f0
-                         CoglContext       *cogl_context,
1725f0
-                         int                width,
1725f0
-                         int                height,
1725f0
-                         GError           **error)
1725f0
+init_fallback_shadowfb (ClutterStageView  *view,
1725f0
+                        CoglContext       *cogl_context,
1725f0
+                        int                width,
1725f0
+                        int                height,
1725f0
+                        GError           **error)
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
@@ -317,7 +384,17 @@ init_shadowfb (ClutterStageView *view)
1725f0
   height = cogl_framebuffer_get_height (priv->framebuffer);
1725f0
   cogl_context = cogl_framebuffer_get_context (priv->framebuffer);
1725f0
 
1725f0
-  if (!init_offscreen_shadowfb (view, cogl_context, width, height, &error))
1725f0
+  if (init_dma_buf_shadowfbs (view, cogl_context, width, height, &error))
1725f0
+    {
1725f0
+      g_message ("Initialized double buffered shadow fb for %s", priv->name);
1725f0
+      return;
1725f0
+    }
1725f0
+
1725f0
+  g_warning ("Failed to initialize double buffered shadow fb for %s: %s",
1725f0
+             priv->name, error->message);
1725f0
+  g_clear_error (&error);
1725f0
+
1725f0
+  if (!init_fallback_shadowfb (view, cogl_context, width, height, &error))
1725f0
     {
1725f0
       g_warning ("Failed to initialize single buffered shadow fb for %s: %s",
1725f0
                  priv->name, error->message);
1725f0
@@ -358,44 +435,298 @@ clutter_stage_view_blit_offscreen (ClutterStageView            *view,
1725f0
     }
1725f0
 }
1725f0
 
1725f0
-void
1725f0
-clutter_stage_view_before_swap_buffer (ClutterStageView            *view,
1725f0
-                                       const cairo_rectangle_int_t *swap_region)
1725f0
+static gboolean
1725f0
+is_tile_dirty (cairo_rectangle_int_t *tile,
1725f0
+               uint8_t               *current_data,
1725f0
+               uint8_t               *prev_data,
1725f0
+               int                    bpp,
1725f0
+               int                    stride)
1725f0
+{
1725f0
+  int y;
1725f0
+
1725f0
+  for (y = tile->y; y < tile->y + tile->height; y++)
1725f0
+    {
1725f0
+      if (memcmp (prev_data + y * stride + tile->x * bpp,
1725f0
+                  current_data + y * stride + tile->x * bpp,
1725f0
+                  tile->width * bpp) != 0)
1725f0
+        return TRUE;
1725f0
+    }
1725f0
+
1725f0
+  return FALSE;
1725f0
+}
1725f0
+
1725f0
+static int
1725f0
+flip_dma_buf_idx (int idx)
1725f0
+{
1725f0
+  return (idx + 1) % 2;
1725f0
+}
1725f0
+
1725f0
+static cairo_region_t *
1725f0
+find_damaged_tiles (ClutterStageView      *view,
1725f0
+                    const cairo_region_t  *damage_region,
1725f0
+                    GError               **error)
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
-  g_autoptr (GError) error = NULL;
1725f0
+  cairo_region_t *tile_damage_region;
1725f0
+  cairo_rectangle_int_t damage_extents;
1725f0
+  cairo_rectangle_int_t fb_rect;
1725f0
+  int prev_dma_buf_idx;
1725f0
+  CoglDmaBufHandle *prev_dma_buf_handle;
1725f0
+  uint8_t *prev_data;
1725f0
+  int current_dma_buf_idx;
1725f0
+  CoglDmaBufHandle *current_dma_buf_handle;
1725f0
+  uint8_t *current_data;
1725f0
+  int width, height, stride, bpp;
1725f0
+  int tile_x_min, tile_x_max;
1725f0
+  int tile_y_min, tile_y_max;
1725f0
+  int tile_x, tile_y;
1725f0
+  const int tile_size = 16;
1725f0
+
1725f0
+  prev_dma_buf_idx = flip_dma_buf_idx (priv->shadow.dma_buf.current_idx);
1725f0
+  prev_dma_buf_handle = priv->shadow.dma_buf.handles[prev_dma_buf_idx];
1725f0
+
1725f0
+  current_dma_buf_idx = priv->shadow.dma_buf.current_idx;
1725f0
+  current_dma_buf_handle = priv->shadow.dma_buf.handles[current_dma_buf_idx];
1725f0
+
1725f0
+  width = cogl_dma_buf_handle_get_width (current_dma_buf_handle);
1725f0
+  height = cogl_dma_buf_handle_get_height (current_dma_buf_handle);
1725f0
+  stride = cogl_dma_buf_handle_get_stride (current_dma_buf_handle);
1725f0
+  bpp = cogl_dma_buf_handle_get_bpp (current_dma_buf_handle);
1725f0
+
1725f0
+  cogl_framebuffer_finish (priv->shadow.framebuffer);
1725f0
+
1725f0
+  if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error))
1725f0
+    return NULL;
1725f0
+
1725f0
+  if (!cogl_dma_buf_handle_sync_read_start (current_dma_buf_handle, error))
1725f0
+    goto err_sync_read_current;
1725f0
+
1725f0
+  prev_data = cogl_dma_buf_handle_mmap (prev_dma_buf_handle, error);
1725f0
+  if (!prev_data)
1725f0
+    goto err_mmap_prev;
1725f0
+  current_data = cogl_dma_buf_handle_mmap (current_dma_buf_handle, error);
1725f0
+  if (!current_data)
1725f0
+    goto err_mmap_current;
1725f0
+
1725f0
+  fb_rect = (cairo_rectangle_int_t) {
1725f0
+    .width = width,
1725f0
+    .height = height,
1725f0
+  };
1725f0
+
1725f0
+  cairo_region_get_extents (damage_region, &damage_extents);
1725f0
+
1725f0
+  tile_x_min = damage_extents.x / tile_size;
1725f0
+  tile_x_max = ((damage_extents.x + damage_extents.width + tile_size - 1) /
1725f0
+                tile_size);
1725f0
+  tile_y_min = damage_extents.y / tile_size;
1725f0
+  tile_y_max = ((damage_extents.y + damage_extents.height + tile_size - 1) /
1725f0
+                tile_size);
1725f0
+
1725f0
+  tile_damage_region = cairo_region_create ();
1725f0
+
1725f0
+  for (tile_y = tile_y_min; tile_y <= tile_y_max; tile_y++)
1725f0
+    {
1725f0
+      for (tile_x = tile_x_min; tile_x <= tile_x_max; tile_x++)
1725f0
+        {
1725f0
+          cairo_rectangle_int_t tile = {
1725f0
+            .x = tile_x * tile_size,
1725f0
+            .y = tile_y * tile_size,
1725f0
+            .width = tile_size,
1725f0
+            .height = tile_size,
1725f0
+          };
1725f0
 
1725f0
-  if (!priv->shadow.framebuffer)
1725f0
-    return;
1725f0
+          if (cairo_region_contains_rectangle (damage_region, &tile) ==
1725f0
+              CAIRO_REGION_OVERLAP_OUT)
1725f0
+            continue;
1725f0
 
1725f0
-  if (swap_region->width == 0 || swap_region->height == 0)
1725f0
+          _clutter_util_rectangle_intersection (&tile, &fb_rect, &tile;;
1725f0
+
1725f0
+          if (is_tile_dirty (&tile, current_data, prev_data, bpp, stride))
1725f0
+            cairo_region_union_rectangle (tile_damage_region, &tile;;
1725f0
+        }
1725f0
+    }
1725f0
+
1725f0
+  if (!cogl_dma_buf_handle_sync_read_end (prev_dma_buf_handle, error))
1725f0
     {
1725f0
-      int width, height;
1725f0
+      g_warning ("Failed to end DMA buffer read synchronization: %s",
1725f0
+                 (*error)->message);
1725f0
+      g_clear_error (error);
1725f0
+    }
1725f0
 
1725f0
-      width = cogl_framebuffer_get_width (priv->framebuffer);
1725f0
-      height = cogl_framebuffer_get_height (priv->framebuffer);
1725f0
-      if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
1725f0
-                                  priv->framebuffer,
1725f0
-                                  0, 0,
1725f0
-                                  0, 0,
1725f0
-                                  width, height,
1725f0
-                                  &error))
1725f0
-        g_warning ("Failed to blit shadow buffer: %s", error->message);
1725f0
+  if (!cogl_dma_buf_handle_sync_read_end (current_dma_buf_handle, error))
1725f0
+    {
1725f0
+      g_warning ("Failed to end DMA buffer read synchronization: %s",
1725f0
+                 (*error)->message);
1725f0
+      g_clear_error (error);
1725f0
+    }
1725f0
+
1725f0
+  cogl_dma_buf_handle_munmap (prev_dma_buf_handle, prev_data, NULL);
1725f0
+  cogl_dma_buf_handle_munmap (current_dma_buf_handle, current_data, NULL);
1725f0
+
1725f0
+  cairo_region_intersect (tile_damage_region, damage_region);
1725f0
+
1725f0
+  return tile_damage_region;
1725f0
+
1725f0
+err_mmap_current:
1725f0
+  cogl_dma_buf_handle_munmap (prev_dma_buf_handle, prev_data, NULL);
1725f0
+
1725f0
+err_mmap_prev:
1725f0
+  cogl_dma_buf_handle_sync_read_end (current_dma_buf_handle, NULL);
1725f0
+
1725f0
+err_sync_read_current:
1725f0
+  cogl_dma_buf_handle_sync_read_end (prev_dma_buf_handle, NULL);
1725f0
+
1725f0
+  return NULL;
1725f0
+}
1725f0
+
1725f0
+static void
1725f0
+swap_dma_buf_framebuffer (ClutterStageView *view)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  int next_idx;
1725f0
+  CoglDmaBufHandle *next_dma_buf_handle;
1725f0
+  CoglOffscreen *next_framebuffer;
1725f0
+
1725f0
+  next_idx = ((priv->shadow.dma_buf.current_idx + 1) %
1725f0
+              G_N_ELEMENTS (priv->shadow.dma_buf.handles));
1725f0
+  priv->shadow.dma_buf.current_idx = next_idx;
1725f0
+
1725f0
+  next_dma_buf_handle = priv->shadow.dma_buf.handles[next_idx];
1725f0
+  next_framebuffer =
1725f0
+    cogl_dma_buf_handle_get_framebuffer (next_dma_buf_handle);
1725f0
+  cogl_clear_object (&priv->shadow.framebuffer);
1725f0
+  priv->shadow.framebuffer = cogl_object_ref (next_framebuffer);
1725f0
+}
1725f0
+
1725f0
+static void
1725f0
+copy_shadowfb_to_onscreen (ClutterStageView            *view,
1725f0
+                           const cairo_rectangle_int_t *swap_region)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+  ClutterDamageHistory *damage_history = priv->shadow.dma_buf.damage_history;
1725f0
+  cairo_region_t *damage_region;
1725f0
+  int age;
1725f0
+  int i;
1725f0
+
1725f0
+  if (swap_region->width == 0 || swap_region->height == 0)
1725f0
+    {
1725f0
+      cairo_rectangle_int_t full_damage = {
1725f0
+        .width = cogl_framebuffer_get_width (priv->framebuffer),
1725f0
+        .height = cogl_framebuffer_get_height (priv->framebuffer),
1725f0
+      };
1725f0
+      damage_region = cairo_region_create_rectangle (&full_damage);
1725f0
     }
1725f0
   else
1725f0
     {
1725f0
+      damage_region = cairo_region_create_rectangle (swap_region);
1725f0
+    }
1725f0
+
1725f0
+  if (is_shadowfb_double_buffered (view))
1725f0
+    {
1725f0
+      CoglOnscreen *onscreen = COGL_ONSCREEN (priv->framebuffer);
1725f0
+      cairo_region_t *changed_region;
1725f0
+
1725f0
+      if (cogl_onscreen_get_frame_counter (onscreen) >= 1)
1725f0
+        {
1725f0
+          g_autoptr (GError) error = NULL;
1725f0
+
1725f0
+          changed_region = find_damaged_tiles (view, damage_region, &error);
1725f0
+          if (!changed_region)
1725f0
+            {
1725f0
+              int other_dma_buf_idx;
1725f0
+
1725f0
+              g_warning ("Disabling actual damage detection: %s",
1725f0
+                         error->message);
1725f0
+
1725f0
+              other_dma_buf_idx =
1725f0
+                flip_dma_buf_idx (priv->shadow.dma_buf.current_idx);
1725f0
+              g_clear_pointer (&priv->shadow.dma_buf.handles[other_dma_buf_idx],
1725f0
+                               cogl_dma_buf_handle_free);
1725f0
+            }
1725f0
+        }
1725f0
+      else
1725f0
+        {
1725f0
+          changed_region = cairo_region_copy (damage_region);
1725f0
+        }
1725f0
+
1725f0
+      if (changed_region)
1725f0
+        {
1725f0
+          cairo_rectangle_int_t changed_extents;
1725f0
+          int buffer_age;
1725f0
+
1725f0
+          cairo_region_get_extents (changed_region, &changed_extents);
1725f0
+          clutter_damage_history_record (damage_history, &changed_extents);
1725f0
+
1725f0
+          buffer_age = cogl_onscreen_get_buffer_age (onscreen);
1725f0
+          if (clutter_damage_history_is_age_valid (damage_history, buffer_age))
1725f0
+            {
1725f0
+              for (age = 1; age <= buffer_age; age++)
1725f0
+                {
1725f0
+                  const cairo_rectangle_int_t *old_damage;
1725f0
+
1725f0
+                  old_damage = clutter_damage_history_lookup (damage_history, age);
1725f0
+                  cairo_region_union_rectangle (changed_region, old_damage);
1725f0
+                }
1725f0
+
1725f0
+              cairo_region_destroy (damage_region);
1725f0
+              damage_region = g_steal_pointer (&changed_region);
1725f0
+            }
1725f0
+          else
1725f0
+            {
1725f0
+              cairo_region_destroy (changed_region);
1725f0
+            }
1725f0
+
1725f0
+          clutter_damage_history_step (damage_history);
1725f0
+        }
1725f0
+    }
1725f0
+
1725f0
+  if (0)
1725f0
+    {
1725f0
+      CoglColor clear_color;
1725f0
+
1725f0
+      cogl_color_init_from_4ub (&clear_color,
1725f0
+                                0, 0, 0, 0);
1725f0
+      cogl_framebuffer_clear (priv->framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
1725f0
+    }
1725f0
+
1725f0
+  for (i = 0; i < cairo_region_num_rectangles (damage_region); i++)
1725f0
+    {
1725f0
+      g_autoptr (GError) error = NULL;
1725f0
+      cairo_rectangle_int_t rect;
1725f0
+
1725f0
+      cairo_region_get_rectangle (damage_region, i, &rect);
1725f0
+
1725f0
       if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
1725f0
                                   priv->framebuffer,
1725f0
-                                  swap_region->x, swap_region->y,
1725f0
-                                  swap_region->x, swap_region->y,
1725f0
-                                  swap_region->width, swap_region->height,
1725f0
+                                  rect.x, rect.y,
1725f0
+                                  rect.x, rect.y,
1725f0
+                                  rect.width, rect.height,
1725f0
                                   &error))
1725f0
         {
1725f0
           g_warning ("Failed to blit shadow buffer: %s", error->message);
1725f0
+          cairo_region_destroy (damage_region);
1725f0
           return;
1725f0
         }
1725f0
     }
1725f0
+
1725f0
+  cairo_region_destroy (damage_region);
1725f0
+
1725f0
+  if (is_shadowfb_double_buffered (view))
1725f0
+    swap_dma_buf_framebuffer (view);
1725f0
+}
1725f0
+
1725f0
+void
1725f0
+clutter_stage_view_before_swap_buffer (ClutterStageView            *view,
1725f0
+                                       const cairo_rectangle_int_t *swap_region)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+
1725f0
+  if (priv->shadow.framebuffer)
1725f0
+    copy_shadowfb_to_onscreen (view, swap_region);
1725f0
 }
1725f0
 
1725f0
 float
1725f0
@@ -407,6 +738,47 @@ clutter_stage_view_get_scale (ClutterStageView *view)
1725f0
   return priv->scale;
1725f0
 }
1725f0
 
1725f0
+typedef void (*FrontBufferCallback) (CoglFramebuffer *framebuffer,
1725f0
+                                     gconstpointer    user_data);
1725f0
+
1725f0
+static void
1725f0
+clutter_stage_view_foreach_front_buffer (ClutterStageView    *view,
1725f0
+                                         FrontBufferCallback  callback,
1725f0
+                                         gconstpointer        user_data)
1725f0
+{
1725f0
+  ClutterStageViewPrivate *priv =
1725f0
+    clutter_stage_view_get_instance_private (view);
1725f0
+
1725f0
+  if (priv->offscreen)
1725f0
+    {
1725f0
+      callback (priv->offscreen, user_data);
1725f0
+    }
1725f0
+  else if (priv->shadow.framebuffer)
1725f0
+    {
1725f0
+      if (is_shadowfb_double_buffered (view))
1725f0
+        {
1725f0
+          int i;
1725f0
+
1725f0
+          for (i = 0; i < G_N_ELEMENTS (priv->shadow.dma_buf.handles); i++)
1725f0
+            {
1725f0
+              CoglDmaBufHandle *handle = priv->shadow.dma_buf.handles[i];
1725f0
+              CoglFramebuffer *framebuffer =
1725f0
+                cogl_dma_buf_handle_get_framebuffer (handle);
1725f0
+
1725f0
+              callback (framebuffer, user_data);
1725f0
+            }
1725f0
+        }
1725f0
+      else
1725f0
+        {
1725f0
+          callback (priv->shadow.framebuffer, user_data);
1725f0
+        }
1725f0
+    }
1725f0
+  else
1725f0
+    {
1725f0
+      callback (priv->framebuffer, user_data);
1725f0
+    }
1725f0
+}
1725f0
+
1725f0
 gboolean
1725f0
 clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
1725f0
 {
1725f0
@@ -425,6 +797,19 @@ clutter_stage_view_invalidate_viewport (ClutterStageView *view)
1725f0
   priv->dirty_viewport = TRUE;
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+set_framebuffer_viewport (CoglFramebuffer *framebuffer,
1725f0
+                          gconstpointer    user_data)
1725f0
+{
1725f0
+  const ClutterRect *rect = user_data;
1725f0
+
1725f0
+  cogl_framebuffer_set_viewport (framebuffer,
1725f0
+                                 rect->origin.x,
1725f0
+                                 rect->origin.y,
1725f0
+                                 rect->size.width,
1725f0
+                                 rect->size.height);
1725f0
+}
1725f0
+
1725f0
 void
1725f0
 clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
                                  float             x,
1725f0
@@ -434,11 +819,17 @@ clutter_stage_view_set_viewport (ClutterStageView *view,
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
-  CoglFramebuffer *framebuffer;
1725f0
+  ClutterRect rect;
1725f0
 
1725f0
   priv->dirty_viewport = FALSE;
1725f0
-  framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
-  cogl_framebuffer_set_viewport (framebuffer, x, y, width, height);
1725f0
+
1725f0
+  rect = (ClutterRect) {
1725f0
+    .origin = { .x = x, .y = y },
1725f0
+    .size = { .width = width, .height = height },
1725f0
+  };
1725f0
+  clutter_stage_view_foreach_front_buffer (view,
1725f0
+                                           set_framebuffer_viewport,
1725f0
+                                           &rect);
1725f0
 }
1725f0
 
1725f0
 gboolean
1725f0
@@ -450,6 +841,13 @@ clutter_stage_view_is_dirty_projection (ClutterStageView *view)
1725f0
   return priv->dirty_projection;
1725f0
 }
1725f0
 
1725f0
+static void
1725f0
+set_framebuffer_projection_matrix (CoglFramebuffer *framebuffer,
1725f0
+                                   gconstpointer    user_data)
1725f0
+{
1725f0
+  cogl_framebuffer_set_projection_matrix (framebuffer, user_data);
1725f0
+}
1725f0
+
1725f0
 void
1725f0
 clutter_stage_view_invalidate_projection (ClutterStageView *view)
1725f0
 {
1725f0
@@ -465,11 +863,11 @@ clutter_stage_view_set_projection (ClutterStageView *view,
1725f0
 {
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
-  CoglFramebuffer *framebuffer;
1725f0
 
1725f0
   priv->dirty_projection = FALSE;
1725f0
-  framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
-  cogl_framebuffer_set_projection_matrix (framebuffer, matrix);
1725f0
+  clutter_stage_view_foreach_front_buffer (view,
1725f0
+                                           set_framebuffer_projection_matrix,
1725f0
+                                           matrix);
1725f0
 }
1725f0
 
1725f0
 void
1725f0
@@ -593,10 +991,20 @@ clutter_stage_view_dispose (GObject *object)
1725f0
   ClutterStageView *view = CLUTTER_STAGE_VIEW (object);
1725f0
   ClutterStageViewPrivate *priv =
1725f0
     clutter_stage_view_get_instance_private (view);
1725f0
+  int i;
1725f0
 
1725f0
   g_clear_pointer (&priv->name, g_free);
1725f0
   g_clear_pointer (&priv->framebuffer, cogl_object_unref);
1725f0
+
1725f0
   g_clear_pointer (&priv->shadow.framebuffer, cogl_object_unref);
1725f0
+  for (i = 0; i < G_N_ELEMENTS (priv->shadow.dma_buf.handles); i++)
1725f0
+    {
1725f0
+      g_clear_pointer (&priv->shadow.dma_buf.handles[i],
1725f0
+                       cogl_dma_buf_handle_free);
1725f0
+    }
1725f0
+  g_clear_pointer (&priv->shadow.dma_buf.damage_history,
1725f0
+                   clutter_damage_history_free);
1725f0
+
1725f0
   g_clear_pointer (&priv->offscreen, cogl_object_unref);
1725f0
   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
1725f0
 
1725f0
diff --git a/clutter/clutter/clutter-util.c b/clutter/clutter/clutter-util.c
1725f0
index ed52b69774..834adae39a 100644
1725f0
--- a/clutter/clutter/clutter-util.c
1725f0
+++ b/clutter/clutter/clutter-util.c
1725f0
@@ -210,6 +210,28 @@ _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1,
1725f0
     }
1725f0
 }
1725f0
 
1725f0
+gboolean
1725f0
+_clutter_util_rectangle_contains (const cairo_rectangle_int_t *src1,
1725f0
+                                  const cairo_rectangle_int_t *src2)
1725f0
+{
1725f0
+  int x1, y1, x2, y2;
1725f0
+
1725f0
+  x1 = MAX (src1->x, src2->x);
1725f0
+  y1 = MAX (src1->y, src2->y);
1725f0
+
1725f0
+  x2 = MIN (src1->x + (int) src1->width,  src2->x + (int) src2->width);
1725f0
+  y2 = MIN (src1->y + (int) src1->height, src2->y + (int) src2->height);
1725f0
+
1725f0
+  if (x1 >= x2 || y1 >= y2)
1725f0
+    {
1725f0
+      return FALSE;
1725f0
+    }
1725f0
+  else
1725f0
+    {
1725f0
+      return TRUE;
1725f0
+    }
1725f0
+}
1725f0
+
1725f0
 float
1725f0
 _clutter_util_matrix_determinant (const ClutterMatrix *matrix)
1725f0
 {
1725f0
-- 
1725f0
2.28.0
1725f0
1725f0
1725f0
From 9968d4aeefc2c47a63e12f977dad031672a63abe Mon Sep 17 00:00:00 2001
1725f0
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
1725f0
Date: Sat, 7 Mar 2020 20:29:09 +0100
1725f0
Subject: [PATCH 20/20] clutter/stage-cogl: Use view fb instead of onscreen fb
1725f0
 for debug-drawing
1725f0
1725f0
We need to use the framebuffer of the view instead of the onscreen
1725f0
framebuffer when painting the damage region, otherwise the redraw clips
1725f0
on rotated monitors won't be shown correctly.
1725f0
1725f0
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
1725f0
(cherry picked from commit 8e1bd64e05c3098fcce4f916f9e4468decb8f30c)
1725f0
---
1725f0
 clutter/clutter/cogl/clutter-stage-cogl.c | 2 +-
1725f0
 1 file changed, 1 insertion(+), 1 deletion(-)
1725f0
1725f0
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
index 11273ec894..3f1f609c4e 100644
1725f0
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
1725f0
@@ -353,7 +353,7 @@ paint_damage_region (ClutterStageWindow    *stage_window,
1725f0
                      ClutterStageView      *view,
1725f0
                      cairo_rectangle_int_t *swap_region)
1725f0
 {
1725f0
-  CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
1725f0
+  CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
1725f0
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
1725f0
   static CoglPipeline *overlay_blue = NULL;
1725f0
   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
1725f0
-- 
1725f0
2.28.0
1725f0