History

wayland: properly use tranche_formats when getting compositor formats

It's a bit roundabout, but we were doing this incorrectly before. The format table alone isn't good enough because it is possible the the compositor may advertise different formats for a specific device which is a subset of the format table. What we need to do is add formats based on the array in tranche_formats. Note that it is possible for the compositor to send multiple tranches (was not able to simulate this but it's allowed by the protocol). For mpv, we only care about the very first one which is supposed to be the most preferred one. The compositor can also send the entire chain of events (main device, format_table, tranches, etc.) all over again. We handle this in the wayland code, but handling this in mpv's core code isn't done. e.g. say a format in use was suddenly no longer supported. We ideally should do a full reconfig in this case, but that gets complicated and is pretty niche so save that for another day. Multiple GPUs isn't taken into account either. We just pick the first one. Not strictly correct, but close enough for us. Fixes #14544.

Dudemanguy committed 2 years ago

Commit 7a803301 parent 4d09cde3 files · +56 −12Browse files

Unified · Split

3 files
  1. video/out/wayland_common.c +45 −9
  2. video/out/wayland_common.h +9 −1
  3. video/out/wldmabuf/ra_wldmabuf.c +2 −2
video/out/wayland_common.c+45−9
@@ -1363,6 +1363,12 @@ static void format_table(void *data, · 1362 unmodified lines
13631363 {
13641364 struct vo_wayland_state *wl = data;
13651365
1366+ if (wl->compositor_format_size) {
1367+ munmap(wl->compositor_format_map, wl->compositor_format_size);
1368+ wl->compositor_format_map = NULL;
1369+ wl->compositor_format_size = 0;
1370+ }
1371+
13661372 void *map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
13671373 close(fd);
13681374
@@ -1377,32 +1383,62 @@ static void main_device(void *data, · 8 unmodified lines
13771383 struct wl_array *device)
13781384 {
13791385 struct vo_wayland_state *wl = data;
1386+ wl->add_tranche = true;
13801387
1381− // Despite being an array, the protocol specifically states there can only be
1382− // one main device so break as soon as we get one.
1383− dev_t *id;
1384− wl_array_for_each(id, device) {
1385− memcpy(&wl->main_device_id, id, sizeof(dev_t));
1386− break;
1387− }
1388− get_gpu_drm_formats(wl);
13891388 }
13901389
13911390 static void tranche_done(void *data,
13921391 struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
13931392 {
1393+ struct vo_wayland_state *wl = data;
1394+ wl->add_tranche = false;
13941395 }
13951396
13961397 static void tranche_target_device(void *data,
13971398 struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
13981399 struct wl_array *device)
13991400 {
1401+ struct vo_wayland_state *wl = data;
1402+ // Only use the first tranche device we get.
1403+ if (wl->add_tranche) {
1404+ dev_t *id;
1405+ wl_array_for_each(id, device) {
1406+ memcpy(&wl->target_device_id, id, sizeof(dev_t));
1407+ break;
1408+ }
1409+ get_gpu_drm_formats(wl);
1410+ }
14001411 }
14011412
14021413 static void tranche_formats(void *data,
14031414 struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
14041415 struct wl_array *indices)
14051416 {
1417+ struct vo_wayland_state *wl = data;
1418+
1419+ // Only grab formats from the first tranche and ignore the rest.
1420+ if (!wl->add_tranche)
1421+ return;
1422+
1423+ // Should never happen.
1424+ if (!wl->compositor_format_map) {
1425+ MP_WARN(wl, "Compositor did not send a format and modifier table!\n");
1426+ return;
1427+ }
1428+
1429+ const compositor_format *formats = wl->compositor_format_map;
1430+ MP_RESIZE_ARRAY(wl, wl->compositor_formats, indices->size);
1431+ wl->num_compositor_formats = 0;
1432+ uint16_t *index;
1433+ wl_array_for_each(index, indices) {
1434+ MP_TARRAY_APPEND(wl, wl->compositor_formats, wl->num_compositor_formats,
1435+ (struct drm_format) {
1436+ formats[*index].format,
1437+ formats[*index].modifier,
1438+ });
1439+ MP_DBG(wl, "Compositor supports drm format: '%s(%016" PRIx64 ")'\n",
1440+ mp_tag_str(formats[*index].format), formats[*index].modifier);
1441+ }
14061442 }
14071443
14081444 static void tranche_flags(void *data,
@@ -1799,7 +1835,7 @@ static void get_gpu_drm_formats(struct vo_wayland_state *wl) · 390 unmodified lines
17991835 drmModePlaneRes *res = NULL;
18001836 drmModePlane *plane = NULL;
18011837
1802− if (drmGetDeviceFromDevId(wl->main_device_id, 0, &device) != 0) {
1838+ if (drmGetDeviceFromDevId(wl->target_device_id, 0, &device) != 0) {
18031839 MP_WARN(wl, "Unable to get drm device from device id: %s\n", mp_strerror(errno));
18041840 goto done;
18051841 }
video/out/wayland_common.h+9−1
@@ -30,6 +30,11 @@ typedef struct { · 29 unmodified lines
3030 uint64_t modifier;
3131 } compositor_format;
3232
33+struct drm_format {
34+ uint32_t format;
35+ uint64_t modifier;
36+};
37+
3338 struct vo_wayland_state {
3439 struct m_config_cache *opts_cache;
3540 struct mp_log *log;
@@ -102,11 +107,14 @@ struct vo_wayland_state { · 66 unmodified lines
102107 struct zwp_idle_inhibitor_v1 *idle_inhibitor;
103108
104109 /* linux-dmabuf */
105− dev_t main_device_id;
110+ dev_t target_device_id;
106111 struct zwp_linux_dmabuf_v1 *dmabuf;
107112 struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback;
113+ bool add_tranche;
108114 compositor_format *compositor_format_map;
109115 uint32_t compositor_format_size;
116+ struct drm_format *compositor_formats;
117+ int num_compositor_formats;
110118 uint32_t *gpu_formats;
111119 int num_gpu_formats;
112120
video/out/wldmabuf/ra_wldmabuf.c+2−2
@@ -32,7 +32,7 @@ bool ra_compatible_format(struct ra *ra, int imgfmt, uint32_t drm_format, uint64 · 31 unmodified lines
3232 {
3333 struct priv *p = ra->priv;
3434 struct vo_wayland_state *wl = p->vo->wl;
35− const compositor_format *formats = wl->compositor_format_map;
35+ struct drm_format *formats = wl->compositor_formats;
3636
3737
3838 // If we were able to make the DRM query, filter out the GPU formats.
@@ -50,7 +50,7 @@ bool ra_compatible_format(struct ra *ra, int imgfmt, uint32_t drm_format, uint64 · 11 unmodified lines
5050 }
5151
5252 // Always check if the compositor supports the format.
53− for (int i = 0; i < wl->compositor_format_size / sizeof(compositor_format); i++) {
53+ for (int i = 0; i < wl->num_compositor_formats; ++i) {
5454 if (drm_format == formats[i].format && modifier == formats[i].modifier)
5555 return true;
5656 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t