mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 20:00:09 +00:00
vulkan: Repurpose mask shader
Use if for mask nodes to do the generic source image + mask image operation with the 4 available mask modes.
This commit is contained in:
parent
a621bd066b
commit
73f1dfc762
@ -121,6 +121,7 @@ if have_vulkan
|
||||
'vulkan/gskvulkanimage.c',
|
||||
'vulkan/gskvulkaninsetshadowop.c',
|
||||
'vulkan/gskvulkanlineargradientop.c',
|
||||
'vulkan/gskvulkanmaskop.c',
|
||||
'vulkan/gskvulkanmemory.c',
|
||||
'vulkan/gskvulkanoffscreenop.c',
|
||||
'vulkan/gskvulkanop.c',
|
||||
|
140
gsk/vulkan/gskvulkanmaskop.c
Normal file
140
gsk/vulkan/gskvulkanmaskop.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskvulkanmaskopprivate.h"
|
||||
|
||||
#include "gskvulkanprivate.h"
|
||||
|
||||
#include "vulkan/resources/mask.vert.h"
|
||||
|
||||
typedef struct _GskVulkanMaskOp GskVulkanMaskOp;
|
||||
|
||||
struct _GskVulkanMaskOp
|
||||
{
|
||||
GskVulkanOp op;
|
||||
|
||||
struct {
|
||||
GskVulkanImage *image;
|
||||
graphene_rect_t rect;
|
||||
graphene_rect_t tex_rect;
|
||||
guint32 image_descriptor;
|
||||
} source, mask;
|
||||
GskMaskMode mask_mode;
|
||||
|
||||
gsize vertex_offset;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_vulkan_mask_op_finish (GskVulkanOp *op)
|
||||
{
|
||||
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
|
||||
|
||||
g_object_unref (self->source.image);
|
||||
g_object_unref (self->mask.image);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_mask_op_upload (GskVulkanOp *op,
|
||||
GskVulkanRenderPass *pass,
|
||||
GskVulkanRender *render,
|
||||
GskVulkanUploader *uploader)
|
||||
{
|
||||
}
|
||||
|
||||
static inline gsize
|
||||
round_up (gsize number, gsize divisor)
|
||||
{
|
||||
return (number + divisor - 1) / divisor * divisor;
|
||||
}
|
||||
|
||||
static gsize
|
||||
gsk_vulkan_mask_op_count_vertex_data (GskVulkanOp *op,
|
||||
gsize n_bytes)
|
||||
{
|
||||
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
|
||||
gsize vertex_stride;
|
||||
|
||||
vertex_stride = gsk_vulkan_mask_info.pVertexBindingDescriptions[0].stride;
|
||||
n_bytes = round_up (n_bytes, vertex_stride);
|
||||
self->vertex_offset = n_bytes;
|
||||
n_bytes += vertex_stride;
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_mask_op_collect_vertex_data (GskVulkanOp *op,
|
||||
GskVulkanRenderPass *pass,
|
||||
GskVulkanRender *render,
|
||||
guchar *data)
|
||||
{
|
||||
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
|
||||
GskVulkanMaskInstance *instance = (GskVulkanMaskInstance *) (data + self->vertex_offset);
|
||||
|
||||
gsk_vulkan_rect_to_float (&self->source.rect, instance->source_rect);
|
||||
gsk_vulkan_rect_to_float (&self->source.tex_rect, instance->source_tex_rect);
|
||||
instance->source_id = self->source.image_descriptor;
|
||||
gsk_vulkan_rect_to_float (&self->mask.rect, instance->mask_rect);
|
||||
gsk_vulkan_rect_to_float (&self->mask.tex_rect, instance->mask_tex_rect);
|
||||
instance->mask_id = self->mask.image_descriptor;
|
||||
instance->mask_mode = self->mask_mode;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_mask_op_reserve_descriptor_sets (GskVulkanOp *op,
|
||||
GskVulkanRender *render)
|
||||
{
|
||||
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
|
||||
|
||||
self->source.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, self->source.image, GSK_VULKAN_SAMPLER_DEFAULT);
|
||||
self->mask.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, self->mask.image, GSK_VULKAN_SAMPLER_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_mask_op_command (GskVulkanOp *op,
|
||||
GskVulkanRender *render,
|
||||
VkPipelineLayout pipeline_layout,
|
||||
VkCommandBuffer command_buffer)
|
||||
{
|
||||
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
|
||||
|
||||
vkCmdDraw (command_buffer,
|
||||
6, 1,
|
||||
0, self->vertex_offset / gsk_vulkan_mask_info.pVertexBindingDescriptions[0].stride);
|
||||
}
|
||||
|
||||
static const GskVulkanOpClass GSK_VULKAN_COLOR_MASK_OP_CLASS = {
|
||||
GSK_VULKAN_OP_SIZE (GskVulkanMaskOp),
|
||||
"mask",
|
||||
&gsk_vulkan_mask_info,
|
||||
gsk_vulkan_mask_op_finish,
|
||||
gsk_vulkan_mask_op_upload,
|
||||
gsk_vulkan_mask_op_count_vertex_data,
|
||||
gsk_vulkan_mask_op_collect_vertex_data,
|
||||
gsk_vulkan_mask_op_reserve_descriptor_sets,
|
||||
gsk_vulkan_mask_op_command
|
||||
};
|
||||
|
||||
void
|
||||
gsk_vulkan_mask_op (GskVulkanRenderPass *render_pass,
|
||||
const char *clip_type,
|
||||
const graphene_point_t *offset,
|
||||
GskVulkanImage *source,
|
||||
const graphene_rect_t *source_rect,
|
||||
const graphene_rect_t *source_tex_rect,
|
||||
GskVulkanImage *mask,
|
||||
const graphene_rect_t *mask_rect,
|
||||
const graphene_rect_t *mask_tex_rect,
|
||||
GskMaskMode mask_mode)
|
||||
{
|
||||
GskVulkanMaskOp *self;
|
||||
|
||||
self = (GskVulkanMaskOp *) gsk_vulkan_op_alloc (render_pass, &GSK_VULKAN_COLOR_MASK_OP_CLASS);
|
||||
|
||||
((GskVulkanOp *) self)->clip_type = g_intern_string (clip_type);
|
||||
self->source.image = g_object_ref (source);
|
||||
graphene_rect_offset_r (source_rect, offset->x, offset->y, &self->source.rect);
|
||||
gsk_vulkan_normalize_tex_coords (&self->source.tex_rect, source_rect, source_tex_rect);
|
||||
self->mask.image = g_object_ref (mask);
|
||||
graphene_rect_offset_r (mask_rect, offset->x, offset->y, &self->mask.rect);
|
||||
gsk_vulkan_normalize_tex_coords (&self->mask.tex_rect, mask_rect, mask_tex_rect);
|
||||
self->mask_mode = mask_mode;
|
||||
}
|
20
gsk/vulkan/gskvulkanmaskopprivate.h
Normal file
20
gsk/vulkan/gskvulkanmaskopprivate.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskvulkanopprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_vulkan_mask_op (GskVulkanRenderPass *render_pass,
|
||||
const char *clip_type,
|
||||
const graphene_point_t *offset,
|
||||
GskVulkanImage *source,
|
||||
const graphene_rect_t *source_rect,
|
||||
const graphene_rect_t *source_tex_rect,
|
||||
GskVulkanImage *mask,
|
||||
const graphene_rect_t *mask_rect,
|
||||
const graphene_rect_t *mask_tex_rect,
|
||||
GskMaskMode mask_mode);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "gskvulkanglyphopprivate.h"
|
||||
#include "gskvulkaninsetshadowopprivate.h"
|
||||
#include "gskvulkanlineargradientopprivate.h"
|
||||
#include "gskvulkanmaskopprivate.h"
|
||||
#include "gskvulkanopprivate.h"
|
||||
#include "gskvulkanprivate.h"
|
||||
#include "gskvulkanrendererprivate.h"
|
||||
@ -1212,8 +1213,8 @@ gsk_vulkan_render_pass_add_mask_node (GskVulkanRenderPass *self,
|
||||
const GskVulkanParseState *state,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskVulkanImage *mask_image;
|
||||
graphene_rect_t mask_tex_rect;
|
||||
GskVulkanImage *source_image, *mask_image;
|
||||
graphene_rect_t source_tex_rect, mask_tex_rect;
|
||||
GskRenderNode *source, *mask;
|
||||
GskMaskMode mode;
|
||||
|
||||
@ -1249,7 +1250,25 @@ gsk_vulkan_render_pass_add_mask_node (GskVulkanRenderPass *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
source_image = gsk_vulkan_render_pass_get_node_as_image (self,
|
||||
render,
|
||||
state,
|
||||
source,
|
||||
&source_tex_rect);
|
||||
if (source_image == NULL)
|
||||
return TRUE;
|
||||
|
||||
gsk_vulkan_mask_op (self,
|
||||
gsk_vulkan_clip_get_clip_type (&state->clip, &state->offset, &node->bounds),
|
||||
&state->offset,
|
||||
source_image,
|
||||
&source->bounds,
|
||||
&source_tex_rect,
|
||||
mask_image,
|
||||
&mask->bounds,
|
||||
&mask_tex_rect,
|
||||
mode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
|
@ -13,7 +13,7 @@ with open(sys.argv[1]) as f:
|
||||
matches = []
|
||||
|
||||
for line in lines:
|
||||
match = re.search(r"^layout\(location = ([0-9]+)\) in ([a-z0-9]+) ([a-zA-Z0-9]+);$", line)
|
||||
match = re.search(r"^layout\(location = ([0-9]+)\) in ([a-z0-9]+) ([a-zA-Z0-9_]+);$", line)
|
||||
if not match:
|
||||
if re.search(r"layout.*\sin\s.*", line):
|
||||
raise Exception("Failed to parse file")
|
||||
|
@ -2,15 +2,41 @@
|
||||
|
||||
#include "common.frag.glsl"
|
||||
#include "clip.frag.glsl"
|
||||
#include "rect.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec2 inTexCoord;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
layout(location = 3) flat in uint inTexId;
|
||||
layout(location = 0) in vec2 in_pos;
|
||||
layout(location = 1) in flat Rect in_source_rect;
|
||||
layout(location = 2) in vec2 in_source_coord;
|
||||
layout(location = 3) in flat uint in_source_id;
|
||||
layout(location = 4) in flat Rect in_mask_rect;
|
||||
layout(location = 5) in vec2 in_mask_coord;
|
||||
layout(location = 6) in flat uint in_mask_id;
|
||||
layout(location = 7) in flat uint in_mask_mode;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
float
|
||||
luminance (vec3 color)
|
||||
{
|
||||
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * texture(get_sampler (inTexId), inTexCoord).a);
|
||||
vec4 source = texture(get_sampler (in_source_id), in_source_coord);
|
||||
source *= rect_coverage (in_source_rect, in_pos);
|
||||
vec4 mask = texture(get_sampler (in_mask_id), in_mask_coord);
|
||||
mask *= rect_coverage (in_mask_rect, in_pos);
|
||||
|
||||
float alpha;
|
||||
if (in_mask_mode == 0)
|
||||
alpha = mask.a;
|
||||
else if (in_mask_mode == 1)
|
||||
alpha = 1.0 - mask.a;
|
||||
else if (in_mask_mode == 2)
|
||||
alpha = luminance (mask.rgb);
|
||||
else if (in_mask_mode == 3)
|
||||
alpha = mask.a - luminance (mask.rgb);
|
||||
|
||||
color = clip_scaled (in_pos, source * alpha);
|
||||
}
|
||||
|
@ -1,36 +1,43 @@
|
||||
#version 450
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#include "common.vert.glsl"
|
||||
#include "rect.vert.glsl"
|
||||
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inTexRect;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
layout(location = 3) in uint inTexId;
|
||||
layout(location = 0) in vec4 in_source_rect;
|
||||
layout(location = 1) in vec4 in_source_tex_rect;
|
||||
layout(location = 2) in uint in_source_id;
|
||||
layout(location = 3) in vec4 in_mask_rect;
|
||||
layout(location = 4) in vec4 in_mask_tex_rect;
|
||||
layout(location = 5) in uint in_mask_id;
|
||||
layout(location = 6) in uint in_mask_mode;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out vec2 outTexCoord;
|
||||
layout(location = 2) out flat vec4 outColor;
|
||||
layout(location = 3) out flat uint outTexId;
|
||||
layout(location = 0) out vec2 out_pos;
|
||||
layout(location = 1) out flat Rect out_source_rect;
|
||||
layout(location = 2) out vec2 out_source_coord;
|
||||
layout(location = 3) out flat uint out_source_id;
|
||||
layout(location = 4) out flat Rect out_mask_rect;
|
||||
layout(location = 5) out vec2 out_mask_coord;
|
||||
layout(location = 6) out flat uint out_mask_id;
|
||||
layout(location = 7) out flat uint out_mask_mode;
|
||||
|
||||
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(1.0, 1.0) };
|
||||
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
Rect sr = rect_from_gsk (in_source_rect);
|
||||
Rect mr = rect_from_gsk (in_mask_rect);
|
||||
Rect r;
|
||||
if (in_mask_mode == 1)
|
||||
r = rect_union (sr, mr);
|
||||
else
|
||||
r = rect_intersect (sr, mr);
|
||||
|
||||
outPos = pos;
|
||||
vec2 pos = set_position_from_rect (r);
|
||||
|
||||
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
|
||||
rect.zw / inRect.zw);
|
||||
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
|
||||
inTexRect.zw * texrect.zw);
|
||||
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
|
||||
outTexId = inTexId;
|
||||
outColor = inColor;
|
||||
out_pos = pos;
|
||||
out_source_rect = sr;
|
||||
out_source_coord = scale_tex_coord (pos, sr, in_source_tex_rect);
|
||||
out_source_id = in_source_id;
|
||||
out_mask_rect = mr;
|
||||
out_mask_coord = scale_tex_coord (pos, mr, in_mask_tex_rect);
|
||||
out_mask_id = in_mask_id;
|
||||
out_mask_mode = in_mask_mode;
|
||||
}
|
||||
|
@ -55,4 +55,10 @@ rect_intersect (Rect a, Rect b)
|
||||
return Rect(result);
|
||||
}
|
||||
|
||||
Rect
|
||||
rect_union (Rect a, Rect b)
|
||||
{
|
||||
return Rect (vec4 (min (a.bounds.xy, b.bounds.xy), max (a.bounds.zw, b.bounds.zw)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user