gpu: Add colorize shader

... and use it for glyphs.

The name is a slight variation of the "coloring" name from the GL
renderer.
The functionality is exactly what the "glyph" shader from the Vulkan
renderer does.
This commit is contained in:
Benjamin Otte 2023-09-16 19:29:30 +02:00
parent d1d1af1a62
commit 5ab8fde0bc
6 changed files with 238 additions and 1 deletions

102
gsk/gpu/gskgpucolorizeop.c Normal file
View File

@ -0,0 +1,102 @@
#include "config.h"
#include "gskgpucolorizeopprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskrectprivate.h"
#include "gpu/shaders/gskgpucolorizeinstance.h"
typedef struct _GskGpuColorizeOp GskGpuColorizeOp;
struct _GskGpuColorizeOp
{
GskGpuShaderOp op;
GskGpuShaderImage image;
};
static void
gsk_gpu_colorize_op_finish (GskGpuOp *op)
{
GskGpuColorizeOp *self = (GskGpuColorizeOp *) op;
g_object_unref (self->image.image);
}
static void
gsk_gpu_colorize_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuColorizeOp *self = (GskGpuColorizeOp *) op;
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColorizeInstance *instance;
instance = (GskGpuColorizeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "colorize");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image (string, self->image.image);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderImage *
gsk_gpu_colorize_op_get_images (GskGpuShaderOp *op,
gsize *n_images)
{
GskGpuColorizeOp *self = (GskGpuColorizeOp *) op;
*n_images = 1;
return &self->image;
}
static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
{
GSK_GPU_OP_SIZE (GskGpuColorizeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_colorize_op_finish,
gsk_gpu_colorize_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
gsk_gpu_shader_op_gl_command
},
"gskgpucolorize",
sizeof (GskGpuColorizeInstance),
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_colorize_info,
#endif
gsk_gpu_colorize_op_get_images,
gsk_gpu_colorize_setup_vao
};
void
gsk_gpu_colorize_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color)
{
GskGpuColorizeInstance *instance;
GskGpuColorizeOp *self;
self = (GskGpuColorizeOp *) gsk_gpu_shader_op_alloc (frame,
&GSK_GPU_COLORIZE_OP_CLASS,
clip,
&instance);
gsk_gpu_rect_to_float (rect, offset, instance->rect);
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
self->image.image = g_object_ref (image);
self->image.sampler = GSK_GPU_SAMPLER_DEFAULT;
self->image.descriptor = gsk_gpu_frame_get_image_descriptor (frame, image, GSK_GPU_SAMPLER_DEFAULT);
instance->tex_id = self->image.descriptor;
gsk_gpu_rgba_to_float (color, instance->color);
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "gskgpushaderopprivate.h"
#include <graphene.h>
G_BEGIN_DECLS
void gsk_gpu_colorize_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color);
G_END_DECLS

View File

@ -4,6 +4,7 @@
#include "gskgpuborderopprivate.h"
#include "gskgpuclipprivate.h"
#include "gskgpucolorizeopprivate.h"
#include "gskgpudeviceprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuglobalsopprivate.h"
@ -985,6 +986,72 @@ gsk_gpu_node_processor_create_conic_gradient_pattern (GskGpuPatternWriter *self,
return TRUE;
}
static void
gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
GskRenderNode *node)
{
GskGpuDevice *device;
const PangoGlyphInfo *glyphs;
PangoFont *font;
graphene_point_t offset;
guint i, num_glyphs;
float scale, inv_scale;
device = gsk_gpu_frame_get_device (self->frame);
num_glyphs = gsk_text_node_get_num_glyphs (node);
glyphs = gsk_text_node_get_glyphs (node, NULL);
font = gsk_text_node_get_font (node);
offset = *gsk_text_node_get_offset (node);
offset.x += self->offset.x;
offset.y += self->offset.y;
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
font,
glyphs[i].glyph,
0,
scale,
&glyph_bounds,
&glyph_offset);
graphene_rect_scale (&glyph_bounds, inv_scale, inv_scale, &glyph_bounds);
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_tex_rect = GRAPHENE_RECT_INIT (
0, 0,
gsk_gpu_image_get_width (image) * inv_scale,
gsk_gpu_image_get_height (image) * inv_scale
);
if (gsk_text_node_has_color_glyphs (node))
gsk_gpu_texture_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
image,
GSK_GPU_SAMPLER_DEFAULT,
&glyph_bounds,
&glyph_offset,
&glyph_tex_rect);
else
gsk_gpu_colorize_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
image,
&glyph_bounds,
&glyph_offset,
&glyph_tex_rect,
gsk_text_node_get_color (node));
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
}
}
static gboolean
gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
GskRenderNode *node)
@ -1247,7 +1314,7 @@ static const struct
},
[GSK_TEXT_NODE] = {
0,
NULL,
gsk_gpu_node_processor_add_glyph_node,
gsk_gpu_node_processor_create_glyph_pattern,
},
[GSK_BLUR_NODE] = {

View File

@ -0,0 +1,47 @@
#include "common.glsl"
PASS(0) vec2 _pos;
PASS_FLAT(1) Rect _rect;
PASS_FLAT(2) vec4 _color;
PASS(3) vec2 _tex_coord;
PASS_FLAT(4) uint _tex_id;
#ifdef GSK_VERTEX_SHADER
IN(0) vec4 in_rect;
IN(1) vec4 in_color;
IN(2) vec4 in_tex_rect;
IN(3) uint in_tex_id;
void
run (out vec2 pos)
{
Rect r = rect_from_gsk (in_rect);
pos = rect_get_position (r);
_pos = pos;
_rect = r;
_color = color_premultiply (in_color);
_tex_coord = rect_get_coord (rect_from_gsk (in_tex_rect), pos);
_tex_id = in_tex_id;
}
#endif
#ifdef GSK_FRAGMENT_SHADER
void
run (out vec4 color,
out vec2 position)
{
float alpha = texture (gsk_get_texture (_tex_id), _tex_coord).a * rect_coverage (_rect, _pos);
color = _color * alpha;
position = _pos;
}
#endif

View File

@ -13,6 +13,7 @@ gsk_private_gpu_include_shaders = files([
gsk_private_gpu_shaders = files([
'gskgpuborder.glsl',
'gskgpucolorize.glsl',
'gskgputexture.glsl',
'gskgpuuber.glsl',
])

View File

@ -76,6 +76,7 @@ gsk_private_sources = files([
'gpu/gskgpubuffer.c',
'gpu/gskgpubufferwriter.c',
'gpu/gskgpuclip.c',
'gpu/gskgpucolorizeop.c',
'gpu/gskgpudownloadop.c',
'gpu/gskgpudevice.c',
'gpu/gskgpuframe.c',