mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 02:38:04 +02:00
Merge branch 'dmabuf-target-device' into 'main'
Draft: wayland/wsi: linux-dmabuf version 6 See merge request mesa/mesa!33344
This commit is contained in:
commit
6c78782e29
12 changed files with 279 additions and 88 deletions
|
|
@ -48,7 +48,7 @@
|
|||
#include "dri_screen.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
#if HAVE_BIND_WL_DISPLAY
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#include "wayland-drm.h"
|
||||
|
|
|
|||
|
|
@ -285,8 +285,9 @@ struct dri2_egl_display {
|
|||
struct wp_presentation *wp_presentation;
|
||||
struct dri2_wl_formats formats;
|
||||
struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
struct dmabuf_feedback dmabuf_feedback;
|
||||
char *device_name;
|
||||
dev_t display_device_dev;
|
||||
bool is_render_node;
|
||||
clockid_t presentation_clock_id;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <unistd.h>
|
||||
#include "util/libdrm.h"
|
||||
#include "drm-uapi/drm_fourcc.h"
|
||||
#include "util/u_dynarray.h"
|
||||
#include <sys/mman.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
|
|
@ -56,7 +57,7 @@
|
|||
#include "dri_util.h"
|
||||
#include <loader_wayland_helper.h>
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#endif
|
||||
|
|
@ -1217,8 +1218,8 @@ create_dri_image_from_dmabuf_feedback(struct dri2_egl_surface *dri2_surf,
|
|||
{
|
||||
uint32_t flags;
|
||||
|
||||
/* We don't have valid dma-buf feedback, so return */
|
||||
if (dri2_surf->dmabuf_feedback.main_device == 0)
|
||||
/* We don't have any tranches for our surface dma-buf feedback, so return */
|
||||
if (util_dynarray_num_elements(&dri2_surf->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche) == 0)
|
||||
return;
|
||||
|
||||
/* Iterates through the dma-buf feedback to pick a new set of modifiers. The
|
||||
|
|
@ -1709,6 +1710,16 @@ create_wl_buffer(struct dri2_egl_display *dri2_dpy,
|
|||
if (dri2_surf)
|
||||
wl_proxy_set_queue((struct wl_proxy *)params, dri2_surf->wl_queue);
|
||||
|
||||
if (wl_proxy_get_version((struct wl_proxy *)dri2_dpy->wl_dmabuf) >=
|
||||
ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION) {
|
||||
struct wl_array dev;
|
||||
wl_array_init(&dev);
|
||||
wl_array_add(&dev, sizeof(dev_t));
|
||||
memcpy(dev.data, &dri2_dpy->display_device_dev, sizeof(dev_t));
|
||||
zwp_linux_buffer_params_v1_set_sampling_device(params, &dev);
|
||||
wl_array_release(&dev);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_planes; i++) {
|
||||
struct dri_image *p_image;
|
||||
int stride, offset;
|
||||
|
|
@ -2157,26 +2168,24 @@ default_dmabuf_feedback_format_table(
|
|||
int32_t fd, uint32_t size)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
|
||||
dri2_dpy->format_table.size = size;
|
||||
dri2_dpy->format_table.data =
|
||||
feedback->format_table.size = size;
|
||||
feedback->format_table.data =
|
||||
mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
default_dmabuf_feedback_main_device(
|
||||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
struct wl_array *device)
|
||||
dri2_wl_init_display_dev(
|
||||
struct dri2_egl_display *dri2_dpy,
|
||||
dev_t dev)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
char *node;
|
||||
int fd;
|
||||
dev_t dev;
|
||||
|
||||
/* Given the device, look for a render node and try to open it. */
|
||||
memcpy(&dev, device->data, sizeof(dev));
|
||||
node = loader_get_render_node(dev);
|
||||
if (!node)
|
||||
return;
|
||||
|
|
@ -2186,6 +2195,7 @@ default_dmabuf_feedback_main_device(
|
|||
return;
|
||||
}
|
||||
|
||||
dri2_dpy->display_device_dev = dev;
|
||||
dri2_dpy->device_name = node;
|
||||
dri2_dpy->fd_render_gpu = fd;
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
|
|
@ -2193,12 +2203,27 @@ default_dmabuf_feedback_main_device(
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
default_dmabuf_feedback_main_device(
|
||||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
struct wl_array *device)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
|
||||
memcpy(&feedback->main_device, device->data, sizeof(feedback->main_device));
|
||||
dri2_wl_init_display_dev(dri2_dpy, feedback->main_device);
|
||||
}
|
||||
|
||||
static void
|
||||
default_dmabuf_feedback_tranche_target_device(
|
||||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
struct wl_array *device)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
|
||||
memcpy(&feedback->pending_tranche.target_device, device->data, sizeof(feedback->pending_tranche.target_device));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2206,7 +2231,10 @@ default_dmabuf_feedback_tranche_flags(
|
|||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
uint32_t flags)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
|
||||
feedback->pending_tranche.flags = flags;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2215,18 +2243,19 @@ default_dmabuf_feedback_tranche_formats(
|
|||
struct wl_array *indices)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
uint64_t *modifier_ptr, modifier;
|
||||
uint32_t format;
|
||||
uint16_t *index;
|
||||
int visual_idx;
|
||||
|
||||
if (dri2_dpy->format_table.data == MAP_FAILED) {
|
||||
if (feedback->format_table.data == MAP_FAILED) {
|
||||
_eglLog(_EGL_WARNING, "wayland-egl: we could not map the format table "
|
||||
"so we won't be able to use this batch of dma-buf "
|
||||
"feedback events.");
|
||||
return;
|
||||
}
|
||||
if (dri2_dpy->format_table.data == NULL) {
|
||||
if (feedback->format_table.data == NULL) {
|
||||
_eglLog(_EGL_WARNING,
|
||||
"wayland-egl: compositor didn't advertise a format "
|
||||
"table, so we won't be able to use this batch of dma-buf "
|
||||
|
|
@ -2235,8 +2264,8 @@ default_dmabuf_feedback_tranche_formats(
|
|||
}
|
||||
|
||||
wl_array_for_each (index, indices) {
|
||||
format = dri2_dpy->format_table.data[*index].format;
|
||||
modifier = dri2_dpy->format_table.data[*index].modifier;
|
||||
format = feedback->format_table.data[*index].format;
|
||||
modifier = feedback->format_table.data[*index].modifier;
|
||||
|
||||
/* skip formats that we don't support */
|
||||
visual_idx = dri2_wl_visual_idx_from_fourcc(format);
|
||||
|
|
@ -2254,15 +2283,20 @@ static void
|
|||
default_dmabuf_feedback_tranche_done(
|
||||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
struct dmabuf_feedback *feedback = &dri2_dpy->dmabuf_feedback;
|
||||
|
||||
/* Add tranche to array of tranches. */
|
||||
util_dynarray_append(&feedback->tranches,
|
||||
feedback->pending_tranche);
|
||||
|
||||
dmabuf_feedback_tranche_init(&feedback->pending_tranche);
|
||||
}
|
||||
|
||||
static void
|
||||
default_dmabuf_feedback_done(
|
||||
void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
|
||||
{
|
||||
/* ignore this event */
|
||||
}
|
||||
{}
|
||||
|
||||
static const struct zwp_linux_dmabuf_feedback_v1_listener
|
||||
dmabuf_feedback_listener = {
|
||||
|
|
@ -2304,7 +2338,7 @@ registry_handle_global_drm(void *data, struct wl_registry *registry,
|
|||
version >= 3) {
|
||||
dri2_dpy->wl_dmabuf = wl_registry_bind(
|
||||
registry, name, &zwp_linux_dmabuf_v1_interface,
|
||||
MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION));
|
||||
MIN2(version, ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION));
|
||||
zwp_linux_dmabuf_v1_add_listener(dri2_dpy->wl_dmabuf, &dmabuf_listener,
|
||||
dri2_dpy);
|
||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||
|
|
@ -2618,7 +2652,9 @@ dri2_initialize_wayland_drm_extensions(struct dri2_egl_display *dri2_dpy)
|
|||
if (dri2_dpy->wl_dmabuf &&
|
||||
zwp_linux_dmabuf_v1_get_version(dri2_dpy->wl_dmabuf) >=
|
||||
ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) {
|
||||
dmabuf_feedback_format_table_init(&dri2_dpy->format_table);
|
||||
if (dmabuf_feedback_init(&dri2_dpy->dmabuf_feedback) < 0) {
|
||||
return false;
|
||||
}
|
||||
dri2_dpy->wl_dmabuf_feedback =
|
||||
zwp_linux_dmabuf_v1_get_default_feedback(dri2_dpy->wl_dmabuf);
|
||||
zwp_linux_dmabuf_feedback_v1_add_listener(
|
||||
|
|
@ -2628,11 +2664,20 @@ dri2_initialize_wayland_drm_extensions(struct dri2_egl_display *dri2_dpy)
|
|||
if (roundtrip(dri2_dpy) < 0)
|
||||
return false;
|
||||
|
||||
/* Destroy the default dma-buf feedback and the format table. */
|
||||
/* Destroy the default dma-buf feedback. */
|
||||
if (dri2_dpy->wl_dmabuf_feedback) {
|
||||
zwp_linux_dmabuf_feedback_v1_destroy(dri2_dpy->wl_dmabuf_feedback);
|
||||
dri2_dpy->wl_dmabuf_feedback = NULL;
|
||||
dmabuf_feedback_format_table_fini(&dri2_dpy->format_table);
|
||||
|
||||
/* For dmabuf v6 we don't get a main device, use the first tranch suitable for sampling as default */
|
||||
if (dri2_dpy->fd_render_gpu == -1) {
|
||||
util_dynarray_foreach(&dri2_dpy->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) {
|
||||
if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0) {
|
||||
dri2_wl_init_display_dev(dri2_dpy, tranche->target_device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
|
|
@ -2661,6 +2706,8 @@ static EGLBoolean
|
|||
dri2_initialize_wayland_drm(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
dev_t preferred_dev_id = 0;
|
||||
drmDevicePtr render_dev = NULL, preferred_dev = NULL, tranche_dev = NULL;
|
||||
|
||||
if (dri2_wl_formats_init(&dri2_dpy->formats) < 0)
|
||||
goto cleanup;
|
||||
|
|
@ -2697,8 +2744,43 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
|
|||
if (!dri2_initialize_wayland_drm_extensions(dri2_dpy))
|
||||
goto cleanup;
|
||||
|
||||
loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu,
|
||||
&dri2_dpy->fd_display_gpu);
|
||||
if (drmGetDevice2(dri2_dpy->fd_render_gpu, 0, &render_dev) != 0)
|
||||
goto cleanup;
|
||||
|
||||
if (loader_get_user_preferred_device(render_dev, &preferred_dev_id))
|
||||
{
|
||||
bool found_matching_tranche = false;
|
||||
if (drmGetDeviceFromDevId(preferred_dev_id, 0, &preferred_dev) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* check if the compositor can sample from the new device */
|
||||
util_dynarray_foreach(&dri2_dpy->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) {
|
||||
if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0) {
|
||||
if (drmGetDeviceFromDevId(tranche->target_device, 0, &tranche_dev) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!found_matching_tranche && loader_drm_devices_match(preferred_dev, tranche_dev)) {
|
||||
close(dri2_dpy->fd_render_gpu);
|
||||
dri2_wl_init_display_dev(dri2_dpy, tranche->target_device);
|
||||
found_matching_tranche = true;
|
||||
}
|
||||
|
||||
drmFreeDevice(&tranche_dev);
|
||||
}
|
||||
}
|
||||
|
||||
dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
|
||||
if (!found_matching_tranche) {
|
||||
// fallback to copying
|
||||
dri2_dpy->fd_render_gpu = loader_open_device(preferred_dev->nodes[DRM_NODE_RENDER]);
|
||||
}
|
||||
drmFreeDevice(&preferred_dev);
|
||||
} else {
|
||||
dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
|
||||
}
|
||||
drmFreeDevice(&render_dev);
|
||||
|
||||
if (dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) {
|
||||
free(dri2_dpy->device_name);
|
||||
|
|
@ -2781,6 +2863,9 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
|
|||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
if (render_dev) drmFreeDevice(&render_dev);
|
||||
if (preferred_dev) drmFreeDevice(&preferred_dev);
|
||||
if (tranche_dev) drmFreeDevice(&tranche_dev);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -3291,7 +3376,6 @@ dri2_initialize_wayland(_EGLDisplay *disp)
|
|||
void
|
||||
dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
dri2_wl_formats_fini(&dri2_dpy->formats);
|
||||
if (dri2_dpy->wp_presentation)
|
||||
wp_presentation_destroy(dri2_dpy->wp_presentation);
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
|
|
@ -3300,6 +3384,7 @@ dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy)
|
|||
#endif
|
||||
if (dri2_dpy->wl_dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(dri2_dpy->wl_dmabuf);
|
||||
dmabuf_feedback_fini(&dri2_dpy->dmabuf_feedback);
|
||||
if (dri2_dpy->wl_shm)
|
||||
wl_shm_destroy(dri2_dpy->wl_shm);
|
||||
if (dri2_dpy->wl_registry) {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ if with_dri
|
|||
deps_for_egl += [dep_wayland_client, dep_wayland_server, dep_wayland_egl_headers]
|
||||
link_for_egl += libloader_wayland_helper
|
||||
files_egl += files('drivers/dri2/platform_wayland.c')
|
||||
files_egl += wp_files['linux-dmabuf-unstable-v1']
|
||||
files_egl += wp_files['linux-dmabuf-v1']
|
||||
files_egl += wp_files['presentation-time']
|
||||
if with_wayland_bind_display
|
||||
files_egl += [wayland_drm_client_protocol_h]
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <xf86drm.h>
|
||||
#include <sys/param.h>
|
||||
#ifdef MAJOR_IN_MKDEV
|
||||
#include <sys/mkdev.h>
|
||||
|
|
@ -48,7 +49,6 @@
|
|||
#include "mesa_interface.h"
|
||||
#include "loader.h"
|
||||
#include "util/drm_is_nouveau.h"
|
||||
#include "util/libdrm.h"
|
||||
#include "util/os_file.h"
|
||||
#include "util/os_misc.h"
|
||||
#include "util/u_debug.h"
|
||||
|
|
@ -450,13 +450,20 @@ static char *drm_get_id_path_tag_for_fd(int fd)
|
|||
return tag;
|
||||
}
|
||||
|
||||
bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd)
|
||||
bool loader_drm_devices_match(drmDevicePtr dev1, drmDevicePtr dev2)
|
||||
{
|
||||
char *tag = drm_construct_id_path_tag(dev1);
|
||||
return drm_device_matches_tag(dev2, tag);
|
||||
}
|
||||
|
||||
bool loader_get_user_preferred_device(drmDevicePtr default_dev, dev_t *preferred_dev_id)
|
||||
{
|
||||
const char *dri_prime = os_get_option("DRI_PRIME");
|
||||
bool debug = debug_get_bool_option("DRI_PRIME_DEBUG", false);
|
||||
char *default_tag = NULL;
|
||||
drmDevicePtr devices[MAX_DRM_DEVICES];
|
||||
int i, num_devices, fd = -1;
|
||||
int i, num_devices = -1;
|
||||
struct stat sbuf;
|
||||
struct {
|
||||
enum {
|
||||
PRIME_IS_INTEGER,
|
||||
|
|
@ -502,7 +509,7 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd)
|
|||
}
|
||||
}
|
||||
|
||||
default_tag = drm_get_id_path_tag_for_fd(*fd_render_gpu);
|
||||
default_tag = drm_construct_id_path_tag(default_dev);
|
||||
if (default_tag == NULL)
|
||||
goto err;
|
||||
|
||||
|
|
@ -607,20 +614,58 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd)
|
|||
|
||||
log_(debug ? _LOADER_WARNING : _LOADER_INFO,
|
||||
"selected (%s)\n", devices[i]->nodes[DRM_NODE_RENDER]);
|
||||
fd = loader_open_device(devices[i]->nodes[DRM_NODE_RENDER]);
|
||||
if (fd < 0) {
|
||||
log_(debug ? _LOADER_WARNING : _LOADER_INFO,
|
||||
"DRI_PRIME: failed to open '%s'\n",
|
||||
devices[i]->nodes[DRM_NODE_RENDER]);
|
||||
char *preferred_node = devices[i]->nodes[DRM_NODE_RENDER];
|
||||
if (stat(preferred_node, &sbuf) != 0) {
|
||||
goto err;
|
||||
}
|
||||
*preferred_dev_id = sbuf.st_rdev;
|
||||
break;
|
||||
}
|
||||
drmFreeDevices(devices, num_devices);
|
||||
|
||||
if (i == num_devices || fd < 0)
|
||||
if (i == num_devices)
|
||||
goto err;
|
||||
|
||||
bool is_render_and_display_gpu_diff = !!strcmp(default_tag, prime.str);
|
||||
|
||||
free(default_tag);
|
||||
free(prime.str);
|
||||
return is_render_and_display_gpu_diff;
|
||||
err:
|
||||
log_(debug ? _LOADER_WARNING : _LOADER_INFO,
|
||||
"DRI_PRIME: error. Using the default GPU\n");
|
||||
free(default_tag);
|
||||
free(prime.str);
|
||||
no_prime_gpu_offloading:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd)
|
||||
{
|
||||
int fd = -1;
|
||||
bool is_render_and_display_gpu_diff;
|
||||
dev_t preferred_dev_id = 0;
|
||||
drmDevicePtr render_dev, preferred_dev;
|
||||
bool debug = debug_get_bool_option("DRI_PRIME_DEBUG", false);
|
||||
|
||||
if (drmGetDevice2(*fd_render_gpu, 0, &render_dev) != 0)
|
||||
return false;
|
||||
is_render_and_display_gpu_diff = loader_get_user_preferred_device(render_dev, &preferred_dev_id);
|
||||
if (drmGetDeviceFromDevId(preferred_dev_id, 0, &preferred_dev) != 0) {
|
||||
drmFreeDevice(&render_dev);
|
||||
return false;
|
||||
};
|
||||
fd = loader_open_device(preferred_dev->nodes[DRM_NODE_RENDER]);
|
||||
|
||||
if (fd < 0) {
|
||||
log_(debug ? _LOADER_WARNING : _LOADER_INFO,
|
||||
"DRI_PRIME: failed to open '%s'\n",
|
||||
render_dev->nodes[DRM_NODE_RENDER]);
|
||||
drmFreeDevice(&render_dev);
|
||||
drmFreeDevice(&preferred_dev);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (original_fd) {
|
||||
if (is_render_and_display_gpu_diff) {
|
||||
*original_fd = *fd_render_gpu;
|
||||
|
|
@ -634,18 +679,9 @@ bool loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd)
|
|||
*fd_render_gpu = fd;
|
||||
}
|
||||
|
||||
free(default_tag);
|
||||
free(prime.str);
|
||||
drmFreeDevice(&render_dev);
|
||||
drmFreeDevice(&preferred_dev);
|
||||
return is_render_and_display_gpu_diff;
|
||||
err:
|
||||
log_(debug ? _LOADER_WARNING : _LOADER_INFO,
|
||||
"DRI_PRIME: error. Using the default GPU\n");
|
||||
free(default_tag);
|
||||
free(prime.str);
|
||||
no_prime_gpu_offloading:
|
||||
if (original_fd)
|
||||
*original_fd = *fd_render_gpu;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h>
|
||||
#include <xf86drm.h>
|
||||
#include "mesa_interface.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -75,6 +76,9 @@ loader_open_driver_lib(const char *driver_name,
|
|||
char *
|
||||
loader_get_device_name_for_fd(int fd);
|
||||
|
||||
bool
|
||||
loader_drm_devices_match(drmDevicePtr dev1, drmDevicePtr dev2);
|
||||
|
||||
/* For dri prime gpu offloading this function will take current render fd and possibly
|
||||
* update it with new prime gpu offloading fd. For dri prime gpu offloading optionally
|
||||
* this function can return the original fd. Also this function returns true/false based
|
||||
|
|
@ -84,6 +88,14 @@ loader_get_device_name_for_fd(int fd);
|
|||
bool
|
||||
loader_get_user_preferred_fd(int *fd_render_gpu, int *original_fd);
|
||||
|
||||
/* For dri prime offloading this function will take a default device and possibly set
|
||||
* the user preferred device for prime gpu offloading. This function returns true/false
|
||||
* based on if the default device is different from the preferred one.
|
||||
*/
|
||||
|
||||
bool
|
||||
loader_get_user_preferred_device(drmDevicePtr default_dev, dev_t *preferred_dev_id);
|
||||
|
||||
/* for logging.. keep this aligned with egllog.h so we can just use
|
||||
* _eglLog directly.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ if with_platform_wayland
|
|||
wp_protos = {
|
||||
'fifo-v1': mod_wl.find_protocol('fifo', state : 'staging', version : 1),
|
||||
'commit-timing-v1': mod_wl.find_protocol('commit-timing', state : 'staging', version : 1),
|
||||
'linux-dmabuf-unstable-v1': mod_wl.find_protocol('linux-dmabuf', state : 'unstable', version : 1),
|
||||
'linux-dmabuf-v1': mod_wl.find_protocol('linux-dmabuf', state : 'stable', version : 1),
|
||||
'presentation-time': mod_wl.find_protocol('presentation-time'),
|
||||
'tearing-control-v1': mod_wl.find_protocol('tearing-control', state : 'staging', version : 1),
|
||||
'linux-drm-syncobj-v1': mod_wl.find_protocol('linux-drm-syncobj', state : 'staging', version : 1),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include "device_select.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
|
||||
struct device_select_wayland_info {
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ if with_platform_wayland
|
|||
vklayer_files += [ wayland_drm_client_protocol_h, wayland_drm_protocol_c ]
|
||||
vklayer_flags += [ '-DHAVE_BIND_WL_DISPLAY' ]
|
||||
endif
|
||||
vklayer_files += wp_files['linux-dmabuf-unstable-v1']
|
||||
vklayer_files += wp_files['linux-dmabuf-v1']
|
||||
vklayer_deps += dep_wayland_client
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ if with_platform_wayland
|
|||
files_vulkan_wsi += files('wsi_common_wayland.c')
|
||||
files_vulkan_wsi += wp_files['fifo-v1']
|
||||
files_vulkan_wsi += wp_files['commit-timing-v1']
|
||||
files_vulkan_wsi += wp_files['linux-dmabuf-unstable-v1']
|
||||
files_vulkan_wsi += wp_files['linux-dmabuf-v1']
|
||||
files_vulkan_wsi += wp_files['presentation-time']
|
||||
files_vulkan_wsi += wp_files['tearing-control-v1']
|
||||
links_vulkan_wsi += libloader_wayland_helper
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#include "wsi_common_private.h"
|
||||
#include "fifo-v1-client-protocol.h"
|
||||
#include "commit-timing-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
#include "tearing-control-v1-client-protocol.h"
|
||||
|
|
@ -114,7 +114,7 @@ struct wsi_wl_display {
|
|||
|
||||
struct wp_color_manager_v1 *color_manager;
|
||||
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
struct dmabuf_feedback dmabuf_feedback;
|
||||
|
||||
struct u_vector color_primaries;
|
||||
struct u_vector color_transfer_funcs;
|
||||
|
|
@ -137,7 +137,7 @@ struct wsi_wl_display {
|
|||
|
||||
bool sw;
|
||||
|
||||
dev_t main_device;
|
||||
dev_t display_device_dev;
|
||||
bool same_gpu;
|
||||
|
||||
clockid_t presentation_clock_id;
|
||||
|
|
@ -854,9 +854,10 @@ default_dmabuf_feedback_format_table(void *data,
|
|||
int32_t fd, uint32_t size)
|
||||
{
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
|
||||
display->format_table.size = size;
|
||||
display->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
feedback->format_table.size = size;
|
||||
feedback->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
|
@ -867,9 +868,10 @@ default_dmabuf_feedback_main_device(void *data,
|
|||
struct wl_array *device)
|
||||
{
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
|
||||
assert(device->size == sizeof(dev_t));
|
||||
memcpy(&display->main_device, device->data, device->size);
|
||||
memcpy(&feedback->main_device, device->data, device->size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -877,7 +879,10 @@ default_dmabuf_feedback_tranche_target_device(void *data,
|
|||
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
struct wl_array *device)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
|
||||
memcpy(&feedback->pending_tranche.target_device, device->data, sizeof(feedback->pending_tranche.target_device));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -885,7 +890,10 @@ default_dmabuf_feedback_tranche_flags(void *data,
|
|||
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback,
|
||||
uint32_t flags)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
|
||||
feedback->pending_tranche.flags = flags;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -894,19 +902,20 @@ default_dmabuf_feedback_tranche_formats(void *data,
|
|||
struct wl_array *indices)
|
||||
{
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
uint32_t format;
|
||||
uint64_t modifier;
|
||||
uint16_t *index;
|
||||
|
||||
/* We couldn't map the format table or the compositor didn't advertise it,
|
||||
* so we have to ignore the feedback. */
|
||||
if (display->format_table.data == MAP_FAILED ||
|
||||
display->format_table.data == NULL)
|
||||
if (feedback->format_table.data == MAP_FAILED ||
|
||||
feedback->format_table.data == NULL)
|
||||
return;
|
||||
|
||||
wl_array_for_each(index, indices) {
|
||||
format = display->format_table.data[*index].format;
|
||||
modifier = display->format_table.data[*index].modifier;
|
||||
format = feedback->format_table.data[*index].format;
|
||||
modifier = feedback->format_table.data[*index].modifier;
|
||||
wsi_wl_display_add_drm_format_modifier(display, &display->formats,
|
||||
format, modifier);
|
||||
}
|
||||
|
|
@ -916,15 +925,20 @@ static void
|
|||
default_dmabuf_feedback_tranche_done(void *data,
|
||||
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
|
||||
{
|
||||
/* ignore this event */
|
||||
struct wsi_wl_display *display = data;
|
||||
struct dmabuf_feedback *feedback = &display->dmabuf_feedback;
|
||||
|
||||
/* Add tranche to array of tranches. */
|
||||
util_dynarray_append(&feedback->tranches,
|
||||
feedback->pending_tranche);
|
||||
|
||||
dmabuf_feedback_tranche_init(&feedback->pending_tranche);
|
||||
}
|
||||
|
||||
static void
|
||||
default_dmabuf_feedback_done(void *data,
|
||||
struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback)
|
||||
{
|
||||
/* ignore this event */
|
||||
}
|
||||
{}
|
||||
|
||||
static const struct zwp_linux_dmabuf_feedback_v1_listener
|
||||
dmabuf_feedback_listener = {
|
||||
|
|
@ -1453,7 +1467,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
|||
if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0 && version >= 3) {
|
||||
display->wl_dmabuf =
|
||||
wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface,
|
||||
MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION));
|
||||
MIN2(version, ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION));
|
||||
zwp_linux_dmabuf_v1_add_listener(display->wl_dmabuf,
|
||||
&dmabuf_listener, display);
|
||||
} else if (strcmp(interface, wp_linux_drm_syncobj_manager_v1_interface.name) == 0) {
|
||||
|
|
@ -1609,7 +1623,7 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
|
|||
/* Get the default dma-buf feedback */
|
||||
if (display->wl_dmabuf && zwp_linux_dmabuf_v1_get_version(display->wl_dmabuf) >=
|
||||
ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) {
|
||||
dmabuf_feedback_format_table_init(&display->format_table);
|
||||
dmabuf_feedback_init(&display->dmabuf_feedback);
|
||||
display->wl_dmabuf_feedback =
|
||||
zwp_linux_dmabuf_v1_get_default_feedback(display->wl_dmabuf);
|
||||
zwp_linux_dmabuf_feedback_v1_add_listener(display->wl_dmabuf_feedback,
|
||||
|
|
@ -1623,13 +1637,42 @@ wsi_wl_display_init(struct wsi_wayland *wsi_wl,
|
|||
/* Apparently some wayland compositor do not send the render
|
||||
* device node but the primary, so test against both.
|
||||
*/
|
||||
display->same_gpu =
|
||||
(wsi_wl->wsi->drm_info.hasRender &&
|
||||
major(display->main_device) == wsi_wl->wsi->drm_info.renderMajor &&
|
||||
minor(display->main_device) == wsi_wl->wsi->drm_info.renderMinor) ||
|
||||
(wsi_wl->wsi->drm_info.hasPrimary &&
|
||||
major(display->main_device) == wsi_wl->wsi->drm_info.primaryMajor &&
|
||||
minor(display->main_device) == wsi_wl->wsi->drm_info.primaryMinor);
|
||||
if (wl_proxy_get_version((struct wl_proxy *)display->wl_dmabuf) >=
|
||||
ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION)
|
||||
{
|
||||
/*
|
||||
For dmabuf v6 we don't get a main device, so we use the first one the compositor can sample from
|
||||
as default and then try to figure out, if we can use our gpu directly.
|
||||
*/
|
||||
util_dynarray_foreach(&display->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche, tranche) {
|
||||
if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0 && !display->display_device_dev) {
|
||||
display->same_gpu = false; // if this actually is the same_gpu, we'll figure out in the next loop
|
||||
display->display_device_dev = tranche->target_device;
|
||||
}
|
||||
|
||||
if ((tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SAMPLING) != 0 &&
|
||||
((wsi_wl->wsi->drm_info.hasRender &&
|
||||
major(tranche->target_device) == wsi_wl->wsi->drm_info.renderMajor &&
|
||||
minor(tranche->target_device) == wsi_wl->wsi->drm_info.renderMinor) ||
|
||||
(wsi_wl->wsi->drm_info.hasPrimary &&
|
||||
major(tranche->target_device) == wsi_wl->wsi->drm_info.primaryMajor &&
|
||||
minor(tranche->target_device) == wsi_wl->wsi->drm_info.primaryMinor)))
|
||||
{
|
||||
display->display_device_dev = tranche->target_device;
|
||||
display->same_gpu = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
display->same_gpu =
|
||||
(wsi_wl->wsi->drm_info.hasRender &&
|
||||
major(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.renderMajor &&
|
||||
minor(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.renderMinor) ||
|
||||
(wsi_wl->wsi->drm_info.hasPrimary &&
|
||||
major(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.primaryMajor &&
|
||||
minor(display->dmabuf_feedback.main_device) == wsi_wl->wsi->drm_info.primaryMinor);
|
||||
display->display_device_dev = display->dmabuf_feedback.main_device;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1667,7 +1710,7 @@ out:
|
|||
if (display->wl_dmabuf_feedback) {
|
||||
zwp_linux_dmabuf_feedback_v1_destroy(display->wl_dmabuf_feedback);
|
||||
display->wl_dmabuf_feedback = NULL;
|
||||
dmabuf_feedback_format_table_fini(&display->format_table);
|
||||
dmabuf_feedback_fini(&display->dmabuf_feedback);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
|
@ -2229,8 +2272,8 @@ pick_format_from_surface_dmabuf_feedback(struct wsi_wl_surface *wsi_wl_surface,
|
|||
{
|
||||
struct wsi_wl_format *f = NULL;
|
||||
|
||||
/* If the main_device was not advertised, we don't have valid feedback */
|
||||
if (wsi_wl_surface->dmabuf_feedback.main_device == 0)
|
||||
/* We don't have any tranches for our surface dma-buf feedback, so return */
|
||||
if (util_dynarray_num_elements(&wsi_wl_surface->dmabuf_feedback.tranches, struct dmabuf_feedback_tranche) == 0)
|
||||
return NULL;
|
||||
|
||||
util_dynarray_foreach(&wsi_wl_surface->dmabuf_feedback.tranches,
|
||||
|
|
@ -3500,6 +3543,17 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
|
|||
if (!params)
|
||||
goto fail_image;
|
||||
|
||||
if (wl_proxy_get_version((struct wl_proxy *)display->wl_dmabuf) >=
|
||||
ZWP_LINUX_BUFFER_PARAMS_V1_SET_SAMPLING_DEVICE_SINCE_VERSION)
|
||||
{
|
||||
struct wl_array dev;
|
||||
wl_array_init(&dev);
|
||||
wl_array_add(&dev, sizeof(dev_t));
|
||||
memcpy(dev.data, &display->display_device_dev, sizeof(dev_t));
|
||||
zwp_linux_buffer_params_v1_set_sampling_device(params, &dev);
|
||||
wl_array_release(&dev);
|
||||
}
|
||||
|
||||
for (int i = 0; i < image->base.num_planes; i++) {
|
||||
zwp_linux_buffer_params_v1_add(params,
|
||||
image->base.dma_buf_fd,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
[wrap-file]
|
||||
[wrap-git]
|
||||
directory = wayland-protocols-1.41
|
||||
source_url = https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.41/downloads/wayland-protocols-1.41.tar.xz
|
||||
source_filename = wayland-protocols-1.41.tar.xz
|
||||
source_hash = 2786b6b1b79965e313f2c289c12075b9ed700d41844810c51afda10ee329576b
|
||||
#source_url = https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.41/downloads/wayland-protocols-1.41.tar.xz
|
||||
#source_filename = wayland-protocols-1.41.tar.xz
|
||||
#source_hash = 2786b6b1b79965e313f2c289c12075b9ed700d41844810c51afda10ee329576b
|
||||
url = https://gitlab.freedesktop.org/Zamundaaa/wayland-protocols.git
|
||||
revision = work/multi-gpu-dmabuf
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
wayland-protocols = wayland_protocols
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue