forked from AuroraMiddleware/gtk
Merge branch 'wip/otte/conic' into 'master'
Implement a GL shader for conic gradients See merge request GNOME/gtk!2913
This commit is contained in:
commit
0daa905a27
@ -54,6 +54,8 @@
|
|||||||
glGetUniformLocation(programs->program_name ## _program.id, "u_" #uniform_basename);\
|
glGetUniformLocation(programs->program_name ## _program.id, "u_" #uniform_basename);\
|
||||||
if (programs->program_name ## _program.program_name.uniform_basename ## _location == -1) \
|
if (programs->program_name ## _program.program_name.uniform_basename ## _location == -1) \
|
||||||
{ \
|
{ \
|
||||||
|
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED, \
|
||||||
|
"Failed to find variable \"u_%s\" in shader program \"%s\"", #uniform_basename, #program_name); \
|
||||||
g_clear_pointer (&programs, gsk_gl_renderer_programs_unref); \
|
g_clear_pointer (&programs, gsk_gl_renderer_programs_unref); \
|
||||||
goto out; \
|
goto out; \
|
||||||
} \
|
} \
|
||||||
@ -1481,6 +1483,35 @@ render_radial_gradient_node (GskGLRenderer *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
render_conic_gradient_node (GskGLRenderer *self,
|
||||||
|
GskRenderNode *node,
|
||||||
|
RenderOpBuilder *builder)
|
||||||
|
{
|
||||||
|
const int n_color_stops = gsk_conic_gradient_node_get_n_color_stops (node);
|
||||||
|
|
||||||
|
if (n_color_stops < GL_MAX_GRADIENT_STOPS)
|
||||||
|
{
|
||||||
|
const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
|
||||||
|
const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
|
||||||
|
const float rotation = gsk_conic_gradient_node_get_rotation (node);
|
||||||
|
|
||||||
|
ops_set_program (builder, &self->programs->conic_gradient_program);
|
||||||
|
ops_set_conic_gradient (builder,
|
||||||
|
n_color_stops,
|
||||||
|
stops,
|
||||||
|
builder->dx + center->x,
|
||||||
|
builder->dy + center->y,
|
||||||
|
rotation);
|
||||||
|
|
||||||
|
load_vertex_data (ops_draw (builder, NULL), &node->bounds, builder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_fallback_node (self, node, builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
||||||
const graphene_rect_t *rect)
|
const graphene_rect_t *rect)
|
||||||
@ -3014,6 +3045,23 @@ apply_radial_gradient_op (const Program *program,
|
|||||||
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
apply_conic_gradient_op (const Program *program,
|
||||||
|
const OpConicGradient *op)
|
||||||
|
{
|
||||||
|
OP_PRINT (" -> Conic gradient");
|
||||||
|
if (op->n_color_stops.send)
|
||||||
|
glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||||
|
|
||||||
|
if (op->color_stops.send)
|
||||||
|
glUniform1fv (program->conic_gradient.color_stops_location,
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
apply_border_op (const Program *program,
|
apply_border_op (const Program *program,
|
||||||
const OpBorder *op)
|
const OpBorder *op)
|
||||||
@ -3248,6 +3296,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
|||||||
{ "/org/gtk/libgsk/glsl/inset_shadow.glsl", "inset shadow" },
|
{ "/org/gtk/libgsk/glsl/inset_shadow.glsl", "inset shadow" },
|
||||||
{ "/org/gtk/libgsk/glsl/linear_gradient.glsl", "linear gradient" },
|
{ "/org/gtk/libgsk/glsl/linear_gradient.glsl", "linear gradient" },
|
||||||
{ "/org/gtk/libgsk/glsl/radial_gradient.glsl", "radial gradient" },
|
{ "/org/gtk/libgsk/glsl/radial_gradient.glsl", "radial gradient" },
|
||||||
|
{ "/org/gtk/libgsk/glsl/conic_gradient.glsl", "conic gradient" },
|
||||||
{ "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" },
|
{ "/org/gtk/libgsk/glsl/outset_shadow.glsl", "outset shadow" },
|
||||||
{ "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" },
|
{ "/org/gtk/libgsk/glsl/repeat.glsl", "repeat" },
|
||||||
{ "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" },
|
{ "/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl", "unblurred_outset shadow" },
|
||||||
@ -3310,6 +3359,12 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
|||||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
||||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
/* blur */
|
/* blur */
|
||||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
||||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
|
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
|
||||||
@ -3361,9 +3416,8 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
|||||||
out:
|
out:
|
||||||
gsk_gl_shader_builder_finish (&shader_builder);
|
gsk_gl_shader_builder_finish (&shader_builder);
|
||||||
|
|
||||||
if (error && !(*error) && !programs)
|
/* Check we indeed emitted an error if there was one */
|
||||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
g_assert (programs || !error || *error);
|
||||||
"Failed to compile all shader programs"); /* Probably, eh. */
|
|
||||||
|
|
||||||
return programs;
|
return programs;
|
||||||
}
|
}
|
||||||
@ -3662,6 +3716,10 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
|||||||
render_radial_gradient_node (self, node, builder);
|
render_radial_gradient_node (self, node, builder);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_CONIC_GRADIENT_NODE:
|
||||||
|
render_conic_gradient_node (self, node, builder);
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_CLIP_NODE:
|
case GSK_CLIP_NODE:
|
||||||
render_clip_node (self, node, builder);
|
render_clip_node (self, node, builder);
|
||||||
break;
|
break;
|
||||||
@ -3723,7 +3781,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
|||||||
|
|
||||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||||
case GSK_CONIC_GRADIENT_NODE:
|
|
||||||
case GSK_CAIRO_NODE:
|
case GSK_CAIRO_NODE:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -4026,6 +4083,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self)
|
|||||||
apply_radial_gradient_op (program, ptr);
|
apply_radial_gradient_op (program, ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_CHANGE_CONIC_GRADIENT:
|
||||||
|
apply_conic_gradient_op (program, ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_CHANGE_BLUR:
|
case OP_CHANGE_BLUR:
|
||||||
apply_blur_op (program, ptr);
|
apply_blur_op (program, ptr);
|
||||||
break;
|
break;
|
||||||
|
@ -1038,3 +1038,27 @@ ops_set_radial_gradient (RenderOpBuilder *self,
|
|||||||
op->start = start;
|
op->start = start;
|
||||||
op->end = end;
|
op->end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ops_set_conic_gradient (RenderOpBuilder *self,
|
||||||
|
guint n_color_stops,
|
||||||
|
const GskColorStop *color_stops,
|
||||||
|
float center_x,
|
||||||
|
float center_y,
|
||||||
|
float rotation)
|
||||||
|
{
|
||||||
|
const guint real_n_color_stops = MIN (GL_MAX_GRADIENT_STOPS, n_color_stops);
|
||||||
|
OpConicGradient *op;
|
||||||
|
|
||||||
|
/* TODO: State tracking? */
|
||||||
|
|
||||||
|
op = ops_begin (self, OP_CHANGE_CONIC_GRADIENT);
|
||||||
|
op->n_color_stops.value = real_n_color_stops;
|
||||||
|
op->n_color_stops.send = true;
|
||||||
|
op->color_stops.value = color_stops;
|
||||||
|
op->color_stops.send = true;
|
||||||
|
op->center[0] = center_x;
|
||||||
|
op->center[1] = center_y;
|
||||||
|
op->rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "opbuffer.h"
|
#include "opbuffer.h"
|
||||||
|
|
||||||
#define GL_N_VERTICES 6
|
#define GL_N_VERTICES 6
|
||||||
#define GL_N_PROGRAMS 14
|
#define GL_N_PROGRAMS 15
|
||||||
#define GL_MAX_GRADIENT_STOPS 6
|
#define GL_MAX_GRADIENT_STOPS 6
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -129,6 +129,12 @@ struct _Program
|
|||||||
int end_location;
|
int end_location;
|
||||||
int radius_location;
|
int radius_location;
|
||||||
} radial_gradient;
|
} radial_gradient;
|
||||||
|
struct {
|
||||||
|
int num_color_stops_location;
|
||||||
|
int color_stops_location;
|
||||||
|
int center_location;
|
||||||
|
int rotation_location;
|
||||||
|
} conic_gradient;
|
||||||
struct {
|
struct {
|
||||||
int blur_radius_location;
|
int blur_radius_location;
|
||||||
int blur_size_location;
|
int blur_size_location;
|
||||||
@ -193,6 +199,7 @@ typedef struct {
|
|||||||
Program inset_shadow_program;
|
Program inset_shadow_program;
|
||||||
Program linear_gradient_program;
|
Program linear_gradient_program;
|
||||||
Program radial_gradient_program;
|
Program radial_gradient_program;
|
||||||
|
Program conic_gradient_program;
|
||||||
Program outset_shadow_program;
|
Program outset_shadow_program;
|
||||||
Program repeat_program;
|
Program repeat_program;
|
||||||
Program unblurred_outset_shadow_program;
|
Program unblurred_outset_shadow_program;
|
||||||
@ -327,6 +334,12 @@ void ops_set_radial_gradient (RenderOpBuilder *self,
|
|||||||
float end,
|
float end,
|
||||||
float hradius,
|
float hradius,
|
||||||
float vradius);
|
float vradius);
|
||||||
|
void ops_set_conic_gradient (RenderOpBuilder *self,
|
||||||
|
guint n_color_stops,
|
||||||
|
const GskColorStop *color_stops,
|
||||||
|
float center_x,
|
||||||
|
float center_y,
|
||||||
|
float rotation);
|
||||||
|
|
||||||
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
||||||
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
||||||
|
@ -33,6 +33,7 @@ static guint op_sizes[OP_LAST] = {
|
|||||||
sizeof (OpBlend),
|
sizeof (OpBlend),
|
||||||
sizeof (OpGLShader),
|
sizeof (OpGLShader),
|
||||||
sizeof (OpExtraTexture),
|
sizeof (OpExtraTexture),
|
||||||
|
sizeof (OpConicGradient),
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -41,6 +41,7 @@ typedef enum
|
|||||||
OP_CHANGE_BLEND = 27,
|
OP_CHANGE_BLEND = 27,
|
||||||
OP_CHANGE_GL_SHADER_ARGS = 28,
|
OP_CHANGE_GL_SHADER_ARGS = 28,
|
||||||
OP_CHANGE_EXTRA_SOURCE_TEXTURE = 29,
|
OP_CHANGE_EXTRA_SOURCE_TEXTURE = 29,
|
||||||
|
OP_CHANGE_CONIC_GRADIENT = 30,
|
||||||
OP_LAST
|
OP_LAST
|
||||||
} OpKind;
|
} OpKind;
|
||||||
|
|
||||||
@ -156,6 +157,14 @@ typedef struct
|
|||||||
float center[2];
|
float center[2];
|
||||||
} OpRadialGradient;
|
} OpRadialGradient;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ColorStopUniformValue color_stops;
|
||||||
|
IntUniformValue n_color_stops;
|
||||||
|
float center[2];
|
||||||
|
float rotation;
|
||||||
|
} OpConicGradient;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const graphene_matrix_t *matrix;
|
const graphene_matrix_t *matrix;
|
||||||
|
@ -5333,8 +5333,8 @@ gsk_render_node_init_types_once (void)
|
|||||||
{
|
{
|
||||||
const GskRenderNodeTypeInfo node_info =
|
const GskRenderNodeTypeInfo node_info =
|
||||||
{
|
{
|
||||||
GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
GSK_CONIC_GRADIENT_NODE,
|
||||||
sizeof (GskRadialGradientNode),
|
sizeof (GskConicGradientNode),
|
||||||
NULL,
|
NULL,
|
||||||
gsk_conic_gradient_node_finalize,
|
gsk_conic_gradient_node_finalize,
|
||||||
gsk_conic_gradient_node_draw,
|
gsk_conic_gradient_node_draw,
|
||||||
|
@ -8,6 +8,7 @@ gsk_private_gl_shaders = [
|
|||||||
'resources/glsl/color.glsl',
|
'resources/glsl/color.glsl',
|
||||||
'resources/glsl/linear_gradient.glsl',
|
'resources/glsl/linear_gradient.glsl',
|
||||||
'resources/glsl/radial_gradient.glsl',
|
'resources/glsl/radial_gradient.glsl',
|
||||||
|
'resources/glsl/conic_gradient.glsl',
|
||||||
'resources/glsl/color_matrix.glsl',
|
'resources/glsl/color_matrix.glsl',
|
||||||
'resources/glsl/blur.glsl',
|
'resources/glsl/blur.glsl',
|
||||||
'resources/glsl/inset_shadow.glsl',
|
'resources/glsl/inset_shadow.glsl',
|
||||||
|
69
gsk/resources/glsl/conic_gradient.glsl
Normal file
69
gsk/resources/glsl/conic_gradient.glsl
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
_OUT_ vec2 center;
|
||||||
|
_OUT_ float rotation;
|
||||||
|
_OUT_ vec4 color_stops[6];
|
||||||
|
_OUT_ float color_offsets[6];
|
||||||
|
|
||||||
|
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, 360.0);
|
||||||
|
if (rotation < 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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
const float PI = 3.1415926535897932384626433832795;
|
||||||
|
|
||||||
|
_IN_ vec2 center;
|
||||||
|
_IN_ float rotation;
|
||||||
|
_IN_ vec4 color_stops[6];
|
||||||
|
_IN_ float color_offsets[6];
|
||||||
|
|
||||||
|
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;
|
||||||
|
// fract() does the modulo here, so now we have progress
|
||||||
|
// into the current conic
|
||||||
|
float offset = fract (angle / 2 / PI + 2);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user