mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-14 06:10:21 +00:00
gpu: Add a color matrix shader
This allows avoiding the uber shader in 2 important cases: 1. opacity - and Adwaita uses that a lot 2. color-matrix - it's used for symbolic icons
This commit is contained in:
parent
9f65cdf3aa
commit
42d89a0ff1
109
gsk/gpu/gskgpucolormatrixop.c
Normal file
109
gsk/gpu/gskgpucolormatrixop.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gskgpucolormatrixopprivate.h"
|
||||||
|
|
||||||
|
#include "gskgpuframeprivate.h"
|
||||||
|
#include "gskgpuprintprivate.h"
|
||||||
|
#include "gskrectprivate.h"
|
||||||
|
|
||||||
|
#include "gpu/shaders/gskgpucolormatrixinstance.h"
|
||||||
|
|
||||||
|
typedef struct _GskGpuColorMatrixOp GskGpuColorMatrixOp;
|
||||||
|
|
||||||
|
struct _GskGpuColorMatrixOp
|
||||||
|
{
|
||||||
|
GskGpuShaderOp op;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_color_matrix_op_print (GskGpuOp *op,
|
||||||
|
GskGpuFrame *frame,
|
||||||
|
GString *string,
|
||||||
|
guint indent)
|
||||||
|
{
|
||||||
|
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
|
||||||
|
GskGpuColormatrixInstance *instance;
|
||||||
|
|
||||||
|
instance = (GskGpuColormatrixInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||||
|
|
||||||
|
gsk_gpu_print_op (string, indent, "color-matrix");
|
||||||
|
gsk_gpu_print_rect (string, instance->rect);
|
||||||
|
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||||
|
gsk_gpu_print_newline (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
|
||||||
|
{
|
||||||
|
GSK_GPU_OP_SIZE (GskGpuColorMatrixOp),
|
||||||
|
GSK_GPU_STAGE_SHADER,
|
||||||
|
gsk_gpu_shader_op_finish,
|
||||||
|
gsk_gpu_color_matrix_op_print,
|
||||||
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
|
gsk_gpu_shader_op_vk_command,
|
||||||
|
#endif
|
||||||
|
gsk_gpu_shader_op_gl_command
|
||||||
|
},
|
||||||
|
"gskgpucolormatrix",
|
||||||
|
sizeof (GskGpuColormatrixInstance),
|
||||||
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
|
&gsk_gpu_colormatrix_info,
|
||||||
|
#endif
|
||||||
|
gsk_gpu_colormatrix_setup_vao
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_gpu_color_matrix_op (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
GskGpuDescriptors *desc,
|
||||||
|
guint32 descriptor,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const graphene_rect_t *tex_rect,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset)
|
||||||
|
{
|
||||||
|
GskGpuColormatrixInstance *instance;
|
||||||
|
|
||||||
|
gsk_gpu_shader_op_alloc (frame,
|
||||||
|
&GSK_GPU_COLOR_MATRIX_OP_CLASS,
|
||||||
|
clip,
|
||||||
|
desc,
|
||||||
|
&instance);
|
||||||
|
|
||||||
|
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||||
|
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
|
||||||
|
instance->tex_id = descriptor;
|
||||||
|
graphene_matrix_to_float (color_matrix, instance->color_matrix);
|
||||||
|
graphene_vec4_to_float (color_offset, instance->color_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_gpu_color_matrix_op_opacity (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
GskGpuDescriptors *desc,
|
||||||
|
guint32 descriptor,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const graphene_rect_t *tex_rect,
|
||||||
|
float opacity)
|
||||||
|
{
|
||||||
|
graphene_matrix_t matrix;
|
||||||
|
|
||||||
|
graphene_matrix_init_from_float (&matrix,
|
||||||
|
(float[16]) {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, opacity
|
||||||
|
});
|
||||||
|
|
||||||
|
gsk_gpu_color_matrix_op (frame,
|
||||||
|
clip,
|
||||||
|
desc,
|
||||||
|
descriptor,
|
||||||
|
rect,
|
||||||
|
offset,
|
||||||
|
tex_rect,
|
||||||
|
&matrix,
|
||||||
|
graphene_vec4_zero ());
|
||||||
|
}
|
29
gsk/gpu/gskgpucolormatrixopprivate.h
Normal file
29
gsk/gpu/gskgpucolormatrixopprivate.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gskgpushaderopprivate.h"
|
||||||
|
|
||||||
|
#include <graphene.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gsk_gpu_color_matrix_op (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
GskGpuDescriptors *desc,
|
||||||
|
guint32 descriptor,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const graphene_rect_t *tex_rect,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset);
|
||||||
|
|
||||||
|
void gsk_gpu_color_matrix_op_opacity (GskGpuFrame *frame,
|
||||||
|
GskGpuShaderClip clip,
|
||||||
|
GskGpuDescriptors *desc,
|
||||||
|
guint32 descriptor,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
const graphene_point_t *offset,
|
||||||
|
const graphene_rect_t *tex_rect,
|
||||||
|
float opacity);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
@ -9,6 +9,7 @@
|
|||||||
#include "gskgpuclearopprivate.h"
|
#include "gskgpuclearopprivate.h"
|
||||||
#include "gskgpuclipprivate.h"
|
#include "gskgpuclipprivate.h"
|
||||||
#include "gskgpucolorizeopprivate.h"
|
#include "gskgpucolorizeopprivate.h"
|
||||||
|
#include "gskgpucolormatrixopprivate.h"
|
||||||
#include "gskgpucoloropprivate.h"
|
#include "gskgpucoloropprivate.h"
|
||||||
#include "gskgpudescriptorsprivate.h"
|
#include "gskgpudescriptorsprivate.h"
|
||||||
#include "gskgpudeviceprivate.h"
|
#include "gskgpudeviceprivate.h"
|
||||||
@ -918,8 +919,36 @@ static void
|
|||||||
gsk_gpu_node_processor_add_without_opacity (GskGpuNodeProcessor *self,
|
gsk_gpu_node_processor_add_without_opacity (GskGpuNodeProcessor *self,
|
||||||
GskRenderNode *node)
|
GskRenderNode *node)
|
||||||
{
|
{
|
||||||
|
GskGpuImage *image;
|
||||||
|
guint32 descriptor;
|
||||||
|
graphene_rect_t tex_rect;
|
||||||
|
|
||||||
gsk_gpu_node_processor_sync_globals (self, 0);
|
gsk_gpu_node_processor_sync_globals (self, 0);
|
||||||
gsk_gpu_node_processor_add_node_as_pattern (self, node);
|
|
||||||
|
if (gsk_gpu_node_processor_try_node_as_pattern (self, node))
|
||||||
|
return;
|
||||||
|
|
||||||
|
image = gsk_gpu_node_processor_get_node_as_image (self,
|
||||||
|
0,
|
||||||
|
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
|
||||||
|
NULL,
|
||||||
|
node,
|
||||||
|
&tex_rect);
|
||||||
|
if (image == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||||
|
|
||||||
|
gsk_gpu_color_matrix_op_opacity (self->frame,
|
||||||
|
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||||
|
self->desc,
|
||||||
|
descriptor,
|
||||||
|
&node->bounds,
|
||||||
|
&self->offset,
|
||||||
|
&tex_rect,
|
||||||
|
self->opacity);
|
||||||
|
|
||||||
|
g_object_unref (image);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2176,6 +2205,56 @@ gsk_gpu_node_processor_create_opacity_pattern (GskGpuPatternWriter *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_node_processor_add_color_matrix_node (GskGpuNodeProcessor *self,
|
||||||
|
GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskGpuImage *image;
|
||||||
|
guint32 descriptor;
|
||||||
|
GskRenderNode *child;
|
||||||
|
graphene_matrix_t opacity_matrix;
|
||||||
|
const graphene_matrix_t *color_matrix;
|
||||||
|
graphene_rect_t tex_rect;
|
||||||
|
|
||||||
|
child = gsk_color_matrix_node_get_child (node);
|
||||||
|
color_matrix = gsk_color_matrix_node_get_color_matrix (node);
|
||||||
|
if (self->opacity < 1.0f)
|
||||||
|
{
|
||||||
|
graphene_matrix_init_from_float (&opacity_matrix,
|
||||||
|
(float[16]) {
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, self->opacity
|
||||||
|
});
|
||||||
|
graphene_matrix_multiply (&opacity_matrix, color_matrix, &opacity_matrix);
|
||||||
|
color_matrix = &opacity_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
image = gsk_gpu_node_processor_get_node_as_image (self,
|
||||||
|
0,
|
||||||
|
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
|
||||||
|
NULL,
|
||||||
|
child,
|
||||||
|
&tex_rect);
|
||||||
|
if (image == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||||
|
|
||||||
|
gsk_gpu_color_matrix_op (self->frame,
|
||||||
|
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||||
|
self->desc,
|
||||||
|
descriptor,
|
||||||
|
&node->bounds,
|
||||||
|
&self->offset,
|
||||||
|
&tex_rect,
|
||||||
|
color_matrix,
|
||||||
|
gsk_color_matrix_node_get_color_offset (node));
|
||||||
|
|
||||||
|
g_object_unref (image);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gsk_gpu_node_processor_create_color_matrix_pattern (GskGpuPatternWriter *self,
|
gsk_gpu_node_processor_create_color_matrix_pattern (GskGpuPatternWriter *self,
|
||||||
GskRenderNode *node)
|
GskRenderNode *node)
|
||||||
@ -2414,7 +2493,7 @@ static const struct
|
|||||||
[GSK_COLOR_MATRIX_NODE] = {
|
[GSK_COLOR_MATRIX_NODE] = {
|
||||||
0,
|
0,
|
||||||
GSK_GPU_HANDLE_OPACITY,
|
GSK_GPU_HANDLE_OPACITY,
|
||||||
gsk_gpu_node_processor_add_node_as_pattern,
|
gsk_gpu_node_processor_add_color_matrix_node,
|
||||||
gsk_gpu_node_processor_create_color_matrix_pattern
|
gsk_gpu_node_processor_create_color_matrix_pattern
|
||||||
},
|
},
|
||||||
[GSK_REPEAT_NODE] = {
|
[GSK_REPEAT_NODE] = {
|
||||||
|
58
gsk/gpu/shaders/gskgpucolormatrix.glsl
Normal file
58
gsk/gpu/shaders/gskgpucolormatrix.glsl
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "common.glsl"
|
||||||
|
|
||||||
|
PASS_FLAT(0) mat4 _color_matrix;
|
||||||
|
PASS_FLAT(4) vec4 _color_offset;
|
||||||
|
PASS(5) vec2 _pos;
|
||||||
|
PASS_FLAT(6) Rect _rect;
|
||||||
|
PASS(7) vec2 _tex_coord;
|
||||||
|
PASS_FLAT(8) uint _tex_id;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GSK_VERTEX_SHADER
|
||||||
|
|
||||||
|
IN(0) mat4 in_color_matrix;
|
||||||
|
IN(4) vec4 in_color_offset;
|
||||||
|
IN(5) vec4 in_rect;
|
||||||
|
IN(6) vec4 in_tex_rect;
|
||||||
|
IN(7) 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;
|
||||||
|
_tex_coord = rect_get_coord (rect_from_gsk (in_tex_rect), pos);
|
||||||
|
_tex_id = in_tex_id;
|
||||||
|
_color_matrix = in_color_matrix;
|
||||||
|
_color_offset = in_color_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GSK_FRAGMENT_SHADER
|
||||||
|
|
||||||
|
void
|
||||||
|
run (out vec4 color,
|
||||||
|
out vec2 position)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
vec4 pixel = gsk_texture_straight_alpha (_tex_id, _tex_coord);
|
||||||
|
#else
|
||||||
|
vec4 pixel = gsk_texture (_tex_id, _tex_coord);
|
||||||
|
pixel = color_unpremultiply (pixel);
|
||||||
|
#endif
|
||||||
|
pixel = _color_matrix * pixel + _color_offset;
|
||||||
|
pixel = clamp (pixel, 0.0, 1.0);
|
||||||
|
|
||||||
|
color = color_premultiply (pixel) * rect_coverage (_rect, _pos);
|
||||||
|
position = _pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -17,6 +17,7 @@ gsk_private_gpu_shaders = files([
|
|||||||
'gskgpuboxshadow.glsl',
|
'gskgpuboxshadow.glsl',
|
||||||
'gskgpucolor.glsl',
|
'gskgpucolor.glsl',
|
||||||
'gskgpucolorize.glsl',
|
'gskgpucolorize.glsl',
|
||||||
|
'gskgpucolormatrix.glsl',
|
||||||
'gskgpuroundedcolor.glsl',
|
'gskgpuroundedcolor.glsl',
|
||||||
'gskgpustraightalpha.glsl',
|
'gskgpustraightalpha.glsl',
|
||||||
'gskgputexture.glsl',
|
'gskgputexture.glsl',
|
||||||
|
@ -81,6 +81,7 @@ gsk_private_sources = files([
|
|||||||
'gpu/gskgpuclearop.c',
|
'gpu/gskgpuclearop.c',
|
||||||
'gpu/gskgpuclip.c',
|
'gpu/gskgpuclip.c',
|
||||||
'gpu/gskgpucolorizeop.c',
|
'gpu/gskgpucolorizeop.c',
|
||||||
|
'gpu/gskgpucolormatrixop.c',
|
||||||
'gpu/gskgpucolorop.c',
|
'gpu/gskgpucolorop.c',
|
||||||
'gpu/gskgpudescriptors.c',
|
'gpu/gskgpudescriptors.c',
|
||||||
'gpu/gskgpudownloadop.c',
|
'gpu/gskgpudownloadop.c',
|
||||||
|
Loading…
Reference in New Issue
Block a user