[gtk/wip/chergert/glproto] gskglrenderer: Optimize conic-gradient shader



commit 23da0acb25a472ecf2c0b8133cbd5b06f0701507
Author: Fabio Lagalla <lagfabio amazon com>
Date:   Tue Jan 26 12:40:48 2021 +0100

    gskglrenderer: Optimize conic-gradient shader

 gsk/gl/gskglrenderer.c                 | 18 +++++--
 gsk/gl/gskglrenderopsprivate.h         |  3 +-
 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 649914101c..d606e06164 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -3086,6 +3086,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);
@@ -3095,8 +3099,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
@@ -3397,8 +3408,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));
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]