diff options
Diffstat (limited to 'msm8909/gralloc/gr_buf_mgr.cpp')
-rw-r--r-- | msm8909/gralloc/gr_buf_mgr.cpp | 929 |
1 files changed, 929 insertions, 0 deletions
diff --git a/msm8909/gralloc/gr_buf_mgr.cpp b/msm8909/gralloc/gr_buf_mgr.cpp new file mode 100644 index 00000000..23bed236 --- /dev/null +++ b/msm8909/gralloc/gr_buf_mgr.cpp @@ -0,0 +1,929 @@ +/* + * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Not a Contribution + * + * Copyright (C) 2010 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 DEBUG 0 + +#include <iomanip> +#include <utility> +#include <vector> +#include <sstream> + +#include "qd_utils.h" +#include "gr_priv_handle.h" +#include "gr_buf_descriptor.h" +#include "gr_utils.h" +#include "gr_buf_mgr.h" +#include "qdMetaData.h" + +namespace gralloc1 { +std::atomic<gralloc1_buffer_descriptor_t> BufferDescriptor::next_id_(1); + +static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) { + return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(), + descriptor.GetProducerUsage(), descriptor.GetConsumerUsage()); +} + +BufferManager::BufferManager() : next_id_(0) { + char property[PROPERTY_VALUE_MAX]; + + // Map framebuffer memory + if ((property_get(MAP_FB_MEMORY_PROP, property, NULL) > 0) && + (!strncmp(property, "1", PROPERTY_VALUE_MAX) || + (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) { + map_fb_mem_ = true; + } + + handles_map_.clear(); + allocator_ = new Allocator(); + allocator_->Init(); +} + + +gralloc1_error_t BufferManager::CreateBufferDescriptor( + gralloc1_buffer_descriptor_t *descriptor_id) { + std::lock_guard<std::mutex> lock(descriptor_lock_); + auto descriptor = std::make_shared<BufferDescriptor>(); + descriptors_map_.emplace(descriptor->GetId(), descriptor); + *descriptor_id = descriptor->GetId(); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t BufferManager::DestroyBufferDescriptor( + gralloc1_buffer_descriptor_t descriptor_id) { + std::lock_guard<std::mutex> lock(descriptor_lock_); + const auto descriptor = descriptors_map_.find(descriptor_id); + if (descriptor == descriptors_map_.end()) { + return GRALLOC1_ERROR_BAD_DESCRIPTOR; + } + descriptors_map_.erase(descriptor); + return GRALLOC1_ERROR_NONE; +} + +BufferManager::~BufferManager() { + if (allocator_) { + delete allocator_; + } +} + +gralloc1_error_t BufferManager::AllocateBuffers(uint32_t num_descriptors, + const gralloc1_buffer_descriptor_t *descriptor_ids, + buffer_handle_t *out_buffers) { + bool shared = true; + gralloc1_error_t status = GRALLOC1_ERROR_NONE; + + // since GRALLOC1_CAPABILITY_TEST_ALLOCATE capability is supported + // client can ask to test the allocation by passing NULL out_buffers + bool test_allocate = !out_buffers; + + // Validate descriptors + std::lock_guard<std::mutex> descriptor_lock(descriptor_lock_); + std::vector<std::shared_ptr<BufferDescriptor>> descriptors; + for (uint32_t i = 0; i < num_descriptors; i++) { + const auto map_descriptor = descriptors_map_.find(descriptor_ids[i]); + if (map_descriptor == descriptors_map_.end()) { + return GRALLOC1_ERROR_BAD_DESCRIPTOR; + } else { + descriptors.push_back(map_descriptor->second); + } + } + + // Resolve implementation defined formats + for (auto &descriptor : descriptors) { + descriptor->SetColorFormat(allocator_->GetImplDefinedFormat(descriptor->GetProducerUsage(), + descriptor->GetConsumerUsage(), + descriptor->GetFormat())); + } + + // Check if input descriptors can be supported AND + // Find out if a single buffer can be shared for all the given input descriptors + uint32_t i = 0; + ssize_t max_buf_index = -1; + shared = allocator_->CheckForBufferSharing(num_descriptors, descriptors, &max_buf_index); + + if (test_allocate) { + status = shared ? GRALLOC1_ERROR_NOT_SHARED : status; + return status; + } + + std::lock_guard<std::mutex> buffer_lock(buffer_lock_); + if (shared && (max_buf_index >= 0)) { + // Allocate one and duplicate/copy the handles for each descriptor + if (AllocateBuffer(*descriptors[UINT(max_buf_index)], &out_buffers[max_buf_index])) { + return GRALLOC1_ERROR_NO_RESOURCES; + } + + for (i = 0; i < num_descriptors; i++) { + // Create new handle for a given descriptor. + // Current assumption is even MetaData memory would be same + // Need to revisit if there is a need for own metadata memory + if (i != UINT(max_buf_index)) { + CreateSharedHandle(out_buffers[max_buf_index], *descriptors[i], &out_buffers[i]); + } + } + } else { + // Buffer sharing is not feasible. + // Allocate separate buffer for each descriptor + for (i = 0; i < num_descriptors; i++) { + if (AllocateBuffer(*descriptors[i], &out_buffers[i])) { + return GRALLOC1_ERROR_NO_RESOURCES; + } + } + } + + // Allocation is successful. If backstore is not shared inform the client. + if (!shared) { + return GRALLOC1_ERROR_NOT_SHARED; + } + + return status; +} + +void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDescriptor &descriptor, + buffer_handle_t *outbuffer) { + // TODO(user): This path is not verified + private_handle_t const *input = reinterpret_cast<private_handle_t const *>(inbuffer); + + // Get Buffer attributes or dimension + unsigned int alignedw = 0, alignedh = 0; + BufferInfo info = GetBufferInfo(descriptor); + + GetAlignedWidthAndHeight(info, &alignedw, &alignedh); + + // create new handle from input reference handle and given descriptor + int flags = GetHandleFlags(descriptor.GetFormat(), descriptor.GetProducerUsage(), + descriptor.GetConsumerUsage()); + int buffer_type = GetBufferType(descriptor.GetFormat()); + + // Duplicate the fds + // TODO(user): Not sure what to do for fb_id. Use duped fd and new dimensions? + private_handle_t *out_hnd = new private_handle_t(dup(input->fd), + dup(input->fd_metadata), + flags, + INT(alignedw), + INT(alignedh), + descriptor.GetWidth(), + descriptor.GetHeight(), + descriptor.GetFormat(), + buffer_type, + input->size, + descriptor.GetProducerUsage(), + descriptor.GetConsumerUsage()); + out_hnd->id = ++next_id_; + // TODO(user): Base address of shared handle and ion handles + RegisterHandleLocked(out_hnd, -1, -1); + *outbuffer = out_hnd; +} + +gralloc1_error_t BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) { + auto hnd = buf->handle; + ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd); + + if (private_handle_t::validate(hnd) != 0) { + ALOGE("FreeBuffer: Invalid handle: %p", hnd); + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset, + hnd->fd, buf->ion_handle_main) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE); + if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size, + hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + private_handle_t * handle = const_cast<private_handle_t *>(hnd); + handle->fd = -1; + handle->fd_metadata = -1; + if (!(handle->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED)) { + delete handle; + } + return GRALLOC1_ERROR_NONE; +} + +void BufferManager::RegisterHandleLocked(const private_handle_t *hnd, + int ion_handle, + int ion_handle_meta) { + auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta); + handles_map_.emplace(std::make_pair(hnd, buffer)); +} + +gralloc1_error_t BufferManager::ImportHandleLocked(private_handle_t *hnd) { + ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id); + int ion_handle = allocator_->ImportBuffer(hnd->fd); + if (ion_handle < 0) { + ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id); + return GRALLOC1_ERROR_BAD_HANDLE; + } + int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata); + if (ion_handle_meta < 0) { + ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, + hnd->fd, hnd->id); + return GRALLOC1_ERROR_BAD_HANDLE; + } + // Set base pointers to NULL since the data here was received over binder + hnd->base = 0; + hnd->base_metadata = 0; + RegisterHandleLocked(hnd, ion_handle, ion_handle_meta); + return GRALLOC1_ERROR_NONE; +} + +std::shared_ptr<BufferManager::Buffer> +BufferManager::GetBufferFromHandleLocked(const private_handle_t *hnd) { + auto it = handles_map_.find(hnd); + if (it != handles_map_.end()) { + return it->second; + } else { + return nullptr; + } +} + +gralloc1_error_t BufferManager::MapBuffer(private_handle_t const *handle) { + private_handle_t *hnd = const_cast<private_handle_t *>(handle); + ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id); + + hnd->base = 0; + if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base), hnd->size, hnd->offset, + hnd->fd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) { + ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id); + gralloc1_error_t err = GRALLOC1_ERROR_NONE; + std::lock_guard<std::mutex> lock(buffer_lock_); + auto buf = GetBufferFromHandleLocked(hnd); + if (buf != nullptr) { + buf->IncRef(); + } else { + private_handle_t *handle = const_cast<private_handle_t *>(hnd); + err = ImportHandleLocked(handle); + } + return err; +} + +gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) { + ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd); + std::lock_guard<std::mutex> lock(buffer_lock_); + auto buf = GetBufferFromHandleLocked(hnd); + if (buf == nullptr) { + ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id); + return GRALLOC1_ERROR_BAD_HANDLE; + } else { + if (buf->DecRef()) { + handles_map_.erase(hnd); + // Unmap, close ion handle and close fd + FreeBuffer(buf); + } + } + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd, + gralloc1_producer_usage_t prod_usage, + gralloc1_consumer_usage_t cons_usage) { + std::lock_guard<std::mutex> lock(buffer_lock_); + gralloc1_error_t err = GRALLOC1_ERROR_NONE; + ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id); + + // If buffer is not meant for CPU return err + if (!CpuCanAccess(prod_usage, cons_usage)) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + auto buf = GetBufferFromHandleLocked(hnd); + if (buf == nullptr) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (hnd->base == 0) { + // we need to map for real + err = MapBuffer(hnd); + } + + // todo use handle here + if (!err && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) && + (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) { + + // Invalidate if CPU reads in software and there are non-CPU + // writers. No need to do this for the metadata buffer as it is + // only read/written in software. + if ((cons_usage & (GRALLOC1_CONSUMER_USAGE_CPU_READ | GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN)) + && (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER)) { + if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset, + buf->ion_handle_main, CACHE_INVALIDATE)) { + + return GRALLOC1_ERROR_BAD_HANDLE; + } + } + } + + // Mark the buffer to be flushed after CPU write. + if (!err && CpuCanWrite(prod_usage)) { + private_handle_t *handle = const_cast<private_handle_t *>(hnd); + handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; + } + + return err; +} + +gralloc1_error_t BufferManager::UnlockBuffer(const private_handle_t *handle) { + std::lock_guard<std::mutex> lock(buffer_lock_); + gralloc1_error_t status = GRALLOC1_ERROR_NONE; + + private_handle_t *hnd = const_cast<private_handle_t *>(handle); + auto buf = GetBufferFromHandleLocked(hnd); + if (buf == nullptr) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { + if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset, + buf->ion_handle_main, CACHE_CLEAN) != 0) { + status = GRALLOC1_ERROR_BAD_HANDLE; + } + hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; + } + + return status; +} + +uint32_t BufferManager::GetDataAlignment(int format, gralloc1_producer_usage_t prod_usage, + gralloc1_consumer_usage_t cons_usage) { + uint32_t align = UINT(getpagesize()); + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + align = 8192; + } + + if (prod_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) { + if ((prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) || + (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY)) { + // The alignment here reflects qsee mmu V7L/V8L requirement + align = SZ_2M; + } else { + align = SECURE_ALIGN; + } + } + + return align; +} + +int BufferManager::GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage, + gralloc1_consumer_usage_t cons_usage) { + int flags = 0; + if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY) { + flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY; + } + + if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY) { + flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY; + } + + if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) { + flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER; + } + + if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) { + flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE; + } + + if (prod_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) { + flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ; + } + + if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) { + flags |= private_handle_t::PRIV_FLAGS_HW_COMPOSER; + } + + if (prod_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) { + flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE; + } + + if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY) { + flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY; + } + + if (IsUBwcEnabled(format, prod_usage, cons_usage)) { + flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED; + } + + if (prod_usage & (GRALLOC1_PRODUCER_USAGE_CPU_READ | GRALLOC1_PRODUCER_USAGE_CPU_WRITE)) { + flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED; + } + + // TODO(user): is this correct??? + if ((cons_usage & + (GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER | GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET)) || + (prod_usage & (GRALLOC1_PRODUCER_USAGE_CAMERA | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))) { + flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER; + } + + if (cons_usage & GRALLOC1_CONSUMER_USAGE_HWCOMPOSER) { + flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER; + } + + if (!allocator_->UseUncached(prod_usage, cons_usage)) { + flags |= private_handle_t::PRIV_FLAGS_CACHED; + } + + return flags; +} + +int BufferManager::GetBufferType(int inputFormat) { + int buffer_type = BUFFER_TYPE_VIDEO; + if (IsUncompressedRGBFormat(inputFormat)) { + // RGB formats + buffer_type = BUFFER_TYPE_UI; + } + + return buffer_type; +} + +int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle, + unsigned int bufferSize) { + if (!handle) + return -EINVAL; + + int format = descriptor.GetFormat(); + gralloc1_producer_usage_t prod_usage = descriptor.GetProducerUsage(); + gralloc1_consumer_usage_t cons_usage = descriptor.GetConsumerUsage(); + uint32_t layer_count = descriptor.GetLayerCount(); + + // Get implementation defined format + int gralloc_format = allocator_->GetImplDefinedFormat(prod_usage, cons_usage, format); + + unsigned int size; + unsigned int alignedw, alignedh; + int buffer_type = GetBufferType(gralloc_format); + BufferInfo info = GetBufferInfo(descriptor); + GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh); + size = (bufferSize >= size) ? bufferSize : size; + + int err = 0; + int flags = 0; + auto page_size = UINT(getpagesize()); + AllocData data; + data.align = GetDataAlignment(format, prod_usage, cons_usage); + size = ALIGN(size, data.align) * layer_count; + data.size = size; + data.handle = (uintptr_t) handle; + data.uncached = allocator_->UseUncached(prod_usage, cons_usage); + + // Allocate buffer memory + err = allocator_->AllocateMem(&data, prod_usage, cons_usage); + if (err) { + ALOGE("gralloc failed to allocate err=%s", strerror(-err)); + return err; + } + + // Allocate memory for MetaData + AllocData e_data; + e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size); + e_data.handle = data.handle; + e_data.align = page_size; + + err = + allocator_->AllocateMem(&e_data, GRALLOC1_PRODUCER_USAGE_NONE, GRALLOC1_CONSUMER_USAGE_NONE); + if (err) { + ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err)); + return err; + } + + flags = GetHandleFlags(format, prod_usage, cons_usage); + flags |= data.alloc_type; + + // Create handle + private_handle_t *hnd = new private_handle_t(data.fd, + e_data.fd, + flags, + INT(alignedw), + INT(alignedh), + descriptor.GetWidth(), + descriptor.GetHeight(), + format, + buffer_type, + data.size, + prod_usage, + cons_usage); + + hnd->id = ++next_id_; + hnd->base = 0; + hnd->base_metadata = 0; + hnd->layer_count = layer_count; + + ColorSpace_t colorSpace = ITU_R_601; + setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace)); + *handle = hnd; + RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle); + ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id); + if (DEBUG) { + private_handle_t::Dump(hnd); + } + return err; +} + +gralloc1_error_t BufferManager::Perform(int operation, va_list args) { + switch (operation) { + case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: { + int fd = va_arg(args, int); + unsigned int size = va_arg(args, unsigned int); + unsigned int offset = va_arg(args, unsigned int); + void *base = va_arg(args, void *); + int width = va_arg(args, int); + int height = va_arg(args, int); + int format = va_arg(args, int); + + native_handle_t **handle = va_arg(args, native_handle_t **); + if (!handle) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + private_handle_t *hnd = reinterpret_cast<private_handle_t *>( + native_handle_create(private_handle_t::kNumFds, private_handle_t::NumInts())); + if (hnd) { + unsigned int alignedw = 0, alignedh = 0; + hnd->magic = private_handle_t::kMagic; + hnd->fd = fd; + hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; + hnd->size = size; + hnd->offset = offset; + hnd->base = uint64_t(base); + hnd->gpuaddr = 0; + BufferInfo info(width, height, format); + GetAlignedWidthAndHeight(info, &alignedw, &alignedh); + hnd->unaligned_width = width; + hnd->unaligned_height = height; + hnd->width = INT(alignedw); + hnd->height = INT(alignedh); + hnd->format = format; + *handle = reinterpret_cast<native_handle_t *>(hnd); + } + } break; + + case GRALLOC_MODULE_PERFORM_GET_STRIDE: { + int width = va_arg(args, int); + int format = va_arg(args, int); + int *stride = va_arg(args, int *); + unsigned int alignedw = 0, alignedh = 0; + + if (!stride) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + BufferInfo info(width, width, format); + GetAlignedWidthAndHeight(info, &alignedw, &alignedh); + *stride = INT(alignedw); + } break; + + case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *stride = va_arg(args, int *); + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!stride) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + BufferDim_t buffer_dim; + if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) { + *stride = buffer_dim.sliceWidth; + } else { + *stride = hnd->width; + } + } break; + + // TODO(user) : this alone should be sufficient, ask gfx to get rid of above + case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *stride = va_arg(args, int *); + int *height = va_arg(args, int *); + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!stride || !height) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + BufferDim_t buffer_dim; + if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) { + *stride = buffer_dim.sliceWidth; + *height = buffer_dim.sliceHeight; + } else { + *stride = hnd->width; + *height = hnd->height; + } + } break; + + case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES: { + // TODO(user): Usage is split now. take care of it from Gfx client. + // see if we can directly expect descriptor from gfx client. + int width = va_arg(args, int); + int height = va_arg(args, int); + int format = va_arg(args, int); + uint64_t producer_usage = va_arg(args, uint64_t); + uint64_t consumer_usage = va_arg(args, uint64_t); + gralloc1_producer_usage_t prod_usage = static_cast<gralloc1_producer_usage_t>(producer_usage); + gralloc1_consumer_usage_t cons_usage = static_cast<gralloc1_consumer_usage_t>(consumer_usage); + + int *aligned_width = va_arg(args, int *); + int *aligned_height = va_arg(args, int *); + int *tile_enabled = va_arg(args, int *); + if (!aligned_width || !aligned_height || !tile_enabled) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + unsigned int alignedw, alignedh; + BufferInfo info(width, height, format, prod_usage, cons_usage); + *tile_enabled = IsUBwcEnabled(format, prod_usage, cons_usage); + GetAlignedWidthAndHeight(info, &alignedw, &alignedh); + *aligned_width = INT(alignedw); + *aligned_height = INT(alignedh); + } break; + + case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *color_space = va_arg(args, int *); + + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!color_space) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + *color_space = 0; + ColorMetaData color_metadata; + if (getMetaData(hnd, GET_COLOR_METADATA, &color_metadata) == 0) { + switch (color_metadata.colorPrimaries) { + case ColorPrimaries_BT709_5: + *color_space = HAL_CSC_ITU_R_709; + break; + case ColorPrimaries_BT601_6_525: + *color_space = ((color_metadata.range) ? HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601); + break; + case ColorPrimaries_BT2020: + *color_space = (color_metadata.range) ? HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020; + break; + default: + ALOGE("Unknown Color Space = %d", color_metadata.colorPrimaries); + break; + } + break; + } else if (getMetaData(hnd, GET_COLOR_SPACE, color_space) != 0) { + *color_space = 0; + } + } break; + case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + android_ycbcr *ycbcr = va_arg(args, struct android_ycbcr *); + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!ycbcr) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + if (GetYUVPlaneInfo(hnd, ycbcr)) { + return GRALLOC1_ERROR_UNDEFINED; + } + } break; + + case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *map_secure_buffer = va_arg(args, int *); + + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!map_secure_buffer) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) == 0) { + *map_secure_buffer = 0; + } + } break; + + case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *flag = va_arg(args, int *); + + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!flag) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + *flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED; + int linear_format = 0; + if (getMetaData(hnd, GET_LINEAR_FORMAT, &linear_format) == 0) { + if (linear_format) { + *flag = 0; + } + } + } break; + + case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + void **rgb_data = va_arg(args, void **); + + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!rgb_data) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + if (GetRgbDataAddress(hnd, rgb_data)) { + return GRALLOC1_ERROR_UNDEFINED; + } + } break; + + case GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS: { + int width = va_arg(args, int); + int height = va_arg(args, int); + int format = va_arg(args, int); + uint64_t p_usage = va_arg(args, uint64_t); + uint64_t c_usage = va_arg(args, uint64_t); + gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage); + gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage); + uint32_t *aligned_width = va_arg(args, uint32_t *); + uint32_t *aligned_height = va_arg(args, uint32_t *); + uint32_t *size = va_arg(args, uint32_t *); + + if (!aligned_width || !aligned_height || !size) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + auto info = BufferInfo(width, height, format, producer_usage, consumer_usage); + GetBufferSizeAndDimensions(info, size, aligned_width, aligned_height); + // Align size + auto align = GetDataAlignment(format, producer_usage, consumer_usage); + *size = ALIGN(*size, align); + } break; + + case GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER: { + std::lock_guard<std::mutex> lock(buffer_lock_); + int width = va_arg(args, int); + int height = va_arg(args, int); + int format = va_arg(args, int); + uint64_t p_usage = va_arg(args, uint64_t); + uint64_t c_usage = va_arg(args, uint64_t); + buffer_handle_t *hnd = va_arg(args, buffer_handle_t*); + gralloc1_producer_usage_t producer_usage = static_cast<gralloc1_producer_usage_t>(p_usage); + gralloc1_consumer_usage_t consumer_usage = static_cast<gralloc1_consumer_usage_t>(c_usage); + BufferDescriptor descriptor(width, height, format, producer_usage, consumer_usage); + unsigned int size; + unsigned int alignedw, alignedh; + GetBufferSizeAndDimensions(GetBufferInfo(descriptor), &size, &alignedw, &alignedh); + AllocateBuffer(descriptor, hnd, size); + } break; + + case GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG: { + private_handle_t *hnd = va_arg(args, private_handle_t *); + int *flag = va_arg(args, int *); + + if (private_handle_t::validate(hnd) != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + if (!flag) { + return GRALLOC1_ERROR_BAD_VALUE; + } + + if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, flag) != 0) { + *flag = 0; + } + } break; + + default: + break; + } + return GRALLOC1_ERROR_NONE; +} + +static bool IsYuvFormat(const private_handle_t *hnd) { + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: // Same as YCbCr_420_SP_VENUS + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: + case HAL_PIXEL_FORMAT_NV21_ZSL: + case HAL_PIXEL_FORMAT_RAW16: + case HAL_PIXEL_FORMAT_Y16: + case HAL_PIXEL_FORMAT_RAW12: + case HAL_PIXEL_FORMAT_RAW10: + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_Y8: + return true; + default: + return false; + } +} + +gralloc1_error_t BufferManager::GetNumFlexPlanes(const private_handle_t *hnd, + uint32_t *out_num_planes) { + if (!IsYuvFormat(hnd)) { + return GRALLOC1_ERROR_UNSUPPORTED; + } else { + *out_num_planes = 3; + } + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t BufferManager::GetFlexLayout(const private_handle_t *hnd, + struct android_flex_layout *layout) { + if (!IsYuvFormat(hnd)) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + + android_ycbcr ycbcr; + int err = GetYUVPlaneInfo(hnd, &ycbcr); + + if (err != 0) { + return GRALLOC1_ERROR_BAD_HANDLE; + } + + layout->format = FLEX_FORMAT_YCbCr; + layout->num_planes = 3; + + for (uint32_t i = 0; i < layout->num_planes; i++) { + layout->planes[i].bits_per_component = 8; + layout->planes[i].bits_used = 8; + layout->planes[i].h_increment = 1; + layout->planes[i].v_increment = 1; + layout->planes[i].h_subsampling = 2; + layout->planes[i].v_subsampling = 2; + } + + layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y); + layout->planes[0].component = FLEX_COMPONENT_Y; + layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride); + + layout->planes[1].top_left = static_cast<uint8_t *>(ycbcr.cb); + layout->planes[1].component = FLEX_COMPONENT_Cb; + layout->planes[1].h_increment = static_cast<int32_t>(ycbcr.chroma_step); + layout->planes[1].v_increment = static_cast<int32_t>(ycbcr.cstride); + + layout->planes[2].top_left = static_cast<uint8_t *>(ycbcr.cr); + layout->planes[2].component = FLEX_COMPONENT_Cr; + layout->planes[2].h_increment = static_cast<int32_t>(ycbcr.chroma_step); + layout->planes[2].v_increment = static_cast<int32_t>(ycbcr.cstride); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t BufferManager::Dump(std::ostringstream *os) { + for (auto it : handles_map_) { + auto buf = it.second; + auto hnd = buf->handle; + *os << "handle id: " << std::setw(4) << hnd->id; + *os << " fd: " << std::setw(3) << hnd->fd; + *os << " fd_meta: " << std::setw(3) << hnd->fd_metadata; + *os << " wxh: " << std::setw(4) << hnd->width <<" x " << std::setw(4) << hnd->height; + *os << " uwxuh: " << std::setw(4) << hnd->unaligned_width << " x "; + *os << std::setw(4) << hnd->unaligned_height; + *os << " size: " << std::setw(9) << hnd->size; + *os << std::hex << std::setfill('0'); + *os << " priv_flags: " << "0x" << std::setw(8) << hnd->flags; + *os << " prod_usage: " << "0x" << std::setw(8) << hnd->producer_usage; + *os << " cons_usage: " << "0x" << std::setw(8) << hnd->consumer_usage; + // TODO(user): get format string from qdutils + *os << " format: " << "0x" << std::setw(8) << hnd->format; + *os << std::dec << std::setfill(' ') << std::endl; + } + return GRALLOC1_ERROR_NONE; +} +} // namespace gralloc1 |