Many GL drivers assume that first value in the native_handle data
array is the fd associated with the graphics buffer, i.e,
int prime_fd = handle->data[0];
This in our case until
4bfc7401. We added 64-bit modifiers in
our import data, so all values in the drv_import_fd_data struct get
8-byte aligned. In our cros_gralloc_handle, 4 bytes of padding
are added between native_handle_t and drv_import_fd_data to make
the alignment work. To counter-act this, we can stop embedding
drv_import_fd_data in cros_gralloc_handle.
BUG=chromium:616275
TEST=Mali driver doesn't return an error when running cros_gralloc
CQ-DEPEND=CL:414585
Change-Id: Ib6c165e98126468b96fa7119d5ca13eebee1655c
Reviewed-on: https://chromium-review.googlesource.com/414536
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
return NULL;
}
+ /*
+ * If there is a desire for more than one kernel buffer, this can be
+ * removed once the ArcCodec and Wayland service have the ability to
+ * send more than one fd. GL/Vulkan drivers may also have to modified.
+ */
if (drv_num_buffers_per_bo(bo->bo) != 1) {
drv_bo_destroy(bo->bo);
delete bo;
static struct cros_gralloc_handle *cros_gralloc_handle_from_bo(struct bo *bo)
{
+ uint64_t mod;
+ size_t num_planes;
struct cros_gralloc_handle *hnd;
hnd = new cros_gralloc_handle();
memset(hnd, 0, sizeof(*hnd));
- hnd->base.version = sizeof(hnd->base);
- hnd->base.numFds = 1;
- hnd->base.numInts = num_ints();
+ num_planes = drv_bo_get_num_planes(bo);
- for (size_t p = 0; p < drv_bo_get_num_planes(bo); p++) {
- hnd->data.strides[p] = drv_bo_get_plane_stride(bo, p);
- hnd->data.offsets[p] = drv_bo_get_plane_offset(bo, p);
- hnd->data.sizes[p] = drv_bo_get_plane_size(bo, p);
+ hnd->base.version = sizeof(hnd->base);
+ hnd->base.numFds = num_planes;
+ hnd->base.numInts = num_ints_handle() - num_planes;
+
+ for (size_t p = 0; p < num_planes; p++) {
+ hnd->fds[p] = drv_bo_get_plane_fd(bo, p);
+ hnd->strides[p] = drv_bo_get_plane_stride(bo, p);
+ hnd->offsets[p] = drv_bo_get_plane_offset(bo, p);
+ hnd->sizes[p] = drv_bo_get_plane_size(bo, p);
+
+ mod = drv_bo_get_plane_format_modifier(bo, p);
+ hnd->format_modifiers[p] = static_cast<uint32_t>(mod >> 32);
+ hnd->format_modifiers[p+1] = static_cast<uint32_t>(mod);
}
- hnd->data.fds[0] = drv_bo_get_plane_fd(bo, 0);
- hnd->data.width = drv_bo_get_width(bo);
- hnd->data.height = drv_bo_get_height(bo);
- hnd->data.format = drv_bo_get_format(bo);
+ hnd->width = drv_bo_get_width(bo);
+ hnd->height = drv_bo_get_height(bo);
+ hnd->format = drv_bo_get_format(bo);
hnd->magic = cros_gralloc_magic();
hnd->registrations = 0;
- hnd->pixel_stride = hnd->data.strides[0];
- hnd->pixel_stride /= drv_stride_from_format(hnd->data.format, 1, 0);
+ hnd->pixel_stride = hnd->strides[0];
+ hnd->pixel_stride /= drv_stride_from_format(hnd->format, 1, 0);
return hnd;
}
return CROS_GRALLOC_ERROR_NO_RESOURCES;
auto hnd = cros_gralloc_handle_from_bo(bo->bo);
- hnd->format = static_cast<int32_t>(format);
+ hnd->droid_format = static_cast<int32_t>(format);
hnd->usage = static_cast<int32_t>(usage);
hnd->bo = reinterpret_cast<uint64_t>(bo);
#include <cutils/native_handle.h>
#include <cstdint>
-#include "../drv.h"
+#define DRV_MAX_PLANES 4
+
+/*
+ * Only use 32-bit integers in the handle. This guarantees that the handle is
+ * densely packed (i.e, the compiler does not insert any padding).
+ */
struct cros_gralloc_handle {
native_handle_t base;
- drv_import_fd_data data;
+ int32_t fds[DRV_MAX_PLANES];
+ uint32_t strides[DRV_MAX_PLANES];
+ uint32_t offsets[DRV_MAX_PLANES];
+ uint32_t sizes[DRV_MAX_PLANES];
+ uint32_t format_modifiers[2 * DRV_MAX_PLANES];
+ uint32_t width;
+ uint32_t height;
+ uint32_t format; /* DRM format */
uint32_t magic;
uint32_t pixel_stride;
- int32_t format, usage; /* Android format and usage. */
- uint64_t bo; /* Pointer to cros_gralloc_bo. */
- int32_t registrations; /*
- * Number of times (*register)() has been
- * called on this handle.
- */
+ int32_t droid_format;
+ int32_t usage; /* Android usage. */
+ uint64_t bo; /* Pointer to cros_gralloc_bo. */
+ int32_t registrations; /*
+ * Number of times (*register)() has been
+ * called on this handle.
+ */
};
#endif
#ifndef CROS_GRALLOC_HELPERS_H
#define CROS_GRALLOC_HELPERS_H
+#include "../drv.h"
#include "cros_gralloc_handle.h"
#include <hardware/gralloc.h>
return 0xABCDDCBA;
}
-constexpr uint32_t num_ints(void)
+constexpr uint32_t num_ints_handle()
{
- /*
- * numFds in our case is one. Subtract that from our numInts
- * calculation.
- */
- return ((sizeof(struct cros_gralloc_handle)
- - offsetof(cros_gralloc_handle, data)) / sizeof(int)) - 1;
+ return ((sizeof(struct cros_gralloc_handle)) / sizeof(int));
}
constexpr uint32_t sw_access(void)
return CROS_GRALLOC_ERROR_NONE;
}
- if (drmPrimeFDToHandle(drv_get_fd(mod->drv), hnd->data.fds[0], &id)) {
+ if (drmPrimeFDToHandle(drv_get_fd(mod->drv), hnd->fds[0], &id)) {
cros_gralloc_error("drmPrimeFDToHandle failed.");
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
bo->refcount++;
hnd->bo = reinterpret_cast<uint64_t>(bo);
} else {
- hnd->data.fds[1] = hnd->data.fds[2] = hnd->data.fds[3]
- = hnd->data.fds[0];
+ struct drv_import_fd_data data;
+ size_t num_planes = drv_num_planes_from_format(hnd->format);
+
+ data.format = hnd->format;
+ data.width = hnd->width;
+ data.height = hnd->height;
+ for (size_t p = 0; p < num_planes; p++) {
+ data.fds[p] = hnd->fds[p];
+ data.strides[p] = hnd->strides[p];
+ data.offsets[p] = hnd->offsets[p];
+ data.sizes[p] = hnd->sizes[p];
+ data.format_modifiers[p] = static_cast<uint64_t>
+ (hnd->format_modifiers[p]) << 32;
+ data.format_modifiers[p] |= hnd->format_modifiers[p+1];
+ }
+
bo = new cros_gralloc_bo();
- bo->bo = drv_bo_import(mod->drv, &hnd->data);
+ bo->bo = drv_bo_import(mod->drv, &data);
if (!bo->bo) {
delete bo;
return CROS_GRALLOC_ERROR_NO_RESOURCES;
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
- if (hnd->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
cros_gralloc_error("YUV format not compatible.");
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
break;
case GRALLOC_DRM_GET_FORMAT:
out_format = va_arg(args, int32_t *);
- *out_format = hnd->format;
+ *out_format = hnd->droid_format;
break;
case GRALLOC_DRM_GET_DIMENSIONS:
out_width = va_arg(args, uint32_t *);
out_height = va_arg(args, uint32_t *);
- *out_width = hnd->data.width;
- *out_height = hnd->data.height;
+ *out_width = hnd->width;
+ *out_height = hnd->height;
break;
case GRALLOC_DRM_GET_BACKING_STORE:
out_store = va_arg(args, uint64_t *);
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
- if ((hnd->format != HAL_PIXEL_FORMAT_YCbCr_420_888)) {
+ if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888)) {
cros_gralloc_error("Non-YUV format not compatible.");
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
for (size_t p = 0; p < drv_bo_get_num_planes(bo->bo); p++)
offsets[p] = drv_bo_get_plane_offset(bo->bo, p);
- switch (hnd->data.format) {
+ switch (hnd->format) {
case DRM_FORMAT_NV12:
ycbcr->y = addr;
ycbcr->cb = addr + offsets[1];