diff --git a/Android.bp b/Android.bp index 727054cd3d..6f85a7035f 100644 --- a/Android.bp +++ b/Android.bp @@ -4,6 +4,7 @@ subdirs = [ "audio/effect/2.0", "benchmarks/msgq/1.0", "graphics/allocator/2.0", + "graphics/allocator/2.0/default", "memtrack/1.0", "memtrack/1.0/default", "nfc/1.0", 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 */