/* * Copyright (C) 2010 ARM Limited. All rights reserved. * * Copyright (C) 2008 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 ENABLE_DEBUG_LOG #include "custom_log.h" #include #include #include #include #include #include #include #include #define USE_GRALLOC_0 #include #include #include "alloc_device.h" #include "gralloc_priv.h" #include "gralloc_helper.h" #include "log.h" #include "core/buffer_descriptor.h" #include "core/buffer_allocation.h" #include "allocator/shared_memory/shared_memory.h" #define GRALLOC_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) static void get_yuv_info(int usage, mali_gralloc_yuv_info *yuv_info) { int private_usage = usage & (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1); switch (private_usage) { case 0: *yuv_info = MALI_YUV_BT601_NARROW; break; case GRALLOC_USAGE_PRIVATE_1: *yuv_info = MALI_YUV_BT601_WIDE; break; case GRALLOC_USAGE_PRIVATE_0: *yuv_info = MALI_YUV_BT709_NARROW; break; case (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1): *yuv_info = MALI_YUV_BT709_WIDE; break; } } static int get_specific_hal_format(int req_format, int usage) { int specific_format; if ( req_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ) { if ( (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) || (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) ) { D("to use NV12 for HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, usage : 0x%x.", usage); specific_format = HAL_PIXEL_FORMAT_YCrCb_NV12; } else { D("to use RGBX_8888, for HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, usage : 0x%x.", usage); specific_format = HAL_PIXEL_FORMAT_RGBX_8888; } } else if ( HAL_PIXEL_FORMAT_YCbCr_420_888 == req_format ) { D("to use NV12 for HAL_PIXEL_FORMAT_YCbCr_420_888."); specific_format = HAL_PIXEL_FORMAT_YCrCb_NV12; } else { specific_format = req_format; } return specific_format; } static int alloc_device_alloc(alloc_device_t *dev, int w, int h, int format, int usage, buffer_handle_t *pHandle, int *pStride) // pixel_stride #if 1 { MALI_IGNORE(dev); buffer_descriptor_t grallocDescriptor; buffer_descriptor_t* bufferDescriptor = &grallocDescriptor; private_handle_t *hnd = nullptr; // 将返回到 *pHandle 中. bufferDescriptor->width = w; bufferDescriptor->height = h; bufferDescriptor->producer_usage = usage; bufferDescriptor->consumer_usage = usage; bufferDescriptor->hal_format = format; bufferDescriptor->layer_count = 1; bufferDescriptor->signature = sizeof(buffer_descriptor_t); if (mali_gralloc_buffer_allocate(bufferDescriptor, &hnd) != 0) { MALI_GRALLOC_LOGE("%s, buffer allocation failed with %d", __func__, errno); return -1; } hnd->reserved_region_size = bufferDescriptor->reserved_size; hnd->usage = hnd->producer_usage | hnd->consumer_usage; hnd->format = get_specific_hal_format(hnd->req_format, hnd->usage); get_yuv_info(hnd->usage, &(hnd->yuv_info) ); /*-------------------------------------------------------*/ hnd->ashmem_size = PAGE_SIZE; std::tie(hnd->ashmem_fd, hnd->ashmem_base) = gralloc_shared_memory_allocate("rk_ashmem", hnd->ashmem_size); if (hnd->ashmem_fd < 0 || hnd->ashmem_base == MAP_FAILED) { MALI_GRALLOC_LOGE("%s, shared memory allocation failed with errno %d", __func__, errno); mali_gralloc_buffer_free(hnd); return -1; } struct rk_ashmem_t* rk_ashmem = static_cast(hnd->ashmem_base); rk_ashmem->alreadyStereo = 0; rk_ashmem->displayStereo = 0; strcpy(rk_ashmem->LayerName, ""); rk_ashmem->offset_of_dynamic_hdr_metadata = -1; munmap(hnd->ashmem_base, hnd->ashmem_size); hnd->ashmem_base = MAP_FAILED; /*-------------------------------------------------------*/ hnd->rsm_size = PAGE_SIZE; std::tie(hnd->rsm_fd, hnd->rsm_base) = gralloc_shared_memory_allocate("rkvdec_scaling_metadata_buf", hnd->rsm_size); if (hnd->rsm_fd < 0 || hnd->rsm_base == MAP_FAILED) { E("rkvdec_scaling_metadata_buf allocation failed with errno %d", errno); close(hnd->ashmem_fd); mali_gralloc_buffer_free(hnd); return -1; } metadata_for_rkvdec_scaling_t* metadata = static_cast(hnd->rsm_base); memset(static_cast(metadata), 0, sizeof(*metadata)); munmap(hnd->rsm_base, hnd->rsm_size); hnd->rsm_base = MAP_FAILED; /*-------------------------------------------------------*/ #if 0 // 这段代码引用的函数依赖 gralloc 4.0 的 mapper 接口, 先不引入. hnd->attr_size = mapper::common::shared_metadata_size() + hnd->reserved_region_size; std::tie(hnd->share_attr_fd, hnd->attr_base) = gralloc_shared_memory_allocate("gralloc_shared_memory", hnd->attr_size); if (hnd->share_attr_fd < 0 || hnd->attr_base == MAP_FAILED) { MALI_GRALLOC_LOGE("%s, shared memory allocation failed with errno %d", __func__, errno); mali_gralloc_buffer_free(hnd); return -1; } mapper::common::shared_metadata_init(hnd->attr_base, bufferDescriptor->name); const uint32_t base_format = bufferDescriptor->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK; const uint64_t usage = bufferDescriptor->consumer_usage | bufferDescriptor->producer_usage; android_dataspace_t dataspace; get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace, &hnd->yuv_info); mapper::common::set_dataspace(hnd, static_cast(dataspace)); /* * We need to set attr_base to MAP_FAILED before the HIDL callback * to avoid sending an invalid pointer to the client process. * * hnd->attr_base = mmap(...); * hidl_callback(hnd); // client receives hnd->attr_base = */ munmap(hnd->attr_base, hnd->attr_size); hnd->attr_base = MAP_FAILED; #endif { buffer_descriptor_t* bufDescriptor = bufferDescriptor; D("got new private_handle_t instance @%p for buffer '%s'. share_fd : %d, " // "share_attr_fd : %d, " "flags : 0x%x, width : %d, height : %d, " "req_format : 0x%x, producer_usage : 0x%" PRIx64 ", consumer_usage : 0x%" PRIx64 ", " "format: %d, stride : %d, pixel_stride: %d, " "alloc_format : 0x%" PRIx64 ", size : %d, layer_count : %u, backing_store_size : %d, " "backing_store_id : %" PRIu64 ", " "allocating_pid : %d, ref_count : %d, yuv_info : %d", hnd, (bufDescriptor->name).c_str() == nullptr ? "unset" : (bufDescriptor->name).c_str(), hnd->share_fd, // hnd->share_attr_fd, hnd->flags, hnd->width, hnd->height, hnd->req_format, hnd->producer_usage, hnd->consumer_usage, hnd->format, hnd->stride, hnd->pixel_stride, hnd->alloc_format, hnd->size, hnd->layer_count, hnd->backing_store_size, hnd->backing_store_id, hnd->allocating_pid, hnd->ref_count, hnd->yuv_info); #ifdef ENABLE_DEBUG_LOG ALOGD("plane_info[0]: offset : %u, byte_stride : %u, alloc_width : %u, alloc_height : %u", (hnd->plane_info)[0].offset, (hnd->plane_info)[0].byte_stride, (hnd->plane_info)[0].alloc_width, (hnd->plane_info)[0].alloc_height); ALOGD("plane_info[1]: offset : %u, byte_stride : %u, alloc_width : %u, alloc_height : %u", (hnd->plane_info)[1].offset, (hnd->plane_info)[1].byte_stride, (hnd->plane_info)[1].alloc_width, (hnd->plane_info)[1].alloc_height); #endif } *pHandle = hnd; *pStride = hnd->pixel_stride; D("*pStride: %d", *pStride); return 0; } #else { if (!pHandle || !pStride) { return -EINVAL; } size_t size; size_t stride; if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP || format == HAL_PIXEL_FORMAT_YV12 /* HAL_PIXEL_FORMAT_YCbCr_420_SP, HAL_PIXEL_FORMAT_YCbCr_420_P, HAL_PIXEL_FORMAT_YCbCr_422_I are not defined in Android. * To enable Mali DDK EGLImage support for those formats, firstly, you have to add them in Android system/core/include/system/graphics.h. * Then, define SUPPORT_LEGACY_FORMAT in the same header file(Mali DDK will also check this definition). */ #ifdef SUPPORT_LEGACY_FORMAT || format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCbCr_420_P || format == HAL_PIXEL_FORMAT_YCbCr_422_I #endif ) { switch (format) { case HAL_PIXEL_FORMAT_YCrCb_420_SP: stride = GRALLOC_ALIGN(w, 16); size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16)); break; case HAL_PIXEL_FORMAT_YV12: #ifdef SUPPORT_LEGACY_FORMAT case HAL_PIXEL_FORMAT_YCbCr_420_P: #endif stride = GRALLOC_ALIGN(w, 16); size = GRALLOC_ALIGN(h, 2) * (stride + GRALLOC_ALIGN(stride / 2, 16)); break; #ifdef SUPPORT_LEGACY_FORMAT case HAL_PIXEL_FORMAT_YCbCr_420_SP: stride = GRALLOC_ALIGN(w, 16); size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16)); break; case HAL_PIXEL_FORMAT_YCbCr_422_I: stride = GRALLOC_ALIGN(w, 16); size = h * stride * 2; break; #endif default: return -EINVAL; } } else { int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: bpp = 4; break; case HAL_PIXEL_FORMAT_RGB_888: bpp = 3; break; case HAL_PIXEL_FORMAT_RGB_565: bpp = 2; break; default: return -EINVAL; } size_t bpr = GRALLOC_ALIGN(w * bpp, 64); size = bpr * h; stride = bpr / bpp; } int err; err = gralloc_alloc_buffer(dev, size, usage, pHandle); if (err < 0) { return err; } /* match the framebuffer format */ if (usage & GRALLOC_USAGE_HW_FB) { #ifdef GRALLOC_16_BITS format = HAL_PIXEL_FORMAT_RGB_565; #else format = HAL_PIXEL_FORMAT_BGRA_8888; #endif } private_handle_t *hnd = (private_handle_t *)*pHandle; int private_usage = usage & (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1); switch (private_usage) { case 0: hnd->yuv_info = MALI_YUV_BT601_NARROW; break; case GRALLOC_USAGE_PRIVATE_1: hnd->yuv_info = MALI_YUV_BT601_WIDE; break; case GRALLOC_USAGE_PRIVATE_0: hnd->yuv_info = MALI_YUV_BT709_NARROW; break; case (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1): hnd->yuv_info = MALI_YUV_BT709_WIDE; break; } hnd->width = w; hnd->height = h; hnd->format = format; hnd->stride = stride; *pStride = stride; return 0; } #endif static int alloc_device_free(alloc_device_t *dev, buffer_handle_t handle) { MALI_IGNORE(dev); if (private_handle_t::validate(handle) < 0) { return -EINVAL; } private_handle_t *hnd = static_cast(const_cast(handle) ); { /* Buffer might be unregistered so we need to check for invalid ump handle*/ if (0 != hnd->base) { if (0 != munmap(static_cast(hnd->base), hnd->size)) { AERR("Failed to munmap handle 0x%p", hnd); } } close(hnd->share_fd); close(hnd->ashmem_fd); // 目前设计中, 此时 'hnd->ashmem_base' 是 MAP_FAILED. close(hnd->rsm_fd); // 目前设计中, 预期 'hnd->rsm_base' 是 MAP_FAILED. memset(static_cast(hnd), 0, sizeof(*hnd)); } delete hnd; return 0; } static int alloc_device_close(struct hw_device_t *device) { alloc_device_t *dev = reinterpret_cast(device); if (dev) { delete dev; } return 0; } int alloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device) { MALI_IGNORE(name); alloc_device_t *dev; dev = new alloc_device_t; if (NULL == dev) { return -1; } /* initialize our state here */ memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = const_cast(module); dev->common.close = alloc_device_close; dev->alloc = alloc_device_alloc; dev->free = alloc_device_free; *device = &dev->common; return 0; }