Merge changes from topic 'gralloc-hal'
* changes:
graphics: add a default implementation to IMapper
graphics: add IMapper to complement IAllocator
graphics: add a default implementation to IAllocator
Add HAL definition for graphics buffer allocator
diff --git a/Android.bp b/Android.bp
index 7188e91..1d90fd1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3,6 +3,10 @@
"audio/common/2.0",
"audio/effect/2.0",
"benchmarks/msgq/1.0",
+ "graphics/allocator/2.0",
+ "graphics/allocator/2.0/default",
+ "graphics/mapper/2.0",
+ "graphics/mapper/2.0/default",
"memtrack/1.0",
"memtrack/1.0/default",
"light/2.0",
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
new file mode 100644
index 0000000..f29c50b
--- /dev/null
+++ b/graphics/allocator/2.0/Android.bp
@@ -0,0 +1,46 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+ name: "android.hardware.graphics.allocator@2.0_genc++",
+ tool: "hidl-gen",
+ cmd: "$tool -o $genDir -Lc++ -randroid.hardware:hardware/interfaces android.hardware.graphics.allocator@2.0",
+ srcs: [
+ "types.hal",
+ "IAllocator.hal",
+ ],
+ out: [
+ "android/hardware/graphics/allocator/2.0/types.cpp",
+ "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
+ ],
+}
+
+genrule {
+ name: "android.hardware.graphics.allocator@2.0_genc++_headers",
+ tool: "hidl-gen",
+ cmd: "$tool -o $genDir -Lc++ -randroid.hardware:hardware/interfaces android.hardware.graphics.allocator@2.0",
+ srcs: [
+ "types.hal",
+ "IAllocator.hal",
+ ],
+ out: [
+ "android/hardware/graphics/allocator/2.0/types.h",
+ "android/hardware/graphics/allocator/2.0/IAllocator.h",
+ "android/hardware/graphics/allocator/2.0/IHwAllocator.h",
+ "android/hardware/graphics/allocator/2.0/BnAllocator.h",
+ "android/hardware/graphics/allocator/2.0/BpAllocator.h",
+ "android/hardware/graphics/allocator/2.0/BsAllocator.h",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.graphics.allocator@2.0",
+ generated_sources: ["android.hardware.graphics.allocator@2.0_genc++"],
+ generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
+ export_generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
+ shared_libs: [
+ "libhidl",
+ "libhwbinder",
+ "libutils",
+ "libcutils",
+ ],
+}
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
new file mode 100644
index 0000000..8accb82
--- /dev/null
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.hardware.graphics.allocator@2.0;
+
+interface IAllocator {
+ enum Capability : int32_t {
+ /* reserved */
+ INVALID = 0,
+
+ /*
+ * testAllocate will always return UNDEFINED unless this capability
+ * is supported.
+ */
+ TEST_ALLOCATE = 1,
+ };
+
+ struct BufferDescriptorInfo {
+ /*
+ * The width specifies how many columns of pixels should be in the
+ * allocated buffer, but does not necessarily represent the offset in
+ * columns between the same column in adjacent rows. The rows may be
+ * padded.
+ */
+ uint32_t width;
+
+ /*
+ * The height specifies how many rows of pixels should be in the
+ * allocated buffer.
+ */
+ uint32_t height;
+
+ /* Buffer pixel format. */
+ PixelFormat format;
+
+ /*
+ * Buffer producer usage mask; valid flags can be found in the
+ * definition of ProducerUsage.
+ */
+ uint64_t producerUsageMask;
+
+ /*
+ * Buffer consumer usage mask; valid flags can be found in the
+ * definition of ConsumerUsage.
+ */
+ uint64_t consumerUsageMask;
+ };
+
+ /*
+ * Provides a list of supported capabilities (as described in the
+ * definition of Capability above). This list must not change after
+ * initialization.
+ *
+ * @return capabilities is a list of supported capabilities.
+ */
+ getCapabilities() generates (vec<Capability> capabilities);
+
+ /*
+ * Retrieves implementation-defined debug information, which will be
+ * displayed during, for example, `dumpsys SurfaceFlinger`.
+ *
+ * @return debugInfo is a string of debug information.
+ */
+ dumpDebugInfo() generates (string debugInfo);
+
+ /*
+ * Creates a new, opaque buffer descriptor.
+ *
+ * @param descriptorInfo specifies the attributes of the buffer
+ * descriptor.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_VALUE when any attribute in descriptorInfo is invalid.
+ * NO_RESOURCES when no more descriptors can currently be created.
+ * @return descriptor is the newly created buffer descriptor.
+ */
+ createDescriptor(BufferDescriptorInfo descriptorInfo)
+ generates (Error error,
+ BufferDescriptor descriptor);
+
+ /*
+ * Destroys an existing buffer descriptor.
+ *
+ * @param descriptor is the descriptor to destroy.
+ * @return error is either NONE or BAD_DESCRIPTOR.
+ */
+ destroyDescriptor(BufferDescriptor descriptor) generates (Error error);
+
+ /*
+ * Tests whether a buffer allocation can succeed, ignoring potential
+ * resource contention which might lead to a NO_RESOURCES error.
+ *
+ * @param descriptors is a list of buffer descriptors.
+ * @return error is NONE or NOT_SHARED upon success;
+ * NONE when buffers can be created and share a backing store.
+ * NOT_SHARED when buffers can be created but require more than a
+ * backing store.
+ * Otherwise,
+ * BAD_DESCRIPTOR when any of the descriptors is invalid.
+ * UNSUPPORTED when any of the descriptors can never be satisfied.
+ * UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
+ */
+ testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);
+
+ /*
+ * Attempts to allocate a list of buffers sharing a backing store.
+ *
+ * Each buffer will correspond to one of the descriptors passed into the
+ * function and will hold a reference to its backing store. If the device
+ * is unable to share the backing store between the buffers, it must
+ * attempt to allocate the buffers with different backing stores and
+ * return NOT_SHARED if it is successful.
+ *
+ * @param descriptors is the buffer descriptors to attempt to allocate.
+ * @return error is NONE or NOT_SHARED upon success;
+ * NONE when buffers can be created and share a backing store.
+ * NOT_SHARED when buffers can be created but require more than a
+ * backing store.
+ * Otherwise,
+ * BAD_DESCRIPTOR when any of the descriptors is invalid.
+ * UNSUPPORTED when any of the descriptors can never be satisfied.
+ * NO_RESOURCES when any of the buffers cannot be created at this
+ * time.
+ * @return buffers is the allocated buffers.
+ */
+ allocate(vec<BufferDescriptor> descriptors)
+ generates (Error error,
+ vec<Buffer> buffers);
+
+ /*
+ * Frees a buffer.
+ *
+ * @param buffer is the buffer to be freed.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer is invalid.
+ */
+ free(Buffer buffer) generates (Error error);
+
+ /*
+ * Exports a buffer for use in other client libraries or for cross-process
+ * sharing.
+ *
+ * The exported handle is a handle to the backing store of the buffer, not
+ * to the buffer itself. It however may not hold any reference to the
+ * backing store and may be considered invalid by client libraries. To use
+ * it and, in most cases, to save it for later use, a client must make a
+ * clone of the handle and have the cloned handle hold a reference to the
+ * backing store. Such a cloned handle will stay valid even after the
+ * original buffer is freed. Refer to native_handle_clone and IMapper for
+ * how a handle is cloned and how a reference is added.
+ *
+ * @param descriptor is the descriptor used to allocate the buffer.
+ * @param buffer is the buffer to be exported.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DESCRIPTOR when the descriptor is invalid.
+ * BAD_BUFFER when the buffer is invalid.
+ * BAD_VALUE when descriptor and buffer do not match.
+ * NO_RESOURCES when the buffer cannot be exported at this time.
+ * @return bufferHandle is the exported handle.
+ */
+ exportHandle(BufferDescriptor descriptor,
+ Buffer buffer)
+ generates (Error error,
+ handle bufferHandle);
+};
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
new file mode 100644
index 0000000..9a24773
--- /dev/null
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -0,0 +1,24 @@
+cc_library_shared {
+ name: "android.hardware.graphics.allocator@2.0-impl",
+ relative_install_path: "hw",
+ srcs: ["Gralloc.cpp"],
+ cppflags: ["-Wall", "-Wextra"],
+ shared_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidl",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_library_static {
+ name: "libgralloc1-adapter",
+ srcs: ["gralloc1-adapter.c"],
+ include_dirs: ["system/core/libsync/include"],
+ cflags: ["-Wall", "-Wextra", "-Wno-unused-parameter"],
+ export_include_dirs: ["."],
+}
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
new file mode 100644
index 0000000..a7fc6c1
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#define LOG_TAG "GrallocPassthrough"
+
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include <string.h>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+#include "Gralloc.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+class GrallocHal : public IAllocator {
+public:
+ GrallocHal(const hw_module_t* module);
+ virtual ~GrallocHal();
+
+ // IAllocator interface
+ Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
+ Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+ Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+ createDescriptor_cb hidl_cb) override;
+ Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
+
+ Return<Error> testAllocate(
+ const hidl_vec<BufferDescriptor>& descriptors) override;
+ Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
+ allocate_cb hidl_cb) override;
+ Return<Error> free(Buffer buffer) override;
+
+ Return<void> exportHandle(BufferDescriptor descriptor,
+ Buffer buffer, exportHandle_cb hidl_cb) override;
+
+private:
+ void initCapabilities();
+
+ template<typename T>
+ void initDispatch(T& func, gralloc1_function_descriptor_t desc);
+ void initDispatch();
+
+ bool hasCapability(Capability capability) const;
+
+ gralloc1_device_t* mDevice;
+
+ std::unordered_set<Capability> mCapabilities;
+
+ struct {
+ GRALLOC1_PFN_DUMP dump;
+ GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+ GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+ GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+ GRALLOC1_PFN_SET_FORMAT setFormat;
+ GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+ GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+ GRALLOC1_PFN_ALLOCATE allocate;
+ GRALLOC1_PFN_RELEASE release;
+ GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
+ GRALLOC1_PFN_GET_STRIDE getStride;
+ GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+ } mDispatch;
+};
+
+GrallocHal::GrallocHal(const hw_module_t* module)
+ : mDevice(nullptr), mDispatch()
+{
+ int status = gralloc1_open(module, &mDevice);
+ if (status) {
+ LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+ strerror(-status));
+ }
+
+ initCapabilities();
+ initDispatch();
+}
+
+GrallocHal::~GrallocHal()
+{
+ gralloc1_close(mDevice);
+}
+
+void GrallocHal::initCapabilities()
+{
+ uint32_t count;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<Capability> caps(count);
+ mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
+ std::underlying_type<Capability>::type*>(caps.data()));
+ caps.resize(count);
+
+ mCapabilities.insert(caps.cbegin(), caps.cend());
+}
+
+template<typename T>
+void GrallocHal::initDispatch(T& func, gralloc1_function_descriptor_t desc)
+{
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (!pfn) {
+ LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
+ }
+
+ func = reinterpret_cast<T>(pfn);
+}
+
+void GrallocHal::initDispatch()
+{
+ initDispatch(mDispatch.dump, GRALLOC1_FUNCTION_DUMP);
+ initDispatch(mDispatch.createDescriptor,
+ GRALLOC1_FUNCTION_CREATE_DESCRIPTOR);
+ initDispatch(mDispatch.destroyDescriptor,
+ GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR);
+ initDispatch(mDispatch.setDimensions, GRALLOC1_FUNCTION_SET_DIMENSIONS);
+ initDispatch(mDispatch.setFormat, GRALLOC1_FUNCTION_SET_FORMAT);
+ initDispatch(mDispatch.setConsumerUsage,
+ GRALLOC1_FUNCTION_SET_CONSUMER_USAGE);
+ initDispatch(mDispatch.setProducerUsage,
+ GRALLOC1_FUNCTION_SET_PRODUCER_USAGE);
+ initDispatch(mDispatch.allocate, GRALLOC1_FUNCTION_ALLOCATE);
+ initDispatch(mDispatch.release, GRALLOC1_FUNCTION_RELEASE);
+}
+
+bool GrallocHal::hasCapability(Capability capability) const
+{
+ return (mCapabilities.count(capability) > 0);
+}
+
+Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
+{
+ std::vector<Capability> caps(
+ mCapabilities.cbegin(), mCapabilities.cend());
+
+ hidl_vec<Capability> reply;
+ reply.setToExternal(caps.data(), caps.size());
+ hidl_cb(reply);
+
+ return Void();
+}
+
+Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
+{
+ uint32_t len = 0;
+ mDispatch.dump(mDevice, &len, nullptr);
+
+ std::vector<char> buf(len + 1);
+ mDispatch.dump(mDevice, &len, buf.data());
+ buf.resize(len + 1);
+ buf[len] = '\0';
+
+ hidl_string reply;
+ reply.setToExternal(buf.data(), len);
+ hidl_cb(reply);
+
+ return Void();
+}
+
+Return<void> GrallocHal::createDescriptor(
+ const BufferDescriptorInfo& descriptorInfo,
+ createDescriptor_cb hidl_cb)
+{
+ BufferDescriptor descriptor;
+ int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
+ if (err == GRALLOC1_ERROR_NONE) {
+ err = mDispatch.setDimensions(mDevice, descriptor,
+ descriptorInfo.width, descriptorInfo.height);
+ }
+ if (err == GRALLOC1_ERROR_NONE) {
+ err = mDispatch.setFormat(mDevice, descriptor,
+ static_cast<int32_t>(descriptorInfo.format));
+ }
+ if (err == GRALLOC1_ERROR_NONE) {
+ uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
+ if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
+ producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+ }
+ if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
+ producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+ }
+ err = mDispatch.setProducerUsage(mDevice, descriptor,
+ descriptorInfo.producerUsageMask);
+ }
+ if (err == GRALLOC1_ERROR_NONE) {
+ uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
+ if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
+ consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+ }
+ err = mDispatch.setConsumerUsage(mDevice, descriptor,
+ consumerUsageMask);
+ }
+
+ hidl_cb(static_cast<Error>(err), descriptor);
+
+ return Void();
+}
+
+Return<Error> GrallocHal::destroyDescriptor(
+ BufferDescriptor descriptor)
+{
+ int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
+ return static_cast<Error>(err);
+}
+
+Return<Error> GrallocHal::testAllocate(
+ const hidl_vec<BufferDescriptor>& descriptors)
+{
+ if (!hasCapability(Capability::TEST_ALLOCATE)) {
+ return Error::UNDEFINED;
+ }
+
+ int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
+ &descriptors[0], nullptr);
+ return static_cast<Error>(err);
+}
+
+Return<void> GrallocHal::allocate(
+ const hidl_vec<BufferDescriptor>& descriptors,
+ allocate_cb hidl_cb) {
+ std::vector<buffer_handle_t> buffers(descriptors.size());
+ int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
+ &descriptors[0], buffers.data());
+ if (err != GRALLOC1_ERROR_NONE && err != GRALLOC1_ERROR_NOT_SHARED) {
+ buffers.clear();
+ }
+
+ hidl_vec<Buffer> reply;
+ reply.setToExternal(
+ reinterpret_cast<Buffer*>(buffers.data()),
+ buffers.size());
+ hidl_cb(static_cast<Error>(err), reply);
+
+ return Void();
+}
+
+Return<Error> GrallocHal::free(Buffer buffer)
+{
+ buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(buffer);
+ int32_t err = mDispatch.release(mDevice, handle);
+ return static_cast<Error>(err);
+}
+
+Return<void> GrallocHal::exportHandle(BufferDescriptor /*descriptor*/,
+ Buffer buffer, exportHandle_cb hidl_cb)
+{
+ // do we want to validate?
+ buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(buffer);
+
+ hidl_cb(Error::NONE, handle);
+
+ return Void();
+}
+
+IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
+ const hw_module_t* module;
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ ALOGE("failed to get gralloc module");
+ return nullptr;
+ }
+
+ uint8_t major = (module->module_api_version >> 8) & 0xff;
+ if (major != 1) {
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
+ }
+
+ return new GrallocHal(module);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc.h b/graphics/allocator/2.0/default/Gralloc.h
new file mode 100644
index 0000000..c79eeaa
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.c b/graphics/allocator/2.0/default/gralloc1-adapter.c
new file mode 100644
index 0000000..724cd47
--- /dev/null
+++ b/graphics/allocator/2.0/default/gralloc1-adapter.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#define LOG_TAG "Gralloc1Adapter"
+
+#include <stdatomic.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pthread.h>
+
+#include <cutils/native_handle.h>
+#include <hardware/gralloc1.h>
+#include <sync/sync.h>
+#include <log/log.h>
+
+#include "gralloc1-adapter.h"
+
+struct gralloc1_adapter_module {
+ struct gralloc_module_t base;
+ struct gralloc1_adapter adapter;
+};
+
+struct gralloc1_adapter_device {
+ struct gralloc1_device base;
+
+ struct alloc_device_t* alloc_dev;
+
+ /* fixed size for thread safety */
+ char saved_dump[4096];
+ size_t saved_dump_size;
+};
+
+/* additional data associated with registered buffer_handle_t */
+struct gralloc1_adapter_buffer_data {
+ struct gralloc1_adapter_buffer_info info;
+
+ atomic_int refcount;
+ bool owned;
+};
+
+struct gralloc1_adapter_buffer_descriptor {
+ int width;
+ int height;
+ int format;
+ int producer_usage;
+ int consumer_usage;
+};
+
+static const struct gralloc1_adapter_module* gralloc1_adapter_module(
+ struct gralloc1_device* dev)
+{
+ return (const struct gralloc1_adapter_module*) dev->common.module;
+}
+
+static struct gralloc1_adapter_device* gralloc1_adapter_device(
+ struct gralloc1_device* dev)
+{
+ return (struct gralloc1_adapter_device*) dev;
+}
+
+static struct gralloc1_adapter_buffer_data* lookup_buffer_data(
+ struct gralloc1_device* dev, buffer_handle_t buffer)
+{
+ const struct gralloc1_adapter_module* mod = gralloc1_adapter_module(dev);
+ if (!mod->adapter.is_registered(&mod->base, buffer))
+ return NULL;
+
+ return mod->adapter.get_data(&mod->base, buffer);
+}
+
+static struct gralloc1_adapter_buffer_descriptor* lookup_buffer_descriptor(
+ struct gralloc1_device* dev, gralloc1_buffer_descriptor_t id)
+{
+ /* do we want to validate? */
+ return (struct gralloc1_adapter_buffer_descriptor*) ((uintptr_t) id);
+}
+
+static void device_dump(struct gralloc1_device* device,
+ uint32_t* outSize, char* outBuffer)
+{
+ struct gralloc1_adapter_device* dev = gralloc1_adapter_device(device);
+
+ if (outBuffer) {
+ uint32_t copy = (uint32_t) dev->saved_dump_size;
+ if (*outSize < copy) {
+ copy = *outSize;
+ } else {
+ *outSize = copy;
+ }
+
+ memcpy(outBuffer, dev->saved_dump, copy);
+ } else {
+ /* dump is optional and may not null-terminate */
+ if (dev->alloc_dev->dump) {
+ dev->alloc_dev->dump(dev->alloc_dev, dev->saved_dump,
+ sizeof(dev->saved_dump) - 1);
+ dev->saved_dump_size = strlen(dev->saved_dump);
+ }
+
+ *outSize = (uint32_t) dev->saved_dump_size;
+ }
+}
+
+static int32_t device_create_descriptor(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t* outDescriptor)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc;
+
+ desc = calloc(1, sizeof(*desc));
+ if (!desc) {
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+
+ *outDescriptor = (gralloc1_buffer_descriptor_t) (uintptr_t) desc;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_destroy_descriptor(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t descriptor)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptor);
+ if (!desc) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ free(desc);
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_set_consumer_usage(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t descriptor, uint64_t usage)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptor);
+ if (!desc) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ desc->consumer_usage = (int) usage;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_set_dimensions(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t descriptor,
+ uint32_t width, uint32_t height)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptor);
+ if (!desc) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ desc->width = (int) width;
+ desc->height = (int) height;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_set_format(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t descriptor, int32_t format)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptor);
+ if (!desc) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ desc->format = format;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_set_producer_usage(struct gralloc1_device* device,
+ gralloc1_buffer_descriptor_t descriptor, uint64_t usage)
+{
+ struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptor);
+ if (!desc) {
+ return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ }
+
+ desc->producer_usage = (int) usage;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_backing_store(struct gralloc1_device* device,
+ buffer_handle_t buffer, gralloc1_backing_store_t* outStore)
+{
+ /* we never share backing store */
+ *outStore = (gralloc1_backing_store_t) (uintptr_t) buffer;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_consumer_usage(struct gralloc1_device* device,
+ buffer_handle_t buffer, uint64_t* outUsage)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outUsage = data->info.usage;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_dimensions(struct gralloc1_device* device,
+ buffer_handle_t buffer, uint32_t* outWidth, uint32_t* outHeight)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outWidth = data->info.width;
+ *outHeight = data->info.height;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_format(struct gralloc1_device* device,
+ buffer_handle_t buffer, int32_t* outFormat)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outFormat = data->info.format;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_producer_usage(struct gralloc1_device* device,
+ buffer_handle_t buffer, uint64_t* outUsage)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outUsage = data->info.usage;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_stride(struct gralloc1_device* device,
+ buffer_handle_t buffer, uint32_t* outStride)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outStride = data->info.stride;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_allocate(struct gralloc1_device* device,
+ uint32_t numDescriptors,
+ const gralloc1_buffer_descriptor_t* descriptors,
+ buffer_handle_t* outBuffers)
+{
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ struct gralloc1_adapter_device* dev = gralloc1_adapter_device(device);
+ gralloc1_error_t err = GRALLOC1_ERROR_NONE;
+ uint32_t i;
+
+ for (i = 0; i < numDescriptors; i++) {
+ const struct gralloc1_adapter_buffer_descriptor* desc =
+ lookup_buffer_descriptor(device, descriptors[i]);
+ struct gralloc1_adapter_buffer_data* data;
+ buffer_handle_t buffer;
+ int dummy_stride;
+ int ret;
+
+ if (!desc) {
+ err = GRALLOC1_ERROR_BAD_DESCRIPTOR;
+ break;
+ }
+
+ data = calloc(1, sizeof(*data));
+ if (!data) {
+ err = GRALLOC1_ERROR_NO_RESOURCES;
+ break;
+ }
+
+ ret = dev->alloc_dev->alloc(dev->alloc_dev, desc->width, desc->height,
+ desc->format, desc->producer_usage | desc->consumer_usage,
+ &buffer, &dummy_stride);
+ if (ret) {
+ free(data);
+ err = GRALLOC1_ERROR_NO_RESOURCES;
+ break;
+ }
+
+ mod->adapter.get_info(&mod->base, buffer, &data->info);
+ data->refcount = 1;
+ data->owned = true;
+
+ mod->adapter.set_data(&mod->base, buffer, data);
+
+ outBuffers[i] = buffer;
+ }
+
+ if (err != GRALLOC1_ERROR_NONE) {
+ uint32_t j;
+ for (j = 0; j < i; j++) {
+ free(mod->adapter.get_data(&mod->base, outBuffers[i]));
+ dev->alloc_dev->free(dev->alloc_dev, outBuffers[i]);
+ }
+
+ return err;
+ }
+
+ return (numDescriptors > 1) ?
+ GRALLOC1_ERROR_NOT_SHARED : GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_retain(struct gralloc1_device* device,
+ buffer_handle_t buffer)
+{
+ static pthread_mutex_t register_mutex = PTHREAD_MUTEX_INITIALIZER;
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ struct gralloc1_adapter_buffer_data* data;
+
+ pthread_mutex_lock(®ister_mutex);
+
+ if (mod->adapter.is_registered(&mod->base, buffer)) {
+ data = mod->adapter.get_data(&mod->base, buffer);
+ data->refcount++;
+ } else {
+ int ret;
+
+ data = calloc(1, sizeof(*data));
+ if (!data) {
+ pthread_mutex_unlock(®ister_mutex);
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+
+ ret = mod->base.registerBuffer(&mod->base, buffer);
+ if (ret) {
+ pthread_mutex_unlock(®ister_mutex);
+ free(data);
+
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+
+ mod->adapter.get_info(&mod->base, buffer, &data->info);
+ data->refcount = 1;
+ data->owned = false;
+
+ mod->adapter.set_data(&mod->base, buffer, data);
+ }
+
+ pthread_mutex_unlock(®ister_mutex);
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_release(struct gralloc1_device* device,
+ buffer_handle_t buffer)
+{
+ struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ ALOGE("unable to release unregistered buffer %p", buffer);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ data->refcount--;
+ if (!data->refcount) {
+ if (data->owned) {
+ struct gralloc1_adapter_device* dev =
+ gralloc1_adapter_device(device);
+ dev->alloc_dev->free(dev->alloc_dev, buffer);
+ } else {
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ mod->base.unregisterBuffer(&mod->base, buffer);
+
+ native_handle_close(buffer);
+ native_handle_delete((native_handle_t*) buffer);
+ }
+
+ free(data);
+ }
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_get_num_flex_planes(struct gralloc1_device* device,
+ buffer_handle_t buffer, uint32_t* outNumPlanes)
+{
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ if (!data) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ *outNumPlanes = data->info.num_flex_planes;
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_lock(struct gralloc1_device* device,
+ buffer_handle_t buffer,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ const gralloc1_rect_t* accessRegion, void** outData,
+ int32_t acquireFence)
+{
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ const int usage = (int) (producerUsage | consumerUsage);
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ int ret;
+
+ if (!data) {
+ ALOGE("unable to lock unregistered buffer %p", buffer);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (mod->adapter.real_module_api_version >=
+ GRALLOC_MODULE_API_VERSION_0_3) {
+ ret = mod->base.lockAsync(&mod->base,
+ buffer, usage,
+ accessRegion->left,
+ accessRegion->top,
+ accessRegion->width,
+ accessRegion->height,
+ outData, acquireFence);
+ } else {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ }
+
+ ret = mod->base.lock(&mod->base,
+ buffer, usage,
+ accessRegion->left,
+ accessRegion->top,
+ accessRegion->width,
+ accessRegion->height,
+ outData);
+
+ if (acquireFence >= 0 && !ret) {
+ close(acquireFence);
+ }
+ }
+
+ return (ret) ? GRALLOC1_ERROR_NO_RESOURCES : GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_lock_flex(struct gralloc1_device* device,
+ buffer_handle_t buffer,
+ uint64_t producerUsage, uint64_t consumerUsage,
+ const gralloc1_rect_t* accessRegion,
+ struct android_flex_layout* outFlexLayout,
+ int32_t acquireFence)
+{
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ const int usage = (int) (producerUsage | consumerUsage);
+ const struct gralloc1_adapter_buffer_data* data =
+ lookup_buffer_data(device, buffer);
+ struct android_ycbcr ycbcr;
+ int ret;
+
+ if (!data) {
+ ALOGE("unable to lockFlex unregistered buffer %p", buffer);
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ if (outFlexLayout->num_planes < data->info.num_flex_planes) {
+ return GRALLOC1_ERROR_BAD_VALUE;
+ }
+
+ if (mod->adapter.real_module_api_version >=
+ GRALLOC_MODULE_API_VERSION_0_3 && mod->base.lockAsync_ycbcr) {
+ ret = mod->base.lockAsync_ycbcr(&mod->base,
+ buffer, usage,
+ accessRegion->left,
+ accessRegion->top,
+ accessRegion->width,
+ accessRegion->height,
+ &ycbcr, acquireFence);
+ } else if (mod->base.lock_ycbcr) {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ }
+
+ ret = mod->base.lock_ycbcr(&mod->base,
+ buffer, usage,
+ accessRegion->left,
+ accessRegion->top,
+ accessRegion->width,
+ accessRegion->height,
+ &ycbcr);
+
+ if (acquireFence >= 0 && !ret) {
+ close(acquireFence);
+ }
+ } else {
+ return GRALLOC1_ERROR_UNSUPPORTED;
+ }
+
+ if (ret) {
+ return GRALLOC1_ERROR_NO_RESOURCES;
+ }
+
+ mod->adapter.get_flexible_layout(&mod->base, buffer,
+ &ycbcr, outFlexLayout);
+
+ return GRALLOC1_ERROR_NONE;
+}
+
+static int32_t device_unlock(struct gralloc1_device* device,
+ buffer_handle_t buffer, int32_t* outReleaseFence)
+{
+ const struct gralloc1_adapter_module* mod =
+ gralloc1_adapter_module(device);
+ int ret;
+
+ if (mod->adapter.real_module_api_version >=
+ GRALLOC_MODULE_API_VERSION_0_3) {
+ ret = mod->base.unlockAsync(&mod->base, buffer, outReleaseFence);
+ } else {
+ ret = mod->base.unlock(&mod->base, buffer);
+ if (!ret) {
+ *outReleaseFence = -1;
+ }
+ }
+
+ return (ret) ? GRALLOC1_ERROR_BAD_HANDLE : GRALLOC1_ERROR_NONE;
+}
+
+static gralloc1_function_pointer_t device_get_function(
+ struct gralloc1_device* device, int32_t descriptor)
+{
+ switch ((gralloc1_function_descriptor_t) descriptor) {
+#define CASE(id, ptr) \
+ case GRALLOC1_FUNCTION_ ## id: \
+ return (gralloc1_function_pointer_t) device_ ## ptr
+ CASE(DUMP, dump);
+ CASE(CREATE_DESCRIPTOR, create_descriptor);
+ CASE(DESTROY_DESCRIPTOR, destroy_descriptor);
+ CASE(SET_CONSUMER_USAGE, set_consumer_usage);
+ CASE(SET_DIMENSIONS, set_dimensions);
+ CASE(SET_FORMAT, set_format);
+ CASE(SET_PRODUCER_USAGE, set_producer_usage);
+ CASE(GET_BACKING_STORE, get_backing_store);
+ CASE(GET_CONSUMER_USAGE, get_consumer_usage);
+ CASE(GET_DIMENSIONS, get_dimensions);
+ CASE(GET_FORMAT, get_format);
+ CASE(GET_PRODUCER_USAGE, get_producer_usage);
+ CASE(GET_STRIDE, get_stride);
+ CASE(ALLOCATE, allocate);
+ CASE(RETAIN, retain);
+ CASE(RELEASE, release);
+ CASE(GET_NUM_FLEX_PLANES, get_num_flex_planes);
+ CASE(LOCK, lock);
+ CASE(LOCK_FLEX, lock_flex);
+ CASE(UNLOCK, unlock);
+#undef CASE
+ default: return NULL;
+ }
+}
+
+static void device_get_capabilities(struct gralloc1_device* device,
+ uint32_t* outCount, int32_t* outCapabilities)
+{
+ *outCount = 0;
+}
+
+static int device_close(struct hw_device_t* device)
+{
+ struct gralloc1_adapter_device* dev =
+ (struct gralloc1_adapter_device*) device;
+ int ret;
+
+ ret = dev->alloc_dev->common.close(&dev->alloc_dev->common);
+ if (!ret) {
+ free(dev);
+ }
+
+ return ret;
+}
+
+int gralloc1_adapter_device_open(const struct hw_module_t* module,
+ const char* id, struct hw_device_t** device)
+{
+ const struct gralloc1_adapter_module* mod =
+ (const struct gralloc1_adapter_module*) module;
+ struct alloc_device_t* alloc_dev;
+ struct gralloc1_adapter_device* dev;
+ int ret;
+
+ if (strcmp(id, GRALLOC_HARDWARE_MODULE_ID) != 0) {
+ ALOGE("unknown gralloc1 device id: %s", id);
+ return -EINVAL;
+ }
+
+ ret = module->methods->open(module, GRALLOC_HARDWARE_GPU0,
+ (struct hw_device_t**) &alloc_dev);
+ if (ret) {
+ return ret;
+ }
+
+ dev = malloc(sizeof(*dev));
+ if (!dev) {
+ alloc_dev->common.close(&alloc_dev->common);
+ return -ENOMEM;
+ }
+
+ *dev = (struct gralloc1_adapter_device) {
+ .base = {
+ .common = {
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = HARDWARE_DEVICE_API_VERSION(0, 0),
+ .module = (struct hw_module_t*) mod,
+ .close = device_close,
+ },
+ .getCapabilities = device_get_capabilities,
+ .getFunction = device_get_function,
+ },
+ .alloc_dev = alloc_dev,
+ };
+
+ *device = (struct hw_device_t*) dev;
+
+ return 0;
+}
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.h b/graphics/allocator/2.0/default/gralloc1-adapter.h
new file mode 100644
index 0000000..f48cd9e
--- /dev/null
+++ b/graphics/allocator/2.0/default/gralloc1-adapter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.
+ */
+#ifndef ANDROID_HARDWARE_GRALLOC1_ADAPTER_H
+#define ANDROID_HARDWARE_GRALLOC1_ADAPTER_H
+
+#include <stdbool.h>
+#include <hardware/gralloc.h>
+
+__BEGIN_DECLS
+
+struct gralloc1_adapter_buffer_info {
+ int width;
+ int height;
+ int format;
+ int usage;
+
+ int stride;
+ uint32_t num_flex_planes;
+};
+
+/* This struct must be embedded in the HAL's HAL_MODULE_INFO_SYM and must
+ * follow gralloc_module_t immediately. */
+struct gralloc1_adapter {
+ uint16_t real_module_api_version;
+
+ /* Return true if the buffer is registered. A locally allocated buffer is
+ * always registered.
+ *
+ * This function is called frequently. It must be thread safe just like
+ * other functions are.
+ */
+ bool (*is_registered)(const struct gralloc_module_t* mod,
+ buffer_handle_t buffer);
+
+ /* Set the adapter data for a registered buffer. */
+ void (*set_data)(const struct gralloc_module_t* mod,
+ buffer_handle_t buffer, void* data);
+
+ /* Get the adapter data for a registered buffer. */
+ void* (*get_data)(const struct gralloc_module_t* mod,
+ buffer_handle_t buffer);
+
+ /* Get the buffer info, such as width, height, etc. */
+ void (*get_info)(const struct gralloc_module_t* mod,
+ buffer_handle_t buffer,
+ struct gralloc1_adapter_buffer_info* info);
+
+ /* Get the flexilble layout matching ycbcr. */
+ void (*get_flexible_layout)(const struct gralloc_module_t* mod,
+ buffer_handle_t buffer, const struct android_ycbcr* ycbcr,
+ struct android_flex_layout* layout);
+};
+
+int gralloc1_adapter_device_open(const struct hw_module_t* module,
+ const char* id, struct hw_device_t** device);
+
+__END_DECLS
+
+#endif /* ANDROID_HARDWARE_GRALLOC1_ADAPTER_H */
diff --git a/graphics/allocator/2.0/types.hal b/graphics/allocator/2.0/types.hal
new file mode 100644
index 0000000..23b7345
--- /dev/null
+++ b/graphics/allocator/2.0/types.hal
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.hardware.graphics.allocator@2.0;
+
+enum Error : int32_t {
+ NONE = 0, /* no error */
+ BAD_DESCRIPTOR = 1, /* invalid BufferDescriptor */
+ BAD_BUFFER = 2, /* invalid Buffer */
+ BAD_VALUE = 3, /* invalid width, height, etc. */
+ NOT_SHARED = 4, /* buffers not sharing backing store */
+ NO_RESOURCES = 5, /* temporary failure due to resource contention */
+ UNDEFINED = 6, /* an operation has no defined meaning */
+ UNSUPPORTED = 7, /* permanent failure */
+};
+
+enum ProducerUsage : uint64_t {
+ /* bit 0 is reserved */
+
+ /* buffer will be read by CPU occasionally */
+ CPU_READ = 1ULL << 1,
+ /* buffer will be read by CPU frequently */
+ CPU_READ_OFTEN = 1ULL << 2,
+
+ /* bit 3 is reserved */
+ /* bit 4 is reserved */
+
+ /* buffer will be written by CPU occasionally */
+ CPU_WRITE = 1ULL << 5,
+ /* buffer will be written by CPU frequently */
+ CPU_WRITE_OFTEN = 1ULL << 6,
+
+ /* bit 7 is reserved */
+ /* bit 8 is reserved */
+
+ /* buffer will be used as a GPU render target */
+ GPU_RENDER_TARGET = 1ULL << 9,
+
+ /* bit 10 is reserved */
+ /* bit 11 is reserved */
+ /* bit 12 is reserved */
+ /* bit 13 is reserved */
+
+ /*
+ * Buffer is allocated with hardware-level protection against copying the
+ * contents (or information derived from the contents) into unprotected
+ * memory.
+ */
+ PROTECTED = 1ULL << 14,
+
+ /* bit 15 is reserved */
+ /* bit 16 is reserved */
+
+ /* buffer will be used as a camera HAL output */
+ CAMERA = 1ULL << 17,
+
+ /* bit 18 is reserved */
+ /* bit 19 is reserved */
+ /* bit 20 is reserved */
+ /* bit 21 is reserved */
+
+ /* buffer will be used as a video decoder output */
+ VIDEO_DECODER = 1ULL << 22,
+
+ /* bits 23-27 are reserved for future versions */
+ /* bits 28-31 are reserved for vendor extensions */
+
+ /* bits 32-47 are reserved for future versions */
+ /* bits 48-63 are reserved for vendor extensions */
+};
+
+enum ConsumerUsage : uint64_t {
+ /* bit 0 is reserved */
+
+ /* buffer will be read by CPU occasionally */
+ CPU_READ = 1ULL << 1,
+ /* buffer will be read by CPU frequently */
+ CPU_READ_OFTEN = 1ULL << 2,
+
+ /* bit 3 is reserved */
+ /* bit 4 is reserved */
+ /* bit 5 is reserved */
+ /* bit 6 is reserved */
+ /* bit 7 is reserved */
+
+ /* buffer will be used as a GPU texture */
+ GPU_TEXTURE = 1ULL << 8,
+
+ /* bit 9 is reserved */
+ /* bit 10 is reserved */
+
+ /* buffer will be used by hwcomposer HAL */
+ HWCOMPOSER = 1ULL << 11,
+ /* buffer will be as a hwcomposer HAL client target */
+ CLIENT_TARGET = 1ULL << 12,
+
+ /* bit 13 is reserved */
+ /* bit 14 is reserved */
+
+ /* buffer will be used as a hwcomposer HAL cursor */
+ CURSOR = 1ULL << 15,
+
+ /* buffer will be used as a video encoder input */
+ VIDEO_ENCODER = 1ULL << 16,
+
+ /* bit 17 is reserved */
+
+ /* buffer will be used as a camera HAL input */
+ CAMERA = 1ULL << 18,
+
+ /* bit 19 is reserved */
+
+ /* buffer will be used as a renderscript allocation */
+ RENDERSCRIPT = 1ULL << 20,
+
+ /* bit 21 is reserved */
+ /* bit 22 is reserved */
+
+ /* bits 23-27 are reserved for future versions */
+ /* bits 28-31 are reserved for vendor extensions */
+
+ /* bits 32-47 are reserved for future versions */
+ /* bits 48-63 are reserved for vendor extensions */
+};
+
+/*
+ * Copied from android_pixel_format_t.
+ *
+ * TODO(olv) copy comments as well and have android_pixel_format_t generated
+ */
+@export(name="android_pixel_format", value_prefix="HAL_PIXEL_FORMAT_")
+enum PixelFormat : int32_t {
+ RGBA_8888 = 1,
+ RGBX_8888 = 2,
+ RGB_888 = 3,
+ RGB_565 = 4,
+ BGRA_8888 = 5,
+ YV12 = 0x32315659,
+ Y8 = 0x20203859,
+ Y16 = 0x20363159,
+ RAW16 = 0x20,
+ RAW10 = 0x25,
+ RAW12 = 0x26,
+ RAW_OPAQUE = 0x24,
+ BLOB = 0x21,
+ IMPLEMENTATION_DEFINED = 0x22,
+ YCbCr_420_888 = 0x23,
+ YCbCr_422_888 = 0x27,
+ YCbCr_444_888 = 0x28,
+ FLEX_RGB_888 = 0x29,
+ FLEX_RGBA_8888 = 0x2A,
+ YCbCr_422_SP = 0x10,
+ YCrCb_420_SP = 0x11,
+ YCbCr_422_I = 0x14,
+};
+
+typedef uint64_t BufferDescriptor;
+typedef uint64_t Buffer;
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
new file mode 100644
index 0000000..3718503
--- /dev/null
+++ b/graphics/mapper/2.0/Android.bp
@@ -0,0 +1,15 @@
+genrule {
+ name: "android.hardware.graphics.mapper@2.0_genc++_headers",
+ cmd: "cp $in $genDir/android/hardware/graphics/mapper/2.0",
+ srcs: ["IMapper.h", "types.h"],
+ out: [
+ "android/hardware/graphics/mapper/2.0/IMapper.h",
+ "android/hardware/graphics/mapper/2.0/types.h",
+ ],
+}
+
+cc_library_static {
+ name: "android.hardware.graphics.mapper@2.0",
+ generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
+ export_generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
+}
diff --git a/graphics/mapper/2.0/IMapper.h b/graphics/mapper/2.0/IMapper.h
new file mode 100644
index 0000000..23faa80
--- /dev/null
+++ b/graphics/mapper/2.0/IMapper.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_IMAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_IMAPPER_H
+
+#include <type_traits>
+
+#include <android/hardware/graphics/mapper/2.0/types.h>
+
+extern "C" {
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+
+struct Device {
+ struct Rect {
+ int32_t left;
+ int32_t top;
+ int32_t width;
+ int32_t height;
+ };
+ static_assert(std::is_pod<Rect>::value, "Device::Rect is not POD");
+
+ /*
+ * Create a mapper device.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * NOT_SUPPORTED when creation will never succeed.
+ * BAD_RESOURCES when creation failed at this time.
+ * @return device is the newly created mapper device.
+ */
+ typedef Error (*createDevice)(Device** outDevice);
+
+ /*
+ * Destroy a mapper device.
+ *
+ * @return error is always NONE.
+ * @param device is the mapper device to destroy.
+ */
+ typedef Error (*destroyDevice)(Device* device);
+
+ /*
+ * Adds a reference to the given buffer handle.
+ *
+ * A buffer handle received from a remote process or exported by
+ * IAllocator::exportHandle is unknown to this client-side library. There
+ * is also no guarantee that the buffer's backing store will stay alive.
+ * This function must be called at least once in both cases to intrdouce
+ * the buffer handle to this client-side library and to secure the backing
+ * store. It may also be called more than once to increase the reference
+ * count if two components in the same process want to interact with the
+ * buffer independently.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer to which a reference must be added.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid
+ * NO_RESOURCES when it is not possible to add a
+ * reference to this buffer at this time
+ */
+ typedef Error (*retain)(Device* device,
+ const native_handle_t* bufferHandle);
+
+ /*
+ * Removes a reference from the given buffer buffer.
+ *
+ * If no references remain, the buffer handle should be freed with
+ * native_handle_close/native_handle_delete. When the last buffer handle
+ * referring to a particular backing store is freed, that backing store
+ * should also be freed.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which a reference must be
+ * removed.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ */
+ typedef Error (*release)(Device* device,
+ const native_handle_t* bufferHandle);
+
+ /*
+ * Gets the width and height of the buffer in pixels.
+ *
+ * See IAllocator::BufferDescriptorInfo for more information.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get the dimensions.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return width is the width of the buffer in pixels.
+ * @return height is the height of the buffer in pixels.
+ */
+ typedef Error (*getDimensions)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint32_t* outWidth,
+ uint32_t* outHeight);
+
+ /*
+ * Gets the format of the buffer.
+ *
+ * See IAllocator::BufferDescriptorInfo for more information.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get format.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return format is the format of the buffer.
+ */
+ typedef Error (*getFormat)(Device* device,
+ const native_handle_t* bufferHandle,
+ PixelFormat* outFormat);
+
+ /*
+ * Gets the producer usage flags which were used to allocate this buffer.
+ *
+ * See IAllocator::BufferDescriptorInfo for more information.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get the producer usage
+ * flags.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return usageMask contains the producer usage flags of the buffer.
+ */
+ typedef Error (*getProducerUsageMask)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask);
+
+ /*
+ * Gets the consumer usage flags which were used to allocate this buffer.
+ *
+ * See IAllocator::BufferDescriptorInfo for more information.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get the consumer usage
+ * flags.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return usageMask contains the consumer usage flags of the buffer.
+ */
+ typedef Error (*getConsumerUsageMask)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask);
+
+ /*
+ * Gets a value that uniquely identifies the backing store of the given
+ * buffer.
+ *
+ * Buffers which share a backing store should return the same value from
+ * this function. If the buffer is present in more than one process, the
+ * backing store value for that buffer is not required to be the same in
+ * every process.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get the backing store
+ * identifier.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return store is the backing store identifier for this buffer.
+ */
+ typedef Error (*getBackingStore)(Device* device,
+ const native_handle_t* bufferHandle,
+ BackingStore* outStore);
+
+ /*
+ * Gets the stride of the buffer in pixels.
+ *
+ * The stride is the offset in pixel-sized elements between the same
+ * column in two adjacent rows of pixels. This may not be equal to the
+ * width of the buffer.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer from which to get the stride.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * UNDEFINED when the notion of a stride is not
+ * meaningful for the buffer format.
+ * @return store is the stride in pixels.
+ */
+ typedef Error (*getStride)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint32_t* outStride);
+
+ /*
+ * Returns the number of flex layout planes which are needed to represent
+ * the given buffer. This may be used to efficiently allocate only as many
+ * plane structures as necessary before calling into lockFlex.
+ *
+ * If the given buffer cannot be locked as a flex format, this function
+ * may return UNSUPPORTED (as lockFlex would).
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer for which the number of planes should
+ * be queried.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * UNSUPPORTED when the buffer's format cannot be
+ * represented in a flex layout.
+ * @return numPlanes is the number of flex planes required to describe the
+ * given buffer.
+ */
+ typedef Error (*getNumFlexPlanes)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint32_t* outNumPlanes);
+
+ /*
+ * Locks the given buffer for the specified CPU usage.
+ *
+ * Exactly one of producerUsageMask and consumerUsageMask must be 0. The
+ * usage which is not 0 must be one of the *Usage::CPU* values, as
+ * applicable. Locking a buffer for a non-CPU usage is not supported.
+ *
+ * Locking the same buffer simultaneously from multiple threads is
+ * permitted, but if any of the threads attempt to lock the buffer for
+ * writing, the behavior is undefined, except that it must not cause
+ * process termination or block the client indefinitely. Leaving the
+ * buffer content in an indeterminate state or returning an error are both
+ * acceptable.
+ *
+ * The client must not modify the content of the buffer outside of
+ * accessRegion, and the device need not guarantee that content outside of
+ * accessRegion is valid for reading. The result of reading or writing
+ * outside of accessRegion is undefined, except that it must not cause
+ * process termination.
+ *
+ * data will be filled with a pointer to the locked buffer memory. This
+ * address will represent the top-left corner of the entire buffer, even
+ * if accessRegion does not begin at the top-left corner.
+ *
+ * acquireFence is a file descriptor referring to a acquire sync fence
+ * object, which will be signaled when it is safe for the device to access
+ * the contents of the buffer (prior to locking). If it is already safe to
+ * access the buffer contents, -1 may be passed instead.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer to lock.
+ * @param producerUsageMask contains the producer usage flags to request;
+ * either this or consumerUsagemask must be 0, and the other must
+ * be a CPU usage.
+ * @param consumerUsageMask contains the consumer usage flags to request;
+ * either this or producerUsageMask must be 0, and the other must
+ * be a CPU usage.
+ * @param accessRegion is the portion of the buffer that the client
+ * intends to access.
+ * @param acquireFence is a sync fence file descriptor as described above.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * BAD_VALUE when neither or both of producerUsageMask
+ * and consumerUsageMask were 0, or the usage
+ * which was not 0 was not a CPU usage.
+ * NO_RESOURCES when the buffer cannot be locked at this
+ * time, but locking may succeed at a future
+ * time.
+ * UNSUPPORTED when the buffer cannot be locked with the
+ * given usage, and any future attempts at
+ * locking will also fail.
+ * @return data will be filled with a CPU-accessible pointer to the buffer
+ * data.
+ */
+ typedef Error (*lock)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask,
+ uint64_t consumerUsageMask,
+ const Rect* accessRegion,
+ int32_t acquireFence,
+ void** outData);
+
+ /*
+ * This is largely the same as lock(), except that instead of returning a
+ * pointer directly to the buffer data, it returns an FlexLayout struct
+ * describing how to access the data planes.
+ *
+ * This function must work on buffers with PixelFormat::YCbCr_*_888 if
+ * supported by the device, as well as with any other formats requested by
+ * multimedia codecs when they are configured with a
+ * flexible-YUV-compatible color format.
+ *
+ * This function may also be called on buffers of other formats, including
+ * non-YUV formats, but if the buffer format is not compatible with a
+ * flexible representation, it may return UNSUPPORTED.
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer to lock.
+ * @param producerUsageMask contains the producer usage flags to request;
+ * either this or consumerUsagemask must be 0, and the other must
+ * be a CPU usage.
+ * @param consumerUsageMask contains the consumer usage flags to request;
+ * either this or producerUsageMask must be 0, and the other must
+ * be a CPU usage.
+ * @param accessRegion is the portion of the buffer that the client
+ * intends to access.
+ * @param acquireFence is a sync fence file descriptor as described in
+ * lock().
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * BAD_VALUE when neither or both of producerUsageMask
+ * and consumerUsageMask were 0, or the usage
+ * which was not 0 was not a CPU usage.
+ * NO_RESOURCES when the buffer cannot be locked at this
+ * time, but locking may succeed at a future
+ * time.
+ * UNSUPPORTED when the buffer cannot be locked with the
+ * given usage, and any future attempts at
+ * locking will also fail.
+ * @return flexLayout will be filled with the description of the planes in
+ * the buffer.
+ */
+ typedef Error (*lockFlex)(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask,
+ uint64_t consumerUsageMask,
+ const Rect* accessRegion,
+ int32_t acquireFence,
+ FlexLayout* outFlexLayout);
+
+ /*
+ * This function indicates to the device that the client will be done with
+ * the buffer when releaseFence signals.
+ *
+ * releaseFence will be filled with a file descriptor referring to a
+ * release sync fence object, which will be signaled when it is safe to
+ * access the contents of the buffer (after the buffer has been unlocked).
+ * If it is already safe to access the buffer contents, then -1 may be
+ * returned instead.
+ *
+ * This function is used to unlock both buffers locked by lock() and those
+ * locked by lockFlex().
+ *
+ * @param device is the mapper device.
+ * @param bufferHandle is the buffer to unlock.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer handle is invalid.
+ * @return releaseFence is a sync fence file descriptor as described
+ * above.
+ */
+ typedef Error (*unlock)(Device* device,
+ const native_handle_t* bufferHandle,
+ int32_t* outReleaseFence);
+};
+static_assert(std::is_pod<Device>::value, "Device is not POD");
+
+struct IMapper {
+ Device::createDevice createDevice;
+ Device::destroyDevice destroyDevice;
+
+ Device::retain retain;
+ Device::release release;
+ Device::getDimensions getDimensions;
+ Device::getFormat getFormat;
+ Device::getProducerUsageMask getProducerUsageMask;
+ Device::getConsumerUsageMask getConsumerUsageMask;
+ Device::getBackingStore getBackingStore;
+ Device::getStride getStride;
+ Device::getNumFlexPlanes getNumFlexPlanes;
+ Device::lock lock;
+ Device::lockFlex lockFlex;
+ Device::unlock unlock;
+};
+static_assert(std::is_pod<IMapper>::value, "IMapper is not POD");
+
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+const void* HALLIB_FETCH_Interface(const char* name);
+
+} // extern "C"
+
+#endif /* ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_IMAPPER_H */
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
new file mode 100644
index 0000000..b738ae8
--- /dev/null
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2016 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_library_shared {
+ name: "android.hardware.graphics.mapper.hallib",
+ relative_install_path: "hw",
+ srcs: ["GrallocMapper.cpp"],
+ cppflags: ["-Wall", "-Wextra"],
+ static_libs: ["android.hardware.graphics.mapper@2.0"],
+ shared_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "libhardware",
+ "libhidl",
+ "libhwbinder",
+ "liblog",
+ ],
+}
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
new file mode 100644
index 0000000..eeca5c7
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#define LOG_TAG "GrallocMapperPassthrough"
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class GrallocDevice : public Device {
+public:
+ GrallocDevice();
+ ~GrallocDevice();
+
+ // IMapper interface
+ Error retain(const native_handle_t* bufferHandle);
+ Error release(const native_handle_t* bufferHandle);
+ Error getDimensions(const native_handle_t* bufferHandle,
+ uint32_t* outWidth, uint32_t* outHeight);
+ Error getFormat(const native_handle_t* bufferHandle,
+ PixelFormat* outFormat);
+ Error getProducerUsageMask(const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask);
+ Error getConsumerUsageMask(const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask);
+ Error getBackingStore(const native_handle_t* bufferHandle,
+ BackingStore* outStore);
+ Error getStride(const native_handle_t* bufferHandle, uint32_t* outStride);
+ Error getNumFlexPlanes(const native_handle_t* bufferHandle,
+ uint32_t* outNumPlanes);
+ Error lock(const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Rect* accessRegion, int32_t acquireFence, void** outData);
+ Error lockFlex(const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Rect* accessRegion, int32_t acquireFence,
+ FlexLayout* outFlexLayout);
+ Error unlock(const native_handle_t* bufferHandle,
+ int32_t* outReleaseFence);
+
+private:
+ void initDispatch();
+
+ gralloc1_device_t* mDevice;
+
+ struct {
+ GRALLOC1_PFN_RETAIN retain;
+ GRALLOC1_PFN_RELEASE release;
+ GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
+ GRALLOC1_PFN_GET_FORMAT getFormat;
+ GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
+ GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
+ GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
+ GRALLOC1_PFN_GET_STRIDE getStride;
+ GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+ GRALLOC1_PFN_LOCK lock;
+ GRALLOC1_PFN_LOCK_FLEX lockFlex;
+ GRALLOC1_PFN_UNLOCK unlock;
+ } mDispatch;
+};
+
+GrallocDevice::GrallocDevice()
+{
+ const hw_module_t* module;
+ int status = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (status) {
+ LOG_ALWAYS_FATAL("failed to get gralloc module");
+ }
+
+ uint8_t major = (module->module_api_version >> 8) & 0xff;
+ if (major != 1) {
+ LOG_ALWAYS_FATAL("unknown gralloc module major version %d", major);
+ }
+
+ status = gralloc1_open(module, &mDevice);
+ if (status) {
+ LOG_ALWAYS_FATAL("failed to open gralloc1 device");
+ }
+
+ initDispatch();
+}
+
+GrallocDevice::~GrallocDevice()
+{
+ gralloc1_close(mDevice);
+}
+
+void GrallocDevice::initDispatch()
+{
+#define CHECK_FUNC(func, desc) do { \
+ mDispatch.func = reinterpret_cast<decltype(mDispatch.func)>( \
+ mDevice->getFunction(mDevice, desc)); \
+ if (!mDispatch.func) { \
+ LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc); \
+ } \
+} while (0)
+
+ CHECK_FUNC(retain, GRALLOC1_FUNCTION_RETAIN);
+ CHECK_FUNC(release, GRALLOC1_FUNCTION_RELEASE);
+ CHECK_FUNC(getDimensions, GRALLOC1_FUNCTION_GET_DIMENSIONS);
+ CHECK_FUNC(getFormat, GRALLOC1_FUNCTION_GET_FORMAT);
+ CHECK_FUNC(getProducerUsage, GRALLOC1_FUNCTION_GET_PRODUCER_USAGE);
+ CHECK_FUNC(getConsumerUsage, GRALLOC1_FUNCTION_GET_CONSUMER_USAGE);
+ CHECK_FUNC(getBackingStore, GRALLOC1_FUNCTION_GET_BACKING_STORE);
+ CHECK_FUNC(getStride, GRALLOC1_FUNCTION_GET_STRIDE);
+ CHECK_FUNC(getNumFlexPlanes, GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES);
+ CHECK_FUNC(lock, GRALLOC1_FUNCTION_LOCK);
+ CHECK_FUNC(lockFlex, GRALLOC1_FUNCTION_LOCK_FLEX);
+ CHECK_FUNC(unlock, GRALLOC1_FUNCTION_UNLOCK);
+
+#undef CHECK_FUNC
+}
+
+Error GrallocDevice::retain(const native_handle_t* bufferHandle)
+{
+ int32_t error = mDispatch.retain(mDevice, bufferHandle);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::release(const native_handle_t* bufferHandle)
+{
+ int32_t error = mDispatch.release(mDevice, bufferHandle);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getDimensions(const native_handle_t* bufferHandle,
+ uint32_t* outWidth, uint32_t* outHeight)
+{
+ int32_t error = mDispatch.getDimensions(mDevice, bufferHandle,
+ outWidth, outHeight);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getFormat(const native_handle_t* bufferHandle,
+ PixelFormat* outFormat)
+{
+ int32_t error = mDispatch.getFormat(mDevice, bufferHandle,
+ reinterpret_cast<int32_t*>(outFormat));
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getProducerUsageMask(const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask)
+{
+ int32_t error = mDispatch.getProducerUsage(mDevice, bufferHandle,
+ outUsageMask);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getConsumerUsageMask(const native_handle_t* bufferHandle,
+ uint64_t* outUsageMask)
+{
+ int32_t error = mDispatch.getConsumerUsage(mDevice, bufferHandle,
+ outUsageMask);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getBackingStore(const native_handle_t* bufferHandle,
+ BackingStore* outStore)
+{
+ int32_t error = mDispatch.getBackingStore(mDevice, bufferHandle,
+ outStore);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getStride(const native_handle_t* bufferHandle,
+ uint32_t* outStride)
+{
+ int32_t error = mDispatch.getStride(mDevice, bufferHandle, outStride);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::getNumFlexPlanes(const native_handle_t* bufferHandle,
+ uint32_t* outNumPlanes)
+{
+ int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle,
+ outNumPlanes);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::lock(const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Rect* accessRegion, int32_t acquireFence,
+ void** outData)
+{
+ int32_t error = mDispatch.lock(mDevice, bufferHandle,
+ producerUsageMask, consumerUsageMask,
+ reinterpret_cast<const gralloc1_rect_t*>(accessRegion),
+ outData, acquireFence);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::lockFlex(const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Rect* accessRegion, int32_t acquireFence,
+ FlexLayout* outFlexLayout)
+{
+ int32_t error = mDispatch.lockFlex(mDevice, bufferHandle,
+ producerUsageMask, consumerUsageMask,
+ reinterpret_cast<const gralloc1_rect_t*>(accessRegion),
+ reinterpret_cast<android_flex_layout_t*>(outFlexLayout),
+ acquireFence);
+ return static_cast<Error>(error);
+}
+
+Error GrallocDevice::unlock(const native_handle_t* bufferHandle,
+ int32_t* outReleaseFence)
+{
+ int32_t error = mDispatch.unlock(mDevice, bufferHandle, outReleaseFence);
+ return static_cast<Error>(error);
+}
+
+class GrallocMapper : public IMapper {
+public:
+ GrallocMapper() : IMapper{
+ .createDevice = createDevice,
+ .destroyDevice = destroyDevice,
+ .retain = retain,
+ .release = release,
+ .getDimensions = getDimensions,
+ .getFormat = getFormat,
+ .getProducerUsageMask = getProducerUsageMask,
+ .getConsumerUsageMask = getConsumerUsageMask,
+ .getBackingStore = getBackingStore,
+ .getStride = getStride,
+ .getNumFlexPlanes = getNumFlexPlanes,
+ .lock = lock,
+ .lockFlex = lockFlex,
+ .unlock = unlock,
+ } {}
+
+ const IMapper* getInterface() const
+ {
+ return static_cast<const IMapper*>(this);
+ }
+
+private:
+ static GrallocDevice* cast(Device* device)
+ {
+ return reinterpret_cast<GrallocDevice*>(device);
+ }
+
+ static Error createDevice(Device** outDevice)
+ {
+ *outDevice = new GrallocDevice;
+ return Error::NONE;
+ }
+
+ static Error destroyDevice(Device* device)
+ {
+ delete cast(device);
+ return Error::NONE;
+ }
+
+ static Error retain(Device* device,
+ const native_handle_t* bufferHandle)
+ {
+ return cast(device)->retain(bufferHandle);
+ }
+
+ static Error release(Device* device,
+ const native_handle_t* bufferHandle)
+ {
+ return cast(device)->release(bufferHandle);
+ }
+
+ static Error getDimensions(Device* device,
+ const native_handle_t* bufferHandle,
+ uint32_t* outWidth, uint32_t* outHeight)
+ {
+ return cast(device)->getDimensions(bufferHandle, outWidth, outHeight);
+ }
+
+ static Error getFormat(Device* device,
+ const native_handle_t* bufferHandle, PixelFormat* outFormat)
+ {
+ return cast(device)->getFormat(bufferHandle, outFormat);
+ }
+
+ static Error getProducerUsageMask(Device* device,
+ const native_handle_t* bufferHandle, uint64_t* outUsageMask)
+ {
+ return cast(device)->getProducerUsageMask(bufferHandle, outUsageMask);
+ }
+
+ static Error getConsumerUsageMask(Device* device,
+ const native_handle_t* bufferHandle, uint64_t* outUsageMask)
+ {
+ return cast(device)->getConsumerUsageMask(bufferHandle, outUsageMask);
+ }
+
+ static Error getBackingStore(Device* device,
+ const native_handle_t* bufferHandle, BackingStore* outStore)
+ {
+ return cast(device)->getBackingStore(bufferHandle, outStore);
+ }
+
+ static Error getStride(Device* device,
+ const native_handle_t* bufferHandle, uint32_t* outStride)
+ {
+ return cast(device)->getStride(bufferHandle, outStride);
+ }
+
+ static Error getNumFlexPlanes(Device* device,
+ const native_handle_t* bufferHandle, uint32_t* outNumPlanes)
+ {
+ return cast(device)->getNumFlexPlanes(bufferHandle, outNumPlanes);
+ }
+
+ static Error lock(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Device::Rect* accessRegion, int32_t acquireFence,
+ void** outData)
+ {
+ return cast(device)->lock(bufferHandle,
+ producerUsageMask, consumerUsageMask,
+ accessRegion, acquireFence, outData);
+ }
+
+ static Error lockFlex(Device* device,
+ const native_handle_t* bufferHandle,
+ uint64_t producerUsageMask, uint64_t consumerUsageMask,
+ const Device::Rect* accessRegion, int32_t acquireFence,
+ FlexLayout* outFlexLayout)
+ {
+ return cast(device)->lockFlex(bufferHandle,
+ producerUsageMask, consumerUsageMask,
+ accessRegion, acquireFence, outFlexLayout);
+ }
+
+ static Error unlock(Device* device,
+ const native_handle_t* bufferHandle, int32_t* outReleaseFence)
+ {
+ return cast(device)->unlock(bufferHandle, outReleaseFence);
+ }
+};
+
+extern "C" const void* HALLIB_FETCH_Interface(const char* name)
+{
+ if (strcmp(name, "android.hardware.graphics.mapper@2.0::IMapper") == 0) {
+ static GrallocMapper sGrallocMapper;
+ return sGrallocMapper.getInterface();
+ }
+
+ return nullptr;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/types.h b/graphics/mapper/2.0/types.h
new file mode 100644
index 0000000..63a6b16
--- /dev/null
+++ b/graphics/mapper/2.0/types.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_TYPES_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_TYPES_H
+
+#include <type_traits>
+
+#include <android/hardware/graphics/allocator/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+
+using android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::allocator::V2_0::PixelFormat;
+using android::hardware::graphics::allocator::V2_0::ProducerUsage;
+using android::hardware::graphics::allocator::V2_0::ConsumerUsage;
+
+/*
+ * Structures for describing flexible YUVA/RGBA formats for consumption by
+ * applications. Such flexible formats contain a plane for each component
+ * (e.g. red, green, blue), where each plane is laid out in a grid-like
+ * pattern occupying unique byte addresses and with consistent byte offsets
+ * between neighboring pixels.
+ *
+ * The FlexLayout structure is used with any pixel format that can be
+ * represented by it, such as:
+ *
+ * - PixelFormat::YCbCr_*_888
+ * - PixelFormat::FLEX_RGB*_888
+ * - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888
+ * - PixelFormat::YV12,Y8,Y16,YCbCr_422_SP/I,YCrCb_420_SP
+ * - even implementation defined formats that can be represented by the
+ * structures
+ *
+ * Vertical increment (aka. row increment or stride) describes the distance in
+ * bytes from the first pixel of one row to the first pixel of the next row
+ * (below) for the component plane. This can be negative.
+ *
+ * Horizontal increment (aka. column or pixel increment) describes the
+ * distance in bytes from one pixel to the next pixel (to the right) on the
+ * same row for the component plane. This can be negative.
+ *
+ * Each plane can be subsampled either vertically or horizontally by a
+ * power-of-two factor.
+ *
+ * The bit-depth of each component can be arbitrary, as long as the pixels are
+ * laid out on whole bytes, in native byte-order, using the most significant
+ * bits of each unit.
+ */
+
+enum class FlexComponent : int32_t {
+ Y = 1 << 0, /* luma */
+ Cb = 1 << 1, /* chroma blue */
+ Cr = 1 << 2, /* chroma red */
+
+ R = 1 << 10, /* red */
+ G = 1 << 11, /* green */
+ B = 1 << 12, /* blue */
+
+ A = 1 << 30, /* alpha */
+};
+
+inline FlexComponent operator|(FlexComponent lhs, FlexComponent rhs)
+{
+ return static_cast<FlexComponent>(static_cast<int32_t>(lhs) |
+ static_cast<int32_t>(rhs));
+}
+
+inline FlexComponent& operator|=(FlexComponent &lhs, FlexComponent rhs)
+{
+ lhs = static_cast<FlexComponent>(static_cast<int32_t>(lhs) |
+ static_cast<int32_t>(rhs));
+ return lhs;
+}
+
+enum class FlexFormat : int32_t {
+ /* not a flexible format */
+ INVALID = 0x0,
+
+ Y = static_cast<int32_t>(FlexComponent::Y),
+ YCbCr = static_cast<int32_t>(FlexComponent::Y) |
+ static_cast<int32_t>(FlexComponent::Cb) |
+ static_cast<int32_t>(FlexComponent::Cr),
+ YCbCrA = static_cast<int32_t>(YCbCr) |
+ static_cast<int32_t>(FlexComponent::A),
+ RGB = static_cast<int32_t>(FlexComponent::R) |
+ static_cast<int32_t>(FlexComponent::G) |
+ static_cast<int32_t>(FlexComponent::B),
+ RGBA = static_cast<int32_t>(RGB) |
+ static_cast<int32_t>(FlexComponent::A),
+};
+
+struct FlexPlane {
+ /* pointer to the first byte of the top-left pixel of the plane. */
+ uint8_t *topLeft;
+
+ FlexComponent component;
+
+ /*
+ * bits allocated for the component in each pixel. Must be a positive
+ * multiple of 8.
+ */
+ int32_t bitsPerComponent;
+
+ /*
+ * number of the most significant bits used in the format for this
+ * component. Must be between 1 and bits_per_component, inclusive.
+ */
+ int32_t bitsUsed;
+
+ /* horizontal increment */
+ int32_t hIncrement;
+ /* vertical increment */
+ int32_t vIncrement;
+
+ /* horizontal subsampling. Must be a positive power of 2. */
+ int32_t hSubsampling;
+ /* vertical subsampling. Must be a positive power of 2. */
+ int32_t vSubsampling;
+};
+static_assert(std::is_pod<FlexPlane>::value, "FlexPlane is not POD");
+
+struct FlexLayout {
+ /* the kind of flexible format */
+ FlexFormat format;
+
+ /* number of planes; 0 for FLEX_FORMAT_INVALID */
+ uint32_t numPlanes;
+
+ /*
+ * a plane for each component; ordered in increasing component value order.
+ * E.g. FLEX_FORMAT_RGBA maps 0 -> R, 1 -> G, etc.
+ * Can be NULL for FLEX_FORMAT_INVALID
+ */
+ FlexPlane* planes;
+};
+static_assert(std::is_pod<FlexLayout>::value, "FlexLayout is not POD");
+
+typedef uint64_t BackingStore;
+
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif /* ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_TYPES_H */