OSDN Git Service

Distinguish COMPOSER_TARGET_BUFFER
[android-x86/external-minigbm.git] / dri.c
diff --git a/dri.c b/dri.c
index 97dc567..1dde121 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;
@@ -34,7 +38,11 @@ static const struct {
        { DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888 },
        { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888 },
        { DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010 },
+       { DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010 },
        { DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010 },
+       { DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010 },
+       { DRM_FORMAT_ARGB4444, __DRI_IMAGE_FORMAT_RGB565 },
+
 };
 
 static int drm_format_to_dri_format(uint32_t drm_format)
@@ -64,28 +72,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;
-       int ret = 0;
-
-       memset(&gem_close, 0, sizeof(gem_close));
-       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);
-}
+       struct dri_driver *dri = bo->drv->priv;
+       __DRIimage *plane_image = NULL;
+       int fd = -1;
+
+       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;
@@ -105,8 +113,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);
@@ -135,17 +141,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;
 
@@ -182,11 +186,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;
 }
@@ -202,7 +201,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;
 
@@ -260,6 +259,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.
@@ -275,14 +307,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;
@@ -290,50 +328,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:
@@ -341,6 +394,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;
@@ -354,7 +419,7 @@ int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data)
 
                // clang-format off
                bo->priv = dri->image_extension->createImageFromDmaBufs2(dri->device, data->width, data->height,
-                                                                        data->format,
+                                                                        drv_get_standard_fourcc(data->format),
                                                                         data->format_modifiers[0],
                                                                         data->fds,
                                                                         bo->meta.num_planes,
@@ -373,7 +438,7 @@ int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data)
        } else {
                // clang-format off
                bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
-                                                                   data->format, data->fds,
+                                                                   drv_get_standard_fourcc(data->format), data->fds,
                                                                    bo->meta.num_planes,
                                                                    (int *)data->strides,
                                                                    (int *)data->offsets, NULL);
@@ -396,7 +461,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;