DRM: Add support for HDMI content type

Some monitors expose a selector for the kind of content that will get
displayed, allowing them to optimise their settings for this particular
content type.

I got access to such a monitor, sadly even setting it to game mode
didn’t lower its atrocious latency, but drm_info[1] reports it to be set
correctly so hopefully it’ll work better with other monitors.

[1] https://github.com/ascent12/drm_info

Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This commit is contained in:
Emmanuel Gil Peyrot 2021-10-02 17:10:37 +02:00 committed by Daniel Stone
parent 2e39630214
commit 1c5ce4c2cc
6 changed files with 100 additions and 0 deletions

View file

@ -2024,6 +2024,7 @@ drm_backend_output_configure(struct weston_output *output,
char *s;
char *modeline = NULL;
char *gbm_format = NULL;
char *content_type = NULL;
char *seat = NULL;
api = weston_drm_output_get_api(output->compositor);
@ -2080,6 +2081,12 @@ drm_backend_output_configure(struct weston_output *output,
api->set_gbm_format(output, gbm_format);
free(gbm_format);
weston_config_section_get_string(section,
"content-type", &content_type, NULL);
if (api->set_content_type(output, content_type) < 0)
return -1;
free(content_type);
weston_config_section_get_string(section, "seat", &seat, "");
api->set_seat(output, seat);

View file

@ -93,6 +93,17 @@ struct weston_drm_output_api {
* This can be set only while the output is disabled.
*/
void (*set_max_bpc)(struct weston_output *output, unsigned max_bpc);
/** The content type primarily used on the output. Valid values are:
* - NULL or "no data" - No information is provided about the usage of the
* output
* - "graphics"
* - "photo"
* - "cinema"
* - "game"
*/
int (*set_content_type)(struct weston_output *output,
const char *content_type);
};
static inline const struct weston_drm_output_api *

View file

@ -188,6 +188,7 @@ enum wdrm_connector_property {
WDRM_CONNECTOR_PANEL_ORIENTATION,
WDRM_CONNECTOR_HDR_OUTPUT_METADATA,
WDRM_CONNECTOR_MAX_BPC,
WDRM_CONNECTOR_CONTENT_TYPE,
WDRM_CONNECTOR__COUNT
};
@ -220,6 +221,15 @@ enum wdrm_panel_orientation {
WDRM_PANEL_ORIENTATION__COUNT
};
enum wdrm_content_type {
WDRM_CONTENT_TYPE_NO_DATA = 0,
WDRM_CONTENT_TYPE_GRAPHICS,
WDRM_CONTENT_TYPE_PHOTO,
WDRM_CONTENT_TYPE_CINEMA,
WDRM_CONTENT_TYPE_GAME,
WDRM_CONTENT_TYPE__COUNT
};
/**
* List of properties attached to DRM CRTCs
*/
@ -587,6 +597,8 @@ struct drm_output {
void (*virtual_destroy)(struct weston_output *base);
submit_frame_cb virtual_submit_frame;
enum wdrm_content_type content_type;
};
void

View file

@ -1425,6 +1425,38 @@ drm_output_set_max_bpc(struct weston_output *base, unsigned max_bpc)
output->max_bpc = max_bpc;
}
static const struct { const char *name; uint32_t token; } content_types[] = {
{ "no data", WDRM_CONTENT_TYPE_NO_DATA },
{ "graphics", WDRM_CONTENT_TYPE_GRAPHICS },
{ "photo", WDRM_CONTENT_TYPE_PHOTO },
{ "cinema", WDRM_CONTENT_TYPE_CINEMA },
{ "game", WDRM_CONTENT_TYPE_GAME },
};
static int
drm_output_set_content_type(struct weston_output *base,
const char *content_type)
{
unsigned int i;
struct drm_output *output = to_drm_output(base);
if (content_type == NULL) {
output->content_type = WDRM_CONTENT_TYPE_NO_DATA;
return 0;
}
for (i = 0; i < ARRAY_LENGTH(content_types); i++)
if (strcmp(content_types[i].name, content_type) == 0) {
output->content_type = content_types[i].token;
return 0;
}
weston_log("Error: unknown content-type for output %s: \"%s\"\n",
base->name, content_type);
output->content_type = WDRM_CONTENT_TYPE_NO_DATA;
return -1;
}
static int
drm_output_init_gamma_size(struct drm_output *output)
{
@ -3084,6 +3116,7 @@ static const struct weston_drm_output_api api = {
drm_output_set_gbm_format,
drm_output_set_seat,
drm_output_set_max_bpc,
drm_output_set_content_type,
};
static struct drm_backend *

View file

@ -119,6 +119,14 @@ struct drm_property_enum_info panel_orientation_enums[] = {
[WDRM_PANEL_ORIENTATION_RIGHT_SIDE_UP] = { .name = "Right Side Up", },
};
struct drm_property_enum_info content_type_enums[] = {
[WDRM_CONTENT_TYPE_NO_DATA] = { .name = "No Data", },
[WDRM_CONTENT_TYPE_GRAPHICS] = { .name = "Graphics", },
[WDRM_CONTENT_TYPE_PHOTO] = { .name = "Photo", },
[WDRM_CONTENT_TYPE_CINEMA] = { .name = "Cinema", },
[WDRM_CONTENT_TYPE_GAME] = { .name = "Game", },
};
const struct drm_property_info connector_props[] = {
[WDRM_CONNECTOR_EDID] = { .name = "EDID" },
[WDRM_CONNECTOR_DPMS] = {
@ -147,6 +155,11 @@ const struct drm_property_info connector_props[] = {
.name = "HDR_OUTPUT_METADATA",
},
[WDRM_CONNECTOR_MAX_BPC] = { .name = "max bpc", },
[WDRM_CONNECTOR_CONTENT_TYPE] = {
.name = "content type",
.enum_values = content_type_enums,
.num_enum_values = WDRM_CONTENT_TYPE__COUNT,
},
};
const struct drm_property_info crtc_props[] = {
@ -939,6 +952,24 @@ drm_connector_set_max_bpc(struct drm_connector *connector,
WDRM_CONNECTOR_MAX_BPC, max_bpc);
}
static int
drm_connector_set_content_type(struct drm_connector *connector,
enum wdrm_content_type content_type,
drmModeAtomicReq *req)
{
struct drm_property_enum_info *enum_info;
uint64_t prop_val;
struct drm_property_info *props = connector->props;
if (!drm_connector_has_prop(connector, WDRM_CONNECTOR_CONTENT_TYPE))
return 0;
enum_info = props[WDRM_CONNECTOR_CONTENT_TYPE].enum_values;
prop_val = enum_info[content_type].value;
return connector_add_prop(req, connector,
WDRM_CONNECTOR_CONTENT_TYPE, prop_val);
}
static int
drm_output_apply_state_atomic(struct drm_output_state *state,
drmModeAtomicReq *req,
@ -992,6 +1023,8 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
wl_list_for_each(head, &output->base.head_list, base.output_link) {
drm_connector_set_hdcp_property(&head->connector,
state->protection, req);
ret |= drm_connector_set_content_type(&head->connector,
output->content_type, req);
if (drm_connector_has_prop(&head->connector,
WDRM_CONNECTOR_HDR_OUTPUT_METADATA)) {

View file

@ -543,6 +543,10 @@ content-protection can actually be realized, only if the hardware
(source and sink) support HDCP, and the backend has the implementation
of content-protection protocol. Currently, HDCP is supported by drm-backend.
.TP 7
.BI "content-type=" content_type
The type of the content being primarily displayed to this output. Can be "no
data" (default), "graphics", "photo", "cinema" or "game".
.TP 7
.BI "app-ids=" app-id[,app_id]*
A comma separated list of the IDs of applications to place on this output.
These IDs should match the application IDs as set with the xdg_shell.set_app_id