gralloc4: adds gralloc4 support am: 1476c7ea85 am: 06937a2a57
Change-Id: I5187e4cab429cf54e397e6b8f1b559da2820bf2a
diff --git a/Android.bp b/Android.bp
index 63a50f7..02e8e5d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2,17 +2,7 @@
// found in the LICENSE file.
cc_defaults {
- name: "gralloc.minigbm_intel_defaults",
- cflags: ["-DDRV_I915"],
-}
-
-cc_defaults {
- name: "gralloc.minigbm_meson_defaults",
- cflags: ["-DDRV_MESON"],
-}
-
-cc_defaults {
- name: "gralloc.minigbm_defaults",
+ name: "minigbm_defaults",
srcs: [
"amdgpu.c",
@@ -34,11 +24,6 @@
"vc4.c",
"vgem.c",
"virtio_gpu.c",
-
- "cros_gralloc/cros_gralloc_buffer.cc",
- "cros_gralloc/cros_gralloc_driver.cc",
- "cros_gralloc/cros_gralloc_helpers.cc",
- "cros_gralloc/gralloc0/gralloc0.cc",
],
cflags: [
@@ -53,61 +38,50 @@
],
cppflags: ["-std=c++14"],
- // The preferred path for vendor HALs is /vendor/lib/hw
vendor: true,
- relative_install_path: "hw",
header_libs: [
"libhardware_headers",
"libnativebase_headers",
+ "libnativewindow_headers",
+ "libsystem_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libhardware_headers",
+ "libnativebase_headers",
+ "libnativewindow_headers",
"libsystem_headers",
],
shared_libs: [
"libcutils",
"libdrm",
-
"libnativewindow",
"libsync",
"liblog",
],
static_libs: ["libarect"],
+
+ export_static_lib_headers: ["libarect"],
}
-cc_library_shared {
- name: "gralloc.minigbm",
- defaults: ["gralloc.minigbm_defaults"],
+cc_defaults {
+ name: "minigbm_cros_gralloc_defaults",
+
+ defaults: ["minigbm_defaults"],
+
+ srcs: [
+ "cros_gralloc/cros_gralloc_buffer.cc",
+ "cros_gralloc/cros_gralloc_helpers.cc",
+ "cros_gralloc/cros_gralloc_driver.cc",
+ ]
}
-cc_library_shared {
- name: "gralloc.minigbm_intel",
- defaults: [
- "gralloc.minigbm_defaults",
- "gralloc.minigbm_intel_defaults",
- ],
- enabled: false,
- arch: {
- x86: {
- enabled: true,
- },
- x86_64: {
- enabled: true,
- },
- },
-}
-
-cc_library_shared {
- name: "gralloc.minigbm_meson",
- defaults: [
- "gralloc.minigbm_defaults",
- "gralloc.minigbm_meson_defaults",
- ],
-}
-
-cc_library_shared {
+cc_library_static {
name: "libminigbm",
- defaults: ["gralloc.minigbm_defaults"],
+ defaults: ["minigbm_defaults"],
shared_libs: ["liblog"],
static_libs: ["libdrm"],
@@ -118,3 +92,41 @@
export_include_dirs: ["."],
}
+
+cc_library_static {
+ name: "libminigbm_cros_gralloc",
+ defaults: ["minigbm_cros_gralloc_defaults"],
+ shared_libs: ["liblog"],
+ static_libs: ["libdrm"],
+
+ export_include_dirs: ["."],
+}
+
+cc_library_shared {
+ name: "gralloc.minigbm",
+ defaults: ["minigbm_cros_gralloc_defaults"],
+ srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
+
+cc_library_shared {
+ name: "gralloc.minigbm_intel",
+ defaults: ["minigbm_cros_gralloc_defaults"],
+ enabled: false,
+ arch: {
+ x86: {
+ enabled: true,
+ },
+ x86_64: {
+ enabled: true,
+ },
+ },
+ cflags: ["-DDRV_I915"],
+ srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
+
+cc_library_shared {
+ name: "gralloc.minigbm_meson",
+ defaults: ["minigbm_cros_gralloc_defaults"],
+ cflags: ["-DDRV_MESON"],
+ srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
\ No newline at end of file
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index 1066edc..2982505 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -10,8 +10,11 @@
#include <sys/mman.h>
cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
- struct cros_gralloc_handle *acquire_handle)
- : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0)
+ struct cros_gralloc_handle *acquire_handle,
+ int32_t reserved_region_fd, uint64_t reserved_region_size)
+ : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0),
+ reserved_region_fd_(reserved_region_fd), reserved_region_size_(reserved_region_size),
+ reserved_region_addr_(nullptr)
{
assert(bo_);
num_planes_ = drv_bo_get_num_planes(bo_);
@@ -26,6 +29,9 @@
native_handle_close(&hnd_->base);
delete hnd_;
}
+ if (reserved_region_addr_) {
+ munmap(reserved_region_addr_, reserved_region_size_);
+ }
}
uint32_t cros_gralloc_buffer::get_id() const
@@ -114,3 +120,52 @@
{
return drv_resource_info(bo_, strides, offsets);
}
+
+int32_t cros_gralloc_buffer::invalidate()
+{
+ if (lockcount_ <= 0) {
+ drv_log("Buffer was not locked.\n");
+ return -EINVAL;
+ }
+
+ if (lock_data_[0]) {
+ return drv_bo_invalidate(bo_, lock_data_[0]);
+ }
+
+ return 0;
+}
+
+int32_t cros_gralloc_buffer::flush()
+{
+ if (lockcount_ <= 0) {
+ drv_log("Buffer was not locked.\n");
+ return -EINVAL;
+ }
+
+ if (lock_data_[0]) {
+ return drv_bo_flush(bo_, lock_data_[0]);
+ }
+
+ return 0;
+}
+
+int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size)
+{
+ if (reserved_region_fd_ <= 0) {
+ drv_log("Buffer does not have reserved region.\n");
+ return -EINVAL;
+ }
+
+ if (!reserved_region_addr_) {
+ reserved_region_addr_ = mmap(nullptr, reserved_region_size_, PROT_WRITE | PROT_READ,
+ MAP_SHARED, reserved_region_fd_, 0);
+ if (reserved_region_addr_ == MAP_FAILED) {
+ drv_log("Failed to mmap reserved region: %s.\n", strerror(errno));
+ return -errno;
+ }
+ }
+
+ *addr = reserved_region_addr_;
+ *size = reserved_region_size_;
+ return 0;
+}
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index ebd72ec..8634882 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -14,7 +14,8 @@
{
public:
cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
- struct cros_gralloc_handle *acquire_handle);
+ struct cros_gralloc_handle *acquire_handle, int32_t reserved_region_fd,
+ uint64_t reserved_region_size);
~cros_gralloc_buffer();
uint32_t get_id() const;
@@ -28,12 +29,19 @@
int32_t unlock();
int32_t resource_info(uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES]);
+ int32_t invalidate();
+ int32_t flush();
+
+ int32_t get_reserved_region(void **reserved_region_addr, uint64_t *reserved_region_size);
+
private:
cros_gralloc_buffer(cros_gralloc_buffer const &);
cros_gralloc_buffer operator=(cros_gralloc_buffer const &);
uint32_t id_;
struct bo *bo_;
+
+ /* Note: this will be nullptr for imported/retained buffers. */
struct cros_gralloc_handle *hnd_;
int32_t refcount_;
@@ -41,6 +49,11 @@
uint32_t num_planes_;
struct mapping *lock_data_[DRV_MAX_PLANES];
+
+ /* Optional additional shared memory region attached to some gralloc4 buffers. */
+ int32_t reserved_region_fd_;
+ uint64_t reserved_region_size_;
+ void *reserved_region_addr_;
};
#endif
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index 62b43d4..e324bce 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -5,12 +5,16 @@
*/
#include "cros_gralloc_driver.h"
-#include "../util.h"
#include <cstdlib>
#include <fcntl.h>
+#include <sys/mman.h>
#include <xf86drm.h>
+#include "../drv_priv.h"
+#include "../helpers.h"
+#include "../util.h"
+
cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
{
}
@@ -90,15 +94,38 @@
return (combo != nullptr);
}
+int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
+{
+ int32_t reserved_region_fd;
+ std::string reserved_region_name = buffer_name + " reserved region";
+
+ reserved_region_fd = memfd_create(reserved_region_name.c_str(), FD_CLOEXEC);
+ if (reserved_region_fd == -1) {
+ drv_log("Failed to create reserved region fd: %s.\n", strerror(errno));
+ return -errno;
+ }
+
+ if (ftruncate(reserved_region_fd, reserved_region_size)) {
+ drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
+ return -errno;
+ }
+
+ return reserved_region_fd;
+}
+
int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
buffer_handle_t *out_handle)
{
uint32_t id;
- uint64_t mod;
size_t num_planes;
+ size_t num_fds;
+ size_t num_ints;
+ size_t num_bytes;
uint32_t resolved_format;
uint32_t bytes_per_pixel;
uint64_t use_flags;
+ int32_t reserved_region_fd;
+ char *name;
struct bo *bo;
struct cros_gralloc_handle *hnd;
@@ -140,41 +167,72 @@
return -EINVAL;
}
- hnd = new cros_gralloc_handle();
num_planes = drv_bo_get_num_planes(bo);
+ num_fds = num_planes;
+ if (descriptor->reserved_region_size > 0) {
+ reserved_region_fd =
+ create_reserved_region(descriptor->name, descriptor->reserved_region_size);
+ if (reserved_region_fd < 0) {
+ drv_bo_destroy(bo);
+ return reserved_region_fd;
+ }
+ num_fds += 1;
+ } else {
+ reserved_region_fd = -1;
+ }
+
+ num_bytes = sizeof(struct cros_gralloc_handle);
+ num_bytes += (descriptor->name.size() + 1);
+ /*
+ * Ensure that the total number of bytes is a multiple of sizeof(int) as
+ * native_handle_clone() copies data based on hnd->base.numInts.
+ */
+ num_bytes = ALIGN(num_bytes, sizeof(int));
+ num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
+ /*
+ * Malloc is used as handles are ultimetly destroyed via free in
+ * native_handle_delete().
+ */
+ hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
hnd->base.version = sizeof(hnd->base);
- hnd->base.numFds = num_planes;
- hnd->base.numInts = handle_data_size - num_planes;
-
+ hnd->base.numFds = num_fds;
+ hnd->base.numInts = num_ints;
+ hnd->num_planes = num_planes;
for (size_t plane = 0; plane < num_planes; plane++) {
hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
-
- mod = drv_bo_get_plane_format_modifier(bo, plane);
- hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
- hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
+ hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
}
-
+ hnd->fds[hnd->num_planes] = reserved_region_fd;
+ hnd->reserved_region_size = descriptor->reserved_region_size;
+ static std::atomic<uint32_t> next_buffer_id{ 1 };
+ hnd->id = next_buffer_id++;
hnd->width = drv_bo_get_width(bo);
hnd->height = drv_bo_get_height(bo);
hnd->format = drv_bo_get_format(bo);
- hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32);
- hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags);
+ hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
+ hnd->use_flags = descriptor->use_flags;
bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
hnd->magic = cros_gralloc_magic;
hnd->droid_format = descriptor->droid_format;
- hnd->usage = descriptor->producer_usage;
+ hnd->usage = descriptor->droid_usage;
+ hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
+ hnd->name_offset = handle_data_size;
+
+ name = (char *)(&hnd->base.data[hnd->name_offset]);
+ snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
id = drv_bo_get_plane_handle(bo, 0).u32;
- auto buffer = new cros_gralloc_buffer(id, bo, hnd);
+ auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
+ hnd->reserved_region_size);
std::lock_guard<std::mutex> lock(mutex_);
buffers_.emplace(id, buffer);
handles_.emplace(hnd, std::make_pair(buffer, 1));
- *out_handle = &hnd->base;
+ *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
return 0;
}
@@ -208,18 +266,16 @@
struct bo *bo;
struct drv_import_fd_data data;
data.format = hnd->format;
+
data.width = hnd->width;
data.height = hnd->height;
- data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32;
- data.use_flags |= hnd->use_flags[1];
+ data.use_flags = hnd->use_flags;
memcpy(data.fds, hnd->fds, sizeof(data.fds));
memcpy(data.strides, hnd->strides, sizeof(data.strides));
memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
- data.format_modifiers[plane] =
- static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
- data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
+ data.format_modifiers[plane] = hnd->format_modifier;
}
bo = drv_bo_import(drv_, &data);
@@ -228,7 +284,8 @@
id = drv_bo_get_plane_handle(bo, 0).u32;
- buffer = new cros_gralloc_buffer(id, bo, nullptr);
+ buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
+ hnd->reserved_region_size);
buffers_.emplace(id, buffer);
}
@@ -264,10 +321,10 @@
}
int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
- const struct rectangle *rect, uint32_t map_flags,
- uint8_t *addr[DRV_MAX_PLANES])
+ bool close_acquire_fence, const struct rectangle *rect,
+ uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
{
- int32_t ret = cros_gralloc_sync_wait(acquire_fence);
+ int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
if (ret)
return ret;
@@ -313,6 +370,51 @@
return buffer->unlock();
}
+int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
+{
+ 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->invalidate();
+}
+
+int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
+{
+ 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;
+ }
+
+ /*
+ * From the ANativeWindow::dequeueBuffer documentation:
+ *
+ * "A value of -1 indicates that the caller may access the buffer immediately without
+ * waiting on a fence."
+ */
+ *release_fence = -1;
+ return buffer->flush();
+}
+
int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
{
std::lock_guard<std::mutex> lock(mutex_);
@@ -353,6 +455,32 @@
return buffer->resource_info(strides, offsets);
}
+int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
+ void **reserved_region_addr,
+ uint64_t *reserved_region_size)
+{
+ 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->get_reserved_region(reserved_region_addr, reserved_region_size);
+}
+
+uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
+{
+ return drv_resolve_format(drv_, drm_format, usage);
+}
+
cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
{
/* Assumes driver mutex is held. */
@@ -361,3 +489,13 @@
return nullptr;
}
+
+void cros_gralloc_driver::for_each_handle(
+ const std::function<void(cros_gralloc_handle_t)> &function)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ for (const auto &pair : handles_) {
+ function(pair.first);
+ }
+}
\ No newline at end of file
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index f051277..d444ecd 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -9,6 +9,7 @@
#include "cros_gralloc_buffer.h"
+#include <functional>
#include <mutex>
#include <unordered_map>
@@ -26,14 +27,25 @@
int32_t retain(buffer_handle_t handle);
int32_t release(buffer_handle_t handle);
- int32_t lock(buffer_handle_t handle, int32_t acquire_fence, const struct rectangle *rect,
- uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES]);
+ int32_t lock(buffer_handle_t handle, int32_t acquire_fence, bool close_acquire_fence,
+ const struct rectangle *rect, uint32_t map_flags,
+ uint8_t *addr[DRV_MAX_PLANES]);
int32_t unlock(buffer_handle_t handle, int32_t *release_fence);
+ int32_t invalidate(buffer_handle_t handle);
+ int32_t flush(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]);
+ int32_t get_reserved_region(buffer_handle_t handle, void **reserved_region_addr,
+ uint64_t *reserved_region_size);
+
+ uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t usage);
+
+ void for_each_handle(const std::function<void(cros_gralloc_handle_t)> &function);
+
private:
cros_gralloc_driver(cros_gralloc_driver const &);
cros_gralloc_driver operator=(cros_gralloc_driver const &);
diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h
index cd3edfe..d2e1607 100644
--- a/cros_gralloc/cros_gralloc_handle.h
+++ b/cros_gralloc/cros_gralloc_handle.h
@@ -11,27 +11,40 @@
#include <cutils/native_handle.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).
- */
+#define DRV_MAX_FDS (DRV_MAX_PLANES + 1)
struct cros_gralloc_handle {
native_handle_t base;
- int32_t fds[DRV_MAX_PLANES];
+ /*
+ * File descriptors must immediately follow the native_handle_t base and used file
+ * descriptors must be packed at the beginning of this array to work with
+ * native_handle_clone().
+ *
+ * This field contains 'num_planes' plane file descriptors followed by an optional metadata
+ * reserved region file descriptor if 'reserved_region_size' is greater than zero.
+ */
+ int32_t fds[DRV_MAX_FDS];
uint32_t strides[DRV_MAX_PLANES];
uint32_t offsets[DRV_MAX_PLANES];
- uint32_t format_modifiers[2 * DRV_MAX_PLANES];
+ uint32_t sizes[DRV_MAX_PLANES];
+ uint32_t id;
uint32_t width;
uint32_t height;
- uint32_t format; /* DRM format */
- uint32_t use_flags[2]; /* Buffer creation flags */
+ uint32_t format; /* DRM format */
+ uint64_t format_modifier;
+ uint64_t use_flags; /* Buffer creation flags */
uint32_t magic;
uint32_t pixel_stride;
int32_t droid_format;
int32_t usage; /* Android usage. */
-};
+ uint32_t num_planes;
+ uint64_t reserved_region_size;
+ uint64_t total_size; /* Total allocation size */
+ /*
+ * Name is a null terminated char array located at handle->base.data[handle->name_offset].
+ */
+ uint32_t name_offset;
+} __attribute__((packed));
typedef const struct cros_gralloc_handle *cros_gralloc_handle_t;
diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc
index 73e59cb..1e05150 100644
--- a/cros_gralloc/cros_gralloc_helpers.cc
+++ b/cros_gralloc/cros_gralloc_helpers.cc
@@ -20,6 +20,8 @@
return DRM_FORMAT_ARGB8888;
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
+ case HAL_PIXEL_FORMAT_RAW16:
+ return DRM_FORMAT_R16;
case HAL_PIXEL_FORMAT_RGB_565:
return DRM_FORMAT_RGB565;
case HAL_PIXEL_FORMAT_RGB_888:
@@ -59,29 +61,31 @@
return hnd;
}
-int32_t cros_gralloc_sync_wait(int32_t acquire_fence)
+int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence)
{
- if (acquire_fence < 0)
+ if (fence < 0)
return 0;
/*
* Wait initially for 1000 ms, and then wait indefinitely. The SYNC_IOC_WAIT
* documentation states the caller waits indefinitely on the fence if timeout < 0.
*/
- int err = sync_wait(acquire_fence, 1000);
+ int err = sync_wait(fence, 1000);
if (err < 0) {
drv_log("Timed out on sync wait, err = %s\n", strerror(errno));
- err = sync_wait(acquire_fence, -1);
+ err = sync_wait(fence, -1);
if (err < 0) {
drv_log("sync wait error = %s\n", strerror(errno));
return -errno;
}
}
- err = close(acquire_fence);
- if (err) {
- drv_log("Unable to close fence fd, err = %s\n", strerror(errno));
- return -errno;
+ if (close_fence) {
+ err = close(fence);
+ if (err) {
+ drv_log("Unable to close fence fd, err = %s\n", strerror(errno));
+ return -errno;
+ }
}
return 0;
diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h
index a55eebc..36f86ef 100644
--- a/cros_gralloc/cros_gralloc_helpers.h
+++ b/cros_gralloc/cros_gralloc_helpers.h
@@ -22,6 +22,6 @@
cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle);
-int32_t cros_gralloc_sync_wait(int32_t acquire_fence);
+int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence);
#endif
diff --git a/cros_gralloc/cros_gralloc_types.h b/cros_gralloc/cros_gralloc_types.h
index 1fa81de..22f58e2 100644
--- a/cros_gralloc/cros_gralloc_types.h
+++ b/cros_gralloc/cros_gralloc_types.h
@@ -7,14 +7,17 @@
#ifndef CROS_GRALLOC_TYPES_H
#define CROS_GRALLOC_TYPES_H
+#include <string>
+
struct cros_gralloc_buffer_descriptor {
uint32_t width;
uint32_t height;
- uint32_t consumer_usage;
- uint32_t producer_usage;
- uint32_t droid_format;
+ int32_t droid_format;
+ int32_t droid_usage;
uint32_t drm_format;
uint64_t use_flags;
+ uint64_t reserved_region_size;
+ std::string name;
};
#endif
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index a70498a..170dae9 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -119,9 +119,10 @@
descriptor.width = w;
descriptor.height = h;
descriptor.droid_format = format;
- descriptor.producer_usage = descriptor.consumer_usage = usage;
+ descriptor.droid_usage = usage;
descriptor.drm_format = cros_gralloc_convert_format(format);
descriptor.use_flags = gralloc0_convert_usage(usage);
+ descriptor.reserved_region_size = 0;
supported = mod->driver->is_supported(&descriptor);
if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
@@ -248,7 +249,7 @@
if (ret)
return ret;
- ret = cros_gralloc_sync_wait(fence_fd);
+ ret = cros_gralloc_sync_wait(fence_fd, /*close_acquire_fence=*/true);
if (ret)
return ret;
@@ -359,7 +360,7 @@
assert(h >= 0);
map_flags = gralloc0_convert_map_usage(usage);
- ret = mod->driver->lock(handle, fence_fd, &rect, map_flags, addr);
+ ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
*vaddr = addr[0];
return ret;
}
@@ -404,7 +405,7 @@
assert(h >= 0);
map_flags = gralloc0_convert_map_usage(usage);
- ret = mod->driver->lock(handle, fence_fd, &rect, map_flags, addr);
+ ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
if (ret)
return ret;
diff --git a/cros_gralloc/gralloc0/tests/gralloctest.c b/cros_gralloc/gralloc0/tests/gralloctest.c
index 8dfcd0b..f663cd0 100644
--- a/cros_gralloc/gralloc0/tests/gralloctest.c
+++ b/cros_gralloc/gralloc0/tests/gralloctest.c
@@ -42,10 +42,11 @@
} while (0)
/* Private API enumeration -- see <gralloc_drm.h> */
-enum { GRALLOC_DRM_GET_STRIDE,
- GRALLOC_DRM_GET_FORMAT,
- GRALLOC_DRM_GET_DIMENSIONS,
- GRALLOC_DRM_GET_BACKING_STORE,
+enum {
+ GRALLOC_DRM_GET_STRIDE,
+ GRALLOC_DRM_GET_FORMAT,
+ GRALLOC_DRM_GET_DIMENSIONS,
+ GRALLOC_DRM_GET_BACKING_STORE,
};
struct gralloctest_context {
diff --git a/cros_gralloc/gralloc4/.clang-format b/cros_gralloc/gralloc4/.clang-format
new file mode 100644
index 0000000..b310cc1
--- /dev/null
+++ b/cros_gralloc/gralloc4/.clang-format
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This directory is formatted to match the format of the interfaces implemented.
+
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
\ No newline at end of file
diff --git a/cros_gralloc/gralloc4/Android.bp b/cros_gralloc/gralloc4/Android.bp
new file mode 100644
index 0000000..a0a8622
--- /dev/null
+++ b/cros_gralloc/gralloc4/Android.bp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_binary {
+ name: "android.hardware.graphics.allocator@4.0-service.minigbm",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "android.hardware.graphics.allocator@4.0",
+ "android.hardware.graphics.mapper@4.0",
+ "libbase",
+ "libcutils",
+ "libgralloctypes",
+ "libhidlbase",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libdrm",
+ "libminigbm_cros_gralloc",
+ ],
+
+ srcs: [
+ "CrosGralloc4Allocator.cc",
+ "CrosGralloc4AllocatorService.cc",
+ "CrosGralloc4Utils.cc",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
+ relative_install_path: "hw",
+ vendor: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "android.hardware.graphics.mapper@4.0",
+ "libbase",
+ "libcutils",
+ "libgralloctypes",
+ "libhidlbase",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libdrm",
+ "libminigbm_cros_gralloc",
+ ],
+
+ srcs: [
+ "CrosGralloc4Mapper.cc",
+ "CrosGralloc4Utils.cc",
+ ],
+}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
new file mode 100644
index 0000000..4fb7845
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Allocator.h"
+
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <gralloctypes/Gralloc4.h>
+
+#include "cros_gralloc/cros_gralloc_helpers.h"
+#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
+
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::graphics::common::V1_2::BufferUsage;
+using android::hardware::graphics::common::V1_2::PixelFormat;
+using android::hardware::graphics::mapper::V4_0::Error;
+
+using BufferDescriptorInfo =
+ android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
+
+CrosGralloc4Allocator::CrosGralloc4Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) {
+ if (mDriver->init()) {
+ drv_log("Failed to initialize driver.\n");
+ mDriver = nullptr;
+ }
+}
+
+Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride,
+ hidl_handle* outHandle) {
+ if (!mDriver) {
+ drv_log("Failed to allocate. Driver is uninitialized.\n");
+ return Error::NO_RESOURCES;
+ }
+
+ if (!outStride || !outHandle) {
+ return Error::NO_RESOURCES;
+ }
+
+ struct cros_gralloc_buffer_descriptor crosDescriptor;
+ if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
+ return Error::UNSUPPORTED;
+ }
+
+ bool supported = mDriver->is_supported(&crosDescriptor);
+ if (!supported && (descriptor.usage & BufferUsage::COMPOSER_OVERLAY)) {
+ crosDescriptor.use_flags &= ~BO_USE_SCANOUT;
+ supported = mDriver->is_supported(&crosDescriptor);
+ }
+
+ if (!supported) {
+ std::string drmFormatString = getDrmFormatString(crosDescriptor.drm_format);
+ std::string pixelFormatString = getPixelFormatString(descriptor.format);
+ std::string usageString = getUsageString(descriptor.usage);
+ drv_log("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s\n",
+ pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
+ return Error::UNSUPPORTED;
+ }
+
+ buffer_handle_t handle;
+ int ret = mDriver->allocate(&crosDescriptor, &handle);
+ if (ret) {
+ return Error::NO_RESOURCES;
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
+ if (!crosHandle) {
+ return Error::NO_RESOURCES;
+ }
+
+ *outHandle = handle;
+ *outStride = crosHandle->pixel_stride;
+
+ return Error::NONE;
+}
+
+Return<void> CrosGralloc4Allocator::allocate(const hidl_vec<uint8_t>& descriptor, uint32_t count,
+ allocate_cb hidlCb) {
+ hidl_vec<hidl_handle> handles;
+
+ if (!mDriver) {
+ drv_log("Failed to allocate. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, 0, handles);
+ return Void();
+ }
+
+ BufferDescriptorInfo description;
+
+ int ret = android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description);
+ if (ret) {
+ drv_log("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
+ hidlCb(Error::BAD_DESCRIPTOR, 0, handles);
+ return Void();
+ }
+
+ handles.resize(count);
+
+ uint32_t stride = 0;
+ for (int i = 0; i < handles.size(); i++) {
+ Error err = allocate(description, &stride, &(handles[i]));
+ if (err != Error::NONE) {
+ for (int j = 0; j < i; j++) {
+ mDriver->release(handles[j].getNativeHandle());
+ }
+ handles.resize(0);
+ hidlCb(err, 0, handles);
+ return Void();
+ }
+ }
+
+ hidlCb(Error::NONE, stride, handles);
+
+ for (const hidl_handle& handle : handles) {
+ mDriver->release(handle.getNativeHandle());
+ }
+
+ return Void();
+}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
new file mode 100644
index 0000000..21ad7ad
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+
+#include "cros_gralloc/cros_gralloc_driver.h"
+
+class CrosGralloc4Allocator : public android::hardware::graphics::allocator::V4_0::IAllocator {
+ public:
+ CrosGralloc4Allocator();
+
+ android::hardware::Return<void> allocate(const android::hardware::hidl_vec<uint8_t>& descriptor,
+ uint32_t count, allocate_cb hidl_cb) override;
+
+ private:
+ android::hardware::graphics::mapper::V4_0::Error allocate(
+ const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo&
+ description,
+ uint32_t* outStride, android::hardware::hidl_handle* outHandle);
+
+ std::unique_ptr<cros_gralloc_driver> mDriver;
+};
diff --git a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc
new file mode 100644
index 0000000..5b79860
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#define LOG_TAG "AllocatorService"
+
+#include <hidl/LegacySupport.h>
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Allocator.h"
+
+using android::sp;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::graphics::allocator::V4_0::IAllocator;
+
+int main(int, char**) {
+ sp<IAllocator> allocator = new CrosGralloc4Allocator();
+ configureRpcThreadpool(4, true /* callerWillJoin */);
+ if (allocator->registerAsService() != android::NO_ERROR) {
+ ALOGE("failed to register graphics IAllocator 4.0 service");
+ return -EINVAL;
+ }
+
+ ALOGI("graphics IAllocator 4.0 service is initialized");
+ android::hardware::joinRpcThreadpool();
+ ALOGI("graphics IAllocator 4.0 service is terminating");
+ return 0;
+}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
new file mode 100644
index 0000000..47e24ac
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -0,0 +1,1004 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Mapper.h"
+
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <cutils/native_handle.h>
+#include <gralloctypes/Gralloc4.h>
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
+#include "helpers.h"
+
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::Rect;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::graphics::common::V1_2::BufferUsage;
+using android::hardware::graphics::common::V1_2::PixelFormat;
+using android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::graphics::mapper::V4_0::IMapper;
+
+CrosGralloc4Mapper::CrosGralloc4Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) {
+ if (mDriver->init()) {
+ drv_log("Failed to initialize driver.\n");
+ mDriver = nullptr;
+ }
+}
+
+Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& description,
+ createDescriptor_cb hidlCb) {
+ hidl_vec<uint8_t> descriptor;
+
+ if (description.width == 0) {
+ drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width);
+ hidlCb(Error::BAD_VALUE, descriptor);
+ return Void();
+ }
+
+ if (description.height == 0) {
+ drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height);
+ hidlCb(Error::BAD_VALUE, descriptor);
+ return Void();
+ }
+
+ if (description.layerCount == 0) {
+ drv_log("Failed to createDescriptor. Bad layer count: %d.\n", description.layerCount);
+ hidlCb(Error::BAD_VALUE, descriptor);
+ return Void();
+ }
+
+ int ret = android::gralloc4::encodeBufferDescriptorInfo(description, &descriptor);
+ if (ret) {
+ drv_log("Failed to createDescriptor. Failed to encode: %d.\n", ret);
+ hidlCb(Error::BAD_VALUE, descriptor);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, descriptor);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to import buffer. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ const native_handle_t* bufferHandle = handle.getNativeHandle();
+ if (!bufferHandle || bufferHandle->numFds == 0) {
+ drv_log("Failed to importBuffer. Bad handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
+ if (!importedBufferHandle) {
+ drv_log("Failed to importBuffer. Handle clone failed.\n");
+ hidlCb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ int ret = mDriver->retain(importedBufferHandle);
+ if (ret) {
+ native_handle_close(importedBufferHandle);
+ native_handle_delete(importedBufferHandle);
+ hidlCb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, importedBufferHandle);
+ return Void();
+}
+
+Return<Error> CrosGralloc4Mapper::freeBuffer(void* rawHandle) {
+ if (!mDriver) {
+ drv_log("Failed to freeBuffer. Driver is uninitialized.\n");
+ return Error::NO_RESOURCES;
+ }
+
+ native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to freeBuffer. Empty handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ int ret = mDriver->release(bufferHandle);
+ if (ret) {
+ return Error::BAD_BUFFER;
+ }
+
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ return Error::NONE;
+}
+
+Return<Error> CrosGralloc4Mapper::validateBufferSize(void* rawHandle,
+ const BufferDescriptorInfo& descriptor,
+ uint32_t stride) {
+ if (!mDriver) {
+ drv_log("Failed to validateBufferSize. Driver is uninitialized.\n");
+ return Error::NO_RESOURCES;
+ }
+
+ native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to validateBufferSize. Empty handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ drv_log("Failed to validateBufferSize. Invalid handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format);
+ if (descriptor.format != crosHandleFormat) {
+ drv_log("Failed to validateBufferSize. Format mismatch.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ if (descriptor.width != crosHandle->width) {
+ drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width,
+ crosHandle->width);
+ return Error::BAD_VALUE;
+ }
+
+ if (descriptor.height != crosHandle->height) {
+ drv_log("Failed to validateBufferSize. Height mismatch (%d vs %d).\n", descriptor.height,
+ crosHandle->height);
+ return Error::BAD_VALUE;
+ }
+
+ if (stride != crosHandle->pixel_stride) {
+ drv_log("Failed to validateBufferSize. Stride mismatch (%d vs %d).\n", stride,
+ crosHandle->pixel_stride);
+ return Error::BAD_VALUE;
+ }
+
+ return Error::NONE;
+}
+
+Return<void> CrosGralloc4Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to getTransportSize. Driver is uninitialized.\n");
+ hidlCb(Error::BAD_BUFFER, 0, 0);
+ return Void();
+ }
+
+ native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to getTransportSize. Bad handle.\n");
+ hidlCb(Error::BAD_BUFFER, 0, 0);
+ return Void();
+ }
+
+ // No local process data is currently stored on the native handle.
+ hidlCb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::lock(void* rawBuffer, uint64_t cpuUsage, const Rect& region,
+ const hidl_handle& acquireFence, lock_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to lock. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawBuffer);
+ if (!bufferHandle) {
+ drv_log("Failed to lock. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ if (cpuUsage == 0) {
+ drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ uint32_t mapUsage = 0;
+ int ret = convertToMapUsage(cpuUsage, &mapUsage);
+ if (ret) {
+ drv_log("Failed to lock. Convert usage failed.\n");
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (crosHandle == nullptr) {
+ drv_log("Failed to lock. Invalid handle.\n");
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.left < 0) {
+ drv_log("Failed to lock. Invalid region: negative left value %d.\n", region.left);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.top < 0) {
+ drv_log("Failed to lock. Invalid region: negative top value %d.\n", region.top);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.width < 0) {
+ drv_log("Failed to lock. Invalid region: negative width value %d.\n", region.width);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.height < 0) {
+ drv_log("Failed to lock. Invalid region: negative height value %d.\n", region.height);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.width > crosHandle->width) {
+ drv_log("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).\n",
+ region.width, crosHandle->width);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ if (region.height > crosHandle->height) {
+ drv_log("Failed to lock. Invalid region: height greater than buffer height (%d vs %d).\n",
+ region.height, crosHandle->height);
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ struct rectangle rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top),
+ static_cast<uint32_t>(region.width),
+ static_cast<uint32_t>(region.height)};
+
+ // An access region of all zeros means the entire buffer.
+ if (rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0) {
+ rect.width = crosHandle->width;
+ rect.height = crosHandle->height;
+ }
+
+ int acquireFenceFd = -1;
+ ret = convertToFenceFd(acquireFence, &acquireFenceFd);
+ if (ret) {
+ drv_log("Failed to lock. Bad acquire fence.\n");
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ uint8_t* addr[DRV_MAX_PLANES];
+ ret = mDriver->lock(bufferHandle, acquireFenceFd, /*close_acquire_fence=*/false, &rect,
+ mapUsage, addr);
+ if (ret) {
+ hidlCb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, addr[0]);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to unlock. Driver is uninitialized.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to unlock. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ int releaseFenceFd = -1;
+ int ret = mDriver->unlock(bufferHandle, &releaseFenceFd);
+ if (ret) {
+ drv_log("Failed to unlock.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ hidl_handle releaseFenceHandle;
+ ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle);
+ if (ret) {
+ drv_log("Failed to unlock. Failed to convert release fence to handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, releaseFenceHandle);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::flushLockedBuffer(void* rawHandle, flushLockedBuffer_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to flushLockedBuffer. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to flushLockedBuffer. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ int releaseFenceFd = -1;
+ int ret = mDriver->flush(bufferHandle, &releaseFenceFd);
+ if (ret) {
+ drv_log("Failed to flushLockedBuffer. Flush failed.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ hidl_handle releaseFenceHandle;
+ ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle);
+ if (ret) {
+ drv_log("Failed to flushLockedBuffer. Failed to convert release fence to handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, releaseFenceHandle);
+ return Void();
+}
+
+Return<Error> CrosGralloc4Mapper::rereadLockedBuffer(void* rawHandle) {
+ if (!mDriver) {
+ drv_log("Failed to rereadLockedBuffer. Driver is uninitialized.\n");
+ return Error::NO_RESOURCES;
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to rereadLockedBuffer. Empty handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ int ret = mDriver->invalidate(bufferHandle);
+ if (ret) {
+ drv_log("Failed to rereadLockedBuffer. Failed to invalidate.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ return Error::NONE;
+}
+
+Return<void> CrosGralloc4Mapper::isSupported(const BufferDescriptorInfo& descriptor,
+ isSupported_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to isSupported. Driver is uninitialized.\n");
+ hidlCb(Error::BAD_VALUE, false);
+ return Void();
+ }
+
+ struct cros_gralloc_buffer_descriptor crosDescriptor;
+ if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
+ hidlCb(Error::NONE, false);
+ return Void();
+ }
+
+ bool supported = mDriver->is_supported(&crosDescriptor);
+ if (!supported) {
+ crosDescriptor.use_flags &= ~BO_USE_SCANOUT;
+ supported = mDriver->is_supported(&crosDescriptor);
+ }
+
+ hidlCb(Error::NONE, supported);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::get(void* rawHandle, const MetadataType& metadataType,
+ get_cb hidlCb) {
+ hidl_vec<uint8_t> encodedMetadata;
+
+ if (!mDriver) {
+ drv_log("Failed to get. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, encodedMetadata);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to get. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, encodedMetadata);
+ return Void();
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ drv_log("Failed to get. Invalid handle.\n");
+ hidlCb(Error::BAD_BUFFER, encodedMetadata);
+ return Void();
+ }
+
+ get(crosHandle, metadataType, hidlCb);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle,
+ const MetadataType& metadataType, get_cb hidlCb) {
+ hidl_vec<uint8_t> encodedMetadata;
+
+ if (!mDriver) {
+ drv_log("Failed to get. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, encodedMetadata);
+ return Void();
+ }
+
+ if (!crosHandle) {
+ drv_log("Failed to get. Invalid handle.\n");
+ hidlCb(Error::BAD_BUFFER, encodedMetadata);
+ return Void();
+ }
+
+ android::status_t status = android::NO_ERROR;
+ if (metadataType == android::gralloc4::MetadataType_BufferId) {
+ status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Name) {
+ const char* name = (const char*)(&crosHandle->base.data[crosHandle->name_offset]);
+ status = android::gralloc4::encodeName(name, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Width) {
+ status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Height) {
+ status = android::gralloc4::encodeHeight(crosHandle->height, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_LayerCount) {
+ status = android::gralloc4::encodeLayerCount(1, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) {
+ PixelFormat pixelFormat = static_cast<PixelFormat>(crosHandle->droid_format);
+ status = android::gralloc4::encodePixelFormatRequested(pixelFormat, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) {
+ status = android::gralloc4::encodePixelFormatFourCC(crosHandle->format, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatModifier) {
+ status = android::gralloc4::encodePixelFormatModifier(crosHandle->format_modifier,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Usage) {
+ uint64_t usage = static_cast<uint64_t>(crosHandle->usage);
+ status = android::gralloc4::encodeUsage(usage, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_AllocationSize) {
+ status = android::gralloc4::encodeAllocationSize(crosHandle->total_size, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) {
+ uint64_t hasProtectedContent = crosHandle->usage & BufferUsage::PROTECTED ? 1 : 0;
+ status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Compression) {
+ status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Interlaced) {
+ status = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_ChromaSiting) {
+ status = android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PlaneLayouts) {
+ std::vector<PlaneLayout> planeLayouts;
+ getPlaneLayouts(crosHandle->format, &planeLayouts);
+
+ for (size_t plane = 0; plane < planeLayouts.size(); plane++) {
+ PlaneLayout& planeLayout = planeLayouts[plane];
+ planeLayout.offsetInBytes = crosHandle->offsets[plane];
+ planeLayout.strideInBytes = crosHandle->strides[plane];
+ planeLayout.totalSizeInBytes = crosHandle->sizes[plane];
+ planeLayout.widthInSamples = crosHandle->width;
+ planeLayout.heightInSamples = crosHandle->height;
+ }
+
+ status = android::gralloc4::encodePlaneLayouts(planeLayouts, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Crop) {
+ std::vector<aidl::android::hardware::graphics::common::Rect> crops;
+ for (size_t plane = 0; plane < crosHandle->num_planes; plane++) {
+ aidl::android::hardware::graphics::common::Rect crop;
+ crop.left = 0;
+ crop.top = 0;
+ crop.right = crosHandle->width;
+ crop.bottom = crosHandle->height;
+ crops.push_back(crop);
+ }
+
+ status = android::gralloc4::encodeCrop(crops, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
+ status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_BlendMode) {
+ status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
+ status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
+ status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) {
+ status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata);
+ } else {
+ hidlCb(Error::UNSUPPORTED, encodedMetadata);
+ return Void();
+ }
+
+ if (status != android::NO_ERROR) {
+ hidlCb(Error::NO_RESOURCES, encodedMetadata);
+ drv_log("Failed to get. Failed to encode metadata.\n");
+ return Void();
+ }
+
+ hidlCb(Error::NONE, encodedMetadata);
+ return Void();
+}
+
+Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metadataType,
+ const hidl_vec<uint8_t>& /*metadata*/) {
+ if (!mDriver) {
+ drv_log("Failed to set. Driver is uninitialized.\n");
+ return Error::NO_RESOURCES;
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to set. Empty handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ drv_log("Failed to set. Invalid handle.\n");
+ return Error::BAD_BUFFER;
+ }
+
+ if (metadataType == android::gralloc4::MetadataType_BufferId) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_Name) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_Width) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_Height) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_LayerCount) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) {
+ return Error::BAD_VALUE;
+ } else if (metadataType == android::gralloc4::MetadataType_Usage) {
+ return Error::BAD_VALUE;
+ }
+
+ return Error::UNSUPPORTED;
+}
+
+int CrosGralloc4Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage,
+ uint32_t* outDrmFormat) {
+ uint32_t drmFormat;
+ if (convertToDrmFormat(pixelFormat, &drmFormat)) {
+ std::string pixelFormatString = getPixelFormatString(pixelFormat);
+ drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n",
+ pixelFormatString.c_str());
+ return -1;
+ }
+
+ uint64_t usage;
+ if (convertToBufferUsage(bufferUsage, &usage)) {
+ std::string usageString = getUsageString(bufferUsage);
+ drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n",
+ usageString.c_str());
+ return -1;
+ }
+
+ uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage);
+ if (resolvedDrmFormat == DRM_FORMAT_INVALID) {
+ std::string drmFormatString = getDrmFormatString(drmFormat);
+ drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n",
+ drmFormatString.c_str());
+ return -1;
+ }
+
+ *outDrmFormat = resolvedDrmFormat;
+
+ return 0;
+}
+
+Return<void> CrosGralloc4Mapper::getFromBufferDescriptorInfo(
+ const BufferDescriptorInfo& descriptor, const MetadataType& metadataType,
+ getFromBufferDescriptorInfo_cb hidlCb) {
+ hidl_vec<uint8_t> encodedMetadata;
+
+ if (!mDriver) {
+ drv_log("Failed to getFromBufferDescriptorInfo. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, encodedMetadata);
+ return Void();
+ }
+
+ android::status_t status = android::NO_ERROR;
+ if (metadataType == android::gralloc4::MetadataType_Name) {
+ status = android::gralloc4::encodeName(descriptor.name, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Width) {
+ status = android::gralloc4::encodeWidth(descriptor.width, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Height) {
+ status = android::gralloc4::encodeHeight(descriptor.height, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_LayerCount) {
+ status = android::gralloc4::encodeLayerCount(1, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) {
+ status = android::gralloc4::encodePixelFormatRequested(descriptor.format, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) {
+ uint32_t drmFormat;
+ if (getResolvedDrmFormat(descriptor.format, descriptor.usage, &drmFormat)) {
+ hidlCb(Error::BAD_VALUE, encodedMetadata);
+ return Void();
+ }
+ status = android::gralloc4::encodePixelFormatFourCC(drmFormat, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Usage) {
+ status = android::gralloc4::encodeUsage(descriptor.usage, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) {
+ uint64_t hasProtectedContent = descriptor.usage & BufferUsage::PROTECTED ? 1 : 0;
+ status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Compression) {
+ status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Interlaced) {
+ status = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_ChromaSiting) {
+ status = android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None,
+ &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Crop) {
+ uint32_t drmFormat;
+ if (getResolvedDrmFormat(descriptor.format, descriptor.usage, &drmFormat)) {
+ hidlCb(Error::BAD_VALUE, encodedMetadata);
+ return Void();
+ }
+
+ size_t numPlanes = drv_num_planes_from_format(drmFormat);
+
+ std::vector<aidl::android::hardware::graphics::common::Rect> crops;
+ for (size_t plane = 0; plane < numPlanes; plane++) {
+ aidl::android::hardware::graphics::common::Rect crop;
+ crop.left = 0;
+ crop.top = 0;
+ crop.right = descriptor.width;
+ crop.bottom = descriptor.height;
+ crops.push_back(crop);
+ }
+ status = android::gralloc4::encodeCrop(crops, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
+ status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_BlendMode) {
+ status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
+ status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
+ status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata);
+ } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) {
+ status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata);
+ } else {
+ hidlCb(Error::UNSUPPORTED, encodedMetadata);
+ return Void();
+ }
+
+ if (status != android::NO_ERROR) {
+ hidlCb(Error::NO_RESOURCES, encodedMetadata);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, encodedMetadata);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::listSupportedMetadataTypes(listSupportedMetadataTypes_cb hidlCb) {
+ hidl_vec<MetadataTypeDescription> supported;
+
+ if (!mDriver) {
+ drv_log("Failed to listSupportedMetadataTypes. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, supported);
+ return Void();
+ }
+
+ supported = hidl_vec<IMapper::MetadataTypeDescription>({
+ {
+ android::gralloc4::MetadataType_BufferId,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Name,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Width,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Height,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_LayerCount,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_PixelFormatRequested,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_PixelFormatFourCC,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_PixelFormatModifier,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Usage,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_AllocationSize,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_ProtectedContent,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Compression,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Interlaced,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_ChromaSiting,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_PlaneLayouts,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Dataspace,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_BlendMode,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Smpte2086,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Cta861_3,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ {
+ android::gralloc4::MetadataType_Smpte2094_40,
+ "",
+ /*isGettable=*/true,
+ /*isSettable=*/false,
+ },
+ });
+
+ hidlCb(Error::NONE, supported);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::dumpBuffer(void* rawHandle, dumpBuffer_cb hidlCb) {
+ BufferDump bufferDump;
+
+ if (!mDriver) {
+ drv_log("Failed to dumpBuffer. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, bufferDump);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to dumpBuffer. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, bufferDump);
+ return Void();
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ drv_log("Failed to dumpBuffer. Invalid handle.\n");
+ hidlCb(Error::BAD_BUFFER, bufferDump);
+ return Void();
+ }
+
+ return dumpBuffer(crosHandle, hidlCb);
+}
+
+Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle,
+ dumpBuffer_cb hidlCb) {
+ BufferDump bufferDump;
+
+ if (!mDriver) {
+ drv_log("Failed to dumpBuffer. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, bufferDump);
+ return Void();
+ }
+
+ if (!crosHandle) {
+ drv_log("Failed to dumpBuffer. Invalid handle.\n");
+ hidlCb(Error::BAD_BUFFER, bufferDump);
+ return Void();
+ }
+
+ std::vector<MetadataDump> metadataDumps;
+
+ MetadataType metadataType = android::gralloc4::MetadataType_BufferId;
+ auto metadata_get_callback = [&](Error, hidl_vec<uint8_t> metadata) {
+ MetadataDump metadataDump;
+ metadataDump.metadataType = metadataType;
+ metadataDump.metadata = metadata;
+ metadataDumps.push_back(metadataDump);
+ };
+
+ metadataType = android::gralloc4::MetadataType_BufferId;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Name;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Width;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Height;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_LayerCount;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_PixelFormatRequested;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_PixelFormatFourCC;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_PixelFormatModifier;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Usage;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_AllocationSize;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_ProtectedContent;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Compression;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Interlaced;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_ChromaSiting;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_PlaneLayouts;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_Dataspace;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ metadataType = android::gralloc4::MetadataType_BlendMode;
+ get(crosHandle, metadataType, metadata_get_callback);
+
+ bufferDump.metadataDump = metadataDumps;
+ hidlCb(Error::NONE, bufferDump);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::dumpBuffers(dumpBuffers_cb hidlCb) {
+ std::vector<BufferDump> bufferDumps;
+
+ if (!mDriver) {
+ drv_log("Failed to dumpBuffers. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, bufferDumps);
+ return Void();
+ }
+
+ Error error = Error::NONE;
+
+ auto handleCallback = [&](cros_gralloc_handle_t crosHandle) {
+ auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) {
+ error = err;
+ if (error == Error::NONE) {
+ bufferDumps.push_back(bufferDump);
+ }
+ };
+
+ dumpBuffer(crosHandle, dumpBufferCallback);
+ };
+ mDriver->for_each_handle(handleCallback);
+
+ hidlCb(error, bufferDumps);
+ return Void();
+}
+
+Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedRegion_cb hidlCb) {
+ if (!mDriver) {
+ drv_log("Failed to getReservedRegion. Driver is uninitialized.\n");
+ hidlCb(Error::NO_RESOURCES, nullptr, 0);
+ return Void();
+ }
+
+ buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
+ if (!bufferHandle) {
+ drv_log("Failed to getReservedRegion. Empty handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr, 0);
+ return Void();
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ drv_log("Failed to getReservedRegion. Invalid handle.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr, 0);
+ return Void();
+ }
+
+ void* reservedRegionAddr = nullptr;
+ uint64_t reservedRegionSize = 0;
+ int ret = mDriver->get_reserved_region(bufferHandle, &reservedRegionAddr, &reservedRegionSize);
+ if (ret) {
+ drv_log("Failed to getReservedRegion.\n");
+ hidlCb(Error::BAD_BUFFER, nullptr, 0);
+ return Void();
+ }
+
+ hidlCb(Error::NONE, reservedRegionAddr, reservedRegionSize);
+ return Void();
+}
+
+android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
+ return static_cast<android::hardware::graphics::mapper::V4_0::IMapper*>(new CrosGralloc4Mapper);
+}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
new file mode 100644
index 0000000..b318930
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+
+#include "cros_gralloc/cros_gralloc_driver.h"
+#include "cros_gralloc/cros_gralloc_handle.h"
+
+class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper {
+ public:
+ CrosGralloc4Mapper();
+
+ android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description,
+ createDescriptor_cb hidlCb) override;
+
+ android::hardware::Return<void> importBuffer(const android::hardware::hidl_handle& rawHandle,
+ importBuffer_cb hidlCb) override;
+
+ android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> freeBuffer(
+ void* rawHandle) override;
+
+ android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> validateBufferSize(
+ void* rawHandle, const BufferDescriptorInfo& descriptor, uint32_t stride) override;
+
+ android::hardware::Return<void> getTransportSize(void* rawHandle,
+ getTransportSize_cb hidlCb) override;
+
+ android::hardware::Return<void> lock(void* rawHandle, uint64_t cpuUsage,
+ const Rect& accessRegion,
+ const android::hardware::hidl_handle& acquireFence,
+ lock_cb hidlCb) override;
+
+ android::hardware::Return<void> unlock(void* rawHandle, unlock_cb hidlCb) override;
+
+ android::hardware::Return<void> flushLockedBuffer(void* rawHandle,
+ flushLockedBuffer_cb hidlCb) override;
+
+ android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> rereadLockedBuffer(
+ void* rawHandle) override;
+
+ android::hardware::Return<void> isSupported(const BufferDescriptorInfo& descriptor,
+ isSupported_cb hidlCb) override;
+
+ android::hardware::Return<void> get(void* rawHandle, const MetadataType& metadataType,
+ get_cb hidlCb) override;
+
+ android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> set(
+ void* rawHandle, const MetadataType& metadataType,
+ const android::hardware::hidl_vec<uint8_t>& metadata) override;
+
+ android::hardware::Return<void> getFromBufferDescriptorInfo(
+ const BufferDescriptorInfo& descriptor, const MetadataType& metadataType,
+ getFromBufferDescriptorInfo_cb hidlCb) override;
+
+ android::hardware::Return<void> listSupportedMetadataTypes(
+ listSupportedMetadataTypes_cb hidlCb) override;
+
+ android::hardware::Return<void> dumpBuffer(void* rawHandle, dumpBuffer_cb hidlCb) override;
+ android::hardware::Return<void> dumpBuffers(dumpBuffers_cb hidlCb) override;
+
+ android::hardware::Return<void> getReservedRegion(void* rawHandle,
+ getReservedRegion_cb hidlCb) override;
+
+ private:
+ android::hardware::Return<void> get(cros_gralloc_handle_t crosHandle,
+ const MetadataType& metadataType, get_cb hidlCb);
+
+ android::hardware::Return<void> dumpBuffer(cros_gralloc_handle_t crosHandle,
+ dumpBuffer_cb hidlCb);
+
+ int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat,
+ uint64_t bufferUsage, uint32_t* outDrmFormat);
+
+ std::unique_ptr<cros_gralloc_driver> mDriver;
+};
+
+extern "C" android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* name);
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
new file mode 100644
index 0000000..8931164
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
+
+#include <array>
+#include <unordered_map>
+
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <cutils/native_handle.h>
+#include <gralloctypes/Gralloc4.h>
+
+#include "cros_gralloc/cros_gralloc_helpers.h"
+
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using android::hardware::hidl_bitfield;
+using android::hardware::hidl_handle;
+using android::hardware::graphics::common::V1_2::BufferUsage;
+using android::hardware::graphics::common::V1_2::PixelFormat;
+
+using BufferDescriptorInfo =
+ android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
+
+std::string getDrmFormatString(uint32_t drmFormat) {
+ switch (drmFormat) {
+ case DRM_FORMAT_ABGR1555:
+ return "DRM_FORMAT_ABGR1555";
+ case DRM_FORMAT_ABGR2101010:
+ return "DRM_FORMAT_ABGR2101010";
+ case DRM_FORMAT_ABGR4444:
+ return "DRM_FORMAT_ABGR4444";
+ case DRM_FORMAT_ABGR8888:
+ return "DRM_FORMAT_ABGR8888";
+ case DRM_FORMAT_ARGB1555:
+ return "DRM_FORMAT_ARGB1555";
+ case DRM_FORMAT_ARGB2101010:
+ return "DRM_FORMAT_ARGB2101010";
+ case DRM_FORMAT_ARGB4444:
+ return "DRM_FORMAT_ARGB4444";
+ case DRM_FORMAT_ARGB8888:
+ return "DRM_FORMAT_ARGB8888";
+ case DRM_FORMAT_AYUV:
+ return "DRM_FORMAT_AYUV";
+ case DRM_FORMAT_BGR233:
+ return "DRM_FORMAT_BGR233";
+ case DRM_FORMAT_BGR565:
+ return "DRM_FORMAT_BGR565";
+ case DRM_FORMAT_BGR888:
+ return "DRM_FORMAT_BGR888";
+ case DRM_FORMAT_BGRA1010102:
+ return "DRM_FORMAT_BGRA1010102";
+ case DRM_FORMAT_BGRA4444:
+ return "DRM_FORMAT_BGRA4444";
+ case DRM_FORMAT_BGRA5551:
+ return "DRM_FORMAT_BGRA5551";
+ case DRM_FORMAT_BGRA8888:
+ return "DRM_FORMAT_BGRA8888";
+ case DRM_FORMAT_BGRX1010102:
+ return "DRM_FORMAT_BGRX1010102";
+ case DRM_FORMAT_BGRX4444:
+ return "DRM_FORMAT_BGRX4444";
+ case DRM_FORMAT_BGRX5551:
+ return "DRM_FORMAT_BGRX5551";
+ case DRM_FORMAT_BGRX8888:
+ return "DRM_FORMAT_BGRX8888";
+ case DRM_FORMAT_C8:
+ return "DRM_FORMAT_C8";
+ case DRM_FORMAT_GR88:
+ return "DRM_FORMAT_GR88";
+ case DRM_FORMAT_NV12:
+ return "DRM_FORMAT_NV12";
+ case DRM_FORMAT_NV21:
+ return "DRM_FORMAT_NV21";
+ case DRM_FORMAT_R8:
+ return "DRM_FORMAT_R8";
+ case DRM_FORMAT_RG88:
+ return "DRM_FORMAT_RG88";
+ case DRM_FORMAT_RGB332:
+ return "DRM_FORMAT_RGB332";
+ case DRM_FORMAT_RGB565:
+ return "DRM_FORMAT_RGB565";
+ case DRM_FORMAT_RGB888:
+ return "DRM_FORMAT_RGB888";
+ case DRM_FORMAT_RGBA1010102:
+ return "DRM_FORMAT_RGBA1010102";
+ case DRM_FORMAT_RGBA4444:
+ return "DRM_FORMAT_RGBA4444";
+ case DRM_FORMAT_RGBA5551:
+ return "DRM_FORMAT_RGBA5551";
+ case DRM_FORMAT_RGBA8888:
+ return "DRM_FORMAT_RGBA8888";
+ case DRM_FORMAT_RGBX1010102:
+ return "DRM_FORMAT_RGBX1010102";
+ case DRM_FORMAT_RGBX4444:
+ return "DRM_FORMAT_RGBX4444";
+ case DRM_FORMAT_RGBX5551:
+ return "DRM_FORMAT_RGBX5551";
+ case DRM_FORMAT_RGBX8888:
+ return "DRM_FORMAT_RGBX8888";
+ case DRM_FORMAT_UYVY:
+ return "DRM_FORMAT_UYVY";
+ case DRM_FORMAT_VYUY:
+ return "DRM_FORMAT_VYUY";
+ case DRM_FORMAT_XBGR1555:
+ return "DRM_FORMAT_XBGR1555";
+ case DRM_FORMAT_XBGR2101010:
+ return "DRM_FORMAT_XBGR2101010";
+ case DRM_FORMAT_XBGR4444:
+ return "DRM_FORMAT_XBGR4444";
+ case DRM_FORMAT_XBGR8888:
+ return "DRM_FORMAT_XBGR8888";
+ case DRM_FORMAT_XRGB1555:
+ return "DRM_FORMAT_XRGB1555";
+ case DRM_FORMAT_XRGB2101010:
+ return "DRM_FORMAT_XRGB2101010";
+ case DRM_FORMAT_XRGB4444:
+ return "DRM_FORMAT_XRGB4444";
+ case DRM_FORMAT_XRGB8888:
+ return "DRM_FORMAT_XRGB8888";
+ case DRM_FORMAT_YUYV:
+ return "DRM_FORMAT_YUYV";
+ case DRM_FORMAT_YVU420:
+ return "DRM_FORMAT_YVU420";
+ case DRM_FORMAT_YVYU:
+ return "DRM_FORMAT_YVYU";
+ }
+ return android::base::StringPrintf("Unknown(%d)", drmFormat);
+}
+
+std::string getPixelFormatString(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::BGRA_8888:
+ return "PixelFormat::BGRA_8888";
+ case PixelFormat::BLOB:
+ return "PixelFormat::BLOB";
+ case PixelFormat::DEPTH_16:
+ return "PixelFormat::DEPTH_16";
+ case PixelFormat::DEPTH_24:
+ return "PixelFormat::DEPTH_24";
+ case PixelFormat::DEPTH_24_STENCIL_8:
+ return "PixelFormat::DEPTH_24_STENCIL_8";
+ case PixelFormat::DEPTH_32F:
+ return "PixelFormat::DEPTH_24";
+ case PixelFormat::DEPTH_32F_STENCIL_8:
+ return "PixelFormat::DEPTH_24_STENCIL_8";
+ case PixelFormat::HSV_888:
+ return "PixelFormat::HSV_888";
+ case PixelFormat::IMPLEMENTATION_DEFINED:
+ return "PixelFormat::IMPLEMENTATION_DEFINED";
+ case PixelFormat::RAW10:
+ return "PixelFormat::RAW10";
+ case PixelFormat::RAW12:
+ return "PixelFormat::RAW12";
+ case PixelFormat::RAW16:
+ return "PixelFormat::RAW16";
+ case PixelFormat::RAW_OPAQUE:
+ return "PixelFormat::RAW_OPAQUE";
+ case PixelFormat::RGBA_1010102:
+ return "PixelFormat::RGBA_1010102";
+ case PixelFormat::RGBA_8888:
+ return "PixelFormat::RGBA_8888";
+ case PixelFormat::RGBA_FP16:
+ return "PixelFormat::RGBA_FP16";
+ case PixelFormat::RGBX_8888:
+ return "PixelFormat::RGBX_8888";
+ case PixelFormat::RGB_565:
+ return "PixelFormat::RGB_565";
+ case PixelFormat::RGB_888:
+ return "PixelFormat::RGB_888";
+ case PixelFormat::STENCIL_8:
+ return "PixelFormat::STENCIL_8";
+ case PixelFormat::Y16:
+ return "PixelFormat::Y16";
+ case PixelFormat::Y8:
+ return "PixelFormat::Y8";
+ case PixelFormat::YCBCR_420_888:
+ return "PixelFormat::YCBCR_420_888";
+ case PixelFormat::YCBCR_422_I:
+ return "PixelFormat::YCBCR_422_I";
+ case PixelFormat::YCBCR_422_SP:
+ return "PixelFormat::YCBCR_422_SP";
+ case PixelFormat::YCBCR_P010:
+ return "PixelFormat::YCBCR_P010";
+ case PixelFormat::YCRCB_420_SP:
+ return "PixelFormat::YCRCB_420_SP";
+ case PixelFormat::YV12:
+ return "PixelFormat::YV12";
+ }
+ return android::base::StringPrintf("PixelFormat::Unknown(%d)", static_cast<uint32_t>(format));
+}
+
+std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) {
+ using Underlying = typename std::underlying_type<BufferUsage>::type;
+
+ Underlying usage = static_cast<Underlying>(bufferUsage);
+
+ std::vector<std::string> usages;
+ if (usage & BufferUsage::CAMERA_INPUT) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_INPUT);
+ usages.push_back("BufferUsage::CAMERA_INPUT");
+ }
+ if (usage & BufferUsage::CAMERA_OUTPUT) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_OUTPUT);
+ usages.push_back("BufferUsage::CAMERA_OUTPUT");
+ }
+ if (usage & BufferUsage::COMPOSER_CURSOR) {
+ usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_CURSOR);
+ usages.push_back("BufferUsage::COMPOSER_CURSOR");
+ }
+ if (usage & BufferUsage::COMPOSER_OVERLAY) {
+ usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_OVERLAY);
+ usages.push_back("BufferUsage::COMPOSER_OVERLAY");
+ }
+ if (usage & BufferUsage::CPU_READ_OFTEN) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_OFTEN);
+ usages.push_back("BufferUsage::CPU_READ_OFTEN");
+ }
+ if (usage & BufferUsage::CPU_READ_NEVER) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_NEVER);
+ usages.push_back("BufferUsage::CPU_READ_NEVER");
+ }
+ if (usage & BufferUsage::CPU_READ_RARELY) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_RARELY);
+ usages.push_back("BufferUsage::CPU_READ_RARELY");
+ }
+ if (usage & BufferUsage::CPU_WRITE_NEVER) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_NEVER);
+ usages.push_back("BufferUsage::CPU_WRITE_NEVER");
+ }
+ if (usage & BufferUsage::CPU_WRITE_OFTEN) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_OFTEN);
+ usages.push_back("BufferUsage::CPU_WRITE_OFTEN");
+ }
+ if (usage & BufferUsage::CPU_WRITE_RARELY) {
+ usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_RARELY);
+ usages.push_back("BufferUsage::CPU_WRITE_RARELY");
+ }
+ if (usage & BufferUsage::GPU_RENDER_TARGET) {
+ usage &= ~static_cast<Underlying>(BufferUsage::GPU_RENDER_TARGET);
+ usages.push_back("BufferUsage::GPU_RENDER_TARGET");
+ }
+ if (usage & BufferUsage::GPU_TEXTURE) {
+ usage &= ~static_cast<Underlying>(BufferUsage::GPU_TEXTURE);
+ usages.push_back("BufferUsage::GPU_TEXTURE");
+ }
+ if (usage & BufferUsage::PROTECTED) {
+ usage &= ~static_cast<Underlying>(BufferUsage::PROTECTED);
+ usages.push_back("BufferUsage::PROTECTED");
+ }
+ if (usage & BufferUsage::RENDERSCRIPT) {
+ usage &= ~static_cast<Underlying>(BufferUsage::RENDERSCRIPT);
+ usages.push_back("BufferUsage::RENDERSCRIPT");
+ }
+ if (usage & BufferUsage::VIDEO_DECODER) {
+ usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_DECODER);
+ usages.push_back("BufferUsage::VIDEO_DECODER");
+ }
+ if (usage & BufferUsage::VIDEO_ENCODER) {
+ usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_ENCODER);
+ usages.push_back("BufferUsage::VIDEO_ENCODER");
+ }
+
+ if (usage) {
+ usages.push_back(android::base::StringPrintf("UnknownUsageBits-%" PRIu64, usage));
+ }
+
+ return android::base::Join(usages, '|');
+}
+
+int convertToDrmFormat(PixelFormat format, uint32_t* outDrmFormat) {
+ switch (format) {
+ case PixelFormat::BGRA_8888:
+ *outDrmFormat = DRM_FORMAT_ARGB8888;
+ return 0;
+ /**
+ * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers
+ * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width
+ * equal to their size in bytes.
+ */
+ case PixelFormat::BLOB:
+ *outDrmFormat = DRM_FORMAT_R8;
+ return 0;
+ case PixelFormat::DEPTH_16:
+ return -EINVAL;
+ case PixelFormat::DEPTH_24:
+ return -EINVAL;
+ case PixelFormat::DEPTH_24_STENCIL_8:
+ return -EINVAL;
+ case PixelFormat::DEPTH_32F:
+ return -EINVAL;
+ case PixelFormat::DEPTH_32F_STENCIL_8:
+ return -EINVAL;
+ case PixelFormat::HSV_888:
+ return -EINVAL;
+ case PixelFormat::IMPLEMENTATION_DEFINED:
+ *outDrmFormat = DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
+ return 0;
+ case PixelFormat::RAW10:
+ return -EINVAL;
+ case PixelFormat::RAW12:
+ return -EINVAL;
+ case PixelFormat::RAW16:
+ *outDrmFormat = DRM_FORMAT_R16;
+ return 0;
+ /* TODO use blob */
+ case PixelFormat::RAW_OPAQUE:
+ return -EINVAL;
+ case PixelFormat::RGBA_1010102:
+ *outDrmFormat = DRM_FORMAT_ABGR2101010;
+ return 0;
+ case PixelFormat::RGBA_8888:
+ *outDrmFormat = DRM_FORMAT_ABGR8888;
+ return 0;
+ case PixelFormat::RGBA_FP16:
+ *outDrmFormat = DRM_FORMAT_ABGR16161616F;
+ return 0;
+ case PixelFormat::RGBX_8888:
+ *outDrmFormat = DRM_FORMAT_XBGR8888;
+ return 0;
+ case PixelFormat::RGB_565:
+ *outDrmFormat = DRM_FORMAT_RGB565;
+ return 0;
+ case PixelFormat::RGB_888:
+ *outDrmFormat = DRM_FORMAT_RGB888;
+ return 0;
+ case PixelFormat::STENCIL_8:
+ return -EINVAL;
+ case PixelFormat::Y16:
+ *outDrmFormat = DRM_FORMAT_R16;
+ return 0;
+ case PixelFormat::Y8:
+ *outDrmFormat = DRM_FORMAT_R8;
+ return 0;
+ case PixelFormat::YCBCR_420_888:
+ *outDrmFormat = DRM_FORMAT_FLEX_YCbCr_420_888;
+ return 0;
+ case PixelFormat::YCBCR_422_SP:
+ return -EINVAL;
+ case PixelFormat::YCBCR_422_I:
+ return -EINVAL;
+ case PixelFormat::YCBCR_P010:
+ *outDrmFormat = DRM_FORMAT_P010;
+ return 0;
+ case PixelFormat::YCRCB_420_SP:
+ *outDrmFormat = DRM_FORMAT_NV21;
+ return 0;
+ case PixelFormat::YV12:
+ *outDrmFormat = DRM_FORMAT_YVU420_ANDROID;
+ return 0;
+ };
+ return -EINVAL;
+}
+
+int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) {
+ uint64_t bufferUsage = BO_USE_NONE;
+
+ if ((grallocUsage & BufferUsage::CPU_READ_MASK) ==
+ static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY)) {
+ bufferUsage |= BO_USE_SW_READ_RARELY;
+ }
+ if ((grallocUsage & BufferUsage::CPU_READ_MASK) ==
+ static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN)) {
+ bufferUsage |= BO_USE_SW_READ_OFTEN;
+ }
+ if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) ==
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY)) {
+ bufferUsage |= BO_USE_SW_WRITE_RARELY;
+ }
+ if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) ==
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN)) {
+ bufferUsage |= BO_USE_SW_WRITE_OFTEN;
+ }
+ if (grallocUsage & BufferUsage::GPU_TEXTURE) {
+ bufferUsage |= BO_USE_TEXTURE;
+ }
+ if (grallocUsage & BufferUsage::GPU_RENDER_TARGET) {
+ bufferUsage |= BO_USE_RENDERING;
+ }
+ if (grallocUsage & BufferUsage::COMPOSER_OVERLAY) {
+ /* HWC wants to use display hardware, but can defer to OpenGL. */
+ bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE;
+ }
+ if (grallocUsage & BufferUsage::PROTECTED) {
+ bufferUsage |= BO_USE_PROTECTED;
+ }
+ if (grallocUsage & BufferUsage::COMPOSER_CURSOR) {
+ bufferUsage |= BO_USE_NONE;
+ }
+ if (grallocUsage & BufferUsage::VIDEO_ENCODER) {
+ /*HACK: See b/30054495 */
+ bufferUsage |= BO_USE_SW_READ_OFTEN;
+ }
+ if (grallocUsage & BufferUsage::CAMERA_OUTPUT) {
+ bufferUsage |= BO_USE_CAMERA_WRITE;
+ }
+ if (grallocUsage & BufferUsage::CAMERA_INPUT) {
+ bufferUsage |= BO_USE_CAMERA_READ;
+ }
+ if (grallocUsage & BufferUsage::RENDERSCRIPT) {
+ bufferUsage |= BO_USE_RENDERSCRIPT;
+ }
+ if (grallocUsage & BufferUsage::VIDEO_DECODER) {
+ bufferUsage |= BO_USE_HW_VIDEO_DECODER;
+ }
+
+ *outBufferUsage = bufferUsage;
+ return 0;
+}
+
+int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor,
+ struct cros_gralloc_buffer_descriptor* outCrosDescriptor) {
+ outCrosDescriptor->name = descriptor.name;
+ outCrosDescriptor->width = descriptor.width;
+ outCrosDescriptor->height = descriptor.height;
+ outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format);
+ outCrosDescriptor->droid_usage = descriptor.usage;
+ outCrosDescriptor->reserved_region_size = descriptor.reservedSize;
+
+ if (convertToDrmFormat(descriptor.format, &outCrosDescriptor->drm_format)) {
+ std::string pixelFormatString = getPixelFormatString(descriptor.format);
+ drv_log("Failed to convert descriptor. Unsupported fomat %s\n", pixelFormatString.c_str());
+ return -1;
+ }
+ if (convertToBufferUsage(descriptor.usage, &outCrosDescriptor->use_flags)) {
+ std::string usageString = getUsageString(descriptor.usage);
+ drv_log("Failed to convert descriptor. Unsupported usage flags %s\n", usageString.c_str());
+ return -1;
+ }
+ return 0;
+}
+
+int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage) {
+ uint32_t mapUsage = BO_MAP_NONE;
+
+ if (grallocUsage & BufferUsage::CPU_READ_MASK) {
+ mapUsage |= BO_MAP_READ;
+ }
+ if (grallocUsage & BufferUsage::CPU_WRITE_MASK) {
+ mapUsage |= BO_MAP_WRITE;
+ }
+
+ *outMapUsage = mapUsage;
+ return 0;
+}
+
+int convertToFenceFd(const hidl_handle& fenceHandle, int* outFenceFd) {
+ if (!outFenceFd) {
+ return -EINVAL;
+ }
+
+ const native_handle_t* nativeHandle = fenceHandle.getNativeHandle();
+ if (nativeHandle && nativeHandle->numFds > 1) {
+ return -EINVAL;
+ }
+
+ *outFenceFd = (nativeHandle && nativeHandle->numFds == 1) ? nativeHandle->data[0] : -1;
+ return 0;
+}
+
+int convertToFenceHandle(int fenceFd, hidl_handle* outFenceHandle) {
+ if (!outFenceHandle) {
+ return -EINVAL;
+ }
+ if (fenceFd < 0) {
+ return 0;
+ }
+
+ NATIVE_HANDLE_DECLARE_STORAGE(handleStorage, 1, 0);
+ auto fenceHandle = native_handle_init(handleStorage, 1, 0);
+ fenceHandle->data[0] = fenceFd;
+
+ *outFenceHandle = fenceHandle;
+ return 0;
+}
+
+const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap() {
+ static const auto* kPlaneLayoutsMap =
+ new std::unordered_map<uint32_t, std::vector<PlaneLayout>>({
+ {DRM_FORMAT_ABGR8888,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 8,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 16,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_A,
+ .offsetInBits = 24,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 32,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_ABGR2101010,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 10},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 10,
+ .sizeInBits = 10},
+ {.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 20,
+ .sizeInBits = 10},
+ {.type = android::gralloc4::PlaneLayoutComponentType_A,
+ .offsetInBits = 30,
+ .sizeInBits = 2}},
+ .sampleIncrementInBits = 32,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_ABGR16161616F,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 16},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 16,
+ .sizeInBits = 16},
+ {.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 32,
+ .sizeInBits = 16},
+ {.type = android::gralloc4::PlaneLayoutComponentType_A,
+ .offsetInBits = 48,
+ .sizeInBits = 16}},
+ .sampleIncrementInBits = 64,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_ARGB8888,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 8,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 16,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_A,
+ .offsetInBits = 24,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 32,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_NV12,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ },
+ {
+ .components =
+ {{.type = android::gralloc4::PlaneLayoutComponentType_CB,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_CR,
+ .offsetInBits = 8,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 16,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ }}},
+
+ {DRM_FORMAT_NV21,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ },
+ {
+ .components =
+ {{.type = android::gralloc4::PlaneLayoutComponentType_CR,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_CB,
+ .offsetInBits = 8,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 16,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ }}},
+
+ {DRM_FORMAT_P010,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y,
+ .offsetInBits = 6,
+ .sizeInBits = 10}},
+ .sampleIncrementInBits = 16,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ },
+ {
+ .components =
+ {{.type = android::gralloc4::PlaneLayoutComponentType_CB,
+ .offsetInBits = 6,
+ .sizeInBits = 10},
+ {.type = android::gralloc4::PlaneLayoutComponentType_CR,
+ .offsetInBits = 22,
+ .sizeInBits = 10}},
+ .sampleIncrementInBits = 32,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ }}},
+
+ {DRM_FORMAT_R8,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_R16,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 16}},
+ .sampleIncrementInBits = 16,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_RGB565,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 5},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 5,
+ .sizeInBits = 6},
+ {.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 11,
+ .sizeInBits = 5}},
+ .sampleIncrementInBits = 16,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_RGB888,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 8,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 16,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 24,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_XBGR8888,
+ {{
+ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B,
+ .offsetInBits = 0,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_G,
+ .offsetInBits = 8,
+ .sizeInBits = 8},
+ {.type = android::gralloc4::PlaneLayoutComponentType_R,
+ .offsetInBits = 16,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 32,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ }}},
+
+ {DRM_FORMAT_YVU420,
+ {
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_Y,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ },
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_CB,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ },
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_CR,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ },
+ }},
+
+ {DRM_FORMAT_YVU420_ANDROID,
+ {
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_Y,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 1,
+ .verticalSubsampling = 1,
+ },
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_CR,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ },
+ {
+ .components = {{.type = android::gralloc4::
+ PlaneLayoutComponentType_CB,
+ .offsetInBits = 0,
+ .sizeInBits = 8}},
+ .sampleIncrementInBits = 8,
+ .horizontalSubsampling = 2,
+ .verticalSubsampling = 2,
+ },
+ }},
+ });
+ return *kPlaneLayoutsMap;
+}
+
+int getPlaneLayouts(uint32_t drmFormat, std::vector<PlaneLayout>* outPlaneLayouts) {
+ const auto& planeLayoutsMap = GetPlaneLayoutsMap();
+ const auto it = planeLayoutsMap.find(drmFormat);
+ if (it == planeLayoutsMap.end()) {
+ drv_log("Unknown plane layout for format %d\n", drmFormat);
+ return -1;
+ }
+
+ *outPlaneLayouts = it->second;
+ return 0;
+}
\ No newline at end of file
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.h b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
new file mode 100644
index 0000000..094ef74
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <string>
+#include <vector>
+
+#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+
+#include "cros_gralloc/cros_gralloc_types.h"
+
+std::string getDrmFormatString(uint32_t drmFormat);
+
+std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format);
+
+std::string getUsageString(
+ android::hardware::hidl_bitfield<android::hardware::graphics::common::V1_2::BufferUsage>
+ usage);
+
+int convertToDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat format,
+ uint32_t* outDrmFormat);
+
+int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage);
+
+int convertToCrosDescriptor(
+ const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo& descriptor,
+ struct cros_gralloc_buffer_descriptor* outCrosDescriptor);
+
+int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage);
+
+int convertToFenceFd(const android::hardware::hidl_handle& fence_handle, int* out_fence_fd);
+
+int convertToFenceHandle(int fence_fd, android::hardware::hidl_handle* out_fence_handle);
+
+int getPlaneLayouts(
+ uint32_t drm_format,
+ std::vector<aidl::android::hardware::graphics::common::PlaneLayout>* out_layouts);
\ No newline at end of file
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc
new file mode 100644
index 0000000..a96a6e1
--- /dev/null
+++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc
@@ -0,0 +1,24 @@
+#
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm
+ interface android.hardware.graphics.allocator@4.0::IAllocator default
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
+ writepid /dev/cpuset/system-background/tasks
diff --git a/drv.c b/drv.c
index 920cf4d..636cd07 100644
--- a/drv.c
+++ b/drv.c
@@ -117,7 +117,7 @@
#ifdef DRV_VC4
&backend_vc4,
#endif
- &backend_vgem, &backend_virtio_gpu,
+ &backend_vgem, &backend_virtio_gpu,
};
for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
@@ -558,6 +558,21 @@
return ret;
}
+int drv_bo_flush(struct bo *bo, struct mapping *mapping)
+{
+ int ret = 0;
+
+ assert(mapping);
+ assert(mapping->vma);
+ assert(mapping->refcount > 0);
+ assert(mapping->vma->refcount > 0);
+
+ if (bo->drv->backend->bo_flush)
+ ret = bo->drv->backend->bo_flush(bo, mapping);
+
+ return ret;
+}
+
int drv_bo_flush_or_unmap(struct bo *bo, struct mapping *mapping)
{
int ret = 0;
@@ -648,6 +663,11 @@
return bo->meta.format;
}
+size_t drv_bo_get_total_size(struct bo *bo)
+{
+ return bo->meta.total_size;
+}
+
uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
{
if (drv->backend->resolve_format)
diff --git a/drv.h b/drv.h
index 2b86aad..f19f9de 100644
--- a/drv.h
+++ b/drv.h
@@ -145,6 +145,8 @@
int drv_bo_invalidate(struct bo *bo, struct mapping *mapping);
+int drv_bo_flush(struct bo *bo, struct mapping *mapping);
+
int drv_bo_flush_or_unmap(struct bo *bo, struct mapping *mapping);
uint32_t drv_bo_get_width(struct bo *bo);
diff --git a/helpers.c b/helpers.c
index fed4af9..17b1765 100644
--- a/helpers.c
+++ b/helpers.c
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <xf86drm.h>
#include "drv_priv.h"
@@ -92,6 +94,9 @@
case DRM_FORMAT_RGB332:
return &packed_1bpp_layout;
+ case DRM_FORMAT_R16:
+ return &packed_2bpp_layout;
+
case DRM_FORMAT_YVU420:
case DRM_FORMAT_YVU420_ANDROID:
return &triplanar_yuv_420_layout;
@@ -312,6 +317,11 @@
aligned_width = width;
aligned_height = height;
switch (format) {
+ case DRM_FORMAT_R16:
+ /* HAL_PIXEL_FORMAT_Y16 requires that the buffer's width be 16 pixel
+ * aligned. See hardware/interfaces/graphics/common/1.0/types.hal. */
+ aligned_width = ALIGN(width, 16);
+ break;
case DRM_FORMAT_YVU420_ANDROID:
/* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not
* be aligned. Update 'height' so that drv_bo_from_format below
@@ -327,6 +337,7 @@
break;
case DRM_FORMAT_YVU420:
case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
/* Adjust the height to include room for chroma planes */
aligned_height = 3 * DIV_ROUND_UP(height, 2);
break;
diff --git a/virgl_hw.h b/virgl_hw.h
index 145780b..1c493d1 100644
--- a/virgl_hw.h
+++ b/virgl_hw.h
@@ -69,7 +69,7 @@
VIRGL_FORMAT_R8_UNORM = 64,
VIRGL_FORMAT_R8G8_UNORM = 65,
-
+ VIRGL_FORMAT_R8G8B8_UNORM = 66,
VIRGL_FORMAT_R8G8B8A8_UNORM = 67,
VIRGL_FORMAT_R8_SNORM = 74,
diff --git a/virtio_gpu.c b/virtio_gpu.c
index 4dbcc4f..83d46d3 100644
--- a/virtio_gpu.c
+++ b/virtio_gpu.c
@@ -4,6 +4,7 @@
* found in the LICENSE file.
*/
+#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
@@ -50,21 +51,27 @@
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888 };
-static const uint32_t dumb_texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
- DRM_FORMAT_NV12,
- DRM_FORMAT_YVU420_ANDROID };
+static const uint32_t dumb_texture_source_formats[] = {
+ DRM_FORMAT_R8, DRM_FORMAT_R16, DRM_FORMAT_YVU420,
+ DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID
+};
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R8, DRM_FORMAT_RG88,
- DRM_FORMAT_YVU420_ANDROID };
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
+ DRM_FORMAT_R8, DRM_FORMAT_R16,
+ DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID };
struct virtio_gpu_priv {
int caps_is_v2;
union virgl_caps caps;
+ int host_gbm_enabled;
};
static uint32_t translate_format(uint32_t drm_fourcc)
{
switch (drm_fourcc) {
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ return VIRGL_FORMAT_R8G8B8_UNORM;
case DRM_FORMAT_XRGB8888:
return VIRGL_FORMAT_B8G8R8X8_UNORM;
case DRM_FORMAT_ARGB8888:
@@ -73,6 +80,8 @@
return VIRGL_FORMAT_R8G8B8X8_UNORM;
case DRM_FORMAT_ABGR8888:
return VIRGL_FORMAT_R8G8B8A8_UNORM;
+ case DRM_FORMAT_ABGR16161616F:
+ return VIRGL_FORMAT_R16G16B16A16_UNORM;
case DRM_FORMAT_RGB565:
return VIRGL_FORMAT_B5G6R5_UNORM;
case DRM_FORMAT_R8:
@@ -81,6 +90,8 @@
return VIRGL_FORMAT_R8G8_UNORM;
case DRM_FORMAT_NV12:
return VIRGL_FORMAT_NV12;
+ case DRM_FORMAT_NV21:
+ return VIRGL_FORMAT_NV21;
case DRM_FORMAT_YVU420:
case DRM_FORMAT_YVU420_ANDROID:
return VIRGL_FORMAT_YV12;
@@ -89,8 +100,8 @@
}
}
-static bool virtio_gpu_supports_format(struct virgl_supported_format_mask *supported,
- uint32_t drm_format)
+static bool virtio_gpu_bitmask_supports_format(struct virgl_supported_format_mask *supported,
+ uint32_t drm_format)
{
uint32_t virgl_format = translate_format(drm_format);
if (!virgl_format) {
@@ -102,6 +113,243 @@
return supported->bitmask[bitmask_index] & (1 << bit_index);
}
+// The metadata generated here for emulated buffers is slightly different than the metadata
+// generated by drv_bo_from_format. In order to simplify transfers in the flush and invalidate
+// functions below, the emulated buffers are oversized. For example, ignoring stride alignment
+// requirements to demonstrate, a 6x6 YUV420 image buffer might have the following layout from
+// drv_bo_from_format:
+//
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | U | U | U | U | U | U |
+// | U | U | U | V | V | V |
+// | V | V | V | V | V | V |
+//
+// where each plane immediately follows the previous plane in memory. This layout makes it
+// difficult to compute the transfers needed for example when the middle 2x2 region of the
+// image is locked and needs to be flushed/invalidated.
+//
+// Emulated multi-plane buffers instead have a layout of:
+//
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | U | U | U | | | |
+// | U | U | U | | | |
+// | U | U | U | | | |
+// | V | V | V | | | |
+// | V | V | V | | | |
+// | V | V | V | | | |
+//
+// where each plane is placed as a sub-image (albeit with a very large stride) in order to
+// simplify transfers into 3 sub-image transfers for the above example.
+//
+// Additional note: the V-plane is not placed to the right of the U-plane due to some
+// observed failures in media framework code which assumes the V-plane is not
+// "row-interlaced" with the U-plane.
+static void virtio_gpu_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
+{
+ uint32_t y_plane_height;
+ uint32_t c_plane_height;
+ uint32_t original_width = bo->meta.width;
+ uint32_t original_height = bo->meta.height;
+
+ metadata->format = DRM_FORMAT_R8;
+ switch (bo->meta.format) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ // Bi-planar
+ metadata->num_planes = 2;
+
+ y_plane_height = original_height;
+ c_plane_height = DIV_ROUND_UP(original_height, 2);
+
+ metadata->width = original_width;
+ metadata->height = y_plane_height + c_plane_height;
+
+ // Y-plane (full resolution)
+ metadata->strides[0] = metadata->width;
+ metadata->offsets[0] = 0;
+ metadata->sizes[0] = metadata->width * y_plane_height;
+
+ // CbCr-plane (half resolution, interleaved, placed below Y-plane)
+ metadata->strides[1] = metadata->width;
+ metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
+ metadata->sizes[1] = metadata->width * c_plane_height;
+
+ metadata->total_size = metadata->width * metadata->height;
+ break;
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ // Tri-planar
+ metadata->num_planes = 3;
+
+ y_plane_height = original_height;
+ c_plane_height = DIV_ROUND_UP(original_height, 2);
+
+ metadata->width = ALIGN(original_width, 32);
+ metadata->height = y_plane_height + (2 * c_plane_height);
+
+ // Y-plane (full resolution)
+ metadata->strides[0] = metadata->width;
+ metadata->offsets[0] = 0;
+ metadata->sizes[0] = metadata->width * original_height;
+
+ // Cb-plane (half resolution, placed below Y-plane)
+ metadata->strides[1] = metadata->width;
+ metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
+ metadata->sizes[1] = metadata->width * c_plane_height;
+
+ // Cr-plane (half resolution, placed below Cb-plane)
+ metadata->strides[2] = metadata->width;
+ metadata->offsets[2] = metadata->offsets[1] + metadata->sizes[1];
+ metadata->sizes[2] = metadata->width * c_plane_height;
+
+ metadata->total_size = metadata->width * metadata->height;
+ break;
+ default:
+ break;
+ }
+}
+
+struct virtio_transfers_params {
+ size_t xfers_needed;
+ struct rectangle xfer_boxes[DRV_MAX_PLANES];
+};
+
+static void virtio_gpu_get_emulated_transfers_params(const struct bo *bo,
+ const struct rectangle *transfer_box,
+ struct virtio_transfers_params *xfer_params)
+{
+ uint32_t y_plane_height;
+ uint32_t c_plane_height;
+ struct bo_metadata emulated_metadata;
+
+ if (transfer_box->x == 0 && transfer_box->y == 0 && transfer_box->width == bo->meta.width &&
+ transfer_box->height == bo->meta.height) {
+ virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
+
+ xfer_params->xfers_needed = 1;
+ xfer_params->xfer_boxes[0].x = 0;
+ xfer_params->xfer_boxes[0].y = 0;
+ xfer_params->xfer_boxes[0].width = emulated_metadata.width;
+ xfer_params->xfer_boxes[0].height = emulated_metadata.height;
+
+ return;
+ }
+
+ switch (bo->meta.format) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ // Bi-planar
+ xfer_params->xfers_needed = 2;
+
+ y_plane_height = bo->meta.height;
+ c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
+
+ // Y-plane (full resolution)
+ xfer_params->xfer_boxes[0].x = transfer_box->x;
+ xfer_params->xfer_boxes[0].y = transfer_box->y;
+ xfer_params->xfer_boxes[0].width = transfer_box->width;
+ xfer_params->xfer_boxes[0].height = transfer_box->height;
+
+ // CbCr-plane (half resolution, interleaved, placed below Y-plane)
+ xfer_params->xfer_boxes[1].x = transfer_box->x;
+ xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
+ xfer_params->xfer_boxes[1].width = transfer_box->width;
+ xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+ break;
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ // Tri-planar
+ xfer_params->xfers_needed = 3;
+
+ y_plane_height = bo->meta.height;
+ c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
+
+ // Y-plane (full resolution)
+ xfer_params->xfer_boxes[0].x = transfer_box->x;
+ xfer_params->xfer_boxes[0].y = transfer_box->y;
+ xfer_params->xfer_boxes[0].width = transfer_box->width;
+ xfer_params->xfer_boxes[0].height = transfer_box->height;
+
+ // Cb-plane (half resolution, placed below Y-plane)
+ xfer_params->xfer_boxes[1].x = transfer_box->x;
+ xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
+ xfer_params->xfer_boxes[1].width = DIV_ROUND_UP(transfer_box->width, 2);
+ xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+ // Cr-plane (half resolution, placed below Cb-plane)
+ xfer_params->xfer_boxes[2].x = transfer_box->x;
+ xfer_params->xfer_boxes[2].y = transfer_box->y + y_plane_height + c_plane_height;
+ xfer_params->xfer_boxes[2].width = DIV_ROUND_UP(transfer_box->width, 2);
+ xfer_params->xfer_boxes[2].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+ break;
+ }
+}
+
+static bool virtio_gpu_supports_combination_natively(struct driver *drv, uint32_t drm_format,
+ uint64_t use_flags)
+{
+ struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+ if (priv->caps.max_version == 0) {
+ return true;
+ }
+
+ if ((use_flags & BO_USE_RENDERING) &&
+ !virtio_gpu_bitmask_supports_format(&priv->caps.v1.render, drm_format)) {
+ return false;
+ }
+
+ if ((use_flags & BO_USE_TEXTURE) &&
+ !virtio_gpu_bitmask_supports_format(&priv->caps.v1.sampler, drm_format)) {
+ return false;
+ }
+
+ if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
+ !virtio_gpu_bitmask_supports_format(&priv->caps.v2.scanout, drm_format)) {
+ return false;
+ }
+
+ return true;
+}
+
+// For virtio backends that do not support formats natively (e.g. multi-planar formats are not
+// supported in virglrenderer when gbm is unavailable on the host machine), whether or not the
+// format and usage combination can be handled as a blob (byte buffer).
+static bool virtio_gpu_supports_combination_through_emulation(struct driver *drv,
+ uint32_t drm_format,
+ uint64_t use_flags)
+{
+ struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+ // Only enable emulation on non-gbm virtio backends.
+ if (priv->host_gbm_enabled) {
+ return false;
+ }
+
+ if (use_flags & (BO_USE_RENDERING | BO_USE_SCANOUT)) {
+ return false;
+ }
+
+ if (!virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags)) {
+ return false;
+ }
+
+ return drm_format == DRM_FORMAT_NV12 || drm_format == DRM_FORMAT_NV21 ||
+ drm_format == DRM_FORMAT_YVU420 || drm_format == DRM_FORMAT_YVU420_ANDROID;
+}
+
// Adds the given buffer combination to the list of supported buffer combinations if the
// combination is supported by the virtio backend.
static void virtio_gpu_add_combination(struct driver *drv, uint32_t drm_format,
@@ -110,22 +358,18 @@
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
if (features[feat_3d].enabled && priv->caps.max_version >= 1) {
- if ((use_flags & BO_USE_RENDERING) &&
- !virtio_gpu_supports_format(&priv->caps.v1.render, drm_format)) {
- drv_log("Skipping unsupported render format: %d\n", drm_format);
- return;
+ if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
+ !virtio_gpu_supports_combination_natively(drv, drm_format, use_flags)) {
+ drv_log("Scanout format: %d\n", drm_format);
+ use_flags &= ~BO_USE_SCANOUT;
}
- if ((use_flags & BO_USE_TEXTURE) &&
- !virtio_gpu_supports_format(&priv->caps.v1.sampler, drm_format)) {
- drv_log("Skipping unsupported texture format: %d\n", drm_format);
+ if (!virtio_gpu_supports_combination_natively(drv, drm_format, use_flags) &&
+ !virtio_gpu_supports_combination_through_emulation(drv, drm_format,
+ use_flags)) {
+ drv_log("Skipping unsupported combination format:%d\n", drm_format);
return;
}
- if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
- !virtio_gpu_supports_format(&priv->caps.v2.scanout, drm_format)) {
- drv_log("Unsupported scanout format: %d\n", drm_format);
- use_flags &= ~BO_USE_SCANOUT;
- }
}
drv_add_combination(drv, drm_format, metadata, use_flags);
@@ -196,11 +440,30 @@
uint64_t use_flags)
{
int ret;
+ size_t i;
uint32_t stride;
struct drm_virtgpu_resource_create res_create;
+ struct bo_metadata emulated_metadata;
- stride = drv_stride_from_format(format, width, 0);
- drv_bo_from_format(bo, stride, height, format);
+ if (virtio_gpu_supports_combination_natively(bo->drv, format, use_flags)) {
+ stride = drv_stride_from_format(format, width, 0);
+ drv_bo_from_format(bo, stride, height, format);
+ } else {
+ assert(
+ virtio_gpu_supports_combination_through_emulation(bo->drv, format, use_flags));
+
+ virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
+
+ format = emulated_metadata.format;
+ width = emulated_metadata.width;
+ height = emulated_metadata.height;
+ for (i = 0; i < emulated_metadata.num_planes; i++) {
+ bo->meta.strides[i] = emulated_metadata.strides[i];
+ bo->meta.offsets[i] = emulated_metadata.offsets[i];
+ bo->meta.sizes[i] = emulated_metadata.sizes[i];
+ }
+ bo->meta.total_size = emulated_metadata.total_size;
+ }
/*
* Setting the target is intended to ensure this resource gets bound as a 2D
@@ -290,26 +553,39 @@
return ret;
}
-static int virtio_gpu_init(struct driver *drv)
+static void virtio_gpu_init_features_and_caps(struct driver *drv)
{
- int ret;
- struct virtio_gpu_priv *priv;
+ struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
- priv = calloc(1, sizeof(*priv));
- drv->priv = priv;
for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) {
struct drm_virtgpu_getparam params = { 0 };
params.param = features[i].feature;
params.value = (uint64_t)(uintptr_t)&features[i].enabled;
- ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, ¶ms);
+ int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, ¶ms);
if (ret)
drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
}
if (features[feat_3d].enabled) {
virtio_gpu_get_caps(drv, &priv->caps, &priv->caps_is_v2);
+ }
+ // Multi-planar formats are currently only supported in virglrenderer through gbm.
+ priv->host_gbm_enabled =
+ virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
+}
+
+static int virtio_gpu_init(struct driver *drv)
+{
+ struct virtio_gpu_priv *priv;
+
+ priv = calloc(1, sizeof(*priv));
+ drv->priv = priv;
+
+ virtio_gpu_init_features_and_caps(drv);
+
+ if (features[feat_3d].enabled) {
/* This doesn't mean host can scanout everything, it just means host
* hypervisor can show it. */
virtio_gpu_add_combinations(drv, render_target_formats,
@@ -336,16 +612,29 @@
&LINEAR_METADATA, BO_USE_TEXTURE_MASK);
virtio_gpu_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
BO_USE_SW_MASK | BO_USE_LINEAR);
+ virtio_gpu_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
+ BO_USE_SW_MASK | BO_USE_LINEAR);
}
/* Android CTS tests require this. */
+ virtio_gpu_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
virtio_gpu_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
+ virtio_gpu_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA,
+ BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
BO_USE_HW_VIDEO_ENCODER);
+ drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
+ BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+ BO_USE_HW_VIDEO_ENCODER);
+ drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA,
+ BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+ BO_USE_HW_VIDEO_ENCODER | BO_USE_RENDERSCRIPT);
drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER);
+ drv_modify_combination(drv, DRM_FORMAT_R16, &LINEAR_METADATA,
+ BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER);
return drv_modify_linear_combinations(drv);
}
@@ -384,8 +673,11 @@
static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
{
int ret;
+ size_t i;
struct drm_virtgpu_3d_transfer_from_host xfer;
struct drm_virtgpu_3d_wait waitcmd;
+ struct virtio_transfers_params xfer_params;
+ struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
if (!features[feat_3d].enabled)
return 0;
@@ -397,27 +689,44 @@
memset(&xfer, 0, sizeof(xfer));
xfer.bo_handle = mapping->vma->handle;
- xfer.box.x = mapping->rect.x;
- xfer.box.y = mapping->rect.y;
- xfer.box.w = mapping->rect.width;
- xfer.box.h = mapping->rect.height;
- xfer.box.d = 1;
if ((bo->meta.use_flags & BO_USE_RENDERING) == 0) {
- // Unfortunately, the kernel doesn't actually pass the guest layer_stride and
- // guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h). For gbm
- // based resources, we can work around this by using the level field to pass
- // the stride to virglrenderer's gbm transfer code. However, we need to avoid
- // doing this for resources which don't rely on that transfer code, which is
- // resources with the BO_USE_RENDERING flag set.
+ // Unfortunately, the kernel doesn't actually pass the guest layer_stride
+ // and guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h).
+ // For gbm based resources, we can work around this by using the level field
+ // to pass the stride to virglrenderer's gbm transfer code. However, we need
+ // to avoid doing this for resources which don't rely on that transfer code,
+ // which is resources with the BO_USE_RENDERING flag set.
// TODO(b/145993887): Send also stride when the patches are landed
- xfer.level = bo->meta.strides[0];
+ if (priv->host_gbm_enabled) {
+ xfer.level = bo->meta.strides[0];
+ }
}
- ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer);
- if (ret) {
- drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n", strerror(errno));
- return -errno;
+ if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
+ bo->meta.use_flags)) {
+ xfer_params.xfers_needed = 1;
+ xfer_params.xfer_boxes[0] = mapping->rect;
+ } else {
+ assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
+ bo->meta.use_flags));
+
+ virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
+ }
+
+ for (i = 0; i < xfer_params.xfers_needed; i++) {
+ xfer.box.x = xfer_params.xfer_boxes[i].x;
+ xfer.box.y = xfer_params.xfer_boxes[i].y;
+ xfer.box.w = xfer_params.xfer_boxes[i].width;
+ xfer.box.h = xfer_params.xfer_boxes[i].height;
+ xfer.box.d = 1;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer);
+ if (ret) {
+ drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n",
+ strerror(errno));
+ return -errno;
+ }
}
// The transfer needs to complete before invalidate returns so that any host changes
@@ -437,8 +746,11 @@
static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
{
int ret;
+ size_t i;
struct drm_virtgpu_3d_transfer_to_host xfer;
struct drm_virtgpu_3d_wait waitcmd;
+ struct virtio_transfers_params xfer_params;
+ struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
if (!features[feat_3d].enabled)
return 0;
@@ -448,21 +760,38 @@
memset(&xfer, 0, sizeof(xfer));
xfer.bo_handle = mapping->vma->handle;
- xfer.box.x = mapping->rect.x;
- xfer.box.y = mapping->rect.y;
- xfer.box.w = mapping->rect.width;
- xfer.box.h = mapping->rect.height;
- xfer.box.d = 1;
// Unfortunately, the kernel doesn't actually pass the guest layer_stride and
// guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h). We can use
// the level to work around this.
- xfer.level = bo->meta.strides[0];
+ if (priv->host_gbm_enabled) {
+ xfer.level = bo->meta.strides[0];
+ }
- ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);
- if (ret) {
- drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n", strerror(errno));
- return -errno;
+ if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
+ bo->meta.use_flags)) {
+ xfer_params.xfers_needed = 1;
+ xfer_params.xfer_boxes[0] = mapping->rect;
+ } else {
+ assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
+ bo->meta.use_flags));
+
+ virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
+ }
+
+ for (i = 0; i < xfer_params.xfers_needed; i++) {
+ xfer.box.x = xfer_params.xfer_boxes[i].x;
+ xfer.box.y = xfer_params.xfer_boxes[i].y;
+ xfer.box.w = xfer_params.xfer_boxes[i].width;
+ xfer.box.h = xfer_params.xfer_boxes[i].height;
+ xfer.box.d = 1;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);
+ if (ret) {
+ drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n",
+ strerror(errno));
+ return -errno;
+ }
}
// If the buffer is only accessed by the host GPU, then the flush is ordered
@@ -485,7 +814,6 @@
static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
{
-
switch (format) {
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
/* Camera subsystem requires NV12. */