diff --git a/gsk/gpu/gskgpucolormatrixop.c b/gsk/gpu/gskgpucolormatrixop.c new file mode 100644 index 0000000000..db67d43d57 --- /dev/null +++ b/gsk/gpu/gskgpucolormatrixop.c @@ -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 ()); +} diff --git a/gsk/gpu/gskgpucolormatrixopprivate.h b/gsk/gpu/gskgpucolormatrixopprivate.h new file mode 100644 index 0000000000..50d40bd775 --- /dev/null +++ b/gsk/gpu/gskgpucolormatrixopprivate.h @@ -0,0 +1,29 @@ +#pragma once + +#include "gskgpushaderopprivate.h" + +#include + +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 + diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index bd56db5b11..5a174b69e0 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -9,6 +9,7 @@ #include "gskgpuclearopprivate.h" #include "gskgpuclipprivate.h" #include "gskgpucolorizeopprivate.h" +#include "gskgpucolormatrixopprivate.h" #include "gskgpucoloropprivate.h" #include "gskgpudescriptorsprivate.h" #include "gskgpudeviceprivate.h" @@ -918,8 +919,36 @@ static void gsk_gpu_node_processor_add_without_opacity (GskGpuNodeProcessor *self, GskRenderNode *node) { + GskGpuImage *image; + guint32 descriptor; + graphene_rect_t tex_rect; + 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 @@ -2176,6 +2205,56 @@ gsk_gpu_node_processor_create_opacity_pattern (GskGpuPatternWriter *self, 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 gsk_gpu_node_processor_create_color_matrix_pattern (GskGpuPatternWriter *self, GskRenderNode *node) @@ -2414,7 +2493,7 @@ static const struct [GSK_COLOR_MATRIX_NODE] = { 0, 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_REPEAT_NODE] = { diff --git a/gsk/gpu/shaders/gskgpucolormatrix.glsl b/gsk/gpu/shaders/gskgpucolormatrix.glsl new file mode 100644 index 0000000000..0b9d428103 --- /dev/null +++ b/gsk/gpu/shaders/gskgpucolormatrix.glsl @@ -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 + diff --git a/gsk/gpu/shaders/meson.build b/gsk/gpu/shaders/meson.build index 492817609c..559b8e7d40 100644 --- a/gsk/gpu/shaders/meson.build +++ b/gsk/gpu/shaders/meson.build @@ -17,6 +17,7 @@ gsk_private_gpu_shaders = files([ 'gskgpuboxshadow.glsl', 'gskgpucolor.glsl', 'gskgpucolorize.glsl', + 'gskgpucolormatrix.glsl', 'gskgpuroundedcolor.glsl', 'gskgpustraightalpha.glsl', 'gskgputexture.glsl', diff --git a/gsk/meson.build b/gsk/meson.build index 81a7413fe6..590d7c0ee4 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -81,6 +81,7 @@ gsk_private_sources = files([ 'gpu/gskgpuclearop.c', 'gpu/gskgpuclip.c', 'gpu/gskgpucolorizeop.c', + 'gpu/gskgpucolormatrixop.c', 'gpu/gskgpucolorop.c', 'gpu/gskgpudescriptors.c', 'gpu/gskgpudownloadop.c',