vulkan: Add cross-fade op
authorBenjamin Otte <otte@redhat.com>
Thu, 29 Jun 2023 19:44:40 +0000 (21:44 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 16 Jul 2023 10:12:36 +0000 (12:12 +0200)
The benefit here is that we can now properly cross-fade when one of
start/end is fully clipped out by just replacing it with an opacity op
for the other.

This was not possible with the old way we did things.

gsk/meson.build
gsk/vulkan/gskvulkanopprivate.h
gsk/vulkan/gskvulkanrender.c
gsk/vulkan/gskvulkanrenderpass.c
gsk/vulkan/gskvulkanrenderprivate.h

index 9ac20b019778c38154bc30afcc2bf9e118c90132..2ef5fae5ae34a65015d980d4b5ae4fa19f3c66d7 100644 (file)
@@ -117,7 +117,7 @@ if have_vulkan
     'vulkan/gskvulkancolorop.c',
     'vulkan/gskvulkancolortextpipeline.c',
     'vulkan/gskvulkancommandpool.c',
-    'vulkan/gskvulkancrossfadepipeline.c',
+    'vulkan/gskvulkancrossfadeop.c',
     'vulkan/gskvulkanglyphcache.c',
     'vulkan/gskvulkanimage.c',
     'vulkan/gskvulkanlineargradientpipeline.c',
index 1c3de3efb02214e499817da5d2b2571efc676bdd..75959af22c0b4fbf4da636f3f8fb59aa4840edaa 100644 (file)
@@ -85,5 +85,15 @@ gsk_vulkan_normalize_tex_coords (graphene_rect_t       *tex_coords,
                       rect->size.height / tex->size.height);
 }
 
+static inline void
+gsk_vulkan_rect_to_float (const graphene_rect_t *rect,
+                          float                  values[4])
+{
+  values[0] = rect->origin.x;
+  values[1] = rect->origin.y;
+  values[2] = rect->size.width;
+  values[3] = rect->size.height;
+}
+
 G_END_DECLS
 
index d529cc551e62fa9d9300a41e469fa6d513c5e159..b05b2f7a664416970a41bed0c4e6bf396e3a0d7e 100644 (file)
@@ -15,7 +15,6 @@
 #include "gskvulkanborderpipelineprivate.h"
 #include "gskvulkanboxshadowpipelineprivate.h"
 #include "gskvulkancolortextpipelineprivate.h"
-#include "gskvulkancrossfadepipelineprivate.h"
 #include "gskvulkanlineargradientpipelineprivate.h"
 #include "gskvulkantextpipelineprivate.h"
 #include "gskvulkanpushconstantsprivate.h"
@@ -523,9 +522,6 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender       *self,
     { "texture",                    1, gsk_vulkan_color_text_pipeline_new },
     { "texture-clip",               1, gsk_vulkan_color_text_pipeline_new },
     { "texture-clip-rounded",       1, gsk_vulkan_color_text_pipeline_new },
-    { "cross-fade",                 2, gsk_vulkan_cross_fade_pipeline_new },
-    { "cross-fade-clip",            2, gsk_vulkan_cross_fade_pipeline_new },
-    { "cross-fade-clip-rounded",    2, gsk_vulkan_cross_fade_pipeline_new },
     { "blend-mode",                 2, gsk_vulkan_blend_mode_pipeline_new },
     { "blend-mode-clip",            2, gsk_vulkan_blend_mode_pipeline_new },
     { "blend-mode-clip-rounded",    2, gsk_vulkan_blend_mode_pipeline_new },
index 6d04f53d0d823aadd5df71feea3c5935a60674f6..3be521878c878a1e76b208406f0ccbce97f861e6 100644 (file)
@@ -17,7 +17,7 @@
 #include "gskvulkancolormatrixopprivate.h"
 #include "gskvulkancoloropprivate.h"
 #include "gskvulkancolortextpipelineprivate.h"
-#include "gskvulkancrossfadepipelineprivate.h"
+#include "gskvulkancrossfadeopprivate.h"
 #include "gskvulkanlineargradientpipelineprivate.h"
 #include "gskvulkanopprivate.h"
 #include "gskvulkanrendererprivate.h"
@@ -57,7 +57,6 @@ typedef enum {
   GSK_VULKAN_OP_BORDER,
   GSK_VULKAN_OP_INSET_SHADOW,
   GSK_VULKAN_OP_OUTSET_SHADOW,
-  GSK_VULKAN_OP_CROSS_FADE,
   GSK_VULKAN_OP_BLEND_MODE,
   /* GskVulkanOpText */
   GSK_VULKAN_OP_TEXT,
@@ -867,14 +866,12 @@ gsk_vulkan_render_pass_add_transform_node (GskVulkanRenderPass       *self,
   return TRUE;
 }
 
-static inline gboolean
+static gboolean
 gsk_vulkan_render_pass_add_opacity_node (GskVulkanRenderPass       *self,
                                          GskVulkanRender           *render,
                                          const GskVulkanParseState *state,
                                          GskRenderNode             *node)
 {
-  graphene_matrix_t color_matrix;
-  graphene_vec4_t color_offset;
   GskVulkanImage *image;
   graphene_rect_t tex_rect;
 
@@ -1147,22 +1144,62 @@ gsk_vulkan_render_pass_add_cross_fade_node (GskVulkanRenderPass       *self,
                                             const GskVulkanParseState *state,
                                             GskRenderNode             *node)
 {
-  GskVulkanOpRender op = {
-    .type = GSK_VULKAN_OP_CROSS_FADE,
-    .node = node,
-    .offset = state->offset,
-  };
-  GskVulkanPipelineType pipeline_type;
+  GskRenderNode *start_child, *end_child;
+  GskVulkanImage *start_image, *end_image;
+  graphene_rect_t start_tex_rect, end_tex_rect;
+  float progress;
+
+  progress = gsk_cross_fade_node_get_progress (node);
+  start_child = gsk_cross_fade_node_get_start_child (node);
+  start_image = gsk_vulkan_render_pass_get_node_as_image (self,
+                                                          render,
+                                                          state,
+                                                          start_child,
+                                                          &start_tex_rect);
+  end_child = gsk_cross_fade_node_get_end_child (node);
+  end_image = gsk_vulkan_render_pass_get_node_as_image (self,
+                                                        render,
+                                                        state,
+                                                        end_child,
+                                                        &end_tex_rect);
+  if (start_image == NULL)
+    {
+      if (end_image == NULL)
+        return TRUE;
 
-  if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds))
-    pipeline_type = GSK_VULKAN_PIPELINE_CROSS_FADE;
-  else if (state->clip.type == GSK_VULKAN_CLIP_RECT)
-    pipeline_type = GSK_VULKAN_PIPELINE_CROSS_FADE_CLIP;
-  else
-    pipeline_type = GSK_VULKAN_PIPELINE_CROSS_FADE_CLIP_ROUNDED;
+      gsk_vulkan_color_matrix_op_opacity (self,
+                                          gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &end_child->bounds),
+                                          end_image,
+                                          &node->bounds,
+                                          &state->offset,
+                                          &end_tex_rect,
+                                          progress);
 
-  op.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
-  gsk_vulkan_render_pass_add_op (self, (GskVulkanOp *) &op);
+      return TRUE;
+    }
+  else if (end_image == NULL)
+    {
+      gsk_vulkan_color_matrix_op_opacity (self,
+                                          gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &start_child->bounds),
+                                          start_image,
+                                          &node->bounds,
+                                          &state->offset,
+                                          &start_tex_rect,
+                                          1.0f - progress);
+      return TRUE;
+    }
+
+  gsk_vulkan_cross_fade_op (self,
+                            gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &node->bounds),
+                            &node->bounds,
+                            &state->offset,
+                            progress,
+                            start_image,
+                            &start_child->bounds,
+                            &start_tex_rect,
+                            end_image,
+                            &end_child->bounds,
+                            &end_tex_rect);
 
   return TRUE;
 }
@@ -1637,44 +1674,6 @@ gsk_vulkan_render_op_upload (GskVulkanOp           *op_,
           }
           break;
 
-        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);
-            graphene_rect_t tex_bounds;
-
-            op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
-                                                                            render,
-                                                                            uploader,
-                                                                            start,
-                                                                            scale,
-                                                                            clip,
-                                                                            &op->render.offset,
-                                                                            &tex_bounds);
-            gsk_vulkan_normalize_tex_coords (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
-
-            op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
-                                                                             render,
-                                                                             uploader,
-                                                                             end,
-                                                                             scale,
-                                                                             clip,
-                                                                             &op->render.offset,
-                                                                             &tex_bounds);
-            gsk_vulkan_normalize_tex_coords (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds);
-            if (!op->render.source)
-              {
-                op->render.source = op->render.source2;
-                op->render.source_rect = *graphene_rect_zero();
-              }
-            if (!op->render.source2)
-              {
-                op->render.source2 = op->render.source;
-                op->render.source2_rect = *graphene_rect_zero();
-              }
-          }
-          break;
-
         case GSK_VULKAN_OP_BLEND_MODE:
           {
             GskRenderNode *top = gsk_blend_node_get_top_child (op->render.node);
@@ -1756,7 +1755,6 @@ gsk_vulkan_render_op_count_vertex_data (GskVulkanOp *op_,
         case GSK_VULKAN_OP_BORDER:
         case GSK_VULKAN_OP_INSET_SHADOW:
         case GSK_VULKAN_OP_OUTSET_SHADOW:
-        case GSK_VULKAN_OP_CROSS_FADE:
         case GSK_VULKAN_OP_BLEND_MODE:
           vertex_stride = gsk_vulkan_pipeline_get_vertex_stride (op->render.pipeline);
           n_bytes = round_up (n_bytes, vertex_stride);
@@ -1900,20 +1898,6 @@ gsk_vulkan_render_op_collect_vertex_data (GskVulkanOp         *op_,
                                                               gsk_outset_shadow_node_get_blur_radius (op->render.node));
           break;
 
-        case GSK_VULKAN_OP_CROSS_FADE:
-          gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GSK_VULKAN_CROSS_FADE_PIPELINE (op->render.pipeline),
-                                                              data + op->render.vertex_offset,
-                                                              op->render.image_descriptor,
-                                                              op->render.image_descriptor2,
-                                                              &op->render.offset,
-                                                              &op->render.node->bounds,
-                                                              &gsk_cross_fade_node_get_start_child (op->render.node)->bounds,
-                                                              &gsk_cross_fade_node_get_end_child (op->render.node)->bounds,
-                                                              &op->render.source_rect,
-                                                              &op->render.source2_rect,
-                                                              gsk_cross_fade_node_get_progress (op->render.node));
-          break;
-
         case GSK_VULKAN_OP_BLEND_MODE:
           gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GSK_VULKAN_BLEND_MODE_PIPELINE (op->render.pipeline),
                                                               data + op->render.vertex_offset,
@@ -2012,7 +1996,6 @@ gsk_vulkan_render_op_reserve_descriptor_sets (GskVulkanOp     *op_,
                                                                               GSK_VULKAN_SAMPLER_DEFAULT);
           break;
 
-        case GSK_VULKAN_OP_CROSS_FADE:
         case GSK_VULKAN_OP_BLEND_MODE:
           if (op->render.source && op->render.source2)
             {
@@ -2114,7 +2097,6 @@ gsk_vulkan_render_op_get_pipeline (GskVulkanOp *op_)
     case GSK_VULKAN_OP_BORDER:
     case GSK_VULKAN_OP_INSET_SHADOW:
     case GSK_VULKAN_OP_OUTSET_SHADOW:
-    case GSK_VULKAN_OP_CROSS_FADE:
     case GSK_VULKAN_OP_BLEND_MODE:
       return gsk_vulkan_pipeline_get_pipeline (op->render.pipeline);
 
@@ -2194,15 +2176,6 @@ gsk_vulkan_render_op_command (GskVulkanOp      *op_,
                                           &op->constants.clip);
           break;
 
-        case GSK_VULKAN_OP_CROSS_FADE:
-          if (!op->render.source || !op->render.source2)
-            break;
-          gsk_vulkan_cross_fade_pipeline_draw (GSK_VULKAN_CROSS_FADE_PIPELINE (op->render.pipeline),
-                                               command_buffer,
-                                               op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (op->render.pipeline),
-                                               1);
-          break;
-
         case GSK_VULKAN_OP_BLEND_MODE:
           if (!op->render.source || !op->render.source2)
             break;
index 307b4832ca3b68eeedaf5fe7228319ec7f67fb70..c61a9fa7da1668775fa5288b9b726a69631603d6 100644 (file)
@@ -32,9 +32,6 @@ typedef enum {
   GSK_VULKAN_PIPELINE_COLOR_TEXT,
   GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP,
   GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED,
-  GSK_VULKAN_PIPELINE_CROSS_FADE,
-  GSK_VULKAN_PIPELINE_CROSS_FADE_CLIP,
-  GSK_VULKAN_PIPELINE_CROSS_FADE_CLIP_ROUNDED,
   GSK_VULKAN_PIPELINE_BLEND_MODE,
   GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP,
   GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP_ROUNDED,