Files
android_vendor_qcom_opensou…/libgralloc/mapper.cpp
Saurabh Shah c5b2b70479 gralloc/qdutils: Remove unused gralloc code, add driver type check
Remove unused code related to macro tiling from galloc and qdutils.
Add API to check for driver type and query caps based on driver.

Change-Id: I36cfa5529395c69deb886080be1c904ff5c9ad15
CRs-fixed: 1109207
2017-01-28 07:23:10 -08:00

524 lines
18 KiB
C++

/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <limits.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <utils/Trace.h>
#include <hardware/hardware.h>
#include <hardware/gralloc.h>
#include "gralloc_priv.h"
#include "gr.h"
#include "alloc_controller.h"
#include "memalloc.h"
#include <qdMetaData.h>
using namespace gralloc;
/*****************************************************************************/
// Return the type of allocator -
// these are used for mapping/unmapping
static IMemAlloc* getAllocator(int flags)
{
IMemAlloc* memalloc;
IAllocController* alloc_ctrl = IAllocController::getInstance();
memalloc = alloc_ctrl->getAllocator(flags);
return memalloc;
}
static int gralloc_map_metadata(buffer_handle_t handle) {
private_handle_t* hnd = (private_handle_t*)handle;
hnd->base_metadata = 0;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
void *mappedAddress = MAP_FAILED;
unsigned int size = 0;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
mappedAddress = MAP_FAILED;
size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
int ret = memalloc->map_buffer(&mappedAddress, size,
hnd->offset_metadata, hnd->fd_metadata);
if(ret || mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
hnd, hnd->fd_metadata, strerror(errno));
return -errno;
}
hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
}
return 0;
}
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
if(!module)
return -EINVAL;
private_handle_t* hnd = (private_handle_t*)handle;
unsigned int size = 0;
int err = 0;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
void *mappedAddress = MAP_FAILED;
hnd->base = 0;
// Dont map framebuffer and secure buffers
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
!(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
size = hnd->size;
err = memalloc->map_buffer(&mappedAddress, size,
hnd->offset, hnd->fd);
if(err || mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap handle %p, fd=%d (%s)",
handle, hnd->fd, strerror(errno));
return -errno;
}
hnd->base = uint64_t(mappedAddress) + hnd->offset;
} else {
// Cannot map secure buffers or framebuffers, but still need to map
// metadata for secure buffers.
// If mapping a secure buffers fails, the framework needs to get
// an error code.
err = -EACCES;
}
//Allow mapping of metadata for all buffers including secure ones, but not
//of framebuffer
int metadata_err = gralloc_map_metadata(handle);
if (!err) {
err = metadata_err;
}
return err;
}
static int gralloc_unmap(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
int err = -EINVAL;
if(!module)
return err;
private_handle_t* hnd = (private_handle_t*)handle;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
if(!memalloc)
return err;
if(hnd->base) {
err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
if (err) {
ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
strerror(errno));
return -errno;
}
hnd->base = 0;
}
if(hnd->base_metadata) {
unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
err = memalloc->unmap_buffer((void*)hnd->base_metadata,
size, hnd->offset_metadata);
if (err) {
ALOGE("Could not unmap memory at address %p, %s",
(void*) hnd->base_metadata, strerror(errno));
return -errno;
}
hnd->base_metadata = 0;
}
return 0;
}
/*****************************************************************************/
static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
/*****************************************************************************/
int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
int err = gralloc_map(module, handle);
/* Do not fail register_buffer for secure buffers*/
if (err == -EACCES)
err = 0;
return err;
}
int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
/*
* If the buffer has been mapped during a lock operation, it's time
* to un-map it. It's an error to be here with a locked buffer.
* NOTE: the framebuffer is handled differently and is never unmapped.
* Also base and base_metadata are reset.
*/
return gralloc_unmap(module, handle);
}
int terminateBuffer(gralloc_module_t const* module,
private_handle_t* hnd)
{
ATRACE_CALL();
if(!module)
return -EINVAL;
/*
* If the buffer has been mapped during a lock operation, it's time
* to un-map it. It's an error to be here with a locked buffer.
* NOTE: the framebuffer is handled differently and is never unmapped.
* Also base and base_metadata are reset.
*/
return gralloc_unmap(module, hnd);
}
static int gralloc_map_and_invalidate (gralloc_module_t const* module,
buffer_handle_t handle, int usage)
{
ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
if (hnd->base == 0) {
// we need to map for real
pthread_mutex_t* const lock = &sMapLock;
pthread_mutex_lock(lock);
err = gralloc_map(module, handle);
pthread_mutex_unlock(lock);
}
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
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 ((usage & GRALLOC_USAGE_SW_READ_MASK) and
(hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
{
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
err = memalloc->clean_buffer((void*)hnd->base,
hnd->size, hnd->offset, hnd->fd,
CACHE_INVALIDATE);
}
//Mark the buffer to be flushed after CPU write.
if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
}
}
return err;
}
int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int /*l*/, int /*t*/, int /*w*/, int /*h*/,
void** vaddr)
{
ATRACE_CALL();
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage);
if(!err)
*vaddr = (void*)hnd->base;
return err;
}
int gralloc_lock_ycbcr(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int /*l*/, int /*t*/, int /*w*/, int /*h*/,
struct android_ycbcr *ycbcr)
{
ATRACE_CALL();
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage);
if(!err)
err = getYUVPlaneInfo(hnd, ycbcr);
return err;
}
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
ATRACE_CALL();
if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
IMemAlloc* memalloc = getAllocator(hnd->flags);
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
err = memalloc->clean_buffer((void*)hnd->base,
hnd->size, hnd->offset, hnd->fd,
CACHE_CLEAN);
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
return err;
}
/*****************************************************************************/
int gralloc_perform(struct gralloc_module_t const* module,
int operation, ... )
{
int res = -EINVAL;
va_list args;
if(!module)
return res;
va_start(args, operation);
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);
int alignedw = 0, alignedh = 0;
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts());
if (hnd) {
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
hnd->size = size;
hnd->offset = offset;
hnd->base = uint64_t(base) + offset;
hnd->gpuaddr = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height, format, 0, alignedw, alignedh);
hnd->width = alignedw;
hnd->height = alignedh;
hnd->unaligned_width = width;
hnd->unaligned_height = height;
hnd->format = format;
*handle = (native_handle_t *)hnd;
res = 0;
}
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 *);
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
0, format, 0, alignedw, alignedh);
*stride = alignedw;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
{
const private_handle_t* hnd = va_arg(args, private_handle_t*);
int *stride = va_arg(args, int *);
if (private_handle_t::validate(hnd)) {
return res;
}
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
*stride = alignedw;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
{
const 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)) {
return res;
}
int alignedw = 0, alignedh = 0;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
*stride = alignedw;
*height = alignedh;
res = 0;
} break;
case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
{
int width = va_arg(args, int);
int height = va_arg(args, int);
int format = va_arg(args, int);
int usage = va_arg(args, int);
int *alignedWidth = va_arg(args, int *);
int *alignedHeight = va_arg(args, int *);
int *tileEnabled = va_arg(args,int *);
*tileEnabled = isUBwcEnabled(format, usage);
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height, format, usage, *alignedWidth, *alignedHeight);
res = 0;
} 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)) {
return res;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (!metadata) {
break;
#ifdef USE_COLOR_METADATA
} else if (metadata->operation & COLOR_METADATA) {
ColorMetaData *colorMetadata = &metadata->color;
res = 0;
switch (colorMetadata->colorPrimaries) {
case ColorPrimaries_BT709_5:
*color_space = HAL_CSC_ITU_R_709;
break;
case ColorPrimaries_BT601_6_525:
*color_space = ((colorMetadata->range) ?
HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
break;
case ColorPrimaries_BT2020:
*color_space = (colorMetadata->range) ?
HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
break;
default:
res = -EINVAL;
break;
}
#endif
} else if(metadata->operation & UPDATE_COLOR_SPACE) {
*color_space = metadata->colorSpace;
res = 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)) {
res = getYUVPlaneInfo(hnd, ycbcr);
}
} 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)) {
return res;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
*map_secure_buffer = metadata->mapSecureBuffer;
res = 0;
} else {
*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)) {
return res;
}
*flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (metadata && (metadata->operation & LINEAR_FORMAT)) {
*flag = 0;
}
res = 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)) {
res = getRgbDataAddress(hnd, rgb_data);
}
} break;
case GRALLOC_MODULE_PERFORM_GET_IGC:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t *igc = va_arg(args, uint32_t *);
if (!private_handle_t::validate(hnd) && igc) {
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if (metadata && (metadata->operation & SET_IGC)) {
*igc = metadata->igc;
res = 0;
}
}
} break;
case GRALLOC_MODULE_PERFORM_SET_IGC:
res = 0;
break;
case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
{
private_handle_t* hnd = va_arg(args, private_handle_t*);
uint32_t *enable = va_arg(args, uint32_t*);
if (!private_handle_t::validate(hnd)) {
setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
res = 0;
}
} break;
default:
break;
}
va_end(args);
return res;
}