diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index 42bd6b4e1..6aa45baa7 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]; @@ -439,9 +443,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 }; diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index d07c7c41d..7059c4972 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -67,6 +67,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]; @@ -1475,9 +1479,9 @@ static void vulkan_clear(struct wlr_renderer *wlr_renderer, // But in other parts of wlroots we just always assume // srgb so that's why we have to convert here. .clearValue.color.float32 = { - color_to_linear(color[0]), - color_to_linear(color[1]), - color_to_linear(color[2]), + color_to_linear_premult(color[0], color[3]), + color_to_linear_premult(color[1], color[3]), + color_to_linear_premult(color[2], color[3]), color[3], // no conversion for alpha }, }; @@ -1553,9 +1557,9 @@ static void vulkan_render_quad_with_matrix(struct wlr_renderer *wlr_renderer, // But in other parts of wlroots we just always assume // srgb so that's why we have to convert here. float linear_color[4]; - linear_color[0] = color_to_linear(color[0]); - linear_color[1] = color_to_linear(color[1]); - linear_color[2] = color_to_linear(color[2]); + linear_color[0] = color_to_linear_premult(color[0], color[3]); + linear_color[1] = color_to_linear_premult(color[1], color[3]); + linear_color[2] = color_to_linear_premult(color[2], color[3]); linear_color[3] = color[3]; // no conversion for alpha vkCmdPushConstants(cb, pipe->layout->vk,