From ffc117564b32aa96ab4b24a825ecb0cde265c015 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 31 Aug 2023 13:27:25 +0200 Subject: [PATCH] gpu: Make patterns do opacity nodes Of course, for now this only works for opacity nodes that contain color nodes, but we're still building up to ore useful stuff here. --- gsk/gpu/gskgpunodeprocessor.c | 28 ++++++++++++++- gsk/gpu/gskgpupattern.c | 39 +++++++++++++++++--- gsk/gpu/gskgpupatternprivate.h | 2 ++ gsk/gpu/shaders/enums.glsl | 4 ++- gsk/gpu/shaders/pattern.glsl | 66 +++++++++++++++++++++++++--------- 5 files changed, 116 insertions(+), 23 deletions(-) diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index bc2f9b9c95..c83ffba9e6 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -601,6 +601,32 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self, pattern_id); } +static void +gsk_gpu_node_processor_add_opacity_node (GskGpuNodeProcessor *self, + GskRenderNode *node) +{ + GskGpuBufferWriter writer; + guint32 pattern_id; + + gsk_gpu_frame_write_buffer_memory (self->frame, &writer); + + if (!gsk_gpu_pattern_create_for_node (&writer, node)) + { + gsk_gpu_buffer_writer_abort (&writer); + GSK_DEBUG (FALLBACK, "Color node children can't be turned into pattern"); + gsk_gpu_node_processor_add_fallback_node (self, node); + return; + } + + pattern_id = gsk_gpu_buffer_writer_commit (&writer) / sizeof (float); + + gsk_gpu_uber_op (self->frame, + gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds), + &node->bounds, + &self->offset, + pattern_id); +} + static void gsk_gpu_node_processor_add_container_node (GskGpuNodeProcessor *self, GskRenderNode *node) @@ -673,7 +699,7 @@ static const struct }, [GSK_OPACITY_NODE] = { 0, - NULL, + gsk_gpu_node_processor_add_opacity_node, }, [GSK_COLOR_MATRIX_NODE] = { 0, diff --git a/gsk/gpu/gskgpupattern.c b/gsk/gpu/gskgpupattern.c index e1dc87b1c2..1992677f56 100644 --- a/gsk/gpu/gskgpupattern.c +++ b/gsk/gpu/gskgpupattern.c @@ -4,6 +4,10 @@ #include "gskrendernode.h" +static gboolean +gsk_gpu_pattern_create_internal (GskGpuBufferWriter *writer, + GskRenderNode *node); + static gboolean gsk_gpu_pattern_create_for_color_node (GskGpuBufferWriter *writer, GskRenderNode *node) @@ -21,6 +25,19 @@ gsk_gpu_pattern_create_for_color_node (GskGpuBufferWriter *writer, return TRUE; } +static gboolean +gsk_gpu_pattern_create_for_opacity_node (GskGpuBufferWriter *writer, + GskRenderNode *node) +{ + if (!gsk_gpu_pattern_create_internal (writer, gsk_opacity_node_get_child (node))) + return FALSE; + + gsk_gpu_buffer_writer_append_uint (writer, GSK_GPU_PATTERN_OPACITY); + gsk_gpu_buffer_writer_append_float (writer, gsk_opacity_node_get_opacity (node)); + + return TRUE; +} + static const struct { gboolean (* create_for_node) (GskGpuBufferWriter *writer, @@ -69,7 +86,7 @@ static const struct NULL, }, [GSK_OPACITY_NODE] = { - NULL, + gsk_gpu_pattern_create_for_opacity_node, }, [GSK_COLOR_MATRIX_NODE] = { NULL, @@ -118,8 +135,8 @@ static const struct }, }; -gboolean -gsk_gpu_pattern_create_for_node (GskGpuBufferWriter *writer, +static gboolean +gsk_gpu_pattern_create_internal (GskGpuBufferWriter *writer, GskRenderNode *node) { GskRenderNodeType node_type; @@ -134,5 +151,19 @@ gsk_gpu_pattern_create_for_node (GskGpuBufferWriter *writer, if (nodes_vtable[node_type].create_for_node == NULL) return FALSE; - return nodes_vtable[node_type].create_for_node (writer, node); + if (!nodes_vtable[node_type].create_for_node (writer, node)) + return FALSE; + + return TRUE; +} + +gboolean +gsk_gpu_pattern_create_for_node (GskGpuBufferWriter *writer, + GskRenderNode *node) +{ + if (!gsk_gpu_pattern_create_internal (writer, node)) + return FALSE; + + gsk_gpu_buffer_writer_append_uint (writer, GSK_GPU_PATTERN_DONE); + return TRUE; } diff --git a/gsk/gpu/gskgpupatternprivate.h b/gsk/gpu/gskgpupatternprivate.h index 39993dfe03..73be488ba4 100644 --- a/gsk/gpu/gskgpupatternprivate.h +++ b/gsk/gpu/gskgpupatternprivate.h @@ -7,7 +7,9 @@ G_BEGIN_DECLS typedef enum { + GSK_GPU_PATTERN_DONE, GSK_GPU_PATTERN_COLOR, + GSK_GPU_PATTERN_OPACITY, } GskGpuPatternType; gboolean gsk_gpu_pattern_create_for_node (GskGpuBufferWriter *writer, diff --git a/gsk/gpu/shaders/enums.glsl b/gsk/gpu/shaders/enums.glsl index 683a009270..b5274a8a74 100644 --- a/gsk/gpu/shaders/enums.glsl +++ b/gsk/gpu/shaders/enums.glsl @@ -5,6 +5,8 @@ #define GSK_GPU_SHADER_CLIP_RECT 1u #define GSK_GPU_SHADER_CLIP_ROUNDED 2u -#define GSK_GPU_PATTERN_COLOR 0 +#define GSK_GPU_PATTERN_DONE 0u +#define GSK_GPU_PATTERN_COLOR 1u +#define GSK_GPU_PATTERN_OPACITY 2u #endif diff --git a/gsk/gpu/shaders/pattern.glsl b/gsk/gpu/shaders/pattern.glsl index e17353145d..6b64dfd241 100644 --- a/gsk/gpu/shaders/pattern.glsl +++ b/gsk/gpu/shaders/pattern.glsl @@ -5,36 +5,68 @@ #ifdef GSK_FRAGMENT_SHADER -vec4 -gsk_get_vec4 (uint id) +uint +read_uint (inout uint reader) { - return vec4 (gsk_get_float (id), - gsk_get_float (id + 1), - gsk_get_float (id + 2), - gsk_get_float (id + 3)); + uint result = gsk_get_uint (reader); + reader++; + return result; +} + +float +read_float (inout uint reader) +{ + float result = gsk_get_float (reader); + reader++; + return result; } vec4 -color_pattern (uint pattern) +read_vec4 (inout uint reader) { - vec4 color = gsk_get_vec4 (pattern); + return vec4 (read_float (reader), read_float (reader), read_float (reader), read_float (reader)); +} + +void +opacity_pattern (inout uint reader, + inout vec4 color, + vec2 pos) +{ + float opacity = read_float (reader); + + color *= opacity; +} + +vec4 +color_pattern (inout uint reader) +{ + vec4 color = read_vec4 (reader); return color_premultiply (color); } vec4 -pattern (uint pattern, +pattern (uint reader, vec2 pos) { - uint type = gsk_get_uint (pattern); + vec4 color = vec4 (1.0, 0.0, 0.8, 1.0); /* pink */ - switch (type) - { - case GSK_GPU_PATTERN_COLOR: - return color_pattern (pattern + 1); - default: - return vec4 (1.0, 0.0, 0.8, 1.0); /* pink */ - } + for(;;) + { + uint type = read_uint (reader); + switch (type) + { + default: + case GSK_GPU_PATTERN_DONE: + return color; + case GSK_GPU_PATTERN_COLOR: + color = color_pattern (reader); + break; + case GSK_GPU_PATTERN_OPACITY: + opacity_pattern (reader, color, pos); + break; + } + } } #endif