diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 4104b022df..14181f76ed 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -1047,6 +1047,67 @@ gsk_gpu_node_processor_create_cross_fade_pattern (GskGpuPatternWriter *self, return TRUE; } +static gboolean +gsk_gpu_node_processor_create_mask_pattern (GskGpuPatternWriter *self, + GskRenderNode *node) +{ + GskRenderNode *source_child, *mask_child; + + source_child = gsk_mask_node_get_source (node); + mask_child = gsk_mask_node_get_mask (node); + + if (!gsk_gpu_node_processor_create_node_pattern (self, source_child)) + return FALSE; + if (!gsk_rect_contains_rect (&source_child->bounds, &node->bounds)) + { + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_CLIP); + gsk_gpu_buffer_writer_append_rect (&self->writer, &source_child->bounds, &self->offset); + } + + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_PUSH_COLOR); + + if (!gsk_gpu_pattern_writer_push_stack (self)) + return FALSE; + + if (!gsk_gpu_node_processor_create_node_pattern (self, mask_child)) + { + gsk_gpu_pattern_writer_pop_stack (self); + return FALSE; + } + if (!gsk_rect_contains_rect (&mask_child->bounds, &node->bounds)) + { + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_CLIP); + gsk_gpu_buffer_writer_append_rect (&self->writer, &mask_child->bounds, &self->offset); + } + + switch (gsk_mask_node_get_mask_mode (node)) + { + case GSK_MASK_MODE_ALPHA: + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_POP_MASK_ALPHA); + break; + + case GSK_MASK_MODE_INVERTED_ALPHA: + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_POP_MASK_INVERTED_ALPHA); + break; + + case GSK_MASK_MODE_LUMINANCE: + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_POP_MASK_LUMINANCE); + break; + + case GSK_MASK_MODE_INVERTED_LUMINANCE: + gsk_gpu_buffer_writer_append_uint (&self->writer, GSK_GPU_PATTERN_POP_MASK_INVERTED_LUMINANCE); + break; + + default: + g_return_val_if_reached (FALSE); + } + + + gsk_gpu_pattern_writer_pop_stack (self); + + return TRUE; +} + static void gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self, GskRenderNode *node) @@ -1448,8 +1509,8 @@ static const struct }, [GSK_MASK_NODE] = { 0, - NULL, - NULL, + gsk_gpu_node_processor_add_node_as_pattern, + gsk_gpu_node_processor_create_mask_pattern, }, [GSK_FILL_NODE] = { 0, diff --git a/gsk/gpu/gskgputypesprivate.h b/gsk/gpu/gskgputypesprivate.h index 512003c80b..18469a8814 100644 --- a/gsk/gpu/gskgputypesprivate.h +++ b/gsk/gpu/gskgputypesprivate.h @@ -47,5 +47,9 @@ typedef enum { GSK_GPU_PATTERN_POSITION_POP, GSK_GPU_PATTERN_PUSH_COLOR, GSK_GPU_PATTERN_POP_CROSS_FADE, + GSK_GPU_PATTERN_POP_MASK_ALPHA, + GSK_GPU_PATTERN_POP_MASK_INVERTED_ALPHA, + GSK_GPU_PATTERN_POP_MASK_LUMINANCE, + GSK_GPU_PATTERN_POP_MASK_INVERTED_LUMINANCE, } GskGpuPatternType; diff --git a/gsk/gpu/shaders/color.glsl b/gsk/gpu/shaders/color.glsl index 4ab9a567bf..3f18784593 100644 --- a/gsk/gpu/shaders/color.glsl +++ b/gsk/gpu/shaders/color.glsl @@ -13,4 +13,10 @@ color_unpremultiply (vec4 color) return color.a > 0.0 ? color / vec4 (color.aaa, 1.0) : color; } +float +luminance (vec3 color) +{ + return dot (vec3 (0.2126, 0.7152, 0.0722), color); +} + #endif /* _COLOR_ */ diff --git a/gsk/gpu/shaders/enums.glsl b/gsk/gpu/shaders/enums.glsl index 7635baf63d..771fba85a7 100644 --- a/gsk/gpu/shaders/enums.glsl +++ b/gsk/gpu/shaders/enums.glsl @@ -24,6 +24,10 @@ #define GSK_GPU_PATTERN_POSITION_POP 14u #define GSK_GPU_PATTERN_PUSH_COLOR 15u #define GSK_GPU_PATTERN_POP_CROSS_FADE 16u +#define GSK_GPU_PATTERN_POP_MASK_ALPHA 17u +#define GSK_GPU_PATTERN_POP_MASK_INVERTED_ALPHA 18u +#define GSK_GPU_PATTERN_POP_MASK_LUMINANCE 19u +#define GSK_GPU_PATTERN_POP_MASK_INVERTED_LUMINANCE 20u #define TOP 0u #define RIGHT 1u diff --git a/gsk/gpu/shaders/pattern.glsl b/gsk/gpu/shaders/pattern.glsl index 3d84cee6d1..1ac8ba83b9 100644 --- a/gsk/gpu/shaders/pattern.glsl +++ b/gsk/gpu/shaders/pattern.glsl @@ -150,6 +150,42 @@ cross_fade_pattern (inout uint reader, color = mix (start, color, progress); } +void +mask_alpha_pattern (inout uint reader, + inout vec4 color) +{ + vec4 source = stack_pop (); + + color = source * color.a; +} + +void +mask_inverted_alpha_pattern (inout uint reader, + inout vec4 color) +{ + vec4 source = stack_pop (); + + color = source * (1.0 - color.a); +} + +void +mask_luminance_pattern (inout uint reader, + inout vec4 color) +{ + vec4 source = stack_pop (); + + color = source * luminance (color.rgb); +} + +void +mask_inverted_luminance_pattern (inout uint reader, + inout vec4 color) +{ + vec4 source = stack_pop (); + + color = source * (color.a - luminance (color.rgb)); +} + vec4 glyphs_pattern (inout uint reader, vec2 pos) @@ -311,6 +347,18 @@ pattern (uint reader, case GSK_GPU_PATTERN_POP_CROSS_FADE: cross_fade_pattern (reader, color); break; + case GSK_GPU_PATTERN_POP_MASK_ALPHA: + mask_alpha_pattern (reader, color); + break; + case GSK_GPU_PATTERN_POP_MASK_INVERTED_ALPHA: + mask_inverted_alpha_pattern (reader, color); + break; + case GSK_GPU_PATTERN_POP_MASK_LUMINANCE: + mask_luminance_pattern (reader, color); + break; + case GSK_GPU_PATTERN_POP_MASK_INVERTED_LUMINANCE: + mask_inverted_luminance_pattern (reader, color); + break; } } }