[gtk+] Clip intermediate textures



commit 3aaea0ef406f143cb4f0a262c65f0f5ea593cf00
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Oct 1 19:17:39 2017 -0400

    Clip intermediate textures
    
    In some cases, we were creating gigantic intermediate textures
    only to clip out a small section afterwards (e.g. in the listbox
    example in gtk4-demo). This is wasteful if we apply effects on
    the texture, such as blur or color-matrix. So, clip the dimensions
    of the intermediate texture with the current clip. To make this
    feasible, we move the texture coordinate computation out of the
    pipeline setup functions into the node_as_texture function where
    this clipping happens.
    
    One extra complication we encounter is that the node might get
    clipped away completely. Since Vulkan does not allow to create
    empty images, we bail out in this case and not draw anything.
    
    With these changes, the listbox example in gtk4-demo goes from
    32M pixels of intermediate texture to 320000.

 gsk/gskvulkanblendmodepipeline.c     |   20 ++--
 gsk/gskvulkanblurpipeline.c          |    9 +-
 gsk/gskvulkanblurpipelineprivate.h   |    1 +
 gsk/gskvulkancrossfadepipeline.c     |   20 ++--
 gsk/gskvulkaneffectpipeline.c        |    9 +-
 gsk/gskvulkaneffectpipelineprivate.h |    1 +
 gsk/gskvulkanrenderpass.c            |  252 ++++++++++++++++++++++------------
 gsk/gskvulkantexturepipeline.c       |    8 +-
 8 files changed, 197 insertions(+), 123 deletions(-)
---
diff --git a/gsk/gskvulkanblendmodepipeline.c b/gsk/gskvulkanblendmodepipeline.c
index 062921e..117ed41 100644
--- a/gsk/gskvulkanblendmodepipeline.c
+++ b/gsk/gskvulkanblendmodepipeline.c
@@ -108,8 +108,8 @@ void
 gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline,
                                                     guchar                *data,
                                                     const graphene_rect_t *bounds,
-                                                    const graphene_rect_t *start_bounds,
-                                                    const graphene_rect_t *end_bounds,
+                                                    const graphene_rect_t *start_tex_rect,
+                                                    const graphene_rect_t *end_tex_rect,
                                                     GskBlendMode blend_mode)
 {
   GskVulkanBlendModeInstance *instance = (GskVulkanBlendModeInstance *) data;
@@ -119,15 +119,15 @@ gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *
   instance->rect[2] = bounds->size.width;
   instance->rect[3] = bounds->size.height;
 
-  instance->start_tex_rect[0] = (bounds->origin.x - start_bounds->origin.x)/start_bounds->size.width;
-  instance->start_tex_rect[1] = (bounds->origin.y - start_bounds->origin.y)/start_bounds->size.height;
-  instance->start_tex_rect[2] = (bounds->size.width + bounds->origin.x - 
start_bounds->origin.x)/start_bounds->size.width;
-  instance->start_tex_rect[3] = (bounds->size.height + bounds->origin.y - 
start_bounds->origin.y)/start_bounds->size.height;
+  instance->start_tex_rect[0] = start_tex_rect->origin.x;
+  instance->start_tex_rect[1] = start_tex_rect->origin.y;
+  instance->start_tex_rect[2] = start_tex_rect->size.width;
+  instance->start_tex_rect[3] = start_tex_rect->size.height;
 
-  instance->end_tex_rect[0] = (bounds->origin.x - end_bounds->origin.x)/end_bounds->size.width;
-  instance->end_tex_rect[1] = (bounds->origin.y - end_bounds->origin.y)/end_bounds->size.height;
-  instance->end_tex_rect[2] = (bounds->size.width + bounds->origin.x - 
end_bounds->origin.x)/end_bounds->size.width;
-  instance->end_tex_rect[3] = (bounds->size.height + bounds->origin.y - 
end_bounds->origin.y)/end_bounds->size.height;
+  instance->end_tex_rect[0] = end_tex_rect->origin.x;
+  instance->end_tex_rect[1] = end_tex_rect->origin.y;
+  instance->end_tex_rect[2] = end_tex_rect->size.width;
+  instance->end_tex_rect[3] = end_tex_rect->size.height;
 
   instance->blend_mode = blend_mode;
 }
diff --git a/gsk/gskvulkanblurpipeline.c b/gsk/gskvulkanblurpipeline.c
index 6e9bff1..5686e54 100644
--- a/gsk/gskvulkanblurpipeline.c
+++ b/gsk/gskvulkanblurpipeline.c
@@ -101,6 +101,7 @@ void
 gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
                                               guchar                *data,
                                               const graphene_rect_t *rect,
+                                              const graphene_rect_t *tex_rect,
                                               double                 blur_radius)
 {
   GskVulkanBlurInstance *instance = (GskVulkanBlurInstance *) data;
@@ -109,10 +110,10 @@ gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
   instance->rect[1] = rect->origin.y;
   instance->rect[2] = rect->size.width;
   instance->rect[3] = rect->size.height;
-  instance->tex_rect[0] = 0.0;
-  instance->tex_rect[1] = 0.0;
-  instance->tex_rect[2] = 1.0;
-  instance->tex_rect[3] = 1.0;
+  instance->tex_rect[0] = tex_rect->origin.x;
+  instance->tex_rect[1] = tex_rect->origin.y;
+  instance->tex_rect[2] = tex_rect->size.width;
+  instance->tex_rect[3] = tex_rect->size.height;
   instance->blur_radius = blur_radius;
 }
 
diff --git a/gsk/gskvulkanblurpipelineprivate.h b/gsk/gskvulkanblurpipelineprivate.h
index 2fc4273..0fc2cb6 100644
--- a/gsk/gskvulkanblurpipelineprivate.h
+++ b/gsk/gskvulkanblurpipelineprivate.h
@@ -22,6 +22,7 @@ gsize                   gsk_vulkan_blur_pipeline_count_vertex_data     (GskVulka
 void                    gsk_vulkan_blur_pipeline_collect_vertex_data   (GskVulkanBlurPipeline   *pipeline,
                                                                         guchar                  *data,
                                                                         const graphene_rect_t   *rect,
+                                                                        const graphene_rect_t   *tex_rect,
                                                                         double                   radius);
 gsize                   gsk_vulkan_blur_pipeline_draw                  (GskVulkanBlurPipeline   *pipeline,
                                                                         VkCommandBuffer          
command_buffer,
diff --git a/gsk/gskvulkancrossfadepipeline.c b/gsk/gskvulkancrossfadepipeline.c
index a0de8c3..679c583 100644
--- a/gsk/gskvulkancrossfadepipeline.c
+++ b/gsk/gskvulkancrossfadepipeline.c
@@ -108,8 +108,8 @@ void
 gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *pipeline,
                                                     guchar                *data,
                                                     const graphene_rect_t *bounds,
-                                                    const graphene_rect_t *start_bounds,
-                                                    const graphene_rect_t *end_bounds,
+                                                    const graphene_rect_t *start_tex_rect,
+                                                    const graphene_rect_t *end_tex_rect,
                                                     double                 progress)
 {
   GskVulkanCrossFadeInstance *instance = (GskVulkanCrossFadeInstance *) data;
@@ -119,15 +119,15 @@ gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *
   instance->rect[2] = bounds->size.width;
   instance->rect[3] = bounds->size.height;
 
-  instance->start_tex_rect[0] = (bounds->origin.x - start_bounds->origin.x)/start_bounds->size.width;
-  instance->start_tex_rect[1] = (bounds->origin.y - start_bounds->origin.y)/start_bounds->size.height;
-  instance->start_tex_rect[2] = (bounds->size.width + bounds->origin.x - 
start_bounds->origin.x)/start_bounds->size.width;
-  instance->start_tex_rect[3] = (bounds->size.height + bounds->origin.y - 
start_bounds->origin.y)/start_bounds->size.height;
+  instance->start_tex_rect[0] = start_tex_rect->origin.x;
+  instance->start_tex_rect[1] = start_tex_rect->origin.y;
+  instance->start_tex_rect[2] = start_tex_rect->size.width;
+  instance->start_tex_rect[3] = start_tex_rect->size.height;
 
-  instance->end_tex_rect[0] = (bounds->origin.x - end_bounds->origin.x)/end_bounds->size.width;
-  instance->end_tex_rect[1] = (bounds->origin.y - end_bounds->origin.y)/end_bounds->size.height;
-  instance->end_tex_rect[2] = (bounds->size.width + bounds->origin.x - 
end_bounds->origin.x)/end_bounds->size.width;
-  instance->end_tex_rect[3] = (bounds->size.height + bounds->origin.y - 
end_bounds->origin.y)/end_bounds->size.height;
+  instance->end_tex_rect[0] = end_tex_rect->origin.x;
+  instance->end_tex_rect[1] = end_tex_rect->origin.y;
+  instance->end_tex_rect[2] = end_tex_rect->size.width;
+  instance->end_tex_rect[3] = end_tex_rect->size.height;
 
   instance->progress = progress;
 }
diff --git a/gsk/gskvulkaneffectpipeline.c b/gsk/gskvulkaneffectpipeline.c
index 1db9ec6..aa9973c 100644
--- a/gsk/gskvulkaneffectpipeline.c
+++ b/gsk/gskvulkaneffectpipeline.c
@@ -126,6 +126,7 @@ void
 gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline,
                                                 guchar                  *data,
                                                 const graphene_rect_t   *rect,
+                                                const graphene_rect_t   *tex_rect,
                                                 const graphene_matrix_t *color_matrix,
                                                 const graphene_vec4_t   *color_offset)
 {
@@ -135,10 +136,10 @@ gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipelin
   instance->rect[1] = rect->origin.y;
   instance->rect[2] = rect->size.width;
   instance->rect[3] = rect->size.height;
-  instance->tex_rect[0] = 0.0;
-  instance->tex_rect[1] = 0.0;
-  instance->tex_rect[2] = 1.0;
-  instance->tex_rect[3] = 1.0;
+  instance->tex_rect[0] = tex_rect->origin.x;
+  instance->tex_rect[1] = tex_rect->origin.y;
+  instance->tex_rect[2] = tex_rect->size.width;
+  instance->tex_rect[3] = tex_rect->size.height;
   graphene_matrix_to_float (color_matrix, instance->color_matrix);
   graphene_vec4_to_float (color_offset, instance->color_offset);
 }
diff --git a/gsk/gskvulkaneffectpipelineprivate.h b/gsk/gskvulkaneffectpipelineprivate.h
index 8e3b976..45ac6af 100644
--- a/gsk/gskvulkaneffectpipelineprivate.h
+++ b/gsk/gskvulkaneffectpipelineprivate.h
@@ -22,6 +22,7 @@ gsize                   gsk_vulkan_effect_pipeline_count_vertex_data    (GskVulk
 void                    gsk_vulkan_effect_pipeline_collect_vertex_data  (GskVulkanEffectPipeline        
*pipeline,
                                                                          guchar                         
*data,
                                                                          const graphene_rect_t          
*rect,
+                                                                         const graphene_rect_t          
*tex_rect,
                                                                          const graphene_matrix_t        
*color_matrix,
                                                                          const graphene_vec4_t          
*color_offset);
 gsize                   gsk_vulkan_effect_pipeline_draw                 (GskVulkanEffectPipeline        
*pipeline,
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index 6b10345..770ebdb 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -73,6 +73,8 @@ struct _GskVulkanOpRender
   gsize                vertex_count; /* number of vertices */
   gsize                descriptor_set_index; /* index into descriptor sets array for the right descriptor 
set to bind */
   gsize                descriptor_set_index2; /* descriptor index for the second source (if relevant) */
+  graphene_rect_t      source_rect; /* area that source maps to */
+  graphene_rect_t      source2_rect; /* area that source2 maps to */
 };
 
 struct _GskVulkanOpText
@@ -660,88 +662,117 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
 }
 
 static GskVulkanImage *
-gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass   *self,
-                                            GskVulkanRender       *render,
-                                            GskVulkanUploader     *uploader,
-                                            GskRenderNode         *node,
-                                            const graphene_rect_t *bounds)
+gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
+                                            GskVulkanRender     *render,
+                                            GskVulkanUploader   *uploader,
+                                            GskRenderNode       *node,
+                                            graphene_rect_t     *bounds,
+                                            GskVulkanClip       *current_clip,
+                                            graphene_rect_t     *tex_rect)
 {
   GskVulkanImage *result;
   cairo_surface_t *surface;
   cairo_t *cr;
 
-  if (graphene_rect_equal (bounds, &node->bounds))
+  switch (gsk_render_node_get_node_type (node))
     {
-      switch (gsk_render_node_get_node_type (node))
+    case GSK_TEXTURE_NODE:
+      if (graphene_rect_equal (bounds, &node->bounds))
         {
-        case GSK_TEXTURE_NODE:
           result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER 
(gsk_vulkan_render_get_renderer (render)),
                                                           gsk_texture_node_get_texture (node),
                                                           uploader);
           gsk_vulkan_render_add_cleanup_image (render, result);
+          *tex_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
           return result;
+        }
+      break;
 
-        case GSK_CAIRO_NODE:
+    case GSK_CAIRO_NODE:
+      if (graphene_rect_equal (bounds, &node->bounds))
+        {
           surface = cairo_surface_reference (gsk_cairo_node_get_surface (node));
           goto got_surface;
+        }
+      break;
 
-        default: ;
-          {
-            VkSemaphore semaphore;
-            graphene_rect_t view;
-            cairo_region_t *clip;
-            GskVulkanRenderPass *pass;
+    default: ;
+      {
+        VkSemaphore semaphore;
+        graphene_rect_t view;
+        cairo_region_t *clip;
+        GskVulkanRenderPass *pass;
+        graphene_rect_t clipped;
+
+        if (current_clip)
+          graphene_rect_intersection (&current_clip->rect.bounds, bounds, &clipped);
+        else
+          clipped = *bounds;
 
-            graphene_matrix_transform_bounds (&self->mv, bounds, &view);
+        if (clipped.size.width == 0 || clipped.size.height == 0)
+          return NULL;
 
-            result = gsk_vulkan_image_new_for_texture (self->vulkan,
-                                                       ceil (view.size.width),
-                                                       ceil (view.size.height));
+        graphene_matrix_transform_bounds (&self->mv, &clipped, &view);
+        view.origin.x = floor (view.origin.x);
+        view.origin.y = floor (view.origin.y);
+        view.size.width = ceil (view.size.width);
+        view.size.height = ceil (view.size.height);
+
+        result = gsk_vulkan_image_new_for_texture (self->vulkan,
+                                                   view.size.width,
+                                                   view.size.height);
 
 #ifdef G_ENABLE_DEBUG
-            {
-              GskProfiler *profiler = gsk_renderer_get_profiler (gsk_vulkan_render_get_renderer (render));
-              gsk_profiler_counter_add (profiler,
-                                        self->texture_pixels,
-                                        ceil (view.size.width) * ceil (view.size.height));
-            }
+        {
+          GskProfiler *profiler = gsk_renderer_get_profiler (gsk_vulkan_render_get_renderer (render));
+          gsk_profiler_counter_add (profiler,
+                                    self->texture_pixels,
+                                    view.size.width * view.size.height);
+        }
 #endif
 
-            vkCreateSemaphore (gdk_vulkan_context_get_device (self->vulkan),
-                               &(VkSemaphoreCreateInfo) {
-                                   VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
-                                   NULL,
-                                   0
-                               },
-                               NULL,
-                               &semaphore);
-
-            g_array_append_val (self->wait_semaphores, semaphore);
-
-            clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
-                                                  0, 0,
-                                                  gsk_vulkan_image_get_width (result),
-                                                  gsk_vulkan_image_get_height (result)
-                                                  });
-
-            pass = gsk_vulkan_render_pass_new (self->vulkan,
-                                               result,
-                                               1,
-                                               &self->mv,
-                                               &view,
-                                               clip,
-                                               semaphore);
-
-            cairo_region_destroy (clip);
-
-            gsk_vulkan_render_add_render_pass (render, pass);
-            gsk_vulkan_render_pass_add (pass, render, node);
-            gsk_vulkan_render_add_cleanup_image (render, result);
-
-            return result;
-          }
-        }
-    }
+        vkCreateSemaphore (gdk_vulkan_context_get_device (self->vulkan),
+                           &(VkSemaphoreCreateInfo) {
+                             VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+                             NULL,
+                             0
+                           },
+                           NULL,
+                           &semaphore);
+
+        g_array_append_val (self->wait_semaphores, semaphore);
+
+        clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+                                                0, 0,
+                                                gsk_vulkan_image_get_width (result),
+                                                gsk_vulkan_image_get_height (result)
+                                              });
+
+        pass = gsk_vulkan_render_pass_new (self->vulkan,
+                                           result,
+                                           self->scale_factor,
+                                           &self->mv,
+                                           &view,
+                                           clip,
+                                           semaphore);
+
+        cairo_region_destroy (clip);
+
+        gsk_vulkan_render_add_render_pass (render, pass);
+        gsk_vulkan_render_pass_add (pass, render, node);
+        gsk_vulkan_render_add_cleanup_image (render, result);
+
+        /* assuming the unclipped bounds should go to texture coordinates 0..1,
+         * calculate the coordinates for the clipped texture size
+         */
+        tex_rect->origin.x = (bounds->origin.x - clipped.origin.x)/clipped.size.width;
+        tex_rect->origin.y = (bounds->origin.y - clipped.origin.y)/clipped.size.height;
+        tex_rect->size.width = bounds->size.width/clipped.size.width;
+        tex_rect->size.height = bounds->size.height/clipped.size.height;
+
+        return result;
+      }
+   }
 
   GSK_NOTE (FALLBACK, g_print ("Node as texture not implemented for this case. Using %gx%g fallback 
surface\n",
                                ceil (bounds->size.width),
@@ -777,6 +808,8 @@ got_surface:
 
   gsk_vulkan_render_add_cleanup_image (render, result);
 
+  *tex_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
+
   return result;
 }
 
@@ -842,6 +875,8 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass  *self,
                                                cairo_image_surface_get_height (surface),
                                                cairo_image_surface_get_stride (surface));
 
+  op->source_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
+
   cairo_surface_destroy (surface);
 
   gsk_vulkan_render_add_cleanup_image (render, op->source);
@@ -854,6 +889,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
 {
   GskVulkanOp *op;
   guint i;
+  const GskVulkanClip *clip = NULL;
 
   for (i = 0; i < self->render_ops->len; i++)
     {
@@ -877,6 +913,8 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                 cairo_image_surface_get_width (surface),
                                                                 cairo_image_surface_get_height (surface),
                                                                 cairo_image_surface_get_stride (surface));
+            op->render.source_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
+
             gsk_vulkan_render_add_cleanup_image (render, op->render.source);
           }
           break;
@@ -896,6 +934,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
             op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER 
(gsk_vulkan_render_get_renderer (render)),
                                                                        gsk_texture_node_get_texture 
(op->render.node),
                                                                        uploader);
+            op->render.source_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
             gsk_vulkan_render_add_cleanup_image (render, op->render.source);
           }
           break;
@@ -908,20 +947,24 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                             render,
                                                                             uploader,
                                                                             child,
-                                                                            &child->bounds);
+                                                                            &child->bounds,
+                                                                            clip,
+                                                                            &op->render.source_rect);
           }
           break;
 
         case GSK_VULKAN_OP_REPEAT:
           {
             GskRenderNode *child = gsk_repeat_node_get_child (op->render.node);
-            const graphene_rect_t *child_bounds = gsk_repeat_node_peek_child_bounds (op->render.node);
+            const graphene_rect_t *bounds = gsk_repeat_node_peek_child_bounds (op->render.node);
 
             op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
                                                                             render,
                                                                             uploader,
                                                                             child,
-                                                                            child_bounds);
+                                                                            bounds,
+                                                                            NULL,
+                                                                            &op->render.source_rect);
           }
           break;
 
@@ -933,7 +976,9 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                             render,
                                                                             uploader,
                                                                             child,
-                                                                            &child->bounds);
+                                                                            &child->bounds,
+                                                                            clip,
+                                                                            &op->render.source_rect);
           }
           break;
 
@@ -945,7 +990,9 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                             render,
                                                                             uploader,
                                                                             child,
-                                                                            &child->bounds);
+                                                                            &child->bounds,
+                                                                            clip,
+                                                                            &op->render.source_rect);
           }
           break;
 
@@ -958,12 +1005,16 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                             render,
                                                                             uploader,
                                                                             start,
-                                                                            &start->bounds);
+                                                                            &start->bounds,
+                                                                            clip,
+                                                                            &op->render.source_rect);
             op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
                                                                              render,
                                                                              uploader,
                                                                              end,
-                                                                             &end->bounds);
+                                                                             &end->bounds,
+                                                                             clip,
+                                                                             &op->render.source2_rect);
           }
           break;
 
@@ -976,20 +1027,27 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
                                                                             render,
                                                                             uploader,
                                                                             top,
-                                                                            &top->bounds);
+                                                                            &top->bounds,
+                                                                            clip,
+                                                                            &op->render.source_rect);
             op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
                                                                              render,
                                                                              uploader,
                                                                              bottom,
-                                                                             &bottom->bounds);
+                                                                             &bottom->bounds,
+                                                                             clip,
+                                                                             &op->render.source2_rect);
           }
           break;
 
+        case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+          clip = &op->constants.constants.clip;
+          break;
+
         default:
           g_assert_not_reached ();
         case GSK_VULKAN_OP_COLOR:
         case GSK_VULKAN_OP_LINEAR_GRADIENT:
-        case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
         case GSK_VULKAN_OP_BORDER:
         case GSK_VULKAN_OP_INSET_SHADOW:
         case GSK_VULKAN_OP_OUTSET_SHADOW:
@@ -1115,20 +1173,18 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
             gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE 
(op->render.pipeline),
                                                              data + n_bytes + offset,
                                                              &op->render.node->bounds,
-                                                             &op->render.node->bounds);
+                                                             &op->render.source_rect);
             n_bytes += op->render.vertex_count;
           }
           break;
 
         case GSK_VULKAN_OP_REPEAT:
           {
-            const graphene_rect_t *child_bounds = gsk_repeat_node_peek_child_bounds (op->render.node);
-
             op->render.vertex_offset = offset + n_bytes;
             gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE 
(op->render.pipeline),
                                                              data + n_bytes + offset,
                                                              &op->render.node->bounds,
-                                                             child_bounds);
+                                                             &op->render.source_rect);
             n_bytes += op->render.vertex_count;
           }
           break;
@@ -1198,18 +1254,21 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
           {
             graphene_matrix_t color_matrix;
             graphene_vec4_t color_offset;
+
             graphene_matrix_init_from_float (&color_matrix,
                                              (float[16]) {
-                                                 1.0, 0.0, 0.0, 0.0,         
-                                                 0.0, 1.0, 0.0, 0.0,         
-                                                 0.0, 0.0, 1.0, 0.0,         
+                                                 1.0, 0.0, 0.0, 0.0,
+                                                 0.0, 1.0, 0.0, 0.0,
+                                                 0.0, 0.0, 1.0, 0.0,
                                                  0.0, 0.0, 0.0, gsk_opacity_node_get_opacity 
(op->render.node)
                                              });
             graphene_vec4_init (&color_offset, 0.0, 0.0, 0.0, 0.0);
             op->render.vertex_offset = offset + n_bytes;
+
             gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),
                                                             data + n_bytes + offset,
                                                             &op->render.node->bounds,
+                                                            &op->render.source_rect,
                                                             &color_matrix,
                                                             &color_offset);
             n_bytes += op->render.vertex_count;
@@ -1222,6 +1281,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
             gsk_vulkan_blur_pipeline_collect_vertex_data (GSK_VULKAN_BLUR_PIPELINE (op->render.pipeline),
                                                           data + n_bytes + offset,
                                                           &op->render.node->bounds,
+                                                          &op->render.source_rect,
                                                           gsk_blur_node_get_radius (op->render.node));
             n_bytes += op->render.vertex_count;
           }
@@ -1233,6 +1293,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
             gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),
                                                             data + n_bytes + offset,
                                                             &op->render.node->bounds,
+                                                            &op->render.source_rect,
                                                             gsk_color_matrix_node_peek_color_matrix 
(op->render.node),
                                                             gsk_color_matrix_node_peek_color_offset 
(op->render.node));
             n_bytes += op->render.vertex_count;
@@ -1283,15 +1344,12 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
 
         case GSK_VULKAN_OP_CROSS_FADE:
           {
-            GskRenderNode *start = gsk_cross_fade_node_get_start_child (op->render.node);
-            GskRenderNode *end = gsk_cross_fade_node_get_end_child (op->render.node);
-
             op->render.vertex_offset = offset + n_bytes;
             gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GSK_VULKAN_CROSS_FADE_PIPELINE 
(op->render.pipeline),
                                                                 data + n_bytes + offset,
                                                                 &op->render.node->bounds,
-                                                                &start->bounds,
-                                                                &end->bounds,
+                                                                &op->render.source_rect,
+                                                                &op->render.source2_rect,
                                                                 gsk_cross_fade_node_get_progress 
(op->render.node));
             n_bytes += op->render.vertex_count;
           }
@@ -1299,15 +1357,12 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
 
         case GSK_VULKAN_OP_BLEND_MODE:
           {
-            GskRenderNode *top = gsk_blend_node_get_top_child (op->render.node);
-            GskRenderNode *bottom = gsk_blend_node_get_bottom_child (op->render.node);
-
             op->render.vertex_offset = offset + n_bytes;
             gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GSK_VULKAN_BLEND_MODE_PIPELINE 
(op->render.pipeline),
                                                                 data + n_bytes + offset,
                                                                 &op->render.node->bounds,
-                                                                &top->bounds,
-                                                                &bottom->bounds,
+                                                                &op->render.source_rect,
+                                                                &op->render.source2_rect,
                                                                 gsk_blend_node_get_blend_mode 
(op->render.node));
             n_bytes += op->render.vertex_count;
           }
@@ -1381,11 +1436,13 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_OPACITY:
         case GSK_VULKAN_OP_BLUR:
         case GSK_VULKAN_OP_COLOR_MATRIX:
-          op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, FALSE);
+          if (op->render.source)
+            op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, FALSE);
           break;
 
         case GSK_VULKAN_OP_REPEAT:
-          op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, TRUE);
+          if (op->render.source)
+            op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, TRUE);
           break;
 
         case GSK_VULKAN_OP_TEXT:
@@ -1395,8 +1452,11 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
 
         case GSK_VULKAN_OP_CROSS_FADE:
         case GSK_VULKAN_OP_BLEND_MODE:
-          op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, FALSE);
-          op->render.descriptor_set_index2 = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source2, FALSE);
+          if (op->render.source && op->render.source2)
+            {
+              op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source, FALSE);
+              op->render.descriptor_set_index2 = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source2, FALSE);
+            }
           break;
 
         default:
@@ -1441,6 +1501,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
         case GSK_VULKAN_OP_SURFACE:
         case GSK_VULKAN_OP_TEXTURE:
         case GSK_VULKAN_OP_REPEAT:
+          if (!op->render.source)
+            continue;
           if (current_pipeline != op->render.pipeline)
             {
               current_pipeline = op->render.pipeline;
@@ -1541,6 +1603,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
 
         case GSK_VULKAN_OP_OPACITY:
         case GSK_VULKAN_OP_COLOR_MATRIX:
+          if (!op->render.source)
+            continue;
           if (current_pipeline != op->render.pipeline)
             {
               current_pipeline = op->render.pipeline;
@@ -1574,6 +1638,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
           break;
 
         case GSK_VULKAN_OP_BLUR:
+          if (!op->render.source)
+            continue;
           if (current_pipeline != op->render.pipeline)
             {
               current_pipeline = op->render.pipeline;
@@ -1707,6 +1773,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
           break;
 
         case GSK_VULKAN_OP_CROSS_FADE:
+          if (!op->render.source || !op->render.source2)
+            continue;
           if (current_pipeline != op->render.pipeline)
             {
               current_pipeline = op->render.pipeline;
@@ -1741,6 +1809,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
           break;
 
         case GSK_VULKAN_OP_BLEND_MODE:
+          if (!op->render.source || !op->render.source2)
+            continue;
           if (current_pipeline != op->render.pipeline)
             {
               current_pipeline = op->render.pipeline;
diff --git a/gsk/gskvulkantexturepipeline.c b/gsk/gskvulkantexturepipeline.c
index 83dae29..9db7190 100644
--- a/gsk/gskvulkantexturepipeline.c
+++ b/gsk/gskvulkantexturepipeline.c
@@ -102,10 +102,10 @@ gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipel
   instance->rect[1] = rect->origin.y;
   instance->rect[2] = rect->size.width;
   instance->rect[3] = rect->size.height;
-  instance->tex_rect[0] = (rect->origin.x - tex_rect->origin.x)/tex_rect->size.width;
-  instance->tex_rect[1] = (rect->origin.y - tex_rect->origin.y)/tex_rect->size.height;
-  instance->tex_rect[2] = (rect->size.width + rect->origin.x - tex_rect->origin.x)/tex_rect->size.width;
-  instance->tex_rect[3] = (rect->size.height + rect->origin.y - tex_rect->origin.y)/tex_rect->size.height;
+  instance->tex_rect[0] = tex_rect->origin.x;
+  instance->tex_rect[1] = tex_rect->origin.y;
+  instance->tex_rect[2] = tex_rect->size.width;
+  instance->tex_rect[3] = tex_rect->size.height;
 }
 
 gsize



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