305 lines
11 KiB
Diff
305 lines
11 KiB
Diff
From f1f625dbcb4e0cc062369729b1da3d7fc65969e8 Mon Sep 17 00:00:00 2001
|
|
From: Brendan King <Brendan.King@imgtec.com>
|
|
Date: Thu, 20 May 2021 20:16:18 +0100
|
|
Subject: [PATCH 54/67] egl/null: add support for DRI_PRIME GPU selection
|
|
|
|
Add support for selecting the GPU to be used for rendering using
|
|
the DRI_PRIME environment variable. If a different GPU is selected,
|
|
a duplicate of the file descriptor for the original GPU/display is
|
|
preserved, which can be obtained by calling the getDisplayFD
|
|
function in the image loader extension.
|
|
|
|
This change includes code, in function dri2_null_try_device, to
|
|
skip display devices that are not supported by the PVR driver.
|
|
This is to prevent failure on PC based test systems, that often
|
|
include display hardware that is incompatible with the driver.
|
|
This code would not be needed for systems that don't use the PVR
|
|
driver, or on production systems that use the PVR driver.
|
|
---
|
|
src/egl/drivers/dri2/egl_dri2.c | 1 +
|
|
src/egl/drivers/dri2/platform_null.c | 133 +++++++++++++++++++--------
|
|
2 files changed, 98 insertions(+), 36 deletions(-)
|
|
|
|
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
|
|
index ec4ac602a84..56b5175db6e 100644
|
|
--- a/src/egl/drivers/dri2/egl_dri2.c
|
|
+++ b/src/egl/drivers/dri2/egl_dri2.c
|
|
@@ -1369,6 +1369,7 @@ dri2_display_destroy(_EGLDisplay *disp)
|
|
|
|
switch (disp->Platform) {
|
|
case _EGL_PLATFORM_DRM:
|
|
+ case _EGL_PLATFORM_NULL:
|
|
case _EGL_PLATFORM_WAYLAND:
|
|
case _EGL_PLATFORM_X11:
|
|
if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
|
|
diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
|
|
index db6f1147670..af77ea4dd89 100644
|
|
--- a/src/egl/drivers/dri2/platform_null.c
|
|
+++ b/src/egl/drivers/dri2/platform_null.c
|
|
@@ -44,6 +44,7 @@
|
|
|
|
#include "egl_dri2.h"
|
|
#include "loader.h"
|
|
+#include "util/os_file.h"
|
|
|
|
#define NULL_CARD_MINOR_MAX 63U
|
|
|
|
@@ -953,7 +954,7 @@ swap_idle_get_target_frame(struct dri2_egl_surface *dri2_surf,
|
|
* current vblank by the number of intervals set at the time swapBuffer
|
|
* is called. For intervals of 1 or 0, we don't need a target frame.
|
|
*/
|
|
- err = display_get_vblank_sequence(dri2_dpy->fd, current_vblank_out);
|
|
+ err = display_get_vblank_sequence(dri2_dpy->fd_dpy, current_vblank_out);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -1003,7 +1004,7 @@ swap_vblank_state_transition(struct dri2_egl_surface *dri2_surf,
|
|
uint32_t flags = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
|
|
int err;
|
|
|
|
- err = display_request_vblank(dri2_dpy->fd, target_frame,
|
|
+ err = display_request_vblank(dri2_dpy->fd_dpy, target_frame,
|
|
flags, dri2_surf);
|
|
if (err) {
|
|
dri2_surf->swap_state = SWAP_ERROR;
|
|
@@ -1029,7 +1030,7 @@ swap_flip_state_transition(struct dri2_egl_surface *dri2_surf)
|
|
flags |= DRM_MODE_PAGE_FLIP_ASYNC;
|
|
}
|
|
|
|
- err = display_output_flip(dri2_dpy->fd, &dri2_dpy->output,
|
|
+ err = display_output_flip(dri2_dpy->fd_dpy, &dri2_dpy->output,
|
|
dri2_surf->swap_data->fb_id, flags, dri2_surf);
|
|
if (err) {
|
|
dri2_surf->swap_state = SWAP_ERROR;
|
|
@@ -1049,7 +1050,7 @@ swap_poll_state_transition(struct dri2_egl_surface *dri2_surf)
|
|
int err;
|
|
|
|
/* dri2_surf->swap_state is being set inside the handler */
|
|
- err = drm_event_process(dri2_dpy->fd);
|
|
+ err = drm_event_process(dri2_dpy->fd_dpy);
|
|
if (err) {
|
|
dri2_surf->swap_state = SWAP_ERROR;
|
|
return err;
|
|
@@ -1201,7 +1202,7 @@ add_fb_for_dri_image(struct dri2_egl_display *dri2_dpy, __DRIimage *image,
|
|
handles[i] = (uint32_t) handle;
|
|
}
|
|
|
|
- return !drmModeAddFB2WithModifiers(dri2_dpy->fd, width, height,
|
|
+ return !drmModeAddFB2WithModifiers(dri2_dpy->fd_dpy, width, height,
|
|
dri2_null_formats[format_idx].drm_format,
|
|
handles, pitches, offsets, modifiers,
|
|
fb_id_out, flags);
|
|
@@ -1459,7 +1460,7 @@ dri2_null_create_window_surface(_EGLDisplay *disp, _EGLConfig *config,
|
|
goto err_destroy_surface;
|
|
}
|
|
|
|
- err = display_output_modeset(dri2_dpy->fd, &dri2_dpy->output,
|
|
+ err = display_output_modeset(dri2_dpy->fd_dpy, &dri2_dpy->output,
|
|
dri2_surf->front_buffer.fb_id);
|
|
if (err) {
|
|
_eglError(EGL_BAD_NATIVE_WINDOW, "window set mode");
|
|
@@ -1573,11 +1574,11 @@ dri2_null_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
|
dri2_dpy->image->destroyImage(dri2_surf->front_buffer.dri_image);
|
|
|
|
if (dri2_surf->front_buffer.fb_id)
|
|
- drmModeRmFB(dri2_dpy->fd, dri2_surf->front_buffer.fb_id);
|
|
+ drmModeRmFB(dri2_dpy->fd_dpy, dri2_surf->front_buffer.fb_id);
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
|
if (dri2_surf->color_buffers[i].fb_id)
|
|
- drmModeRmFB(dri2_dpy->fd, dri2_surf->color_buffers[i].fb_id);
|
|
+ drmModeRmFB(dri2_dpy->fd_dpy, dri2_surf->color_buffers[i].fb_id);
|
|
if (dri2_surf->color_buffers[i].dri_image)
|
|
dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
|
|
}
|
|
@@ -1734,12 +1735,22 @@ dri2_null_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
|
|
(void) loaderPrivate;
|
|
}
|
|
|
|
+static int
|
|
+dri2_null_get_display_fd(void *loaderPrivate)
|
|
+{
|
|
+ _EGLDisplay *disp = loaderPrivate;
|
|
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
+
|
|
+ return dri2_dpy->fd_dpy;
|
|
+}
|
|
+
|
|
static const __DRIimageLoaderExtension image_loader_extension = {
|
|
- .base = { __DRI_IMAGE_LOADER, 2 },
|
|
+ .base = { __DRI_IMAGE_LOADER, 5 },
|
|
|
|
.getBuffers = dri2_null_image_get_buffers,
|
|
.flushFrontBuffer = dri2_null_flush_front_buffer,
|
|
.getCapability = dri2_null_get_capability,
|
|
+ .getDisplayFD = dri2_null_get_display_fd,
|
|
};
|
|
|
|
static const __DRIextension *image_loader_extensions[] = {
|
|
@@ -1768,12 +1779,74 @@ dri2_null_device_is_kms(int fd)
|
|
return is_kms;
|
|
}
|
|
|
|
+static bool
|
|
+dri2_null_try_device(_EGLDisplay *disp)
|
|
+{
|
|
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
+
|
|
+ if (!dri2_null_device_is_kms(dri2_dpy->fd_dpy))
|
|
+ return false;
|
|
+
|
|
+#if 1
|
|
+ /* Skip devices not supported by the pvr driver */
|
|
+ {
|
|
+ char *driver_name = loader_get_driver_for_fd(dri2_dpy->fd_dpy);
|
|
+ bool skip = !driver_name || !!strcmp(driver_name, "pvr");
|
|
+
|
|
+ free(driver_name);
|
|
+
|
|
+ if (skip)
|
|
+ return false;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ dri2_dpy->fd = os_dupfd_cloexec(dri2_dpy->fd_dpy);
|
|
+ if (dri2_dpy->fd < 0) {
|
|
+ _eglLog(_EGL_WARNING, "DRI2: failed to dup display FD");
|
|
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
|
|
+ } else {
|
|
+ int fd_old;
|
|
+ bool is_different_gpu;
|
|
+
|
|
+ fd_old = dri2_dpy->fd;
|
|
+ dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
|
|
+ &is_different_gpu);
|
|
+ if (dri2_dpy->fd == fd_old) {
|
|
+ close (dri2_dpy->fd);
|
|
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
|
|
+ if (!dri2_dpy->driver_name)
|
|
+ return false;
|
|
+
|
|
+ if (dri2_load_driver_dri3(disp)) {
|
|
+ _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false);
|
|
+ if (!dev) {
|
|
+ dlclose(dri2_dpy->driver);
|
|
+ _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
|
|
+ } else {
|
|
+ dri2_dpy->loader_extensions = image_loader_extensions;
|
|
+ dri2_dpy->own_device = 1;
|
|
+ disp->Device = dev;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ free(dri2_dpy->driver_name);
|
|
+ dri2_dpy->driver_name = NULL;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
static bool
|
|
dri2_null_probe_device(_EGLDisplay *disp)
|
|
{
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
dri2_dpy->fd = -1;
|
|
+ dri2_dpy->fd_dpy = -1;
|
|
|
|
for (unsigned i = 0; i <= NULL_CARD_MINOR_MAX; i++) {
|
|
char *card_path;
|
|
@@ -1781,32 +1854,20 @@ dri2_null_probe_device(_EGLDisplay *disp)
|
|
if (asprintf(&card_path, DRM_DEV_NAME, DRM_DIR_NAME, i) < 0)
|
|
continue;
|
|
|
|
- dri2_dpy->fd = loader_open_device(card_path);
|
|
+ dri2_dpy->fd_dpy = loader_open_device(card_path);
|
|
free(card_path);
|
|
- if (dri2_dpy->fd < 0)
|
|
+ if (dri2_dpy->fd_dpy < 0)
|
|
continue;
|
|
|
|
- if (dri2_null_device_is_kms(dri2_dpy->fd)) {
|
|
- dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
|
|
- if (dri2_dpy->driver_name) {
|
|
- if (dri2_load_driver_dri3(disp)) {
|
|
- _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false);
|
|
- if (!dev) {
|
|
- dlclose(dri2_dpy->driver);
|
|
- _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
|
|
- } else {
|
|
- dri2_dpy->loader_extensions = image_loader_extensions;
|
|
- dri2_dpy->own_device = 1;
|
|
- disp->Device = dev;
|
|
- return true;
|
|
- }
|
|
- }
|
|
- free(dri2_dpy->driver_name);
|
|
- dri2_dpy->driver_name = NULL;
|
|
- }
|
|
- }
|
|
+ if (dri2_null_try_device(disp))
|
|
+ return true;
|
|
+
|
|
+ close(dri2_dpy->fd_dpy);
|
|
+
|
|
+ if (dri2_dpy->fd >= 0 && dri2_dpy->fd != dri2_dpy->fd_dpy)
|
|
+ close(dri2_dpy->fd);
|
|
|
|
- close(dri2_dpy->fd);
|
|
+ dri2_dpy->fd_dpy = -1;
|
|
dri2_dpy->fd = -1;
|
|
}
|
|
|
|
@@ -1867,7 +1928,7 @@ dri2_null_setup_swap_interval(_EGLDisplay *disp)
|
|
|
|
dri2_setup_swap_interval(disp, swap_max_interval);
|
|
|
|
- err = drmGetCap(dri2_dpy->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
|
|
+ err = drmGetCap(dri2_dpy->fd_dpy, DRM_CAP_ASYNC_PAGE_FLIP, &value);
|
|
if (err || value == 0) {
|
|
|
|
/* DRM/KMS does not support async page flip. In order to support
|
|
@@ -1914,7 +1975,7 @@ dri2_initialize_null(_EGLDisplay *disp)
|
|
* modesetting if not. If this succeeds then universal planes will also have
|
|
* been enabled.
|
|
*/
|
|
- err = drmSetClientCap(dri2_dpy->fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
|
+ err = drmSetClientCap(dri2_dpy->fd_dpy, DRM_CLIENT_CAP_ATOMIC, 1);
|
|
dri2_dpy->atomic_enabled = !err;
|
|
|
|
if (!dri2_dpy->atomic_enabled) {
|
|
@@ -1922,7 +1983,7 @@ dri2_initialize_null(_EGLDisplay *disp)
|
|
* Enable universal planes so that we can get the pixel formats for the
|
|
* primary plane
|
|
*/
|
|
- err = drmSetClientCap(dri2_dpy->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
|
+ err = drmSetClientCap(dri2_dpy->fd_dpy, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
|
if (err) {
|
|
_eglError(EGL_NOT_INITIALIZED, "failed to enable universal planes");
|
|
goto cleanup;
|
|
@@ -1955,7 +2016,7 @@ dri2_initialize_null(_EGLDisplay *disp)
|
|
prefer_in_formats = dri2_dpy->image->base.version >= 14 &&
|
|
dri2_dpy->image->createImageWithModifiers;
|
|
|
|
- if (!display_output_init(dri2_dpy->fd, &dri2_dpy->output,
|
|
+ if (!display_output_init(dri2_dpy->fd_dpy, &dri2_dpy->output,
|
|
dri2_dpy->atomic_enabled,
|
|
prefer_in_formats,
|
|
&dri2_dpy->in_formats_enabled)) {
|
|
@@ -1990,7 +2051,7 @@ dri2_teardown_null(struct dri2_egl_display *dri2_dpy)
|
|
drmModeFreeFormats(dri2_dpy->output.in_formats);
|
|
|
|
if (dri2_dpy->output.mode_blob_id)
|
|
- drmModeDestroyPropertyBlob(dri2_dpy->fd, dri2_dpy->output.mode_blob_id);
|
|
+ drmModeDestroyPropertyBlob(dri2_dpy->fd_dpy, dri2_dpy->output.mode_blob_id);
|
|
|
|
if (dri2_dpy->output.plane_prop_res) {
|
|
for (unsigned i = 0; dri2_dpy->output.plane_prop_res[i]; i++)
|
|
--
|
|
2.25.1
|
|
|