diff --git a/frontend/main.c b/frontend/main.c index 1c7f363b4..b32b9399d 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -72,6 +72,7 @@ #include #include #include +#include #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; diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 838cd358a..1228ce176 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -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 diff --git a/libweston/color.c b/libweston/color.c index 6eb1b519d..13e65df34 100644 --- a/libweston/color.c +++ b/libweston/color.c @@ -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); +} diff --git a/libweston/color.h b/libweston/color.h index 08c2edfbe..deef06b01 100644 --- a/libweston/color.h +++ b/libweston/color.h @@ -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 */ diff --git a/libweston/compositor.c b/libweston/compositor.c index 8ea21e4f6..d806ebdc4 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -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)