mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 21:40:22 +00:00
gpu: Add a mask shader
This shader can take over from the ubershader. And it can be used instead of launching the ubershader when no offscreens are necessary. Also includes an optimization that uses the colorize shader when appropriate.
This commit is contained in:
parent
cb5c994cd9
commit
bd901896ee
83
gsk/gpu/gskgpumaskop.c
Normal file
83
gsk/gpu/gskgpumaskop.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpumaskopprivate.h"
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpumaskinstance.h"
|
||||
|
||||
typedef struct _GskGpuMaskOp GskGpuMaskOp;
|
||||
|
||||
struct _GskGpuMaskOp
|
||||
{
|
||||
GskGpuShaderOp op;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_mask_op_print (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
|
||||
GskGpuMaskInstance *instance;
|
||||
|
||||
instance = (GskGpuMaskInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "mask");
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->source_id);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->mask_id);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
|
||||
{
|
||||
GSK_GPU_OP_SIZE (GskGpuMaskOp),
|
||||
GSK_GPU_STAGE_SHADER,
|
||||
gsk_gpu_shader_op_finish,
|
||||
gsk_gpu_mask_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_shader_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_shader_op_gl_command
|
||||
},
|
||||
"gskgpumask",
|
||||
sizeof (GskGpuMaskInstance),
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
&gsk_gpu_mask_info,
|
||||
#endif
|
||||
gsk_gpu_mask_setup_vao
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_mask_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GskGpuDescriptors *desc,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
float opacity,
|
||||
GskMaskMode mask_mode,
|
||||
guint32 source_descriptor,
|
||||
const graphene_rect_t *source_rect,
|
||||
guint32 mask_descriptor,
|
||||
const graphene_rect_t *mask_rect)
|
||||
{
|
||||
GskGpuMaskInstance *instance;
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_MASK_OP_CLASS,
|
||||
clip,
|
||||
desc,
|
||||
&instance);
|
||||
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (source_rect, offset, instance->source_rect);
|
||||
instance->source_id = source_descriptor;
|
||||
gsk_gpu_rect_to_float (mask_rect, offset, instance->mask_rect);
|
||||
instance->mask_id = mask_descriptor;
|
||||
instance->mask_mode = mask_mode;
|
||||
instance->opacity = opacity;
|
||||
}
|
23
gsk/gpu/gskgpumaskopprivate.h
Normal file
23
gsk/gpu/gskgpumaskopprivate.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_mask_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GskGpuDescriptors *desc,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
float opacity,
|
||||
GskMaskMode mask_mode,
|
||||
guint32 source_descriptor,
|
||||
const graphene_rect_t *source_rect,
|
||||
guint32 mask_descriptor,
|
||||
const graphene_rect_t *mask_rect);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuglobalsopprivate.h"
|
||||
#include "gskgpuimageprivate.h"
|
||||
#include "gskgpumaskopprivate.h"
|
||||
#include "gskgpumipmapopprivate.h"
|
||||
#include "gskgpurenderpassopprivate.h"
|
||||
#include "gskgpuroundedcoloropprivate.h"
|
||||
@ -2235,6 +2236,100 @@ gsk_gpu_node_processor_create_cross_fade_pattern (GskGpuPatternWriter *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_add_mask_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *source_child, *mask_child;
|
||||
GskGpuImage *mask_image;
|
||||
graphene_rect_t bounds, mask_rect;
|
||||
guint32 mask_descriptor;
|
||||
GskMaskMode mask_mode;
|
||||
|
||||
source_child = gsk_mask_node_get_source (node);
|
||||
mask_child = gsk_mask_node_get_mask (node);
|
||||
mask_mode = gsk_mask_node_get_mask_mode (node);
|
||||
|
||||
if ((gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, mask_child) ||
|
||||
(gsk_gpu_node_processor_ubershader_instead_of_offscreen (self, source_child) &&
|
||||
gsk_render_node_get_node_type (source_child) != GSK_COLOR_NODE)) &&
|
||||
gsk_gpu_node_processor_try_node_as_pattern (self, node))
|
||||
return;
|
||||
|
||||
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &bounds))
|
||||
return;
|
||||
|
||||
mask_image = gsk_gpu_node_processor_get_node_as_image (self,
|
||||
0,
|
||||
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
|
||||
&bounds,
|
||||
mask_child,
|
||||
&mask_rect);
|
||||
if (mask_image == NULL)
|
||||
{
|
||||
if (mask_mode == GSK_MASK_MODE_INVERTED_ALPHA)
|
||||
gsk_gpu_node_processor_add_node (self, source_child);
|
||||
return;
|
||||
}
|
||||
mask_descriptor = gsk_gpu_node_processor_add_image (self, mask_image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
|
||||
if (gsk_render_node_get_node_type (source_child) == GSK_COLOR_NODE &&
|
||||
mask_mode == GSK_MASK_MODE_ALPHA)
|
||||
{
|
||||
const GdkRGBA *rgba = gsk_color_node_get_color (source_child);
|
||||
gsk_gpu_colorize_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
self->desc,
|
||||
mask_descriptor,
|
||||
&node->bounds,
|
||||
&self->offset,
|
||||
&mask_rect,
|
||||
&GDK_RGBA_INIT_ALPHA (rgba, self->opacity));
|
||||
}
|
||||
else
|
||||
{
|
||||
GskGpuDescriptors *desc = self->desc;
|
||||
GskGpuImage *source_image;
|
||||
graphene_rect_t source_rect;
|
||||
guint32 source_descriptor;
|
||||
|
||||
source_image = gsk_gpu_node_processor_get_node_as_image (self,
|
||||
0,
|
||||
GSK_GPU_IMAGE_STRAIGHT_ALPHA,
|
||||
&bounds,
|
||||
source_child,
|
||||
&source_rect);
|
||||
if (source_image == NULL)
|
||||
{
|
||||
g_object_unref (mask_image);
|
||||
return;
|
||||
}
|
||||
source_descriptor = gsk_gpu_node_processor_add_image (self, source_image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
if (desc != self->desc)
|
||||
{
|
||||
desc = self->desc;
|
||||
mask_descriptor = gsk_gpu_node_processor_add_image (self, mask_image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
g_assert (desc == self->desc);
|
||||
}
|
||||
|
||||
gsk_gpu_mask_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
desc,
|
||||
&node->bounds,
|
||||
&self->offset,
|
||||
self->opacity,
|
||||
mask_mode,
|
||||
source_descriptor,
|
||||
&source_rect,
|
||||
mask_descriptor,
|
||||
&mask_rect);
|
||||
|
||||
g_object_unref (source_image);
|
||||
}
|
||||
|
||||
g_object_unref (mask_image);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gpu_node_processor_create_mask_pattern (GskGpuPatternWriter *self,
|
||||
GskRenderNode *node)
|
||||
@ -3022,7 +3117,7 @@ static const struct
|
||||
[GSK_MASK_NODE] = {
|
||||
0,
|
||||
GSK_GPU_HANDLE_OPACITY,
|
||||
gsk_gpu_node_processor_add_node_as_pattern,
|
||||
gsk_gpu_node_processor_add_mask_node,
|
||||
gsk_gpu_node_processor_create_mask_pattern,
|
||||
},
|
||||
[GSK_FILL_NODE] = {
|
||||
|
@ -47,6 +47,11 @@
|
||||
#define GSK_GPU_PATTERN_BLEND_SATURATION 37u
|
||||
#define GSK_GPU_PATTERN_BLEND_LUMINOSITY 38u
|
||||
|
||||
#define GSK_MASK_MODE_ALPHA 0u
|
||||
#define GSK_MASK_MODE_INVERTED_ALPHA 1u
|
||||
#define GSK_MASK_MODE_LUMINANCE 2u
|
||||
#define GSK_MASK_MODE_INVERTED_LUMINANCE 3u
|
||||
|
||||
#define TOP 0u
|
||||
#define RIGHT 1u
|
||||
#define BOTTOM 2u
|
||||
|
86
gsk/gpu/shaders/gskgpumask.glsl
Normal file
86
gsk/gpu/shaders/gskgpumask.glsl
Normal file
@ -0,0 +1,86 @@
|
||||
#include "common.glsl"
|
||||
|
||||
PASS(0) vec2 _pos;
|
||||
PASS_FLAT(1) Rect _source_rect;
|
||||
PASS_FLAT(2) Rect _mask_rect;
|
||||
PASS(3) vec2 _source_coord;
|
||||
PASS(4) vec2 _mask_coord;
|
||||
PASS_FLAT(5) uint _source_id;
|
||||
PASS_FLAT(6) uint _mask_id;
|
||||
PASS_FLAT(7) uint _mask_mode;
|
||||
PASS_FLAT(8) float _opacity;
|
||||
|
||||
|
||||
#ifdef GSK_VERTEX_SHADER
|
||||
|
||||
IN(0) vec4 in_rect;
|
||||
IN(1) vec4 in_source_rect;
|
||||
IN(2) uint in_source_id;
|
||||
IN(3) vec4 in_mask_rect;
|
||||
IN(4) uint in_mask_id;
|
||||
IN(5) uint in_mask_mode;
|
||||
IN(6) float in_opacity;
|
||||
|
||||
void
|
||||
run (out vec2 pos)
|
||||
{
|
||||
Rect r = rect_from_gsk (in_rect);
|
||||
|
||||
pos = rect_get_position (r);
|
||||
|
||||
_pos = pos;
|
||||
Rect source_rect = rect_from_gsk (in_source_rect);
|
||||
_source_rect = source_rect;
|
||||
_source_coord = rect_get_coord (source_rect, pos);
|
||||
_source_id = in_source_id;
|
||||
Rect mask_rect = rect_from_gsk (in_mask_rect);
|
||||
_mask_rect = mask_rect;
|
||||
_mask_coord = rect_get_coord (mask_rect, pos);
|
||||
_mask_id = in_mask_id;
|
||||
_mask_mode = in_mask_mode;
|
||||
_opacity = in_opacity;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef GSK_FRAGMENT_SHADER
|
||||
|
||||
void
|
||||
run (out vec4 color,
|
||||
out vec2 position)
|
||||
{
|
||||
vec4 source = gsk_texture (_source_id, _source_coord) *
|
||||
rect_coverage (_source_rect, _pos);
|
||||
vec4 mask = gsk_texture (_mask_id, _mask_coord) *
|
||||
rect_coverage (_mask_rect, _pos);
|
||||
|
||||
float alpha = _opacity;
|
||||
switch (_mask_mode)
|
||||
{
|
||||
case GSK_MASK_MODE_ALPHA:
|
||||
alpha *= mask.a;
|
||||
break;
|
||||
|
||||
case GSK_MASK_MODE_INVERTED_ALPHA:
|
||||
alpha *= (1.0 - mask.a);
|
||||
break;
|
||||
|
||||
case GSK_MASK_MODE_LUMINANCE:
|
||||
alpha *= luminance (mask.rgb);
|
||||
break;
|
||||
|
||||
case GSK_MASK_MODE_INVERTED_LUMINANCE:
|
||||
alpha *= (mask.a - luminance (mask.rgb));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
color = source * alpha;
|
||||
position = _pos;
|
||||
}
|
||||
|
||||
#endif
|
@ -19,6 +19,7 @@ gsk_private_gpu_shaders = files([
|
||||
'gskgpucolor.glsl',
|
||||
'gskgpucolorize.glsl',
|
||||
'gskgpucolormatrix.glsl',
|
||||
'gskgpumask.glsl',
|
||||
'gskgpuroundedcolor.glsl',
|
||||
'gskgpustraightalpha.glsl',
|
||||
'gskgputexture.glsl',
|
||||
|
@ -88,6 +88,7 @@ gsk_private_sources = files([
|
||||
'gpu/gskgpuframe.c',
|
||||
'gpu/gskgpuglobalsop.c',
|
||||
'gpu/gskgpuimage.c',
|
||||
'gpu/gskgpumaskop.c',
|
||||
'gpu/gskgpumipmapop.c',
|
||||
'gpu/gskgpunodeprocessor.c',
|
||||
'gpu/gskgpuop.c',
|
||||
|
Loading…
Reference in New Issue
Block a user