From 3252f1e301d27a63fbdd7e662d9742af9119ed8d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Mar 2021 21:31:31 -0500 Subject: [PATCH 1/5] gsk: Give ngl its own shader sources We may want to change the interface between the shaders and the renderer for ngl, and therefore, sharing the shaders between gl and ngl will not be practical, going forward. --- gsk/gen-gsk-gresources-xml.py | 15 +- gsk/meson.build | 23 ++ gsk/ngl/gskngldriver.c | 6 +- gsk/ngl/gsknglprograms.defs | 30 +- gsk/ngl/resources/blend.glsl | 310 ++++++++++++++++++ gsk/ngl/resources/blit.glsl | 13 + gsk/ngl/resources/blur.glsl | 55 ++++ gsk/ngl/resources/border.glsl | 40 +++ gsk/ngl/resources/color.glsl | 18 + gsk/ngl/resources/color_matrix.glsl | 25 ++ gsk/ngl/resources/coloring.glsl | 22 ++ gsk/ngl/resources/conic_gradient.glsl | 73 +++++ gsk/ngl/resources/cross_fade.glsl | 20 ++ gsk/ngl/resources/custom.glsl | 21 ++ gsk/ngl/resources/inset_shadow.glsl | 41 +++ gsk/ngl/resources/linear_gradient.glsl | 95 ++++++ gsk/ngl/resources/outset_shadow.glsl | 33 ++ gsk/ngl/resources/preamble.fs.glsl | 139 ++++++++ gsk/ngl/resources/preamble.glsl | 57 ++++ gsk/ngl/resources/preamble.vs.glsl | 69 ++++ gsk/ngl/resources/radial_gradient.glsl | 74 +++++ gsk/ngl/resources/repeat.glsl | 41 +++ .../resources/unblurred_outset_shadow.glsl | 42 +++ 23 files changed, 1241 insertions(+), 21 deletions(-) create mode 100644 gsk/ngl/resources/blend.glsl create mode 100644 gsk/ngl/resources/blit.glsl create mode 100644 gsk/ngl/resources/blur.glsl create mode 100644 gsk/ngl/resources/border.glsl create mode 100644 gsk/ngl/resources/color.glsl create mode 100644 gsk/ngl/resources/color_matrix.glsl create mode 100644 gsk/ngl/resources/coloring.glsl create mode 100644 gsk/ngl/resources/conic_gradient.glsl create mode 100644 gsk/ngl/resources/cross_fade.glsl create mode 100644 gsk/ngl/resources/custom.glsl create mode 100644 gsk/ngl/resources/inset_shadow.glsl create mode 100644 gsk/ngl/resources/linear_gradient.glsl create mode 100644 gsk/ngl/resources/outset_shadow.glsl create mode 100644 gsk/ngl/resources/preamble.fs.glsl create mode 100644 gsk/ngl/resources/preamble.glsl create mode 100644 gsk/ngl/resources/preamble.vs.glsl create mode 100644 gsk/ngl/resources/radial_gradient.glsl create mode 100644 gsk/ngl/resources/repeat.glsl create mode 100644 gsk/ngl/resources/unblurred_outset_shadow.glsl diff --git a/gsk/gen-gsk-gresources-xml.py b/gsk/gen-gsk-gresources-xml.py index 5db5044b09..16a2c4042a 100644 --- a/gsk/gen-gsk-gresources-xml.py +++ b/gsk/gen-gsk-gresources-xml.py @@ -20,13 +20,17 @@ def replace_if_changed(new, old): else: os.remove(new) -source_shaders = [] +gl_source_shaders = [] +ngl_source_shaders = [] vulkan_compiled_shaders = [] vulkan_shaders = [] for f in sys.argv[2:]: if f.endswith('.glsl'): - source_shaders.append(f) + if f.startswith('ngl'): + ngl_source_shaders.append(f); + else: + gl_source_shaders.append(f) elif f.endswith('.spv'): vulkan_compiled_shaders.append(f) elif f.endswith('.frag') or f.endswith('.vert'): @@ -40,11 +44,16 @@ xml = ''' ''' -for f in source_shaders: +for f in gl_source_shaders: xml += ' resources/glsl/{0}\n'.format(os.path.basename(f)) xml += '\n' +for f in ngl_source_shaders: + xml += ' ngl/resources/{0}\n'.format(os.path.basename(f)) + +xml += '\n' + for f in vulkan_compiled_shaders: xml += ' resources/vulkan/{0}\n'.format(os.path.basename(f)) diff --git a/gsk/meson.build b/gsk/meson.build index dd1ac34ff9..8f9a6281c0 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -20,6 +20,28 @@ gsk_private_gl_shaders = [ 'resources/glsl/custom.glsl', ] +gsk_private_ngl_shaders = [ + 'ngl/resources/preamble.glsl', + 'ngl/resources/preamble.fs.glsl', + 'ngl/resources/preamble.vs.glsl', + 'ngl/resources/border.glsl', + 'ngl/resources/blit.glsl', + 'ngl/resources/coloring.glsl', + 'ngl/resources/color.glsl', + 'ngl/resources/linear_gradient.glsl', + 'ngl/resources/radial_gradient.glsl', + 'ngl/resources/conic_gradient.glsl', + 'ngl/resources/color_matrix.glsl', + 'ngl/resources/blur.glsl', + 'ngl/resources/inset_shadow.glsl', + 'ngl/resources/outset_shadow.glsl', + 'ngl/resources/unblurred_outset_shadow.glsl', + 'ngl/resources/cross_fade.glsl', + 'ngl/resources/blend.glsl', + 'ngl/resources/repeat.glsl', + 'ngl/resources/custom.glsl', +] + gsk_public_sources = files([ 'gskdiff.c', 'gskcairorenderer.c', @@ -150,6 +172,7 @@ gsk_resources_xml = configure_file(output: 'gsk.resources.xml', find_program('gen-gsk-gresources-xml.py'), '@OUTPUT@', gsk_private_gl_shaders, + gsk_private_ngl_shaders, gsk_private_vulkan_compiled_shaders, gsk_private_vulkan_shaders ], diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c index 692e6a9d5d..1b00b135ed 100644 --- a/gsk/ngl/gskngldriver.c +++ b/gsk/ngl/gskngldriver.c @@ -336,13 +336,13 @@ gsk_ngl_driver_load_programs (GskNglDriver *self, /* Setup preambles that are shared by all shaders */ gsk_ngl_compiler_set_preamble_from_resource (compiler, GSK_NGL_COMPILER_ALL, - "/org/gtk/libgsk/glsl/preamble.glsl"); + "/org/gtk/libgsk/ngl/preamble.glsl"); gsk_ngl_compiler_set_preamble_from_resource (compiler, GSK_NGL_COMPILER_VERTEX, - "/org/gtk/libgsk/glsl/preamble.vs.glsl"); + "/org/gtk/libgsk/ngl/preamble.vs.glsl"); gsk_ngl_compiler_set_preamble_from_resource (compiler, GSK_NGL_COMPILER_FRAGMENT, - "/org/gtk/libgsk/glsl/preamble.fs.glsl"); + "/org/gtk/libgsk/ngl/preamble.fs.glsl"); /* Setup attributes that are provided via VBO */ gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0); diff --git a/gsk/ngl/gsknglprograms.defs b/gsk/ngl/gsknglprograms.defs index b0b797f0e9..85c9366ad6 100644 --- a/gsk/ngl/gsknglprograms.defs +++ b/gsk/ngl/gsknglprograms.defs @@ -1,69 +1,69 @@ GSK_NGL_DEFINE_PROGRAM (blend, - "/org/gtk/libgsk/glsl/blend.glsl", + "/org/gtk/libgsk/ngl/blend.glsl", GSK_NGL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2) GSK_NGL_ADD_UNIFORM (2, BLEND_MODE, u_mode)) GSK_NGL_DEFINE_PROGRAM (blit, - "/org/gtk/libgsk/glsl/blit.glsl", + "/org/gtk/libgsk/ngl/blit.glsl", GSK_NGL_NO_UNIFORMS) GSK_NGL_DEFINE_PROGRAM (blur, - "/org/gtk/libgsk/glsl/blur.glsl", + "/org/gtk/libgsk/ngl/blur.glsl", GSK_NGL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius) GSK_NGL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size) GSK_NGL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir)) GSK_NGL_DEFINE_PROGRAM (border, - "/org/gtk/libgsk/glsl/border.glsl", + "/org/gtk/libgsk/ngl/border.glsl", GSK_NGL_ADD_UNIFORM (1, BORDER_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths) GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (color, - "/org/gtk/libgsk/glsl/color.glsl", + "/org/gtk/libgsk/ngl/color.glsl", GSK_NGL_ADD_UNIFORM (1, COLOR_COLOR, u_color)) GSK_NGL_DEFINE_PROGRAM (coloring, - "/org/gtk/libgsk/glsl/coloring.glsl", + "/org/gtk/libgsk/ngl/coloring.glsl", GSK_NGL_ADD_UNIFORM (1, COLORING_COLOR, u_color)) GSK_NGL_DEFINE_PROGRAM (color_matrix, - "/org/gtk/libgsk/glsl/color_matrix.glsl", + "/org/gtk/libgsk/ngl/color_matrix.glsl", GSK_NGL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix) GSK_NGL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset)) GSK_NGL_DEFINE_PROGRAM (conic_gradient, - "/org/gtk/libgsk/glsl/conic_gradient.glsl", + "/org/gtk/libgsk/ngl/conic_gradient.glsl", GSK_NGL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops) GSK_NGL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops) GSK_NGL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry)) GSK_NGL_DEFINE_PROGRAM (cross_fade, - "/org/gtk/libgsk/glsl/cross_fade.glsl", + "/org/gtk/libgsk/ngl/cross_fade.glsl", GSK_NGL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress) GSK_NGL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2)) GSK_NGL_DEFINE_PROGRAM (inset_shadow, - "/org/gtk/libgsk/glsl/inset_shadow.glsl", + "/org/gtk/libgsk/ngl/inset_shadow.glsl", GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread) GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset) GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (linear_gradient, - "/org/gtk/libgsk/glsl/linear_gradient.glsl", + "/org/gtk/libgsk/ngl/linear_gradient.glsl", GSK_NGL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops) GSK_NGL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops) GSK_NGL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points) GSK_NGL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat)) GSK_NGL_DEFINE_PROGRAM (outset_shadow, - "/org/gtk/libgsk/glsl/outset_shadow.glsl", + "/org/gtk/libgsk/ngl/outset_shadow.glsl", GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (radial_gradient, - "/org/gtk/libgsk/glsl/radial_gradient.glsl", + "/org/gtk/libgsk/ngl/radial_gradient.glsl", GSK_NGL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops) GSK_NGL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops) GSK_NGL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat) @@ -71,12 +71,12 @@ GSK_NGL_DEFINE_PROGRAM (radial_gradient, GSK_NGL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry)) GSK_NGL_DEFINE_PROGRAM (repeat, - "/org/gtk/libgsk/glsl/repeat.glsl", + "/org/gtk/libgsk/ngl/repeat.glsl", GSK_NGL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds) GSK_NGL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect)) GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow, - "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", + "/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl", GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread) GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset) diff --git a/gsk/ngl/resources/blend.glsl b/gsk/ngl/resources/blend.glsl new file mode 100644 index 0000000000..22323402ac --- /dev/null +++ b/gsk/ngl/resources/blend.glsl @@ -0,0 +1,310 @@ +// 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 int u_mode; +uniform sampler2D u_source2; + +float +combine (float source, float backdrop) +{ + return source + backdrop * (1.0 - source); +} + +vec4 +composite (vec4 Cs, vec4 Cb, vec3 B) +{ + float ao = Cs.a + Cb.a * (1.0 - Cs.a); + vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao; + return vec4(Co, ao); +} + +vec4 +normal (vec4 Cs, vec4 Cb) +{ + return composite (Cs, Cb, Cs.rgb); +} + +vec4 +multiply (vec4 Cs, vec4 Cb) +{ + return composite (Cs, Cb, Cs.rgb * Cb.rgb); +} + +vec4 +difference (vec4 Cs, vec4 Cb) +{ + return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb)); +} + +vec4 +screen (vec4 Cs, vec4 Cb) +{ + return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb); +} + +float +hard_light (float source, float backdrop) +{ + if (source <= 0.5) + return 2.0 * backdrop * source; + else + return 2.0 * (backdrop + source - backdrop * source) - 1.0; +} + +vec4 +hard_light (vec4 Cs, vec4 Cb) +{ + vec3 B = vec3 (hard_light (Cs.r, Cb.r), + hard_light (Cs.g, Cb.g), + hard_light (Cs.b, Cb.b)); + return composite (Cs, Cb, B); +} + +float +soft_light (float source, float backdrop) +{ + float db; + + if (backdrop <= 0.25) + db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop; + else + db = sqrt (backdrop); + + if (source <= 0.5) + return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop); + else + return backdrop + (2.0 * source - 1.0) * (db - backdrop); +} + +vec4 +soft_light (vec4 Cs, vec4 Cb) +{ + vec3 B = vec3 (soft_light (Cs.r, Cb.r), + soft_light (Cs.g, Cb.g), + soft_light (Cs.b, Cb.b)); + return composite (Cs, Cb, B); +} + +vec4 +overlay (vec4 Cs, vec4 Cb) +{ + vec3 B = vec3 (hard_light (Cb.r, Cs.r), + hard_light (Cb.g, Cs.g), + hard_light (Cb.b, Cs.b)); + return composite (Cs, Cb, B); +} + +vec4 +darken (vec4 Cs, vec4 Cb) +{ + vec3 B = min (Cs.rgb, Cb.rgb); + return composite (Cs, Cb, B); +} + +vec4 +lighten (vec4 Cs, vec4 Cb) +{ + vec3 B = max (Cs.rgb, Cb.rgb); + return composite (Cs, Cb, B); +} + +float +color_dodge (float source, float backdrop) +{ + return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0); +} + +vec4 +color_dodge (vec4 Cs, vec4 Cb) +{ + vec3 B = vec3 (color_dodge (Cs.r, Cb.r), + color_dodge (Cs.g, Cb.g), + color_dodge (Cs.b, Cb.b)); + return composite (Cs, Cb, B); +} + + +float +color_burn (float source, float backdrop) +{ + return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0); +} + +vec4 +color_burn (vec4 Cs, vec4 Cb) +{ + vec3 B = vec3 (color_burn (Cs.r, Cb.r), + color_burn (Cs.g, Cb.g), + color_burn (Cs.b, Cb.b)); + return composite (Cs, Cb, B); +} + +vec4 +exclusion (vec4 Cs, vec4 Cb) +{ + vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb; + return composite (Cs, Cb, B); +} + +float +lum (vec3 c) +{ + return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b; +} + +vec3 +clip_color (vec3 c) +{ + float l = lum (c); + float n = min (c.r, min (c.g, c.b)); + float x = max (c.r, max (c.g, c.b)); + if (n < 0.0) c = l + (((c - l) * l) / (l - n)); + if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l)); + return c; +} + +vec3 +set_lum (vec3 c, float l) +{ + float d = l - lum (c); + return clip_color (vec3 (c.r + d, c.g + d, c.b + d)); +} + +float +sat (vec3 c) +{ + return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b)); +} + +vec3 +set_sat (vec3 c, float s) +{ + float cmin = min (c.r, min (c.g, c.b)); + float cmax = max (c.r, max (c.g, c.b)); + vec3 res; + + if (cmax == cmin) + res = vec3 (0, 0, 0); + else + { + if (c.r == cmax) + { + if (c.g == cmin) + { + res.b = ((c.b - cmin) * s) / (cmax - cmin); + res.g = 0.0; + } + else + { + res.g = ((c.g - cmin) * s) / (cmax - cmin); + res.b = 0.0; + } + res.r = s; + } + else if (c.g == cmax) + { + if (c.r == cmin) + { + res.b = ((c.b - cmin) * s) / (cmax - cmin); + res.r = 0.0; + } + else + { + res.r = ((c.r - cmin) * s) / (cmax - cmin); + res.b = 0.0; + } + res.g = s; + } + else + { + if (c.r == cmin) + { + res.g = ((c.g - cmin) * s) / (cmax - cmin); + res.r = 0.0; + } + else + { + res.r = ((c.r - cmin) * s) / (cmax - cmin); + res.g = 0.0; + } + res.b = s; + } + } + return res; +} + +vec4 +color (vec4 Cs, vec4 Cb) +{ + vec3 B = set_lum (Cs.rgb, lum (Cb.rgb)); + return composite (Cs, Cb, B); +} + +vec4 +hue (vec4 Cs, vec4 Cb) +{ + vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb)); + return composite (Cs, Cb, B); +} + +vec4 +saturation (vec4 Cs, vec4 Cb) +{ + vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb)); + return composite (Cs, Cb, B); +} + +vec4 +luminosity (vec4 Cs, vec4 Cb) +{ + vec3 B = set_lum (Cb.rgb, lum (Cs.rgb)); + return composite (Cs, Cb, B); +} + +void main() { + vec4 bottom_color = GskTexture(u_source, vUv); + vec4 top_color = GskTexture(u_source2, vUv); + + vec4 result; + if (u_mode == 0) + result = normal(top_color, bottom_color); + else if (u_mode == 1) + result = multiply(top_color, bottom_color); + else if (u_mode == 2) + result = screen(top_color, bottom_color); + else if (u_mode == 3) + result = overlay(top_color, bottom_color); + else if (u_mode == 4) + result = darken(top_color, bottom_color); + else if (u_mode == 5) + result = lighten(top_color, bottom_color); + else if (u_mode == 6) + result = color_dodge(top_color, bottom_color); + else if (u_mode == 7) + result = color_burn(top_color, bottom_color); + else if (u_mode == 8) + result = hard_light(top_color, bottom_color); + else if (u_mode == 9) + result = soft_light(top_color, bottom_color); + else if (u_mode == 10) + result = difference(top_color, bottom_color); + else if (u_mode == 11) + result = exclusion(top_color, bottom_color); + else if (u_mode == 12) + result = color(top_color, bottom_color); + else if (u_mode == 13) + result = hue(top_color, bottom_color); + else if (u_mode == 14) + result = saturation(top_color, bottom_color); + else if (u_mode == 15) + result = luminosity(top_color, bottom_color); + else + discard; + + gskSetOutputColor(result * u_alpha); +} diff --git a/gsk/ngl/resources/blit.glsl b/gsk/ngl/resources/blit.glsl new file mode 100644 index 0000000000..f01cd238ec --- /dev/null +++ b/gsk/ngl/resources/blit.glsl @@ -0,0 +1,13 @@ +// VERTEX_SHADER: +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); +} + +// FRAGMENT_SHADER: +void main() { + vec4 diffuse = GskTexture(u_source, vUv); + + gskSetOutputColor(diffuse * u_alpha); +} diff --git a/gsk/ngl/resources/blur.glsl b/gsk/ngl/resources/blur.glsl new file mode 100644 index 0000000000..f782ab48cc --- /dev/null +++ b/gsk/ngl/resources/blur.glsl @@ -0,0 +1,55 @@ +// VERTEX_SHADER: +uniform float u_blur_radius; +uniform vec2 u_blur_size; +uniform vec2 u_blur_dir; + +_OUT_ vec2 pixel_step; +_OUT_ float pixels_per_side; +_OUT_ vec3 initial_gaussian; + +const float PI = 3.14159265; +const float RADIUS_MULTIPLIER = 2.0; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); + + pixel_step = (vec2(1.0) / u_blur_size) * u_blur_dir; + pixels_per_side = floor(u_blur_radius * RADIUS_MULTIPLIER / 2.0); + + float sigma = u_blur_radius / 2.0; // *shrug* + initial_gaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma); + initial_gaussian.y = exp(-0.5 / (sigma * sigma)); + initial_gaussian.z = initial_gaussian.y * initial_gaussian.y; +} + +// FRAGMENT_SHADER: +_IN_ vec2 pixel_step; +_IN_ float pixels_per_side; +_IN_ vec3 initial_gaussian; + +// blur_radius 0 is NOT supported and MUST be caught before. + +// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html +void main() { + vec3 incrementalGaussian = initial_gaussian; + + float coefficientSum = 0.0; + vec4 sum = GskTexture(u_source, vUv) * incrementalGaussian.x; + coefficientSum += incrementalGaussian.x; + incrementalGaussian.xy *= incrementalGaussian.yz; + + vec2 p = pixel_step; + for (int i = 1; i <= int(pixels_per_side); i++) { + sum += GskTexture(u_source, vUv - p) * incrementalGaussian.x; + sum += GskTexture(u_source, vUv + p) * incrementalGaussian.x; + + coefficientSum += 2.0 * incrementalGaussian.x; + incrementalGaussian.xy *= incrementalGaussian.yz; + + p += pixel_step; + } + + gskSetOutputColor(sum / coefficientSum); +} diff --git a/gsk/ngl/resources/border.glsl b/gsk/ngl/resources/border.glsl new file mode 100644 index 0000000000..677a0df7cd --- /dev/null +++ b/gsk/ngl/resources/border.glsl @@ -0,0 +1,40 @@ +// VERTEX_SHADER: +uniform vec4 u_color; +uniform vec4 u_widths; +uniform vec4[3] u_outline_rect; + +_OUT_ vec4 final_color; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + final_color = gsk_premultiply(u_color) * u_alpha; + + GskRoundedRect outside = gsk_create_rect(u_outline_rect); + GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths); + + gsk_rounded_rect_transform(outside, u_modelview); + gsk_rounded_rect_transform(inside, u_modelview); + + gsk_rounded_rect_encode(outside, transformed_outside_outline); + gsk_rounded_rect_encode(inside, transformed_inside_outline); +} + +// FRAGMENT_SHADER: +uniform vec4[3] u_outline_rect; + +_IN_ vec4 final_color; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + vec2 frag = gsk_get_frag_coord(); + + float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) - + gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), + 0.0, 1.0); + + gskSetOutputColor(final_color * alpha); +} diff --git a/gsk/ngl/resources/color.glsl b/gsk/ngl/resources/color.glsl new file mode 100644 index 0000000000..636456ce0d --- /dev/null +++ b/gsk/ngl/resources/color.glsl @@ -0,0 +1,18 @@ +// VERTEX_SHADER: +uniform vec4 u_color; + +_OUT_ vec4 final_color; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + final_color = gsk_premultiply(u_color) * u_alpha; +} + +// FRAGMENT_SHADER: +_IN_ vec4 final_color; + +void main() { + gskSetOutputColor(final_color); +} + diff --git a/gsk/ngl/resources/color_matrix.glsl b/gsk/ngl/resources/color_matrix.glsl new file mode 100644 index 0000000000..79cb36434e --- /dev/null +++ b/gsk/ngl/resources/color_matrix.glsl @@ -0,0 +1,25 @@ +// 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 mat4 u_color_matrix; +uniform vec4 u_color_offset; + +void main() { + vec4 color = GskTexture(u_source, vUv); + + // Un-premultilpy + if (color.a != 0.0) + color.rgb /= color.a; + + color = u_color_matrix * color + u_color_offset; + color = clamp(color, 0.0, 1.0); + + color.rgb *= color.a; + + gskSetOutputColor(color * u_alpha); +} diff --git a/gsk/ngl/resources/coloring.glsl b/gsk/ngl/resources/coloring.glsl new file mode 100644 index 0000000000..a675493030 --- /dev/null +++ b/gsk/ngl/resources/coloring.glsl @@ -0,0 +1,22 @@ +// VERTEX_SHADER: +uniform vec4 u_color; + +_OUT_ vec4 final_color; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); + + final_color = gsk_premultiply(u_color) * u_alpha; +} + +// FRAGMENT_SHADER: + +_IN_ vec4 final_color; + +void main() { + vec4 diffuse = GskTexture(u_source, vUv); + + gskSetOutputColor(final_color * diffuse.a); +} diff --git a/gsk/ngl/resources/conic_gradient.glsl b/gsk/ngl/resources/conic_gradient.glsl new file mode 100644 index 0000000000..630a42c5e6 --- /dev/null +++ b/gsk/ngl/resources/conic_gradient.glsl @@ -0,0 +1,73 @@ +// VERTEX_SHADER +uniform vec4 u_geometry; + +_NOPERSPECTIVE_ _OUT_ vec2 coord; + +void main() { + gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0)); + + vec2 mv0 = u_modelview[0].xy; + vec2 mv1 = u_modelview[1].xy; + vec2 offset = aPosition - u_geometry.xy; + + coord = vec2(dot(mv0, offset), + dot(mv1, offset)); +} + +// FRAGMENT_SHADER: +#ifdef GSK_LEGACY +uniform int u_num_color_stops; +#else +uniform highp int u_num_color_stops; // Why? Because it works like this. +#endif + +uniform vec4 u_geometry; +uniform float u_color_stops[6 * 5]; + +_NOPERSPECTIVE_ _IN_ vec2 coord; + +float get_offset(int index) { + return u_color_stops[5 * index]; +} + +vec4 get_color(int index) { + int base = 5 * index + 1; + + return vec4(u_color_stops[base], + u_color_stops[base + 1], + u_color_stops[base + 2], + u_color_stops[base + 3]); +} + +void main() { + // direction of point in range [-PI, PI] + vec2 pos = floor(coord); + float angle = atan(pos.y, pos.x); + + // fract() does the modulo here, so now we have progress + // into the current conic + float offset = fract(angle * u_geometry.z + u_geometry.w); + + if (offset < get_offset(0)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); + return; + } + + int n = u_num_color_stops - 1; + for (int i = 0; i < n; i++) { + float curr_offset = get_offset(i); + float next_offset = get_offset(i + 1); + + if (offset >= curr_offset && offset < next_offset) { + float f = (offset - curr_offset) / (next_offset - curr_offset); + vec4 curr_color = gsk_premultiply(get_color(i)); + vec4 next_color = gsk_premultiply(get_color(i + 1)); + vec4 color = mix(curr_color, next_color, f); + + gskSetOutputColor(color * u_alpha); + return; + } + } + + gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); +} diff --git a/gsk/ngl/resources/cross_fade.glsl b/gsk/ngl/resources/cross_fade.glsl new file mode 100644 index 0000000000..f824430f9d --- /dev/null +++ b/gsk/ngl/resources/cross_fade.glsl @@ -0,0 +1,20 @@ +// 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 float u_progress; +uniform sampler2D u_source2; + +void main() { + vec4 source1 = GskTexture(u_source, vUv); // start child + vec4 source2 = GskTexture(u_source2, vUv); // end child + + float p_start = (1.0 - u_progress) * u_alpha; + float p_end = u_progress * u_alpha; + vec4 color = (p_start * source1) + (p_end * source2); + gskSetOutputColor(color); +} diff --git a/gsk/ngl/resources/custom.glsl b/gsk/ngl/resources/custom.glsl new file mode 100644 index 0000000000..d2aed97fc8 --- /dev/null +++ b/gsk/ngl/resources/custom.glsl @@ -0,0 +1,21 @@ +// VERTEX_SHADER: +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + vUv = vec2(aUv.x, aUv.y); +} + +// FRAGMENT_SHADER: +// The shader supplies: +void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv); + +uniform vec2 u_size; +uniform sampler2D u_source2; +uniform sampler2D u_source3; +uniform sampler2D u_source4; + +void main() { + vec4 fragColor; + vec2 fragCoord = vec2(vUv.x * u_size.x, (1.0-vUv.y) * u_size.y); + mainImage(fragColor, fragCoord, u_size, vUv); + gskSetOutputColor(fragColor); +} diff --git a/gsk/ngl/resources/inset_shadow.glsl b/gsk/ngl/resources/inset_shadow.glsl new file mode 100644 index 0000000000..9a21cdef09 --- /dev/null +++ b/gsk/ngl/resources/inset_shadow.glsl @@ -0,0 +1,41 @@ +// VERTEX_SHADER: +uniform vec4 u_color; +uniform float u_spread; +uniform vec2 u_offset; +uniform vec4[3] u_outline_rect; + +_OUT_ vec4 final_color; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + final_color = gsk_premultiply(u_color) * u_alpha; + + GskRoundedRect outside = gsk_create_rect(u_outline_rect); + GskRoundedRect inside = gsk_rounded_rect_shrink(outside, vec4(u_spread)); + + gsk_rounded_rect_offset(inside, u_offset); + + gsk_rounded_rect_transform(outside, u_modelview); + gsk_rounded_rect_transform(inside, u_modelview); + + gsk_rounded_rect_encode(outside, transformed_outside_outline); + gsk_rounded_rect_encode(inside, transformed_inside_outline); +} + +// FRAGMENT_SHADER: +_IN_ vec4 final_color; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + vec2 frag = gsk_get_frag_coord(); + + float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) - + gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), + 0.0, 1.0); + + gskSetOutputColor(final_color * alpha); +} diff --git a/gsk/ngl/resources/linear_gradient.glsl b/gsk/ngl/resources/linear_gradient.glsl new file mode 100644 index 0000000000..cc90392c06 --- /dev/null +++ b/gsk/ngl/resources/linear_gradient.glsl @@ -0,0 +1,95 @@ +// VERTEX_SHADER +uniform vec4 u_points; + +_NOPERSPECTIVE_ _OUT_ vec4 info; + +void main() { + gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0)); + + vec2 mv0 = u_modelview[0].xy; + vec2 mv1 = u_modelview[1].xy; + vec2 offset = aPosition - u_points.xy; + vec2 coord = vec2(dot(mv0, offset), + dot(mv1, offset)); + + // Original equation: + // VS | maxDist = length(end - start); + // VS | gradient = end - start; + // VS | gradientLength = length(gradient); + // FS | pos = frag_coord - start + // FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient + // FS | offset = length(proj) / maxDist + + // Simplified formula derivation: + // 1. Notice that maxDist = gradientLength: + // offset = length(proj) / gradientLength + // 2. Let gnorm = gradient / gradientLength, then: + // proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) = + // = dot(gnorm, pos) * gnorm + // 3. Since gnorm is unit length then: + // length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos) + // 4. We can avoid the FS division by passing a scaled pos from the VS: + // offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength) + // 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL + vec2 gradient = vec2(dot(mv0, u_points.zw), + dot(mv1, u_points.zw)); + float rcp_gradient_length = inversesqrt(dot(gradient, gradient)); + + info = rcp_gradient_length * vec4(coord, gradient); +} + +// FRAGMENT_SHADER: +#ifdef GSK_LEGACY +uniform int u_num_color_stops; +#else +uniform highp int u_num_color_stops; // Why? Because it works like this. +#endif + +uniform float u_color_stops[6 * 5]; +uniform bool u_repeat; + +_NOPERSPECTIVE_ _IN_ vec4 info; + +float get_offset(int index) { + return u_color_stops[5 * index]; +} + +vec4 get_color(int index) { + int base = 5 * index + 1; + + return vec4(u_color_stops[base], + u_color_stops[base + 1], + u_color_stops[base + 2], + u_color_stops[base + 3]); +} + +void main() { + float offset = dot(info.xy, info.zw); + + if (u_repeat) { + offset = fract(offset); + } + + if (offset < get_offset(0)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); + return; + } + + int n = u_num_color_stops - 1; + for (int i = 0; i < n; i++) { + float curr_offset = get_offset(i); + float next_offset = get_offset(i + 1); + + if (offset >= curr_offset && offset < next_offset) { + float f = (offset - curr_offset) / (next_offset - curr_offset); + vec4 curr_color = gsk_premultiply(get_color(i)); + vec4 next_color = gsk_premultiply(get_color(i + 1)); + vec4 color = mix(curr_color, next_color, f); + + gskSetOutputColor(color * u_alpha); + return; + } + } + + gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); +} diff --git a/gsk/ngl/resources/outset_shadow.glsl b/gsk/ngl/resources/outset_shadow.glsl new file mode 100644 index 0000000000..373c650179 --- /dev/null +++ b/gsk/ngl/resources/outset_shadow.glsl @@ -0,0 +1,33 @@ +// VERTEX_SHADER: +uniform vec4 u_color; +uniform vec4[3] u_outline_rect; + +_OUT_ vec4 final_color; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); + + final_color = gsk_premultiply(u_color) * u_alpha; + + GskRoundedRect outline = gsk_create_rect(u_outline_rect); + gsk_rounded_rect_transform(outline, u_modelview); + gsk_rounded_rect_encode(outline, transformed_outline); +} + +// FRAGMENT_SHADER: +_IN_ vec4 final_color; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline; + +void main() { + vec2 frag = gsk_get_frag_coord(); + + float alpha = GskTexture(u_source, vUv).a; + alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0)); + + vec4 color = final_color * alpha; + + gskSetOutputColor(color); +} diff --git a/gsk/ngl/resources/preamble.fs.glsl b/gsk/ngl/resources/preamble.fs.glsl new file mode 100644 index 0000000000..3a2fe49240 --- /dev/null +++ b/gsk/ngl/resources/preamble.fs.glsl @@ -0,0 +1,139 @@ +uniform sampler2D u_source; +uniform mat4 u_projection; +uniform mat4 u_modelview; +uniform float u_alpha;// = 1.0; +uniform vec4 u_viewport; +uniform vec4[3] u_clip_rect; + +#if defined(GSK_LEGACY) +_OUT_ vec4 outputColor; +#elif !defined(GSK_GLES) +_OUT_ vec4 outputColor; +#endif + +_IN_ vec2 vUv; + + + +GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r) +{ +#if defined(GSK_GLES) || defined(GSK_LEGACY) + return GskRoundedRect(r[0], r[1], r[2]); +#else + return r; +#endif +} + +float +gsk_ellipsis_dist (vec2 p, vec2 radius) +{ + if (radius == vec2(0, 0)) + return 0.0; + + vec2 p0 = p / radius; + vec2 p1 = 2.0 * p0 / radius; + + return (dot(p0, p0) - 1.0) / length (p1); +} + +float +gsk_ellipsis_coverage (vec2 point, vec2 center, vec2 radius) +{ + float d = gsk_ellipsis_dist (point - center, radius); + return clamp (0.5 - d, 0.0, 1.0); +} + +float +gsk_rounded_rect_coverage (GskRoundedRect r, vec2 p) +{ + if (p.x < r.bounds.x || p.y < r.bounds.y || + p.x >= r.bounds.z || p.y >= r.bounds.w) + return 0.0; + + vec2 ref_tl = r.corner_points1.xy; + vec2 ref_tr = r.corner_points1.zw; + vec2 ref_br = r.corner_points2.xy; + vec2 ref_bl = r.corner_points2.zw; + + if (p.x >= ref_tl.x && p.x >= ref_bl.x && + p.x <= ref_tr.x && p.x <= ref_br.x) + return 1.0; + + if (p.y >= ref_tl.y && p.y >= ref_tr.y && + p.y <= ref_bl.y && p.y <= ref_br.y) + return 1.0; + + vec2 rad_tl = r.corner_points1.xy - r.bounds.xy; + vec2 rad_tr = r.corner_points1.zw - r.bounds.zy; + vec2 rad_br = r.corner_points2.xy - r.bounds.zw; + vec2 rad_bl = r.corner_points2.zw - r.bounds.xw; + + float d_tl = gsk_ellipsis_coverage(p, ref_tl, rad_tl); + float d_tr = gsk_ellipsis_coverage(p, ref_tr, rad_tr); + float d_br = gsk_ellipsis_coverage(p, ref_br, rad_br); + float d_bl = gsk_ellipsis_coverage(p, ref_bl, rad_bl); + + vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl); + + bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y, + p.x > ref_tr.x && p.y < ref_tr.y, + p.x > ref_br.x && p.y > ref_br.y, + p.x < ref_bl.x && p.y > ref_bl.y); + + return 1.0 - dot(vec4(is_out), corner_coverages); +} + +float +gsk_rect_coverage (vec4 r, vec2 p) +{ + if (p.x < r.x || p.y < r.y || + p.x >= r.z || p.y >= r.w) + return 0.0; + + return 1.0; +} + +vec4 GskTexture(sampler2D sampler, vec2 texCoords) { +#if defined(GSK_GLES) || defined(GSK_LEGACY) + return texture2D(sampler, texCoords); +#else + return texture(sampler, texCoords); +#endif +} + +#ifdef GSK_GL3 +layout(origin_upper_left) in vec4 gl_FragCoord; +#endif + +vec2 gsk_get_frag_coord() { + vec2 fc = gl_FragCoord.xy; + +#ifdef GSK_GL3 + fc += u_viewport.xy; +#else + fc.x += u_viewport.x; + fc.y = (u_viewport.y + u_viewport.w) - fc.y; +#endif + + return fc; +} + +void gskSetOutputColor(vec4 color) { + vec4 result; + +#if defined(NO_CLIP) + result = color; +#elif defined(RECT_CLIP) + result = color * gsk_rect_coverage(gsk_get_bounds(u_clip_rect), + gsk_get_frag_coord()); +#else + result = color * gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect), + gsk_get_frag_coord()); +#endif + +#if defined(GSK_GLES) || defined(GSK_LEGACY) + gl_FragColor = result; +#else + outputColor = result; +#endif +} diff --git a/gsk/ngl/resources/preamble.glsl b/gsk/ngl/resources/preamble.glsl new file mode 100644 index 0000000000..8bc007ba67 --- /dev/null +++ b/gsk/ngl/resources/preamble.glsl @@ -0,0 +1,57 @@ +#ifndef GSK_LEGACY +precision highp float; +#endif + +#if defined(GSK_GLES) || defined(GSK_LEGACY) +#define _OUT_ varying +#define _IN_ varying +#define _NOPERSPECTIVE_ +#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3] +#else +#define _OUT_ out +#define _IN_ in +#define _NOPERSPECTIVE_ noperspective +#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect +#endif + + +struct GskRoundedRect +{ + vec4 bounds; // Top left and bottom right + // Look, arrays can't be in structs if you want to return the struct + // from a function in gles or whatever. Just kill me. + vec4 corner_points1; // xy = top left, zw = top right + vec4 corner_points2; // xy = bottom right, zw = bottom left +}; + +// Transform from a C GskRoundedRect to what we need. +GskRoundedRect +gsk_create_rect(vec4[3] data) +{ + vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw); + + vec4 corner_points1 = vec4(bounds.xy + data[1].xy, + bounds.zy + vec2(data[1].zw * vec2(-1, 1))); + vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)), + bounds.xw + vec2(data[2].zw * vec2(1, -1))); + + return GskRoundedRect(bounds, corner_points1, corner_points2); +} + +vec4 +gsk_get_bounds(vec4[3] data) +{ + return vec4(data[0].xy, data[0].xy + data[0].zw); +} + +vec4 gsk_premultiply(vec4 c) { + return vec4(c.rgb * c.a, c.a); +} + +vec4 gsk_scaled_premultiply(vec4 c, float s) { + // Fast version of gsk_premultiply(c) * s + // 4 muls instead of 7 + float a = s * c.a; + + return vec4(c.rgb * a, a); +} diff --git a/gsk/ngl/resources/preamble.vs.glsl b/gsk/ngl/resources/preamble.vs.glsl new file mode 100644 index 0000000000..89ee6f74e0 --- /dev/null +++ b/gsk/ngl/resources/preamble.vs.glsl @@ -0,0 +1,69 @@ +uniform mat4 u_projection; +uniform mat4 u_modelview; +uniform float u_alpha; + +#if defined(GSK_GLES) || defined(GSK_LEGACY) +attribute vec2 aPosition; +attribute vec2 aUv; +_OUT_ vec2 vUv; +#else +_IN_ vec2 aPosition; +_IN_ vec2 aUv; +_OUT_ vec2 vUv; +#endif + +// amount is: top, right, bottom, left +GskRoundedRect +gsk_rounded_rect_shrink (GskRoundedRect r, vec4 amount) +{ + vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz; + vec4 new_corner_points1 = r.corner_points1; + vec4 new_corner_points2 = r.corner_points2; + + if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy; + if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy; + if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw; + if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw; + + return GskRoundedRect (new_bounds, new_corner_points1, new_corner_points2); +} + +void +gsk_rounded_rect_offset(inout GskRoundedRect r, vec2 offset) +{ + r.bounds.xy += offset; + r.bounds.zw += offset; + r.corner_points1.xy += offset; + r.corner_points1.zw += offset; + r.corner_points2.xy += offset; + r.corner_points2.zw += offset; +} + +void gsk_rounded_rect_transform(inout GskRoundedRect r, mat4 mat) +{ + r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy; + r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy; + + r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy; + r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy; + + r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy; + r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy; +} + +#if defined(GSK_LEGACY) +// Can't have out or inout array parameters... +#define gsk_rounded_rect_encode(r, uni) uni[0] = r.bounds; uni[1] = r.corner_points1; uni[2] = r.corner_points2; +#else +void gsk_rounded_rect_encode(GskRoundedRect r, out _GSK_ROUNDED_RECT_UNIFORM_ out_r) +{ +#if defined(GSK_GLES) + out_r[0] = r.bounds; + out_r[1] = r.corner_points1; + out_r[2] = r.corner_points2; +#else + out_r = r; +#endif +} + +#endif diff --git a/gsk/ngl/resources/radial_gradient.glsl b/gsk/ngl/resources/radial_gradient.glsl new file mode 100644 index 0000000000..0ab3fdf07a --- /dev/null +++ b/gsk/ngl/resources/radial_gradient.glsl @@ -0,0 +1,74 @@ +// VERTEX_SHADER +uniform vec4 u_geometry; + +_NOPERSPECTIVE_ _OUT_ vec2 coord; + +void main() { + gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0)); + + vec2 mv0 = u_modelview[0].xy; + vec2 mv1 = u_modelview[1].xy; + vec2 offset = aPosition - u_geometry.xy; + vec2 dir = vec2(dot(mv0, offset), + dot(mv1, offset)); + + coord = dir * u_geometry.zw; +} + +// FRAGMENT_SHADER: +#ifdef GSK_LEGACY +uniform int u_num_color_stops; +#else +uniform highp int u_num_color_stops; +#endif + +uniform bool u_repeat; +uniform vec2 u_range; +uniform float u_color_stops[6 * 5]; + +_NOPERSPECTIVE_ _IN_ vec2 coord; + +float get_offset(int index) { + return u_color_stops[5 * index]; +} + +vec4 get_color(int index) { + int base = 5 * index + 1; + + return vec4(u_color_stops[base], + u_color_stops[base + 1], + u_color_stops[base + 2], + u_color_stops[base + 3]); +} + +void main() { + // Reverse scale + float offset = length(coord) * u_range.x + u_range.y; + + if (u_repeat) { + offset = fract(offset); + } + + if (offset < get_offset(0)) { + gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha)); + return; + } + + int n = u_num_color_stops - 1; + for (int i = 0; i < n; i++) { + float curr_offset = get_offset(i); + float next_offset = get_offset(i + 1); + + if (offset >= curr_offset && offset < next_offset) { + float f = (offset - curr_offset) / (next_offset - curr_offset); + vec4 curr_color = gsk_premultiply(get_color(i)); + vec4 next_color = gsk_premultiply(get_color(i + 1)); + vec4 color = mix(curr_color, next_color, f); + + gskSetOutputColor(color * u_alpha); + return; + } + } + + gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); +} diff --git a/gsk/ngl/resources/repeat.glsl b/gsk/ngl/resources/repeat.glsl new file mode 100644 index 0000000000..a9ebcc5e10 --- /dev/null +++ b/gsk/ngl/resources/repeat.glsl @@ -0,0 +1,41 @@ +// 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 vec4 u_child_bounds; +uniform vec4 u_texture_rect; + + +float wrap(float f, float wrap_for) { + return mod(f, wrap_for); +} + +/* We get the texture coordinates via vUv, + * but that might be on a texture atlas, so we need to do the + * wrapping ourselves. + */ +void main() { + + /* We map the texture coordinate to [1;0], then wrap it and scale the result again */ + + float tw = u_texture_rect.z - u_texture_rect.x; + float th = u_texture_rect.w - u_texture_rect.y; + + float mapped_x = (vUv.x - u_texture_rect.x) / tw; + float mapped_y = (vUv.y - u_texture_rect.y) / th; + + float wrapped_x = wrap(u_child_bounds.x + mapped_x * u_child_bounds.z, 1.0); + float wrapped_y = wrap(u_child_bounds.y + mapped_y * u_child_bounds.w, 1.0); + + vec2 tp; + tp.x = u_texture_rect.x + (wrapped_x * tw); + tp.y = u_texture_rect.y + (wrapped_y * th); + + vec4 diffuse = GskTexture(u_source, tp); + + gskSetOutputColor(diffuse * u_alpha); +} diff --git a/gsk/ngl/resources/unblurred_outset_shadow.glsl b/gsk/ngl/resources/unblurred_outset_shadow.glsl new file mode 100644 index 0000000000..f110370412 --- /dev/null +++ b/gsk/ngl/resources/unblurred_outset_shadow.glsl @@ -0,0 +1,42 @@ +// VERTEX_SHADER: +uniform vec4 u_color; +uniform float u_spread; +uniform vec2 u_offset; +uniform vec4[3] u_outline_rect; + +_OUT_ vec4 final_color; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + final_color = gsk_premultiply(u_color) * u_alpha; + + GskRoundedRect inside = gsk_create_rect(u_outline_rect); + GskRoundedRect outside = gsk_rounded_rect_shrink(inside, vec4(- u_spread)); + + gsk_rounded_rect_offset(outside, u_offset); + + gsk_rounded_rect_transform(outside, u_modelview); + gsk_rounded_rect_transform(inside, u_modelview); + + gsk_rounded_rect_encode(outside, transformed_outside_outline); + gsk_rounded_rect_encode(inside, transformed_inside_outline); +} + +// FRAGMENT_SHADER: +_IN_ vec4 final_color; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; +_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; + +void main() { + vec2 frag = gsk_get_frag_coord(); + + float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) - + gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag), + 0.0, 1.0); + + gskSetOutputColor(final_color * alpha); +} + From 06d5c8e72dee3d63391fc05ebf081c6f63ed3ce6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Mar 2021 19:46:15 -0500 Subject: [PATCH 2/5] ngl: Set color as vertex attribute Instead of using uniforms for color used in multiple programs, pass it as vertex attributes. This will let us batch more draw calls, since we don't have to change uniforms so often. In particular, for syntax-highlighted text. --- gsk/ngl/gsknglcommandqueue.c | 6 + gsk/ngl/gskngldriver.c | 3 +- gsk/ngl/gskngldriverprivate.h | 8 +- gsk/ngl/gsknglprograms.defs | 8 +- gsk/ngl/gsknglrenderjob.c | 364 ++++++++---------- gsk/ngl/gskngltypesprivate.h | 1 + gsk/ngl/resources/blend.glsl | 1 + gsk/ngl/resources/blit.glsl | 1 + gsk/ngl/resources/border.glsl | 3 +- gsk/ngl/resources/color.glsl | 4 +- gsk/ngl/resources/color_matrix.glsl | 1 + gsk/ngl/resources/coloring.glsl | 4 +- gsk/ngl/resources/conic_gradient.glsl | 3 +- gsk/ngl/resources/cross_fade.glsl | 1 + gsk/ngl/resources/inset_shadow.glsl | 3 +- gsk/ngl/resources/outset_shadow.glsl | 3 +- gsk/ngl/resources/preamble.fs.glsl | 3 +- gsk/ngl/resources/preamble.vs.glsl | 2 + gsk/ngl/resources/repeat.glsl | 2 +- .../resources/unblurred_outset_shadow.glsl | 3 +- 20 files changed, 185 insertions(+), 239 deletions(-) diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c index 9426c199b1..7d5a8b30be 100644 --- a/gsk/ngl/gsknglcommandqueue.c +++ b/gsk/ngl/gsknglcommandqueue.c @@ -1096,6 +1096,12 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self, sizeof (GskNglDrawVertex), (void *) G_STRUCT_OFFSET (GskNglDrawVertex, uv)); + /* 2 = color location */ + glEnableVertexAttribArray (2); + glVertexAttribPointer (2, 4, GL_FLOAT, GL_FALSE, + sizeof (GskNglDrawVertex), + (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color)); + /* Setup initial scissor clip */ if (scissor != NULL) { diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c index 1b00b135ed..3d910e5d51 100644 --- a/gsk/ngl/gskngldriver.c +++ b/gsk/ngl/gskngldriver.c @@ -347,6 +347,7 @@ gsk_ngl_driver_load_programs (GskNglDriver *self, /* Setup attributes that are provided via VBO */ gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0); gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1); + gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2); /* Use XMacros to register all of our programs and their uniforms */ #define GSK_NGL_NO_UNIFORMS @@ -376,7 +377,6 @@ gsk_ngl_driver_load_programs (GskNglDriver *self, uniforms \ \ gsk_ngl_program_uniforms_added (program, have_source); \ - \ if (have_alpha) \ gsk_ngl_program_set_uniform1f (program, UNIFORM_SHARED_ALPHA, 0, 1.0f); \ \ @@ -1045,6 +1045,7 @@ gsk_ngl_driver_lookup_shader (GskNglDriver *self, /* Setup attributes that are provided via VBO */ gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0); gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1); + gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2); if ((program = gsk_ngl_compiler_compile (compiler, NULL, "", error))) { diff --git a/gsk/ngl/gskngldriverprivate.h b/gsk/ngl/gskngldriverprivate.h index 28199ec016..c50e112e86 100644 --- a/gsk/ngl/gskngldriverprivate.h +++ b/gsk/ngl/gskngldriverprivate.h @@ -58,13 +58,17 @@ typedef struct { graphene_rect_t parent_rect; /* Valid when pointer_is_child */ } GskTextureKey; -#define GSL_GK_NO_UNIFORMS UNIFORM_INVALID_##__COUNTER__ +#define GSK_NGL_NO_UNIFORMS CONCAT_EXPANDED(UNIFORM_INVALID_,__COUNTER__) +#define CONCAT_EXPANDED(a,b) CONCAT_EXPANDED2(a,b) +#define CONCAT_EXPANDED2(a,b) a##b #define GSK_NGL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos, #define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms }; # include "gsknglprograms.defs" #undef GSK_NGL_DEFINE_PROGRAM #undef GSK_NGL_ADD_UNIFORM -#undef GSL_GK_NO_UNIFORMS +#undef GSK_NGL_NO_UNIFORMS +#undef CONCAT_EXPANDED +#undef CONCAT_EXPANDED2 #define GSK_TYPE_NGL_DRIVER (gsk_ngl_driver_get_type()) diff --git a/gsk/ngl/gsknglprograms.defs b/gsk/ngl/gsknglprograms.defs index 85c9366ad6..e20cca2fa9 100644 --- a/gsk/ngl/gsknglprograms.defs +++ b/gsk/ngl/gsknglprograms.defs @@ -15,17 +15,16 @@ GSK_NGL_DEFINE_PROGRAM (blur, GSK_NGL_DEFINE_PROGRAM (border, "/org/gtk/libgsk/ngl/border.glsl", - GSK_NGL_ADD_UNIFORM (1, BORDER_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths) GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (color, "/org/gtk/libgsk/ngl/color.glsl", - GSK_NGL_ADD_UNIFORM (1, COLOR_COLOR, u_color)) + GSK_NGL_NO_UNIFORMS) GSK_NGL_DEFINE_PROGRAM (coloring, "/org/gtk/libgsk/ngl/coloring.glsl", - GSK_NGL_ADD_UNIFORM (1, COLORING_COLOR, u_color)) + GSK_NGL_NO_UNIFORMS) GSK_NGL_DEFINE_PROGRAM (color_matrix, "/org/gtk/libgsk/ngl/color_matrix.glsl", @@ -45,7 +44,6 @@ GSK_NGL_DEFINE_PROGRAM (cross_fade, GSK_NGL_DEFINE_PROGRAM (inset_shadow, "/org/gtk/libgsk/ngl/inset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread) GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset) GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect)) @@ -59,7 +57,6 @@ GSK_NGL_DEFINE_PROGRAM (linear_gradient, GSK_NGL_DEFINE_PROGRAM (outset_shadow, "/org/gtk/libgsk/ngl/outset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) GSK_NGL_DEFINE_PROGRAM (radial_gradient, @@ -77,7 +74,6 @@ GSK_NGL_DEFINE_PROGRAM (repeat, GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow, "/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl", - GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_COLOR, u_color) GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread) GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset) GSK_NGL_ADD_UNIFORM (4, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect)) diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index 93ca180133..14e3b3e42b 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -142,6 +142,9 @@ struct _GskNglRenderJob /* Our current alpha state as we process nodes */ float alpha; + /* Our current color state as we process nodes */ + GdkRGBA color; + /* Offset (delta x,y) as we process nodes. Occasionally this is merged into * a transform that is referenced from child transform nodes. */ @@ -395,6 +398,13 @@ gsk_ngl_render_job_set_alpha (GskNglRenderJob *job, return alpha; } +static inline void +gsk_ngl_render_job_set_color (GskNglRenderJob *job, + const GdkRGBA *color) +{ + job->color = *color; +} + static void extract_matrix_metadata (GskNglRenderModelview *modelview) { @@ -874,13 +884,81 @@ gsk_ngl_render_job_update_clip (GskNglRenderJob *job, return TRUE; } +/* fill_vertex_data */ +static void +gsk_ngl_render_job_draw_coords (GskNglRenderJob *job, + float min_x, + float min_y, + float max_x, + float max_y, + float min_u, + float min_v, + float max_u, + float max_v) +{ + GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); + + vertices[0].position[0] = min_x; + vertices[0].position[1] = min_y; + vertices[0].uv[0] = min_u; + vertices[0].uv[1] = min_v; + vertices[0].color[0] = job->color.red; + vertices[0].color[1] = job->color.green; + vertices[0].color[2] = job->color.blue; + vertices[0].color[3] = job->color.alpha; + + vertices[1].position[0] = min_x; + vertices[1].position[1] = max_y; + vertices[1].uv[0] = min_u; + vertices[1].uv[1] = max_v; + vertices[1].color[0] = job->color.red; + vertices[1].color[1] = job->color.green; + vertices[1].color[2] = job->color.blue; + vertices[1].color[3] = job->color.alpha; + + vertices[2].position[0] = max_x; + vertices[2].position[1] = min_y; + vertices[2].uv[0] = max_u; + vertices[2].uv[1] = min_v; + vertices[2].color[0] = job->color.red; + vertices[2].color[1] = job->color.green; + vertices[2].color[2] = job->color.blue; + vertices[2].color[3] = job->color.alpha; + + vertices[3].position[0] = max_x; + vertices[3].position[1] = max_y; + vertices[3].uv[0] = max_u; + vertices[3].uv[1] = max_v; + vertices[3].color[0] = job->color.red; + vertices[3].color[1] = job->color.green; + vertices[3].color[2] = job->color.blue; + vertices[3].color[3] = job->color.alpha; + + vertices[4].position[0] = min_x; + vertices[4].position[1] = max_y; + vertices[4].uv[0] = min_u; + vertices[4].uv[1] = max_v; + vertices[4].color[0] = job->color.red; + vertices[4].color[1] = job->color.green; + vertices[4].color[2] = job->color.blue; + vertices[4].color[3] = job->color.alpha; + + vertices[5].position[0] = max_x; + vertices[5].position[1] = min_y; + vertices[5].uv[0] = max_u; + vertices[5].uv[1] = min_v; + vertices[5].color[0] = job->color.red; + vertices[5].color[1] = job->color.green; + vertices[5].color[2] = job->color.blue; + vertices[5].color[3] = job->color.alpha; +} + /* load_vertex_data_with_region */ static inline void gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *job, const graphene_rect_t *bounds, const GskNglRenderOffscreen *offscreen) { - GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); float min_x = job->offset_x + bounds->origin.x; float min_y = job->offset_y + bounds->origin.y; float max_x = min_x + bounds->size.width; @@ -888,35 +966,9 @@ gsk_ngl_render_job_load_vertices_from_offscreen (GskNglRenderJob *jo float y1 = offscreen->was_offscreen ? offscreen->area.y2 : offscreen->area.y; float y2 = offscreen->was_offscreen ? offscreen->area.y : offscreen->area.y2; - vertices[0].position[0] = min_x; - vertices[0].position[1] = min_y; - vertices[0].uv[0] = offscreen->area.x; - vertices[0].uv[1] = y1; - - vertices[1].position[0] = min_x; - vertices[1].position[1] = max_y; - vertices[1].uv[0] = offscreen->area.x; - vertices[1].uv[1] = y2; - - vertices[2].position[0] = max_x; - vertices[2].position[1] = min_y; - vertices[2].uv[0] = offscreen->area.x2; - vertices[2].uv[1] = y1; - - vertices[3].position[0] = max_x; - vertices[3].position[1] = max_y; - vertices[3].uv[0] = offscreen->area.x2; - vertices[3].uv[1] = y2; - - vertices[4].position[0] = min_x; - vertices[4].position[1] = max_y; - vertices[4].uv[0] = offscreen->area.x; - vertices[4].uv[1] = y2; - - vertices[5].position[0] = max_x; - vertices[5].position[1] = min_y; - vertices[5].uv[0] = offscreen->area.x2; - vertices[5].uv[1] = y1; + gsk_ngl_render_job_draw_coords (job, + min_x, min_y, max_x, max_y, + offscreen->area.x, y1, offscreen->area.x2, y2); } /* load_float_vertex_data */ @@ -927,41 +979,12 @@ gsk_ngl_render_job_draw (GskNglRenderJob *job, float width, float height) { - GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); float min_x = job->offset_x + x; float min_y = job->offset_y + y; float max_x = min_x + width; float max_y = min_y + height; - vertices[0].position[0] = min_x; - vertices[0].position[1] = min_y; - vertices[0].uv[0] = 0; - vertices[0].uv[1] = 0; - - vertices[1].position[0] = min_x; - vertices[1].position[1] = max_y; - vertices[1].uv[0] = 0; - vertices[1].uv[1] = 1; - - vertices[2].position[0] = max_x; - vertices[2].position[1] = min_y; - vertices[2].uv[0] = 1; - vertices[2].uv[1] = 0; - - vertices[3].position[0] = max_x; - vertices[3].position[1] = max_y; - vertices[3].uv[0] = 1; - vertices[3].uv[1] = 1; - - vertices[4].position[0] = min_x; - vertices[4].position[1] = max_y; - vertices[4].uv[0] = 0; - vertices[4].uv[1] = 1; - - vertices[5].position[0] = max_x; - vertices[5].position[1] = min_y; - vertices[5].uv[0] = 1; - vertices[5].uv[1] = 0; + gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 0, 1, 1); } /* load_vertex_data */ @@ -976,47 +999,6 @@ gsk_ngl_render_job_draw_rect (GskNglRenderJob *job, bounds->size.height); } -/* fill_vertex_data */ -static void -gsk_ngl_render_job_draw_coords (GskNglRenderJob *job, - float min_x, - float min_y, - float max_x, - float max_y) -{ - GskNglDrawVertex *vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - - vertices[0].position[0] = min_x; - vertices[0].position[1] = min_y; - vertices[0].uv[0] = 0; - vertices[0].uv[1] = 1; - - vertices[1].position[0] = min_x; - vertices[1].position[1] = max_y; - vertices[1].uv[0] = 0; - vertices[1].uv[1] = 0; - - vertices[2].position[0] = max_x; - vertices[2].position[1] = min_y; - vertices[2].uv[0] = 1; - vertices[2].uv[1] = 1; - - vertices[3].position[0] = max_x; - vertices[3].position[1] = max_y; - vertices[3].uv[0] = 1; - vertices[3].uv[1] = 0; - - vertices[4].position[0] = min_x; - vertices[4].position[1] = max_y; - vertices[4].uv[0] = 0; - vertices[4].uv[1] = 0; - - vertices[5].position[0] = max_x; - vertices[5].position[1] = min_y; - vertices[5].uv[0] = 1; - vertices[5].uv[1] = 1; -} - /* load_offscreen_vertex_data */ static inline void gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job, @@ -1027,7 +1009,7 @@ gsk_ngl_render_job_draw_offscreen_rect (GskNglRenderJob *job, float max_x = min_x + bounds->size.width; float max_y = min_y + bounds->size.height; - gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y); + gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0); } static inline void @@ -1283,7 +1265,7 @@ blur_offscreen (GskNglRenderJob *job, gsk_ngl_program_set_uniform2f (job->current_program, UNIFORM_BLUR_DIR, 0, 1, 0); - gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height); + gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0); gsk_ngl_render_job_end_draw (job); /* Bind second pass framebuffer and clear it */ @@ -1307,7 +1289,7 @@ blur_offscreen (GskNglRenderJob *job, gsk_ngl_program_set_uniform2f (job->current_program, UNIFORM_BLUR_DIR, 0, 0, 1); - gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height); + gsk_ngl_render_job_draw_coords (job, 0, 0, texture_to_blur_width, texture_to_blur_height, 0, 1, 1, 0); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_pop_modelview (job); @@ -1381,9 +1363,7 @@ gsk_ngl_render_job_visit_color_node (GskNglRenderJob *job, const GskRenderNode *node) { gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_COLOR_COLOR, 0, - gsk_color_node_get_color (node)); + gsk_ngl_render_job_set_color (job, gsk_color_node_get_color (node)); gsk_ngl_render_job_draw_rect (job, &node->bounds); gsk_ngl_render_job_end_draw (job); } @@ -1694,9 +1674,7 @@ gsk_ngl_render_job_visit_rect_border_node (GskNglRenderJob *job, gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_COLOR_COLOR, 0, - &colors[0]); + gsk_ngl_render_job_set_color (job, &colors[0]); gsk_ngl_render_job_draw_rect (job, &GRAPHENE_RECT_INIT (origin->x, @@ -1737,12 +1715,10 @@ gsk_ngl_render_job_visit_uniform_border_node (GskNglRenderJob *job, gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); + gsk_ngl_render_job_set_color (job, &colors[0]); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, &outline); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_INSET_SHADOW_COLOR, 0, - &colors[0]); gsk_ngl_program_set_uniform1f (job->current_program, UNIFORM_INSET_SHADOW_SPREAD, 0, widths[0]); @@ -1758,7 +1734,7 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job, const GskRenderNode *node) { const GskRoundedRect *rounded_outline = gsk_border_node_get_outline (node); - const GdkRGBA *colors = gsk_border_node_get_colors (node); + const GdkRGBA *c = gsk_border_node_get_colors (node); const float *widths = gsk_border_node_get_widths (node); struct { float w; @@ -1818,52 +1794,48 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job, const GskNglDrawVertex side_data[4][6] = { /* Top */ { - { { min_x, min_y }, { 0, 1 }, }, /* Upper left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, }, /* Upper right */ + { { min_x, min_y }, { 0, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper left */ + { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */ + { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */ - { { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, }, /* Lower right */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, }, /* Upper right */ + { { max_x - sizes[1].w, min_y + sizes[1].h }, { 1, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower right */ + { { min_x + sizes[0].w, min_y + sizes[0].h }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Lower left */ + { { max_x, min_y }, { 1, 1 }, { c[0].red, c[0].green, c[0].blue, c[0].alpha } }, /* Upper right */ }, /* Right */ { - { { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, }, /* Upper left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, }, /* Upper right */ + { { max_x - sizes[1].w, min_y + sizes[1].h }, { 0, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper left */ + { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */ + { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */ - { { max_x, max_y }, { 1, 0 }, }, /* Lower right */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, }, /* Lower left */ - { { max_x, min_y }, { 1, 1 }, }, /* Upper right */ + { { max_x, max_y }, { 1, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower right */ + { { max_x - sizes[2].w, max_y - sizes[2].h }, { 0, 0 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Lower left */ + { { max_x, min_y }, { 1, 1 }, { c[1].red, c[1].green, c[1].blue, c[1].alpha } }, /* Upper right */ }, /* Bottom */ { - { { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, }, /* Upper left */ - { { min_x, max_y }, { 0, 0 }, }, /* Lower left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, }, /* Upper right */ + { { min_x + sizes[3].w, max_y - sizes[3].h }, { 0, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper left */ + { { min_x, max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */ + { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */ - { { max_x, max_y }, { 1, 0 }, }, /* Lower right */ - { { min_x , max_y }, { 0, 0 }, }, /* Lower left */ - { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, }, /* Upper right */ + { { max_x, max_y }, { 1, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower right */ + { { min_x , max_y }, { 0, 0 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Lower left */ + { { max_x - sizes[2].w, max_y - sizes[2].h }, { 1, 1 }, { c[2].red, c[2].green, c[2].blue, c[2].alpha } }, /* Upper right */ }, /* Left */ { - { { min_x, min_y }, { 0, 1 }, }, /* Upper left */ - { { min_x, max_y }, { 0, 0 }, }, /* Lower left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, }, /* Upper right */ + { { min_x, min_y }, { 0, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper left */ + { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */ + { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */ - { { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, }, /* Lower right */ - { { min_x, max_y }, { 0, 0 }, }, /* Lower left */ - { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, }, /* Upper right */ + { { min_x + sizes[3].w, max_y - sizes[3].h }, { 1, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower right */ + { { min_x, max_y }, { 0, 0 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Lower left */ + { { min_x + sizes[0].w, min_y + sizes[0].h }, { 1, 1 }, { c[3].red, c[3].green, c[3].blue, c[3].alpha } }, /* Upper right */ } }; - int indices[4] = { 0, 1, 2, 3 }; GskRoundedRect outline; GskNglProgram *program; - /* We sort them by color */ - sort_border_sides (colors, indices); - /* Prepare outline */ gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline); @@ -1881,16 +1853,12 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob *job, { GskNglDrawVertex *vertices; - if (widths[indices[i]] <= 0) + if (widths[i] <= 0) continue; gsk_ngl_render_job_begin_draw (job, program); - gsk_ngl_program_set_uniform4fv (job->current_program, - UNIFORM_BORDER_COLOR, 0, - 1, - (const float *)&colors[indices[i]]); vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - memcpy (vertices, side_data[indices[i]], sizeof (GskNglDrawVertex) * GSK_NGL_N_VERTICES); + memcpy (vertices, side_data[i], sizeof (GskNglDrawVertex) * GSK_NGL_N_VERTICES); gsk_ngl_render_job_end_draw (job); } } @@ -2019,12 +1987,10 @@ gsk_ngl_render_job_visit_unblurred_inset_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); + gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_INSET_SHADOW_COLOR, 0, - gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform1f (job->current_program, UNIFORM_INSET_SHADOW_SPREAD, 0, gsk_inset_shadow_node_get_spread (node)); @@ -2122,12 +2088,10 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job, /* Actual inset shadow outline drawing */ gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); + gsk_ngl_render_job_set_color (job, gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_INSET_SHADOW_COLOR, 0, - gsk_inset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform1f (job->current_program, UNIFORM_INSET_SHADOW_SPREAD, 0, spread * MAX (scale_x, scale_y)); @@ -2231,12 +2195,10 @@ gsk_ngl_render_job_visit_unblurred_outset_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_transform_rounded_rect (job, outline, &transformed_outline); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow)); + gsk_ngl_render_job_set_color (job, gsk_outset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_UNBLURRED_OUTSET_SHADOW_COLOR, 0, - gsk_outset_shadow_node_get_color (node)); gsk_ngl_program_set_uniform1f (job->current_program, UNIFORM_UNBLURRED_OUTSET_SHADOW_SPREAD, 0, spread); @@ -2387,9 +2349,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, /* Draw the outline using color program */ gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_COLOR_COLOR, 0, - &white); + gsk_ngl_render_job_set_color (job, &white); gsk_ngl_render_job_draw (job, 0, 0, texture_width, texture_height); gsk_ngl_render_job_end_draw (job); @@ -2433,9 +2393,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, init_full_texture_region (&offscreen); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_OUTSET_SHADOW_COLOR, 0, - color); + gsk_ngl_render_job_set_color (job, color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -2456,9 +2414,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, } gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_OUTSET_SHADOW_COLOR, 0, - color); + gsk_ngl_render_job_set_color (job, color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -2753,14 +2709,9 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, /* If the font has color glyphs, we don't need to recolor anything */ if (!force_color && gsk_text_node_has_color_glyphs (node)) - { - program = CHOOSE_PROGRAM (job, blit); - } + program = CHOOSE_PROGRAM (job, blit); else - { - program = CHOOSE_PROGRAM (job, coloring); - gsk_ngl_program_set_uniform_color (program, UNIFORM_COLORING_COLOR, 0, color); - } + program = CHOOSE_PROGRAM (job, coloring); lookup.font = (PangoFont *)font; lookup.scale = (guint) (text_scale * 1024); @@ -2835,31 +2786,55 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, vertices[base+0].position[1] = glyph_y; vertices[base+0].uv[0] = tx; vertices[base+0].uv[1] = ty; + vertices[base+0].color[0] = color->red; + vertices[base+0].color[1] = color->green; + vertices[base+0].color[2] = color->blue; + vertices[base+0].color[3] = color->alpha; vertices[base+1].position[0] = glyph_x; vertices[base+1].position[1] = glyph_y2; vertices[base+1].uv[0] = tx; vertices[base+1].uv[1] = ty2; + vertices[base+1].color[0] = color->red; + vertices[base+1].color[1] = color->green; + vertices[base+1].color[2] = color->blue; + vertices[base+1].color[3] = color->alpha; vertices[base+2].position[0] = glyph_x2; vertices[base+2].position[1] = glyph_y; vertices[base+2].uv[0] = tx2; vertices[base+2].uv[1] = ty; + vertices[base+2].color[0] = color->red; + vertices[base+2].color[1] = color->green; + vertices[base+2].color[2] = color->blue; + vertices[base+2].color[3] = color->alpha; vertices[base+3].position[0] = glyph_x2; vertices[base+3].position[1] = glyph_y2; vertices[base+3].uv[0] = tx2; vertices[base+3].uv[1] = ty2; + vertices[base+3].color[0] = color->red; + vertices[base+3].color[1] = color->green; + vertices[base+3].color[2] = color->blue; + vertices[base+3].color[3] = color->alpha; vertices[base+4].position[0] = glyph_x; vertices[base+4].position[1] = glyph_y2; vertices[base+4].uv[0] = tx; vertices[base+4].uv[1] = ty2; + vertices[base+4].color[0] = color->red; + vertices[base+4].color[1] = color->green; + vertices[base+4].color[2] = color->blue; + vertices[base+4].color[3] = color->alpha; vertices[base+5].position[0] = glyph_x2; vertices[base+5].position[1] = glyph_y; vertices[base+5].uv[0] = tx2; vertices[base+5].uv[1] = ty; + vertices[base+5].color[0] = color->red; + vertices[base+5].color[1] = color->green; + vertices[base+5].color[2] = color->blue; + vertices[base+5].color[3] = color->alpha; batch->draw.vbo_count += GSK_NGL_N_VERTICES; used++; @@ -2952,14 +2927,12 @@ gsk_ngl_render_job_visit_shadow_node (GskNglRenderJob *job, gsk_ngl_render_job_offset (job, dx, dy); gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)); + gsk_ngl_render_job_set_color (job, &shadow->color); gsk_ngl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_COLORING_COLOR, 0, - &shadow->color); gsk_ngl_render_job_load_vertices_from_offscreen (job, &bounds, &offscreen); gsk_ngl_render_job_end_draw (job); gsk_ngl_render_job_offset (job, -dx, -dy); @@ -3014,7 +2987,7 @@ gsk_ngl_render_job_visit_blur_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, offscreen.texture_id); - gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y); + gsk_ngl_render_job_draw_coords (job, min_x, min_y, max_x, max_y, 0, 1, 1, 0); gsk_ngl_render_job_end_draw (job); } @@ -3123,9 +3096,7 @@ gsk_ngl_render_job_visit_gl_shader_node_fallback (GskNglRenderJob *job, static const GdkRGBA pink = { 255 / 255., 105 / 255., 180 / 255., 1.0 }; gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_ngl_program_set_uniform_color (job->current_program, - UNIFORM_COLOR_COLOR, 0, - &pink); + gsk_ngl_render_job_set_color (job, &pink); gsk_ngl_render_job_draw_rect (job, &node->bounds); gsk_ngl_render_job_end_draw (job); } @@ -3317,7 +3288,6 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job, for (guint i = 0; i < n_slices; i ++) { - GskNglDrawVertex *vertices; const GskNglTextureSlice *slice = &slices[i]; float x1, x2, y1, y2; @@ -3333,37 +3303,8 @@ gsk_ngl_render_job_visit_texture_node (GskNglRenderJob *job, GL_TEXTURE_2D, GL_TEXTURE0, slice->texture_id); - vertices = gsk_ngl_command_queue_add_vertices (job->command_queue); - vertices[0].position[0] = x1; - vertices[0].position[1] = y1; - vertices[0].uv[0] = 0; - vertices[0].uv[1] = 0; - - vertices[1].position[0] = x1; - vertices[1].position[1] = y2; - vertices[1].uv[0] = 0; - vertices[1].uv[1] = 1; - - vertices[2].position[0] = x2; - vertices[2].position[1] = y1; - vertices[2].uv[0] = 1; - vertices[2].uv[1] = 0; - - vertices[3].position[0] = x2; - vertices[3].position[1] = y2; - vertices[3].uv[0] = 1; - vertices[3].uv[1] = 1; - - vertices[4].position[0] = x1; - vertices[4].position[1] = y2; - vertices[4].uv[0] = 0; - vertices[4].uv[1] = 1; - - vertices[5].position[0] = x2; - vertices[5].position[1] = y1; - vertices[5].uv[0] = 1; - vertices[5].uv[1] = 0; + gsk_ngl_render_job_draw_coords (job, x1, y1, x2, y2, 0, 0, 1, 1); } gsk_ngl_render_job_end_draw (job); @@ -3900,6 +3841,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver, job->viewport = *viewport; gsk_ngl_render_job_set_alpha (job, 1.0); + gsk_ngl_render_job_set_color (job, &(GdkRGBA){ 0.f, 0.f, 0.f, 0.f }); gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL); gsk_ngl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor)); diff --git a/gsk/ngl/gskngltypesprivate.h b/gsk/ngl/gskngltypesprivate.h index aba6f2f4c9..dc76fb41f4 100644 --- a/gsk/ngl/gskngltypesprivate.h +++ b/gsk/ngl/gskngltypesprivate.h @@ -55,6 +55,7 @@ struct _GskNglDrawVertex { float position[2]; float uv[2]; + float color[4]; }; G_END_DECLS diff --git a/gsk/ngl/resources/blend.glsl b/gsk/ngl/resources/blend.glsl index 22323402ac..51670f8b78 100644 --- a/gsk/ngl/resources/blend.glsl +++ b/gsk/ngl/resources/blend.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); diff --git a/gsk/ngl/resources/blit.glsl b/gsk/ngl/resources/blit.glsl index f01cd238ec..93416bc6a4 100644 --- a/gsk/ngl/resources/blit.glsl +++ b/gsk/ngl/resources/blit.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); diff --git a/gsk/ngl/resources/border.glsl b/gsk/ngl/resources/border.glsl index 677a0df7cd..997aeab3da 100644 --- a/gsk/ngl/resources/border.glsl +++ b/gsk/ngl/resources/border.glsl @@ -1,5 +1,4 @@ // VERTEX_SHADER: -uniform vec4 u_color; uniform vec4 u_widths; uniform vec4[3] u_outline_rect; @@ -10,7 +9,7 @@ _OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; GskRoundedRect outside = gsk_create_rect(u_outline_rect); GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths); diff --git a/gsk/ngl/resources/color.glsl b/gsk/ngl/resources/color.glsl index 636456ce0d..5d2370bdf5 100644 --- a/gsk/ngl/resources/color.glsl +++ b/gsk/ngl/resources/color.glsl @@ -1,12 +1,10 @@ // VERTEX_SHADER: -uniform vec4 u_color; - _OUT_ vec4 final_color; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; } // FRAGMENT_SHADER: diff --git a/gsk/ngl/resources/color_matrix.glsl b/gsk/ngl/resources/color_matrix.glsl index 79cb36434e..06e645b605 100644 --- a/gsk/ngl/resources/color_matrix.glsl +++ b/gsk/ngl/resources/color_matrix.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); diff --git a/gsk/ngl/resources/coloring.glsl b/gsk/ngl/resources/coloring.glsl index a675493030..b6af0c1766 100644 --- a/gsk/ngl/resources/coloring.glsl +++ b/gsk/ngl/resources/coloring.glsl @@ -1,6 +1,4 @@ // VERTEX_SHADER: -uniform vec4 u_color; - _OUT_ vec4 final_color; void main() { @@ -8,7 +6,7 @@ void main() { vUv = vec2(aUv.x, aUv.y); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; } // FRAGMENT_SHADER: diff --git a/gsk/ngl/resources/conic_gradient.glsl b/gsk/ngl/resources/conic_gradient.glsl index 630a42c5e6..48a1cf7149 100644 --- a/gsk/ngl/resources/conic_gradient.glsl +++ b/gsk/ngl/resources/conic_gradient.glsl @@ -10,8 +10,7 @@ void main() { vec2 mv1 = u_modelview[1].xy; vec2 offset = aPosition - u_geometry.xy; - coord = vec2(dot(mv0, offset), - dot(mv1, offset)); + coord = vec2(dot(mv0, offset), dot(mv1, offset)); } // FRAGMENT_SHADER: diff --git a/gsk/ngl/resources/cross_fade.glsl b/gsk/ngl/resources/cross_fade.glsl index f824430f9d..dddc44fdd0 100644 --- a/gsk/ngl/resources/cross_fade.glsl +++ b/gsk/ngl/resources/cross_fade.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); diff --git a/gsk/ngl/resources/inset_shadow.glsl b/gsk/ngl/resources/inset_shadow.glsl index 9a21cdef09..aae2f2ebef 100644 --- a/gsk/ngl/resources/inset_shadow.glsl +++ b/gsk/ngl/resources/inset_shadow.glsl @@ -1,5 +1,4 @@ // VERTEX_SHADER: -uniform vec4 u_color; uniform float u_spread; uniform vec2 u_offset; uniform vec4[3] u_outline_rect; @@ -11,7 +10,7 @@ _OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; GskRoundedRect outside = gsk_create_rect(u_outline_rect); GskRoundedRect inside = gsk_rounded_rect_shrink(outside, vec4(u_spread)); diff --git a/gsk/ngl/resources/outset_shadow.glsl b/gsk/ngl/resources/outset_shadow.glsl index 373c650179..e8a802e494 100644 --- a/gsk/ngl/resources/outset_shadow.glsl +++ b/gsk/ngl/resources/outset_shadow.glsl @@ -1,5 +1,4 @@ // VERTEX_SHADER: -uniform vec4 u_color; uniform vec4[3] u_outline_rect; _OUT_ vec4 final_color; @@ -10,7 +9,7 @@ void main() { vUv = vec2(aUv.x, aUv.y); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; GskRoundedRect outline = gsk_create_rect(u_outline_rect); gsk_rounded_rect_transform(outline, u_modelview); diff --git a/gsk/ngl/resources/preamble.fs.glsl b/gsk/ngl/resources/preamble.fs.glsl index 3a2fe49240..e715d2526d 100644 --- a/gsk/ngl/resources/preamble.fs.glsl +++ b/gsk/ngl/resources/preamble.fs.glsl @@ -1,7 +1,7 @@ uniform sampler2D u_source; uniform mat4 u_projection; uniform mat4 u_modelview; -uniform float u_alpha;// = 1.0; +uniform float u_alpha; uniform vec4 u_viewport; uniform vec4[3] u_clip_rect; @@ -14,7 +14,6 @@ _OUT_ vec4 outputColor; _IN_ vec2 vUv; - GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r) { #if defined(GSK_GLES) || defined(GSK_LEGACY) diff --git a/gsk/ngl/resources/preamble.vs.glsl b/gsk/ngl/resources/preamble.vs.glsl index 89ee6f74e0..a549ff6ded 100644 --- a/gsk/ngl/resources/preamble.vs.glsl +++ b/gsk/ngl/resources/preamble.vs.glsl @@ -5,10 +5,12 @@ uniform float u_alpha; #if defined(GSK_GLES) || defined(GSK_LEGACY) attribute vec2 aPosition; attribute vec2 aUv; +attribute vec4 aColor; _OUT_ vec2 vUv; #else _IN_ vec2 aPosition; _IN_ vec2 aUv; +_IN_ vec4 aColor; _OUT_ vec2 vUv; #endif diff --git a/gsk/ngl/resources/repeat.glsl b/gsk/ngl/resources/repeat.glsl index a9ebcc5e10..654446c70f 100644 --- a/gsk/ngl/resources/repeat.glsl +++ b/gsk/ngl/resources/repeat.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -9,7 +10,6 @@ void main() { uniform vec4 u_child_bounds; uniform vec4 u_texture_rect; - float wrap(float f, float wrap_for) { return mod(f, wrap_for); } diff --git a/gsk/ngl/resources/unblurred_outset_shadow.glsl b/gsk/ngl/resources/unblurred_outset_shadow.glsl index f110370412..56f0750e6d 100644 --- a/gsk/ngl/resources/unblurred_outset_shadow.glsl +++ b/gsk/ngl/resources/unblurred_outset_shadow.glsl @@ -1,5 +1,4 @@ // VERTEX_SHADER: -uniform vec4 u_color; uniform float u_spread; uniform vec2 u_offset; uniform vec4[3] u_outline_rect; @@ -11,7 +10,7 @@ _OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - final_color = gsk_premultiply(u_color) * u_alpha; + final_color = gsk_premultiply(aColor) * u_alpha; GskRoundedRect inside = gsk_create_rect(u_outline_rect); GskRoundedRect outside = gsk_rounded_rect_shrink(inside, vec4(- u_spread)); From 6a30c6b01c82edfbfd812bacd33a6ace8d363f75 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 12 Mar 2021 01:27:19 -0500 Subject: [PATCH 3/5] ngl: Make the coloring shader more versatile When the color passed is transparent black, use the color from the texture as source, instead of as mask. This lets use use the coloring program both for regular and color glyphs, avoiding program changes in text with Emoji. --- gsk/ngl/gsknglrenderjob.c | 59 ++++++++++++++++++--------------- gsk/ngl/resources/coloring.glsl | 15 ++++++++- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index 14e3b3e42b..8f67575564 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -2703,15 +2703,20 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, guint last_texture = 0; GskNglDrawVertex *vertices; guint used = 0; + GdkRGBA c; if (num_glyphs == 0) return; - /* If the font has color glyphs, we don't need to recolor anything */ + program = CHOOSE_PROGRAM (job, coloring); + + /* If the font has color glyphs, we don't need to recolor anything. + * We tell the shader by setting the color to vec4(-1). + */ if (!force_color && gsk_text_node_has_color_glyphs (node)) - program = CHOOSE_PROGRAM (job, blit); + c = (GdkRGBA) { -1.f, -1.f, -1.f, -1.f }; else - program = CHOOSE_PROGRAM (job, coloring); + c = *color; lookup.font = (PangoFont *)font; lookup.scale = (guint) (text_scale * 1024); @@ -2786,55 +2791,55 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, vertices[base+0].position[1] = glyph_y; vertices[base+0].uv[0] = tx; vertices[base+0].uv[1] = ty; - vertices[base+0].color[0] = color->red; - vertices[base+0].color[1] = color->green; - vertices[base+0].color[2] = color->blue; - vertices[base+0].color[3] = color->alpha; + vertices[base+0].color[0] = c.red; + vertices[base+0].color[1] = c.green; + vertices[base+0].color[2] = c.blue; + vertices[base+0].color[3] = c.alpha; vertices[base+1].position[0] = glyph_x; vertices[base+1].position[1] = glyph_y2; vertices[base+1].uv[0] = tx; vertices[base+1].uv[1] = ty2; - vertices[base+1].color[0] = color->red; - vertices[base+1].color[1] = color->green; - vertices[base+1].color[2] = color->blue; - vertices[base+1].color[3] = color->alpha; + vertices[base+1].color[0] = c.red; + vertices[base+1].color[1] = c.green; + vertices[base+1].color[2] = c.blue; + vertices[base+1].color[3] = c.alpha; vertices[base+2].position[0] = glyph_x2; vertices[base+2].position[1] = glyph_y; vertices[base+2].uv[0] = tx2; vertices[base+2].uv[1] = ty; - vertices[base+2].color[0] = color->red; - vertices[base+2].color[1] = color->green; - vertices[base+2].color[2] = color->blue; - vertices[base+2].color[3] = color->alpha; + vertices[base+2].color[0] = c.red; + vertices[base+2].color[1] = c.green; + vertices[base+2].color[2] = c.blue; + vertices[base+2].color[3] = c.alpha; vertices[base+3].position[0] = glyph_x2; vertices[base+3].position[1] = glyph_y2; vertices[base+3].uv[0] = tx2; vertices[base+3].uv[1] = ty2; - vertices[base+3].color[0] = color->red; - vertices[base+3].color[1] = color->green; - vertices[base+3].color[2] = color->blue; - vertices[base+3].color[3] = color->alpha; + vertices[base+3].color[0] = c.red; + vertices[base+3].color[1] = c.green; + vertices[base+3].color[2] = c.blue; + vertices[base+3].color[3] = c.alpha; vertices[base+4].position[0] = glyph_x; vertices[base+4].position[1] = glyph_y2; vertices[base+4].uv[0] = tx; vertices[base+4].uv[1] = ty2; - vertices[base+4].color[0] = color->red; - vertices[base+4].color[1] = color->green; - vertices[base+4].color[2] = color->blue; - vertices[base+4].color[3] = color->alpha; + vertices[base+4].color[0] = c.red; + vertices[base+4].color[1] = c.green; + vertices[base+4].color[2] = c.blue; + vertices[base+4].color[3] = c.alpha; vertices[base+5].position[0] = glyph_x2; vertices[base+5].position[1] = glyph_y; vertices[base+5].uv[0] = tx2; vertices[base+5].uv[1] = ty; - vertices[base+5].color[0] = color->red; - vertices[base+5].color[1] = color->green; - vertices[base+5].color[2] = color->blue; - vertices[base+5].color[3] = color->alpha; + vertices[base+5].color[0] = c.red; + vertices[base+5].color[1] = c.green; + vertices[base+5].color[2] = c.blue; + vertices[base+5].color[3] = c.alpha; batch->draw.vbo_count += GSK_NGL_N_VERTICES; used++; diff --git a/gsk/ngl/resources/coloring.glsl b/gsk/ngl/resources/coloring.glsl index b6af0c1766..d7d2aed7d6 100644 --- a/gsk/ngl/resources/coloring.glsl +++ b/gsk/ngl/resources/coloring.glsl @@ -1,20 +1,33 @@ // VERTEX_SHADER: _OUT_ vec4 final_color; +flat _OUT_ int use_color; void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); vUv = vec2(aUv.x, aUv.y); + // We use this shader for both plain glyphs (used as mask) + // and color glpyhs (used as source). The renderer sets + // aColor to vec4(-1) for color glyhs. + if (distance(aColor, vec4(-1)) < 0.001) + use_color = 0; + else + use_color = 1; + final_color = gsk_premultiply(aColor) * u_alpha; } // FRAGMENT_SHADER: _IN_ vec4 final_color; +flat _IN_ int use_color; void main() { vec4 diffuse = GskTexture(u_source, vUv); - gskSetOutputColor(final_color * diffuse.a); + if (use_color == 1) + gskSetOutputColor(final_color * diffuse.a); + else + gskSetOutputColor(diffuse * u_alpha); } From 0ee6868b7f2ffbeb0af5644fa864aac824936939 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 12 Mar 2021 01:44:05 -0500 Subject: [PATCH 4/5] gtk-demo: Add a test for scrolling with Emoji Make a text with lots of Emoji and text. This is exercising the GL renderers switching between different shaders for color and plain glyphs. --- demos/gtk-demo/iconscroll.c | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/demos/gtk-demo/iconscroll.c b/demos/gtk-demo/iconscroll.c index 9e2fe9dc8a..2eb9aa6e92 100644 --- a/demos/gtk-demo/iconscroll.c +++ b/demos/gtk-demo/iconscroll.c @@ -13,7 +13,7 @@ static GtkWidget *window = NULL; static GtkWidget *scrolledwindow; static int selected; -#define N_WIDGET_TYPES 7 +#define N_WIDGET_TYPES 8 static int hincrement = 5; @@ -110,6 +110,41 @@ populate_text (gboolean highlight) gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), textview); } +static void +populate_emoji_text (void) +{ + GtkWidget *textview; + GtkTextBuffer *buffer; + GString *s; + + s = g_string_sized_new (1000 * 30 * 4); + + for (int i = 0; i < 1000; i++) + { + if (i % 2) + g_string_append (s, "x"); + for (int j = 0; j < 30; j++) + g_string_append (s, "💓x"); + g_string_append (s, "\n"); + } + + buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_set_text (buffer, s->str, s->len); + + g_string_free (s, TRUE); + + textview = gtk_text_view_new (); + gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer); + + hincrement = 0; + vincrement = 5; + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), textview); +} + static void populate_image (void) { @@ -224,21 +259,26 @@ set_widget_type (int type) break; case 3: + gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with Emoji"); + populate_emoji_text (); + break; + + case 4: gtk_window_set_title (GTK_WINDOW (window), "Scrolling a big image"); populate_image (); break; - case 4: + case 5: gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list"); populate_list (); break; - case 5: + case 6: gtk_window_set_title (GTK_WINDOW (window), "Scrolling a columned list"); populate_list2 (); break; - case 6: + case 7: gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid"); populate_grid (); break; From ebe30d851b1d634a178a7d18e22c0d74124edbc0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 12 Mar 2021 14:25:05 -0500 Subject: [PATCH 5/5] ngl: Identify shaders Add a comment with a name to each shader. That makes identifying the shaders in apitrace much easier. --- gsk/ngl/resources/blend.glsl | 3 +++ gsk/ngl/resources/blit.glsl | 3 +++ gsk/ngl/resources/blur.glsl | 4 ++++ gsk/ngl/resources/border.glsl | 4 ++++ gsk/ngl/resources/color.glsl | 4 ++++ gsk/ngl/resources/color_matrix.glsl | 3 +++ gsk/ngl/resources/coloring.glsl | 3 +++ gsk/ngl/resources/conic_gradient.glsl | 4 ++++ gsk/ngl/resources/cross_fade.glsl | 3 +++ gsk/ngl/resources/custom.glsl | 4 ++++ gsk/ngl/resources/inset_shadow.glsl | 4 ++++ gsk/ngl/resources/linear_gradient.glsl | 3 +++ gsk/ngl/resources/outset_shadow.glsl | 6 +++++- gsk/ngl/resources/radial_gradient.glsl | 4 ++++ gsk/ngl/resources/repeat.glsl | 3 +++ gsk/ngl/resources/unblurred_outset_shadow.glsl | 3 +++ 16 files changed, 57 insertions(+), 1 deletion(-) diff --git a/gsk/ngl/resources/blend.glsl b/gsk/ngl/resources/blend.glsl index 51670f8b78..066c20179d 100644 --- a/gsk/ngl/resources/blend.glsl +++ b/gsk/ngl/resources/blend.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: +// blend.glsl void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -7,6 +8,8 @@ void main() { } // FRAGMENT_SHADER: +// blend.glsl + uniform int u_mode; uniform sampler2D u_source2; diff --git a/gsk/ngl/resources/blit.glsl b/gsk/ngl/resources/blit.glsl index 93416bc6a4..c232be2bfd 100644 --- a/gsk/ngl/resources/blit.glsl +++ b/gsk/ngl/resources/blit.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: +// blit.glsl void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -7,6 +8,8 @@ void main() { } // FRAGMENT_SHADER: +// blit.glsl + void main() { vec4 diffuse = GskTexture(u_source, vUv); diff --git a/gsk/ngl/resources/blur.glsl b/gsk/ngl/resources/blur.glsl index f782ab48cc..7e7c1c2518 100644 --- a/gsk/ngl/resources/blur.glsl +++ b/gsk/ngl/resources/blur.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// blur.glsl + uniform float u_blur_radius; uniform vec2 u_blur_size; uniform vec2 u_blur_dir; @@ -25,6 +27,8 @@ void main() { } // FRAGMENT_SHADER: +// blur.glsl + _IN_ vec2 pixel_step; _IN_ float pixels_per_side; _IN_ vec3 initial_gaussian; diff --git a/gsk/ngl/resources/border.glsl b/gsk/ngl/resources/border.glsl index 997aeab3da..a9c04556a4 100644 --- a/gsk/ngl/resources/border.glsl +++ b/gsk/ngl/resources/border.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// border.glsl + uniform vec4 u_widths; uniform vec4[3] u_outline_rect; @@ -22,6 +24,8 @@ void main() { } // FRAGMENT_SHADER: +// border.glsl + uniform vec4[3] u_outline_rect; _IN_ vec4 final_color; diff --git a/gsk/ngl/resources/color.glsl b/gsk/ngl/resources/color.glsl index 5d2370bdf5..670b9979a2 100644 --- a/gsk/ngl/resources/color.glsl +++ b/gsk/ngl/resources/color.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// color.glsl + _OUT_ vec4 final_color; void main() { @@ -8,6 +10,8 @@ void main() { } // FRAGMENT_SHADER: +// color.glsl + _IN_ vec4 final_color; void main() { diff --git a/gsk/ngl/resources/color_matrix.glsl b/gsk/ngl/resources/color_matrix.glsl index 06e645b605..44dcf9a044 100644 --- a/gsk/ngl/resources/color_matrix.glsl +++ b/gsk/ngl/resources/color_matrix.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: +// color_matrix.glsl void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -7,6 +8,8 @@ void main() { } // FRAGMENT_SHADER: +// color_matrix.glsl + uniform mat4 u_color_matrix; uniform vec4 u_color_offset; diff --git a/gsk/ngl/resources/coloring.glsl b/gsk/ngl/resources/coloring.glsl index d7d2aed7d6..69b21c6e2e 100644 --- a/gsk/ngl/resources/coloring.glsl +++ b/gsk/ngl/resources/coloring.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// coloring.glsl + _OUT_ vec4 final_color; flat _OUT_ int use_color; @@ -19,6 +21,7 @@ void main() { } // FRAGMENT_SHADER: +// coloring.glsl _IN_ vec4 final_color; flat _IN_ int use_color; diff --git a/gsk/ngl/resources/conic_gradient.glsl b/gsk/ngl/resources/conic_gradient.glsl index 48a1cf7149..afb427bb15 100644 --- a/gsk/ngl/resources/conic_gradient.glsl +++ b/gsk/ngl/resources/conic_gradient.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER +// conic_gradient.glsl + uniform vec4 u_geometry; _NOPERSPECTIVE_ _OUT_ vec2 coord; @@ -14,6 +16,8 @@ void main() { } // FRAGMENT_SHADER: +// conic_gradient.glsl + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else diff --git a/gsk/ngl/resources/cross_fade.glsl b/gsk/ngl/resources/cross_fade.glsl index dddc44fdd0..e61af597e9 100644 --- a/gsk/ngl/resources/cross_fade.glsl +++ b/gsk/ngl/resources/cross_fade.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: +// cross_fade.glsl void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -7,6 +8,8 @@ void main() { } // FRAGMENT_SHADER: +// cross_fade.glsl + uniform float u_progress; uniform sampler2D u_source2; diff --git a/gsk/ngl/resources/custom.glsl b/gsk/ngl/resources/custom.glsl index d2aed97fc8..6f91df6cf4 100644 --- a/gsk/ngl/resources/custom.glsl +++ b/gsk/ngl/resources/custom.glsl @@ -1,10 +1,14 @@ // VERTEX_SHADER: +// custom.glsl + void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); vUv = vec2(aUv.x, aUv.y); } // FRAGMENT_SHADER: +// custom.glsl + // The shader supplies: void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv); diff --git a/gsk/ngl/resources/inset_shadow.glsl b/gsk/ngl/resources/inset_shadow.glsl index aae2f2ebef..1c3c955035 100644 --- a/gsk/ngl/resources/inset_shadow.glsl +++ b/gsk/ngl/resources/inset_shadow.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// inset_shadow.glsl + uniform float u_spread; uniform vec2 u_offset; uniform vec4[3] u_outline_rect; @@ -25,6 +27,8 @@ void main() { } // FRAGMENT_SHADER: +// inset_shadow.glsl + _IN_ vec4 final_color; _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline; diff --git a/gsk/ngl/resources/linear_gradient.glsl b/gsk/ngl/resources/linear_gradient.glsl index cc90392c06..1a2f2675e0 100644 --- a/gsk/ngl/resources/linear_gradient.glsl +++ b/gsk/ngl/resources/linear_gradient.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER +// linear_gradient.glsl uniform vec4 u_points; _NOPERSPECTIVE_ _OUT_ vec4 info; @@ -39,6 +40,8 @@ void main() { } // FRAGMENT_SHADER: +// linear_gradient.glsl + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else diff --git a/gsk/ngl/resources/outset_shadow.glsl b/gsk/ngl/resources/outset_shadow.glsl index e8a802e494..427aee956c 100644 --- a/gsk/ngl/resources/outset_shadow.glsl +++ b/gsk/ngl/resources/outset_shadow.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// outset_shadow.glsl + uniform vec4[3] u_outline_rect; _OUT_ vec4 final_color; @@ -17,13 +19,15 @@ void main() { } // FRAGMENT_SHADER: +// outset_shadow.glsl + _IN_ vec4 final_color; _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline; void main() { vec2 frag = gsk_get_frag_coord(); - float alpha = GskTexture(u_source, vUv).a; + alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0)); vec4 color = final_color * alpha; diff --git a/gsk/ngl/resources/radial_gradient.glsl b/gsk/ngl/resources/radial_gradient.glsl index 0ab3fdf07a..e8b57ef635 100644 --- a/gsk/ngl/resources/radial_gradient.glsl +++ b/gsk/ngl/resources/radial_gradient.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER +// radial_gradient.glsl + uniform vec4 u_geometry; _NOPERSPECTIVE_ _OUT_ vec2 coord; @@ -16,6 +18,8 @@ void main() { } // FRAGMENT_SHADER: +// radial_gradient.glsl + #ifdef GSK_LEGACY uniform int u_num_color_stops; #else diff --git a/gsk/ngl/resources/repeat.glsl b/gsk/ngl/resources/repeat.glsl index 654446c70f..5d39603396 100644 --- a/gsk/ngl/resources/repeat.glsl +++ b/gsk/ngl/resources/repeat.glsl @@ -1,4 +1,5 @@ // VERTEX_SHADER: +// repeat.glsl void main() { gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); @@ -7,6 +8,8 @@ void main() { } // FRAGMENT_SHADER: +// repeat.glsl + uniform vec4 u_child_bounds; uniform vec4 u_texture_rect; diff --git a/gsk/ngl/resources/unblurred_outset_shadow.glsl b/gsk/ngl/resources/unblurred_outset_shadow.glsl index 56f0750e6d..305cc5f1e2 100644 --- a/gsk/ngl/resources/unblurred_outset_shadow.glsl +++ b/gsk/ngl/resources/unblurred_outset_shadow.glsl @@ -1,4 +1,6 @@ // VERTEX_SHADER: +// unblurred_outset_shadow.glsl + uniform float u_spread; uniform vec2 u_offset; uniform vec4[3] u_outline_rect; @@ -25,6 +27,7 @@ void main() { } // FRAGMENT_SHADER: +// unblurred_outset_shadow.glsl _IN_ vec4 final_color; _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline; _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;