libweston: introduce weston_eotf_mode

This is the switch to turn HDR mode on.

The values in the enumeration come straight from CTA-861-G standard.
Monitors advertise support for some of the HDR modes in their EDID, and
I am not aware of any other way to detect if a HDR mode actually works
or not. Different monitors may support different and multiple modes.
Different modes may look different. Therefore the high-level choice of
how to drive a HDR video sink is left for the Weston frontend to decide.

All the details like what HDR metadata to use are left for the color
manager.

This commit adds the libweston API for backends to advertise support and
for frontends to choose a mode. Backend and frontend implementations
follow in other commits.

The frontend API does not limit the EOTF mode to the supported ones to
allow experimentation and overriding EDID.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
dev
Pekka Paalanen 3 years ago committed by Pekka Paalanen
parent 054aaa5a8b
commit 5f9b68d68f
  1. 46
      include/libweston/libweston.h
  2. 4
      libweston/backend.h
  3. 17
      libweston/color.c
  4. 3
      libweston/color.h
  5. 102
      libweston/compositor.c

@ -207,6 +207,40 @@ struct weston_testsuite_data {
void *test_private_data; void *test_private_data;
}; };
/** EOTF mode for outputs and heads
*
* A list of EOTF modes for driving displays, defined by CTA-861-G for
* Dynamic Range and Mastering InfoFrame.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
*/
enum weston_eotf_mode {
/** Invalid EOTF mode, or none supported. */
WESTON_EOTF_MODE_NONE = 0,
/** Traditional gamma, SDR luminance range */
WESTON_EOTF_MODE_SDR = 0x01,
/** Traditional gamma, HDR luminance range */
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
/** Preceptual quantizer, SMPTE ST 2084 */
WESTON_EOTF_MODE_ST2084 = 0x04,
/** Hybrid log-gamma, ITU-R BT.2100 */
WESTON_EOTF_MODE_HLG = 0x08,
};
/** Bitmask of all defined EOTF modes */
#define WESTON_EOTF_MODE_ALL_MASK \
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
/** Represents a head, usually a display connector /** Represents a head, usually a display connector
* *
* \rst * \rst
@ -243,6 +277,7 @@ struct weston_head {
char *name; /**< head name, e.g. connector name */ char *name; /**< head name, e.g. connector name */
bool connected; /**< is physically connected */ bool connected; /**< is physically connected */
bool non_desktop; /**< non-desktop display, e.g. HMD */ bool non_desktop; /**< non-desktop display, e.g. HMD */
uint32_t supported_eotf_mask; /**< supported weston_eotf_mode bits */
/** Current content protection status */ /** Current content protection status */
enum weston_hdcp_protection current_protection; enum weston_hdcp_protection current_protection;
@ -361,6 +396,7 @@ struct weston_output {
struct weston_color_transform *from_sRGB_to_blend; struct weston_color_transform *from_sRGB_to_blend;
struct weston_color_transform *from_blend_to_output; struct weston_color_transform *from_blend_to_output;
bool from_blend_to_output_by_backend; bool from_blend_to_output_by_backend;
enum weston_eotf_mode eotf_mode;
int (*enable)(struct weston_output *output); int (*enable)(struct weston_output *output);
int (*disable)(struct weston_output *output); int (*disable)(struct weston_output *output);
@ -2107,6 +2143,13 @@ bool
weston_output_set_color_profile(struct weston_output *output, weston_output_set_color_profile(struct weston_output *output,
struct weston_color_profile *cprof); struct weston_color_profile *cprof);
void
weston_output_set_eotf_mode(struct weston_output *output,
enum weston_eotf_mode eotf_mode);
enum weston_eotf_mode
weston_output_get_eotf_mode(const struct weston_output *output);
void void
weston_output_init(struct weston_output *output, weston_output_init(struct weston_output *output,
struct weston_compositor *compositor, struct weston_compositor *compositor,
@ -2121,6 +2164,9 @@ weston_output_enable(struct weston_output *output);
void void
weston_output_disable(struct weston_output *output); weston_output_disable(struct weston_output *output);
uint32_t
weston_output_get_supported_eotf_modes(struct weston_output *output);
void void
weston_compositor_flush_heads_changed(struct weston_compositor *compositor); weston_compositor_flush_heads_changed(struct weston_compositor *compositor);

@ -136,6 +136,10 @@ weston_head_set_subpixel(struct weston_head *head,
void void
weston_head_set_transform(struct weston_head *head, uint32_t transform); weston_head_set_transform(struct weston_head *head, uint32_t transform);
void
weston_head_set_supported_eotf_mask(struct weston_head *head,
uint32_t eotf_mask);
/* weston_output */ /* weston_output */
void void

@ -297,3 +297,20 @@ out_close:
close(fd); close(fd);
return cprof; return cprof;
} }
/** Get a string naming the EOTF mode
*
* \internal
*/
WL_EXPORT const char *
weston_eotf_mode_to_str(enum weston_eotf_mode e)
{
switch (e) {
case WESTON_EOTF_MODE_NONE: return "(none)";
case WESTON_EOTF_MODE_SDR: return "SDR";
case WESTON_EOTF_MODE_TRADITIONAL_HDR: return "traditional gamma HDR";
case WESTON_EOTF_MODE_ST2084: return "ST2084";
case WESTON_EOTF_MODE_HLG: return "HLG";
}
return "???";
}

@ -379,4 +379,7 @@ weston_color_manager_noop_create(struct weston_compositor *compositor);
struct weston_color_manager * struct weston_color_manager *
weston_color_manager_create(struct weston_compositor *compositor); weston_color_manager_create(struct weston_compositor *compositor);
const char *
weston_eotf_mode_to_str(enum weston_eotf_mode e);
#endif /* WESTON_COLOR_H */ #endif /* WESTON_COLOR_H */

@ -5437,6 +5437,7 @@ weston_head_init(struct weston_head *head, const char *name)
wl_list_init(&head->resource_list); wl_list_init(&head->resource_list);
wl_list_init(&head->xdg_output_resource_list); wl_list_init(&head->xdg_output_resource_list);
head->name = strdup(name); head->name = strdup(name);
head->supported_eotf_mask = WESTON_EOTF_MODE_SDR;
head->current_protection = WESTON_HDCP_DISABLE; head->current_protection = WESTON_HDCP_DISABLE;
} }
@ -5962,6 +5963,31 @@ weston_head_set_connection_status(struct weston_head *head, bool connected)
weston_head_set_device_changed(head); weston_head_set_device_changed(head);
} }
/** Store the set of supported EOTF modes
*
* \param head The head to modify.
* \param eotf_mask A bit mask with the possible bits or'ed together from
* enum weston_eotf_mode.
*
* This may set the device_changed flag.
*
* \ingroup head
* \internal
*/
WL_EXPORT void
weston_head_set_supported_eotf_mask(struct weston_head *head,
uint32_t eotf_mask)
{
assert((eotf_mask & ~WESTON_EOTF_MODE_ALL_MASK) == 0);
if (head->supported_eotf_mask == eotf_mask)
return;
head->supported_eotf_mask = eotf_mask;
weston_head_set_device_changed(head);
}
static void static void
weston_output_compute_protection(struct weston_output *output) weston_output_compute_protection(struct weston_output *output)
{ {
@ -6714,6 +6740,50 @@ weston_output_set_color_profile(struct weston_output *output,
return true; return true;
} }
/** Set EOTF mode on an output
*
* \param output The output to modify, must be in disabled state.
* \param eotf_mode The EOTF mode to set.
*
* Setting the output EOTF mode is used for turning HDR on/off. There are
* multiple modes for HDR on, see enum weston_eotf_mode. This is the high level
* choice on how to drive a video sink (monitor), either in the traditional
* SDR mode or in one of the HDR modes.
*
* After attaching heads to an output, you can find out the possibly supported
* EOTF modes with weston_output_get_supported_eotf_modes().
*
* This function does not check whether the given eotf_mode is actually
* supported on the output. Enabling an output with an unsupported EOTF mode
* has undefined visual results.
*
* The initial EOTF mode is SDR.
*
* \ingroup output
*/
WL_EXPORT void
weston_output_set_eotf_mode(struct weston_output *output,
enum weston_eotf_mode eotf_mode)
{
assert(!output->enabled);
output->eotf_mode = eotf_mode;
}
/** Get EOTF mode of an output
*
* \param output The output to query.
* \return The EOTF mode.
*
* \sa weston_output_set_eotf_mode
* \ingroup output
*/
WL_EXPORT enum weston_eotf_mode
weston_output_get_eotf_mode(const struct weston_output *output)
{
return output->eotf_mode;
}
/** Initializes a weston_output object with enough data so /** Initializes a weston_output object with enough data so
** an output can be configured. ** an output can be configured.
* *
@ -6741,6 +6811,7 @@ weston_output_init(struct weston_output *output,
wl_list_init(&output->link); wl_list_init(&output->link);
wl_signal_init(&output->user_destroy_signal); wl_signal_init(&output->user_destroy_signal);
output->enabled = false; output->enabled = false;
output->eotf_mode = WESTON_EOTF_MODE_SDR;
output->desired_protection = WESTON_HDCP_DISABLE; output->desired_protection = WESTON_HDCP_DISABLE;
output->allow_protection = true; output->allow_protection = true;
@ -6903,6 +6974,9 @@ weston_output_enable(struct weston_output *output)
wl_list_init(&output->paint_node_list); wl_list_init(&output->paint_node_list);
wl_list_init(&output->paint_node_z_order_list); wl_list_init(&output->paint_node_z_order_list);
weston_log("Output '%s' attempts EOTF mode: %s\n", output->name,
weston_eotf_mode_to_str(output->eotf_mode));
if (!weston_output_set_color_transforms(output)) if (!weston_output_set_color_transforms(output))
return -1; return -1;
@ -7222,6 +7296,34 @@ weston_output_allow_protection(struct weston_output *output,
output->allow_protection = allow_protection; output->allow_protection = allow_protection;
} }
/** Get supported EOTF modes as a bit mask
*
* \param output The output to query.
* \return A bit mask with values from enum weston_eotf_mode or'ed together.
*
* Returns the bit mask of the EOTF modes that all the currently attached
* heads claim to support. Adding or removing heads may change the result.
* An output can be queried regrdless of whether it is enabled or disabled.
*
* If no heads are attached, no EOTF modes are deemed supported.
*
* \ingroup output
*/
WL_EXPORT uint32_t
weston_output_get_supported_eotf_modes(struct weston_output *output)
{
uint32_t eotf_modes = WESTON_EOTF_MODE_ALL_MASK;
struct weston_head *head;
if (wl_list_empty(&output->head_list))
return WESTON_EOTF_MODE_NONE;
wl_list_for_each(head, &output->head_list, output_link)
eotf_modes = eotf_modes & head->supported_eotf_mask;
return eotf_modes;
}
static void static void
xdg_output_unlist(struct wl_resource *resource) xdg_output_unlist(struct wl_resource *resource)
{ {

Loading…
Cancel
Save