mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-07 11:58:03 +02:00
drm: Look for YUV420 capabilities in the mode list
For now, we tag modes with their YUV capabilities manually here, and print that. Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
3b33d4fab7
commit
d9238bca6a
2 changed files with 123 additions and 23 deletions
|
|
@ -294,6 +294,8 @@ struct drm_mode {
|
|||
drmModeModeInfo mode_info;
|
||||
uint32_t blob_id;
|
||||
uint8_t vic;
|
||||
bool can_yuv420;
|
||||
bool must_yuv420;
|
||||
};
|
||||
|
||||
enum drm_fb_type {
|
||||
|
|
@ -577,6 +579,10 @@ struct drm_head {
|
|||
|
||||
void *display_data; /**< EDID or DisplayID blob */
|
||||
size_t display_data_len; /**< bytes */
|
||||
|
||||
bool yuv420_vics;
|
||||
bool can_yuv420_vic_map[256];
|
||||
bool must_yuv420_vic_map[256];
|
||||
};
|
||||
|
||||
struct drm_crtc {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ struct drm_head_info {
|
|||
/* The monitor supported color foramts, combination of
|
||||
* enum_weston_color_format bits. */
|
||||
uint32_t color_format_mask;
|
||||
|
||||
bool yuv420_vics;
|
||||
bool must_yuv420_vic_map[256];
|
||||
bool can_yuv420_vic_map[256];
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -309,25 +313,91 @@ get_colorimetry_mask(const struct di_info *info)
|
|||
return mask;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_yuv420_cap_map(const struct di_edid_cta *cta)
|
||||
/* Much of the yuv420 capability check code is duplicated or barely modified
|
||||
* from:
|
||||
* libdisplay-info (https://gitlab.freedesktop.org/emersion/libdisplay-info)
|
||||
*
|
||||
* However, bugs should be considered an original work of the Weston project.
|
||||
*/
|
||||
static void
|
||||
add_yuv420_only_block(struct drm_head_info *dhi,
|
||||
const struct di_edid_cta *cta,
|
||||
const struct di_cta_data_block *yuv420_data_block)
|
||||
{
|
||||
const struct di_cta_data_block *const *data_blocks;
|
||||
enum di_cta_data_block_tag db_tag;
|
||||
int i;
|
||||
const struct di_cta_svd *const *svds;
|
||||
int i;
|
||||
|
||||
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
|
||||
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
|
||||
return true;
|
||||
svds = di_cta_data_block_get_ycbcr420_svds(yuv420_data_block);
|
||||
if (!svds)
|
||||
return;
|
||||
|
||||
for (i = 0; svds[i] != NULL; i++) {
|
||||
dhi->yuv420_vics = true;
|
||||
dhi->must_yuv420_vic_map[svds[i]->vic] = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_map_to_yuv420_caps(struct drm_head_info *dhi,
|
||||
const struct di_edid_cta *cta,
|
||||
const struct di_cta_data_block *yuv420_cap_map_block)
|
||||
{
|
||||
const struct di_cta_ycbcr420_cap_map *ycbcr420_cap_map;
|
||||
const struct di_cta_data_block *const *data_blocks;
|
||||
const struct di_cta_data_block *data_block;
|
||||
const struct di_cta_svd *const *svds = NULL;
|
||||
enum di_cta_data_block_tag db_tag;
|
||||
int i, j, svd_index = 0;
|
||||
|
||||
ycbcr420_cap_map = di_cta_data_block_get_ycbcr420_cap_map(yuv420_cap_map_block);
|
||||
|
||||
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||
data_block = data_blocks[i];
|
||||
db_tag = di_cta_data_block_get_tag(data_block);
|
||||
if (db_tag != DI_CTA_DATA_BLOCK_VIDEO)
|
||||
continue;
|
||||
svds = di_cta_data_block_get_svds(data_block);
|
||||
|
||||
for (j = 0; svds[j] != NULL; j++) {
|
||||
if (di_cta_ycbcr420_cap_map_supported(ycbcr420_cap_map, svd_index)) {
|
||||
dhi->yuv420_vics = true;
|
||||
dhi->can_yuv420_vic_map[svds[j]->vic] = true;
|
||||
}
|
||||
svd_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_cta_to_yuv420_caps(struct drm_head_info *dhi,
|
||||
const struct di_edid_cta *cta)
|
||||
{
|
||||
const struct di_cta_data_block *const *data_blocks;
|
||||
const struct di_cta_data_block *data_block;
|
||||
enum di_cta_data_block_tag db_tag;
|
||||
int i;
|
||||
|
||||
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||
data_block = data_blocks[i];
|
||||
db_tag = di_cta_data_block_get_tag(data_block);
|
||||
switch (db_tag) {
|
||||
case DI_CTA_DATA_BLOCK_YCBCR420:
|
||||
add_yuv420_only_block(dhi, cta, data_block);
|
||||
break;
|
||||
case DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP:
|
||||
add_map_to_yuv420_caps(dhi, cta, data_block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_color_format_mask(const struct di_info *info)
|
||||
get_color_format_mask(struct drm_head_info *dhi,
|
||||
const struct di_info *info)
|
||||
{
|
||||
const struct di_edid *edid = di_info_get_edid(info);
|
||||
const struct di_edid_color_encoding_formats *fmts =
|
||||
|
|
@ -364,18 +434,16 @@ get_color_format_mask(const struct di_info *info)
|
|||
if (cta_flags->ycc422)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||
|
||||
/* FIXME: YUV420 detection is really complicated,
|
||||
* do it properly at some point...
|
||||
*/
|
||||
if (has_yuv420_cap_map(cta))
|
||||
mask |= WESTON_COLOR_FORMAT_YUV420;
|
||||
|
||||
break;
|
||||
add_cta_to_yuv420_caps(dhi, cta);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dhi->yuv420_vics)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV420;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
|
@ -395,6 +463,10 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dhi->yuv420_vics = 0;
|
||||
memset(dhi->can_yuv420_vic_map, 0, sizeof(dhi->can_yuv420_vic_map));
|
||||
memset(dhi->must_yuv420_vic_map, 0, sizeof(dhi->must_yuv420_vic_map));
|
||||
|
||||
msg = di_info_get_failure_msg(di_ctx);
|
||||
if (msg)
|
||||
weston_log("DRM: EDID for the following head fails conformity:\n%s\n", msg);
|
||||
|
|
@ -404,7 +476,7 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
|||
dhi->serial_number = di_info_get_serial(di_ctx);
|
||||
dhi->eotf_mask = get_eotf_mask(di_ctx);
|
||||
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
|
||||
dhi->color_format_mask = get_color_format_mask(di_ctx);
|
||||
dhi->color_format_mask = get_color_format_mask(dhi, di_ctx);
|
||||
|
||||
return di_ctx;
|
||||
}
|
||||
|
|
@ -622,6 +694,7 @@ match_cta_mode(const drmModeModeInfo *info)
|
|||
static struct drm_mode *
|
||||
drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
|
||||
{
|
||||
struct drm_head *head = to_drm_head(weston_output_get_first_head(&output->base));
|
||||
struct drm_mode *mode;
|
||||
|
||||
mode = malloc(sizeof *mode);
|
||||
|
|
@ -638,6 +711,14 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
|
|||
|
||||
mode->vic = match_cta_mode(info);
|
||||
|
||||
mode->can_yuv420 = false;
|
||||
mode->must_yuv420 = false;
|
||||
if (mode->vic && head->can_yuv420_vic_map[mode->vic])
|
||||
mode->can_yuv420 = true;
|
||||
|
||||
if (mode->vic && head->must_yuv420_vic_map[mode->vic])
|
||||
mode->must_yuv420 = false;
|
||||
|
||||
if (info->type & DRM_MODE_TYPE_PREFERRED)
|
||||
mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||
|
||||
|
|
@ -682,6 +763,8 @@ drm_output_print_modes(struct drm_output *output)
|
|||
const char *aspect_ratio;
|
||||
|
||||
wl_list_for_each(m, &output->base.mode_list, link) {
|
||||
const char *yuv_cap_str;
|
||||
|
||||
dm = to_drm_mode(m);
|
||||
|
||||
aspect_ratio = aspect_ratio_to_string(m->aspect_ratio);
|
||||
|
|
@ -690,14 +773,21 @@ drm_output_print_modes(struct drm_output *output)
|
|||
else
|
||||
weston_log_continue(STAMP_SPACE " ");
|
||||
|
||||
weston_log_continue("%s@%.1f%s%s%s, %.1f MHz\n",
|
||||
yuv_cap_str = NULL;
|
||||
if (dm->must_yuv420)
|
||||
yuv_cap_str = ", YUV420 only";
|
||||
else if (dm->can_yuv420)
|
||||
yuv_cap_str = ", YUV420 optional";
|
||||
|
||||
weston_log_continue("%s@%.1f%s%s%s, %.1f MHz%s\n",
|
||||
dm->mode_info.name, m->refresh / 1000.0,
|
||||
aspect_ratio,
|
||||
m->flags & WL_OUTPUT_MODE_PREFERRED ?
|
||||
", preferred" : "",
|
||||
m->flags & WL_OUTPUT_MODE_CURRENT ?
|
||||
", current" : "",
|
||||
dm->mode_info.clock / 1000.0);
|
||||
dm->mode_info.clock / 1000.0,
|
||||
yuv_cap_str ?: "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -828,6 +918,10 @@ update_head_from_connector(struct drm_head *head)
|
|||
vrr_mode_mask = WESTON_VRR_MODE_GAME;
|
||||
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
|
||||
|
||||
head->yuv420_vics = dhi.yuv420_vics;
|
||||
memcpy(&head->can_yuv420_vic_map, &dhi.can_yuv420_vic_map, sizeof(head->can_yuv420_vic_map));
|
||||
memcpy(&head->must_yuv420_vic_map, &dhi.must_yuv420_vic_map, sizeof(head->must_yuv420_vic_map));
|
||||
|
||||
drm_head_info_fini(&dhi);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue