[gtk/mask-nodes: 2/5] gl: Add a shader for mask nodes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/mask-nodes: 2/5] gl: Add a shader for mask nodes
- Date: Tue, 15 Dec 2020 03:24:37 +0000 (UTC)
commit 7ec44c6e9ddc16cb8c296350060cecc618068e06
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Dec 14 15:32:58 2020 -0500
gl: Add a shader for mask nodes
gsk/gl/gskglrenderer.c | 67 +++++++++++++++++++++++++++++++++++++++++-
gsk/gl/gskglrenderopsprivate.h | 6 +++-
gsk/gl/opbuffer.c | 1 +
gsk/gl/opbuffer.h | 6 ++++
gsk/meson.build | 1 +
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 26c33d7987..0b8836817b 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2690,6 +2690,48 @@ render_cross_fade_node (GskGLRenderer *self,
load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
}
+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,
@@ -3177,6 +3219,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)
{
@@ -3300,6 +3353,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,
@@ -3395,6 +3449,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);
@@ -3779,12 +3836,15 @@ 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_FILL_NODE:
case GSK_STROKE_NODE:
case GSK_CAIRO_NODE:
- case GSK_MASK_NODE:
default:
{
render_fallback_node (self, node, builder);
@@ -4078,6 +4138,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 3dd3cb3411..8453b3ce89 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 5ce0cc16ca..f7f3894e23 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);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]