OSDN Git Service

Distinguish COMPOSER_TARGET_BUFFER
[android-x86/external-minigbm.git] / dri.c
diff --git a/dri.c b/dri.c
index 950d616..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,42 +72,122 @@ static bool lookup_extension(const __DRIextension *const *extensions, const char
        return false;
 }
 
+int dri_bo_get_plane_fd(struct bo *bo, size_t plane)
+{
+       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 prime_fd, ret;
+       int ret, modifier_upper, modifier_lower, num_planes, i, j;
+       off_t dmabuf_sizes[DRV_MAX_PLANES];
+       __DRIimage *plane_image = NULL;
 
-       if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_FD, &prime_fd))
+       if (dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
+                                            &modifier_upper) &&
+           dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
+                                            &modifier_lower)) {
+               bo->meta.format_modifiers[0] =
+                   ((uint64_t)modifier_upper << 32) | (uint32_t)modifier_lower;
+       } else {
+               bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_INVALID;
+       }
+
+       if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_NUM_PLANES,
+                                             &num_planes)) {
                return -errno;
+       }
 
-       ret = drmPrimeFDToHandle(bo->drv->fd, prime_fd, &handle);
-       if (ret) {
-               drv_log("drmPrimeFDToHandle failed with %s\n", strerror(errno));
-               return ret;
+       for (i = 0; i < num_planes; ++i) {
+               int prime_fd, stride, offset;
+               plane_image = dri->image_extension->fromPlanar(bo->priv, i, NULL);
+               __DRIimage *image = plane_image ? plane_image : bo->priv;
+
+               if (i)
+                       bo->meta.format_modifiers[i] = bo->meta.format_modifiers[0];
+
+               if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride) ||
+                   !dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset)) {
+                       ret = -errno;
+                       goto cleanup;
+               }
+
+               if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &prime_fd)) {
+                       ret = -errno;
+                       goto cleanup;
+               }
+
+               dmabuf_sizes[i] = lseek(prime_fd, 0, SEEK_END);
+               if (dmabuf_sizes[i] == (off_t)-1) {
+                       ret = -errno;
+                       close(prime_fd);
+                       goto cleanup;
+               }
+
+               lseek(prime_fd, 0, SEEK_SET);
+
+               close(prime_fd);
+
+               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->meta.strides[i] = stride;
+               bo->meta.offsets[i] = offset;
+
+               if (plane_image)
+                       dri->image_extension->destroyImage(plane_image);
+       }
+
+       for (i = 0; i < num_planes; ++i) {
+               off_t next_plane = dmabuf_sizes[i];
+               for (j = 0; j < num_planes; ++j) {
+                       if (bo->meta.offsets[j] < next_plane &&
+                           bo->meta.offsets[j] > bo->meta.offsets[i] &&
+                           bo->handles[j].u32 == bo->handles[i].u32)
+                               next_plane = bo->meta.offsets[j];
+               }
+
+               bo->meta.sizes[i] = next_plane - bo->meta.offsets[i];
+
+               /* This is kind of misleading if different planes use
+                  different dmabufs. */
+               bo->meta.total_size += bo->meta.sizes[i];
        }
 
-       bo->handles[0].u32 = handle;
-       close(prime_fd);
        return 0;
-}
 
-/*
- * Close Gem Handle
- */
-static void close_gem_handle(uint32_t handle, int fd)
-{
-       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);
+cleanup:
+       if (plane_image)
+               dri->image_extension->destroyImage(plane_image);
+       while (--i >= 0) {
+               for (j = 0; j <= i; ++j)
+                       if (bo->handles[j].u32 == bo->handles[i].u32)
+                               break;
+
+               /* Multiple equivalent handles) */
+               if (i == j)
+                       break;
+       }
+       return ret;
 }
 
 /*
@@ -113,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;
 
@@ -171,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.
@@ -186,16 +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, stride, offset;
-       int modifier_upper, modifier_lower;
+       int ret, dri_format;
+       int dri_format_unavailable = false;
        struct dri_driver *dri = bo->drv->priv;
 
-       assert(bo->meta.num_planes == 1);
        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;
@@ -203,69 +328,124 @@ 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;
+       if (dri_format_unavailable) {
+               __DRIimage *plane_image = dri->image_extension->fromPlanar(bo->priv, 0, NULL);
+               __DRIimage *image = plane_image ? plane_image : bo->priv;
 
-       if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_STRIDE, &stride)) {
-               ret = -errno;
-               goto close_handle;
-       }
+               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;
+               }
 
-       if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_OFFSET, &offset)) {
-               ret = -errno;
-               goto close_handle;
-       }
+               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->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
-                                            &modifier_upper) &&
-           dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
-                                            &modifier_lower)) {
-               bo->meta.format_modifiers[0] =
-                   ((uint64_t)modifier_upper << 32) | (uint32_t)modifier_lower;
+               drv_bo_from_format(bo, bo->meta.strides[0], height, format);
+
+               if (plane_image)
+                       dri->image_extension->destroyImage(plane_image);
+
+               for (size_t plane = 1; plane < bo->meta.num_planes; plane++)
+                       bo->handles[plane].u32 = bo->handles[0].u32;
        } else {
-               bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_INVALID;
+               ret = import_into_minigbm(dri, bo);
+               if (ret)
+                       goto free_image;
        }
 
-       bo->meta.strides[0] = stride;
-       bo->meta.sizes[0] = stride * height;
-       bo->meta.offsets[0] = offset;
-       bo->meta.total_size = offset + bo->meta.sizes[0];
        return 0;
 
-close_handle:
-       close_gem_handle(bo->handles[0].u32, bo->drv->fd);
 free_image:
        dri->image_extension->destroyImage(bo->priv);
        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;
        struct dri_driver *dri = bo->drv->priv;
 
-       assert(bo->meta.num_planes == 1);
-
-       // clang-format off
-       bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
-                                                           data->format, data->fds,
-                                                           bo->meta.num_planes,
-                                                           (int *)data->strides,
-                                                           (int *)data->offsets, NULL);
-       // clang-format on
-       if (!bo->priv)
-               return -errno;
+       if (data->format_modifiers[0] != DRM_FORMAT_MOD_INVALID) {
+               unsigned error;
+
+               if (!dri->image_extension->createImageFromDmaBufs2)
+                       return -ENOSYS;
+
+               // clang-format off
+               bo->priv = dri->image_extension->createImageFromDmaBufs2(dri->device, data->width, data->height,
+                                                                        drv_get_standard_fourcc(data->format),
+                                                                        data->format_modifiers[0],
+                                                                        data->fds,
+                                                                        bo->meta.num_planes,
+                                                                        (int *)data->strides,
+                                                                        (int *)data->offsets,
+                                                                        __DRI_YUV_COLOR_SPACE_UNDEFINED,
+                                                                        __DRI_YUV_RANGE_UNDEFINED,
+                                                                        __DRI_YUV_CHROMA_SITING_UNDEFINED,
+                                                                        __DRI_YUV_CHROMA_SITING_UNDEFINED,
+                                                                        &error, NULL);
+               // clang-format on
+
+               /* Could translate the DRI error, but the Mesa GBM also returns ENOSYS. */
+               if (!bo->priv)
+                       return -ENOSYS;
+       } else {
+               // clang-format off
+               bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
+                                                                   drv_get_standard_fourcc(data->format), data->fds,
+                                                                   bo->meta.num_planes,
+                                                                   (int *)data->strides,
+                                                                   (int *)data->offsets, NULL);
+               // clang-format on
+               if (!bo->priv)
+                       return -errno;
+       }
 
        ret = import_into_minigbm(dri, bo);
        if (ret) {
@@ -281,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;
@@ -329,4 +508,22 @@ int dri_bo_unmap(struct bo *bo, struct vma *vma)
        return 0;
 }
 
+size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier)
+{
+       struct dri_driver *dri = drv->priv;
+       if (!dri->image_extension->queryDmaBufFormatModifierAttribs) {
+               /* We do not do any modifier checks here. The create will fail
+                * later if the modifier is not supported. */
+               return drv_num_planes_from_format(format);
+       }
+
+       uint64_t planes;
+       GLboolean ret = dri->image_extension->queryDmaBufFormatModifierAttribs(
+           dri->device, format, modifier, __DRI_IMAGE_ATTRIB_NUM_PLANES, &planes);
+       if (!ret)
+               return 0;
+
+       return planes;
+}
+
 #endif