frontend: Add support for forcing a color format

Allow dictating which color format we'd like to use. This introduces the
front-end side and the core parts, leaving the EDID parsing and DRM
connector property for later patches.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
Derek Foreman 2024-10-09 10:51:16 -05:00 committed by Daniel Stone
parent 0664d5bdc1
commit 2c7fd792b5
5 changed files with 147 additions and 0 deletions

View file

@ -72,6 +72,7 @@
#include <libweston/weston-log.h>
#include <libweston/remoting-plugin.h>
#include <libweston/pipewire-plugin.h>
#include <libweston/color.h>
#define WINDOW_TITLE "Weston Compositor"
/* flight recorder size (in bytes) */
@ -2389,6 +2390,55 @@ out_error:
return -1;
}
static int
wet_output_set_color_format(struct weston_output *output,
struct weston_config_section *section)
{
static const struct weston_enum_map color_formats[] = {
{ "auto", WESTON_COLOR_FORMAT_AUTO },
{ "rgb", WESTON_COLOR_FORMAT_RGB },
{ "yuv444", WESTON_COLOR_FORMAT_YUV444 },
{ "yuv422", WESTON_COLOR_FORMAT_YUV422 },
{ "yuv420", WESTON_COLOR_FORMAT_YUV420 },
};
enum weston_color_format color_format = WESTON_COLOR_FORMAT_AUTO;
const struct weston_enum_map *entry;
char *str = NULL;
weston_config_section_get_string(section, "color-format", &str, "auto");
entry = weston_enum_map_find_name(color_formats, str);
if (!entry) {
char *mask_to_str = NULL;
weston_log("Error in config for output '%s': '%s' is not a "
"valid color format. Try one of: ",
output->name, str);
mask_to_str = bits_to_str(WESTON_COLOR_FORMAT_ALL_MASK,
weston_color_format_to_str);
weston_log_continue("%s\n", mask_to_str);
free(mask_to_str);
free(str);
return -1;
}
color_format = entry->value;
if ((weston_output_get_supported_color_formats(output) & color_format) == 0) {
weston_log("Error: output '%s' does not support output format %s\n",
output->name, str);
free(str);
return -1;
}
weston_log("Setting output '%s' to color %s format\n",
output->name, weston_color_format_to_str(color_format));
weston_output_set_color_format(output, color_format);
free(str);
return 0;
}
static void
allow_content_protection(struct weston_output *output,
struct weston_config_section *section)
@ -3142,6 +3192,9 @@ drm_backend_output_configure(struct weston_output *output,
if (wet_output_set_color_profile(output, section, wet->config, NULL) < 0)
return -1;
if (wet_output_set_color_format(output, section) < 0)
return -1;
if (wet_output_set_color_characteristics(output,
wet->config, section) < 0)
return -1;

View file

@ -291,6 +291,8 @@ struct weston_head {
struct wl_list cm_output_resource_list;
uint32_t supported_vrr_mode_mask;
uint32_t supported_color_format_mask;
};
enum weston_output_power_state {
@ -320,6 +322,25 @@ enum weston_vrr_mode {
#define WESTON_VRR_MODE_ALL_MASK \
((uint32_t)(WESTON_VRR_MODE_GAME))
enum weston_color_format {
/** Driver assigned color format automatically */
WESTON_COLOR_FORMAT_AUTO = (1 << 0),
/** Force RGB color format */
WESTON_COLOR_FORMAT_RGB = (1 << 1),
/** Force YUV color format with 4:2:2 susampling */
WESTON_COLOR_FORMAT_YUV422 = (1 << 2),
/** Force YUV color format with no subsampling */
WESTON_COLOR_FORMAT_YUV444 = (1 << 3),
/** Force YUV color format with 4:2:0 subsampling */
WESTON_COLOR_FORMAT_YUV420 = (1 << 4),
};
/** Bitmask of all defined color formats */
#define WESTON_COLOR_FORMAT_ALL_MASK \
((uint32_t)(WESTON_COLOR_FORMAT_AUTO | WESTON_COLOR_FORMAT_RGB | \
WESTON_COLOR_FORMAT_YUV444 | WESTON_COLOR_FORMAT_YUV422 | \
WESTON_COLOR_FORMAT_YUV420))
struct weston_plane {
struct weston_compositor *compositor;
int32_t x, y;
@ -517,6 +538,8 @@ struct weston_output {
struct weston_output *mirror_of;
enum weston_vrr_mode vrr_mode;
enum weston_color_format color_format;
};
enum weston_pointer_motion_mask {
@ -2681,6 +2704,13 @@ weston_compositor_arm_surface_counter_fps(struct weston_compositor *ec);
void
weston_compositor_disarm_surface_counter_fps(struct weston_compositor *ec);
void
weston_output_set_color_format(struct weston_output *output,
enum weston_color_format color_format);
uint32_t
weston_output_get_supported_color_formats(struct weston_output *output);
#ifdef __cplusplus
}
#endif

View file

@ -1077,3 +1077,38 @@ weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to)
tmp = weston_m3f_mul_m3f(weston_m3f_diag(r), bradford);
return weston_m3f_mul_m3f(inv, tmp);
}
/** Get a string naming the color format
*
* \internal
*/
WL_EXPORT const char *
weston_color_format_to_str(enum weston_color_format c)
{
switch (c) {
case WESTON_COLOR_FORMAT_AUTO:
return "AUTO";
case WESTON_COLOR_FORMAT_RGB:
return "RGB";
case WESTON_COLOR_FORMAT_YUV444:
return "YUV 4:4:4";
case WESTON_COLOR_FORMAT_YUV422:
return "YUV 4:2:2";
case WESTON_COLOR_FORMAT_YUV420:
return "YUV 4:2:0";
}
return "???";
}
/** A list of color formats as a string
*
* \param color_format_mask Bitwise-or'd enum weston_color_format values.
* \return Comma separated names of the listed color formats.
* Must be free()'d by the caller.
*/
WL_EXPORT char *
weston_color_format_mask_to_str(uint32_t color_format_mask)
{
return bits_to_str(color_format_mask, weston_color_format_to_str);
}

View file

@ -750,4 +750,10 @@ weston_colorimetry_mask_to_str(uint32_t colorimetry_mask);
void
weston_output_color_outcome_destroy(struct weston_output_color_outcome **pco);
const char *
weston_color_format_to_str(enum weston_color_format c);
char *
weston_color_format_mask_to_str(uint32_t color_format_mask);
#endif /* WESTON_COLOR_H */

View file

@ -6009,6 +6009,7 @@ weston_head_init(struct weston_head *head, const char *name)
head->name = xstrdup(name);
head->supported_eotf_mask = WESTON_EOTF_MODE_SDR;
head->supported_colorimetry_mask = WESTON_COLORIMETRY_MODE_DEFAULT;
head->supported_color_format_mask = WESTON_COLOR_FORMAT_AUTO;
head->current_protection = WESTON_HDCP_DISABLE;
weston_head_set_monitor_strings(head, NULL, NULL, NULL);
@ -7901,6 +7902,7 @@ weston_output_init(struct weston_output *output,
output->enabled = false;
output->eotf_mode = WESTON_EOTF_MODE_SDR;
output->colorimetry_mode = WESTON_COLORIMETRY_MODE_DEFAULT;
output->color_format = WESTON_COLOR_FORMAT_AUTO;
output->desired_protection = WESTON_HDCP_DISABLE;
output->allow_protection = true;
output->power_state = WESTON_OUTPUT_POWER_NORMAL;
@ -8546,6 +8548,27 @@ weston_output_set_vrr_mode(struct weston_output *output,
return 0;
}
WL_EXPORT void
weston_output_set_color_format(struct weston_output *output,
enum weston_color_format color_format)
{
output->color_format = color_format;
}
WL_EXPORT uint32_t
weston_output_get_supported_color_formats(struct weston_output *output)
{
uint32_t color_formats = WESTON_COLOR_FORMAT_ALL_MASK;
struct weston_head *head;
if (wl_list_empty(&output->head_list))
return WESTON_COLOR_FORMAT_AUTO;
wl_list_for_each(head, &output->head_list, output_link)
color_formats &= head->supported_color_format_mask;
return color_formats;
}
static void
xdg_output_unlist(struct wl_resource *resource)