fix: advertise a render node as the dmabuf main device
On split display/render platforms (vc4 display + v3d render) the GLES2 renderer resolves to the display node, which has no 3D engine -- and wlroots then advertises that node as the dmabuf main device, so Mesa clients try to render there and fall back to llvmpipe (mpv goes software, drops hundreds of frames). Discover a real render node under /dev/dri and override the advertised main device with it; rendering, allocation and scanout paths are untouched, and a missing node falls back to the previous renderer-derived behavior.
This commit is contained in:
parent
689ab662f8
commit
31f413ff9f
2 changed files with 67 additions and 1 deletions
66
kick.c
66
kick.c
|
|
@ -39,10 +39,14 @@ const char *__ubsan_default_options(void) {
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
|
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
|
@ -13124,6 +13128,46 @@ static bool started_on_console(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Split display/render platforms (vc4 display + v3d render): the GLES2
|
||||||
|
renderer resolves to the display node, which has no 3D engine -- and
|
||||||
|
wlroots would then advertise that node as the dmabuf main device, so
|
||||||
|
Mesa clients try to render there and fall back to llvmpipe (mpv goes
|
||||||
|
software). Find a real render node and report it instead; rendering,
|
||||||
|
allocation and scanout paths are untouched, only the advertisement.
|
||||||
|
Skips software rasterizers; the caller keeps the renderer-derived
|
||||||
|
device when nothing usable is found. */
|
||||||
|
static bool dmabuf_render_node(dev_t *dev_out) {
|
||||||
|
DIR *d = opendir("/dev/dri");
|
||||||
|
if (!d)
|
||||||
|
return false;
|
||||||
|
bool found = false;
|
||||||
|
struct dirent *e;
|
||||||
|
while ((e = readdir(d)) != NULL) {
|
||||||
|
if (strncmp(e->d_name, "renderD", 7) != 0)
|
||||||
|
continue;
|
||||||
|
char path[16 + NAME_MAX];
|
||||||
|
snprintf(path, sizeof(path), "/dev/dri/%s", e->d_name);
|
||||||
|
int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
continue;
|
||||||
|
drmVersionPtr v = drmGetVersion(fd);
|
||||||
|
bool hw = v && v->name && strcmp(v->name, "swrast") != 0 &&
|
||||||
|
strcmp(v->name, "kmsro") != 0;
|
||||||
|
struct stat st;
|
||||||
|
if (hw && fstat(fd, &st) == 0) {
|
||||||
|
*dev_out = st.st_rdev;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (v)
|
||||||
|
drmFreeVersion(v);
|
||||||
|
close(fd);
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
snprintf(kick_socket, sizeof(kick_socket), "kick-%d",
|
snprintf(kick_socket, sizeof(kick_socket), "kick-%d",
|
||||||
(int)getpid());
|
(int)getpid());
|
||||||
|
|
@ -13634,7 +13678,27 @@ int main(int argc, char *argv[]) {
|
||||||
server.renderer);
|
server.renderer);
|
||||||
wlr_subcompositor_create(server.wl_display);
|
wlr_subcompositor_create(server.wl_display);
|
||||||
wlr_shm_create_with_renderer(server.wl_display, 1, server.renderer);
|
wlr_shm_create_with_renderer(server.wl_display, 1, server.renderer);
|
||||||
wlr_linux_dmabuf_v1_create_with_renderer(server.wl_display, 5, server.renderer);
|
/* Advertise a render node, not the display node, as the dmabuf main
|
||||||
|
device (see dmabuf_render_node): on failure keep wlroots' default
|
||||||
|
renderer-derived device rather than dropping dmabuf entirely. */
|
||||||
|
struct wlr_linux_dmabuf_feedback_v1_init_options dmabuf_opts = {
|
||||||
|
.main_renderer = server.renderer,
|
||||||
|
};
|
||||||
|
struct wlr_linux_dmabuf_feedback_v1 dmabuf_feedback = {0};
|
||||||
|
if (wlr_linux_dmabuf_feedback_v1_init_with_options(&dmabuf_feedback,
|
||||||
|
&dmabuf_opts)) {
|
||||||
|
dev_t render_dev;
|
||||||
|
if (dmabuf_render_node(&render_dev)) {
|
||||||
|
dmabuf_feedback.main_device = render_dev;
|
||||||
|
kick_log(KICK_LOG_INFO, "[dmabuf] main device %u:%u (render node)\n",
|
||||||
|
major(render_dev), minor(render_dev));
|
||||||
|
}
|
||||||
|
wlr_linux_dmabuf_v1_create(server.wl_display, 5, &dmabuf_feedback);
|
||||||
|
wlr_linux_dmabuf_feedback_v1_finish(&dmabuf_feedback);
|
||||||
|
} else {
|
||||||
|
wlr_linux_dmabuf_v1_create_with_renderer(server.wl_display, 5,
|
||||||
|
server.renderer);
|
||||||
|
}
|
||||||
wlr_data_device_manager_create(server.wl_display);
|
wlr_data_device_manager_create(server.wl_display);
|
||||||
wlr_ext_data_control_manager_v1_create(server.wl_display, 1);
|
wlr_ext_data_control_manager_v1_create(server.wl_display, 1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ deps = [
|
||||||
dependency('pixman-1'),
|
dependency('pixman-1'),
|
||||||
# Server-side/client-side window decorations via libdecor (nested mode).
|
# Server-side/client-side window decorations via libdecor (nested mode).
|
||||||
dependency('libdecor-0'),
|
dependency('libdecor-0'),
|
||||||
|
# libdrm for render-node discovery (dmabuf main device override).
|
||||||
|
dependency('libdrm'),
|
||||||
]
|
]
|
||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue