diff options
author | Sebastian Wick <sebastian.wick@redhat.com> | 2022-05-03 15:22:49 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2022-05-28 04:57:38 +0200 |
commit | c39a551fee3a14b88cce7d2d5c4e57578dd45bd2 (patch) | |
tree | d841e637ecff0f25e3c7b931c9051fdcb3071413 | |
parent | 38ec040fce4a9ca41fba59d1ccb66a9065345951 (diff) | |
download | gtk+-c39a551fee3a14b88cce7d2d5c4e57578dd45bd2.tar.gz |
gsk/gl: Apply dither to gradients and shadows
-rw-r--r-- | gsk/gl/gskglcommandqueue.c | 16 | ||||
-rw-r--r-- | gsk/gl/gskglcommandqueueprivate.h | 3 | ||||
-rw-r--r-- | gsk/gl/gskgldriver.c | 7 | ||||
-rw-r--r-- | gsk/gl/gskgldriverprivate.h | 2 | ||||
-rw-r--r-- | gsk/gl/gskglrenderjob.c | 103 | ||||
-rw-r--r-- | gsk/gl/resources/conic_gradient.glsl | 2 | ||||
-rw-r--r-- | gsk/gl/resources/linear_gradient.glsl | 6 | ||||
-rw-r--r-- | gsk/gl/resources/outset_shadow.glsl | 2 | ||||
-rw-r--r-- | gsk/gl/resources/preamble.fs.glsl | 65 | ||||
-rw-r--r-- | gsk/gl/resources/radial_gradient.glsl | 2 |
10 files changed, 153 insertions, 55 deletions
diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c index 4d7ef4b3d3..ed70fb1aad 100644 --- a/gsk/gl/gskglcommandqueue.c +++ b/gsk/gl/gskglcommandqueue.c @@ -1246,10 +1246,13 @@ gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self, int min_filter, int mag_filter, guint *out_fbo_id, - guint *out_texture_id) + guint *out_texture_id, + int *out_bit_depth) { + GdkGLContext *context = self->context; GLuint fbo_id = 0; GLint texture_id; + int bit_depth; g_assert (GSK_IS_GL_COMMAND_QUEUE (self)); g_assert (width > 0); @@ -1266,6 +1269,7 @@ gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self, { *out_fbo_id = 0; *out_texture_id = 0; + *out_bit_depth = 0; return FALSE; } @@ -1275,8 +1279,18 @@ gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); g_assert_cmphex (glCheckFramebufferStatus (GL_FRAMEBUFFER), ==, GL_FRAMEBUFFER_COMPLETE); + bit_depth = 8; + if (context && gdk_gl_context_check_version (context, 0, 0, 3, 0)) + { + glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, + &bit_depth); + } + *out_fbo_id = fbo_id; *out_texture_id = texture_id; + *out_bit_depth = bit_depth; return TRUE; } diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h index 48911305a8..a3985370ee 100644 --- a/gsk/gl/gskglcommandqueueprivate.h +++ b/gsk/gl/gskglcommandqueueprivate.h @@ -298,7 +298,8 @@ gboolean gsk_gl_command_queue_create_render_target (GskGLCommandQueue int min_filter, int mag_filter, guint *out_fbo_id, - guint *out_texture_id); + guint *out_texture_id, + int *out_bit_depth); void gsk_gl_command_queue_delete_program (GskGLCommandQueue *self, guint program_id); void gsk_gl_command_queue_clear (GskGLCommandQueue *self, diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c index 179e870d80..7bda780159 100644 --- a/gsk/gl/gskgldriver.c +++ b/gsk/gl/gskgldriver.c @@ -387,6 +387,7 @@ gsk_gl_driver_load_programs (GskGLDriver *self, gsk_gl_program_add_uniform (program, "u_viewport", UNIFORM_SHARED_VIEWPORT); \ gsk_gl_program_add_uniform (program, "u_projection", UNIFORM_SHARED_PROJECTION); \ gsk_gl_program_add_uniform (program, "u_modelview", UNIFORM_SHARED_MODELVIEW); \ + gsk_gl_program_add_uniform (program, "u_bit_depth", UNIFORM_SHARED_BIT_DEPTH); \ \ uniforms \ \ @@ -899,6 +900,7 @@ gsk_gl_driver_create_render_target (GskGLDriver *self, { guint framebuffer_id; guint texture_id; + int bit_depth; g_return_val_if_fail (GSK_IS_GL_DRIVER (self), FALSE); g_return_val_if_fail (GSK_IS_GL_COMMAND_QUEUE (self->command_queue), FALSE); @@ -927,7 +929,8 @@ gsk_gl_driver_create_render_target (GskGLDriver *self, width, height, format, min_filter, mag_filter, - &framebuffer_id, &texture_id)) + &framebuffer_id, &texture_id, + &bit_depth)) { GskGLRenderTarget *render_target; @@ -939,6 +942,7 @@ gsk_gl_driver_create_render_target (GskGLDriver *self, render_target->height = height; render_target->framebuffer_id = framebuffer_id; render_target->texture_id = texture_id; + render_target->bit_depth = bit_depth; *out_render_target = render_target; @@ -1098,6 +1102,7 @@ gsk_gl_driver_lookup_shader (GskGLDriver *self, gsk_gl_program_add_uniform (program, "u_viewport", UNIFORM_SHARED_VIEWPORT); gsk_gl_program_add_uniform (program, "u_projection", UNIFORM_SHARED_PROJECTION); gsk_gl_program_add_uniform (program, "u_modelview", UNIFORM_SHARED_MODELVIEW); + gsk_gl_program_add_uniform (program, "u_bit_depth", UNIFORM_SHARED_BIT_DEPTH); have_alpha = gsk_gl_program_add_uniform (program, "u_alpha", UNIFORM_SHARED_ALPHA); gsk_gl_program_add_uniform (program, "u_size", UNIFORM_CUSTOM_SIZE); diff --git a/gsk/gl/gskgldriverprivate.h b/gsk/gl/gskgldriverprivate.h index accae5b3bb..1cb439da1a 100644 --- a/gsk/gl/gskgldriverprivate.h +++ b/gsk/gl/gskgldriverprivate.h @@ -35,6 +35,7 @@ enum { UNIFORM_SHARED_VIEWPORT, UNIFORM_SHARED_PROJECTION, UNIFORM_SHARED_MODELVIEW, + UNIFORM_SHARED_BIT_DEPTH, UNIFORM_SHARED_LAST }; @@ -91,6 +92,7 @@ struct _GskGLRenderTarget int format; int width; int height; + int bit_depth; }; struct _GskGLDriver diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c index 97b3d9d4c9..3d59b2340e 100644 --- a/gsk/gl/gskglrenderjob.c +++ b/gsk/gl/gskglrenderjob.c @@ -173,6 +173,10 @@ struct _GskGLRenderJob * looking at the format of the framebuffer we are rendering on. */ int target_format; + + /* Bit depth of the framebuffer we render into + */ + int bit_depth; }; typedef struct _GskGLRenderOffscreen @@ -209,6 +213,39 @@ static gboolean gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob const GskRenderNode *node, GskGLRenderOffscreen *offscreen); +static int +get_framebuffer_bit_depth (GdkGLContext *context, + guint framebuffer) +{ + int size; + + if (!gdk_gl_context_check_version (context, 0, 0, 3, 0)) + return 8; + + glBindFramebuffer (GL_FRAMEBUFFER, framebuffer); + glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, + framebuffer ? GL_COLOR_ATTACHMENT0 + : gdk_gl_context_get_use_es (context) ? GL_BACK + : GL_BACK_LEFT, + GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size); + + return size; +} + +static int +get_framebuffer_format (GdkGLContext *context, + guint framebuffer) +{ + int size = get_framebuffer_bit_depth (context, framebuffer); + + if (size > 16) + return GL_RGBA32F; + else if (size > 8) + return GL_RGBA16F; + else + return GL_RGBA8; +} + static inline int get_target_format (GskGLRenderJob *job, const GskRenderNode *node) @@ -475,6 +512,21 @@ init_projection_matrix (graphene_matrix_t *projection, graphene_matrix_scale (projection, 1, -1, 1); } +static inline int +gsk_gl_render_job_set_bit_depth (GskGLRenderJob *job, + int bit_depth) +{ + if (job->bit_depth != bit_depth) + { + int ret = job->bit_depth; + job->bit_depth = bit_depth; + job->driver->stamps[UNIFORM_SHARED_BIT_DEPTH]++; + return ret; + } + + return bit_depth; +} + static inline float gsk_gl_render_job_set_alpha (GskGLRenderJob *job, float alpha) @@ -1157,6 +1209,12 @@ gsk_gl_render_job_begin_draw (GskGLRenderJob *job, UNIFORM_SHARED_ALPHA, job->driver->stamps[UNIFORM_SHARED_ALPHA], job->alpha); + + gsk_gl_uniform_state_set1f (program->uniforms, + program->program_info, + UNIFORM_SHARED_BIT_DEPTH, + job->driver->stamps[UNIFORM_SHARED_BIT_DEPTH], + job->bit_depth); } #define CHOOSE_PROGRAM(job,name) \ @@ -1312,6 +1370,7 @@ blur_offscreen (GskGLRenderJob *job, graphene_matrix_t prev_projection; graphene_rect_t prev_viewport; guint prev_fbo; + int prev_bit_depth; g_assert (blur_radius_x > 0); g_assert (blur_radius_y > 0); @@ -1346,6 +1405,7 @@ blur_offscreen (GskGLRenderJob *job, /* Bind new framebuffer and clear it */ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, pass1->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + prev_bit_depth = gsk_gl_render_job_set_bit_depth (job, pass1->bit_depth); /* Begin drawing the first horizontal pass, using offscreen as the * source texture for the program. @@ -1375,6 +1435,7 @@ blur_offscreen (GskGLRenderJob *job, /* Bind second pass framebuffer and clear it */ gsk_gl_command_queue_bind_framebuffer (job->command_queue, pass2->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + gsk_gl_render_job_set_bit_depth (job, pass2->bit_depth); /* Draw using blur program with first pass as source texture */ gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blur)); @@ -1404,6 +1465,7 @@ blur_offscreen (GskGLRenderJob *job, gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL); gsk_gl_render_job_set_projection (job, &prev_projection); gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo); + gsk_gl_render_job_set_bit_depth (job, prev_bit_depth); gsk_gl_driver_release_render_target (job->driver, pass1, TRUE); @@ -2223,6 +2285,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job, graphene_matrix_t prev_projection; graphene_rect_t prev_viewport; guint prev_fbo; + int prev_bit_depth; /* TODO: In the following code, we have to be careful about where we apply the scale. * We're manually scaling stuff (e.g. the outline) so we can later use texture_width @@ -2265,6 +2328,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job, prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + prev_bit_depth = gsk_gl_render_job_set_bit_depth (job, render_target->bit_depth); gsk_gl_render_job_transform_rounded_rect (job, &outline_to_blur, &transformed_outline); @@ -2291,6 +2355,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job, gsk_gl_render_job_set_projection (job, &prev_projection); gsk_gl_render_job_set_viewport (job, &prev_viewport, NULL); gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo); + gsk_gl_render_job_set_bit_depth (job, prev_bit_depth); offscreen.texture_id = render_target->texture_id; init_full_texture_region (&offscreen); @@ -2523,6 +2588,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, graphene_matrix_t prev_projection; graphene_rect_t prev_viewport; guint prev_fbo; + int prev_bit_depth; gsk_gl_driver_create_render_target (job->driver, texture_width, texture_height, @@ -2553,6 +2619,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, /* Bind render target and clear it */ prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + prev_bit_depth = gsk_gl_render_job_set_bit_depth (job, render_target->bit_depth); /* Draw the outline using color program */ gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); @@ -2582,6 +2649,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, blurred_texture_id); gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo); + gsk_gl_render_job_set_bit_depth (job, prev_bit_depth); } else { @@ -3924,6 +3992,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job, graphene_rect_t prev_viewport; float prev_alpha; guint prev_fbo; + int prev_bit_depth; if (!gsk_gl_driver_create_render_target (job->driver, texture_width, texture_height, @@ -3954,6 +4023,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job, prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + prev_bit_depth = gsk_gl_render_job_set_bit_depth (job, render_target->bit_depth); if (offscreen->reset_clip) gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport)); @@ -3973,6 +4043,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job, gsk_gl_render_job_set_projection (job, &prev_projection); gsk_gl_render_job_set_alpha (job, prev_alpha); gsk_gl_command_queue_bind_framebuffer (job->command_queue, prev_fbo); + gsk_gl_render_job_set_bit_depth (job, prev_bit_depth); job->offset_x = offset_x; job->offset_y = offset_y; @@ -3996,6 +4067,8 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job, guint framebuffer_id; guint texture_id; guint surface_height; + int bit_depth; + int prev_bit_depth; g_return_if_fail (job != NULL); g_return_if_fail (root != NULL); @@ -4017,12 +4090,14 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job, MAX (1, job->viewport.size.height), job->target_format, GL_NEAREST, GL_NEAREST, - &framebuffer_id, &texture_id)) + &framebuffer_id, &texture_id, + &bit_depth)) return; /* Setup drawing to our offscreen texture/framebuffer which is flipped */ gsk_gl_command_queue_bind_framebuffer (job->command_queue, framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + prev_bit_depth = gsk_gl_render_job_set_bit_depth (job, bit_depth); /* Visit all nodes creating batches */ gdk_gl_context_push_debug_group (job->command_queue->context, "Building command queue"); @@ -4033,6 +4108,7 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job, gsk_gl_render_job_set_alpha (job, 1.0f); gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); + gsk_gl_render_job_set_bit_depth (job, prev_bit_depth); gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)); gsk_gl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, @@ -4107,30 +4183,6 @@ gsk_gl_render_job_set_debug_fallback (GskGLRenderJob *job, job->debug_fallback = !!debug_fallback; } -static int -get_framebuffer_format (GdkGLContext *context, - guint framebuffer) -{ - int size; - - if (!gdk_gl_context_check_version (context, 0, 0, 3, 0)) - return GL_RGBA8; - - glBindFramebuffer (GL_FRAMEBUFFER, framebuffer); - glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, - framebuffer ? GL_COLOR_ATTACHMENT0 - : gdk_gl_context_get_use_es (context) ? GL_BACK - : GL_BACK_LEFT, - GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size); - - if (size > 16) - return GL_RGBA32F; - else if (size > 8) - return GL_RGBA16F; - else - return GL_RGBA8; -} - GskGLRenderJob * gsk_gl_render_job_new (GskGLDriver *driver, const graphene_rect_t *viewport, @@ -4177,6 +4229,7 @@ gsk_gl_render_job_new (GskGLDriver *driver, gsk_gl_render_job_set_alpha (job, 1.0f); gsk_gl_render_job_set_projection_from_rect (job, viewport, NULL); gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_factor, scale_factor)); + gsk_gl_render_job_set_bit_depth (job, get_framebuffer_bit_depth (job->command_queue->context, framebuffer)); /* Setup our initial clip. If region is NULL then we are drawing the * whole viewport. Otherwise, we need to convert the region to a diff --git a/gsk/gl/resources/conic_gradient.glsl b/gsk/gl/resources/conic_gradient.glsl index f1d33cd6a7..422a9b4563 100644 --- a/gsk/gl/resources/conic_gradient.glsl +++ b/gsk/gl/resources/conic_gradient.glsl @@ -78,7 +78,7 @@ void main() { 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); - gskSetScaledOutputColor(color, u_alpha); + gskSetScaledDitheredOutputColor(color, u_alpha); return; } } diff --git a/gsk/gl/resources/linear_gradient.glsl b/gsk/gl/resources/linear_gradient.glsl index fa130be4cb..5ff81c75fb 100644 --- a/gsk/gl/resources/linear_gradient.glsl +++ b/gsk/gl/resources/linear_gradient.glsl @@ -87,7 +87,8 @@ void main() { } if (offset >= get_offset(u_num_color_stops - 1)) { - gskSetOutputColor(gsk_scaled_premultiply(get_color(u_num_color_stops - 1), u_alpha)); + vec4 color = get_color(u_num_color_stops - 1); + gskSetDitheredOutputColor(gsk_scaled_premultiply(color, u_alpha)); return; } @@ -99,8 +100,7 @@ void main() { 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); - gskSetScaledOutputColor(color, u_alpha); + gskSetScaledDitheredOutputColor(mix(curr_color, next_color, f), u_alpha); return; } } diff --git a/gsk/gl/resources/outset_shadow.glsl b/gsk/gl/resources/outset_shadow.glsl index 44b05aa152..2a262cf066 100644 --- a/gsk/gl/resources/outset_shadow.glsl +++ b/gsk/gl/resources/outset_shadow.glsl @@ -30,5 +30,5 @@ void main() { alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0)); - gskSetScaledOutputColor(final_color, alpha); + gskSetScaledDitheredOutputColor(final_color, alpha); } diff --git a/gsk/gl/resources/preamble.fs.glsl b/gsk/gl/resources/preamble.fs.glsl index c1c5a954ee..534311f4db 100644 --- a/gsk/gl/resources/preamble.fs.glsl +++ b/gsk/gl/resources/preamble.fs.glsl @@ -4,6 +4,7 @@ uniform mat4 u_modelview; uniform float u_alpha; uniform vec4 u_viewport; uniform vec4[3] u_clip_rect; +uniform float u_bit_depth; #if defined(GSK_LEGACY) _OUT_ vec4 outputColor; @@ -117,29 +118,25 @@ vec2 gsk_get_frag_coord() { return fc; } -void gskSetOutputColor(vec4 color) { - vec4 result; +// from "NEXT GENERATION POST PROCESSING IN CALL OF DUTY: ADVANCED WARFARE" +// http://advances.realtimerendering.com/s2014/index.html +float gsk_interleaved_gradient_noise(vec2 uv) { + const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189); + return fract(magic.z * fract(dot(uv, magic.xy))); +} -#if defined(NO_CLIP) - result = color; -#elif defined(RECT_CLIP) - float coverage = gsk_rect_coverage(gsk_get_bounds(u_clip_rect), - gsk_get_frag_coord()); - result = color * coverage; -#else - float coverage = gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect), - gsk_get_frag_coord()); - result = color * coverage; -#endif +vec4 gskDither(vec4 color) { + if (u_bit_depth > 10) + return color; -#if defined(GSK_GLES) || defined(GSK_LEGACY) - gl_FragColor = result; -#else - outputColor = result; -#endif + float noise = gsk_interleaved_gradient_noise(gsk_get_frag_coord()) - 0.5; + // scale the noise to the number of steps we have + noise = noise / (pow(2.0, u_bit_depth) - 1.0); + color = vec4(color.rgb + noise, color.a); + return color; } -void gskSetScaledOutputColor(vec4 color, float alpha) { +vec4 gsk_get_output_color(vec4 color, float alpha) { vec4 result; #if defined(NO_CLIP) @@ -154,9 +151,35 @@ void gskSetScaledOutputColor(vec4 color, float alpha) { result = color * (alpha * coverage); #endif + return result; +} + +void gsk_set_output_color(vec4 color) { #if defined(GSK_GLES) || defined(GSK_LEGACY) - gl_FragColor = result; + gl_FragColor = color; #else - outputColor = result; + outputColor = color; #endif } + +void gskSetOutputColor(vec4 color) { + vec4 result = gsk_get_output_color(color, 1.0); + gsk_set_output_color(result); +} + +void gskSetDitheredOutputColor(vec4 color) { + vec4 result = gsk_get_output_color(color, 1.0); + result = gskDither(result); + gsk_set_output_color(result); +} + +void gskSetScaledOutputColor(vec4 color, float alpha) { + vec4 result = gsk_get_output_color(color, alpha); + gsk_set_output_color(result); +} + +void gskSetScaledDitheredOutputColor(vec4 color, float alpha) { + vec4 result = gsk_get_output_color(color, alpha); + result = gskDither(result); + gsk_set_output_color(result); +} diff --git a/gsk/gl/resources/radial_gradient.glsl b/gsk/gl/resources/radial_gradient.glsl index 59fad00290..82c5600769 100644 --- a/gsk/gl/resources/radial_gradient.glsl +++ b/gsk/gl/resources/radial_gradient.glsl @@ -80,7 +80,7 @@ void main() { 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); - gskSetScaledOutputColor(color, u_alpha); + gskSetScaledDitheredOutputColor(color, u_alpha); return; } } |