[gtk+] vulkan: Add shader for border rendering
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] vulkan: Add shader for border rendering
- Date: Wed, 11 Jan 2017 17:36:35 +0000 (UTC)
commit b186bce7ff4febcb3fd7cd77a0c40ab7dcb4886b
Author: Benjamin Otte <otte redhat com>
Date: Tue Jan 10 14:59:20 2017 +0100
vulkan: Add shader for border rendering
gsk/Makefile.am | 12 ++-
gsk/gskrendernodeimpl.c | 12 +-
gsk/gskrendernodeprivate.h | 4 +-
gsk/gskvulkanborderpipeline.c | 163 ++++++++++++++++++++
gsk/gskvulkanborderpipelineprivate.h | 34 ++++
gsk/gskvulkanrender.c | 6 +-
gsk/gskvulkanrenderpass.c | 58 +++++++-
gsk/gskvulkanrenderprivate.h | 3 +
gsk/resources/vulkan/border-clip-rounded.frag.glsl | 34 ++++
gsk/resources/vulkan/border-clip-rounded.frag.spv | Bin 0 -> 9832 bytes
gsk/resources/vulkan/border-clip-rounded.vert.glsl | 123 +++++++++++++++
gsk/resources/vulkan/border-clip-rounded.vert.spv | Bin 0 -> 9312 bytes
gsk/resources/vulkan/border-clip.frag.glsl | 23 +++
gsk/resources/vulkan/border-clip.frag.spv | Bin 0 -> 9008 bytes
gsk/resources/vulkan/border-clip.vert.glsl | 117 ++++++++++++++
gsk/resources/vulkan/border-clip.vert.spv | Bin 0 -> 8952 bytes
gsk/resources/vulkan/border.frag.glsl | 23 +++
gsk/resources/vulkan/border.frag.spv | Bin 0 -> 9008 bytes
gsk/resources/vulkan/border.vert.glsl | 106 +++++++++++++
gsk/resources/vulkan/border.vert.spv | Bin 0 -> 7216 bytes
gsk/resources/vulkan/rounded-rect.glsl | 69 ++++++++
21 files changed, 775 insertions(+), 12 deletions(-)
---
diff --git a/gsk/Makefile.am b/gsk/Makefile.am
index e176dd2..e74529c 100644
--- a/gsk/Makefile.am
+++ b/gsk/Makefile.am
@@ -25,6 +25,7 @@ noinst_LTLIBRARIES =
if HAVE_VULKAN
gsk_private_vulkan_source_h = \
gskvulkanblendpipelineprivate.h \
+ gskvulkanborderpipelineprivate.h \
gskvulkanbufferprivate.h \
gskvulkanclipprivate.h \
gskvulkancolorpipelineprivate.h \
@@ -41,6 +42,7 @@ gsk_private_vulkan_source_h = \
gskvulkanshaderprivate.h
gsk_private_vulkan_source_c = \
gskvulkanblendpipeline.c \
+ gskvulkanborderpipeline.c \
gskvulkanbuffer.c \
gskvulkanclip.c \
gskvulkancolorpipeline.c \
@@ -55,6 +57,8 @@ gsk_private_vulkan_source_c = \
gskvulkanrenderer.c \
gskvulkanrenderpass.c \
gskvulkanshader.c
+gsk_private_vulkan_include_shaders = \
+ resources/vulkan/rounded-rect.glsl
gsk_private_vulkan_shaders = \
resources/vulkan/blend-clip.frag.glsl \
resources/vulkan/blend-clip-rounded.frag.glsl \
@@ -62,6 +66,12 @@ gsk_private_vulkan_shaders = \
resources/vulkan/blend-clip.vert.glsl \
resources/vulkan/blend.frag.glsl \
resources/vulkan/blend.vert.glsl \
+ resources/vulkan/border-clip.frag.glsl \
+ resources/vulkan/border-clip.vert.glsl \
+ resources/vulkan/border-clip-rounded.frag.glsl \
+ resources/vulkan/border-clip-rounded.vert.glsl \
+ resources/vulkan/border.frag.glsl \
+ resources/vulkan/border.vert.glsl \
resources/vulkan/color-clip.frag.glsl \
resources/vulkan/color-clip-rounded.frag.glsl \
resources/vulkan/color-clip-rounded.vert.glsl \
@@ -199,7 +209,7 @@ gskresources.c: gsk.resources.xml $(resource_files)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< \
--target=$@ --sourcedir=$(srcdir) --c-name _gsk --generate-source --manual-register
-EXTRA_DIST += $(resource_files)
+EXTRA_DIST += $(resource_files) $(gsk_private_vulkan_include_shaders)
CLEANFILES += gsk.resources.xml
DISTCLEANFILES += gskresources.h gskresources.c
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index af356d5..aaa6a92 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -593,22 +593,20 @@ gsk_border_node_peek_outline (GskRenderNode *node)
return &self->outline;
}
-float
-gsk_border_node_get_width (GskRenderNode *node,
- guint i)
+const float *
+gsk_border_node_peek_widths (GskRenderNode *node)
{
GskBorderNode *self = (GskBorderNode *) node;
- return self->border_width[i];
+ return self->border_width;
}
const GdkRGBA *
-gsk_border_node_peek_color (GskRenderNode *node,
- guint i)
+gsk_border_node_peek_colors (GskRenderNode *node)
{
GskBorderNode *self = (GskBorderNode *) node;
- return &self->border_color[i];
+ return self->border_color;
}
/**
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 938c948..52f7bc8 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -59,8 +59,8 @@ const gsize gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node);
const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node);
const GskRoundedRect * gsk_border_node_peek_outline (GskRenderNode *node);
-float gsk_border_node_get_width (GskRenderNode *node, guint i);
-const GdkRGBA * gsk_border_node_peek_color (GskRenderNode *node, guint i);
+const float * gsk_border_node_peek_widths (GskRenderNode *node);
+const GdkRGBA * gsk_border_node_peek_colors (GskRenderNode *node);
GskRenderNode *gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds, cairo_surface_t *surface);
cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node);
diff --git a/gsk/gskvulkanborderpipeline.c b/gsk/gskvulkanborderpipeline.c
new file mode 100644
index 0000000..ab6509b
--- /dev/null
+++ b/gsk/gskvulkanborderpipeline.c
@@ -0,0 +1,163 @@
+#include "config.h"
+
+#include "gskvulkanborderpipelineprivate.h"
+
+#include "gskroundedrectprivate.h"
+
+struct _GskVulkanBorderPipeline
+{
+ GObject parent_instance;
+};
+
+typedef struct _GskVulkanBorderInstance GskVulkanBorderInstance;
+
+struct _GskVulkanBorderInstance
+{
+ float rect[12];
+ float widths[4];
+ float colors[16];
+};
+
+G_DEFINE_TYPE (GskVulkanBorderPipeline, gsk_vulkan_border_pipeline, GSK_TYPE_VULKAN_PIPELINE)
+
+static const VkPipelineVertexInputStateCreateInfo *
+gsk_vulkan_border_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
+{
+ static const VkVertexInputBindingDescription vertexBindingDescriptions[] = {
+ {
+ .binding = 0,
+ .stride = sizeof (GskVulkanBorderInstance),
+ .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
+ }
+ };
+ static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = {
+ {
+ .location = 0,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect),
+ },
+ {
+ .location = 1,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect) + 4 * sizeof (float),
+ },
+ {
+ .location = 2,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect) + 8 * sizeof (float),
+ },
+ {
+ .location = 3,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, widths),
+ },
+ {
+ .location = 4,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors),
+ },
+ {
+ .location = 5,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 4 * sizeof (float),
+ },
+ {
+ .location = 6,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 8 * sizeof (float),
+ },
+ {
+ .location = 7,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 12 * sizeof (float),
+ }
+ };
+ static const VkPipelineVertexInputStateCreateInfo info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions),
+ .pVertexBindingDescriptions = vertexBindingDescriptions,
+ .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription),
+ .pVertexAttributeDescriptions = vertexInputAttributeDescription
+ };
+
+ return &info;
+}
+
+static void
+gsk_vulkan_border_pipeline_finalize (GObject *gobject)
+{
+ //GskVulkanBorderPipeline *self = GSK_VULKAN_BORDER_PIPELINE (gobject);
+
+ G_OBJECT_CLASS (gsk_vulkan_border_pipeline_parent_class)->finalize (gobject);
+}
+
+static void
+gsk_vulkan_border_pipeline_class_init (GskVulkanBorderPipelineClass *klass)
+{
+ GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass);
+
+ G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_border_pipeline_finalize;
+
+ pipeline_class->get_input_state_create_info = gsk_vulkan_border_pipeline_get_input_state_create_info;
+}
+
+static void
+gsk_vulkan_border_pipeline_init (GskVulkanBorderPipeline *self)
+{
+}
+
+GskVulkanPipeline *
+gsk_vulkan_border_pipeline_new (GskVulkanPipelineLayout *layout,
+ const char *shader_name,
+ VkRenderPass render_pass)
+{
+ return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BORDER_PIPELINE, layout, shader_name, render_pass);
+}
+
+gsize
+gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline *pipeline)
+{
+ return sizeof (GskVulkanBorderInstance);
+}
+
+void
+gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipeline,
+ guchar *data,
+ const GskRoundedRect *rect,
+ const float widths[4],
+ const GdkRGBA colors[4])
+{
+ GskVulkanBorderInstance *instance = (GskVulkanBorderInstance *) data;
+ guint i;
+
+ gsk_rounded_rect_to_float (rect, instance->rect);
+ for (i = 0; i < 4; i++)
+ {
+ instance->widths[i] = widths[i];
+ instance->colors[4 * i + 0] = colors[i].red;
+ instance->colors[4 * i + 1] = colors[i].green;
+ instance->colors[4 * i + 2] = colors[i].blue;
+ instance->colors[4 * i + 3] = colors[i].alpha;
+ }
+}
+
+gsize
+gsk_vulkan_border_pipeline_draw (GskVulkanBorderPipeline *pipeline,
+ VkCommandBuffer command_buffer,
+ gsize offset,
+ gsize n_commands)
+{
+ vkCmdDraw (command_buffer,
+ 6 * 8, n_commands,
+ 0, offset);
+
+ return n_commands;
+}
diff --git a/gsk/gskvulkanborderpipelineprivate.h b/gsk/gskvulkanborderpipelineprivate.h
new file mode 100644
index 0000000..de6d176
--- /dev/null
+++ b/gsk/gskvulkanborderpipelineprivate.h
@@ -0,0 +1,34 @@
+#ifndef __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__
+#define __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__
+
+#include <graphene.h>
+
+#include "gskvulkanpipelineprivate.h"
+#include "gskroundedrect.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GskVulkanBorderPipelineLayout GskVulkanBorderPipelineLayout;
+
+#define GSK_TYPE_VULKAN_BORDER_PIPELINE (gsk_vulkan_border_pipeline_get_type ())
+
+G_DECLARE_FINAL_TYPE (GskVulkanBorderPipeline, gsk_vulkan_border_pipeline, GSK, VULKAN_BORDER_PIPELINE,
GskVulkanPipeline)
+
+GskVulkanPipeline * gsk_vulkan_border_pipeline_new (GskVulkanPipelineLayout *
layout,
+ const char
*shader_name,
+ VkRenderPass
render_pass);
+
+gsize gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline
*pipeline);
+void gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline
*pipeline,
+ guchar
*data,
+ const GskRoundedRect
*rect,
+ const float
widths[4],
+ const GdkRGBA
colors[4]);
+gsize gsk_vulkan_border_pipeline_draw (GskVulkanBorderPipeline
*pipeline,
+ VkCommandBuffer
command_buffer,
+ gsize
offset,
+ gsize
n_commands);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__ */
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index 6c664ae..cd362d0 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -9,6 +9,7 @@
#include "gskvulkanrenderpassprivate.h"
#include "gskvulkanblendpipelineprivate.h"
+#include "gskvulkanborderpipelineprivate.h"
#include "gskvulkancolorpipelineprivate.h"
#include "gskvulkaneffectpipelineprivate.h"
#include "gskvulkanlineargradientpipelineprivate.h"
@@ -326,7 +327,10 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
{ "linear-clip-rounded", gsk_vulkan_linear_gradient_pipeline_new },
{ "color-matrix", gsk_vulkan_effect_pipeline_new },
{ "color-matrix-clip", gsk_vulkan_effect_pipeline_new },
- { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new }
+ { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new },
+ { "border", gsk_vulkan_border_pipeline_new },
+ { "border-clip", gsk_vulkan_border_pipeline_new },
+ { "border-clip-rounded", gsk_vulkan_border_pipeline_new }
};
g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL);
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index c500d90..c92375e 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -7,6 +7,7 @@
#include "gskrenderer.h"
#include "gskroundedrectprivate.h"
#include "gskvulkanblendpipelineprivate.h"
+#include "gskvulkanborderpipelineprivate.h"
#include "gskvulkanclipprivate.h"
#include "gskvulkancolorpipelineprivate.h"
#include "gskvulkaneffectpipelineprivate.h"
@@ -30,6 +31,7 @@ typedef enum {
GSK_VULKAN_OP_LINEAR_GRADIENT,
GSK_VULKAN_OP_OPACITY,
GSK_VULKAN_OP_COLOR_MATRIX,
+ GSK_VULKAN_OP_BORDER,
/* GskVulkanOpPushConstants */
GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS
} GskVulkanOpType;
@@ -110,9 +112,9 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_NOT_A_RENDER_NODE:
g_assert_not_reached ();
return;
- case GSK_BORDER_NODE:
case GSK_INSET_SHADOW_NODE:
case GSK_OUTSET_SHADOW_NODE:
+ case GSK_REPEAT_NODE:
case GSK_SHADOW_NODE:
case GSK_BLEND_NODE:
case GSK_CROSS_FADE_NODE:
@@ -210,6 +212,20 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
g_array_append_val (self->render_ops, op);
return;
+ case GSK_BORDER_NODE:
+ if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+ pipeline_type = GSK_VULKAN_PIPELINE_BORDER;
+ else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
+ pipeline_type = GSK_VULKAN_PIPELINE_BORDER_CLIP;
+ else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
+ pipeline_type = GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED;
+ else
+ FALLBACK ("Border nodes can't deal with clip type %u\n", constants->clip.type);
+ op.type = GSK_VULKAN_OP_BORDER;
+ op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
+ g_array_append_val (self->render_ops, op);
+ return;
+
case GSK_CONTAINER_NODE:
{
guint i;
@@ -499,6 +515,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+ case GSK_VULKAN_OP_BORDER:
break;
}
}
@@ -543,6 +560,11 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
n_bytes += op->render.vertex_count;
break;
+ case GSK_VULKAN_OP_BORDER:
+ op->render.vertex_count = gsk_vulkan_border_pipeline_count_vertex_data (GSK_VULKAN_BORDER_PIPELINE
(op->render.pipeline));
+ n_bytes += op->render.vertex_count;
+ break;
+
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
@@ -644,6 +666,18 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
}
break;
+ case GSK_VULKAN_OP_BORDER:
+ {
+ op->render.vertex_offset = offset + n_bytes;
+ gsk_vulkan_border_pipeline_collect_vertex_data (GSK_VULKAN_BORDER_PIPELINE (op->render.pipeline),
+ data + n_bytes + offset,
+ gsk_border_node_peek_outline (op->render.node),
+ gsk_border_node_peek_widths (op->render.node),
+ gsk_border_node_peek_colors (op->render.node));
+ n_bytes += op->render.vertex_count;
+ }
+ break;
+
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
@@ -684,6 +718,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+ case GSK_VULKAN_OP_BORDER:
break;
}
}
@@ -829,6 +864,27 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
current_draw_index, 1);
break;
+ case GSK_VULKAN_OP_BORDER:
+ if (current_pipeline != op->render.pipeline)
+ {
+ current_pipeline = op->render.pipeline;
+ vkCmdBindPipeline (command_buffer,
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ gsk_vulkan_pipeline_get_pipeline (current_pipeline));
+ vkCmdBindVertexBuffers (command_buffer,
+ 0,
+ 1,
+ (VkBuffer[1]) {
+ gsk_vulkan_buffer_get_buffer (vertex_buffer)
+ },
+ (VkDeviceSize[1]) { op->render.vertex_offset });
+ current_draw_index = 0;
+ }
+ current_draw_index += gsk_vulkan_border_pipeline_draw (GSK_VULKAN_BORDER_PIPELINE
(current_pipeline),
+ command_buffer,
+ current_draw_index, 1);
+ break;
+
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
gsk_vulkan_push_constants_push_vertex (&op->constants.constants,
command_buffer,
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index 6bfb8b0..ea9c751 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -22,6 +22,9 @@ typedef enum {
GSK_VULKAN_PIPELINE_COLOR_MATRIX,
GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP,
GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED,
+ GSK_VULKAN_PIPELINE_BORDER,
+ GSK_VULKAN_PIPELINE_BORDER_CLIP,
+ GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED,
/* add more */
GSK_VULKAN_N_PIPELINES
} GskVulkanPipelineType;
diff --git a/gsk/resources/vulkan/border-clip-rounded.frag.glsl
b/gsk/resources/vulkan/border-clip-rounded.frag.glsl
new file mode 100644
index 0000000..bf4ad65
--- /dev/null
+++ b/gsk/resources/vulkan/border-clip-rounded.frag.glsl
@@ -0,0 +1,34 @@
+#version 420 core
+
+#include "rounded-rect.glsl"
+
+layout(location = 0) in vec2 inPos;
+layout(location = 1) in vec4 inColor;
+layout(location = 2) in vec4 inRect;
+layout(location = 3) in vec4 inCornerWidths;
+layout(location = 4) in vec4 inCornerHeights;
+layout(location = 5) in vec4 inBorderWidths;
+layout(location = 6) in flat vec4 inClipBounds;
+layout(location = 7) in flat vec4 inClipWidths;
+layout(location = 8) in flat vec4 inClipHeights;
+
+layout(location = 0) out vec4 color;
+
+vec4
+clip (vec4 color)
+{
+ RoundedRect r = RoundedRect (vec4(inClipBounds.xy, inClipBounds.xy + inClipBounds.zw), inClipWidths,
inClipHeights);
+
+ return color * rounded_rect_coverage (r, inPos);
+}
+
+void main()
+{
+ RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths,
inCornerHeights);
+ RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths);
+
+ float alpha = clamp (rounded_rect_coverage (routside, inPos) -
+ rounded_rect_coverage (rinside, inPos),
+ 0.0, 1.0);
+ color = clip (inColor);
+}
diff --git a/gsk/resources/vulkan/border-clip-rounded.frag.spv
b/gsk/resources/vulkan/border-clip-rounded.frag.spv
new file mode 100644
index 0000000..401d7ae
Binary files /dev/null and b/gsk/resources/vulkan/border-clip-rounded.frag.spv differ
diff --git a/gsk/resources/vulkan/border-clip-rounded.vert.glsl
b/gsk/resources/vulkan/border-clip-rounded.vert.glsl
new file mode 100644
index 0000000..8939a95
--- /dev/null
+++ b/gsk/resources/vulkan/border-clip-rounded.vert.glsl
@@ -0,0 +1,123 @@
+#version 420 core
+
+layout(location = 0) in vec4 inRect;
+layout(location = 1) in vec4 inCornerWidths;
+layout(location = 2) in vec4 inCornerHeights;
+layout(location = 3) in vec4 inBorderWidths;
+layout(location = 4) in mat4 inBorderColors;
+
+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 outRect;
+layout(location = 3) out flat vec4 outCornerWidths;
+layout(location = 4) out flat vec4 outCornerHeights;
+layout(location = 5) out flat vec4 outBorderWidths;
+layout(location = 6) out flat vec4 outClipBounds;
+layout(location = 7) out flat vec4 outClipWidths;
+layout(location = 8) out flat vec4 outClipHeights;
+
+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(1.0, 1.0),
+ vec2(0.0, 1.0),
+ vec2(1.0, 0.0) };
+
+#define TOP 0
+#define RIGHT 1
+#define BOTTOM 2
+#define LEFT 3
+
+#define TOP_LEFT 0
+#define TOP_RIGHT 1
+#define BOTTOM_RIGHT 2
+#define BOTTOM_LEFT 3
+
+#define SLICE_TOP_LEFT 0
+#define SLICE_TOP 1
+#define SLICE_TOP_RIGHT 2
+#define SLICE_RIGHT 3
+#define SLICE_BOTTOM_RIGHT 4
+#define SLICE_BOTTOM 5
+#define SLICE_BOTTOM_LEFT 6
+#define SLICE_LEFT 7
+
+vec4 intersect(vec4 a, vec4 b)
+{
+ a = vec4(a.xy, a.xy + a.zw);
+ b = vec4(b.xy, b.xy + b.zw);
+ vec4 result = vec4(max(a.xy, b.xy), min(a.zw, b.zw));
+ if (any (greaterThanEqual (result.xy, result.zw)))
+ return vec4(0.0,0.0,0.0,0.0);
+ return vec4(result.xy, result.zw - result.xy);
+}
+
+void main() {
+ int slice_index = gl_VertexIndex / 6;
+ int vert_index = gl_VertexIndex % 6;
+
+ vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw);
+ vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz);
+
+ vec4 rect;
+
+ switch (slice_index)
+ {
+ case SLICE_TOP_LEFT:
+ rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_TOP:
+ rect = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] -
corner_widths[TOP_RIGHT], inBorderWidths[TOP]);
+ outColor = inBorderColors[TOP];
+ break;
+ case SLICE_TOP_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT],
corner_heights[TOP_RIGHT]);
+ break;
+ case SLICE_RIGHT:
+ rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT],
inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]);
+ outColor = inBorderColors[RIGHT];
+ break;
+ case SLICE_BOTTOM_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w -
corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]);
+ break;
+ case SLICE_BOTTOM:
+ rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM],
inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]);
+ break;
+ case SLICE_BOTTOM_LEFT:
+ rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT],
corner_heights[BOTTOM_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_LEFT:
+ rect = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w -
corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]);
+ break;
+ }
+
+ rect = intersect (rect, push.clip_bounds);
+ vec2 pos;
+ if ((slice_index % 4) != 0 || (vert_index % 3) != 2)
+ pos = rect.xy + rect.zw * offsets[vert_index];
+ else
+ pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y);
+ gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+ outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4];
+ outPos = pos;
+ outRect = inRect;
+ outCornerWidths = inCornerWidths;
+ outCornerHeights = inCornerHeights;
+ outBorderWidths = inBorderWidths;
+ outClipBounds = push.clip_bounds;
+ outClipWidths = push.clip_widths;
+ outClipHeights = push.clip_heights;
+}
diff --git a/gsk/resources/vulkan/border-clip-rounded.vert.spv
b/gsk/resources/vulkan/border-clip-rounded.vert.spv
new file mode 100644
index 0000000..5aae91a
Binary files /dev/null and b/gsk/resources/vulkan/border-clip-rounded.vert.spv differ
diff --git a/gsk/resources/vulkan/border-clip.frag.glsl b/gsk/resources/vulkan/border-clip.frag.glsl
new file mode 100644
index 0000000..5f9d709
--- /dev/null
+++ b/gsk/resources/vulkan/border-clip.frag.glsl
@@ -0,0 +1,23 @@
+#version 420 core
+
+#include "rounded-rect.glsl"
+
+layout(location = 0) in vec2 inPos;
+layout(location = 1) in flat vec4 inColor;
+layout(location = 2) in flat vec4 inRect;
+layout(location = 3) in flat vec4 inCornerWidths;
+layout(location = 4) in flat vec4 inCornerHeights;
+layout(location = 5) in flat vec4 inBorderWidths;
+
+layout(location = 0) out vec4 color;
+
+void main()
+{
+ RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths,
inCornerHeights);
+ RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths);
+
+ float alpha = clamp (rounded_rect_coverage (routside, inPos) -
+ rounded_rect_coverage (rinside, inPos),
+ 0.0, 1.0);
+ color = inColor * alpha;
+}
diff --git a/gsk/resources/vulkan/border-clip.frag.spv b/gsk/resources/vulkan/border-clip.frag.spv
new file mode 100644
index 0000000..ab43d3d
Binary files /dev/null and b/gsk/resources/vulkan/border-clip.frag.spv differ
diff --git a/gsk/resources/vulkan/border-clip.vert.glsl b/gsk/resources/vulkan/border-clip.vert.glsl
new file mode 100644
index 0000000..5de7a12
--- /dev/null
+++ b/gsk/resources/vulkan/border-clip.vert.glsl
@@ -0,0 +1,117 @@
+#version 420 core
+
+layout(location = 0) in vec4 inRect;
+layout(location = 1) in vec4 inCornerWidths;
+layout(location = 2) in vec4 inCornerHeights;
+layout(location = 3) in vec4 inBorderWidths;
+layout(location = 4) in mat4 inBorderColors;
+
+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 outRect;
+layout(location = 3) out flat vec4 outCornerWidths;
+layout(location = 4) out flat vec4 outCornerHeights;
+layout(location = 5) out flat vec4 outBorderWidths;
+
+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(1.0, 1.0),
+ vec2(0.0, 1.0),
+ vec2(1.0, 0.0) };
+
+#define TOP 0
+#define RIGHT 1
+#define BOTTOM 2
+#define LEFT 3
+
+#define TOP_LEFT 0
+#define TOP_RIGHT 1
+#define BOTTOM_RIGHT 2
+#define BOTTOM_LEFT 3
+
+#define SLICE_TOP_LEFT 0
+#define SLICE_TOP 1
+#define SLICE_TOP_RIGHT 2
+#define SLICE_RIGHT 3
+#define SLICE_BOTTOM_RIGHT 4
+#define SLICE_BOTTOM 5
+#define SLICE_BOTTOM_LEFT 6
+#define SLICE_LEFT 7
+
+vec4 intersect(vec4 a, vec4 b)
+{
+ a = vec4(a.xy, a.xy + a.zw);
+ b = vec4(b.xy, b.xy + b.zw);
+ vec4 result = vec4(max(a.xy, b.xy), min(a.zw, b.zw));
+ if (any (greaterThanEqual (result.xy, result.zw)))
+ return vec4(0.0,0.0,0.0,0.0);
+ return vec4(result.xy, result.zw - result.xy);
+}
+
+void main() {
+ int slice_index = gl_VertexIndex / 6;
+ int vert_index = gl_VertexIndex % 6;
+
+ vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw);
+ vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz);
+
+ vec4 rect;
+
+ switch (slice_index)
+ {
+ case SLICE_TOP_LEFT:
+ rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_TOP:
+ rect = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] -
corner_widths[TOP_RIGHT], inBorderWidths[TOP]);
+ outColor = inBorderColors[TOP];
+ break;
+ case SLICE_TOP_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT],
corner_heights[TOP_RIGHT]);
+ break;
+ case SLICE_RIGHT:
+ rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT],
inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]);
+ outColor = inBorderColors[RIGHT];
+ break;
+ case SLICE_BOTTOM_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w -
corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]);
+ break;
+ case SLICE_BOTTOM:
+ rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM],
inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]);
+ break;
+ case SLICE_BOTTOM_LEFT:
+ rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT],
corner_heights[BOTTOM_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_LEFT:
+ rect = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w -
corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]);
+ break;
+ }
+
+ rect = intersect (rect, push.clip_bounds);
+ vec2 pos;
+ if ((slice_index % 4) != 0 || (vert_index % 3) != 2)
+ pos = rect.xy + rect.zw * offsets[vert_index];
+ else
+ pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y);
+ gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+ outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4];
+ outPos = pos;
+ outRect = inRect;
+ outCornerWidths = inCornerWidths;
+ outCornerHeights = inCornerHeights;
+ outBorderWidths = inBorderWidths;
+}
diff --git a/gsk/resources/vulkan/border-clip.vert.spv b/gsk/resources/vulkan/border-clip.vert.spv
new file mode 100644
index 0000000..5a505d8
Binary files /dev/null and b/gsk/resources/vulkan/border-clip.vert.spv differ
diff --git a/gsk/resources/vulkan/border.frag.glsl b/gsk/resources/vulkan/border.frag.glsl
new file mode 100644
index 0000000..5f9d709
--- /dev/null
+++ b/gsk/resources/vulkan/border.frag.glsl
@@ -0,0 +1,23 @@
+#version 420 core
+
+#include "rounded-rect.glsl"
+
+layout(location = 0) in vec2 inPos;
+layout(location = 1) in flat vec4 inColor;
+layout(location = 2) in flat vec4 inRect;
+layout(location = 3) in flat vec4 inCornerWidths;
+layout(location = 4) in flat vec4 inCornerHeights;
+layout(location = 5) in flat vec4 inBorderWidths;
+
+layout(location = 0) out vec4 color;
+
+void main()
+{
+ RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths,
inCornerHeights);
+ RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths);
+
+ float alpha = clamp (rounded_rect_coverage (routside, inPos) -
+ rounded_rect_coverage (rinside, inPos),
+ 0.0, 1.0);
+ color = inColor * alpha;
+}
diff --git a/gsk/resources/vulkan/border.frag.spv b/gsk/resources/vulkan/border.frag.spv
new file mode 100644
index 0000000..ab43d3d
Binary files /dev/null and b/gsk/resources/vulkan/border.frag.spv differ
diff --git a/gsk/resources/vulkan/border.vert.glsl b/gsk/resources/vulkan/border.vert.glsl
new file mode 100644
index 0000000..48efbc7
--- /dev/null
+++ b/gsk/resources/vulkan/border.vert.glsl
@@ -0,0 +1,106 @@
+#version 420 core
+
+layout(location = 0) in vec4 inRect;
+layout(location = 1) in vec4 inCornerWidths;
+layout(location = 2) in vec4 inCornerHeights;
+layout(location = 3) in vec4 inBorderWidths;
+layout(location = 4) in mat4 inBorderColors;
+
+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 outRect;
+layout(location = 3) out flat vec4 outCornerWidths;
+layout(location = 4) out flat vec4 outCornerHeights;
+layout(location = 5) out flat vec4 outBorderWidths;
+
+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(1.0, 1.0),
+ vec2(0.0, 1.0),
+ vec2(1.0, 0.0) };
+
+#define TOP 0
+#define RIGHT 1
+#define BOTTOM 2
+#define LEFT 3
+
+#define TOP_LEFT 0
+#define TOP_RIGHT 1
+#define BOTTOM_RIGHT 2
+#define BOTTOM_LEFT 3
+
+#define SLICE_TOP_LEFT 0
+#define SLICE_TOP 1
+#define SLICE_TOP_RIGHT 2
+#define SLICE_RIGHT 3
+#define SLICE_BOTTOM_RIGHT 4
+#define SLICE_BOTTOM 5
+#define SLICE_BOTTOM_LEFT 6
+#define SLICE_LEFT 7
+
+void main() {
+ int slice_index = gl_VertexIndex / 6;
+ int vert_index = gl_VertexIndex % 6;
+
+ vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw);
+ vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz);
+
+ vec4 rect;
+
+ switch (slice_index)
+ {
+ case SLICE_TOP_LEFT:
+ rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_TOP:
+ rect = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] -
corner_widths[TOP_RIGHT], inBorderWidths[TOP]);
+ outColor = inBorderColors[TOP];
+ break;
+ case SLICE_TOP_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT],
corner_heights[TOP_RIGHT]);
+ break;
+ case SLICE_RIGHT:
+ rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT],
inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]);
+ outColor = inBorderColors[RIGHT];
+ break;
+ case SLICE_BOTTOM_RIGHT:
+ rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w -
corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]);
+ break;
+ case SLICE_BOTTOM:
+ rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM],
inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]);
+ break;
+ case SLICE_BOTTOM_LEFT:
+ rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT],
corner_heights[BOTTOM_LEFT]);
+ vert_index = (vert_index + 3) % 6;
+ break;
+ case SLICE_LEFT:
+ rect = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w -
corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]);
+ break;
+ }
+
+ vec2 pos;
+ if ((slice_index % 4) != 0 || (vert_index % 3) != 2)
+ pos = rect.xy + rect.zw * offsets[vert_index];
+ else
+ pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y);
+ gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
+ outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4];
+ outPos = pos;
+ outRect = inRect;
+ outCornerWidths = inCornerWidths;
+ outCornerHeights = inCornerHeights;
+ outBorderWidths = inBorderWidths;
+}
diff --git a/gsk/resources/vulkan/border.vert.spv b/gsk/resources/vulkan/border.vert.spv
new file mode 100644
index 0000000..384eebe
Binary files /dev/null and b/gsk/resources/vulkan/border.vert.spv differ
diff --git a/gsk/resources/vulkan/rounded-rect.glsl b/gsk/resources/vulkan/rounded-rect.glsl
new file mode 100644
index 0000000..e0c2ffc
--- /dev/null
+++ b/gsk/resources/vulkan/rounded-rect.glsl
@@ -0,0 +1,69 @@
+#ifndef _ROUNDED_RECT_
+#define _ROUNDED_RECT_
+
+struct RoundedRect
+{
+ vec4 bounds;
+ vec4 corner_widths;
+ vec4 corner_heights;
+};
+
+float
+ellipsis_dist (vec2 p, vec2 radius)
+{
+ vec2 p0 = p / radius;
+ vec2 p1 = 2.0 * p0 / radius;
+
+ return (dot(p0, p0) - 1.0) / length (p1);
+}
+
+float
+ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
+{
+ float d = ellipsis_dist (point - center, radius);
+ return clamp (0.5 - d, 0.0, 1.0);
+}
+
+float
+rounded_rect_coverage (RoundedRect r, vec2 p)
+{
+ if (p.x < r.bounds.x || p.y < r.bounds.y ||
+ p.x >= r.bounds.z || p.y >= r.bounds.w)
+ return 0.0;
+
+ vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
+ vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
+ vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
+ vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
+
+ vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x);
+ vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y);
+ vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
+ vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
+
+ float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
+ float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
+ float d_br = ellipsis_coverage(p, ref_br, rad_br);
+ float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
+
+ vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
+
+ bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
+ p.x > ref_tr.x && p.y < ref_tr.y,
+ p.x > ref_br.x && p.y > ref_br.y,
+ p.x < ref_bl.x && p.y > ref_bl.y);
+
+ return 1.0 - dot(vec4(is_out), corner_coverages);
+}
+
+RoundedRect
+rounded_rect_shrink (RoundedRect r, vec4 amount)
+{
+ vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
+ vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
+ vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
+
+ return RoundedRect (new_bounds, new_widths, new_heights);
+}
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]