diff options
author | Emil Velikov <[email protected]> | 2018-09-03 13:37:47 +0100 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2018-09-20 10:15:38 +0100 |
commit | b8b3517a49555b5127776272848d8689327db960 (patch) | |
tree | b7c1e4bb906d0db982f8954fbc7f8ae72ad9fabc /src/egl/drivers/dri2 | |
parent | 18be7403a11f53d58bbfe3905c0cacd6bc714492 (diff) |
egl/android: rework device probing
Unlike the other platforms, here we aim do guess if the device that we
somewhat arbitrarily picked, is supported or not.
In particular: when a vendor is _not_ requested we loop through all
devices, picking the first one which can create a DRI screen.
When a vendor is requested - we use that and do _not_ fall-back to any
other device.
The former seems a bit fiddly, but considering EGL_EXT_explicit_device and
EGL_MESA_query_renderer are MIA, this is the best we can do for the
moment.
With those (proposed) extensions userspace will be able to create a
separate EGL display for each device, query device details and make the
conscious decision which one to use.
v2:
- update droid_open_device_drm_gralloc()
- set the dri2_dpy->fd before using it
- return a EGLBoolean for droid_{probe,open}_device*
- do not warn on droid_load_driver failure (Tomasz)
- plug mem leak on dri2_create_screen failure (Tomasz)
- fixup function name typo (Tomasz, Rob)
v3:
- add forward declaration for droid_load_driver()
Fixes the HAVE_DRM_GRALLOC build (Mauro)
- split dup() assignment and check in separate lines (Tomasz, Eric)
- make droid_load_driver() static (Tomasz)
- drop unused prop_set variable (Tomasz)
v4:
- rebase
- fwd declarationi should be for droid_probe_device()
Cc: Robert Foss <[email protected]>
Cc: Tomasz Figa <[email protected]>
Cc: Mauro Rossi <[email protected]>
Signed-off-by: Emil Velikov <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
Tested-by: Tomasz Figa <[email protected]>
Tested-by: Tapani Pälli <[email protected]>
Diffstat (limited to 'src/egl/drivers/dri2')
-rw-r--r-- | src/egl/drivers/dri2/platform_android.c | 120 |
1 files changed, 77 insertions, 43 deletions
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 00e62b067fd..bcb3c019b9a 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -1202,10 +1202,14 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy) return (config_count != 0); } +static EGLBoolean +droid_probe_device(_EGLDisplay *disp); + #ifdef HAVE_DRM_GRALLOC -static int -droid_open_device_drm_gralloc(struct dri2_egl_display *dri2_dpy) +static EGLBoolean +droid_open_device_drm_gralloc(_EGLDisplay *disp) { + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); int fd = -1, err = -EINVAL; if (dri2_dpy->gralloc->perform) @@ -1214,10 +1218,14 @@ droid_open_device_drm_gralloc(struct dri2_egl_display *dri2_dpy) &fd); if (err || fd < 0) { _eglLog(_EGL_WARNING, "fail to get drm fd"); - fd = -1; + return EGL_FALSE; } - return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1; + dri2_dpy->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (dri2_dpy->fd < 0) + return EGL_FALSE; + + return droid_probe_device(disp); } #endif /* HAVE_DRM_GRALLOC */ @@ -1404,6 +1412,17 @@ error: return false; } +static void +droid_unload_driver(_EGLDisplay *disp) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + dlclose(dri2_dpy->driver); + dri2_dpy->driver = NULL; + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; +} + static int droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor) { @@ -1420,13 +1439,31 @@ droid_filter_device(_EGLDisplay *disp, int fd, const char *vendor) return 0; } -static int +static EGLBoolean +droid_probe_device(_EGLDisplay *disp) +{ + /* Check that the device is supported, by attempting to: + * - load the dri module + * - and, create a screen + */ + if (!droid_load_driver(disp)) + return EGL_FALSE; + + if (!dri2_create_screen(disp)) { + _eglLog(_EGL_WARNING, "DRI2: failed to create screen"); + droid_unload_driver(disp); + return EGL_FALSE; + } + return EGL_TRUE; +} + +static EGLBoolean droid_open_device(_EGLDisplay *disp) { #define MAX_DRM_DEVICES 32 + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL }; - int prop_set, num_devices; - int fd = -1, fallback_fd = -1; + int num_devices; char *vendor_name = NULL; char vendor_buf[PROPERTY_VALUE_MAX]; @@ -1436,7 +1473,7 @@ droid_open_device(_EGLDisplay *disp) num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); if (num_devices < 0) - return num_devices; + return EGL_FALSE; for (int i = 0; i < num_devices; i++) { device = devices[i]; @@ -1444,41 +1481,49 @@ droid_open_device(_EGLDisplay *disp) if (!(device->available_nodes & (1 << DRM_NODE_RENDER))) continue; - fd = loader_open_device(device->nodes[DRM_NODE_RENDER]); - if (fd < 0) { + dri2_dpy->fd = loader_open_device(device->nodes[DRM_NODE_RENDER]); + if (dri2_dpy->fd < 0) { _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s", __func__, device->nodes[DRM_NODE_RENDER]); continue; } - if (vendor_name && droid_filter_device(disp, fd, vendor_name)) { - /* Match requested, but not found - set as fallback */ - if (fallback_fd == -1) { - fallback_fd = fd; - } else { - close(fd); - fd = -1; + /* If a vendor is explicitly provided, we use only that. + * Otherwise we fall-back the first device that is supported. + */ + if (vendor_name) { + if (droid_filter_device(disp, dri2_dpy->fd, vendor_name)) { + /* Device does not match - try next device */ + close(dri2_dpy->fd); + dri2_dpy->fd = -1; + continue; + } + /* If the requested device matches - use it. Regardless if + * init fails, do not fall-back to any other device. + */ + if (!droid_probe_device(disp)) { + close(dri2_dpy->fd); + dri2_dpy->fd = -1; } - continue; + break; } - /* Found a device */ - break; - } - drmFreeDevices(devices, num_devices); + if (droid_probe_device(disp)) + break; - if (fallback_fd < 0 && fd < 0) { - _eglLog(_EGL_WARNING, "Failed to open any DRM device"); - return -1; + /* No explicit request - attempt the next device */ + close(dri2_dpy->fd); + dri2_dpy->fd = -1; } + drmFreeDevices(devices, num_devices); - if (fd < 0) { - _eglLog(_EGL_WARNING, "Failed to open desired DRM device, using fallback"); - return fallback_fd; + if (dri2_dpy->fd < 0) { + _eglLog(_EGL_WARNING, "Failed to open %s DRM device", + vendor_name ? "desired": "any"); + return EGL_FALSE; } - close(fallback_fd); - return fd; + return EGL_TRUE; #undef MAX_DRM_DEVICES } @@ -1510,25 +1555,14 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp) disp->DriverData = (void *) dri2_dpy; #ifdef HAVE_DRM_GRALLOC - dri2_dpy->fd = droid_open_device_drm_gralloc(dri2_dpy); + if (!droid_open_device_drm_gralloc(disp)) { #else - dri2_dpy->fd = droid_open_device(disp); + if (!droid_open_device(disp)) { #endif - if (dri2_dpy->fd < 0) { err = "DRI2: failed to open device"; goto cleanup; } - if (!droid_load_driver(disp)) { - err = "DRI2: failed to load driver"; - goto cleanup; - } - - if (!dri2_create_screen(disp)) { - err = "DRI2: failed to create screen"; - goto cleanup; - } - if (!dri2_setup_extensions(disp)) { err = "DRI2: failed to setup extensions"; goto cleanup; |