gskglrenderer: Optimize conic-gradient shader

This commit is contained in:
Fabio Lagalla
2021-01-26 12:40:48 +01:00
parent 5ac7529771
commit b15902bf44
3 changed files with 62 additions and 49 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
uniform vec4 u_geometry;
const float PI = 3.1415926535897932384626433832795;
_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);
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;
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
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]));
}
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;
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() {
// Position relative to center
vec2 pos = gsk_get_frag_coord() - center;
// 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);
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));
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(color * u_alpha);
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}