mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-03 18:38:11 +02:00
kmsro: look for graphics capable screen as renderonly device
Exposing a rendernode from a supported driver is not a sufficient
matching criteria to qualify as the render part of a renderonly
device, as the rendernode might only expose compute or 2D accel
capabilities.
Look for a screen that actually supports gallium graphics operations
to qualify as a renderonly screen.
v2 (Tomeu): Have pipe-loader return a list of FDs for kmsro to choose
based on capabilities.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30096>
This commit is contained in:
parent
cfad6fb037
commit
7e76c67632
5 changed files with 145 additions and 62 deletions
|
|
@ -234,6 +234,15 @@ pipe_loader_drm_zink_probe(struct pipe_loader_device **devs, int ndev);
|
|||
int
|
||||
pipe_loader_get_compatible_render_capable_device_fd(int kms_only_fd);
|
||||
|
||||
/**
|
||||
* Get the fds of render-capable devices compatible with a given display-only
|
||||
* device fd.
|
||||
*
|
||||
* Caller must close the returned fds and free the array.
|
||||
*/
|
||||
int *
|
||||
pipe_loader_get_compatible_render_capable_device_fds(int kms_only_fd, unsigned int *n_devices);
|
||||
|
||||
/**
|
||||
* Initialize a DRM device in an already opened fd.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -309,6 +309,24 @@ pipe_loader_drm_release(struct pipe_loader_device **dev)
|
|||
|
||||
int
|
||||
pipe_loader_get_compatible_render_capable_device_fd(int kms_only_fd)
|
||||
{
|
||||
unsigned int n_devices = 0;
|
||||
int result = -1;
|
||||
int *gpu_fds = pipe_loader_get_compatible_render_capable_device_fds(kms_only_fd, &n_devices);
|
||||
|
||||
if (n_devices > 0) {
|
||||
result = gpu_fds[0];
|
||||
for(unsigned int i = 1; i < n_devices; i++)
|
||||
close(gpu_fds[i]);
|
||||
}
|
||||
|
||||
free(gpu_fds);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int *
|
||||
pipe_loader_get_compatible_render_capable_device_fds(int kms_only_fd, unsigned int *n_devices)
|
||||
{
|
||||
bool is_platform_device;
|
||||
struct pipe_loader_device *dev;
|
||||
|
|
@ -335,22 +353,22 @@ pipe_loader_get_compatible_render_capable_device_fd(int kms_only_fd)
|
|||
};
|
||||
|
||||
if (!pipe_loader_drm_probe_fd(&dev, kms_only_fd, false))
|
||||
return -1;
|
||||
return NULL;
|
||||
is_platform_device = (dev->type == PIPE_LOADER_DEVICE_PLATFORM);
|
||||
pipe_loader_release(&dev, 1);
|
||||
|
||||
/* For display-only devices that are not on the platform bus, we can't assume
|
||||
* that any of the rendering devices are compatible. */
|
||||
if (!is_platform_device)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/* For platform display-only devices, we try to find a render-capable device
|
||||
* on the platform bus and that should be compatible with the display-only
|
||||
* device. */
|
||||
if (ARRAY_SIZE(drivers) == 0)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
return loader_open_render_node_platform_device(drivers, ARRAY_SIZE(drivers));
|
||||
return loader_open_render_node_platform_devices(drivers, ARRAY_SIZE(drivers), n_devices);
|
||||
}
|
||||
|
||||
static const struct driOptionDescription *
|
||||
|
|
|
|||
|
|
@ -56,74 +56,94 @@ struct pipe_screen *kmsro_drm_screen_create(int kms_fd,
|
|||
const struct pipe_screen_config *config)
|
||||
{
|
||||
struct pipe_screen *screen = NULL;
|
||||
struct renderonly *ro = CALLOC_STRUCT(renderonly);
|
||||
char *render_dev_name = NULL;
|
||||
int *gpu_fds = NULL;
|
||||
unsigned int n_devices = 0;
|
||||
|
||||
if (!ro)
|
||||
return NULL;
|
||||
|
||||
ro->kms_fd = kms_fd;
|
||||
ro->gpu_fd = pipe_loader_get_compatible_render_capable_device_fd(kms_fd);
|
||||
if (ro->gpu_fd < 0) {
|
||||
FREE(ro);
|
||||
return NULL;
|
||||
gpu_fds = pipe_loader_get_compatible_render_capable_device_fds(kms_fd, &n_devices);
|
||||
if (n_devices == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
render_dev_name = loader_get_kernel_driver_name(ro->gpu_fd);
|
||||
if (!render_dev_name) {
|
||||
close(ro->gpu_fd);
|
||||
FREE(ro);
|
||||
return NULL;
|
||||
}
|
||||
for (unsigned int i = 0; i < n_devices; i++) {
|
||||
struct renderonly *ro = CALLOC_STRUCT(renderonly);
|
||||
|
||||
ro->destroy = kmsro_ro_destroy;
|
||||
util_sparse_array_init(&ro->bo_map, sizeof(struct renderonly_scanout), 64);
|
||||
simple_mtx_init(&ro->bo_map_lock, mtx_plain);
|
||||
if (!ro)
|
||||
goto out;
|
||||
|
||||
if (strcmp(render_dev_name, "asahi") == 0) {
|
||||
ro->kms_fd = kms_fd;
|
||||
ro->gpu_fd = dup(gpu_fds[i]);
|
||||
|
||||
render_dev_name = loader_get_kernel_driver_name(ro->gpu_fd);
|
||||
if (!render_dev_name) {
|
||||
close(ro->gpu_fd);
|
||||
FREE(ro);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ro->destroy = kmsro_ro_destroy;
|
||||
util_sparse_array_init(&ro->bo_map, sizeof(struct renderonly_scanout), 64);
|
||||
simple_mtx_init(&ro->bo_map_lock, mtx_plain);
|
||||
|
||||
if (strcmp(render_dev_name, "asahi") == 0) {
|
||||
#if defined(GALLIUM_ASAHI)
|
||||
ro->create_for_resource = renderonly_create_gpu_import_for_resource;
|
||||
screen = asahi_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = renderonly_create_gpu_import_for_resource;
|
||||
screen = asahi_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(render_dev_name, "etnaviv") == 0) {
|
||||
}
|
||||
else if (strcmp(render_dev_name, "etnaviv") == 0) {
|
||||
#if defined(GALLIUM_ETNAVIV)
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = etna_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = etna_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
} else if (strcmp(render_dev_name, "msm") == 0) {
|
||||
} else if (strcmp(render_dev_name, "msm") == 0) {
|
||||
#if defined(GALLIUM_FREEDRENO)
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = fd_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = fd_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
} else if (strcmp(render_dev_name, "lima") == 0) {
|
||||
} else if (strcmp(render_dev_name, "lima") == 0) {
|
||||
#if defined(GALLIUM_LIMA)
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = lima_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = lima_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
} else if (strcmp(render_dev_name, "panfrost") == 0 ||
|
||||
strcmp(render_dev_name, "panthor") == 0) {
|
||||
} else if (strcmp(render_dev_name, "panfrost") == 0 ||
|
||||
strcmp(render_dev_name, "panthor") == 0) {
|
||||
#if defined(GALLIUM_PANFROST)
|
||||
ro->create_for_resource = panfrost_create_kms_dumb_buffer_for_resource;
|
||||
screen = panfrost_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = panfrost_create_kms_dumb_buffer_for_resource;
|
||||
screen = panfrost_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
} else if (strcmp(render_dev_name, "v3d") == 0) {
|
||||
} else if (strcmp(render_dev_name, "v3d") == 0) {
|
||||
#if defined(GALLIUM_V3D)
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = v3d_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
ro->create_for_resource = renderonly_create_kms_dumb_buffer_for_resource;
|
||||
screen = v3d_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
} else if (strcmp(render_dev_name, "vc4") == 0) {
|
||||
} else if (strcmp(render_dev_name, "vc4") == 0) {
|
||||
#if defined(GALLIUM_VC4)
|
||||
/* Passes the vc4-allocated BO through to the KMS-only DRM device using
|
||||
* PRIME buffer sharing. The VC4 BO must be linear, which the SCANOUT
|
||||
* flag on allocation will have ensured.
|
||||
*/
|
||||
ro->create_for_resource = renderonly_create_gpu_import_for_resource;
|
||||
screen = vc4_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
/* Passes the vc4-allocated BO through to the KMS-only DRM device using
|
||||
* PRIME buffer sharing. The VC4 BO must be linear, which the SCANOUT
|
||||
* flag on allocation will have ensured.
|
||||
*/
|
||||
ro->create_for_resource = renderonly_create_gpu_import_for_resource;
|
||||
screen = vc4_drm_screen_create_renderonly(ro->gpu_fd, ro, config);
|
||||
#endif
|
||||
}
|
||||
|
||||
free(render_dev_name);
|
||||
|
||||
/* test if the screen is actually graphics render capable */
|
||||
if (screen) {
|
||||
if (screen->caps.graphics)
|
||||
goto out;
|
||||
else {
|
||||
screen->destroy(screen);
|
||||
screen = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(render_dev_name);
|
||||
|
||||
out:
|
||||
for (unsigned int i = 0; i < n_devices; i++)
|
||||
close(gpu_fds[i]);
|
||||
free(gpu_fds);
|
||||
return screen;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,16 +173,46 @@ nouveau_zink_predicate(int fd, const char *driver)
|
|||
int
|
||||
loader_open_render_node_platform_device(const char * const drivers[],
|
||||
unsigned int n_drivers)
|
||||
{
|
||||
unsigned int n_devices;
|
||||
int *fds = loader_open_render_node_platform_devices(drivers, n_drivers, &n_devices);
|
||||
int fd = -1;
|
||||
|
||||
if (n_devices > 0) {
|
||||
fd = fds[0];
|
||||
free(fds);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes through all the platform devices whose driver is on the given list and
|
||||
* try to open their render node. It returns an array with the fds of all the
|
||||
* devices that it can open.
|
||||
*
|
||||
* Caller must close the returned fds and free the array.
|
||||
*/
|
||||
int *
|
||||
loader_open_render_node_platform_devices(const char * const drivers[],
|
||||
unsigned int n_drivers,
|
||||
unsigned int *n_devices)
|
||||
{
|
||||
drmDevicePtr devices[MAX_DRM_DEVICES], device;
|
||||
int num_devices, fd = -1;
|
||||
int i, j;
|
||||
bool found = false;
|
||||
int *result;
|
||||
|
||||
num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
|
||||
if (num_devices <= 0)
|
||||
return -ENOENT;
|
||||
if (num_devices <= 0) {
|
||||
*n_devices = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = calloc(n_drivers, num_devices);
|
||||
|
||||
*n_devices = 0;
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
device = devices[i];
|
||||
|
||||
|
|
@ -206,22 +236,23 @@ loader_open_render_node_platform_device(const char * const drivers[],
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
drmFreeVersion(version);
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
drmFreeVersion(version);
|
||||
break;
|
||||
|
||||
if (found)
|
||||
result[(*n_devices)++] = fd;
|
||||
else
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
drmFreeDevices(devices, num_devices);
|
||||
|
||||
if (i == num_devices)
|
||||
return -ENOENT;
|
||||
if (*n_devices == 0) {
|
||||
free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ int
|
|||
loader_open_render_node_platform_device(const char * const drivers[],
|
||||
unsigned int n_drivers);
|
||||
|
||||
int *
|
||||
loader_open_render_node_platform_devices(const char * const drivers[],
|
||||
unsigned int n_drivers,
|
||||
unsigned int *n_devices);
|
||||
|
||||
bool
|
||||
loader_is_device_render_capable(int fd);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue