diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 00cc33ea0..1ed69d6e4 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -152,6 +152,7 @@ struct wlr_vk_pipeline_layout { enum wlr_vk_texture_transform { WLR_VK_TEXTURE_TRANSFORM_IDENTITY = 0, WLR_VK_TEXTURE_TRANSFORM_SRGB = 1, + WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ = 2, }; enum wlr_vk_shader_source { diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index 68be473cf..30cd0fe54 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -781,13 +781,29 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, }; encode_proj_matrix(matrix, vert_pcr_data.mat4); - bool srgb = options->transfer_function == 0 || - options->transfer_function == WLR_COLOR_TRANSFER_FUNCTION_SRGB; - bool srgb_image_view = srgb && texture->using_mutable_srgb; - enum wlr_vk_texture_transform tex_transform = - srgb_image_view || options->transfer_function == WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR ? - WLR_VK_TEXTURE_TRANSFORM_IDENTITY : - WLR_VK_TEXTURE_TRANSFORM_SRGB; + enum wlr_color_transfer_function tf = options->transfer_function; + if (tf == 0) { + tf = WLR_COLOR_TRANSFER_FUNCTION_SRGB; + } + + bool srgb_image_view = false; + enum wlr_vk_texture_transform tex_transform = 0; + switch (tf) { + case WLR_COLOR_TRANSFER_FUNCTION_SRGB: + if (texture->using_mutable_srgb) { + tex_transform = WLR_VK_TEXTURE_TRANSFORM_IDENTITY; + srgb_image_view = true; + } else { + tex_transform = WLR_VK_TEXTURE_TRANSFORM_SRGB; + } + break; + case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR: + tex_transform = WLR_VK_TEXTURE_TRANSFORM_IDENTITY; + break; + case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ: + tex_transform = WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ; + break; + } struct wlr_vk_render_format_setup *setup = pass->srgb_pathway ? pass->render_buffer->srgb.render_setup : diff --git a/render/vulkan/shaders/texture.frag b/render/vulkan/shaders/texture.frag index dc4f60cfe..e1467023b 100644 --- a/render/vulkan/shaders/texture.frag +++ b/render/vulkan/shaders/texture.frag @@ -16,6 +16,7 @@ layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0; // Matches enum wlr_vk_texture_transform #define TEXTURE_TRANSFORM_IDENTITY 0 #define TEXTURE_TRANSFORM_SRGB 1 +#define TEXTURE_TRANSFORM_ST2084_PQ 2 float srgb_channel_to_linear(float x) { return mix(x / 12.92, @@ -31,6 +32,17 @@ vec3 srgb_color_to_linear(vec3 color) { ); } +vec3 pq_color_to_linear(vec3 color) { + float inv_m1 = 1 / 0.1593017578125; + float inv_m2 = 1 / 78.84375; + float c1 = 0.8359375; + float c2 = 18.8515625; + float c3 = 18.6875; + vec3 num = max(pow(color, vec3(inv_m2)) - c1, 0); + vec3 denom = c2 - c3 * pow(color, vec3(inv_m2)); + return pow(num / denom, vec3(inv_m1)); +} + void main() { vec4 in_color = textureLod(tex, uv, 0); @@ -45,6 +57,8 @@ void main() { if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_SRGB) { rgb = srgb_color_to_linear(rgb); + } else if (TEXTURE_TRANSFORM == TEXTURE_TRANSFORM_ST2084_PQ) { + rgb = pq_color_to_linear(rgb); } rgb = mat3(data.matrix) * rgb;