[gtk+] vulkan: Add proof-of-concept clip implementation



commit aa0ec774bf7d4b63641b1cdc887103cb7da65f55
Author: Benjamin Otte <otte redhat com>
Date:   Sat Dec 24 06:16:54 2016 +0100

    vulkan: Add proof-of-concept clip implementation
    
    We can now clip to cicular rounded rectangles when drawing colors.

 gsk/gskvulkanrender.c                             |    3 +-
 gsk/gskvulkanrenderpass.c                         |    9 +++-
 gsk/gskvulkanrenderprivate.h                      |    1 +
 gsk/resources/vulkan/color-clip-rounded.frag.glsl |   51 +++++++++++++++++++++
 gsk/resources/vulkan/color-clip-rounded.frag.spv  |  Bin 0 -> 5228 bytes
 gsk/resources/vulkan/color-clip-rounded.vert.glsl |   36 +++++++++++++++
 gsk/resources/vulkan/color-clip-rounded.vert.spv  |  Bin 0 -> 2176 bytes
 7 files changed, 97 insertions(+), 3 deletions(-)
---
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index e2e8167..d23ff8c 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -314,7 +314,8 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender       *self,
     GskVulkanPipeline * (* create_func) (GskVulkanPipelineLayout *layout, const char *name, VkRenderPass 
render_pass);
   } pipeline_info[GSK_VULKAN_N_PIPELINES] = {
     { "blit", gsk_vulkan_blend_pipeline_new },
-    { "color", gsk_vulkan_color_pipeline_new }
+    { "color", gsk_vulkan_color_pipeline_new },
+    { "color-clip-rounded", gsk_vulkan_color_pipeline_new }
   };
 
   g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL);
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index dc26f31..21a5cb9 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -98,6 +98,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     .type = GSK_VULKAN_OP_FALLBACK,
     .render.node = node
   };
+  GskVulkanPipelineType pipeline_type;
 
   switch (gsk_render_node_get_node_type (node))
     {
@@ -126,10 +127,14 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
       return;
 
     case GSK_COLOR_NODE:
-      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+      if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        pipeline_type = GSK_VULKAN_PIPELINE_COLOR;
+      else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
+        pipeline_type = GSK_VULKAN_PIPELINE_COLOR_CLIP_ROUNDED;
+      else
         FALLBACK ("Color nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_COLOR;
-      op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR);
+      op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
       g_array_append_val (self->render_ops, op);
       return;
 
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index e44f263..c5f7379 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
 typedef enum {
   GSK_VULKAN_PIPELINE_BLIT,
   GSK_VULKAN_PIPELINE_COLOR,
+  GSK_VULKAN_PIPELINE_COLOR_CLIP_ROUNDED,
   /* add more */
   GSK_VULKAN_N_PIPELINES
 } GskVulkanPipelineType;
diff --git a/gsk/resources/vulkan/color-clip-rounded.frag.glsl 
b/gsk/resources/vulkan/color-clip-rounded.frag.glsl
new file mode 100644
index 0000000..9825f78
--- /dev/null
+++ b/gsk/resources/vulkan/color-clip-rounded.frag.glsl
@@ -0,0 +1,51 @@
+#version 420 core
+
+layout(location = 0) in vec2 inPos;
+layout(location = 1) in vec4 inColor;
+layout(location = 2) in vec4 inClipBounds;
+layout(location = 3) in vec4 inClipWidths;
+
+layout(location = 0) out vec4 color;
+
+struct RoundedRect {
+  vec4 bounds;
+  vec4 corners;
+};
+
+float clip(vec2 pos, RoundedRect r) {
+  vec2 ref_tl = r.bounds.xy + vec2( r.corners.x,  r.corners.x);
+  vec2 ref_tr = r.bounds.zy + vec2(-r.corners.y,  r.corners.y);
+  vec2 ref_br = r.bounds.zw + vec2(-r.corners.z, -r.corners.z);
+  vec2 ref_bl = r.bounds.xw + vec2( r.corners.w, -r.corners.w);
+  
+  float d_tl = distance(pos, ref_tl);
+  float d_tr = distance(pos, ref_tr);
+  float d_br = distance(pos, ref_br);
+  float d_bl = distance(pos, ref_bl);
+
+  float pixels_per_fragment = length(fwidth(pos.xy));
+  float nudge = 0.5 * pixels_per_fragment;
+  vec4 distances = vec4(d_tl, d_tr, d_br, d_bl) - r.corners + nudge;
+
+  bvec4 is_out = bvec4(pos.x < ref_tl.x && pos.y < ref_tl.y,
+                       pos.x > ref_tr.x && pos.y < ref_tr.y,
+                       pos.x > ref_br.x && pos.y > ref_br.y,
+                       pos.x < ref_bl.x && pos.y > ref_bl.y);
+
+  float distance_from_border = dot(vec4(is_out),
+                                   max(vec4(0.0, 0.0, 0.0, 0.0), distances));
+
+  // Move the distance back into pixels.
+  distance_from_border /= pixels_per_fragment;
+  // Apply a more gradual fade out to transparent.
+  //distance_from_border -= 0.5;
+
+  return 1.0 - smoothstep(0.0, 1.0, distance_from_border);
+}
+
+void main()
+{
+    RoundedRect r = RoundedRect(vec4(inClipBounds.xy, inClipBounds.xy + inClipBounds.zw), inClipWidths);
+
+    color = vec4(inColor.rgb * inColor.a, inColor.a) * clip (inPos, r);
+}
diff --git a/gsk/resources/vulkan/color-clip-rounded.frag.spv 
b/gsk/resources/vulkan/color-clip-rounded.frag.spv
new file mode 100644
index 0000000..cf650af
Binary files /dev/null and b/gsk/resources/vulkan/color-clip-rounded.frag.spv differ
diff --git a/gsk/resources/vulkan/color-clip-rounded.vert.glsl 
b/gsk/resources/vulkan/color-clip-rounded.vert.glsl
new file mode 100644
index 0000000..a3c5535
--- /dev/null
+++ b/gsk/resources/vulkan/color-clip-rounded.vert.glsl
@@ -0,0 +1,36 @@
+#version 420 core
+
+layout(location = 0) in vec4 inRect;
+layout(location = 1) in vec4 inColor;
+
+layout(push_constant) uniform PushConstants {
+    mat4 mvp;
+    vec4 clip_bounds;
+    vec4 clip_widths;
+    vec4 clip_heights;
+} push;
+
+layout(location = 0) out vec2 outPos;
+layout(location = 1) out flat vec4 outColor;
+layout(location = 2) out flat vec4 outClipBounds;
+layout(location = 3) out flat vec4 outClipWidths;
+
+out gl_PerVertex {
+  vec4 gl_Position;
+};
+
+vec2 offsets[6] = { vec2(0.0, 0.0),
+                    vec2(1.0, 0.0),
+                    vec2(0.0, 1.0),
+                    vec2(0.0, 1.0),
+                    vec2(1.0, 0.0),
+                    vec2(1.0, 1.0) };
+
+void main() {
+  vec2 pos = inRect.xy + inRect.zw * offsets[gl_VertexIndex];
+  gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+  outPos = pos;
+  outColor = inColor;
+  outClipBounds = push.clip_bounds;
+  outClipWidths = push.clip_widths;
+}
diff --git a/gsk/resources/vulkan/color-clip-rounded.vert.spv 
b/gsk/resources/vulkan/color-clip-rounded.vert.spv
new file mode 100644
index 0000000..4414e99
Binary files /dev/null and b/gsk/resources/vulkan/color-clip-rounded.vert.spv differ


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