vulkan: Add support for texture-scale nodes
authorBenjamin Otte <otte@redhat.com>
Tue, 23 May 2023 03:26:08 +0000 (05:26 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 4 Jun 2023 17:42:01 +0000 (19:42 +0200)
gsk/vulkan/gskvulkanrender.c
gsk/vulkan/gskvulkanrenderpass.c
gsk/vulkan/gskvulkanrenderprivate.h

index 12b84cb8c5b8dbb563b83766db8c72ecccf8d163..1957e75e48d4117fc0ed487bc15deae63b1e6d1d 100644 (file)
@@ -58,7 +58,7 @@ struct _GskVulkanRender
 
   GskVulkanImage *target;
 
-  VkSampler samplers[2];
+  VkSampler samplers[3];
 
   GList *render_passes;
   GSList *cleanup_images;
@@ -272,6 +272,21 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
                                  NULL,
                                  &self->samplers[GSK_VULKAN_SAMPLER_REPEAT]);
   
+  GSK_VK_CHECK (vkCreateSampler, device,
+                                 &(VkSamplerCreateInfo) {
+                                     .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+                                     .magFilter = VK_FILTER_NEAREST,
+                                     .minFilter = VK_FILTER_NEAREST,
+                                     .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+                                     .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+                                     .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+                                     .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+                                     .unnormalizedCoordinates = VK_FALSE,
+                                     .maxAnisotropy = 1.0,
+                                 },
+                                 NULL,
+                                 &self->samplers[GSK_VULKAN_SAMPLER_NEAREST]);
+  
 
   self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool);
 
index 1dc2e6286b34fa6474359338c479879efa1d9f51..6dd7fb0d7e6c1890d195937c70a765d0ee922c9c 100644 (file)
@@ -43,6 +43,7 @@ typedef enum {
   GSK_VULKAN_OP_FALLBACK_CLIP,
   GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP,
   GSK_VULKAN_OP_TEXTURE,
+  GSK_VULKAN_OP_TEXTURE_SCALE,
   GSK_VULKAN_OP_COLOR,
   GSK_VULKAN_OP_LINEAR_GRADIENT,
   GSK_VULKAN_OP_OPACITY,
@@ -496,6 +497,34 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass       *self,
   return TRUE;
 }
 
+static inline gboolean
+gsk_vulkan_render_pass_add_texture_scale_node (GskVulkanRenderPass       *self,
+                                               GskVulkanRender           *render,
+                                               const GskVulkanParseState *state,
+                                               GskRenderNode             *node)
+{
+  GskVulkanPipelineType pipeline_type;
+  GskVulkanOp op = {
+    .render.type = GSK_VULKAN_OP_TEXTURE_SCALE,
+    .render.node = node,
+    .render.offset = state->offset,
+  };
+
+  if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds))
+    pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE;
+  else if (state->clip.type == GSK_VULKAN_CLIP_RECT)
+    pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP;
+  else if (state->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
+    pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED;
+  else
+    FALLBACK ("Texture nodes can't deal with clip type %u", state->clip.type);
+
+  op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
+  g_array_append_val (self->render_ops, op);
+
+  return TRUE;
+}
+
 static inline gboolean
 gsk_vulkan_render_pass_add_inset_shadow_node (GskVulkanRenderPass       *self,
                                               GskVulkanRender           *render,
@@ -1162,7 +1191,7 @@ static const GskVulkanRenderPassNodeFunc nodes_vtable[N_RENDER_NODES] = {
   [GSK_BLUR_NODE] = gsk_vulkan_render_pass_add_blur_node,
   [GSK_DEBUG_NODE] = gsk_vulkan_render_pass_add_debug_node,
   [GSK_GL_SHADER_NODE] = NULL,
-  [GSK_TEXTURE_SCALE_NODE] = NULL,
+  [GSK_TEXTURE_SCALE_NODE] = gsk_vulkan_render_pass_add_texture_scale_node,
   [GSK_MASK_NODE] = NULL,
 };
 
@@ -1544,6 +1573,16 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
           }
           break;
 
+        case GSK_VULKAN_OP_TEXTURE_SCALE:
+          {
+            op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
+                                                                       gsk_texture_scale_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;
+
         case GSK_VULKAN_OP_OPACITY:
           {
             GskRenderNode *child = gsk_opacity_node_get_child (op->render.node);
@@ -1761,6 +1800,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
         case GSK_VULKAN_OP_FALLBACK_CLIP:
         case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
         case GSK_VULKAN_OP_TEXTURE:
+        case GSK_VULKAN_OP_TEXTURE_SCALE:
         case GSK_VULKAN_OP_REPEAT:
         case GSK_VULKAN_OP_COLOR:
         case GSK_VULKAN_OP_LINEAR_GRADIENT:
@@ -1816,6 +1856,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_FALLBACK_CLIP:
         case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
         case GSK_VULKAN_OP_TEXTURE:
+        case GSK_VULKAN_OP_TEXTURE_SCALE:
           gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (op->render.pipeline),
                                                            data + op->render.vertex_offset,
                                                            op->render.image_descriptor,
@@ -2071,6 +2112,25 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
             }
           break;
 
+        case GSK_VULKAN_OP_TEXTURE_SCALE:
+          if (op->render.source)
+            {
+              op->render.image_descriptor[0] = gsk_vulkan_render_get_image_descriptor (render, op->render.source);
+              switch (gsk_texture_scale_node_get_filter (op->render.node))
+                {
+                default:
+                  g_assert_not_reached ();
+                case GSK_SCALING_FILTER_LINEAR:
+                case GSK_SCALING_FILTER_TRILINEAR:
+                  op->render.image_descriptor[1] = gsk_vulkan_render_get_sampler_descriptor (render, GSK_VULKAN_SAMPLER_DEFAULT);
+                  break;
+                case GSK_SCALING_FILTER_NEAREST:
+                  op->render.image_descriptor[1] = gsk_vulkan_render_get_sampler_descriptor (render, GSK_VULKAN_SAMPLER_NEAREST);
+                  break;
+                }
+            }
+          break;
+
         case GSK_VULKAN_OP_REPEAT:
           if (op->render.source)
             {
@@ -2144,6 +2204,7 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
         case GSK_VULKAN_OP_FALLBACK_CLIP:
         case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
         case GSK_VULKAN_OP_TEXTURE:
+        case GSK_VULKAN_OP_TEXTURE_SCALE:
         case GSK_VULKAN_OP_REPEAT:
           if (!op->render.source)
             continue;
index 51a9f00f876a96c3eeae6ee5b40e0582ab7d0d35..70771a078a27a51bb45339155c55195a0db85b92 100644 (file)
@@ -53,7 +53,8 @@ typedef enum {
 
 typedef enum {
   GSK_VULKAN_SAMPLER_DEFAULT,
-  GSK_VULKAN_SAMPLER_REPEAT
+  GSK_VULKAN_SAMPLER_REPEAT,
+  GSK_VULKAN_SAMPLER_NEAREST
 } GskVulkanRenderSampler;
 
 GskVulkanRender *       gsk_vulkan_render_new                           (GskRenderer            *renderer,