diff --git a/Android.bp b/Android.bp index 7188e91c76..1d90fd1351 100644 --- a/Android.bp +++ b/Android.bp @@ -3,6 +3,10 @@ subdirs = [ "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 0000000000..f29c50be61 --- /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 0000000000..8accb82131 --- /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 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 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 descriptors) + generates (Error error, + vec 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 0000000000..9a247735d4 --- /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 0000000000..a7fc6c103b --- /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 +#include +#include + +#include + +#include +#include + +#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 getCapabilities(getCapabilities_cb hidl_cb) override; + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return createDescriptor(const BufferDescriptorInfo& descriptorInfo, + createDescriptor_cb hidl_cb) override; + Return destroyDescriptor(BufferDescriptor descriptor) override; + + Return testAllocate( + const hidl_vec& descriptors) override; + Return allocate(const hidl_vec& descriptors, + allocate_cb hidl_cb) override; + Return free(Buffer buffer) override; + + Return exportHandle(BufferDescriptor descriptor, + Buffer buffer, exportHandle_cb hidl_cb) override; + +private: + void initCapabilities(); + + template + void initDispatch(T& func, gralloc1_function_descriptor_t desc); + void initDispatch(); + + bool hasCapability(Capability capability) const; + + gralloc1_device_t* mDevice; + + std::unordered_set 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 caps(count); + mDevice->getCapabilities(mDevice, &count, reinterpret_cast< + std::underlying_type::type*>(caps.data())); + caps.resize(count); + + mCapabilities.insert(caps.cbegin(), caps.cend()); +} + +template +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(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 GrallocHal::getCapabilities(getCapabilities_cb hidl_cb) +{ + std::vector caps( + mCapabilities.cbegin(), mCapabilities.cend()); + + hidl_vec reply; + reply.setToExternal(caps.data(), caps.size()); + hidl_cb(reply); + + return Void(); +} + +Return GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) +{ + uint32_t len = 0; + mDispatch.dump(mDevice, &len, nullptr); + + std::vector 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 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(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(err), descriptor); + + return Void(); +} + +Return GrallocHal::destroyDescriptor( + BufferDescriptor descriptor) +{ + int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor); + return static_cast(err); +} + +Return GrallocHal::testAllocate( + const hidl_vec& descriptors) +{ + if (!hasCapability(Capability::TEST_ALLOCATE)) { + return Error::UNDEFINED; + } + + int32_t err = mDispatch.allocate(mDevice, descriptors.size(), + &descriptors[0], nullptr); + return static_cast(err); +} + +Return GrallocHal::allocate( + const hidl_vec& descriptors, + allocate_cb hidl_cb) { + std::vector 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 reply; + reply.setToExternal( + reinterpret_cast(buffers.data()), + buffers.size()); + hidl_cb(static_cast(err), reply); + + return Void(); +} + +Return GrallocHal::free(Buffer buffer) +{ + buffer_handle_t handle = reinterpret_cast(buffer); + int32_t err = mDispatch.release(mDevice, handle); + return static_cast(err); +} + +Return GrallocHal::exportHandle(BufferDescriptor /*descriptor*/, + Buffer buffer, exportHandle_cb hidl_cb) +{ + // do we want to validate? + buffer_handle_t handle = reinterpret_cast(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 0000000000..c79eeaa42b --- /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 + +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 0000000000..724cd47aab --- /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 +#include +#include + +#include + +#include +#include +#include +#include + +#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 0000000000..f48cd9e08d --- /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 +#include + +__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 0000000000..23b7345134 --- /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 0000000000..3718503584 --- /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 0000000000..23faa802f6 --- /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 + +#include + +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::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::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::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 0000000000..b738ae88ac --- /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 0000000000..eeca5c73ee --- /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 +#include +#include + +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( \ + 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 GrallocDevice::release(const native_handle_t* bufferHandle) +{ + int32_t error = mDispatch.release(mDevice, bufferHandle); + return static_cast(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 GrallocDevice::getFormat(const native_handle_t* bufferHandle, + PixelFormat* outFormat) +{ + int32_t error = mDispatch.getFormat(mDevice, bufferHandle, + reinterpret_cast(outFormat)); + return static_cast(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 GrallocDevice::getConsumerUsageMask(const native_handle_t* bufferHandle, + uint64_t* outUsageMask) +{ + int32_t error = mDispatch.getConsumerUsage(mDevice, bufferHandle, + outUsageMask); + return static_cast(error); +} + +Error GrallocDevice::getBackingStore(const native_handle_t* bufferHandle, + BackingStore* outStore) +{ + int32_t error = mDispatch.getBackingStore(mDevice, bufferHandle, + outStore); + return static_cast(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 GrallocDevice::getNumFlexPlanes(const native_handle_t* bufferHandle, + uint32_t* outNumPlanes) +{ + int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, + outNumPlanes); + return static_cast(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(accessRegion), + outData, acquireFence); + return static_cast(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(accessRegion), + reinterpret_cast(outFlexLayout), + acquireFence); + return static_cast(error); +} + +Error GrallocDevice::unlock(const native_handle_t* bufferHandle, + int32_t* outReleaseFence) +{ + int32_t error = mDispatch.unlock(mDevice, bufferHandle, outReleaseFence); + return static_cast(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(this); + } + +private: + static GrallocDevice* cast(Device* device) + { + return reinterpret_cast(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 0000000000..63a6b16b8c --- /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 + +#include + +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(static_cast(lhs) | + static_cast(rhs)); +} + +inline FlexComponent& operator|=(FlexComponent &lhs, FlexComponent rhs) +{ + lhs = static_cast(static_cast(lhs) | + static_cast(rhs)); + return lhs; +} + +enum class FlexFormat : int32_t { + /* not a flexible format */ + INVALID = 0x0, + + Y = static_cast(FlexComponent::Y), + YCbCr = static_cast(FlexComponent::Y) | + static_cast(FlexComponent::Cb) | + static_cast(FlexComponent::Cr), + YCbCrA = static_cast(YCbCr) | + static_cast(FlexComponent::A), + RGB = static_cast(FlexComponent::R) | + static_cast(FlexComponent::G) | + static_cast(FlexComponent::B), + RGBA = static_cast(RGB) | + static_cast(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::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::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 */