diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-12-14 15:32:58 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-12-14 15:32:58 -0500 |
commit | 51ad547995c131e601d671b7027a84850aa60303 (patch) | |
tree | 00d9a3fd796e678d23790c0b320fbffbd129699c | |
parent | df48be7c4ceb2f9f4384f83c53341aa42ccc4ca6 (diff) | |
download | gtk+-wip/matthiasc/mask-node.tar.gz |
gl: Add a shader for mask nodeswip/matthiasc/mask-node
-rw-r--r-- | gsk/gl/gskglrenderer.c | 67 | ||||
-rw-r--r-- | gsk/gl/gskglrenderopsprivate.h | 6 | ||||
-rw-r--r-- | gsk/gl/opbuffer.c | 1 | ||||
-rw-r--r-- | gsk/gl/opbuffer.h | 6 | ||||
-rw-r--r-- | gsk/meson.build | 1 | ||||
-rw-r--r-- | gsk/resources/glsl/mask.glsl | 15 |
6 files changed, 94 insertions, 2 deletions
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index a740dcf119..bfb21d2882 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -2717,6 +2717,48 @@ render_cross_fade_node (GskGLRenderer *self, } static inline void +render_mask_node (GskGLRenderer *self, + GskRenderNode *node, + RenderOpBuilder *builder) +{ + GskRenderNode *source = gsk_mask_node_get_source (node); + GskRenderNode *mask = gsk_mask_node_get_mask (node); + TextureRegion source_region; + TextureRegion mask_region; + gboolean is_offscreen1, is_offscreen2; + OpMask *op; + + if (!add_offscreen_ops (self, builder, + &node->bounds, + source, + &source_region, &is_offscreen1, + FORCE_OFFSCREEN | RESET_CLIP)) + { + gsk_gl_renderer_add_render_ops (self, source, builder); + return; + } + + if (!add_offscreen_ops (self, builder, + &node->bounds, + mask, + &mask_region, &is_offscreen2, + FORCE_OFFSCREEN | RESET_CLIP)) + { + gsk_gl_renderer_add_render_ops (self, source, builder); + return; + } + + ops_set_program (builder, &self->programs->mask_program); + + op = ops_begin (builder, OP_CHANGE_MASK); + op->mask = mask_region.texture_id; + + ops_set_texture (builder, source_region.texture_id); + + load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder); +} + +static inline void render_blend_node (GskGLRenderer *self, GskRenderNode *node, RenderOpBuilder *builder) @@ -3203,6 +3245,17 @@ apply_repeat_op (const Program *program, glUniform4fv (program->repeat.texture_rect_location, 1, op->texture_rect); } +static inline void +apply_mask_op (const Program *program, + const OpMask *op) +{ + OP_PRINT (" -> Mask "); + /* Mask texture id */ + glUniform1i (program->mask.mask_location, 1); + glActiveTexture (GL_TEXTURE0 + 1); + glBindTexture (GL_TEXTURE_2D, op->mask); +} + static void gsk_gl_renderer_dispose (GObject *gobject) { @@ -3326,6 +3379,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, { "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" }, { "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" }, { "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" }, + { "/org/gtk/libgsk/glsl/mask.glsl", "mask" }, }; gsk_gl_shader_builder_init (&shader_builder, @@ -3421,6 +3475,9 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, progress); INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, source2); + /* mask */ + INIT_PROGRAM_UNIFORM_LOCATION (mask, mask); + /* blend */ INIT_PROGRAM_UNIFORM_LOCATION (blend, source2); INIT_PROGRAM_UNIFORM_LOCATION (blend, mode); @@ -3805,10 +3862,13 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self, render_gl_shader_node (self, node, builder); break; + case GSK_MASK_NODE: + render_mask_node (self, node, builder); + break; + case GSK_REPEATING_LINEAR_GRADIENT_NODE: case GSK_REPEATING_RADIAL_GRADIENT_NODE: case GSK_CAIRO_NODE: - case GSK_MASK_NODE: default: { render_fallback_node (self, node, builder); @@ -4111,6 +4171,11 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self) apply_blend_op (program, ptr); break; + case OP_CHANGE_MASK: + g_assert (program == &self->programs->mask_program); + apply_mask_op (program, ptr); + break; + case OP_CHANGE_LINEAR_GRADIENT: apply_linear_gradient_op (program, ptr); break; diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 24544b0d44..2c97fdea6c 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -13,7 +13,7 @@ #include "opbuffer.h" #define GL_N_VERTICES 6 -#define GL_N_PROGRAMS 15 +#define GL_N_PROGRAMS 16 #define GL_MAX_GRADIENT_STOPS 6 typedef struct @@ -179,6 +179,9 @@ struct _Program int texture_locations[4]; GError *compile_error; } glshader; + struct { + int mask_location; + } mask; }; ProgramState state; }; @@ -203,6 +206,7 @@ typedef struct { Program outset_shadow_program; Program repeat_program; Program unblurred_outset_shadow_program; + Program mask_program; }; }; GHashTable *custom_programs; /* GskGLShader -> Program* */ diff --git a/gsk/gl/opbuffer.c b/gsk/gl/opbuffer.c index 806b8f7ca4..49ce68eb5d 100644 --- a/gsk/gl/opbuffer.c +++ b/gsk/gl/opbuffer.c @@ -34,6 +34,7 @@ static guint op_sizes[OP_LAST] = { sizeof (OpGLShader), sizeof (OpExtraTexture), sizeof (OpConicGradient), + sizeof (OpMask), }; void diff --git a/gsk/gl/opbuffer.h b/gsk/gl/opbuffer.h index 08f48b7c5f..05e6bd24ba 100644 --- a/gsk/gl/opbuffer.h +++ b/gsk/gl/opbuffer.h @@ -42,6 +42,7 @@ typedef enum OP_CHANGE_GL_SHADER_ARGS = 28, OP_CHANGE_EXTRA_SOURCE_TEXTURE = 29, OP_CHANGE_CONIC_GRADIENT = 30, + OP_CHANGE_MASK = 31, OP_LAST } OpKind; @@ -222,6 +223,11 @@ typedef struct const guchar *uniform_data; } OpGLShader; +typedef struct +{ + int mask; +} OpMask; + void op_buffer_init (OpBuffer *buffer); void op_buffer_destroy (OpBuffer *buffer); void op_buffer_clear (OpBuffer *buffer); diff --git a/gsk/meson.build b/gsk/meson.build index 01c5e58fcc..260da77c8e 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -18,6 +18,7 @@ gsk_private_gl_shaders = [ 'resources/glsl/blend.glsl', 'resources/glsl/repeat.glsl', 'resources/glsl/custom.glsl', + 'resources/glsl/mask.glsl', ] gsk_public_sources = files([ diff --git a/gsk/resources/glsl/mask.glsl b/gsk/resources/glsl/mask.glsl new file mode 100644 index 0000000000..449f773860 --- /dev/null +++ b/gsk/resources/glsl/mask.glsl @@ -0,0 +1,15 @@ +// VERTEX_SHADER: +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); +} + +// FRAGMENT_SHADER: +uniform sampler2D u_mask; + +void main() { + vec4 source = GskTexture(u_source, vUv); + vec4 mask = GskTexture(u_mask, vUv); + gskSetOutputColor(source * mask.a); +} |