mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
render: make wlr_render_pass_add_texture() take a general color_transform
Mirrors the previous changes to wlr_renderer_begin_buffer_pass(), moving color-management decisions to wlr_scene
This commit is contained in:
parent
42cf99a037
commit
03d3041fba
7 changed files with 148 additions and 54 deletions
|
|
@ -374,7 +374,6 @@ struct wlr_vk_vert_pcr_data {
|
|||
struct wlr_vk_frag_texture_pcr_data {
|
||||
float matrix[4][4]; // only a 3x3 subset is used
|
||||
float alpha;
|
||||
float luminance_multiplier;
|
||||
};
|
||||
|
||||
struct wlr_vk_frag_output_pcr_data {
|
||||
|
|
|
|||
|
|
@ -101,16 +101,12 @@ struct wlr_render_texture_options {
|
|||
enum wlr_scale_filter_mode filter_mode;
|
||||
/* Blend mode */
|
||||
enum wlr_render_blend_mode blend_mode;
|
||||
/* Transfer function the source texture is encoded with */
|
||||
enum wlr_color_transfer_function transfer_function;
|
||||
/* Primaries describing the color volume of the source texture */
|
||||
const struct wlr_color_primaries *primaries;
|
||||
/* Applied to convert from source texture to blend space */
|
||||
struct wlr_color_transform *color_transform;
|
||||
/* Color encoding of the source texture for YCbCr conversion to RGB */
|
||||
enum wlr_color_encoding color_encoding;
|
||||
/* Color range of the source texture */
|
||||
enum wlr_color_range color_range;
|
||||
/* Default: 1.0 */
|
||||
const float *luminance_multiplier;
|
||||
|
||||
/* Wait for a timeline synchronization point before texturing.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ struct wlr_output_cursor {
|
|||
|
||||
struct {
|
||||
struct wl_listener renderer_destroy;
|
||||
struct wlr_color_transform *color_transform;
|
||||
struct wlr_color_transform *color_transform_linearize;
|
||||
struct wlr_color_transform *color_transform_encode;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ static bool render_pass_wait_render_buffer(struct wlr_vk_render_pass *pass,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool unwrap_color_transform(struct wlr_color_transform *transform,
|
||||
static bool unwrap_output_color_transform(struct wlr_color_transform *transform,
|
||||
float matrix[static 9], enum wlr_color_transfer_function *tf) {
|
||||
if (transform == NULL) {
|
||||
wlr_matrix_identity(matrix);
|
||||
|
|
@ -175,6 +175,47 @@ static bool unwrap_color_transform(struct wlr_color_transform *transform,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool unwrap_texture_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_eotf *eotf;
|
||||
struct wlr_color_transform_matrix *as_matrix;
|
||||
struct wlr_color_transform_pipeline *pipeline;
|
||||
switch (transform->type) {
|
||||
case COLOR_TRANSFORM_EOTF:
|
||||
eotf = wlr_color_transform_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_EOTF
|
||||
|| pipeline->transforms[1]->type != COLOR_TRANSFORM_MATRIX) {
|
||||
return false;
|
||||
}
|
||||
eotf = wlr_color_transform_eotf_from_base(pipeline->transforms[0]);
|
||||
*tf = eotf->tf;
|
||||
as_matrix = wl_container_of(pipeline->transforms[1], as_matrix, base);
|
||||
memcpy(matrix, as_matrix->matrix, sizeof(float[9]));
|
||||
return true;
|
||||
case COLOR_TRANSFORM_INVERSE_EOTF:
|
||||
case COLOR_TRANSFORM_LCMS2:
|
||||
case COLOR_TRANSFORM_LUT_3X1D:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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_renderer *renderer = pass->renderer;
|
||||
|
|
@ -789,9 +830,12 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
};
|
||||
encode_proj_matrix(matrix, vert_pcr_data.mat4);
|
||||
|
||||
enum wlr_color_transfer_function tf = options->transfer_function;
|
||||
if (tf == 0) {
|
||||
enum wlr_color_transfer_function tf;
|
||||
float color_matrix[9];
|
||||
if (!unwrap_texture_color_transform(options->color_transform, color_matrix, &tf))
|
||||
{
|
||||
tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
|
||||
wlr_matrix_identity(color_matrix);
|
||||
}
|
||||
|
||||
bool srgb_image_view = false;
|
||||
|
|
@ -858,25 +902,8 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
return;
|
||||
}
|
||||
|
||||
float color_matrix[9];
|
||||
if (options->primaries != NULL) {
|
||||
struct wlr_color_primaries srgb;
|
||||
wlr_color_primaries_from_named(&srgb, WLR_COLOR_NAMED_PRIMARIES_SRGB);
|
||||
|
||||
wlr_color_primaries_transform_absolute_colorimetric(options->primaries,
|
||||
&srgb, color_matrix);
|
||||
} else {
|
||||
wlr_matrix_identity(color_matrix);
|
||||
}
|
||||
|
||||
float luminance_multiplier = 1;
|
||||
if (options->luminance_multiplier != NULL) {
|
||||
luminance_multiplier = *options->luminance_multiplier;
|
||||
}
|
||||
|
||||
struct wlr_vk_frag_texture_pcr_data frag_pcr_data = {
|
||||
.alpha = alpha,
|
||||
.luminance_multiplier = luminance_multiplier,
|
||||
};
|
||||
encode_color_matrix(color_matrix, frag_pcr_data.matrix);
|
||||
|
||||
|
|
@ -1147,7 +1174,7 @@ static struct wlr_vk_color_transform *vk_color_transform_create(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool need_lut = !unwrap_color_transform(transform, vk_transform->color_matrix,
|
||||
bool need_lut = !unwrap_output_color_transform(transform, vk_transform->color_matrix,
|
||||
&vk_transform->inverse_eotf);
|
||||
|
||||
if (need_lut) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ layout(location = 0) out vec4 out_color;
|
|||
layout(push_constant, row_major) uniform UBO {
|
||||
layout(offset = 80) mat4 matrix;
|
||||
float alpha;
|
||||
float luminance_multiplier;
|
||||
} data;
|
||||
|
||||
layout (constant_id = 0) const int TEXTURE_TRANSFORM = 0;
|
||||
|
|
@ -82,8 +81,6 @@ void main() {
|
|||
rgb = bt1886_color_to_linear(rgb);
|
||||
}
|
||||
|
||||
rgb *= data.luminance_multiplier;
|
||||
|
||||
rgb = mat3(data.matrix) * rgb;
|
||||
|
||||
// Back to pre-multiplied alpha
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
|||
buffer->width, buffer->height);
|
||||
|
||||
struct wlr_buffer_pass_options options = {
|
||||
.color_transform = cursor->color_transform,
|
||||
.color_transform = cursor->color_transform_encode,
|
||||
};
|
||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, buffer, &options);
|
||||
if (pass == NULL) {
|
||||
|
|
@ -278,6 +278,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
|||
.transform = transform,
|
||||
.wait_timeline = cursor->wait_timeline,
|
||||
.wait_point = cursor->wait_point,
|
||||
.color_transform = cursor->color_transform_linearize,
|
||||
});
|
||||
|
||||
if (!wlr_render_pass_submit(pass)) {
|
||||
|
|
@ -493,18 +494,27 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
|
|||
}
|
||||
wlr_drm_syncobj_timeline_unref(cursor->wait_timeline);
|
||||
wl_list_remove(&cursor->link);
|
||||
wlr_color_transform_unref(cursor->color_transform);
|
||||
wlr_color_transform_unref(cursor->color_transform_linearize);
|
||||
wlr_color_transform_unref(cursor->color_transform_encode);
|
||||
free(cursor);
|
||||
}
|
||||
|
||||
bool output_cursor_refresh_color_transform(struct wlr_output_cursor *output_cursor,
|
||||
const struct wlr_output_image_description *img_desc) {
|
||||
wlr_color_transform_unref(output_cursor->color_transform);
|
||||
output_cursor->color_transform = NULL;
|
||||
wlr_color_transform_unref(output_cursor->color_transform_linearize);
|
||||
output_cursor->color_transform_linearize = NULL;
|
||||
wlr_color_transform_unref(output_cursor->color_transform_encode);
|
||||
output_cursor->color_transform_encode = NULL;
|
||||
if (img_desc == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
output_cursor->color_transform_linearize = wlr_color_transform_init_eotf_to_linear(
|
||||
WLR_COLOR_TRANSFER_FUNCTION_GAMMA22);
|
||||
if (output_cursor->color_transform_linearize == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
struct wlr_color_primaries primaries_srgb;
|
||||
wlr_color_primaries_from_named(&primaries_srgb, WLR_COLOR_NAMED_PRIMARIES_SRGB);
|
||||
struct wlr_color_primaries primaries;
|
||||
|
|
@ -525,13 +535,22 @@ bool output_cursor_refresh_color_transform(struct wlr_output_cursor *output_curs
|
|||
wlr_color_transform_init_linear_to_inverse_eotf(img_desc->transfer_function),
|
||||
};
|
||||
if (transforms[0] == NULL || transforms[1] == NULL) {
|
||||
wlr_color_transform_unref(transforms[0]);
|
||||
wlr_color_transform_unref(transforms[1]);
|
||||
return false;
|
||||
goto err;
|
||||
}
|
||||
output_cursor->color_transform = wlr_color_transform_init_pipeline(transforms,
|
||||
output_cursor->color_transform_encode = wlr_color_transform_init_pipeline(transforms,
|
||||
sizeof(transforms) / sizeof(transforms[0]));
|
||||
if (output_cursor->color_transform_encode == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
wlr_color_transform_unref(transforms[0]);
|
||||
wlr_color_transform_unref(transforms[1]);
|
||||
return output_cursor->color_transform != NULL;
|
||||
return true;
|
||||
|
||||
err:
|
||||
wlr_color_transform_unref(output_cursor->color_transform_linearize);
|
||||
output_cursor->color_transform_linearize = NULL;
|
||||
wlr_color_transform_unref(transforms[0]);
|
||||
wlr_color_transform_unref(transforms[1]);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "types/wlr_scene.h"
|
||||
#include "util/array.h"
|
||||
#include "util/env.h"
|
||||
#include "util/matrix.h"
|
||||
#include "util/time.h"
|
||||
|
||||
#include <wlr/config.h>
|
||||
|
|
@ -1411,6 +1412,63 @@ 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);
|
||||
}
|
||||
|
||||
static struct wlr_color_transform *scene_texture_to_blend_space(
|
||||
struct wlr_scene_buffer *source, enum wlr_color_named_primaries dest_primaries,
|
||||
const struct wlr_color_luminances *dest_luminance) {
|
||||
struct wlr_color_transform *color_matrix = NULL;
|
||||
struct wlr_color_transform *eotf = NULL;
|
||||
struct wlr_color_transform *combined = NULL;
|
||||
|
||||
enum wlr_color_transfer_function source_tf = WLR_COLOR_TRANSFER_FUNCTION_GAMMA22;
|
||||
if (source->transfer_function != 0) {
|
||||
source_tf = source->transfer_function;
|
||||
}
|
||||
eotf = wlr_color_transform_init_eotf_to_linear(source_tf);
|
||||
if (eotf == NULL) {
|
||||
goto cleanup_transforms;
|
||||
}
|
||||
|
||||
struct wlr_color_luminances source_lum;
|
||||
wlr_color_transfer_function_get_default_luminance(source_tf, &source_lum);
|
||||
float luminance_multiplier = get_luminance_multiplier(&source_lum, dest_luminance);
|
||||
|
||||
float matrix[9];
|
||||
|
||||
enum wlr_color_named_primaries source_primaries = WLR_COLOR_NAMED_PRIMARIES_SRGB;
|
||||
if (source->primaries != 0) {
|
||||
source_primaries = source->primaries;
|
||||
}
|
||||
if (source_primaries != dest_primaries) {
|
||||
struct wlr_color_primaries primaries;
|
||||
wlr_color_primaries_from_named(&primaries, source_primaries);
|
||||
struct wlr_color_primaries primaries_blend;
|
||||
wlr_color_primaries_from_named(&primaries_blend, dest_primaries);
|
||||
wlr_color_primaries_transform_absolute_colorimetric(&primaries, &primaries_blend, matrix);
|
||||
} else {
|
||||
wlr_matrix_identity(matrix);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
matrix[i] *= luminance_multiplier;
|
||||
}
|
||||
color_matrix = wlr_color_transform_init_matrix(matrix);
|
||||
if (color_matrix == NULL) {
|
||||
goto cleanup_transforms;
|
||||
}
|
||||
|
||||
struct wlr_color_transform *transforms[] = {
|
||||
eotf,
|
||||
color_matrix,
|
||||
};
|
||||
const size_t transforms_len = sizeof(transforms) / sizeof(transforms[0]);
|
||||
color_transform_compose(&combined, transforms, transforms_len);
|
||||
|
||||
cleanup_transforms:
|
||||
wlr_color_transform_unref(eotf);
|
||||
wlr_color_transform_unref(color_matrix);
|
||||
return combined;
|
||||
}
|
||||
|
||||
static void scene_entry_render(struct render_list_entry *entry, const struct render_data *data) {
|
||||
struct wlr_scene_node *node = entry->node;
|
||||
|
||||
|
|
@ -1489,17 +1547,14 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
|
|||
wlr_output_transform_invert(scene_buffer->transform);
|
||||
transform = wlr_output_transform_compose(transform, data->transform);
|
||||
|
||||
struct wlr_color_primaries primaries = {0};
|
||||
if (scene_buffer->primaries != 0) {
|
||||
wlr_color_primaries_from_named(&primaries, scene_buffer->primaries);
|
||||
}
|
||||
struct wlr_color_transform *source_to_blend = NULL;
|
||||
if (data->output->output->renderer->features.input_color_transform) {
|
||||
struct wlr_color_luminances srgb_lum;
|
||||
wlr_color_transfer_function_get_default_luminance(WLR_COLOR_TRANSFER_FUNCTION_SRGB, &srgb_lum);
|
||||
|
||||
struct wlr_color_luminances src_lum, srgb_lum;
|
||||
wlr_color_transfer_function_get_default_luminance(
|
||||
scene_buffer->transfer_function, &src_lum);
|
||||
wlr_color_transfer_function_get_default_luminance(
|
||||
WLR_COLOR_TRANSFER_FUNCTION_SRGB, &srgb_lum);
|
||||
float luminance_multiplier = get_luminance_multiplier(&src_lum, &srgb_lum);
|
||||
source_to_blend = scene_texture_to_blend_space(
|
||||
scene_buffer, WLR_COLOR_NAMED_PRIMARIES_SRGB, &srgb_lum);
|
||||
}
|
||||
|
||||
wlr_render_pass_add_texture(data->render_pass, &(struct wlr_render_texture_options) {
|
||||
.texture = texture,
|
||||
|
|
@ -1512,15 +1567,15 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
|
|||
.blend_mode = !data->output->scene->calculate_visibility ||
|
||||
!pixman_region32_empty(&opaque) ?
|
||||
WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE,
|
||||
.transfer_function = scene_buffer->transfer_function,
|
||||
.primaries = scene_buffer->primaries != 0 ? &primaries : NULL,
|
||||
.color_transform = source_to_blend,
|
||||
.color_encoding = scene_buffer->color_encoding,
|
||||
.color_range = scene_buffer->color_range,
|
||||
.luminance_multiplier = &luminance_multiplier,
|
||||
.wait_timeline = scene_buffer->wait_timeline,
|
||||
.wait_point = scene_buffer->wait_point,
|
||||
});
|
||||
|
||||
wlr_color_transform_unref(source_to_blend);
|
||||
|
||||
struct wlr_scene_output_sample_event sample_event = {
|
||||
.output = data->output,
|
||||
.direct_scanout = false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue