diff --git a/gsk/gskvulkaneffectpipeline.c b/gsk/gskvulkaneffectpipeline.c index 249185c1cf..8572da56dc 100644 --- a/gsk/gskvulkaneffectpipeline.c +++ b/gsk/gskvulkaneffectpipeline.c @@ -13,7 +13,8 @@ struct _GskVulkanEffectInstance { float rect[4]; float tex_rect[4]; - float value; + float color_matrix[16]; + float color_offset[4]; }; G_DEFINE_TYPE (GskVulkanEffectPipeline, gsk_vulkan_effect_pipeline, GSK_TYPE_VULKAN_PIPELINE) @@ -45,7 +46,31 @@ gsk_vulkan_effect_pipeline_get_input_state_create_info (GskVulkanPipeline *self) .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, value), + .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_matrix), + }, + { + .location = 3, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_matrix) + sizeof (float) * 4, + }, + { + .location = 4, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_matrix) + sizeof (float) * 8, + }, + { + .location = 5, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_matrix) + sizeof (float) * 12, + }, + { + .location = 6, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_offset), } }; static const VkPipelineVertexInputStateCreateInfo info = { @@ -100,7 +125,8 @@ void gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline, guchar *data, const graphene_rect_t *rect, - float value) + const graphene_matrix_t *color_matrix, + const graphene_vec4_t *color_offset) { GskVulkanEffectInstance *instance = (GskVulkanEffectInstance *) data; @@ -112,7 +138,8 @@ gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipelin instance->tex_rect[1] = 0.0; instance->tex_rect[2] = 1.0; instance->tex_rect[3] = 1.0; - instance->value = value; + graphene_matrix_to_float (color_matrix, instance->color_matrix); + graphene_vec4_to_float (color_offset, instance->color_offset); } gsize diff --git a/gsk/gskvulkaneffectpipelineprivate.h b/gsk/gskvulkaneffectpipelineprivate.h index 9a82c0242e..d2bff8105c 100644 --- a/gsk/gskvulkaneffectpipelineprivate.h +++ b/gsk/gskvulkaneffectpipelineprivate.h @@ -21,7 +21,8 @@ gsize gsk_vulkan_effect_pipeline_count_vertex_data (GskVulk void gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline, guchar *data, const graphene_rect_t *rect, - float value); + const graphene_matrix_t *color_matrix, + const graphene_vec4_t *color_offset); gsize gsk_vulkan_effect_pipeline_draw (GskVulkanEffectPipeline *pipeline, VkCommandBuffer command_buffer, gsize offset, diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index 81bc3193b5..35e2dce295 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -321,9 +321,9 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, { "linear", gsk_vulkan_linear_gradient_pipeline_new }, { "linear-clip", gsk_vulkan_linear_gradient_pipeline_new }, { "linear-clip-rounded", gsk_vulkan_linear_gradient_pipeline_new }, - { "opacity", gsk_vulkan_effect_pipeline_new }, - { "opacity-clip", gsk_vulkan_effect_pipeline_new }, - { "opacity-clip-rounded", gsk_vulkan_effect_pipeline_new } + { "color-matrix", gsk_vulkan_effect_pipeline_new }, + { "color-matrix-clip", gsk_vulkan_effect_pipeline_new }, + { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new } }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 70f1de35c5..b005607423 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -171,11 +171,11 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_OPACITY_NODE: if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) - pipeline_type = GSK_VULKAN_PIPELINE_OPACITY; + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX; else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) - pipeline_type = GSK_VULKAN_PIPELINE_OPACITY_CLIP; + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP; else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) - pipeline_type = GSK_VULKAN_PIPELINE_OPACITY_CLIP_ROUNDED; + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED; else FALLBACK ("Opacity nodes can't deal with clip type %u\n", constants->clip.type); op.type = GSK_VULKAN_OP_OPACITY; @@ -554,11 +554,22 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, case GSK_VULKAN_OP_OPACITY: { + graphene_matrix_t color_matrix; + graphene_vec4_t color_offset; + graphene_matrix_init_from_float (&color_matrix, + (float[16]) { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, gsk_opacity_node_get_opacity (op->render.node) + }); + graphene_vec4_init (&color_offset, 0.0, 0.0, 0.0, 0.0); op->render.vertex_offset = offset + n_bytes; gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline), data + n_bytes + offset, &op->render.node->bounds, - gsk_opacity_node_get_opacity (op->render.node)); + &color_matrix, + &color_offset); n_bytes += op->render.vertex_count; } break; diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index 6de38d2747..cffce7f0c5 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -17,9 +17,9 @@ typedef enum { GSK_VULKAN_PIPELINE_LINEAR_GRADIENT, GSK_VULKAN_PIPELINE_LINEAR_GRADIENT_CLIP, GSK_VULKAN_PIPELINE_LINEAR_GRADIENT_CLIP_ROUNDED, - GSK_VULKAN_PIPELINE_OPACITY, - GSK_VULKAN_PIPELINE_OPACITY_CLIP, - GSK_VULKAN_PIPELINE_OPACITY_CLIP_ROUNDED, + GSK_VULKAN_PIPELINE_COLOR_MATRIX, + GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP, + GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType; diff --git a/gsk/resources/vulkan/opacity-clip-rounded.frag.glsl b/gsk/resources/vulkan/color-matrix-clip-rounded.frag.glsl similarity index 75% rename from gsk/resources/vulkan/opacity-clip-rounded.frag.glsl rename to gsk/resources/vulkan/color-matrix-clip-rounded.frag.glsl index 91c1e54437..c0e42cac6d 100644 --- a/gsk/resources/vulkan/opacity-clip-rounded.frag.glsl +++ b/gsk/resources/vulkan/color-matrix-clip-rounded.frag.glsl @@ -7,9 +7,10 @@ struct RoundedRect { layout(location = 0) in vec2 inPos; layout(location = 1) in vec2 inTexCoord; -layout(location = 2) in flat float inOpacity; -layout(location = 3) in flat vec4 inClipBounds; -layout(location = 4) in flat vec4 inClipWidths; +layout(location = 2) in flat vec4 inClipBounds; +layout(location = 3) in flat vec4 inClipWidths; +layout(location = 4) in flat mat4 inColorMatrix; +layout(location = 8) in flat vec4 inColorOffset; layout(set = 0, binding = 0) uniform sampler2D inTexture; @@ -51,14 +52,25 @@ float clip(vec2 pos, RoundedRect r) { } vec4 -opacity (vec4 color, float value) +color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset) { - return color * value; + /* unpremultiply */ + if (color.a != 0.0) + color.rgb /= color.a; + + color = color_matrix * color + color_offset; + color = clamp(color, 0.0, 1.0); + + /* premultiply */ + if (color.a != 0.0) + color.rgb *= color.a; + + return color; } void main() { RoundedRect r = RoundedRect(vec4(inClipBounds.xy, inClipBounds.xy + inClipBounds.zw), inClipWidths); - color = opacity (texture (inTexture, inTexCoord), inOpacity) * clip (inPos, r); + color = color_matrix (texture (inTexture, inTexCoord), inColorMatrix, inColorOffset) * clip (inPos, r); } diff --git a/gsk/resources/vulkan/color-matrix-clip-rounded.frag.spv b/gsk/resources/vulkan/color-matrix-clip-rounded.frag.spv new file mode 100644 index 0000000000..f4c753aae6 Binary files /dev/null and b/gsk/resources/vulkan/color-matrix-clip-rounded.frag.spv differ diff --git a/gsk/resources/vulkan/opacity-clip-rounded.vert.glsl b/gsk/resources/vulkan/color-matrix-clip-rounded.vert.glsl similarity index 79% rename from gsk/resources/vulkan/opacity-clip-rounded.vert.glsl rename to gsk/resources/vulkan/color-matrix-clip-rounded.vert.glsl index 5f0b898ef2..2875e637f7 100644 --- a/gsk/resources/vulkan/opacity-clip-rounded.vert.glsl +++ b/gsk/resources/vulkan/color-matrix-clip-rounded.vert.glsl @@ -2,7 +2,8 @@ layout(location = 0) in vec4 inRect; layout(location = 1) in vec4 inTexRect; -layout(location = 2) in float inOpacity; +layout(location = 2) in mat4 inColorMatrix; +layout(location = 6) in vec4 inColorOffset; layout(push_constant) uniform PushConstants { mat4 mvp; @@ -13,9 +14,10 @@ layout(push_constant) uniform PushConstants { layout(location = 0) out vec2 outPos; layout(location = 1) out vec2 outTexCoord; -layout(location = 2) out flat float outOpacity; -layout(location = 3) out flat vec4 outClipBounds; -layout(location = 4) out flat vec4 outClipWidths; +layout(location = 2) out flat vec4 outClipBounds; +layout(location = 3) out flat vec4 outClipWidths; +layout(location = 4) out flat mat4 outColorMatrix; +layout(location = 8) out flat vec4 outColorOffset; out gl_PerVertex { vec4 gl_Position; @@ -52,5 +54,6 @@ void main() { texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy, inTexRect.zw * texrect.zw); outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex]; - outOpacity = inOpacity; + outColorMatrix = inColorMatrix; + outColorOffset = inColorOffset; } diff --git a/gsk/resources/vulkan/color-matrix-clip-rounded.vert.spv b/gsk/resources/vulkan/color-matrix-clip-rounded.vert.spv new file mode 100644 index 0000000000..49271e4572 Binary files /dev/null and b/gsk/resources/vulkan/color-matrix-clip-rounded.vert.spv differ diff --git a/gsk/resources/vulkan/color-matrix-clip.frag.glsl b/gsk/resources/vulkan/color-matrix-clip.frag.glsl new file mode 100644 index 0000000000..21a324e780 --- /dev/null +++ b/gsk/resources/vulkan/color-matrix-clip.frag.glsl @@ -0,0 +1,31 @@ +#version 420 core + +layout(location = 0) in vec2 inTexCoord; +layout(location = 1) in flat mat4 inColorMatrix; +layout(location = 5) in flat vec4 inColorOffset; + +layout(set = 0, binding = 0) uniform sampler2D inTexture; + +layout(location = 0) out vec4 color; + +vec4 +color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset) +{ + /* unpremultiply */ + if (color.a != 0.0) + color.rgb /= color.a; + + color = color_matrix * color + color_offset; + color = clamp(color, 0.0, 1.0); + + /* premultiply */ + if (color.a != 0.0) + color.rgb *= color.a; + + return color; +} + +void main() +{ + color = color_matrix (texture (inTexture, inTexCoord), inColorMatrix, inColorOffset); +} diff --git a/gsk/resources/vulkan/color-matrix-clip.frag.spv b/gsk/resources/vulkan/color-matrix-clip.frag.spv new file mode 100644 index 0000000000..266c8777f5 Binary files /dev/null and b/gsk/resources/vulkan/color-matrix-clip.frag.spv differ diff --git a/gsk/resources/vulkan/opacity-clip.vert.glsl b/gsk/resources/vulkan/color-matrix-clip.vert.glsl similarity index 83% rename from gsk/resources/vulkan/opacity-clip.vert.glsl rename to gsk/resources/vulkan/color-matrix-clip.vert.glsl index 4cf0f13b64..94d4ef8f90 100644 --- a/gsk/resources/vulkan/opacity-clip.vert.glsl +++ b/gsk/resources/vulkan/color-matrix-clip.vert.glsl @@ -2,7 +2,8 @@ layout(location = 0) in vec4 inRect; layout(location = 1) in vec4 inTexRect; -layout(location = 2) in float inOpacity; +layout(location = 2) in mat4 inColorMatrix; +layout(location = 6) in vec4 inColorOffset; layout(push_constant) uniform PushConstants { mat4 mvp; @@ -12,7 +13,8 @@ layout(push_constant) uniform PushConstants { } push; layout(location = 0) out vec2 outTexCoord; -layout(location = 1) out flat float outOpacity; +layout(location = 1) out flat mat4 outColorMatrix; +layout(location = 5) out flat vec4 outColorOffset; out gl_PerVertex { vec4 gl_Position; @@ -45,5 +47,6 @@ void main() { texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy, inTexRect.zw * texrect.zw); outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex]; - outOpacity = inOpacity; + outColorMatrix = inColorMatrix; + outColorOffset = inColorOffset; } diff --git a/gsk/resources/vulkan/color-matrix-clip.vert.spv b/gsk/resources/vulkan/color-matrix-clip.vert.spv new file mode 100644 index 0000000000..6648e245ba Binary files /dev/null and b/gsk/resources/vulkan/color-matrix-clip.vert.spv differ diff --git a/gsk/resources/vulkan/color-matrix.frag.glsl b/gsk/resources/vulkan/color-matrix.frag.glsl new file mode 100644 index 0000000000..21a324e780 --- /dev/null +++ b/gsk/resources/vulkan/color-matrix.frag.glsl @@ -0,0 +1,31 @@ +#version 420 core + +layout(location = 0) in vec2 inTexCoord; +layout(location = 1) in flat mat4 inColorMatrix; +layout(location = 5) in flat vec4 inColorOffset; + +layout(set = 0, binding = 0) uniform sampler2D inTexture; + +layout(location = 0) out vec4 color; + +vec4 +color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset) +{ + /* unpremultiply */ + if (color.a != 0.0) + color.rgb /= color.a; + + color = color_matrix * color + color_offset; + color = clamp(color, 0.0, 1.0); + + /* premultiply */ + if (color.a != 0.0) + color.rgb *= color.a; + + return color; +} + +void main() +{ + color = color_matrix (texture (inTexture, inTexCoord), inColorMatrix, inColorOffset); +} diff --git a/gsk/resources/vulkan/color-matrix.frag.spv b/gsk/resources/vulkan/color-matrix.frag.spv new file mode 100644 index 0000000000..266c8777f5 Binary files /dev/null and b/gsk/resources/vulkan/color-matrix.frag.spv differ diff --git a/gsk/resources/vulkan/opacity.vert.glsl b/gsk/resources/vulkan/color-matrix.vert.glsl similarity index 74% rename from gsk/resources/vulkan/opacity.vert.glsl rename to gsk/resources/vulkan/color-matrix.vert.glsl index 7e12d41e1a..20b3bbd8d0 100644 --- a/gsk/resources/vulkan/opacity.vert.glsl +++ b/gsk/resources/vulkan/color-matrix.vert.glsl @@ -2,7 +2,8 @@ layout(location = 0) in vec4 inRect; layout(location = 1) in vec4 inTexRect; -layout(location = 2) in float inOpacity; +layout(location = 2) in mat4 inColorMatrix; +layout(location = 6) in vec4 inColorOffset; layout(push_constant) uniform PushConstants { mat4 mvp; @@ -12,7 +13,8 @@ layout(push_constant) uniform PushConstants { } push; layout(location = 0) out vec2 outTexCoord; -layout(location = 1) out flat float outOpacity; +layout(location = 1) out flat mat4 outColorMatrix; +layout(location = 5) out flat vec4 outColorOffset; out gl_PerVertex { vec4 gl_Position; @@ -30,5 +32,6 @@ void main() { gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); outTexCoord = inTexRect.xy + inTexRect.zw * offsets[gl_VertexIndex]; - outOpacity = inOpacity; + outColorMatrix = inColorMatrix; + outColorOffset = inColorOffset; } diff --git a/gsk/resources/vulkan/color-matrix.vert.spv b/gsk/resources/vulkan/color-matrix.vert.spv new file mode 100644 index 0000000000..2985b7409d Binary files /dev/null and b/gsk/resources/vulkan/color-matrix.vert.spv differ diff --git a/gsk/resources/vulkan/opacity-clip-rounded.frag.spv b/gsk/resources/vulkan/opacity-clip-rounded.frag.spv deleted file mode 100644 index 42fa156184..0000000000 Binary files a/gsk/resources/vulkan/opacity-clip-rounded.frag.spv and /dev/null differ diff --git a/gsk/resources/vulkan/opacity-clip-rounded.vert.spv b/gsk/resources/vulkan/opacity-clip-rounded.vert.spv deleted file mode 100644 index 1090dabe9e..0000000000 Binary files a/gsk/resources/vulkan/opacity-clip-rounded.vert.spv and /dev/null differ diff --git a/gsk/resources/vulkan/opacity-clip.frag.glsl b/gsk/resources/vulkan/opacity-clip.frag.glsl deleted file mode 100644 index 7ff7d347c7..0000000000 --- a/gsk/resources/vulkan/opacity-clip.frag.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#version 420 core - -layout(location = 0) in vec2 inTexCoord; -layout(location = 1) in flat float inOpacity; - -layout(set = 0, binding = 0) uniform sampler2D inTexture; - -layout(location = 0) out vec4 color; - -vec4 -opacity (vec4 color, float value) -{ - return color * value; -} - -void main() -{ - color = opacity (texture (inTexture, inTexCoord), inOpacity); -} diff --git a/gsk/resources/vulkan/opacity-clip.frag.spv b/gsk/resources/vulkan/opacity-clip.frag.spv deleted file mode 100644 index 5729abe98c..0000000000 Binary files a/gsk/resources/vulkan/opacity-clip.frag.spv and /dev/null differ diff --git a/gsk/resources/vulkan/opacity-clip.vert.spv b/gsk/resources/vulkan/opacity-clip.vert.spv deleted file mode 100644 index 81aa4f6f85..0000000000 Binary files a/gsk/resources/vulkan/opacity-clip.vert.spv and /dev/null differ diff --git a/gsk/resources/vulkan/opacity.frag.glsl b/gsk/resources/vulkan/opacity.frag.glsl deleted file mode 100644 index 7ff7d347c7..0000000000 --- a/gsk/resources/vulkan/opacity.frag.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#version 420 core - -layout(location = 0) in vec2 inTexCoord; -layout(location = 1) in flat float inOpacity; - -layout(set = 0, binding = 0) uniform sampler2D inTexture; - -layout(location = 0) out vec4 color; - -vec4 -opacity (vec4 color, float value) -{ - return color * value; -} - -void main() -{ - color = opacity (texture (inTexture, inTexCoord), inOpacity); -} diff --git a/gsk/resources/vulkan/opacity.frag.spv b/gsk/resources/vulkan/opacity.frag.spv deleted file mode 100644 index 5729abe98c..0000000000 Binary files a/gsk/resources/vulkan/opacity.frag.spv and /dev/null differ diff --git a/gsk/resources/vulkan/opacity.vert.spv b/gsk/resources/vulkan/opacity.vert.spv deleted file mode 100644 index d0c9b86128..0000000000 Binary files a/gsk/resources/vulkan/opacity.vert.spv and /dev/null differ