[mutter] compositor/native: Check that the surface can be scanned out untransformed



commit 7f930048094d1148d0d314b32523af90f2fe64d8
Author: Robert Mader <robert mader collabora com>
Date:   Tue Feb 8 20:23:27 2022 +0100

    compositor/native: Check that the surface can be scanned out untransformed
    
    Before scanning out the surface of a native client we have
    to check the following attributes that influence the
    relationship between buffer and the defined result on screen:
     - buffer scale
     - buffer transform
     - viewport
    
    In the future we can loose these checks again in cases where the
    display hardware supports the required operations (scaling, cropping
    and rotating).
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2276>

 src/compositor/meta-compositor-native.c |  6 +++
 src/wayland/meta-wayland-surface.c      | 65 +++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-surface.h      |  5 +++
 3 files changed, 76 insertions(+)
---
diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c
index dd77bb7ae7..6a046060a9 100644
--- a/src/compositor/meta-compositor-native.c
+++ b/src/compositor/meta-compositor-native.c
@@ -77,6 +77,7 @@ maybe_assign_primary_plane (MetaCompositor *compositor)
   MetaSurfaceActor *surface_actor;
   MetaSurfaceActorWayland *surface_actor_wayland;
   MetaWaylandSurface *surface;
+  int geometry_scale;
   MetaWaylandSurface *old_candidate =
     compositor_native->current_scanout_candidate;
   MetaWaylandSurface *new_candidate = NULL;
@@ -122,6 +123,11 @@ maybe_assign_primary_plane (MetaCompositor *compositor)
   if (!surface)
     goto done;
 
+  geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
+  if (!meta_wayland_surface_can_scanout_untransformed (surface, view,
+                                                       geometry_scale))
+    goto done;
+
   new_candidate = surface;
 
   onscreen = COGL_ONSCREEN (framebuffer);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index fcac0af4f1..3bbe82456e 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -2189,3 +2189,68 @@ meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
   g_object_notify_by_pspec (G_OBJECT (surface),
                             obj_props[PROP_SCANOUT_CANDIDATE]);
 }
+
+gboolean
+meta_wayland_surface_can_scanout_untransformed (MetaWaylandSurface *surface,
+                                                MetaRendererView   *view,
+                                                int                 geometry_scale)
+{
+  if (meta_renderer_view_get_transform (view) != surface->buffer_transform)
+    return FALSE;
+
+  if (surface->viewport.has_dst_size)
+    {
+      MetaRectangle view_layout;
+      float view_scale;
+
+      clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
+      view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
+
+      if (!G_APPROX_VALUE (view_layout.width, surface->viewport.dst_width,
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (view_layout.height, surface->viewport.dst_height,
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (view_layout.width * view_scale,
+                           get_buffer_width (surface),
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (view_layout.height * view_scale,
+                           get_buffer_height (surface),
+                           FLT_EPSILON))
+        return FALSE;
+    }
+  else
+    {
+      if (meta_is_stage_views_scaled ())
+        {
+          float view_scale;
+
+          view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
+          if (!G_APPROX_VALUE (view_scale, surface->scale, FLT_EPSILON))
+            return FALSE;
+        }
+      else
+        {
+          if (geometry_scale != surface->scale)
+            return FALSE;
+        }
+    }
+
+  if (surface->viewport.has_src_rect)
+    {
+      if (!G_APPROX_VALUE (surface->viewport.src_rect.origin.x, 0.0,
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (surface->viewport.src_rect.origin.y, 0.0,
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (surface->viewport.src_rect.size.width *
+                           surface->scale,
+                           get_buffer_width (surface),
+                           FLT_EPSILON) ||
+          !G_APPROX_VALUE (surface->viewport.src_rect.size.height *
+                           surface->scale,
+                           get_buffer_height (surface),
+                           FLT_EPSILON))
+        return FALSE;
+    }
+
+  return TRUE;
+}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index bd2cf6377c..ccbbb7ed8c 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -368,6 +368,11 @@ MetaCrtc * meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surfa
 void meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
                                                  MetaCrtc           *crtc);
 
+gboolean
+meta_wayland_surface_can_scanout_untransformed (MetaWaylandSurface *surface,
+                                                MetaRendererView   *view,
+                                                int                 geometry_scale);
+
 static inline GNode *
 meta_get_next_subsurface_sibling (GNode *n)
 {


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