};
static EGLBoolean
-droid_load_driver(_EGLDisplay *disp)
+droid_load_driver(_EGLDisplay *disp, bool swrast)
{
struct dri2_egl_display *dri2_dpy = disp->DriverData;
const char *err;
if (dri2_dpy->driver_name == NULL)
return false;
- dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
-
- if (!dri2_dpy->is_render_node) {
#ifdef HAVE_DRM_GRALLOC
- /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
- * for backwards compatibility with drm_gralloc. (Do not use on new
- * systems.) */
- dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
- if (!dri2_load_driver(disp)) {
- err = "DRI2: failed to load driver";
- goto error;
- }
+ /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM names
+ * for backwards compatibility with drm_gralloc. (Do not use on new
+ * systems.) */
+ dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
+ if (!dri2_load_driver(disp)) {
+ err = "DRI2: failed to load driver";
+ goto error;
+ }
#else
- err = "DRI2: handle is not for a render node";
- goto error;
+ if (swrast) {
+ /* Use kms swrast only with vgem / virtio_gpu.
+ * virtio-gpu fallbacks to software rendering when 3D features
+ * are unavailable since 6c5ab.
+ */
+ if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
+ strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {
+ free(dri2_dpy->driver_name);
+ dri2_dpy->driver_name = strdup("kms_swrast");
+ } else {
+ err = "DRI3: failed to find software capable driver";
+ goto error;
+ }
+ }
+
+ dri2_dpy->loader_extensions = droid_image_loader_extensions;
+ if (!dri2_load_driver_dri3(disp)) {
+ err = "DRI3: failed to load driver";
+ goto error;
+ }
#endif
- } else {
- dri2_dpy->loader_extensions = droid_image_loader_extensions;
- if (!dri2_load_driver_dri3(disp)) {
- err = "DRI3: failed to load driver";
- goto error;
- }
- }
return true;
}
static EGLBoolean
-droid_probe_device(_EGLDisplay *disp)
+droid_probe_device(_EGLDisplay *disp, bool swrast)
{
/* Check that the device is supported, by attempting to:
* - load the dri module
* - and, create a screen
*/
- if (!droid_load_driver(disp))
+ if (!droid_load_driver(disp, swrast))
return EGL_FALSE;
if (!dri2_create_screen(disp)) {
#ifdef HAVE_DRM_GRALLOC
static EGLBoolean
-droid_open_device(_EGLDisplay *disp)
+droid_open_device(_EGLDisplay *disp, bool swrast)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
int fd = -1, err = -EINVAL;
+ if (swrast)
+ return EGL_FALSE;
+
if (dri2_dpy->gralloc->perform)
- err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
- GRALLOC_MODULE_PERFORM_GET_DRM_FD,
- &fd);
+ err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
+ GRALLOC_MODULE_PERFORM_GET_DRM_FD,
+ &fd);
if (err || fd < 0) {
_eglLog(_EGL_WARNING, "fail to get drm fd");
return EGL_FALSE;
dri2_dpy->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (dri2_dpy->fd < 0)
- return EGL_FALSE;
+ return EGL_FALSE;
- return droid_probe_device(disp);
+ if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER)
+ return EGL_FALSE;
+
+ return droid_probe_device(disp, swrast);
}
#else
static EGLBoolean
-droid_open_device(_EGLDisplay *disp)
+droid_open_device(_EGLDisplay *disp, bool swrast)
{
#define MAX_DRM_DEVICES 64
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
/* If the requested device matches - use it. Regardless if
* init fails, do not fall-back to any other device.
*/
- if (!droid_probe_device(disp)) {
+ if (!droid_probe_device(disp, false)) {
close(dri2_dpy->fd);
dri2_dpy->fd = -1;
}
break;
}
- if (droid_probe_device(disp))
+ if (droid_probe_device(disp, swrast))
break;
/* No explicit request - attempt the next device */
dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
{
_EGLDevice *dev;
+ bool device_opened = false;
struct dri2_egl_display *dri2_dpy;
const char *err;
int ret;
- /* Not supported yet */
- if (disp->Options.ForceSoftware)
- return EGL_FALSE;
-
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
}
disp->DriverData = (void *) dri2_dpy;
+ if (!disp->Options.ForceSoftware)
+ device_opened = droid_open_device(disp, false);
+ if (!device_opened)
+ device_opened = droid_open_device(disp, true);
- if (!droid_open_device(disp)) {
+ if (!device_opened) {
err = "DRI2: failed to open device";
goto cleanup;
}