From bc4f023bfcc51cf9dcfcfec5bf4177b2e607dd68 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Thu, 27 Jun 2019 20:05:54 -0700 Subject: [PATCH] minigbm: add resource_info callback for virtio-gpu 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 Commit-Queue: Gurchetan Singh Tested-by: Gurchetan Singh --- cros_gralloc/cros_gralloc_buffer.cc | 6 ++++++ cros_gralloc/cros_gralloc_buffer.h | 1 + cros_gralloc/cros_gralloc_driver.cc | 20 ++++++++++++++++++++ cros_gralloc/cros_gralloc_driver.h | 2 ++ cros_gralloc/gralloc0/gralloc0.cc | 34 +++++++++++++++++++++++++++++----- drv.c | 14 ++++++++++++++ drv.h | 3 +++ drv_priv.h | 2 ++ virtgpu_drm.h | 8 +++++++- virtio_gpu.c | 33 +++++++++++++++++++++++++++++++++ 10 files changed, 117 insertions(+), 6 deletions(-) diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc index 01d4038..1066edc 100644 --- a/cros_gralloc/cros_gralloc_buffer.cc +++ b/cros_gralloc/cros_gralloc_buffer.cc @@ -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); +} diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h index e6aec91..ebd72ec 100644 --- a/cros_gralloc/cros_gralloc_buffer.h +++ b/cros_gralloc/cros_gralloc_buffer.h @@ -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 &); diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index 89897e0..62b43d4 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -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 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. */ diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h index 45782c9..f051277 100644 --- a/cros_gralloc/cros_gralloc_driver.h +++ b/cros_gralloc/cros_gralloc_driver.h @@ -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 &); diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc index 0a302b4..6c49d3a 100644 --- a/cros_gralloc/gralloc0/gralloc0.cc +++ b/cros_gralloc/gralloc0/gralloc0.cc @@ -4,6 +4,7 @@ * found in the LICENSE file. */ +#include "../../util.h" #include "../cros_gralloc_driver.h" #include @@ -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(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(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 --- 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 --- 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__); \ diff --git a/drv_priv.h b/drv_priv.h index 4eb1ee1..32c082d 100644 --- a/drv_priv.h +++ b/drv_priv.h @@ -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 diff --git a/virtgpu_drm.h b/virtgpu_drm.h index f06a789..a92d764 100644 --- a/virtgpu_drm.h +++ b/virtgpu_drm.h @@ -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 { diff --git a/virtio_gpu.c b/virtio_gpu.c index b5e5878..eb6c97d 100644 --- a/virtio_gpu.c +++ b/virtio_gpu.c @@ -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, }; -- 2.11.0