android13/hardware/rockchip/libgralloc/utgard/alloc_device.cpp

460 lines
12 KiB
C++

/*
* 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 <string.h>
#include <errno.h>
#include <pthread.h>
#include <inttypes.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <hardware/hardware.h>
#include <hardware/gralloc.h>
#define USE_GRALLOC_0
#include <hardware/gralloc_rockchip.h>
#include <sys/ioctl.h>
#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<struct rk_ashmem_t*>(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<metadata_for_rkvdec_scaling_t*>(hnd->rsm_base);
memset(static_cast<void *>(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<mapper::common::Dataspace>(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 = <dangling pointer>
*/
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<private_handle_t *>(const_cast<native_handle_t *>(handle) );
{
/* Buffer might be unregistered so we need to check for invalid ump handle*/
if (0 != hnd->base)
{
if (0 != munmap(static_cast<void *>(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<void *>(hnd), 0, sizeof(*hnd));
}
delete hnd;
return 0;
}
static int alloc_device_close(struct hw_device_t *device)
{
alloc_device_t *dev = reinterpret_cast<alloc_device_t *>(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<hw_module_t *>(module);
dev->common.close = alloc_device_close;
dev->alloc = alloc_device_alloc;
dev->free = alloc_device_free;
*device = &dev->common;
return 0;
}