clutter/color-state: Add min/max/ref luminances
They represent the minimum and maximum luminance levels of the primary color volume and the reference luminance level (reference white, SDR white, ...) in the reference viewing environment. They help anchoring the white level, optionally help with preserving the dynamic range and help with adjusting from a "dark" to a "bright" viewing environment. The values have defaults which depend on the transfer characteristics. This reflects the wayland color management protocol. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3953>
This commit is contained in:
parent
fe9fff2729
commit
03aad0d99e
2 changed files with 226 additions and 11 deletions
|
@ -61,6 +61,9 @@ enum
|
|||
PROP_CONTEXT,
|
||||
PROP_COLORSPACE,
|
||||
PROP_TRANSFER_FUNCTION,
|
||||
PROP_MIN_LUMINANCE,
|
||||
PROP_MAX_LUMINANCE,
|
||||
PROP_REF_LUMINANCE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
@ -79,6 +82,9 @@ typedef struct _ClutterColorStatePrivate
|
|||
unsigned int id;
|
||||
ClutterColorspace colorspace;
|
||||
ClutterTransferFunction transfer_function;
|
||||
float min_lum;
|
||||
float max_lum;
|
||||
float ref_lum;
|
||||
} ClutterColorStatePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterColorState,
|
||||
|
@ -197,6 +203,71 @@ clutter_color_state_get_transfer_function (ClutterColorState *color_state)
|
|||
return priv->transfer_function;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_transfer_function_get_default_luminances (ClutterTransferFunction transfer_function,
|
||||
float *min_lum_out,
|
||||
float *max_lum_out,
|
||||
float *ref_lum_out)
|
||||
{
|
||||
float min_lum = -1.0f, max_lum = -1.0f, ref_lum = -1.0f;
|
||||
|
||||
switch (transfer_function)
|
||||
{
|
||||
case CLUTTER_TRANSFER_FUNCTION_DEFAULT:
|
||||
case CLUTTER_TRANSFER_FUNCTION_SRGB:
|
||||
case CLUTTER_TRANSFER_FUNCTION_LINEAR:
|
||||
min_lum = 0.2f;
|
||||
max_lum = 80.0f;
|
||||
ref_lum = 80.0f;
|
||||
break;
|
||||
case CLUTTER_TRANSFER_FUNCTION_PQ:
|
||||
min_lum = 0.005f;
|
||||
max_lum = 10000.0f;
|
||||
ref_lum = 203.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (min_lum_out)
|
||||
*min_lum_out = min_lum;
|
||||
if (max_lum_out)
|
||||
*max_lum_out = max_lum;
|
||||
if (ref_lum_out)
|
||||
*ref_lum_out = ref_lum;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_color_state_get_luminances (ClutterColorState *color_state,
|
||||
float *min_lum_out,
|
||||
float *max_lum_out,
|
||||
float *ref_lum_out)
|
||||
{
|
||||
ClutterColorStatePrivate *priv;
|
||||
float min_lum, max_lum, ref_lum;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_COLOR_STATE (color_state));
|
||||
|
||||
priv = clutter_color_state_get_instance_private (color_state);
|
||||
|
||||
clutter_transfer_function_get_default_luminances (priv->transfer_function,
|
||||
&min_lum,
|
||||
&max_lum,
|
||||
&ref_lum);
|
||||
|
||||
if (priv->min_lum >= 0.0f)
|
||||
min_lum = priv->min_lum;
|
||||
if (priv->max_lum >= 0.0f)
|
||||
max_lum = priv->max_lum;
|
||||
if (priv->ref_lum >= 0.0f)
|
||||
ref_lum = priv->ref_lum;
|
||||
|
||||
if (min_lum_out)
|
||||
*min_lum_out = min_lum;
|
||||
if (max_lum_out)
|
||||
*max_lum_out = max_lum;
|
||||
if (ref_lum_out)
|
||||
*ref_lum_out = ref_lum;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_color_state_constructed (GObject *object)
|
||||
{
|
||||
|
@ -237,6 +308,18 @@ clutter_color_state_set_property (GObject *object,
|
|||
priv->transfer_function = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_MIN_LUMINANCE:
|
||||
priv->min_lum = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
case PROP_MAX_LUMINANCE:
|
||||
priv->max_lum = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
case PROP_REF_LUMINANCE:
|
||||
priv->ref_lum = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -260,13 +343,23 @@ clutter_color_state_get_property (GObject *object,
|
|||
break;
|
||||
|
||||
case PROP_COLORSPACE:
|
||||
g_value_set_enum (value,
|
||||
clutter_color_state_get_colorspace (color_state));
|
||||
g_value_set_enum (value, priv->colorspace);
|
||||
break;
|
||||
|
||||
case PROP_TRANSFER_FUNCTION:
|
||||
g_value_set_enum (value,
|
||||
clutter_color_state_get_transfer_function (color_state));
|
||||
g_value_set_enum (value, priv->transfer_function);
|
||||
break;
|
||||
|
||||
case PROP_MIN_LUMINANCE:
|
||||
g_value_set_float (value, priv->min_lum);
|
||||
break;
|
||||
|
||||
case PROP_MAX_LUMINANCE:
|
||||
g_value_set_float (value, priv->max_lum);
|
||||
break;
|
||||
|
||||
case PROP_REF_LUMINANCE:
|
||||
g_value_set_float (value, priv->ref_lum);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -323,6 +416,42 @@ clutter_color_state_class_init (ClutterColorStateClass *klass)
|
|||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
/**
|
||||
* ClutterColorState:min-luminance:
|
||||
*
|
||||
* Minimum luminance.
|
||||
*/
|
||||
obj_props[PROP_MIN_LUMINANCE] =
|
||||
g_param_spec_float ("min-luminance", NULL, NULL,
|
||||
-1.0f, 10000.0f, 0.0f,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
/**
|
||||
* ClutterColorState:max-luminance:
|
||||
*
|
||||
* Maximum luminance.
|
||||
*/
|
||||
obj_props[PROP_MAX_LUMINANCE] =
|
||||
g_param_spec_float ("max-luminance", NULL, NULL,
|
||||
-1.0f, 10000.0f, 0.0f,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
/**
|
||||
* ClutterColorState:ref-luminance:
|
||||
*
|
||||
* Reference luminance.
|
||||
*/
|
||||
obj_props[PROP_REF_LUMINANCE] =
|
||||
g_param_spec_float ("ref-luminance", NULL, NULL,
|
||||
-1.0f, 10000.0f, 0.0f,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, obj_props);
|
||||
}
|
||||
|
||||
|
@ -342,11 +471,35 @@ ClutterColorState *
|
|||
clutter_color_state_new (ClutterContext *context,
|
||||
ClutterColorspace colorspace,
|
||||
ClutterTransferFunction transfer_function)
|
||||
{
|
||||
return clutter_color_state_new_full (context,
|
||||
colorspace, transfer_function,
|
||||
-1.0f, -1.0f, -1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_state_new_full:
|
||||
*
|
||||
* Create a new ClutterColorState object with all possible parameters. Some
|
||||
* arguments might not be valid to set with other arguments.
|
||||
*
|
||||
* Return value: A new ClutterColorState object.
|
||||
**/
|
||||
ClutterColorState *
|
||||
clutter_color_state_new_full (ClutterContext *context,
|
||||
ClutterColorspace colorspace,
|
||||
ClutterTransferFunction transfer_function,
|
||||
float min_lum,
|
||||
float max_lum,
|
||||
float ref_lum)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_COLOR_STATE,
|
||||
"context", context,
|
||||
"colorspace", colorspace,
|
||||
"transfer-function", transfer_function,
|
||||
"min-luminance", min_lum,
|
||||
"max-luminance", max_lum,
|
||||
"ref-luminance", ref_lum,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@ -836,6 +989,37 @@ clutter_color_state_add_pipeline_transform (ClutterColorState *color_state,
|
|||
cogl_pipeline_add_snippet (pipeline, snippet);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
luminance_value_approx_equal (float lum,
|
||||
float other_lum,
|
||||
float epsilon)
|
||||
{
|
||||
if (lum == 0.0f || other_lum == 0.0f)
|
||||
return lum == other_lum;
|
||||
|
||||
return G_APPROX_VALUE (lum / other_lum, 1.0f, epsilon);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
luminances_equal (ClutterColorState *color_state,
|
||||
ClutterColorState *other_color_state)
|
||||
{
|
||||
float min_lum, max_lum, ref_lum;
|
||||
float other_min_lum, other_max_lum, other_ref_lum;
|
||||
|
||||
clutter_color_state_get_luminances (color_state,
|
||||
&min_lum, &max_lum, &ref_lum);
|
||||
|
||||
clutter_color_state_get_luminances (other_color_state,
|
||||
&other_min_lum,
|
||||
&other_max_lum,
|
||||
&other_ref_lum);
|
||||
|
||||
return luminance_value_approx_equal (min_lum, other_min_lum, 0.1f) &&
|
||||
luminance_value_approx_equal (max_lum, other_max_lum, 0.1f) &&
|
||||
luminance_value_approx_equal (ref_lum, other_ref_lum, 0.1f);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_color_state_equals (ClutterColorState *color_state,
|
||||
ClutterColorState *other_color_state)
|
||||
|
@ -855,8 +1039,9 @@ clutter_color_state_equals (ClutterColorState *color_state,
|
|||
priv = clutter_color_state_get_instance_private (color_state);
|
||||
other_priv = clutter_color_state_get_instance_private (other_color_state);
|
||||
|
||||
return (priv->colorspace == other_priv->colorspace &&
|
||||
priv->transfer_function == other_priv->transfer_function);
|
||||
return priv->colorspace == other_priv->colorspace &&
|
||||
priv->transfer_function == other_priv->transfer_function &&
|
||||
luminances_equal (color_state, other_color_state);
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -884,6 +1069,7 @@ clutter_color_state_to_string (ClutterColorState *color_state)
|
|||
ClutterColorStatePrivate *priv;
|
||||
g_autofree char *colorspace_name = NULL;
|
||||
g_autofree char *transfer_function_name = NULL;
|
||||
float min_lum, max_lum, ref_lum;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_COLOR_STATE (color_state), FALSE);
|
||||
|
||||
|
@ -893,11 +1079,17 @@ clutter_color_state_to_string (ClutterColorState *color_state)
|
|||
transfer_function_name = enum_to_string (CLUTTER_TYPE_TRANSFER_FUNCTION,
|
||||
priv->transfer_function);
|
||||
|
||||
clutter_color_state_get_luminances (color_state, &min_lum, &max_lum, &ref_lum);
|
||||
|
||||
return g_strdup_printf ("ClutterColorState %d "
|
||||
"(colorspace: %s, transfer function: %s)",
|
||||
"(colorspace: %s, transfer function: %s, "
|
||||
"min lum: %f, max lum: %f, ref lum: %f)",
|
||||
priv->id,
|
||||
colorspace_name,
|
||||
transfer_function_name);
|
||||
transfer_function_name,
|
||||
min_lum,
|
||||
max_lum,
|
||||
ref_lum);
|
||||
}
|
||||
|
||||
ClutterEncodingRequiredFormat
|
||||
|
@ -972,7 +1164,10 @@ clutter_color_state_get_blending (ClutterColorState *color_state,
|
|||
if (blending_tf == priv->transfer_function)
|
||||
return g_object_ref (color_state);
|
||||
|
||||
return clutter_color_state_new (priv->context,
|
||||
priv->colorspace,
|
||||
blending_tf);
|
||||
return clutter_color_state_new_full (priv->context,
|
||||
priv->colorspace,
|
||||
blending_tf,
|
||||
priv->min_lum,
|
||||
priv->max_lum,
|
||||
priv->ref_lum);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,14 @@ ClutterColorState * clutter_color_state_new (ClutterContext *context,
|
|||
ClutterColorspace colorspace,
|
||||
ClutterTransferFunction transfer_function);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterColorState * clutter_color_state_new_full (ClutterContext *context,
|
||||
ClutterColorspace colorspace,
|
||||
ClutterTransferFunction transfer_function,
|
||||
float min_lum,
|
||||
float max_lum,
|
||||
float ref_lum);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
char * clutter_color_state_to_string (ClutterColorState *color_state);
|
||||
|
||||
|
@ -55,6 +63,12 @@ ClutterColorspace clutter_color_state_get_colorspace (ClutterColorState *color_s
|
|||
CLUTTER_EXPORT
|
||||
ClutterTransferFunction clutter_color_state_get_transfer_function (ClutterColorState *color_state);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_state_get_luminances (ClutterColorState *color_state,
|
||||
float *min_lum_out,
|
||||
float *max_lum_out,
|
||||
float *ref_lum_out);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_state_add_pipeline_transform (ClutterColorState *color_state,
|
||||
ClutterColorState *target_color_state,
|
||||
|
@ -71,4 +85,10 @@ CLUTTER_EXPORT
|
|||
ClutterColorState * clutter_color_state_get_blending (ClutterColorState *color_state,
|
||||
gboolean force);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_transfer_function_get_default_luminances (ClutterTransferFunction transfer_function,
|
||||
float *min_lum_out,
|
||||
float *max_lum_out,
|
||||
float *ref_lum_out);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Add table
Reference in a new issue