mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-12-20 06:50:04 +01:00
render/vulkan: apply "matrix" color transforms in shader
This commit is contained in:
parent
2995f31102
commit
2cac711e55
2 changed files with 65 additions and 17 deletions
|
|
@ -553,11 +553,12 @@ struct wlr_vk_buffer_span {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Lookup table for a color transform
|
// Prepared form for a color transform
|
||||||
struct wlr_vk_color_transform {
|
struct wlr_vk_color_transform {
|
||||||
struct wlr_addon addon; // owned by: wlr_vk_renderer
|
struct wlr_addon addon; // owned by: wlr_vk_renderer
|
||||||
struct wl_list link; // wlr_vk_renderer, list of all color transforms
|
struct wl_list link; // wlr_vk_renderer, list of all color transforms
|
||||||
|
|
||||||
|
// if populated, carries the entire transform, other parameters are to be ignored
|
||||||
struct {
|
struct {
|
||||||
size_t dim;
|
size_t dim;
|
||||||
VkImage image;
|
VkImage image;
|
||||||
|
|
@ -566,6 +567,9 @@ struct wlr_vk_color_transform {
|
||||||
VkDescriptorSet ds;
|
VkDescriptorSet ds;
|
||||||
struct wlr_vk_descriptor_pool *ds_pool;
|
struct wlr_vk_descriptor_pool *ds_pool;
|
||||||
} lut_3d;
|
} lut_3d;
|
||||||
|
|
||||||
|
float color_matrix[9];
|
||||||
|
enum wlr_color_transfer_function inverse_eotf;
|
||||||
};
|
};
|
||||||
void vk_color_transform_destroy(struct wlr_addon *addon);
|
void vk_color_transform_destroy(struct wlr_addon *addon);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,46 @@ static float get_luminance_multiplier(const struct wlr_color_luminances *src_lum
|
||||||
return (dst_lum->reference / src_lum->reference) * (src_lum->max / dst_lum->max);
|
return (dst_lum->reference / src_lum->reference) * (src_lum->max / dst_lum->max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool unwrap_color_transform(struct wlr_color_transform *transform,
|
||||||
|
float matrix[static 9], enum wlr_color_transfer_function *tf) {
|
||||||
|
if (transform == NULL) {
|
||||||
|
wlr_matrix_identity(matrix);
|
||||||
|
*tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
struct wlr_color_transform_inverse_eotf *eotf;
|
||||||
|
struct wlr_color_transform_matrix *as_matrix;
|
||||||
|
struct wlr_color_transform_pipeline *pipeline;
|
||||||
|
switch (transform->type) {
|
||||||
|
case COLOR_TRANSFORM_INVERSE_EOTF:
|
||||||
|
eotf = wlr_color_transform_inverse_eotf_from_base(transform);
|
||||||
|
wlr_matrix_identity(matrix);
|
||||||
|
*tf = eotf->tf;
|
||||||
|
return true;
|
||||||
|
case COLOR_TRANSFORM_MATRIX:
|
||||||
|
as_matrix = wl_container_of(transform, as_matrix, base);
|
||||||
|
memcpy(matrix, as_matrix->matrix, sizeof(float[9]));
|
||||||
|
*tf = WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR;
|
||||||
|
return true;
|
||||||
|
case COLOR_TRANSFORM_PIPELINE:
|
||||||
|
pipeline = wl_container_of(transform, pipeline, base);
|
||||||
|
if (pipeline->len != 2
|
||||||
|
|| pipeline->transforms[0]->type != COLOR_TRANSFORM_MATRIX
|
||||||
|
|| pipeline->transforms[1]->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
as_matrix = wl_container_of(pipeline->transforms[0], as_matrix, base);
|
||||||
|
eotf = wlr_color_transform_inverse_eotf_from_base(pipeline->transforms[1]);
|
||||||
|
memcpy(matrix, as_matrix->matrix, sizeof(float[9]));
|
||||||
|
*tf = eotf->tf;
|
||||||
|
return true;
|
||||||
|
case COLOR_TRANSFORM_LCMS2:
|
||||||
|
case COLOR_TRANSFORM_LUT_3X1D:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
struct wlr_vk_renderer *renderer = pass->renderer;
|
struct wlr_vk_renderer *renderer = pass->renderer;
|
||||||
|
|
@ -190,12 +230,21 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
};
|
};
|
||||||
encode_proj_matrix(final_matrix, vert_pcr_data.mat4);
|
encode_proj_matrix(final_matrix, vert_pcr_data.mat4);
|
||||||
|
|
||||||
struct wlr_vk_color_transform *transform = NULL;
|
float matrix[9];
|
||||||
|
enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
|
||||||
|
bool need_lut = false;
|
||||||
size_t dim = 1;
|
size_t dim = 1;
|
||||||
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
struct wlr_vk_color_transform *transform = NULL;
|
||||||
|
if (pass->color_transform != NULL) {
|
||||||
transform = get_color_transform(pass->color_transform, renderer);
|
transform = get_color_transform(pass->color_transform, renderer);
|
||||||
assert(transform);
|
assert(transform);
|
||||||
dim = transform->lut_3d.dim;
|
need_lut = transform->lut_3d.dim > 0;
|
||||||
|
dim = need_lut ? transform->lut_3d.dim : 1;
|
||||||
|
memcpy(matrix, transform->color_matrix, sizeof(matrix));
|
||||||
|
tf = transform->inverse_eotf;
|
||||||
|
}
|
||||||
|
if (pass->color_transform == NULL || need_lut) {
|
||||||
|
wlr_matrix_identity(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_vk_frag_output_pcr_data frag_pcr_data = {
|
struct wlr_vk_frag_output_pcr_data frag_pcr_data = {
|
||||||
|
|
@ -204,28 +253,20 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
.lut_3d_scale = (float)(dim - 1) / dim,
|
.lut_3d_scale = (float)(dim - 1) / dim,
|
||||||
};
|
};
|
||||||
|
|
||||||
float matrix[9];
|
|
||||||
if (pass->has_primaries) {
|
if (pass->has_primaries) {
|
||||||
|
// overwrite matrix from color_tranform, if any
|
||||||
struct wlr_color_primaries srgb;
|
struct wlr_color_primaries srgb;
|
||||||
wlr_color_primaries_from_named(&srgb, WLR_COLOR_NAMED_PRIMARIES_SRGB);
|
wlr_color_primaries_from_named(&srgb, WLR_COLOR_NAMED_PRIMARIES_SRGB);
|
||||||
|
|
||||||
wlr_color_primaries_transform_absolute_colorimetric(&srgb, &pass->primaries, matrix);
|
wlr_color_primaries_transform_absolute_colorimetric(&srgb, &pass->primaries, matrix);
|
||||||
} else {
|
|
||||||
wlr_matrix_identity(matrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_color_matrix(matrix, frag_pcr_data.matrix);
|
encode_color_matrix(matrix, frag_pcr_data.matrix);
|
||||||
|
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
if (need_lut) {
|
||||||
pipeline = render_buffer->two_pass.render_setup->output_pipe_lut3d;
|
pipeline = render_buffer->two_pass.render_setup->output_pipe_lut3d;
|
||||||
} else {
|
} else {
|
||||||
enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
|
|
||||||
if (pass->color_transform && pass->color_transform->type == COLOR_TRANSFORM_INVERSE_EOTF) {
|
|
||||||
struct wlr_color_transform_inverse_eotf *inverse_eotf =
|
|
||||||
wlr_color_transform_inverse_eotf_from_base(pass->color_transform);
|
|
||||||
tf = inverse_eotf->tf;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (tf) {
|
switch (tf) {
|
||||||
case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR:
|
case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR:
|
||||||
pipeline = render_buffer->two_pass.render_setup->output_pipe_identity;
|
pipeline = render_buffer->two_pass.render_setup->output_pipe_identity;
|
||||||
|
|
@ -258,7 +299,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
sizeof(frag_pcr_data), &frag_pcr_data);
|
sizeof(frag_pcr_data), &frag_pcr_data);
|
||||||
|
|
||||||
VkDescriptorSet lut_ds;
|
VkDescriptorSet lut_ds;
|
||||||
if (transform != NULL) {
|
if (need_lut) {
|
||||||
lut_ds = transform->lut_3d.ds;
|
lut_ds = transform->lut_3d.ds;
|
||||||
} else {
|
} else {
|
||||||
lut_ds = renderer->output_ds_lut3d_dummy;
|
lut_ds = renderer->output_ds_lut3d_dummy;
|
||||||
|
|
@ -1132,7 +1173,10 @@ static struct wlr_vk_color_transform *vk_color_transform_create(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
bool need_lut = !unwrap_color_transform(transform, vk_transform->color_matrix,
|
||||||
|
&vk_transform->inverse_eotf);
|
||||||
|
|
||||||
|
if (need_lut) {
|
||||||
vk_transform->lut_3d.dim = 33;
|
vk_transform->lut_3d.dim = 33;
|
||||||
if (!create_3d_lut_image(renderer, transform,
|
if (!create_3d_lut_image(renderer, transform,
|
||||||
vk_transform->lut_3d.dim,
|
vk_transform->lut_3d.dim,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue