kms/connector: Add support for the Broadcast RGB property
It can be used to force a specific RGB range. Some monitors don't follow the specification and expect a signal different from what we send. This property allows to force a mode which hopefully then works correctly for the sink. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3535>
This commit is contained in:
parent
d45104c14a
commit
c4399bd94d
@ -40,6 +40,14 @@ typedef enum
|
||||
META_OUTPUT_HDR_METADATA_EOTF_HLG,
|
||||
} MetaOutputHdrMetadataEOTF;
|
||||
|
||||
typedef enum _MetaOutputRGBRange
|
||||
{
|
||||
META_OUTPUT_RGB_RANGE_UNKNOWN = 0,
|
||||
META_OUTPUT_RGB_RANGE_AUTO,
|
||||
META_OUTPUT_RGB_RANGE_FULL,
|
||||
META_OUTPUT_RGB_RANGE_LIMITED,
|
||||
} MetaOutputRGBRange;
|
||||
|
||||
typedef struct _MetaOutputHdrMetadata
|
||||
{
|
||||
gboolean active;
|
||||
|
@ -39,6 +39,7 @@ typedef enum _MetaKmsConnectorProp
|
||||
META_KMS_CONNECTOR_PROP_MAX_BPC,
|
||||
META_KMS_CONNECTOR_PROP_COLORSPACE,
|
||||
META_KMS_CONNECTOR_PROP_HDR_OUTPUT_METADATA,
|
||||
META_KMS_CONNECTOR_PROP_BROADCAST_RGB,
|
||||
META_KMS_CONNECTOR_N_PROPS
|
||||
} MetaKmsConnectorProp;
|
||||
|
||||
@ -113,6 +114,15 @@ typedef enum _MetaKmsConnectorColorspace
|
||||
META_KMS_CONNECTOR_COLORSPACE_UNKNOWN,
|
||||
} MetaKmsConnectorColorspace;
|
||||
|
||||
typedef enum _MetaKmsConnectorBroadcastRGB
|
||||
{
|
||||
META_KMS_CONNECTOR_BROADCAST_RGB_AUTOMATIC = 0,
|
||||
META_KMS_CONNECTOR_BROADCAST_RGB_FULL,
|
||||
META_KMS_CONNECTOR_BROADCAST_RGB_LIMITED_16_235,
|
||||
META_KMS_CONNECTOR_BROADCAST_RGB_N_PROPS,
|
||||
META_KMS_CONNECTOR_BROADCAST_RGB_UNKNOWN,
|
||||
} MetaKmsConnectorBroadcastRGB;
|
||||
|
||||
uint32_t meta_kms_connector_get_prop_id (MetaKmsConnector *connector,
|
||||
MetaKmsConnectorProp prop);
|
||||
|
||||
@ -141,6 +151,8 @@ gboolean meta_kms_connector_is_same_as (MetaKmsConnector *connector,
|
||||
|
||||
uint64_t meta_output_color_space_to_drm_color_space (MetaOutputColorspace color_space);
|
||||
|
||||
uint64_t meta_output_rgb_range_to_drm_broadcast_rgb (MetaOutputRGBRange rgb_range);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_set_drm_hdr_metadata (MetaOutputHdrMetadata *metadata,
|
||||
struct hdr_output_metadata *drm_metadata);
|
||||
|
@ -56,6 +56,7 @@ typedef struct _MetaKmsConnectorPropTable
|
||||
MetaKmsEnum scaling_mode_enum[META_KMS_CONNECTOR_SCALING_MODE_N_PROPS];
|
||||
MetaKmsEnum panel_orientation_enum[META_KMS_CONNECTOR_PANEL_ORIENTATION_N_PROPS];
|
||||
MetaKmsEnum colorspace_enum[META_KMS_CONNECTOR_COLORSPACE_N_PROPS];
|
||||
MetaKmsEnum broadcast_rgb_enum[META_KMS_CONNECTOR_BROADCAST_RGB_N_PROPS];
|
||||
} MetaKmsConnectorPropTable;
|
||||
|
||||
struct _MetaKmsConnector
|
||||
@ -253,6 +254,13 @@ meta_kms_connector_is_hdr_metadata_supported (MetaKmsConnector *connector)
|
||||
return connector->current_state->hdr.supported;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_connector_is_broadcast_rgb_supported (MetaKmsConnector *connector,
|
||||
MetaOutputRGBRange broadcast_rgb)
|
||||
{
|
||||
return !!(connector->current_state->broadcast_rgb.supported & (1 << broadcast_rgb));
|
||||
}
|
||||
|
||||
static void
|
||||
set_panel_orientation (MetaKmsConnectorState *state,
|
||||
MetaKmsProp *panel_orientation)
|
||||
@ -355,6 +363,53 @@ meta_output_color_space_to_drm_color_space (MetaOutputColorspace color_space)
|
||||
}
|
||||
}
|
||||
|
||||
static MetaOutputRGBRange
|
||||
drm_broadcast_rgb_to_output_rgb_range (uint64_t drm_broadcast_rgb)
|
||||
{
|
||||
switch (drm_broadcast_rgb)
|
||||
{
|
||||
case META_KMS_CONNECTOR_BROADCAST_RGB_AUTOMATIC:
|
||||
return META_OUTPUT_RGB_RANGE_AUTO;
|
||||
case META_KMS_CONNECTOR_BROADCAST_RGB_FULL:
|
||||
return META_OUTPUT_RGB_RANGE_FULL;
|
||||
case META_KMS_CONNECTOR_BROADCAST_RGB_LIMITED_16_235:
|
||||
return META_OUTPUT_RGB_RANGE_LIMITED;
|
||||
default:
|
||||
return META_OUTPUT_RGB_RANGE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
supported_drm_broadcast_rgb_to_output_rgb_range (uint64_t drm_support)
|
||||
{
|
||||
uint64_t supported = 0;
|
||||
|
||||
if (drm_support & (1 << META_KMS_CONNECTOR_BROADCAST_RGB_AUTOMATIC))
|
||||
supported |= (1 << META_OUTPUT_RGB_RANGE_AUTO);
|
||||
if (drm_support & (1 << META_KMS_CONNECTOR_BROADCAST_RGB_FULL))
|
||||
supported |= (1 << META_OUTPUT_RGB_RANGE_FULL);
|
||||
if (drm_support & (1 << META_KMS_CONNECTOR_BROADCAST_RGB_LIMITED_16_235))
|
||||
supported |= (1 << META_OUTPUT_RGB_RANGE_LIMITED);
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
meta_output_rgb_range_to_drm_broadcast_rgb (MetaOutputRGBRange rgb_range)
|
||||
{
|
||||
switch (rgb_range)
|
||||
{
|
||||
case META_OUTPUT_RGB_RANGE_FULL:
|
||||
return META_KMS_CONNECTOR_BROADCAST_RGB_FULL;
|
||||
case META_OUTPUT_RGB_RANGE_LIMITED:
|
||||
return META_KMS_CONNECTOR_BROADCAST_RGB_LIMITED_16_235;
|
||||
case META_OUTPUT_RGB_RANGE_UNKNOWN:
|
||||
case META_OUTPUT_RGB_RANGE_AUTO:
|
||||
default:
|
||||
return META_KMS_CONNECTOR_BROADCAST_RGB_AUTOMATIC;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
state_set_properties (MetaKmsConnectorState *state,
|
||||
MetaKmsImplDevice *impl_device,
|
||||
@ -408,6 +463,15 @@ state_set_properties (MetaKmsConnectorState *state,
|
||||
state->colorspace.supported =
|
||||
supported_drm_color_spaces_to_output_color_spaces (prop->supported_variants);
|
||||
}
|
||||
|
||||
prop = &props[META_KMS_CONNECTOR_PROP_BROADCAST_RGB];
|
||||
if (prop->prop_id)
|
||||
{
|
||||
state->broadcast_rgb.value =
|
||||
drm_broadcast_rgb_to_output_rgb_range (prop->value);
|
||||
state->broadcast_rgb.supported =
|
||||
supported_drm_broadcast_rgb_to_output_rgb_range (prop->supported_variants);
|
||||
}
|
||||
}
|
||||
|
||||
static CoglSubpixelOrder
|
||||
@ -1013,6 +1077,10 @@ meta_kms_connector_state_changes (MetaKmsConnectorState *state,
|
||||
!hdr_metadata_equal (&state->hdr.value, &new_state->hdr.value))
|
||||
return META_KMS_RESOURCE_CHANGE_FULL;
|
||||
|
||||
if (state->broadcast_rgb.value != new_state->broadcast_rgb.value ||
|
||||
state->broadcast_rgb.supported != new_state->broadcast_rgb.supported)
|
||||
return META_KMS_RESOURCE_CHANGE_FULL;
|
||||
|
||||
if (state->privacy_screen_state != new_state->privacy_screen_state)
|
||||
return META_KMS_RESOURCE_CHANGE_PRIVACY_SCREEN;
|
||||
|
||||
@ -1224,6 +1292,14 @@ meta_kms_connector_predict_state_in_impl (MetaKmsConnector *connector,
|
||||
connector));
|
||||
current_state->hdr.value = connector_update->hdr.value;
|
||||
}
|
||||
|
||||
if (connector_update->broadcast_rgb.has_update)
|
||||
{
|
||||
g_warn_if_fail (meta_kms_connector_is_broadcast_rgb_supported (
|
||||
connector,
|
||||
connector_update->broadcast_rgb.value));
|
||||
current_state->broadcast_rgb.value = connector_update->broadcast_rgb.value;
|
||||
}
|
||||
}
|
||||
|
||||
sync_fd_held (connector, connector->impl_device);
|
||||
@ -1350,6 +1426,14 @@ init_properties (MetaKmsConnector *connector,
|
||||
.name = "HDR_OUTPUT_METADATA",
|
||||
.type = DRM_MODE_PROP_BLOB,
|
||||
},
|
||||
[META_KMS_CONNECTOR_PROP_BROADCAST_RGB] =
|
||||
{
|
||||
.name = "Broadcast RGB",
|
||||
.type = DRM_MODE_PROP_ENUM,
|
||||
.enum_values = prop_table->broadcast_rgb_enum,
|
||||
.num_enum_values = META_KMS_CONNECTOR_BROADCAST_RGB_N_PROPS,
|
||||
.default_value = META_KMS_CONNECTOR_BROADCAST_RGB_UNKNOWN,
|
||||
},
|
||||
},
|
||||
.dpms_enum = {
|
||||
[META_KMS_CONNECTOR_DPMS_ON] =
|
||||
@ -1521,6 +1605,20 @@ init_properties (MetaKmsConnector *connector,
|
||||
.name = "DCI-P3_RGB_Theater",
|
||||
},
|
||||
},
|
||||
.broadcast_rgb_enum = {
|
||||
[META_KMS_CONNECTOR_BROADCAST_RGB_AUTOMATIC] =
|
||||
{
|
||||
.name = "Automatic",
|
||||
},
|
||||
[META_KMS_CONNECTOR_BROADCAST_RGB_FULL] =
|
||||
{
|
||||
.name = "Full",
|
||||
},
|
||||
[META_KMS_CONNECTOR_BROADCAST_RGB_LIMITED_16_235] =
|
||||
{
|
||||
.name = "Limited 16:235",
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,11 @@ typedef struct _MetaKmsConnectorState
|
||||
gboolean supported;
|
||||
gboolean unknown;
|
||||
} hdr;
|
||||
|
||||
struct {
|
||||
MetaOutputRGBRange value;
|
||||
uint64_t supported;
|
||||
} broadcast_rgb;
|
||||
} MetaKmsConnectorState;
|
||||
|
||||
META_EXPORT_TEST
|
||||
@ -98,4 +103,7 @@ const MetaKmsRange * meta_kms_connector_get_max_bpc (MetaKmsConnector *connector
|
||||
gboolean meta_kms_connector_is_color_space_supported (MetaKmsConnector *connector,
|
||||
MetaOutputColorspace color_space);
|
||||
|
||||
gboolean meta_kms_connector_is_broadcast_rgb_supported (MetaKmsConnector *connector,
|
||||
MetaOutputRGBRange broadcast_rgb);
|
||||
|
||||
gboolean meta_kms_connector_is_hdr_metadata_supported (MetaKmsConnector *connector);
|
||||
|
@ -292,6 +292,25 @@ process_connector_update (MetaKmsImplDevice *impl_device,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (connector_update->broadcast_rgb.has_update)
|
||||
{
|
||||
MetaOutputRGBRange rgb_range = connector_update->broadcast_rgb.value;
|
||||
uint64_t value = meta_output_rgb_range_to_drm_broadcast_rgb (rgb_range);
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[atomic] Setting Broadcast RGB to %u on connector %u (%s)",
|
||||
rgb_range,
|
||||
meta_kms_connector_get_id (connector),
|
||||
meta_kms_impl_device_get_path (impl_device));
|
||||
|
||||
if (!add_connector_property (impl_device,
|
||||
connector, req,
|
||||
META_KMS_CONNECTOR_PROP_BROADCAST_RGB,
|
||||
value,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,11 @@ typedef struct _MetaKmsConnectorUpdate
|
||||
gboolean has_update;
|
||||
MetaOutputHdrMetadata value;
|
||||
} hdr;
|
||||
|
||||
struct {
|
||||
gboolean has_update;
|
||||
MetaOutputRGBRange value;
|
||||
} broadcast_rgb;
|
||||
} MetaKmsConnectorUpdate;
|
||||
|
||||
typedef struct _MetaKmsPageFlipListener
|
||||
|
@ -444,8 +444,6 @@ meta_kms_update_set_color_space (MetaKmsUpdate *update,
|
||||
MetaKmsConnectorUpdate *connector_update;
|
||||
|
||||
g_assert (meta_kms_connector_get_device (connector) == update->device);
|
||||
g_return_if_fail (meta_kms_connector_is_color_space_supported (connector,
|
||||
color_space));
|
||||
|
||||
connector_update = ensure_connector_update (update, connector);
|
||||
connector_update->colorspace.has_update = TRUE;
|
||||
@ -470,6 +468,22 @@ meta_kms_update_set_hdr_metadata (MetaKmsUpdate *update,
|
||||
update->needs_modeset = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_update_set_broadcast_rgb (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector,
|
||||
MetaOutputRGBRange rgb_range)
|
||||
{
|
||||
MetaKmsConnectorUpdate *connector_update;
|
||||
|
||||
g_assert (meta_kms_connector_get_device (connector) == update->device);
|
||||
g_return_if_fail (meta_kms_connector_is_broadcast_rgb_supported (connector,
|
||||
rgb_range));
|
||||
|
||||
connector_update = ensure_connector_update (update, connector);
|
||||
connector_update->broadcast_rgb.has_update = TRUE;
|
||||
connector_update->broadcast_rgb.value = rgb_range;
|
||||
}
|
||||
|
||||
static MetaKmsCrtcColorUpdate *
|
||||
ensure_color_update (MetaKmsUpdate *update,
|
||||
MetaKmsCrtc *crtc)
|
||||
|
@ -134,6 +134,10 @@ void meta_kms_update_set_hdr_metadata (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector,
|
||||
MetaOutputHdrMetadata *metadata);
|
||||
|
||||
void meta_kms_update_set_broadcast_rgb (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector,
|
||||
MetaOutputRGBRange rgb_range);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_update_set_power_save (MetaKmsUpdate *update);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user