gpu: Add a blend mode shader

I'm a bit unsure about using the zero rect in the fallback situtation
where one image doesn't exist, but it seems to work.

This removes the last pattern-only rendernode and with that the last
fallback usage with disabled ubershader.
This commit is contained in:
Benjamin Otte
2023-12-31 07:16:09 +01:00
parent d11886e7ac
commit 6e4a526ddf
8 changed files with 255 additions and 21 deletions

View File

@@ -0,0 +1,85 @@
#include "config.h"
#include "gskgpublendmodeopprivate.h"
#include "gskenumtypes.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskrectprivate.h"
#include "gpu/shaders/gskgpublendmodeinstance.h"
typedef struct _GskGpuBlendModeOp GskGpuBlendModeOp;
struct _GskGpuBlendModeOp
{
GskGpuShaderOp op;
};
static void
gsk_gpu_blend_mode_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBlendmodeInstance *instance;
instance = (GskGpuBlendmodeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "blend-mode");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->bottom_id);
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->top_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
{
GSK_GPU_OP_SIZE (GskGpuBlendModeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_blend_mode_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
gsk_gpu_shader_op_gl_command
},
"gskgpublendmode",
sizeof (GskGpuBlendmodeInstance),
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_blendmode_info,
#endif
gsk_gpu_blendmode_setup_vao
};
void
gsk_gpu_blend_mode_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const graphene_point_t *offset,
float opacity,
GskBlendMode blend_mode,
guint32 bottom_descriptor,
const graphene_rect_t *bottom_rect,
guint32 top_descriptor,
const graphene_rect_t *top_rect)
{
GskGpuBlendmodeInstance *instance;
gsk_gpu_shader_op_alloc (frame,
&GSK_GPU_BLEND_MODE_OP_CLASS,
blend_mode,
clip,
desc,
&instance);
gsk_gpu_rect_to_float (rect, offset, instance->rect);
instance->opacity = opacity;
gsk_gpu_rect_to_float (bottom_rect, offset, instance->bottom_rect);
instance->bottom_id = bottom_descriptor;
gsk_gpu_rect_to_float (top_rect, offset, instance->top_rect);
instance->top_id = top_descriptor;
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include "gskgpushaderopprivate.h"
#include <graphene.h>
G_BEGIN_DECLS
void gsk_gpu_blend_mode_op (GskGpuFrame *frame,
GskGpuShaderClip clip,
GskGpuDescriptors *desc,
const graphene_rect_t *rect,
const graphene_point_t *offset,
float opacity,
GskBlendMode blend_mode,
guint32 start_descriptor,
const graphene_rect_t *start_rect,
guint32 end_descriptor,
const graphene_rect_t *end_rect);
G_END_DECLS

View File

@@ -4,6 +4,7 @@
#include "gskgpuborderopprivate.h"
#include "gskgpuboxshadowopprivate.h"
#include "gskgpublendmodeopprivate.h"
#include "gskgpublendopprivate.h"
#include "gskgpublitopprivate.h"
#include "gskgpubluropprivate.h"
@@ -1218,26 +1219,6 @@ gsk_gpu_node_processor_try_node_as_pattern (GskGpuNodeProcessor *self,
return TRUE;
}
static void
gsk_gpu_node_processor_add_node_as_pattern (GskGpuNodeProcessor *self,
GskRenderNode *node)
{
if (!gsk_gpu_node_processor_try_node_as_pattern (self, node))
{
if (!gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_UBER))
{
GSK_DEBUG (FALLBACK, "Using fallback for node %s because pattern shaders are disabled.",
g_type_name_from_instance ((GTypeInstance *) node));
}
else
{
GSK_DEBUG (FALLBACK, "Using fallback because pattern shader for node %s failed",
g_type_name_from_instance ((GTypeInstance *) node));
}
gsk_gpu_node_processor_add_fallback_node (self, node);
}
}
static void
gsk_gpu_node_processor_add_without_opacity (GskGpuNodeProcessor *self,
GskRenderNode *node)
@@ -2530,6 +2511,72 @@ gsk_gpu_node_processor_add_shadow_node (GskGpuNodeProcessor *self,
g_object_unref (image);
}
static void
gsk_gpu_node_processor_add_blend_node (GskGpuNodeProcessor *self,
GskRenderNode *node)
{
GskRenderNode *bottom_child, *top_child;
graphene_rect_t bottom_rect, top_rect;
GskGpuImage *bottom_image, *top_image;
guint32 descriptors[2];
bottom_child = gsk_blend_node_get_bottom_child (node);
top_child = gsk_blend_node_get_top_child (node);
if ((gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, bottom_child) ||
gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, top_child)) &&
gsk_gpu_node_processor_try_node_as_pattern (self, node))
return;
bottom_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
NULL,
bottom_child,
&bottom_rect);
top_image = gsk_gpu_node_processor_get_node_as_image (self,
0,
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
NULL,
top_child,
&top_rect);
if (bottom_image == NULL)
{
if (top_image == NULL)
return;
bottom_image = g_object_ref (top_image);
bottom_rect = *graphene_rect_zero ();
}
else if (top_image == NULL)
{
top_image = g_object_ref (bottom_image);
top_rect = *graphene_rect_zero ();
}
gsk_gpu_node_processor_add_images (self,
2,
(GskGpuImage *[2]) { bottom_image, top_image },
(GskGpuSampler[2]) { GSK_GPU_SAMPLER_DEFAULT, GSK_GPU_SAMPLER_DEFAULT },
descriptors);
gsk_gpu_blend_mode_op (self->frame,
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
self->desc,
&node->bounds,
&self->offset,
self->opacity,
gsk_blend_node_get_blend_mode (node),
descriptors[0],
&bottom_rect,
descriptors[1],
&top_rect);
g_object_unref (top_image);
g_object_unref (bottom_image);
}
static gboolean
gsk_gpu_node_processor_create_blend_pattern (GskGpuPatternWriter *self,
GskRenderNode *node)
@@ -3730,7 +3777,7 @@ static const struct
[GSK_BLEND_NODE] = {
0,
GSK_GPU_HANDLE_OPACITY,
gsk_gpu_node_processor_add_node_as_pattern,
gsk_gpu_node_processor_add_blend_node,
gsk_gpu_node_processor_create_blend_pattern,
},
[GSK_CROSS_FADE_NODE] = {

View File

@@ -30,6 +30,18 @@ gsk_gpu_print_string (GString *string,
g_string_append_c (string, ' ');
}
void
gsk_gpu_print_enum (GString *string,
GType type,
int value)
{
GEnumClass *class;
class = g_type_class_ref (type);
gsk_gpu_print_string (string, g_enum_get_value (class, value)->value_nick);
g_type_class_unref (class);
}
void
gsk_gpu_print_rect (GString *string,
const float rect[4])

View File

@@ -17,6 +17,9 @@ void gsk_gpu_print_newline (GString
void gsk_gpu_print_string (GString *string,
const char *s);
void gsk_gpu_print_enum (GString *string,
GType type,
int value);
void gsk_gpu_print_rect (GString *string,
const float rect[4]);
void gsk_gpu_print_int_rect (GString *string,

View File

@@ -0,0 +1,62 @@
#include "common.glsl"
#include "blendmode.glsl"
PASS(0) vec2 _pos;
PASS_FLAT(1) Rect _bottom_rect;
PASS_FLAT(2) Rect _top_rect;
PASS(3) vec2 _bottom_coord;
PASS(4) vec2 _top_coord;
PASS_FLAT(5) uint _bottom_id;
PASS_FLAT(6) uint _top_id;
PASS_FLAT(7) float _opacity;
#ifdef GSK_VERTEX_SHADER
IN(0) vec4 in_rect;
IN(1) vec4 in_bottom_rect;
IN(2) uint in_bottom_id;
IN(3) vec4 in_top_rect;
IN(4) uint in_top_id;
IN(5) float in_opacity;
void
run (out vec2 pos)
{
Rect r = rect_from_gsk (in_rect);
pos = rect_get_position (r);
_pos = pos;
_opacity = in_opacity;
Rect bottom_rect = rect_from_gsk (in_bottom_rect);
_bottom_rect = bottom_rect;
_bottom_coord = rect_get_coord (bottom_rect, pos);
_bottom_id = in_bottom_id;
Rect top_rect = rect_from_gsk (in_top_rect);
_top_rect = top_rect;
_top_coord = rect_get_coord (top_rect, pos);
_top_id = in_top_id;
}
#endif
#ifdef GSK_FRAGMENT_SHADER
void
run (out vec4 color,
out vec2 position)
{
color = _opacity * blend_mode (gsk_texture (_bottom_id, _bottom_coord)
* rect_coverage (_bottom_rect, _pos),
gsk_texture (_top_id, _top_coord)
* rect_coverage (_top_rect, _pos),
GSK_VARIATION);
position = _pos;
}
#endif

View File

@@ -13,6 +13,7 @@ gsk_private_gpu_include_shaders = files([
])
gsk_private_gpu_shaders = files([
'gskgpublendmode.glsl',
'gskgpublur.glsl',
'gskgpuborder.glsl',
'gskgpuboxshadow.glsl',

View File

@@ -73,6 +73,7 @@ gsk_private_sources = files([
'gpu/gskglframe.c',
'gpu/gskglimage.c',
'gpu/gskgpublendop.c',
'gpu/gskgpublendmodeop.c',
'gpu/gskgpublitop.c',
'gpu/gskgpublurop.c',
'gpu/gskgpuborderop.c',