mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 21:21:21 +00:00
gpu: Add a border shader
Pretty much a copy of the Vulkan border shader. A notable change is that the input arguments are changed, because GL gets confused if you put a mat4 at the end.
This commit is contained in:
parent
16c804c5e3
commit
3efe1bef93
132
gsk/gpu/gskgpuborderop.c
Normal file
132
gsk/gpu/gskgpuborderop.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gskgpuborderopprivate.h"
|
||||||
|
|
||||||
|
#include "gskgpuframeprivate.h"
|
||||||
|
#include "gskgpuprintprivate.h"
|
||||||
|
#include "gskgpushaderopprivate.h"
|
||||||
|
#include "gsk/gskroundedrectprivate.h"
|
||||||
|
|
||||||
|
#include "gpu/shaders/gskgpuborderinstance.h"
|
||||||
|
|
||||||
|
typedef struct _GskGpuBorderOp GskGpuBorderOp;
|
||||||
|
|
||||||
|
struct _GskGpuBorderOp
|
||||||
|
{
|
||||||
|
GskGpuShaderOp op;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_border_op_finish (GskGpuOp *op)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
color_equal (const float *color1,
|
||||||
|
const float *color2)
|
||||||
|
{
|
||||||
|
return gdk_rgba_equal (&(GdkRGBA) { color1[0], color1[1], color1[2], color1[3] },
|
||||||
|
&(GdkRGBA) { color1[0], color1[1], color1[2], color1[3] });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_border_op_print (GskGpuOp *op,
|
||||||
|
GskGpuFrame *frame,
|
||||||
|
GString *string,
|
||||||
|
guint indent)
|
||||||
|
{
|
||||||
|
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
|
||||||
|
GskGpuBorderInstance *instance;
|
||||||
|
|
||||||
|
instance = (GskGpuBorderInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||||
|
|
||||||
|
gsk_gpu_print_op (string, indent, "border");
|
||||||
|
gsk_gpu_print_rounded_rect (string, instance->outline);
|
||||||
|
|
||||||
|
gsk_gpu_print_rgba (string, (const float *) &instance->border_colors[0]);
|
||||||
|
if (!color_equal (&instance->border_colors[12], &instance->border_colors[0]) ||
|
||||||
|
!color_equal (&instance->border_colors[8], &instance->border_colors[0]) ||
|
||||||
|
!color_equal (&instance->border_colors[4], &instance->border_colors[0]))
|
||||||
|
{
|
||||||
|
gsk_gpu_print_rgba (string, &instance->border_colors[4]);
|
||||||
|
gsk_gpu_print_rgba (string, &instance->border_colors[8]);
|
||||||
|
gsk_gpu_print_rgba (string, &instance->border_colors[12]);
|
||||||
|
}
|
||||||
|
g_string_append_printf (string, "%g ", instance->border_widths[0]);
|
||||||
|
if (instance->border_widths[0] != instance->border_widths[1] ||
|
||||||
|
instance->border_widths[0] != instance->border_widths[2] ||
|
||||||
|
instance->border_widths[0] != instance->border_widths[3])
|
||||||
|
{
|
||||||
|
g_string_append_printf (string, "%g %g %g ",
|
||||||
|
instance->border_widths[1],
|
||||||
|
instance->border_widths[2],
|
||||||
|
instance->border_widths[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gsk_gpu_print_newline (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
|
static GskGpuOp *
|
||||||
|
gsk_gpu_border_op_vk_command (GskGpuOp *op,
|
||||||
|
GskGpuFrame *frame,
|
||||||
|
VkRenderPass render_pass,
|
||||||
|
VkFormat format,
|
||||||
|
VkCommandBuffer command_buffer)
|
||||||
|
{
|
||||||
|
return gsk_gpu_shader_op_vk_command_n (op, frame, render_pass, format, command_buffer, 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static GskGpuOp *
|
||||||
|
gsk_gpu_border_op_gl_command (GskGpuOp *op,
|
||||||
|
GskGpuFrame *frame,
|
||||||
|
gsize flip_y)
|
||||||
|
{
|
||||||
|
return gsk_gpu_shader_op_gl_command_n (op, frame, flip_y, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GskGpuShaderOpClass GSK_GPU_BORDER_OP_CLASS = {
|
||||||
|
{
|
||||||
|
GSK_GPU_OP_SIZE (GskGpuBorderOp),
|
||||||
|
GSK_GPU_STAGE_SHADER,
|
||||||
|
gsk_gpu_border_op_finish,
|
||||||
|
gsk_gpu_border_op_print,
|
||||||
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
|
gsk_gpu_border_op_vk_command,
|
||||||
|
#endif
|
||||||
|
gsk_gpu_border_op_gl_command
|
||||||
|
},
|
||||||
|
"gskgpuborder",
|
||||||
|
sizeof (GskGpuBorderInstance),
|
||||||
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
|
&gsk_gpu_border_info,
|
||||||
|
#endif
|
||||||
|
gsk_gpu_border_setup_vao
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_gpu_border_op (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
const GskRoundedRect *outline,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const float widths[4],
|
||||||
|
const GdkRGBA colors[4])
|
||||||
|
{
|
||||||
|
GskGpuBorderInstance *instance;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
gsk_gpu_shader_op_alloc (frame,
|
||||||
|
&GSK_GPU_BORDER_OP_CLASS,
|
||||||
|
clip,
|
||||||
|
&instance);
|
||||||
|
|
||||||
|
gsk_rounded_rect_to_float (outline, offset, instance->outline);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
instance->border_widths[i] = widths[i];
|
||||||
|
gsk_gpu_rgba_to_float (&colors[i], &instance->border_colors[4 * i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
gsk/gpu/gskgpuborderopprivate.h
Normal file
19
gsk/gpu/gskgpuborderopprivate.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gskgputypesprivate.h"
|
||||||
|
#include "gsktypes.h"
|
||||||
|
|
||||||
|
#include <graphene.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gsk_gpu_border_op (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
const GskRoundedRect *outline,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const float widths[4],
|
||||||
|
const GdkRGBA colors[4]);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "gskgpunodeprocessorprivate.h"
|
#include "gskgpunodeprocessorprivate.h"
|
||||||
|
|
||||||
|
#include "gskgpuborderopprivate.h"
|
||||||
#include "gskgpuclipprivate.h"
|
#include "gskgpuclipprivate.h"
|
||||||
#include "gskgpudeviceprivate.h"
|
#include "gskgpudeviceprivate.h"
|
||||||
#include "gskgpuframeprivate.h"
|
#include "gskgpuframeprivate.h"
|
||||||
@ -696,6 +697,18 @@ gsk_gpu_node_processor_create_color_pattern (GskGpuNodeProcessor *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_node_processor_add_border_node (GskGpuNodeProcessor *self,
|
||||||
|
GskRenderNode *node)
|
||||||
|
{
|
||||||
|
gsk_gpu_border_op (self->frame,
|
||||||
|
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||||
|
gsk_border_node_get_outline (node),
|
||||||
|
&self->offset,
|
||||||
|
gsk_border_node_get_widths (node),
|
||||||
|
gsk_border_node_get_colors (node));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||||
GskRenderNode *node)
|
GskRenderNode *node)
|
||||||
@ -1042,7 +1055,7 @@ static const struct
|
|||||||
},
|
},
|
||||||
[GSK_BORDER_NODE] = {
|
[GSK_BORDER_NODE] = {
|
||||||
0,
|
0,
|
||||||
NULL,
|
gsk_gpu_node_processor_add_border_node,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
[GSK_TEXTURE_NODE] = {
|
[GSK_TEXTURE_NODE] = {
|
||||||
|
@ -70,5 +70,15 @@ GskGpuOp * gsk_gpu_shader_op_gl_command (GskGpuO
|
|||||||
GskGpuFrame *frame,
|
GskGpuFrame *frame,
|
||||||
gsize flip_y);
|
gsize flip_y);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gsk_gpu_rgba_to_float (const GdkRGBA *rgba,
|
||||||
|
float values[4])
|
||||||
|
{
|
||||||
|
values[0] = rgba->red;
|
||||||
|
values[1] = rgba->green;
|
||||||
|
values[2] = rgba->blue;
|
||||||
|
values[3] = rgba->alpha;
|
||||||
|
}
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -51,6 +51,66 @@ rect_get_position (Rect rect)
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2
|
||||||
|
border_get_position (RoundedRect outline,
|
||||||
|
vec4 border_widths)
|
||||||
|
{
|
||||||
|
uint slice_index = uint (GSK_VERTEX_INDEX) / 6u;
|
||||||
|
uint vert_index = uint (GSK_VERTEX_INDEX) % 6u;
|
||||||
|
|
||||||
|
vec4 corner_widths = max (outline.corner_widths, border_widths.wyyw);
|
||||||
|
vec4 corner_heights = max (outline.corner_heights, border_widths.xxzz);
|
||||||
|
|
||||||
|
Rect rect;
|
||||||
|
|
||||||
|
switch (slice_index)
|
||||||
|
{
|
||||||
|
case SLICE_TOP_LEFT:
|
||||||
|
rect = Rect (outline.bounds.xyxy + vec4 (0.0, 0.0, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]));
|
||||||
|
rect = rect_round_larger (rect);
|
||||||
|
rect.bounds = rect.bounds.xwzy;
|
||||||
|
break;
|
||||||
|
case SLICE_TOP:
|
||||||
|
rect = Rect (vec4 (outline.bounds.x + corner_widths[TOP_LEFT], outline.bounds.y,
|
||||||
|
outline.bounds.z - corner_widths[TOP_RIGHT], outline.bounds.y + border_widths[TOP]));
|
||||||
|
rect = rect_round_smaller_larger (rect);
|
||||||
|
break;
|
||||||
|
case SLICE_TOP_RIGHT:
|
||||||
|
rect = Rect (outline.bounds.zyzy + vec4 (- corner_widths[TOP_RIGHT], 0.0, 0.0, corner_heights[TOP_RIGHT]));
|
||||||
|
rect = rect_round_larger (rect);
|
||||||
|
break;
|
||||||
|
case SLICE_RIGHT:
|
||||||
|
rect = Rect (vec4 (outline.bounds.z - border_widths[RIGHT], outline.bounds.y + corner_widths[TOP_RIGHT],
|
||||||
|
outline.bounds.z, outline.bounds.w - corner_widths[BOTTOM_RIGHT]));
|
||||||
|
rect = rect_round_larger_smaller (rect);
|
||||||
|
break;
|
||||||
|
case SLICE_BOTTOM_RIGHT:
|
||||||
|
rect = Rect (outline.bounds.zwzw + vec4 (- corner_widths[BOTTOM_RIGHT], - corner_heights[BOTTOM_RIGHT], 0.0, 0.0));
|
||||||
|
rect = rect_round_larger (rect);
|
||||||
|
rect.bounds = rect.bounds.zyxw;
|
||||||
|
break;
|
||||||
|
case SLICE_BOTTOM:
|
||||||
|
rect = Rect (vec4 (outline.bounds.x + corner_widths[BOTTOM_LEFT], outline.bounds.w - border_widths[BOTTOM],
|
||||||
|
outline.bounds.z - corner_widths[BOTTOM_RIGHT], outline.bounds.w));
|
||||||
|
rect = rect_round_smaller_larger (rect);
|
||||||
|
break;
|
||||||
|
case SLICE_BOTTOM_LEFT:
|
||||||
|
rect = Rect (outline.bounds.xwxw + vec4 (0.0, - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT], 0.0));
|
||||||
|
rect = rect_round_larger (rect);
|
||||||
|
rect.bounds = rect.bounds.zwxy;
|
||||||
|
break;
|
||||||
|
case SLICE_LEFT:
|
||||||
|
rect = Rect (vec4 (outline.bounds.x + border_widths[LEFT], outline.bounds.y + corner_widths[TOP_LEFT],
|
||||||
|
outline.bounds.x, outline.bounds.w - corner_widths[BOTTOM_LEFT]));
|
||||||
|
rect = rect_round_larger_smaller (rect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[vert_index]);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
vec2
|
vec2
|
||||||
scale_tex_coord (vec2 in_pos,
|
scale_tex_coord (vec2 in_pos,
|
||||||
Rect in_rect,
|
Rect in_rect,
|
||||||
|
@ -17,4 +17,23 @@
|
|||||||
#define GSK_GPU_PATTERN_REPEATING_RADIAL_GRADIENT 9u
|
#define GSK_GPU_PATTERN_REPEATING_RADIAL_GRADIENT 9u
|
||||||
#define GSK_GPU_PATTERN_CONIC_GRADIENT 10u
|
#define GSK_GPU_PATTERN_CONIC_GRADIENT 10u
|
||||||
|
|
||||||
|
#define TOP 0u
|
||||||
|
#define RIGHT 1u
|
||||||
|
#define BOTTOM 2u
|
||||||
|
#define LEFT 3u
|
||||||
|
|
||||||
|
#define TOP_LEFT 0u
|
||||||
|
#define TOP_RIGHT 1u
|
||||||
|
#define BOTTOM_RIGHT 2u
|
||||||
|
#define BOTTOM_LEFT 3u
|
||||||
|
|
||||||
|
#define SLICE_TOP_LEFT 0u
|
||||||
|
#define SLICE_TOP 1u
|
||||||
|
#define SLICE_TOP_RIGHT 2u
|
||||||
|
#define SLICE_RIGHT 3u
|
||||||
|
#define SLICE_BOTTOM_RIGHT 4u
|
||||||
|
#define SLICE_BOTTOM 5u
|
||||||
|
#define SLICE_BOTTOM_LEFT 6u
|
||||||
|
#define SLICE_LEFT 7u
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
84
gsk/gpu/shaders/gskgpuborder.glsl
Normal file
84
gsk/gpu/shaders/gskgpuborder.glsl
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "common.glsl"
|
||||||
|
|
||||||
|
PASS(0) vec2 _pos;
|
||||||
|
PASS_FLAT(1) vec4 _color;
|
||||||
|
PASS_FLAT(2) RoundedRect _outside;
|
||||||
|
PASS_FLAT(5) RoundedRect _inside;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GSK_VERTEX_SHADER
|
||||||
|
|
||||||
|
IN(0) mat4 in_border_colors;
|
||||||
|
IN(4) mat3x4 in_outline;
|
||||||
|
IN(7) vec4 in_border_widths;
|
||||||
|
|
||||||
|
vec4
|
||||||
|
compute_color (void)
|
||||||
|
{
|
||||||
|
uint triangle_index = uint (GSK_VERTEX_INDEX) / 3u;
|
||||||
|
uint index;
|
||||||
|
|
||||||
|
switch (triangle_index)
|
||||||
|
{
|
||||||
|
case 2u * SLICE_TOP_LEFT + 1u:
|
||||||
|
case 2u * SLICE_TOP:
|
||||||
|
case 2u * SLICE_TOP + 1u:
|
||||||
|
case 2u * SLICE_TOP_RIGHT:
|
||||||
|
index = TOP;
|
||||||
|
break;
|
||||||
|
case 2u * SLICE_TOP_RIGHT + 1u:
|
||||||
|
case 2u * SLICE_RIGHT:
|
||||||
|
case 2u * SLICE_RIGHT + 1u:
|
||||||
|
case 2u * SLICE_BOTTOM_RIGHT:
|
||||||
|
index = RIGHT;
|
||||||
|
break;
|
||||||
|
case 2u * SLICE_BOTTOM_RIGHT + 1u:
|
||||||
|
case 2u * SLICE_BOTTOM:
|
||||||
|
case 2u * SLICE_BOTTOM + 1u:
|
||||||
|
case 2u * SLICE_BOTTOM_LEFT:
|
||||||
|
index = BOTTOM;
|
||||||
|
break;
|
||||||
|
case 2u * SLICE_BOTTOM_LEFT + 1u:
|
||||||
|
case 2u * SLICE_LEFT:
|
||||||
|
case 2u * SLICE_LEFT + 1u:
|
||||||
|
case 2u * SLICE_TOP_LEFT:
|
||||||
|
index = LEFT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return color_premultiply (in_border_colors[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run (out vec2 pos)
|
||||||
|
{
|
||||||
|
vec4 border_widths = in_border_widths * push.scale.yxyx;
|
||||||
|
RoundedRect outside = rounded_rect_from_gsk (in_outline);
|
||||||
|
RoundedRect inside = rounded_rect_shrink (outside, border_widths);
|
||||||
|
|
||||||
|
pos = border_get_position (outside, border_widths);
|
||||||
|
|
||||||
|
_pos = pos;
|
||||||
|
_color = compute_color ();
|
||||||
|
_outside = outside;
|
||||||
|
_inside = inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GSK_FRAGMENT_SHADER
|
||||||
|
|
||||||
|
void
|
||||||
|
run (out vec4 color,
|
||||||
|
out vec2 position)
|
||||||
|
{
|
||||||
|
float alpha = clamp (rounded_rect_coverage (_outside, _pos) -
|
||||||
|
rounded_rect_coverage (_inside, _pos),
|
||||||
|
0.0, 1.0);
|
||||||
|
|
||||||
|
position = _pos;
|
||||||
|
color = _color * alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -12,8 +12,9 @@ gsk_private_gpu_include_shaders = files([
|
|||||||
])
|
])
|
||||||
|
|
||||||
gsk_private_gpu_shaders = files([
|
gsk_private_gpu_shaders = files([
|
||||||
'gskgpuuber.glsl',
|
'gskgpuborder.glsl',
|
||||||
'gskgputexture.glsl',
|
'gskgputexture.glsl',
|
||||||
|
'gskgpuuber.glsl',
|
||||||
])
|
])
|
||||||
|
|
||||||
gsk_private_gpu_shader_headers = []
|
gsk_private_gpu_shader_headers = []
|
||||||
|
@ -72,6 +72,7 @@ gsk_private_sources = files([
|
|||||||
'gpu/gskglframe.c',
|
'gpu/gskglframe.c',
|
||||||
'gpu/gskglimage.c',
|
'gpu/gskglimage.c',
|
||||||
'gpu/gskgpublitop.c',
|
'gpu/gskgpublitop.c',
|
||||||
|
'gpu/gskgpuborderop.c',
|
||||||
'gpu/gskgpubuffer.c',
|
'gpu/gskgpubuffer.c',
|
||||||
'gpu/gskgpubufferwriter.c',
|
'gpu/gskgpubufferwriter.c',
|
||||||
'gpu/gskgpuclip.c',
|
'gpu/gskgpuclip.c',
|
||||||
|
Loading…
Reference in New Issue
Block a user