OSDN Git Service

Add DRI-based generic backend
authorRoman Stratiienko <r.stratiienko@gmail.com>
Mon, 7 Dec 2020 17:22:20 +0000 (19:22 +0200)
committerRoman Stratiienko <r.stratiienko@gmail.com>
Tue, 29 Dec 2020 10:36:43 +0000 (12:36 +0200)
mesa3d project support graphic buffer allocation via DRI API for
various set of hardware, including systems with splitted GPU
and Display controller.

Use it as fallback backend in case no other backends were found in
the supported list.

Tested with Android on sun4i-drm and lima GPU (Pinephone).

Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
Change-Id: I9d6ed0bdf3ef255c3c4f9be5385a7b87b571a232

amdgpu.c
cros_gralloc/cros_gralloc_driver.cc
dri.c
dri.h
dri_generic_driver.c [new file with mode: 0644]
drv.c
drv.h
drv_priv.h
dumb_driver.c

index 93681cb..7f2abcd 100644 (file)
--- a/amdgpu.c
+++ b/amdgpu.c
@@ -672,6 +672,15 @@ static int amdgpu_unmap_bo(struct bo *bo, struct vma *vma)
        }
 }
 
+static int amdgpu_bo_get_plane_fd(struct bo *bo, size_t plane)
+{
+       if (bo->priv)
+               dri_bo_get_plane_fd(bo, plane);
+       else
+               /* Fallback to default implementation */
+               return -1;
+}
+
 static int amdgpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
 {
        int ret;
@@ -723,6 +732,7 @@ const struct backend backend_amdgpu = {
        .bo_import = amdgpu_import_bo,
        .bo_map = amdgpu_map_bo,
        .bo_unmap = amdgpu_unmap_bo,
+       .bo_get_plane_fd = amdgpu_bo_get_plane_fd,
        .bo_invalidate = amdgpu_bo_invalidate,
        .resolve_format = amdgpu_resolve_format,
        .num_planes_from_modifier = dri_num_planes_from_modifier,
index d9e6cf5..07c55b9 100644 (file)
@@ -11,6 +11,7 @@
 #include <sys/mman.h>
 #include <syscall.h>
 #include <xf86drm.h>
+#include <xf86drmMode.h>
 
 #include "../drv_priv.h"
 #include "../helpers.h"
@@ -62,22 +63,47 @@ cros_gralloc_driver::~cros_gralloc_driver()
        }
 }
 
-static struct driver *init_try_node(int idx, char const *str)
+static bool is_kms_dev(const char *path)
+{
+       int fd = open(path, O_RDWR | O_CLOEXEC);
+       if (fd < 0)
+               return false;
+
+       auto res = drmModeGetResources(fd);
+       if (!res) {
+               close(fd);
+               return false;
+       }
+
+       bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && res->count_encoders > 0;
+
+       drmModeFreeResources(res);
+       close(fd);
+
+       return is_kms;
+}
+
+static struct driver *init_try_node(int idx, bool use_card_node, bool try_generic)
 {
        int fd;
        char *node;
        struct driver *drv;
 
-       if (asprintf(&node, str, DRM_DIR_NAME, idx) < 0)
+       if (asprintf(&node, use_card_node ? "%s/card%d" : "%s/renderD%d", DRM_DIR_NAME, idx) < 0)
                return NULL;
 
+       if (use_card_node && !is_kms_dev(node)) {
+               free(node);
+               return NULL;
+       }
+
        fd = open(node, O_RDWR, 0);
        free(node);
 
        if (fd < 0)
                return NULL;
 
-       drv = drv_create(fd);
+       drv = drv_create(fd, try_generic);
        if (!drv)
                close(fd);
 
@@ -93,8 +119,6 @@ int32_t cros_gralloc_driver::init()
         * TODO(gsingh): Enable render nodes on udl/evdi.
         */
 
-       char const *render_nodes_fmt = "%s/renderD%d";
-       char const *card_nodes_fmt = "%s/card%d";
        uint32_t num_nodes = DRM_NUM_NODES;
        uint32_t min_render_node = DRM_RENDER_NODE_START;
        uint32_t max_render_node = (min_render_node + num_nodes);
@@ -103,18 +127,34 @@ int32_t cros_gralloc_driver::init()
 
        // Try render nodes...
        for (uint32_t i = min_render_node; i < max_render_node; i++) {
-               drv_ = init_try_node(i, render_nodes_fmt);
+               drv_ = init_try_node(i, false, false);
                if (drv_)
                        return 0;
        }
 
        // Try card nodes... for vkms mostly.
        for (uint32_t i = min_card_node; i < max_card_node; i++) {
-               drv_ = init_try_node(i, card_nodes_fmt);
+               drv_ = init_try_node(i, true, false);
                if (drv_)
                        return 0;
        }
 
+#ifdef DRI_GENERIC_DRV
+       // Try card nodes using mesa3d/dri backend
+       for (uint32_t i = min_card_node; i < max_card_node; i++) {
+               drv_ = init_try_node(i, true, true);
+               if (drv_)
+                       return 0;
+       }
+
+       // Try render nodes using mesa3d/dri backend
+       for (uint32_t i = min_render_node; i < max_render_node; i++) {
+               drv_ = init_try_node(i, false, true);
+               if (drv_)
+                       return 0;
+       }
+#endif
+
        return -ENODEV;
 }
 
@@ -257,7 +297,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto
        name = (char *)(&hnd->base.data[hnd->name_offset]);
        snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
 
-       id = drv_bo_get_plane_handle(bo, 0).u32;
+       id = hnd->id;
        auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
                                              hnd->reserved_region_size);
 
@@ -286,10 +326,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
                return 0;
        }
 
-       if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
-               drv_log("drmPrimeFDToHandle failed.\n");
-               return -errno;
-       }
+       id = hnd->id;
 
        if (buffers_.count(id)) {
                buffer = buffers_[id];
@@ -315,8 +352,6 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
                if (!bo)
                        return -EFAULT;
 
-               id = drv_bo_get_plane_handle(bo, 0).u32;
-
                buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
                                                 hnd->reserved_region_size);
                buffers_.emplace(id, buffer);
diff --git a/dri.c b/dri.c
index 1d4aa12..0071bef 100644 (file)
--- a/dri.c
+++ b/dri.c
@@ -4,7 +4,7 @@
  * found in the LICENSE file.
  */
 
-#ifdef DRV_AMDGPU
+#if defined(DRI_GENERIC_DRV) || defined(DRV_AMDGPU)
 
 #include <assert.h>
 #include <dlfcn.h>
 #include "helpers.h"
 #include "util.h"
 
+#ifdef DRI_GENERIC_DRV
+#include <loader.h>
+#endif
+
 static const struct {
        uint32_t drm_format;
        int dri_image_format;
@@ -66,27 +70,28 @@ static bool lookup_extension(const __DRIextension *const *extensions, const char
        return false;
 }
 
-/*
- * Close Gem Handle
- */
-static void close_gem_handle(uint32_t handle, int fd)
+int dri_bo_get_plane_fd(struct bo *bo, size_t plane)
 {
-       struct drm_gem_close gem_close = { 0 };
-       int ret = 0;
+       struct dri_driver *dri = bo->drv->priv;
+       __DRIimage *plane_image = NULL;
+       int fd = -1;
 
-       gem_close.handle = handle;
-       ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-       if (ret)
-               drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", handle, ret);
-}
+       plane_image = dri->image_extension->fromPlanar(bo->priv, plane, NULL);
+       __DRIimage *image = plane_image ? plane_image : bo->priv;
+
+       dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
+
+       if (plane_image)
+               dri->image_extension->destroyImage(plane_image);
 
+       return fd;
+}
 /*
  * The DRI GEM namespace may be different from the minigbm's driver GEM namespace. We have
  * to import into minigbm.
  */
 static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
 {
-       uint32_t handle;
        int ret, modifier_upper, modifier_lower, num_planes, i, j;
        off_t dmabuf_sizes[DRV_MAX_PLANES];
        __DRIimage *plane_image = NULL;
@@ -106,8 +111,6 @@ static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
                return -errno;
        }
 
-       bo->meta.num_planes = num_planes;
-
        for (i = 0; i < num_planes; ++i) {
                int prime_fd, stride, offset;
                plane_image = dri->image_extension->fromPlanar(bo->priv, i, NULL);
@@ -136,17 +139,15 @@ static int import_into_minigbm(struct dri_driver *dri, struct bo *bo)
 
                lseek(prime_fd, 0, SEEK_SET);
 
-               ret = drmPrimeFDToHandle(bo->drv->fd, prime_fd, &handle);
-
                close(prime_fd);
 
-               if (ret) {
-                       drv_log("drmPrimeFDToHandle failed with %s\n", strerror(errno));
+               if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE,
+                                                     &bo->handles[i].s32)) {
+                       drv_log("queryImage() failed with %s\n", strerror(errno));
+                       ret = -errno;
                        goto cleanup;
                }
 
-               bo->handles[i].u32 = handle;
-
                bo->meta.strides[i] = stride;
                bo->meta.offsets[i] = offset;
 
@@ -183,11 +184,6 @@ cleanup:
                /* Multiple equivalent handles) */
                if (i == j)
                        break;
-
-               /* This kind of goes horribly wrong when we already imported
-                * the same handles earlier, as we should really reference
-                * count handles. */
-               close_gem_handle(bo->handles[i].u32, bo->drv->fd);
        }
        return ret;
 }
@@ -203,7 +199,7 @@ int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suf
 
        struct dri_driver *dri = drv->priv;
 
-       dri->fd = open(drmGetRenderDeviceNameFromFd(drv_get_fd(drv)), O_RDWR);
+       dri->fd = open(drmGetDeviceNameFromFd(drv_get_fd(drv)), O_RDWR);
        if (dri->fd < 0)
                return -ENODEV;
 
@@ -261,6 +257,39 @@ close_dri_fd:
        close(dri->fd);
        return -ENODEV;
 }
+/*
+ * The caller is responsible for setting drv->priv to a structure that derives from dri_driver.
+ */
+int dri_init2(struct driver *drv)
+{
+#ifdef DRI_GENERIC_DRV
+       char dri_pathname[64];
+       char drv_suffix[32];
+
+       char *drv_name = loader_get_driver_for_fd(drv->fd);
+
+       sprintf(dri_pathname, STRINGIZE(DRI_DRIVER_DIR) "/%s_dri.so", drv_name);
+
+       strcpy(drv_suffix, drv_name);
+       free(drv_name);
+
+       /* replace all '-' chars with '_' in drv_suffix to use in dlsym() */
+       char *current_pos = strchr(drv_suffix, '-');
+       while (current_pos) {
+               *current_pos = '_';
+               current_pos = strchr(current_pos, '-');
+       }
+
+       if (dri_init(drv, dri_pathname, drv_suffix)) {
+               drv_log("dri_init failed for (%s) , (%s)", dri_pathname, drv_suffix);
+               return -ENODEV;
+       }
+
+       return 0;
+#else
+       return -ENOTSUPP;
+#endif
+}
 
 /*
  * The caller is responsible for freeing drv->priv.
@@ -276,14 +305,20 @@ void dri_close(struct driver *drv)
        close(dri->fd);
 }
 
-int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-                 uint64_t use_flags)
+int dri_bo_create_common(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+                        uint64_t use_flags, const uint64_t *modifiers, uint32_t modifier_count)
 {
+       uint32_t width_ = width;
+       uint32_t height_ = height;
        unsigned int dri_use;
        int ret, dri_format;
+       int dri_format_unavailable = false;
        struct dri_driver *dri = bo->drv->priv;
 
        dri_format = drm_format_to_dri_format(format);
+       /* Video buffers can't be allocated using DRI */
+       if (!dri_format)
+               dri_format_unavailable = true;
 
        /* Gallium drivers require shared to get the handle and stride. */
        dri_use = __DRI_IMAGE_USE_SHARE;
@@ -291,50 +326,65 @@ int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t forma
                dri_use |= __DRI_IMAGE_USE_SCANOUT;
        if (use_flags & BO_USE_CURSOR)
                dri_use |= __DRI_IMAGE_USE_CURSOR;
-       if (use_flags & BO_USE_LINEAR)
+       if (use_flags & (BO_USE_LINEAR | BO_USE_SW_MASK))
                dri_use |= __DRI_IMAGE_USE_LINEAR;
 
-       bo->priv = dri->image_extension->createImage(dri->device, width, height, dri_format,
-                                                    dri_use, NULL);
+       if (dri_format_unavailable) {
+               int stride = drv_stride_from_format(format, width, 0);
+               drv_bo_from_format(bo, stride, height, format);
+               dri_format = __DRI_IMAGE_FORMAT_R8;
+               dri_use |= __DRI_IMAGE_USE_LINEAR;
+               width_ = stride /  drv_bytes_per_pixel_from_format(format, 0);
+               height_ = DIV_ROUND_UP(bo->meta.total_size, width_);
+       }
+
+       if (modifier_count == 0) {
+               bo->priv = dri->image_extension->createImage(dri->device, width_, height_,
+                                                            dri_format, dri_use, NULL);
+       } else {
+               if (!dri->image_extension->createImageWithModifiers) {
+                       return -ENOENT;
+               }
+               bo->priv = dri->image_extension->createImageWithModifiers(
+                   dri->device, width, height, dri_format, modifiers, modifier_count, NULL);
+       }
+
        if (!bo->priv) {
                ret = -errno;
                return ret;
        }
 
-       ret = import_into_minigbm(dri, bo);
-       if (ret)
-               goto free_image;
-
-       return 0;
+       if (dri_format_unavailable) {
+               __DRIimage *plane_image = dri->image_extension->fromPlanar(bo->priv, 0, NULL);
+               __DRIimage *image = plane_image ? plane_image : bo->priv;
 
-free_image:
-       dri->image_extension->destroyImage(bo->priv);
-       return ret;
-}
+               if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE,
+                                                     &bo->handles[0].s32)) {
+                       drv_log("queryImage() failed with error %s\n", strerror(errno));
+                       ret = -errno;
+                       goto free_image;
+               }
 
-int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-                                const uint64_t *modifiers, uint32_t modifier_count)
-{
-       int ret, dri_format;
-       struct dri_driver *dri = bo->drv->priv;
+               if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE,
+                                                     (int32_t *)&bo->meta.strides[0])) {
+                       drv_log("queryImage() failed with error %s\n", strerror(errno));
+                       ret = -errno;
+                       goto free_image;
+               }
 
-       if (!dri->image_extension->createImageWithModifiers) {
-               return -ENOENT;
-       }
+               drv_bo_from_format(bo, bo->meta.strides[0], height, format);
 
-       dri_format = drm_format_to_dri_format(format);
+               if (plane_image)
+                       dri->image_extension->destroyImage(plane_image);
 
-       bo->priv = dri->image_extension->createImageWithModifiers(
-           dri->device, width, height, dri_format, modifiers, modifier_count, NULL);
-       if (!bo->priv) {
-               ret = -errno;
-               return ret;
+               for (size_t plane = 1; plane < bo->meta.num_planes; plane++)
+                       bo->handles[plane].u32 = bo->handles[0].u32;
+       } else {
+               ret = import_into_minigbm(dri, bo);
+               if (ret)
+                       goto free_image;
        }
 
-       ret = import_into_minigbm(dri, bo);
-       if (ret)
-               goto free_image;
-
        return 0;
 
 free_image:
@@ -342,6 +392,18 @@ free_image:
        return ret;
 }
 
+int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+                 uint64_t use_flags)
+{
+       return dri_bo_create_common(bo, width, height, format, use_flags, NULL, 0);
+}
+
+int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+                                const uint64_t *modifiers, uint32_t modifier_count)
+{
+       return dri_bo_create_common(bo, width, height, format, 0, modifiers, modifier_count);
+}
+
 int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data)
 {
        int ret;
@@ -397,7 +459,6 @@ int dri_bo_destroy(struct bo *bo)
        struct dri_driver *dri = bo->drv->priv;
 
        assert(bo->priv);
-       close_gem_handle(bo->handles[0].u32, bo->drv->fd);
        dri->image_extension->destroyImage(bo->priv);
        bo->priv = NULL;
        return 0;
diff --git a/dri.h b/dri.h
index 6218e82..f49802c 100644 (file)
--- a/dri.h
+++ b/dri.h
@@ -4,8 +4,12 @@
  * found in the LICENSE file.
  */
 
-#ifdef DRV_AMDGPU
+#if defined(DRI_GENERIC_DRV) || defined(DRV_AMDGPU)
 
+#ifndef __DRIH__
+#define __DRIH__
+
+#define HAVE_LIBDRM
 // Avoid transitively including a bunch of unnecessary headers.
 #define GL_GLEXT_LEGACY
 #include "GL/internal/dri_interface.h"
@@ -27,6 +31,7 @@ struct dri_driver {
 };
 
 int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suffix);
+int dri_init2(struct driver *drv);
 void dri_close(struct driver *drv);
 int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
                  uint64_t use_flags);
@@ -36,6 +41,10 @@ int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data);
 int dri_bo_destroy(struct bo *bo);
 void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
 int dri_bo_unmap(struct bo *bo, struct vma *vma);
+int dri_bo_get_plane_fd(struct bo *bo, size_t plane);
+
 size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier);
 
 #endif
+
+#endif
diff --git a/dri_generic_driver.c b/dri_generic_driver.c
new file mode 100644 (file)
index 0000000..135803d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRI_GENERIC_DRV
+
+#include <string.h>
+#include <xf86drm.h>
+
+#include "dri.h"
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+#include <errno.h>
+
+static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
+                                                  DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888,
+                                                  DRM_FORMAT_RGB565 };
+
+static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
+                                                DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
+
+static int dri_generic_init(struct driver *drv)
+{
+       struct dri_driver *dri;
+
+       dri = calloc(1, sizeof(struct dri_driver));
+       if (!dri)
+               return -ENOMEM;
+
+       drv->priv = dri;
+
+       if (dri_init2(drv)) {
+               free(dri);
+               drv->priv = NULL;
+               return -ENODEV;
+       }
+
+       drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
+                            &LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
+
+       drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats),
+                            &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+
+       drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
+                              BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER |
+                                  BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
+       drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
+
+       return drv_modify_linear_combinations(drv);
+}
+
+static uint32_t dri_generic_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+       switch (format) {
+       case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+               /* Camera subsystem requires NV12. */
+               if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+                       return DRM_FORMAT_NV12;
+               /*HACK: See b/28671744 */
+               return DRM_FORMAT_XBGR8888;
+       case DRM_FORMAT_FLEX_YCbCr_420_888:
+               return DRM_FORMAT_NV12;
+       case DRM_FORMAT_BGR565:
+               /* mesa3d doesn't support BGR565 */
+               return DRM_FORMAT_RGB565;
+       default:
+               return format;
+       }
+}
+
+const struct backend backend_dri_generic = {
+       .name = "dri_generic",
+       .init = dri_generic_init,
+       .close = dri_close,
+       .bo_create = dri_bo_create,
+       .bo_create_with_modifiers = dri_bo_create_with_modifiers,
+       .bo_destroy = dri_bo_destroy,
+       .bo_import = dri_bo_import,
+       .bo_map = dri_bo_map,
+       .bo_unmap = dri_bo_unmap,
+       .bo_get_plane_fd = dri_bo_get_plane_fd,
+       .resolve_format = dri_generic_resolve_format,
+       .num_planes_from_modifier = dri_num_planes_from_modifier,
+};
+
+#endif
diff --git a/drv.c b/drv.c
index 5c8f9a0..3020c35 100644 (file)
--- a/drv.c
+++ b/drv.c
@@ -50,6 +50,7 @@ extern const struct backend backend_tegra;
 extern const struct backend backend_vc4;
 #endif
 
+#ifndef DRI_GENERIC_DRV
 // Dumb / generic drivers
 extern const struct backend backend_evdi;
 extern const struct backend backend_marvell;
@@ -61,6 +62,11 @@ extern const struct backend backend_synaptics;
 extern const struct backend backend_virtio_gpu;
 extern const struct backend backend_udl;
 extern const struct backend backend_vkms;
+#endif
+
+#ifdef DRI_GENERIC_DRV
+extern const struct backend backend_dri_generic;
+#endif
 
 static const struct backend *drv_get_backend(int fd)
 {
@@ -94,9 +100,11 @@ static const struct backend *drv_get_backend(int fd)
 #ifdef DRV_VC4
                &backend_vc4,
 #endif
+#ifndef DRI_GENERIC_DRV
                &backend_evdi,     &backend_marvell,    &backend_meson,     &backend_nouveau,
                &backend_komeda,   &backend_radeon,     &backend_synaptics, &backend_virtio_gpu,
                &backend_udl,      &backend_virtio_gpu, &backend_vkms
+#endif
        };
 
        for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
@@ -119,7 +127,7 @@ static const struct backend *drv_get_backend(int fd)
        return NULL;
 }
 
-struct driver *drv_create(int fd)
+struct driver *drv_create(int fd, bool try_generic)
 {
        struct driver *drv;
        int ret;
@@ -136,6 +144,11 @@ struct driver *drv_create(int fd)
        drv->fd = fd;
        drv->backend = drv_get_backend(fd);
 
+#ifdef DRI_GENERIC_DRV
+       if (!drv->backend && try_generic)
+               drv->backend = &backend_dri_generic;
+#endif
+
        if (!drv->backend)
                goto free_driver;
 
@@ -607,6 +620,13 @@ int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
                return -EINVAL;
        }
 
+       if (bo->drv->backend->bo_get_plane_fd) {
+               fd = bo->drv->backend->bo_get_plane_fd(bo, plane);
+
+               if (fd >= 0)
+                       return fd;
+       }
+
        ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
 
        // Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping anyways
diff --git a/drv.h b/drv.h
index 4a47b76..88c4a67 100644 (file)
--- a/drv.h
+++ b/drv.h
@@ -116,7 +116,7 @@ struct mapping {
        uint32_t refcount;
 };
 
-struct driver *drv_create(int fd);
+struct driver *drv_create(int fd, bool try_generic);
 
 void drv_destroy(struct driver *drv);
 
index 6ce7fa1..3f7a2fd 100644 (file)
@@ -73,6 +73,7 @@ struct backend {
        int (*bo_compute_metadata)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
                                   uint64_t use_flags, const uint64_t *modifiers, uint32_t count);
        int (*bo_create_from_metadata)(struct bo *bo);
+       int (*bo_get_plane_fd)(struct bo *bo, size_t plane);
        int (*bo_destroy)(struct bo *bo);
        int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data);
        void *(*bo_map)(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
index f5a62aa..c9becbc 100644 (file)
@@ -4,6 +4,8 @@
  * found in the LICENSE file.
  */
 
+#ifndef DRI_GENERIC_DRV
+
 #include "drv_priv.h"
 #include "helpers.h"
 #include "util.h"
@@ -51,3 +53,5 @@ INIT_DUMB_DRIVER(radeon)
 INIT_DUMB_DRIVER(synaptics)
 INIT_DUMB_DRIVER(udl)
 INIT_DUMB_DRIVER(vkms)
+
+#endif