mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 13:11:13 +00:00
gpu: Add a conic gradient shader
This commit is contained in:
parent
0c32a94d8e
commit
0e9b967bf9
91
gsk/gpu/gskgpuconicgradientop.c
Normal file
91
gsk/gpu/gskgpuconicgradientop.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpuconicgradientopprivate.h"
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpuconicgradientinstance.h"
|
||||
|
||||
typedef struct _GskGpuConicGradientOp GskGpuConicGradientOp;
|
||||
|
||||
struct _GskGpuConicGradientOp
|
||||
{
|
||||
GskGpuShaderOp op;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_conic_gradient_op_print (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
|
||||
GskGpuConicgradientInstance *instance;
|
||||
|
||||
instance = (GskGpuConicgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "conic-gradient");
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
|
||||
{
|
||||
GSK_GPU_OP_SIZE (GskGpuConicGradientOp),
|
||||
GSK_GPU_STAGE_SHADER,
|
||||
gsk_gpu_shader_op_finish,
|
||||
gsk_gpu_conic_gradient_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_shader_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_shader_op_gl_command
|
||||
},
|
||||
"gskgpuconicgradient",
|
||||
sizeof (GskGpuConicgradientInstance),
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
&gsk_gpu_conicgradient_info,
|
||||
#endif
|
||||
gsk_gpu_conicgradient_setup_vao
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_conic_gradient_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *center,
|
||||
float angle,
|
||||
const graphene_point_t *offset,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
GskGpuConicgradientInstance *instance;
|
||||
|
||||
g_assert (n_stops > 1);
|
||||
g_assert (n_stops <= 7);
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_CONIC_GRADIENT_OP_CLASS,
|
||||
clip,
|
||||
NULL,
|
||||
&instance);
|
||||
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_point_to_float (center, offset, instance->center);
|
||||
instance->angle = angle;
|
||||
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;
|
||||
}
|
22
gsk/gpu/gskgpuconicgradientopprivate.h
Normal file
22
gsk/gpu/gskgpuconicgradientopprivate.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
#include "gskrendernode.h"
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_conic_gradient_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *center,
|
||||
float angle,
|
||||
const graphene_point_t *offset,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "gskgpucolorizeopprivate.h"
|
||||
#include "gskgpucolormatrixopprivate.h"
|
||||
#include "gskgpucoloropprivate.h"
|
||||
#include "gskgpuconicgradientopprivate.h"
|
||||
#include "gskgpudescriptorsprivate.h"
|
||||
#include "gskgpudeviceprivate.h"
|
||||
#include "gskgpuframeprivate.h"
|
||||
@ -2186,6 +2187,33 @@ gsk_gpu_node_processor_create_radial_gradient_pattern (GskGpuPatternWriter *self
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_conic_gradient_op (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node,
|
||||
const GskColorStop *stops,
|
||||
gsize n_stops)
|
||||
{
|
||||
gsk_gpu_conic_gradient_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
&node->bounds,
|
||||
gsk_conic_gradient_node_get_center (node),
|
||||
gsk_conic_gradient_node_get_angle (node),
|
||||
&self->offset,
|
||||
stops,
|
||||
n_stops);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_add_conic_gradient_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
gsk_gpu_node_processor_add_gradient_node (self,
|
||||
node,
|
||||
gsk_conic_gradient_node_get_color_stops (node, NULL),
|
||||
gsk_conic_gradient_node_get_n_color_stops (node),
|
||||
gsk_gpu_node_processor_conic_gradient_op);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gpu_node_processor_create_conic_gradient_pattern (GskGpuPatternWriter *self,
|
||||
GskRenderNode *node)
|
||||
@ -3172,7 +3200,7 @@ static const struct
|
||||
[GSK_CONIC_GRADIENT_NODE] = {
|
||||
0,
|
||||
GSK_GPU_HANDLE_OPACITY,
|
||||
gsk_gpu_node_processor_add_node_as_pattern,
|
||||
gsk_gpu_node_processor_add_conic_gradient_node,
|
||||
gsk_gpu_node_processor_create_conic_gradient_pattern,
|
||||
},
|
||||
[GSK_BORDER_NODE] = {
|
||||
|
125
gsk/gpu/shaders/gskgpuconicgradient.glsl
Normal file
125
gsk/gpu/shaders/gskgpuconicgradient.glsl
Normal file
@ -0,0 +1,125 @@
|
||||
#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) vec2 _center;
|
||||
PASS_FLAT(12) float _angle;
|
||||
|
||||
|
||||
#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) vec2 in_center;
|
||||
IN(11) float in_angle;
|
||||
|
||||
void
|
||||
run (out vec2 pos)
|
||||
{
|
||||
Rect r = rect_from_gsk (in_rect);
|
||||
|
||||
pos = rect_get_position (r);
|
||||
|
||||
_pos = pos;
|
||||
_rect = r;
|
||||
|
||||
_center = in_center;
|
||||
_angle = in_angle;
|
||||
|
||||
_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 = atan (pos.y, pos.x);
|
||||
offset = degrees (offset + _angle) / 360.0;
|
||||
offset = fract (offset);
|
||||
return color_premultiply (get_gradient_color (offset));
|
||||
}
|
||||
|
||||
void
|
||||
run (out vec4 color,
|
||||
out vec2 position)
|
||||
{
|
||||
float alpha = rect_coverage (_rect, _pos);
|
||||
|
||||
vec2 conic_pos = _pos / GSK_GLOBAL_SCALE - _center;
|
||||
color = alpha * get_gradient_color_at (conic_pos);
|
||||
position = _pos;
|
||||
}
|
||||
|
||||
#endif
|
@ -19,6 +19,7 @@ gsk_private_gpu_shaders = files([
|
||||
'gskgpucolor.glsl',
|
||||
'gskgpucolorize.glsl',
|
||||
'gskgpucolormatrix.glsl',
|
||||
'gskgpuconicgradient.glsl',
|
||||
'gskgpulineargradient.glsl',
|
||||
'gskgpumask.glsl',
|
||||
'gskgpuroundedcolor.glsl',
|
||||
|
@ -83,6 +83,7 @@ gsk_private_sources = files([
|
||||
'gpu/gskgpucolorizeop.c',
|
||||
'gpu/gskgpucolormatrixop.c',
|
||||
'gpu/gskgpucolorop.c',
|
||||
'gpu/gskgpuconicgradientop.c',
|
||||
'gpu/gskgpudescriptors.c',
|
||||
'gpu/gskgpudownloadop.c',
|
||||
'gpu/gskgpudevice.c',
|
||||
|
Loading…
Reference in New Issue
Block a user