gsk/vulkan/renderer: Pass appropriate clip region
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Sun, 2 Apr 2023 22:18:24 +0000 (19:18 -0300)
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Mon, 3 Apr 2023 13:59:45 +0000 (10:59 -0300)
This part of the Vulkan renderer is almost exactly equal to the GL
renderer, and the GL renderer already does that since at least
2a38cecd3351. Copy that into the Vulkan renderer.

A nice side effect from this commit is that resizing a window now
actually works again.

Sneak in a trivial cleanup by using a variable to hold the draw
index.

gsk/vulkan/gskvulkanrenderer.c

index 8f4fa13bf54768da690101d5d8c545440753703a..b634a2b7618cd98b24968a35881133b642851c88 100644 (file)
@@ -70,6 +70,55 @@ struct _GskVulkanRendererClass
 
 G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER)
 
+static cairo_region_t *
+get_render_region (GskVulkanRenderer *self)
+{
+  const cairo_region_t *damage;
+  cairo_region_t *render_region;
+  cairo_region_t *scaled_damage;
+  GdkRectangle whole_surface;
+  GdkRectangle extents;
+  GdkSurface *surface;
+  int scale;
+
+  render_region = NULL;
+  surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan));
+  scale = gdk_surface_get_scale_factor (surface);
+
+  whole_surface.x = 0;
+  whole_surface.y = 0;
+  whole_surface.width = gdk_surface_get_width (surface);
+  whole_surface.height = gdk_surface_get_height (surface);
+
+  damage = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan));
+  scaled_damage = cairo_region_create ();
+  for (int i = 0; i < cairo_region_num_rectangles (damage); i++)
+    {
+      cairo_rectangle_int_t rect;
+      cairo_region_get_rectangle (damage, i, &rect);
+      cairo_region_union_rectangle (scaled_damage, &(cairo_rectangle_int_t) {
+                                      .x = rect.x * scale,
+                                      .y = rect.y * scale,
+                                      .width = rect.width * scale,
+                                      .height = rect.height * scale,
+                                    });
+    }
+
+  if (cairo_region_contains_rectangle (scaled_damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN)
+    goto out;
+
+  cairo_region_get_extents (scaled_damage, &extents);
+  if (gdk_rectangle_equal (&extents, &whole_surface))
+    goto out;
+
+  render_region = cairo_region_create_rectangle (&extents);
+
+out:
+  g_clear_pointer (&scaled_damage, cairo_region_destroy);
+
+  return g_steal_pointer (&render_region);
+}
+
 static void
 gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self)
 {
@@ -239,11 +288,12 @@ gsk_vulkan_renderer_render (GskRenderer          *renderer,
 {
   GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
   GskVulkanRender *render;
-  const cairo_region_t *clip;
+  cairo_region_t *render_region;
 #ifdef G_ENABLE_DEBUG
   GskProfiler *profiler;
   gint64 cpu_time;
 #endif
+  uint32_t draw_index;
 
 #ifdef G_ENABLE_DEBUG
   profiler = gsk_renderer_get_profiler (renderer);
@@ -256,8 +306,9 @@ gsk_vulkan_renderer_render (GskRenderer          *renderer,
   gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region);
   render = self->render;
 
-  clip = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan));
-  gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)], NULL, clip);
+  render_region = get_render_region (self);
+  draw_index = gdk_vulkan_context_get_draw_index (self->vulkan);
+  gsk_vulkan_render_reset (render, self->targets[draw_index], NULL, render_region);
 
   gsk_vulkan_render_add_node (render, root);
 
@@ -275,6 +326,8 @@ gsk_vulkan_renderer_render (GskRenderer          *renderer,
 #endif
 
   gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->vulkan));
+
+  g_clear_pointer (&render_region, cairo_region_destroy);
 }
 
 static void