From b1b34cd6653d51f3bf8e331e6ae7b39290ae820e Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Sun, 7 Apr 2024 02:00:14 -0400 Subject: [PATCH] vulkan: perform sRGB-to-linear conversion correctly for premultiplied values Pre-multipled sRGB values need to be un-multiplied before conversion to linear and then re-multiplied after. Compare shaders/texture.frag. This fixes an issue in labwc where titlebar corners (rendered as ARGB textures) did not match the rest of the titlebar (rendered as a solid wlr_scene_rect). Note: 0.17 has other instances in render/vulkan/renderer.c that need the same fix. --- render/vulkan/pass.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index e981a3e1..53534663 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -48,6 +48,10 @@ static float color_to_linear(float non_linear) { non_linear / 12.92; } +static float color_to_linear_premult(float non_linear, float alpha) { + return (alpha == 0) ? 0 : color_to_linear(non_linear / alpha) * alpha; +} + static void mat3_to_mat4(const float mat3[9], float mat4[4][4]) { memset(mat4, 0, sizeof(float) * 16); mat4[0][0] = mat3[0]; @@ -443,9 +447,9 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, // colors in linear space as well (and vulkan then automatically // does the conversion for out sRGB render targets). float linear_color[] = { - color_to_linear(options->color.r), - color_to_linear(options->color.g), - color_to_linear(options->color.b), + color_to_linear_premult(options->color.r, options->color.a), + color_to_linear_premult(options->color.g, options->color.a), + color_to_linear_premult(options->color.b, options->color.a), options->color.a, // no conversion for alpha };