diff options
author | Fabio Lagalla <lagfabio@amazon.com> | 2021-01-26 12:40:48 +0100 |
---|---|---|
committer | Fabio Lagalla <lagfabio@amazon.com> | 2021-01-27 12:44:10 +0100 |
commit | b15902bf4486cb49b14d948b974fefc919e46fd5 (patch) | |
tree | bd15f027cae51e015ec25ab12032fd51b3044a1e | |
parent | 5ac75297717db967d6390207575f4e170c0095d1 (diff) | |
download | gtk+-b15902bf4486cb49b14d948b974fefc919e46fd5.tar.gz |
gskglrenderer: Optimize conic-gradient shader
-rw-r--r-- | gsk/gl/gskglrenderer.c | 18 | ||||
-rw-r--r-- | gsk/gl/gskglrenderopsprivate.h | 3 | ||||
-rw-r--r-- | gsk/resources/glsl/conic_gradient.glsl | 94 |
3 files changed, 64 insertions, 51 deletions
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 28df34f348..4807dbfba1 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -3074,6 +3074,10 @@ static inline void apply_conic_gradient_op (const Program *program, const OpConicGradient *op) { + float angle; + float bias; + float scale; + OP_PRINT (" -> Conic gradient"); if (op->n_color_stops.send) glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value); @@ -3083,8 +3087,15 @@ apply_conic_gradient_op (const Program *program, op->n_color_stops.value * 5, (float *)op->color_stops.value); - glUniform1f (program->conic_gradient.rotation_location, op->rotation); - glUniform2f (program->conic_gradient.center_location, op->center[0], op->center[1]); + angle = 90.0f - op->rotation; + angle = M_PI * angle / 180.0f; + angle = fmodf (angle, 2.0f * M_PI); + if (angle < 0.0f) + angle += 2.0f * M_PI; + + scale = 0.5f * M_1_PI; + bias = angle * scale + 2.0f; + glUniform4f (program->conic_gradient.geometry_location, op->center[0], op->center[1], scale, bias); } static inline void @@ -3385,8 +3396,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, /* conic gradient */ INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, color_stops); INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, num_color_stops); - INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, center); - INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, rotation); + INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, geometry); /* blur */ INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius); diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index a04e1d2b0f..ada8ed43b2 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -129,8 +129,7 @@ struct _Program struct { int num_color_stops_location; int color_stops_location; - int center_location; - int rotation_location; + int geometry_location; } conic_gradient; struct { int blur_radius_location; diff --git a/gsk/resources/glsl/conic_gradient.glsl b/gsk/resources/glsl/conic_gradient.glsl index 7f73508a3f..630a42c5e6 100644 --- a/gsk/resources/glsl/conic_gradient.glsl +++ b/gsk/resources/glsl/conic_gradient.glsl @@ -1,34 +1,17 @@ // VERTEX_SHADER -uniform vec2 u_center; -uniform float u_rotation; -uniform float u_color_stops[6 * 5]; -uniform int u_num_color_stops; - -const float PI = 3.1415926535897932384626433832795; +uniform vec4 u_geometry; -_OUT_ vec2 center; -_OUT_ float rotation; -_OUT_ vec4 color_stops[6]; -_OUT_ float color_offsets[6]; +_NOPERSPECTIVE_ _OUT_ vec2 coord; void main() { - gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - - // The -90 is because conics point to the top by default - rotation = mod (u_rotation - 90.0, 360.0); - if (rotation < 0.0) - rotation += 360.0; - rotation = PI / 180.0 * rotation; - - center = (u_modelview * vec4(u_center, 0, 1)).xy; - - for (int i = 0; i < u_num_color_stops; i ++) { - color_offsets[i] = u_color_stops[(i * 5) + 0]; - color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1], - u_color_stops[(i * 5) + 2], - u_color_stops[(i * 5) + 3], - u_color_stops[(i * 5) + 4])); - } + 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: @@ -38,32 +21,53 @@ uniform int u_num_color_stops; uniform highp int u_num_color_stops; // Why? Because it works like this. #endif -const float PI = 3.1415926535897932384626433832795; +uniform vec4 u_geometry; +uniform float u_color_stops[6 * 5]; -_IN_ vec2 center; -_IN_ float rotation; -_IN_ vec4 color_stops[6]; -_IN_ float color_offsets[6]; +_NOPERSPECTIVE_ _IN_ vec2 coord; -void main() { - // Position relative to center - vec2 pos = gsk_get_frag_coord() - center; +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] - float angle = atan (pos.y, pos.x); - // rotate, it's now [-2 * PI, PI] - angle -= rotation; + 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 / 2.0 / PI + 2.0); + 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); - vec4 color = color_stops[0]; - for (int i = 1; i < u_num_color_stops; i ++) { - if (offset >= color_offsets[i - 1]) { - float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]); - color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0)); + gskSetOutputColor(color * u_alpha); + return; } } - gskSetOutputColor(color * u_alpha); + gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha)); } |