diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index b8883d921c..4a2211eb78 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -74,6 +74,36 @@ font_has_color_glyphs (const PangoFont *font) return has_color; } +static inline void +rounded_rect_to_floats (const GskRoundedRect *rect, + float *outline, + float *corner_widths, + float *corner_heights) +{ + int i; + + outline[0] = rect->bounds.origin.x; + outline[1] = rect->bounds.origin.y; + outline[2] = rect->bounds.size.width; + outline[3] = rect->bounds.size.height; + + for (i = 0; i < 4; i ++) + { + corner_widths[i] = MAX (rect->corner[i].width, 1); + corner_heights[i] = MAX (rect->corner[i].height, 1); + } +} + +static inline void +rgba_to_float (const GdkRGBA *c, + float *f) +{ + f[0] = c->red; + f[1] = c->green; + f[2] = c->blue; + f[3] = c->alpha; +} + static void gsk_gl_renderer_setup_render_mode (GskGLRenderer *self); static void add_offscreen_ops (GskGLRenderer *self, RenderOpBuilder *builder, @@ -131,6 +161,7 @@ struct _GskGLRenderer Program color_matrix_program; Program linear_gradient_program; Program blur_program; + Program inset_shadow_program; }; }; @@ -388,6 +419,25 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_radius_location, "uBlurRadius"); INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_size_location, "uSize"); + self->inset_shadow_program.id = gsk_shader_builder_create_program (builder, + "blit.vs.glsl", "inset_shadow.fs.glsl", + &shader_error); + if (shader_error != NULL) + { + g_propagate_prefixed_error (error, + shader_error, + "Unable to create 'inset shadow' program: "); + goto out; + } + self->blur_program.index = 7; + self->blur_program.name = "inset shadow"; + init_common_locations (self, builder, &self->inset_shadow_program); + INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_color_location, "uColor"); + INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_spread_location, "uSpread"); + INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_location, "uOutline"); + INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_corner_widths_location, "uOutlineCornerWidths"); + INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_corner_heights_location, "uOutlineCornerHeights"); + res = TRUE; out: @@ -1005,9 +1055,35 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self, } break; + case GSK_INSET_SHADOW_NODE: + { + RenderOp op; + + /* TODO: Implement blurred inset shadows as well */ + if (gsk_inset_shadow_node_get_blur_radius (node) > 0) + goto do_default; + + op.op = OP_CHANGE_INSET_SHADOW; + rgba_to_float (gsk_inset_shadow_node_peek_color (node), op.inset_shadow.color); + rounded_rect_to_floats (gsk_inset_shadow_node_peek_outline (node), + op.inset_shadow.outline, + op.inset_shadow.corner_widths, + op.inset_shadow.corner_heights); + op.inset_shadow.radius = gsk_inset_shadow_node_get_blur_radius (node); + op.inset_shadow.spread = gsk_inset_shadow_node_get_spread (node); + op.inset_shadow.d[0] = gsk_inset_shadow_node_get_dx (node); + op.inset_shadow.d[1] = -gsk_inset_shadow_node_get_dy (node); + + ops_set_program (builder, &self->inset_shadow_program); + ops_add (builder, &op); + ops_draw (builder, vertex_data); + } + break; + +do_default: + case GSK_REPEATING_LINEAR_GRADIENT_NODE: case GSK_BORDER_NODE: - case GSK_INSET_SHADOW_NODE: case GSK_OUTSET_SHADOW_NODE: case GSK_SHADOW_NODE: case GSK_CROSS_FADE_NODE: @@ -1305,6 +1381,16 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self, glUniform2f (program->blur_size_location, op->blur.size.width, op->blur.size.height); break; + case OP_CHANGE_INSET_SHADOW: + g_assert (program == &self->inset_shadow_program); + glUniform4fv (program->inset_shadow_color_location, 1, op->inset_shadow.color); + glUniform2fv (program->inset_shadow_d_location, 1, op->inset_shadow.d); + glUniform1f (program->inset_shadow_spread_location, op->inset_shadow.spread); + glUniform4fv (program->inset_shadow_outline_location, 1, op->inset_shadow.outline); + glUniform4fv (program->inset_shadow_outline_corner_widths_location, 1, op->inset_shadow.corner_widths); + glUniform4fv (program->inset_shadow_outline_corner_heights_location, 1, op->inset_shadow.corner_heights); + break; + case OP_DRAW: OP_PRINT (" -> draw %ld, size %ld and program %s\n", op->draw.vao_offset, op->draw.vao_size, program->name); diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index f324c83607..beec752fda 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -10,7 +10,7 @@ #include "gskglrendererprivate.h" #define GL_N_VERTICES 6 -#define GL_N_PROGRAMS 7 +#define GL_N_PROGRAMS 8 enum { OP_NONE, @@ -27,8 +27,9 @@ enum { OP_CHANGE_LINEAR_GRADIENT = 11, OP_CHANGE_COLOR_MATRIX = 12, OP_CHANGE_BLUR = 13, - OP_CLEAR = 14, - OP_DRAW = 15, + OP_CHANGE_INSET_SHADOW = 14, + OP_CLEAR = 15, + OP_DRAW = 16, }; typedef struct @@ -76,6 +77,14 @@ typedef struct int blur_radius_location; int blur_size_location; }; + struct { + int inset_shadow_color_location; + int inset_shadow_spread_location; + int inset_shadow_d_location; + int inset_shadow_outline_location; + int inset_shadow_outline_corner_widths_location; + int inset_shadow_outline_corner_heights_location; + }; }; } Program; @@ -113,6 +122,15 @@ typedef struct float radius; graphene_size_t size; } blur; + struct { + float outline[4]; + float corner_widths[4]; + float corner_heights[4]; + float radius; + float spread; + float d[2]; + float color[4]; + } inset_shadow; }; } RenderOp; diff --git a/gsk/meson.build b/gsk/meson.build index 548c1937d2..01bbd32b40 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -9,6 +9,7 @@ gsk_private_source_shaders = [ 'resources/glsl/linear_gradient.fs.glsl', 'resources/glsl/blur.vs.glsl', 'resources/glsl/blur.fs.glsl', + 'resources/glsl/inset_shadow.fs.glsl', 'resources/glsl/es2_common.fs.glsl', 'resources/glsl/es2_common.vs.glsl', 'resources/glsl/gl3_common.fs.glsl', diff --git a/gsk/resources/glsl/gl3_common.fs.glsl b/gsk/resources/glsl/gl3_common.fs.glsl index 4e516d20db..3eb4c7bfc5 100644 --- a/gsk/resources/glsl/gl3_common.fs.glsl +++ b/gsk/resources/glsl/gl3_common.fs.glsl @@ -100,4 +100,5 @@ void setOutputColor(vec4 color) { RoundedRect r = RoundedRect(clipBounds, uClipCornerWidths, uClipCornerHeights); outputColor = color * rounded_rect_coverage(r, f.xy); + /*outputColor = color;*/ } diff --git a/gsk/resources/glsl/inset_shadow.fs.glsl b/gsk/resources/glsl/inset_shadow.fs.glsl new file mode 100644 index 0000000000..6cb436854d --- /dev/null +++ b/gsk/resources/glsl/inset_shadow.fs.glsl @@ -0,0 +1,28 @@ +uniform float uSpread; +uniform float uBlurRadius; +uniform vec4 uColor; +uniform vec2 uD; +uniform vec4 uOutline; +uniform vec4 uOutlineCornerWidths; +uniform vec4 uOutlineCornerHeights; + + +void main() { + vec4 f = gl_FragCoord; + + f.x += uViewport.x; + f.y = (uViewport.y + uViewport.w) - f.y; + + RoundedRect outline = RoundedRect(vec4(uOutline.xy, uOutline.xy + uOutline.zw), + uOutlineCornerWidths, uOutlineCornerHeights); + RoundedRect inside = rounded_rect_shrink(outline, vec4(uSpread)); + + vec4 color = vec4(uColor.rgb * uColor.a, uColor.a); + color = color * clamp (rounded_rect_coverage (outline, f.xy) - + rounded_rect_coverage (inside, f.xy - uD), + 0.0, 1.0); + setOutputColor(color); + + /*setOutputColor(vec4(1, 0, 0, 1) * rounded_rect_coverage (outline, f.xy));*/ + /*setOutputColor(vec4(0, 0, 1, 1) * rounded_rect_coverage (inside, f.xy));*/ +}