[gtk/mask-nodes: 3/8] gl: Add a shader for mask nodes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/mask-nodes: 3/8] gl: Add a shader for mask nodes
- Date: Wed, 16 Dec 2020 05:04:13 +0000 (UTC)
commit 181fbd29cdceb2a61f209bd748d03ab67defbf02
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 | 72 +++++++++++++++++++++++++++++++++++++++++-
gsk/gl/gskglrenderopsprivate.h | 7 +++-
gsk/gl/opbuffer.c | 1 +
gsk/gl/opbuffer.h | 7 ++++
gsk/meson.build | 1 +
gsk/resources/glsl/mask.glsl | 45 ++++++++++++++++++++++++++
6 files changed, 131 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 26c33d7987..a5a9b3191f 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2690,6 +2690,52 @@ 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;
+ op->texture_rect[0] = 0;
+ op->texture_rect[1] = 0;
+ op->texture_rect[2] = 1;
+ op->texture_rect[3] = 1;
+
+ 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 +3223,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 ");
+ glUniform4fv (program->mask.texture_rect_location, 1, op->texture_rect);
+ 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 +3357,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 +3453,10 @@ 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);
+ INIT_PROGRAM_UNIFORM_LOCATION (mask, texture_rect);
+
/* blend */
INIT_PROGRAM_UNIFORM_LOCATION (blend, source2);
INIT_PROGRAM_UNIFORM_LOCATION (blend, mode);
@@ -3779,12 +3841,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 +4143,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..6cd4d57795 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,10 @@ struct _Program
int texture_locations[4];
GError *compile_error;
} glshader;
+ struct {
+ int mask_location;
+ int texture_rect_location;
+ } mask;
};
ProgramState state;
};
@@ -203,6 +207,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..97bdd4f4a5 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,12 @@ typedef struct
const guchar *uniform_data;
} OpGLShader;
+typedef struct
+{
+ int mask;
+ float texture_rect[4];
+} 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..cd1a75edf6
--- /dev/null
+++ b/gsk/resources/glsl/mask.glsl
@@ -0,0 +1,45 @@
+// 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;
+uniform vec4 u_texture_rect;
+
+void main() {
+ vec4 source = GskTexture(u_source, vUv);
+ vec2 tc;
+
+ if (vUv.x < u_texture_rect.x || vUv.x > u_texture_rect.z)
+ {
+ gskSetOutputColor(vec4 (0, 0, 0, 0));
+ return;
+ }
+
+ tc.x = (vUv.x - u_texture_rect.x) / (u_texture_rect.z - u_texture_rect.x);
+
+ if (u_texture_rect.y <= u_texture_rect.w)
+ {
+ if (vUv.y < u_texture_rect.y || vUv.y > u_texture_rect.w)
+ {
+ gskSetOutputColor(vec4 (0, 0, 0, 0));
+ return;
+ }
+ tc.y = (vUv.y - u_texture_rect.y) / (u_texture_rect.w - u_texture_rect.y);
+ }
+ else
+ {
+ if (vUv.y < u_texture_rect.w || vUv.y > u_texture_rect.y)
+ {
+ gskSetOutputColor(vec4 (0, 0, 0, 0));
+ return;
+ }
+ tc.y = 1.0 - (vUv.y - u_texture_rect.w) / (u_texture_rect.y - u_texture_rect.w);
+ }
+
+ vec4 mask = GskTexture(u_mask, tc);
+ gskSetOutputColor(vec4 (source * mask.a));
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]