123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- From e92a09b72b44a0969983635803022f7dc1a50924 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] 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 ec4ac60..56b5175 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 8efac19..0d81151 100644
- --- a/src/egl/drivers/dri2/platform_null.c
- +++ b/src/egl/drivers/dri2/platform_null.c
- @@ -45,6 +45,7 @@
-
- #include "egl_dri2.h"
- #include "loader.h"
- +#include "util/os_file.h"
-
- #define NULL_CARD_MINOR_MAX 63U
-
- @@ -975,7 +976,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;
-
- @@ -1025,7 +1026,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;
- @@ -1051,7 +1052,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;
- @@ -1071,7 +1072,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;
- @@ -1226,7 +1227,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);
- @@ -1494,7 +1495,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");
- @@ -1608,11 +1609,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);
- }
- @@ -1769,12 +1770,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[] = {
- @@ -1803,12 +1814,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;
- @@ -1816,32 +1889,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;
- }
-
- @@ -1902,7 +1963,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
- @@ -1950,7 +2011,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) {
- @@ -1958,7 +2019,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;
- @@ -1994,7 +2055,7 @@ dri2_initialize_null(_EGLDisplay *disp)
- 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)) {
- @@ -2028,7 +2089,7 @@ dri2_teardown_null(struct dri2_egl_display *dri2_dpy)
- drmModeAtomicFree(dri2_dpy->output.atomic_state);
-
- 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++)
|