mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-31 22:25:21 -04:00
render/color, render/vulkan: add support for PQ transfer function
This commit is contained in:
parent
8430a1922d
commit
4470683591
4 changed files with 56 additions and 17 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
#include <wlr/util/addon.h>
|
#include <wlr/util/addon.h>
|
||||||
|
|
||||||
enum wlr_color_transform_type {
|
enum wlr_color_transform_type {
|
||||||
COLOR_TRANSFORM_SRGB,
|
COLOR_TRANSFORM_INVERSE_EOTF,
|
||||||
COLOR_TRANSFORM_LCMS2,
|
COLOR_TRANSFORM_LCMS2,
|
||||||
COLOR_TRANSFORM_LUT_3X1D,
|
COLOR_TRANSFORM_LUT_3X1D,
|
||||||
};
|
};
|
||||||
|
|
@ -18,8 +18,11 @@ struct wlr_color_transform {
|
||||||
enum wlr_color_transform_type type;
|
enum wlr_color_transform_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
void wlr_color_transform_init(struct wlr_color_transform *tr,
|
struct wlr_color_transform_inverse_eotf {
|
||||||
enum wlr_color_transform_type type);
|
struct wlr_color_transform base;
|
||||||
|
|
||||||
|
enum wlr_color_transfer_function tf;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The formula is approximated via three 1D look-up tables. The flat lut_3x1d
|
* The formula is approximated via three 1D look-up tables. The flat lut_3x1d
|
||||||
|
|
@ -36,6 +39,9 @@ struct wlr_color_transform_lut_3x1d {
|
||||||
size_t dim;
|
size_t dim;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void wlr_color_transform_init(struct wlr_color_transform *tr,
|
||||||
|
enum wlr_color_transform_type type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a struct wlr_color_transform_lcms2 from a generic struct wlr_color_transform.
|
* Get a struct wlr_color_transform_lcms2 from a generic struct wlr_color_transform.
|
||||||
* Asserts that the base type is COLOR_TRANSFORM_LCMS2.
|
* Asserts that the base type is COLOR_TRANSFORM_LCMS2.
|
||||||
|
|
@ -51,6 +57,13 @@ void color_transform_lcms2_finish(struct wlr_color_transform_lcms2 *tr);
|
||||||
void color_transform_lcms2_eval(struct wlr_color_transform_lcms2 *tr,
|
void color_transform_lcms2_eval(struct wlr_color_transform_lcms2 *tr,
|
||||||
float out[static 3], const float in[static 3]);
|
float out[static 3], const float in[static 3]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a wlr_color_transform_inverse_eotf from a generic wlr_color_transform.
|
||||||
|
* Asserts that the base type is COLOR_TRANSFORM_INVERSE_EOTF
|
||||||
|
*/
|
||||||
|
struct wlr_color_transform_inverse_eotf *wlr_color_transform_inverse_eotf_from_base(
|
||||||
|
struct wlr_color_transform *tr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a struct wlr_color_transform_lut_3x1d from a generic
|
* Get a struct wlr_color_transform_lut_3x1d from a generic
|
||||||
* struct wlr_color_transform. Asserts that the base type is
|
* struct wlr_color_transform. Asserts that the base type is
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,11 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_icc(
|
||||||
const void *data, size_t size);
|
const void *data, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a color transformation to apply sRGB encoding.
|
* Initialize a color transformation to apply EOTF⁻¹ encoding. Returns
|
||||||
* Returns NULL on failure.
|
* NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct wlr_color_transform *wlr_color_transform_init_srgb(void);
|
struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf(
|
||||||
|
enum wlr_color_transfer_function tf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a color transformation to apply three 1D look-up tables. dim
|
* Initialize a color transformation to apply three 1D look-up tables. dim
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,15 @@ void wlr_color_transform_init(struct wlr_color_transform *tr, enum wlr_color_tra
|
||||||
wlr_addon_set_init(&tr->addons);
|
wlr_addon_set_init(&tr->addons);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_color_transform *wlr_color_transform_init_srgb(void) {
|
struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf(
|
||||||
struct wlr_color_transform *tx = calloc(1, sizeof(*tx));
|
enum wlr_color_transfer_function tf) {
|
||||||
|
struct wlr_color_transform_inverse_eotf *tx = calloc(1, sizeof(*tx));
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wlr_color_transform_init(tx, COLOR_TRANSFORM_SRGB);
|
wlr_color_transform_init(&tx->base, COLOR_TRANSFORM_INVERSE_EOTF);
|
||||||
return tx;
|
tx->tf = tf;
|
||||||
|
return &tx->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
|
struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
|
||||||
|
|
@ -62,7 +64,7 @@ struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
|
||||||
|
|
||||||
static void color_transform_destroy(struct wlr_color_transform *tr) {
|
static void color_transform_destroy(struct wlr_color_transform *tr) {
|
||||||
switch (tr->type) {
|
switch (tr->type) {
|
||||||
case COLOR_TRANSFORM_SRGB:
|
case COLOR_TRANSFORM_INVERSE_EOTF:
|
||||||
break;
|
break;
|
||||||
case COLOR_TRANSFORM_LCMS2:
|
case COLOR_TRANSFORM_LCMS2:
|
||||||
color_transform_lcms2_finish(color_transform_lcms2_from_base(tr));
|
color_transform_lcms2_finish(color_transform_lcms2_from_base(tr));
|
||||||
|
|
@ -92,6 +94,13 @@ void wlr_color_transform_unref(struct wlr_color_transform *tr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_color_transform_inverse_eotf *wlr_color_transform_inverse_eotf_from_base(
|
||||||
|
struct wlr_color_transform *tr) {
|
||||||
|
assert(tr->type == COLOR_TRANSFORM_INVERSE_EOTF);
|
||||||
|
struct wlr_color_transform_inverse_eotf *inverse_eotf = wl_container_of(tr, inverse_eotf, base);
|
||||||
|
return inverse_eotf;
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base(
|
struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base(
|
||||||
struct wlr_color_transform *tr) {
|
struct wlr_color_transform *tr) {
|
||||||
assert(tr->type == COLOR_TRANSFORM_LUT_3X1D);
|
assert(tr->type == COLOR_TRANSFORM_LUT_3X1D);
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
|
|
||||||
struct wlr_vk_color_transform *transform = NULL;
|
struct wlr_vk_color_transform *transform = NULL;
|
||||||
size_t dim = 1;
|
size_t dim = 1;
|
||||||
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_SRGB) {
|
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
||||||
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;
|
dim = transform->lut_3d.dim;
|
||||||
|
|
@ -219,11 +219,27 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
}
|
}
|
||||||
encode_color_matrix(matrix, frag_pcr_data.matrix);
|
encode_color_matrix(matrix, frag_pcr_data.matrix);
|
||||||
|
|
||||||
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_SRGB) {
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
bind_pipeline(pass, render_buffer->plain.render_setup->output_pipe_lut3d);
|
if (pass->color_transform && pass->color_transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
||||||
|
pipeline = render_buffer->plain.render_setup->output_pipe_lut3d;
|
||||||
} else {
|
} else {
|
||||||
bind_pipeline(pass, render_buffer->plain.render_setup->output_pipe_srgb);
|
enum wlr_color_transfer_function tf = WLR_COLOR_TRANSFER_FUNCTION_SRGB;
|
||||||
|
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) {
|
||||||
|
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
|
||||||
|
pipeline = render_buffer->plain.render_setup->output_pipe_srgb;
|
||||||
|
break;
|
||||||
|
case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ:
|
||||||
|
pipeline = render_buffer->plain.render_setup->output_pipe_pq;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bind_pipeline(pass, pipeline);
|
||||||
vkCmdPushConstants(render_cb->vk, renderer->output_pipe_layout,
|
vkCmdPushConstants(render_cb->vk, renderer->output_pipe_layout,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||||
vkCmdPushConstants(render_cb->vk, renderer->output_pipe_layout,
|
vkCmdPushConstants(render_cb->vk, renderer->output_pipe_layout,
|
||||||
|
|
@ -880,7 +896,7 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer,
|
||||||
struct wlr_color_transform_lcms2 *tr_lcms2 = NULL;
|
struct wlr_color_transform_lcms2 *tr_lcms2 = NULL;
|
||||||
struct wlr_color_transform_lut_3x1d *tr_lut_3x1d = NULL;
|
struct wlr_color_transform_lut_3x1d *tr_lut_3x1d = NULL;
|
||||||
switch (tr->type) {
|
switch (tr->type) {
|
||||||
case COLOR_TRANSFORM_SRGB:
|
case COLOR_TRANSFORM_INVERSE_EOTF:
|
||||||
abort(); // unreachable
|
abort(); // unreachable
|
||||||
case COLOR_TRANSFORM_LCMS2:
|
case COLOR_TRANSFORM_LCMS2:
|
||||||
tr_lcms2 = color_transform_lcms2_from_base(tr);
|
tr_lcms2 = color_transform_lcms2_from_base(tr);
|
||||||
|
|
@ -1061,7 +1077,7 @@ static struct wlr_vk_color_transform *vk_color_transform_create(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transform->type != COLOR_TRANSFORM_SRGB) {
|
if (transform->type != COLOR_TRANSFORM_INVERSE_EOTF) {
|
||||||
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
Add a link
Reference in a new issue