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>
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);
+}
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 &);
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. */
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 &);
* found in the LICENSE file.
*/
+#include "../../util.h"
#include "../cros_gralloc_driver.h"
#include <cassert>
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) {
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 *);
{
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),
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:
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:
#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;
+}
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__); \
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
__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 {
}
}
+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,
.bo_invalidate = virtio_gpu_bo_invalidate,
.bo_flush = virtio_gpu_bo_flush,
.resolve_format = virtio_gpu_resolve_format,
+ .resource_info = virtio_gpu_resource_info,
};