gpu: Add a radial gradient shader
This is mainly copy/paste, so now this almost identical gradient code exists 3 times. That's kinda suboptimal.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "gskgpulineargradientopprivate.h"
|
||||
#include "gskgpumaskopprivate.h"
|
||||
#include "gskgpumipmapopprivate.h"
|
||||
#include "gskgpuradialgradientopprivate.h"
|
||||
#include "gskgpurenderpassopprivate.h"
|
||||
#include "gskgpuroundedcoloropprivate.h"
|
||||
#include "gskgpuscissoropprivate.h"
|
||||
@@ -2164,6 +2165,39 @@ gsk_gpu_node_processor_create_linear_gradient_pattern (GskGpuPatternWriter *self
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_radial_gradient_op (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
gsk_gpu_radial_gradient_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
GSK_RENDER_NODE_TYPE (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
||||
&node->bounds,
|
||||
gsk_radial_gradient_node_get_center (node),
|
||||
&GRAPHENE_POINT_INIT (
|
||||
gsk_radial_gradient_node_get_hradius (node),
|
||||
gsk_radial_gradient_node_get_vradius (node)
|
||||
),
|
||||
gsk_radial_gradient_node_get_start (node),
|
||||
gsk_radial_gradient_node_get_end (node),
|
||||
&self->offset,
|
||||
stops,
|
||||
n_stops);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_add_radial_gradient_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
gsk_gpu_node_processor_add_gradient_node (self,
|
||||
node,
|
||||
gsk_radial_gradient_node_get_color_stops (node, NULL),
|
||||
gsk_radial_gradient_node_get_n_color_stops (node),
|
||||
gsk_gpu_node_processor_radial_gradient_op);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gpu_node_processor_create_radial_gradient_pattern (GskGpuPatternWriter *self,
|
||||
GskRenderNode *node)
|
||||
@@ -3188,13 +3222,13 @@ static const struct
|
||||
[GSK_RADIAL_GRADIENT_NODE] = {
|
||||
0,
|
||||
GSK_GPU_HANDLE_OPACITY,
|
||||
gsk_gpu_node_processor_add_node_as_pattern,
|
||||
gsk_gpu_node_processor_add_radial_gradient_node,
|
||||
gsk_gpu_node_processor_create_radial_gradient_pattern,
|
||||
},
|
||||
[GSK_REPEATING_RADIAL_GRADIENT_NODE] = {
|
||||
0,
|
||||
GSK_GPU_HANDLE_OPACITY,
|
||||
gsk_gpu_node_processor_add_node_as_pattern,
|
||||
gsk_gpu_node_processor_add_radial_gradient_node,
|
||||
gsk_gpu_node_processor_create_radial_gradient_pattern,
|
||||
},
|
||||
[GSK_CONIC_GRADIENT_NODE] = {
|
||||
|
||||
100
gsk/gpu/gskgpuradialgradientop.c
Normal file
100
gsk/gpu/gskgpuradialgradientop.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpuradialgradientopprivate.h"
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpuradialgradientinstance.h"
|
||||
|
||||
typedef struct _GskGpuRadialGradientOp GskGpuRadialGradientOp;
|
||||
|
||||
struct _GskGpuRadialGradientOp
|
||||
{
|
||||
GskGpuShaderOp op;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_radial_gradient_op_print (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
|
||||
GskGpuRadialgradientInstance *instance;
|
||||
|
||||
instance = (GskGpuRadialgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
if (instance->repeating)
|
||||
gsk_gpu_print_op (string, indent, "repeating-radial-gradient");
|
||||
else
|
||||
gsk_gpu_print_op (string, indent, "radial-gradient");
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
|
||||
{
|
||||
GSK_GPU_OP_SIZE (GskGpuRadialGradientOp),
|
||||
GSK_GPU_STAGE_SHADER,
|
||||
gsk_gpu_shader_op_finish,
|
||||
gsk_gpu_radial_gradient_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_shader_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_shader_op_gl_command
|
||||
},
|
||||
"gskgpuradialgradient",
|
||||
sizeof (GskGpuRadialgradientInstance),
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
&gsk_gpu_radialgradient_info,
|
||||
#endif
|
||||
gsk_gpu_radialgradient_setup_vao
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_radial_gradient_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
gboolean repeating,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *center,
|
||||
const graphene_point_t *radius,
|
||||
float start,
|
||||
float end,
|
||||
const graphene_point_t *offset,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
GskGpuRadialgradientInstance *instance;
|
||||
|
||||
g_assert (n_stops > 1);
|
||||
g_assert (n_stops <= 7);
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_RADIAL_GRADIENT_OP_CLASS,
|
||||
clip,
|
||||
NULL,
|
||||
&instance);
|
||||
|
||||
instance->repeating = repeating;
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_point_to_float (center, offset, instance->center_radius);
|
||||
gsk_gpu_point_to_float (radius, graphene_point_zero(), &instance->center_radius[2]);
|
||||
instance->startend[0] = start;
|
||||
instance->startend[1] = end;
|
||||
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 6)].color, instance->color6);
|
||||
instance->offsets1[2] = stops[MIN (n_stops - 1, 6)].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 5)].color, instance->color5);
|
||||
instance->offsets1[1] = stops[MIN (n_stops - 1, 5)].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 4)].color, instance->color4);
|
||||
instance->offsets1[0] = stops[MIN (n_stops - 1, 4)].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 3)].color, instance->color3);
|
||||
instance->offsets0[3] = stops[MIN (n_stops - 1, 3)].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[MIN (n_stops - 1, 2)].color, instance->color2);
|
||||
instance->offsets0[2] = stops[MIN (n_stops - 1, 2)].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[1].color, instance->color1);
|
||||
instance->offsets0[1] = stops[1].offset;
|
||||
gsk_gpu_rgba_to_float (&stops[0].color, instance->color0);
|
||||
instance->offsets0[0] = stops[0].offset;
|
||||
}
|
||||
25
gsk/gpu/gskgpuradialgradientopprivate.h
Normal file
25
gsk/gpu/gskgpuradialgradientopprivate.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
#include "gskrendernode.h"
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_radial_gradient_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
gboolean repeating,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *center,
|
||||
const graphene_point_t *radius,
|
||||
float start,
|
||||
float end,
|
||||
const graphene_point_t *offset,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
131
gsk/gpu/shaders/gskgpuradialgradient.glsl
Normal file
131
gsk/gpu/shaders/gskgpuradialgradient.glsl
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "common.glsl"
|
||||
|
||||
PASS(0) vec2 _pos;
|
||||
PASS_FLAT(1) Rect _rect;
|
||||
PASS_FLAT(2) vec4 _color0;
|
||||
PASS_FLAT(3) vec4 _color1;
|
||||
PASS_FLAT(4) vec4 _color2;
|
||||
PASS_FLAT(5) vec4 _color3;
|
||||
PASS_FLAT(6) vec4 _color4;
|
||||
PASS_FLAT(7) vec4 _color5;
|
||||
PASS_FLAT(8) vec4 _color6;
|
||||
PASS_FLAT(9) vec4 _offsets0;
|
||||
PASS_FLAT(10) vec3 _offsets1;
|
||||
PASS_FLAT(11) vec4 _center_radius;
|
||||
PASS_FLAT(12) vec2 _startend;
|
||||
PASS_FLAT(13) uint _repeating;
|
||||
|
||||
|
||||
#ifdef GSK_VERTEX_SHADER
|
||||
|
||||
IN(0) vec4 in_rect;
|
||||
IN(1) vec4 in_color0;
|
||||
IN(2) vec4 in_color1;
|
||||
IN(3) vec4 in_color2;
|
||||
IN(4) vec4 in_color3;
|
||||
IN(5) vec4 in_color4;
|
||||
IN(6) vec4 in_color5;
|
||||
IN(7) vec4 in_color6;
|
||||
IN(8) vec4 in_offsets0;
|
||||
IN(9) vec3 in_offsets1;
|
||||
IN(10) vec4 in_center_radius;
|
||||
IN(11) vec2 in_startend;
|
||||
IN(12) uint in_repeating;
|
||||
|
||||
void
|
||||
run (out vec2 pos)
|
||||
{
|
||||
Rect r = rect_from_gsk (in_rect);
|
||||
|
||||
pos = rect_get_position (r);
|
||||
|
||||
_pos = pos;
|
||||
_rect = r;
|
||||
|
||||
_center_radius = in_center_radius;
|
||||
_startend = in_startend;
|
||||
_repeating = in_repeating;
|
||||
|
||||
_color0 = in_color0;
|
||||
_color1 = in_color1;
|
||||
_color2 = in_color2;
|
||||
_color3 = in_color3;
|
||||
_color4 = in_color4;
|
||||
_color5 = in_color5;
|
||||
_color6 = in_color6;
|
||||
_offsets0 = in_offsets0;
|
||||
_offsets1 = in_offsets1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef GSK_FRAGMENT_SHADER
|
||||
|
||||
vec4
|
||||
get_gradient_color (float offset)
|
||||
{
|
||||
vec4 color;
|
||||
|
||||
if (offset <= _offsets0[3])
|
||||
{
|
||||
if (offset <= _offsets0[1])
|
||||
{
|
||||
if (offset <= _offsets0[0])
|
||||
color = _color0;
|
||||
else
|
||||
color = mix (_color0, _color1, (offset - _offsets0[0]) / (_offsets0[1] - _offsets0[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset <= _offsets0[2])
|
||||
color = mix (_color1, _color2, (offset - _offsets0[1]) / (_offsets0[2] - _offsets0[1]));
|
||||
else
|
||||
color = mix (_color2, _color3, (offset - _offsets0[2]) / (_offsets0[3] - _offsets0[2]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset <= _offsets1[1])
|
||||
{
|
||||
if (offset <= _offsets1[0])
|
||||
color = mix (_color3, _color4, (offset - _offsets0[3]) / (_offsets1[0] - _offsets0[3]));
|
||||
else
|
||||
color = mix (_color4, _color5, (offset - _offsets1[0]) / (_offsets1[1] - _offsets1[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset <= _offsets1[2])
|
||||
color = mix (_color5, _color6, (offset - _offsets1[1]) / (_offsets1[2] - _offsets1[1]));
|
||||
else
|
||||
color = _color6;
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4
|
||||
get_gradient_color_at (vec2 pos)
|
||||
{
|
||||
float offset = length (pos / _center_radius.zw);
|
||||
offset = (offset - _startend.x) / (_startend.y - _startend.x);
|
||||
if (_repeating != 0u)
|
||||
offset = fract (offset);
|
||||
else
|
||||
offset = clamp (offset, 0.0, 1.0);
|
||||
|
||||
return color_premultiply (get_gradient_color (offset));
|
||||
}
|
||||
|
||||
void
|
||||
run (out vec4 color,
|
||||
out vec2 position)
|
||||
{
|
||||
float alpha = rect_coverage (_rect, _pos);
|
||||
|
||||
color = alpha * get_gradient_color_at (_pos / GSK_GLOBAL_SCALE - _center_radius.xy);
|
||||
position = _pos;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@ gsk_private_gpu_shaders = files([
|
||||
'gskgpuconicgradient.glsl',
|
||||
'gskgpulineargradient.glsl',
|
||||
'gskgpumask.glsl',
|
||||
'gskgpuradialgradient.glsl',
|
||||
'gskgpuroundedcolor.glsl',
|
||||
'gskgpustraightalpha.glsl',
|
||||
'gskgputexture.glsl',
|
||||
|
||||
@@ -96,6 +96,7 @@ gsk_private_sources = files([
|
||||
'gpu/gskgpunodeprocessor.c',
|
||||
'gpu/gskgpuop.c',
|
||||
'gpu/gskgpuprint.c',
|
||||
'gpu/gskgpuradialgradientop.c',
|
||||
'gpu/gskgpurenderer.c',
|
||||
'gpu/gskgpurenderpassop.c',
|
||||
'gpu/gskgpuroundedcolorop.c',
|
||||
|
||||
Reference in New Issue
Block a user