diff --git a/gsk/gpu/gskgpucrossfadeop.c b/gsk/gpu/gskgpucrossfadeop.c new file mode 100644 index 0000000000..bc6ec00952 --- /dev/null +++ b/gsk/gpu/gskgpucrossfadeop.c @@ -0,0 +1,84 @@ +#include "config.h" + +#include "gskgpucrossfadeopprivate.h" + +#include "gskgpuframeprivate.h" +#include "gskgpuprintprivate.h" +#include "gskrectprivate.h" + +#include "gpu/shaders/gskgpucrossfadeinstance.h" + +typedef struct _GskGpuCrossFadeOp GskGpuCrossFadeOp; + +struct _GskGpuCrossFadeOp +{ + GskGpuShaderOp op; +}; + +static void +gsk_gpu_cross_fade_op_print (GskGpuOp *op, + GskGpuFrame *frame, + GString *string, + guint indent) +{ + GskGpuShaderOp *shader = (GskGpuShaderOp *) op; + GskGpuCrossfadeInstance *instance; + + instance = (GskGpuCrossfadeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset); + + gsk_gpu_print_op (string, indent, "cross-fade"); + gsk_gpu_print_rect (string, instance->rect); + gsk_gpu_print_image_descriptor (string, shader->desc, instance->start_id); + gsk_gpu_print_image_descriptor (string, shader->desc, instance->end_id); + g_string_append_printf (string, "%g%%", 100 * instance->opacity_progress[1]); + gsk_gpu_print_newline (string); +} + +static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = { + { + GSK_GPU_OP_SIZE (GskGpuCrossFadeOp), + GSK_GPU_STAGE_SHADER, + gsk_gpu_shader_op_finish, + gsk_gpu_cross_fade_op_print, +#ifdef GDK_RENDERING_VULKAN + gsk_gpu_shader_op_vk_command, +#endif + gsk_gpu_shader_op_gl_command + }, + "gskgpucrossfade", + sizeof (GskGpuCrossfadeInstance), +#ifdef GDK_RENDERING_VULKAN + &gsk_gpu_crossfade_info, +#endif + gsk_gpu_crossfade_setup_vao +}; + +void +gsk_gpu_cross_fade_op (GskGpuFrame *frame, + GskGpuShaderClip clip, + GskGpuDescriptors *desc, + const graphene_rect_t *rect, + const graphene_point_t *offset, + float opacity, + float progress, + guint32 start_descriptor, + const graphene_rect_t *start_rect, + guint32 end_descriptor, + const graphene_rect_t *end_rect) +{ + GskGpuCrossfadeInstance *instance; + + gsk_gpu_shader_op_alloc (frame, + &GSK_GPU_CROSS_FADE_OP_CLASS, + clip, + desc, + &instance); + + gsk_gpu_rect_to_float (rect, offset, instance->rect); + instance->opacity_progress[0] = opacity; + instance->opacity_progress[1] = progress; + gsk_gpu_rect_to_float (start_rect, offset, instance->start_rect); + instance->start_id = start_descriptor; + gsk_gpu_rect_to_float (end_rect, offset, instance->end_rect); + instance->end_id = end_descriptor; +} diff --git a/gsk/gpu/gskgpucrossfadeopprivate.h b/gsk/gpu/gskgpucrossfadeopprivate.h new file mode 100644 index 0000000000..d39ce1dfcf --- /dev/null +++ b/gsk/gpu/gskgpucrossfadeopprivate.h @@ -0,0 +1,23 @@ +#pragma once + +#include "gskgpushaderopprivate.h" + +#include + +G_BEGIN_DECLS + +void gsk_gpu_cross_fade_op (GskGpuFrame *frame, + GskGpuShaderClip clip, + GskGpuDescriptors *desc, + const graphene_rect_t *rect, + const graphene_point_t *offset, + float opacity, + float progress, + guint32 start_descriptor, + const graphene_rect_t *start_rect, + guint32 end_descriptor, + const graphene_rect_t *end_rect); + + +G_END_DECLS + diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index 1439d2f39c..f7a85420ad 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -13,6 +13,7 @@ #include "gskgpucolormatrixopprivate.h" #include "gskgpucoloropprivate.h" #include "gskgpuconicgradientopprivate.h" +#include "gskgpucrossfadeopprivate.h" #include "gskgpudescriptorsprivate.h" #include "gskgpudeviceprivate.h" #include "gskgpuframeprivate.h" @@ -2556,6 +2557,88 @@ gsk_gpu_node_processor_create_blend_pattern (GskGpuPatternWriter *self, return TRUE; } +static void +gsk_gpu_node_processor_add_cross_fade_node (GskGpuNodeProcessor *self, + GskRenderNode *node) +{ + GskRenderNode *start_child, *end_child; + graphene_rect_t start_rect, end_rect; + GskGpuImage *start_image, *end_image; + guint32 descriptors[2]; + float progress, old_opacity; + + start_child = gsk_cross_fade_node_get_start_child (node); + end_child = gsk_cross_fade_node_get_end_child (node); + progress = gsk_cross_fade_node_get_progress (node); + + if ((gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, start_child) || + gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, end_child)) && + gsk_gpu_node_processor_try_node_as_pattern (self, node)) + return; + + start_image = gsk_gpu_node_processor_get_node_as_image (self, + 0, + GSK_GPU_IMAGE_STRAIGHT_ALPHA, + NULL, + start_child, + &start_rect); + end_image = gsk_gpu_node_processor_get_node_as_image (self, + 0, + GSK_GPU_IMAGE_STRAIGHT_ALPHA, + NULL, + end_child, + &end_rect); + + if (start_image == NULL) + { + if (end_image == NULL) + return; + + old_opacity = self->opacity; + self->opacity *= progress; + gsk_gpu_node_processor_image_op (self, + end_image, + &end_child->bounds, + &end_rect); + g_object_unref (end_image); + self->opacity = old_opacity; + return; + } + else if (end_image == NULL) + { + old_opacity = self->opacity; + self->opacity *= (1 - progress); + gsk_gpu_node_processor_image_op (self, + start_image, + &start_child->bounds, + &start_rect); + g_object_unref (start_image); + self->opacity = old_opacity; + return; + } + + gsk_gpu_node_processor_add_images (self, + 2, + (GskGpuImage *[2]) { start_image, end_image }, + (GskGpuSampler[2]) { GSK_GPU_SAMPLER_DEFAULT, GSK_GPU_SAMPLER_DEFAULT }, + descriptors); + + gsk_gpu_cross_fade_op (self->frame, + gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds), + self->desc, + &node->bounds, + &self->offset, + self->opacity, + progress, + descriptors[0], + &start_rect, + descriptors[1], + &end_rect); + + g_object_unref (end_image); + g_object_unref (start_image); +} + static gboolean gsk_gpu_node_processor_create_cross_fade_pattern (GskGpuPatternWriter *self, GskRenderNode *node) @@ -3640,7 +3723,7 @@ static const struct [GSK_CROSS_FADE_NODE] = { 0, GSK_GPU_HANDLE_OPACITY, - gsk_gpu_node_processor_add_node_as_pattern, + gsk_gpu_node_processor_add_cross_fade_node, gsk_gpu_node_processor_create_cross_fade_pattern, }, [GSK_TEXT_NODE] = { diff --git a/gsk/gpu/shaders/gskgpucrossfade.glsl b/gsk/gpu/shaders/gskgpucrossfade.glsl new file mode 100644 index 0000000000..043adc170b --- /dev/null +++ b/gsk/gpu/shaders/gskgpucrossfade.glsl @@ -0,0 +1,64 @@ +#include "common.glsl" + +PASS(0) vec2 _pos; +PASS_FLAT(1) Rect _start_rect; +PASS_FLAT(2) Rect _end_rect; +PASS(3) vec2 _start_coord; +PASS(4) vec2 _end_coord; +PASS_FLAT(5) uint _start_id; +PASS_FLAT(6) uint _end_id; +PASS_FLAT(7) float _start_opacity; +PASS_FLAT(8) float _end_opacity; + + +#ifdef GSK_VERTEX_SHADER + +IN(0) vec4 in_rect; +IN(1) vec4 in_start_rect; +IN(2) uint in_start_id; +IN(3) vec4 in_end_rect; +IN(4) uint in_end_id; +IN(5) vec2 in_opacity_progress; + +void +run (out vec2 pos) +{ + Rect r = rect_from_gsk (in_rect); + + pos = rect_get_position (r); + + _pos = pos; + + Rect start_rect = rect_from_gsk (in_start_rect); + _start_rect = start_rect; + _start_coord = rect_get_coord (start_rect, pos); + _start_id = in_start_id; + _start_opacity = in_opacity_progress[0] * (1.0 - in_opacity_progress[1]); + + Rect end_rect = rect_from_gsk (in_end_rect); + _end_rect = end_rect; + _end_coord = rect_get_coord (end_rect, pos); + _end_id = in_end_id; + _end_opacity = in_opacity_progress[0] * in_opacity_progress[1]; +} + +#endif + + + +#ifdef GSK_FRAGMENT_SHADER + +void +run (out vec4 color, + out vec2 position) +{ + color = gsk_texture (_start_id, _start_coord) * + rect_coverage (_start_rect, _pos) * + _start_opacity + + gsk_texture (_end_id, _end_coord) * + rect_coverage (_end_rect, _pos) * + _end_opacity; + position = _pos; +} + +#endif diff --git a/gsk/gpu/shaders/meson.build b/gsk/gpu/shaders/meson.build index b094d61857..847804cba1 100644 --- a/gsk/gpu/shaders/meson.build +++ b/gsk/gpu/shaders/meson.build @@ -20,6 +20,7 @@ gsk_private_gpu_shaders = files([ 'gskgpucolorize.glsl', 'gskgpucolormatrix.glsl', 'gskgpuconicgradient.glsl', + 'gskgpucrossfade.glsl', 'gskgpulineargradient.glsl', 'gskgpumask.glsl', 'gskgpuradialgradient.glsl', diff --git a/gsk/meson.build b/gsk/meson.build index 00ec1cb8ce..914e0fd712 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -84,6 +84,7 @@ gsk_private_sources = files([ 'gpu/gskgpucolormatrixop.c', 'gpu/gskgpucolorop.c', 'gpu/gskgpuconicgradientop.c', + 'gpu/gskgpucrossfadeop.c', 'gpu/gskgpudescriptors.c', 'gpu/gskgpudownloadop.c', 'gpu/gskgpudevice.c',