OSDN Git Service

minigbm: add resource_info callback for virtio-gpu
authorGurchetan Singh <gurchetansingh@google.com>
Fri, 28 Jun 2019 03:05:54 +0000 (20:05 -0700)
committerCommit Bot <commit-bot@chromium.org>
Thu, 26 Mar 2020 21:48:47 +0000 (21:48 +0000)
In ARC++, the wayland sevice and the video stack rely on
GRALLOC_DRM_GET_STRIDE and (*lock_ycbcr) with zero flags to return
the metadata associated with the buffer.

In the past, we've simply returned the metadata that was calculated
during allocation.

Since the current virtio-gpu API relies on shadow buffers, there's
actually two different sets of metadata:

1) The metadata of the shadow buffer --> useful for mapping
2) The metadata of the host resource --> useful for passing to Chrome

For the wayland_service and video stack, we want to return (2).
For the Android framework, we want to return (1).

BUG=b:132939420
TEST=compile

Change-Id: I1134d651396ba68e064eaf2e3cad3cb3225d7c5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/1681383
Reviewed-by: David Stevens <stevensd@chromium.org>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
cros_gralloc/cros_gralloc_buffer.cc
cros_gralloc/cros_gralloc_buffer.h
cros_gralloc/cros_gralloc_driver.cc
cros_gralloc/cros_gralloc_driver.h
cros_gralloc/gralloc0/gralloc0.cc
drv.c
drv.h
drv_priv.h
virtgpu_drm.h
virtio_gpu.c

index 01d4038..1066edc 100644 (file)
@@ -108,3 +108,9 @@ int32_t cros_gralloc_buffer::unlock()
 
        return 0;
 }
+
+int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
+                                          uint32_t offsets[DRV_MAX_PLANES])
+{
+       return drv_resource_info(bo_, strides, offsets);
+}
index e6aec91..ebd72ec 100644 (file)
@@ -26,6 +26,7 @@ class cros_gralloc_buffer
        int32_t lock(const struct rectangle *rect, uint32_t map_flags,
                     uint8_t *addr[DRV_MAX_PLANES]);
        int32_t unlock();
+       int32_t resource_info(uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES]);
 
       private:
        cros_gralloc_buffer(cros_gralloc_buffer const &);
index 89897e0..62b43d4 100644 (file)
@@ -333,6 +333,26 @@ int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t
        return 0;
 }
 
+int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
+                                          uint32_t offsets[DRV_MAX_PLANES])
+{
+       std::lock_guard<std::mutex> lock(mutex_);
+
+       auto hnd = cros_gralloc_convert_handle(handle);
+       if (!hnd) {
+               drv_log("Invalid handle.\n");
+               return -EINVAL;
+       }
+
+       auto buffer = get_buffer(hnd);
+       if (!buffer) {
+               drv_log("Invalid Reference.\n");
+               return -EINVAL;
+       }
+
+       return buffer->resource_info(strides, offsets);
+}
+
 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
 {
        /* Assumes driver mutex is held. */
index 45782c9..f051277 100644 (file)
@@ -31,6 +31,8 @@ class cros_gralloc_driver
        int32_t unlock(buffer_handle_t handle, int32_t *release_fence);
 
        int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store);
+       int32_t resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
+                             uint32_t offsets[DRV_MAX_PLANES]);
 
       private:
        cros_gralloc_driver(cros_gralloc_driver const &);
index 0a302b4..6c49d3a 100644 (file)
@@ -4,6 +4,7 @@
  * found in the LICENSE file.
  */
 
+#include "../../util.h"
 #include "../cros_gralloc_driver.h"
 
 #include <cassert>
@@ -261,6 +262,8 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
        uint64_t *out_store;
        buffer_handle_t handle;
        uint32_t *out_width, *out_height, *out_stride;
+       uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
+       uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
        auto mod = (struct gralloc0_module const *)module;
 
        switch (op) {
@@ -286,7 +289,17 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
        switch (op) {
        case GRALLOC_DRM_GET_STRIDE:
                out_stride = va_arg(args, uint32_t *);
-               *out_stride = hnd->pixel_stride;
+               ret = mod->driver->resource_info(handle, strides, offsets);
+               if (ret)
+                       break;
+
+               if (strides[0] != hnd->strides[0]) {
+                       uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
+                       *out_stride = DIV_ROUND_UP(strides[0], bytes_per_pixel);
+               } else {
+                       *out_stride = hnd->pixel_stride;
+               }
+
                break;
        case GRALLOC_DRM_GET_FORMAT:
                out_format = va_arg(args, int32_t *);
@@ -364,6 +377,8 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
 {
        int32_t ret;
        uint32_t map_flags;
+       uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
+       uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
        uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
        auto mod = (struct gralloc0_module const *)module;
        struct rectangle rect = { .x = static_cast<uint32_t>(l),
@@ -393,13 +408,22 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
        if (ret)
                return ret;
 
+       if (!map_flags) {
+               ret = mod->driver->resource_info(handle, strides, offsets);
+               if (ret)
+                       return ret;
+
+               for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
+                       addr[plane] = static_cast<uint8_t *>(nullptr) + offsets[plane];
+       }
+
        switch (hnd->format) {
        case DRM_FORMAT_NV12:
                ycbcr->y = addr[0];
                ycbcr->cb = addr[1];
                ycbcr->cr = addr[1] + 1;
-               ycbcr->ystride = hnd->strides[0];
-               ycbcr->cstride = hnd->strides[1];
+               ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
+               ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
                ycbcr->chroma_step = 2;
                break;
        case DRM_FORMAT_YVU420:
@@ -407,8 +431,8 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
                ycbcr->y = addr[0];
                ycbcr->cb = addr[2];
                ycbcr->cr = addr[1];
-               ycbcr->ystride = hnd->strides[0];
-               ycbcr->cstride = hnd->strides[1];
+               ycbcr->ystride = (!map_flags) ? strides[0] : hnd->strides[0];
+               ycbcr->cstride = (!map_flags) ? strides[1] : hnd->strides[1];
                ycbcr->chroma_step = 1;
                break;
        default:
diff --git a/drv.c b/drv.c
index 8009bac..920cf4d 100644 (file)
--- a/drv.c
+++ b/drv.c
@@ -691,3 +691,17 @@ void drv_log_prefix(const char *prefix, const char *file, int line, const char *
 #endif
        va_end(args);
 }
+
+int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+                     uint32_t offsets[DRV_MAX_PLANES])
+{
+       for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
+               strides[plane] = bo->meta.strides[plane];
+               offsets[plane] = bo->meta.offsets[plane];
+       }
+
+       if (bo->drv->backend->resource_info)
+               return bo->drv->backend->resource_info(bo, strides, offsets);
+
+       return 0;
+}
diff --git a/drv.h b/drv.h
index 6642a3d..2b86aad 100644 (file)
--- a/drv.h
+++ b/drv.h
@@ -179,6 +179,9 @@ size_t drv_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_
 
 uint32_t drv_num_buffers_per_bo(struct bo *bo);
 
+int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+                     uint32_t offsets[DRV_MAX_PLANES]);
+
 #define drv_log(format, ...)                                                                       \
        do {                                                                                       \
                drv_log_prefix("minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__);              \
index 4eb1ee1..32c082d 100644 (file)
@@ -80,6 +80,8 @@ struct backend {
        int (*bo_flush)(struct bo *bo, struct mapping *mapping);
        uint32_t (*resolve_format)(struct driver *drv, uint32_t format, uint64_t use_flags);
        size_t (*num_planes_from_modifier)(struct driver *drv, uint32_t format, uint64_t modifier);
+       int (*resource_info)(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+                            uint32_t offsets[DRV_MAX_PLANES]);
 };
 
 // clang-format off
index f06a789..a92d764 100644 (file)
@@ -100,7 +100,13 @@ struct drm_virtgpu_resource_info {
        __u32 bo_handle;
        __u32 res_handle;
        __u32 size;
-       __u32 stride;
+       union {
+               __u32 stride;
+               __u32 strides[4]; /* strides[0] is accessible with stride. */
+       };
+       __u32 num_planes;
+       __u32 offsets[4];
+       __u64 format_modifier;
 };
 
 struct drm_virtgpu_3d_box {
index b5e5878..eb6c97d 100644 (file)
@@ -505,6 +505,38 @@ static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, u
        }
 }
 
+static int virtio_gpu_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+                                   uint32_t offsets[DRV_MAX_PLANES])
+{
+       int ret;
+       struct drm_virtgpu_resource_info res_info;
+       struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+
+       if (!priv->has_3d)
+               return 0;
+
+       memset(&res_info, 0, sizeof(res_info));
+       res_info.bo_handle = bo->handles[0].u32;
+       ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &res_info);
+       if (ret) {
+               drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno));
+               return ret;
+       }
+
+       for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
+               /*
+                * Currently, kernel v4.14 (Betty) doesn't have the extended resource info
+                * ioctl.
+                */
+               if (res_info.strides[plane]) {
+                       strides[plane] = res_info.strides[plane];
+                       offsets[plane] = res_info.offsets[plane];
+               }
+       }
+
+       return 0;
+}
+
 const struct backend backend_virtio_gpu = {
        .name = "virtio_gpu",
        .init = virtio_gpu_init,
@@ -517,4 +549,5 @@ const struct backend backend_virtio_gpu = {
        .bo_invalidate = virtio_gpu_bo_invalidate,
        .bo_flush = virtio_gpu_bo_flush,
        .resolve_format = virtio_gpu_resolve_format,
+       .resource_info = virtio_gpu_resource_info,
 };