libweston: add HDR metadata to weston_output

This adds hdr_meta field in weston_output_color_outcome. This field is
intended to be set by color manager modules, and read by backends which
will send the information to the video sink in SMPTE ST 2084 mode a.k.a
Perceptual Quantizer HDR system.

Such metadata is essential in ST 2084 mode for the video sink to produce
a good picture.

The validation of the data and the group split is based on the HDR
Static Metata Type 1 definition in CTA-861-G specification.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
dev
Pekka Paalanen 3 years ago committed by Pekka Paalanen
parent 518d72a37b
commit cea53a90d4
  1. 60
      include/libweston/libweston.h
  2. 5
      libweston/backend.h
  3. 2
      libweston/color-lcms/color-lcms.c
  4. 2
      libweston/color-noop.c
  5. 80
      libweston/compositor.c

@ -247,6 +247,63 @@ struct weston_CIExy {
float y; float y;
}; };
enum weston_hdr_metadata_type1_groups {
/** weston_hdr_metadata_type1::primary is set */
WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES = 0x01,
/** weston_hdr_metadata_type1::white is set */
WESTON_HDR_METADATA_TYPE1_GROUP_WHITE = 0x02,
/** weston_hdr_metadata_type1::maxDML is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML = 0x04,
/** weston_hdr_metadata_type1::minDML is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MINDML = 0x08,
/** weston_hdr_metadata_type1::maxCLL is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL = 0x10,
/** weston_hdr_metadata_type1::maxFALL is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL = 0x20,
/** all valid bits */
WESTON_HDR_METADATA_TYPE1_GROUP_ALL_MASK = 0x3f
};
/** HDR static metadata type 1
*
* The fields are defined by CTA-861-G except here they use float encoding.
*
* In Weston used only with HDR display modes.
*/
struct weston_hdr_metadata_type1 {
/** Which fields are valid
*
* A bitmask of values from enum weston_hdr_metadata_type1_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries, in any order */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Maximum display mastering luminance, 1 - 65535 cd/m² */
float maxDML;
/** Minimum display mastering luminance, 0.0001 - 6.5535 cd/m² */
float minDML;
/** Maximum content light level, 1 - 65535 cd/m² */
float maxCLL;
/** Maximum frame-average light level, 1 - 65535 cd/m² */
float maxFALL;
};
enum weston_color_characteristics_groups { enum weston_color_characteristics_groups {
/** weston_color_characteristics::primary is set */ /** weston_color_characteristics::primary is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01, WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
@ -358,6 +415,9 @@ struct weston_output_color_outcome {
/** Blending to output color space transformation */ /** Blending to output color space transformation */
struct weston_color_transform *from_blend_to_output; struct weston_color_transform *from_blend_to_output;
/** HDR Static Metadata Type 1 for WESTON_EOTF_MODE_ST2084 */
struct weston_hdr_metadata_type1 hdr_meta;
}; };
/** Content producer for heads /** Content producer for heads

@ -32,6 +32,8 @@
#ifndef LIBWESTON_BACKEND_INTERNAL_H #ifndef LIBWESTON_BACKEND_INTERNAL_H
#define LIBWESTON_BACKEND_INTERNAL_H #define LIBWESTON_BACKEND_INTERNAL_H
struct weston_hdr_metadata_type1;
struct weston_backend { struct weston_backend {
void (*destroy)(struct weston_compositor *compositor); void (*destroy)(struct weston_compositor *compositor);
@ -173,6 +175,9 @@ void
weston_output_region_from_global(struct weston_output *output, weston_output_region_from_global(struct weston_output *output,
pixman_region32_t *region); pixman_region32_t *region);
const struct weston_hdr_metadata_type1 *
weston_output_get_hdr_metadata_type1(const struct weston_output *output);
/* weston_seat */ /* weston_seat */
void void

@ -208,6 +208,8 @@ cmlcms_create_output_color_outcome(struct weston_color_manager *cm_base,
&co->from_sRGB_to_output)) &co->from_sRGB_to_output))
goto out_fail; goto out_fail;
co->hdr_meta.group_mask = 0;
return co; return co;
out_fail: out_fail:

@ -116,6 +116,8 @@ cmnoop_create_output_color_outcome(struct weston_color_manager *cm_base,
co->from_sRGB_to_blend = NULL; co->from_sRGB_to_blend = NULL;
co->from_sRGB_to_output = NULL; co->from_sRGB_to_output = NULL;
co->hdr_meta.group_mask = 0;
return co; return co;
} }

@ -6449,6 +6449,57 @@ weston_output_transform_coordinate(struct weston_output *output,
*y = p.f[1] / p.f[3]; *y = p.f[1] / p.f[3];
} }
static bool
validate_float_range(float val, float min, float max)
{
return val >= min && val <= max;
}
/* Based on CTA-861-G, HDR static metadata type 1 */
static bool
weston_hdr_metadata_type1_validate(const struct weston_hdr_metadata_type1 *md)
{
unsigned i;
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES) {
for (i = 0; i < ARRAY_LENGTH(md->primary); i++) {
if (!validate_float_range(md->primary[i].x, 0.0, 1.0))
return false;
if (!validate_float_range(md->primary[i].y, 0.0, 1.0))
return false;
}
}
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_WHITE) {
if (!validate_float_range(md->white.x, 0.0, 1.0))
return false;
if (!validate_float_range(md->white.y, 0.0, 1.0))
return false;
}
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML) {
if (!validate_float_range(md->maxDML, 1.0, 65535.0))
return false;
}
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MINDML) {
if (!validate_float_range(md->minDML, 0.0001, 6.5535))
return false;
}
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL) {
if (!validate_float_range(md->maxCLL, 1.0, 65535.0))
return false;
}
if (md->group_mask & WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL) {
if (!validate_float_range(md->maxFALL, 1.0, 65535.0))
return false;
}
return true;
}
WL_EXPORT void WL_EXPORT void
weston_output_color_outcome_destroy(struct weston_output_color_outcome **pco) weston_output_color_outcome_destroy(struct weston_output_color_outcome **pco)
{ {
@ -6475,10 +6526,15 @@ weston_output_set_color_outcome(struct weston_output *output)
if (!colorout) { if (!colorout) {
weston_log("Creating color transformation for output \"%s\" failed.\n", weston_log("Creating color transformation for output \"%s\" failed.\n",
output->name); output->name);
return false; return false;
} }
if (!weston_hdr_metadata_type1_validate(&colorout->hdr_meta)) {
weston_log("Internal color manager error creating Metadata Type 1 for output \"%s\".\n",
output->name);
goto out_error;
}
weston_output_color_outcome_destroy(&output->color_outcome); weston_output_color_outcome_destroy(&output->color_outcome);
output->color_outcome = colorout; output->color_outcome = colorout;
@ -6488,6 +6544,11 @@ weston_output_set_color_outcome(struct weston_output *output)
weston_color_profile_get_description(output->color_profile)); weston_color_profile_get_description(output->color_profile));
return true; return true;
out_error:
weston_output_color_outcome_destroy(&colorout);
return false;
} }
/** Removes output from compositor's list of enabled outputs /** Removes output from compositor's list of enabled outputs
@ -6764,6 +6825,23 @@ weston_output_get_eotf_mode(const struct weston_output *output)
return output->eotf_mode; return output->eotf_mode;
} }
/** Get HDR static metadata type 1
*
* \param output The output to query.
* \return Pointer to the metadata stored in weston_output.
*
* This function is meant to be used by libweston backends.
*
* \ingroup output
* \internal
*/
WL_EXPORT const struct weston_hdr_metadata_type1 *
weston_output_get_hdr_metadata_type1(const struct weston_output *output)
{
assert(output->color_outcome);
return &output->color_outcome->hdr_meta;
}
/** Set display or monitor basic color characteristics /** Set display or monitor basic color characteristics
* *
* \param output The output to modify, must be in disabled state. * \param output The output to modify, must be in disabled state.

Loading…
Cancel
Save