1351 lines
31 KiB
C++
1351 lines
31 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 <vector>
|
|
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <cutils/log.h>
|
|
#include <cutils/atomic.h>
|
|
#include <cutils/properties.h>
|
|
#include <hardware/hardware.h>
|
|
#include <hardware/gralloc.h>
|
|
|
|
#define USE_GRALLOC_0
|
|
#include <hardware/gralloc_rockchip.h>
|
|
|
|
#include "gralloc_priv.h"
|
|
#include "alloc_device.h"
|
|
#include "allocator/allocator.h"
|
|
|
|
#include <sys/mman.h>
|
|
|
|
static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static void init_version_info(void)
|
|
{
|
|
char acCommit[128];
|
|
|
|
ALOGI(RK_GRAPHICS_VER);
|
|
|
|
/* RK_GRAPHICS_VER=commit-id:067e5d0: only keep string after '=' */
|
|
sscanf(RK_GRAPHICS_VER, "%*[^=]=%127s", acCommit);
|
|
|
|
property_set("vendor.ggralloc.commit", acCommit);
|
|
}
|
|
|
|
static int gralloc_device_open(const hw_module_t *module, const char *name, hw_device_t **device)
|
|
{
|
|
int status = -EINVAL;
|
|
|
|
init_version_info();
|
|
|
|
if (!strncmp(name, GRALLOC_HARDWARE_GPU0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))
|
|
{
|
|
status = alloc_device_open(module, name, device);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int gralloc_register_buffer(gralloc_module_t const *module, buffer_handle_t handle)
|
|
{
|
|
MALI_IGNORE(module);
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
{
|
|
AERR("Registering invalid buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
// if this handle was created in this process, then we keep it as is.
|
|
private_handle_t *hnd = static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle) );
|
|
|
|
int retval;
|
|
|
|
pthread_mutex_lock(&s_map_lock);
|
|
|
|
hnd->pid = getpid();
|
|
|
|
{
|
|
unsigned char *mappedAddress;
|
|
size_t size = hnd->size;
|
|
|
|
mappedAddress = static_cast<unsigned char *>(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, hnd->share_fd, 0) );
|
|
|
|
if (MAP_FAILED == mappedAddress)
|
|
{
|
|
AERR("mmap( share_fd:%d ) failed with %s", hnd->share_fd, strerror(errno));
|
|
retval = -errno;
|
|
goto cleanup;
|
|
}
|
|
|
|
hnd->base = mappedAddress + hnd->offset;
|
|
hnd->lockState &= ~(private_handle_t::LOCK_STATE_UNREGISTERED);
|
|
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
return 0;
|
|
}
|
|
|
|
cleanup:
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
return retval;
|
|
}
|
|
|
|
static void unmap_buffer(private_handle_t *hnd)
|
|
{
|
|
{
|
|
void *base = static_cast<void *>(hnd->base);
|
|
size_t size = hnd->size;
|
|
|
|
if (munmap(base, size) < 0)
|
|
{
|
|
AERR("Could not munmap base:0x%p size:%lu '%s'", base, (unsigned long)size, strerror(errno));
|
|
}
|
|
}
|
|
|
|
hnd->base = 0;
|
|
hnd->lockState = 0;
|
|
hnd->writeOwner = 0;
|
|
}
|
|
|
|
static int gralloc_unregister_buffer(gralloc_module_t const *module, buffer_handle_t handle)
|
|
{
|
|
MALI_IGNORE(module);
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
{
|
|
AERR("unregistering invalid buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
private_handle_t *hnd = static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle) );
|
|
|
|
AERR_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState);
|
|
|
|
if (hnd->pid == getpid()) // never unmap buffers that were not registered in this process
|
|
{
|
|
pthread_mutex_lock(&s_map_lock);
|
|
|
|
hnd->lockState &= ~(private_handle_t::LOCK_STATE_MAPPED);
|
|
|
|
/* if handle is still locked, the unmapping would not happen until unlocked*/
|
|
if (!(hnd->lockState & private_handle_t::LOCK_STATE_WRITE))
|
|
{
|
|
unmap_buffer(hnd);
|
|
}
|
|
|
|
hnd->lockState |= private_handle_t::LOCK_STATE_UNREGISTERED;
|
|
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
}
|
|
else
|
|
{
|
|
AERR("Trying to unregister buffer 0x%p from process %d that was not created in current process: %d", hnd, hnd->pid, getpid());
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
enum tx_direction
|
|
{
|
|
TX_NONE = 0,
|
|
TX_TO_DEVICE,
|
|
TX_FROM_DEVICE,
|
|
TX_BOTH,
|
|
};
|
|
|
|
/*
|
|
* 根据 'usage' 确定(返回) CUP 将对 buffer 的读写操作.
|
|
*/
|
|
static enum tx_direction get_tx_direction(const uint64_t usage)
|
|
{
|
|
const bool read = (usage & GRALLOC_USAGE_SW_READ_MASK) ? true : false;
|
|
const bool write = (usage & GRALLOC_USAGE_SW_WRITE_MASK) ? true : false;
|
|
enum tx_direction dir = TX_NONE;
|
|
|
|
if (read && write)
|
|
{
|
|
dir = TX_BOTH;
|
|
}
|
|
else if (write)
|
|
{
|
|
dir = TX_TO_DEVICE;
|
|
}
|
|
else if (read)
|
|
{
|
|
dir = TX_FROM_DEVICE;
|
|
}
|
|
|
|
return dir;
|
|
}
|
|
|
|
/*
|
|
* 完成对 buffer cache 的 sync 操作.
|
|
* 'direction':
|
|
* 若是 TX_NONE, 表征当前函数被 unlock() (mali_gralloc_unlock()) 调用.
|
|
* 否则, 表征当前函数被 lock() (mali_gralloc_lock(), ...) 调用,
|
|
* 其 value 表征 lock 后, client 将对 buffer 执行读还是写操作.
|
|
*/
|
|
static void buffer_sync(private_handle_t *hnd, tx_direction direction)
|
|
{
|
|
/* 若本函数被 lock() 调用, 则... */
|
|
if (direction != TX_NONE)
|
|
{
|
|
hnd->cpu_read = direction == TX_FROM_DEVICE || direction == TX_BOTH;
|
|
hnd->cpu_write = direction == TX_TO_DEVICE || direction == TX_BOTH;
|
|
|
|
int status = allocator_sync_start(hnd, hnd->cpu_read, hnd->cpu_write);
|
|
if (status < 0)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
/* 若本函数被 unlock() 调用, 且 CPU 对 buffer 已经有读写操作, 则... */
|
|
else if (hnd->cpu_read || hnd->cpu_write)
|
|
{
|
|
int status = allocator_sync_end(hnd, hnd->cpu_read, hnd->cpu_write);
|
|
if (status < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hnd->cpu_read = 0;
|
|
hnd->cpu_write = 0;
|
|
}
|
|
}
|
|
|
|
static int gralloc_lock(gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void **vaddr)
|
|
{
|
|
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
{
|
|
AERR("Locking invalid buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
private_handle_t *hnd = static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle) );
|
|
|
|
pthread_mutex_lock(&s_map_lock);
|
|
|
|
if (hnd->lockState & private_handle_t::LOCK_STATE_UNREGISTERED)
|
|
{
|
|
AERR("Locking on an unregistered buffer 0x%p, returning error", hnd);
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
return -EINVAL;
|
|
}
|
|
|
|
{
|
|
hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK;
|
|
}
|
|
|
|
hnd->lockState |= private_handle_t::LOCK_STATE_WRITE;
|
|
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
|
|
if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
|
|
{
|
|
*vaddr = static_cast<void *>(hnd->base);
|
|
buffer_sync(hnd,
|
|
get_tx_direction(usage)); // direction
|
|
}
|
|
|
|
MALI_IGNORE(module);
|
|
MALI_IGNORE(l);
|
|
MALI_IGNORE(t);
|
|
MALI_IGNORE(w);
|
|
MALI_IGNORE(h);
|
|
return 0;
|
|
}
|
|
|
|
static int gralloc_lock_ycbcr(gralloc_module_t const* module,
|
|
buffer_handle_t handle,
|
|
int usage,
|
|
int l, int t, int w, int h,
|
|
android_ycbcr *ycbcr)
|
|
{
|
|
if (private_handle_t::validate(handle) < 0)
|
|
{
|
|
AERR("Locking invalid buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
private_handle_t *hnd = static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle) );
|
|
|
|
/*-------------------------------------------------------*/
|
|
|
|
pthread_mutex_lock(&s_map_lock);
|
|
|
|
if (hnd->lockState & private_handle_t::LOCK_STATE_UNREGISTERED)
|
|
{
|
|
AERR("Locking on an unregistered buffer 0x%p, returning error", hnd);
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
return -EINVAL;
|
|
}
|
|
|
|
hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK;
|
|
|
|
hnd->lockState |= private_handle_t::LOCK_STATE_WRITE;
|
|
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
|
|
/*-------------------------------------------------------*/
|
|
|
|
if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
|
|
{
|
|
char *vaddr = static_cast<char *>((hnd->base) );
|
|
buffer_sync(hnd,
|
|
get_tx_direction(usage)); // direction
|
|
|
|
// this is currently only used by camera for yuv420sp
|
|
// if in future other formats are needed, store to private
|
|
// handle and change the below code based on private format.
|
|
|
|
int ystride;
|
|
switch (hnd->format) {
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
|
|
ystride = hnd->stride;
|
|
ycbcr->y = static_cast<void*>(vaddr);
|
|
ycbcr->cr = static_cast<void*>(vaddr + ystride * hnd->height); // 'cr' : V
|
|
ycbcr->cb = static_cast<void*>(vaddr + ystride * hnd->height + 1); // 'cb : U
|
|
ycbcr->ystride = ystride;
|
|
ycbcr->cstride = ystride;
|
|
ycbcr->chroma_step = 2;
|
|
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YCrCb_NV12:
|
|
ystride = hnd->stride;
|
|
ycbcr->y = static_cast<void*>(vaddr);
|
|
ycbcr->cr = static_cast<void*>(vaddr + ystride * hnd->height + 1);
|
|
ycbcr->cb = static_cast<void*>(vaddr + ystride * hnd->height);
|
|
ycbcr->ystride = ystride;
|
|
ycbcr->cstride = ystride;
|
|
ycbcr->chroma_step = 2;
|
|
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
ystride = hnd->stride;
|
|
ycbcr->ystride = ystride;
|
|
ycbcr->cstride = (ystride/2 + 15) & ~15;
|
|
ycbcr->y = static_cast<void*>(vaddr);
|
|
ycbcr->cr = static_cast<void*>(vaddr + ystride * hnd->height);
|
|
ycbcr->cb = static_cast<void*>(vaddr + ystride * hnd->height + ycbcr->cstride * hnd->height/2);
|
|
ycbcr->chroma_step = 1;
|
|
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
|
|
break;
|
|
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
|
ystride = hnd->stride;
|
|
ycbcr->y = static_cast<void*>(vaddr);
|
|
ycbcr->cb = static_cast<void*>(vaddr + ystride * hnd->height);
|
|
ycbcr->cr = static_cast<void*>(vaddr + ystride * hnd->height + 1);
|
|
ycbcr->ystride = ystride;
|
|
ycbcr->cstride = ystride;
|
|
ycbcr->chroma_step = 2;
|
|
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
|
|
break;
|
|
default:
|
|
ALOGE("%s: Invalid format passed: 0x%x", __FUNCTION__, hnd->format);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------*/
|
|
|
|
MALI_IGNORE(module);
|
|
MALI_IGNORE(l);
|
|
MALI_IGNORE(t);
|
|
MALI_IGNORE(w);
|
|
MALI_IGNORE(h);
|
|
return 0;
|
|
}
|
|
|
|
static int gralloc_unlock(gralloc_module_t const *module, buffer_handle_t handle)
|
|
{
|
|
MALI_IGNORE(module);
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
{
|
|
AERR("Unlocking invalid buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
private_handle_t *hnd = static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle) );
|
|
|
|
/*-------------------------------------------------------*/
|
|
pthread_mutex_lock(&s_map_lock);
|
|
|
|
hnd->lockState &= ~(private_handle_t::LOCK_STATE_WRITE);
|
|
|
|
/* if the handle has already been unregistered, unmap it here*/
|
|
if (hnd->lockState & private_handle_t::LOCK_STATE_UNREGISTERED)
|
|
{
|
|
unmap_buffer(hnd);
|
|
}
|
|
|
|
pthread_mutex_unlock(&s_map_lock);
|
|
|
|
/*-------------------------------------------------------*/
|
|
buffer_sync(hnd, TX_NONE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* map rkvdec_scaling_metadata_buf. */
|
|
static inline int gralloc_rsm_map( struct private_handle_t *hnd )
|
|
{
|
|
int rval = -1;
|
|
int prot_flags = PROT_READ | PROT_WRITE;
|
|
|
|
if ( !hnd )
|
|
{
|
|
goto out;
|
|
}
|
|
if ( hnd->rsm_fd < 0 )
|
|
{
|
|
ALOGE("rkvdec_scaling_metadata_buf is not available to be mapped");
|
|
goto out;
|
|
}
|
|
|
|
hnd->rsm_base = mmap( NULL, hnd->rsm_size, prot_flags, MAP_SHARED, hnd->rsm_fd, 0 );
|
|
if(hnd->rsm_base == MAP_FAILED)
|
|
{
|
|
ALOGE("Failed to mmap rkvdec_scaling_metadata_buf err=%s",strerror(errno));
|
|
goto out;
|
|
}
|
|
|
|
rval = 0;
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
/* unmap rkvdec_scaling_metadata_buf. */
|
|
static inline int gralloc_rsm_unmap( struct private_handle_t *hnd )
|
|
{
|
|
int rval = -1;
|
|
|
|
if( !hnd )
|
|
{
|
|
ALOGE("%s: handle is null",__FUNCTION__);
|
|
goto out;
|
|
}
|
|
if( hnd->rsm_base != MAP_FAILED )
|
|
{
|
|
if ( munmap( hnd->rsm_base, hnd->rsm_size ) == 0 )
|
|
{
|
|
hnd->rsm_base = MAP_FAILED;
|
|
rval = 0;
|
|
}
|
|
}
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
* Map the rk_ashmem area before attempting to
|
|
* read/write from it.
|
|
*
|
|
* 'readwrite':
|
|
* 若将对 map 后的 buffer 写入数据, 则要传入 1.
|
|
* 否则, 传入 0.
|
|
*
|
|
* Return 0 on success.
|
|
*/
|
|
static inline int gralloc_rk_ashmem_map( struct private_handle_t *hnd, int readwrite)
|
|
{
|
|
int rval = -1;
|
|
int prot_flags = PROT_READ;
|
|
|
|
if ( !hnd )
|
|
{
|
|
goto out;
|
|
}
|
|
|
|
if ( hnd->ashmem_fd < 0 )
|
|
{
|
|
ALOGE("Shared attribute region not available to be mapped");
|
|
goto out;
|
|
}
|
|
|
|
if ( readwrite )
|
|
{
|
|
prot_flags |= PROT_WRITE;
|
|
}
|
|
|
|
hnd->ashmem_base = mmap( NULL, hnd->ashmem_size, prot_flags, MAP_SHARED, hnd->ashmem_fd, 0 );
|
|
if(hnd->ashmem_base == MAP_FAILED)
|
|
{
|
|
ALOGE("Failed to mmap shared attribute region err=%s",strerror(errno));
|
|
goto out;
|
|
}
|
|
|
|
rval = 0;
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
/*
|
|
* Unmap the rk_ashmem area when done with it.
|
|
*
|
|
* Return 0 on success.
|
|
*/
|
|
static inline int gralloc_rk_ashmem_unmap( struct private_handle_t *hnd )
|
|
{
|
|
int rval = -1;
|
|
|
|
if( !hnd )
|
|
{
|
|
ALOGE("%s:handle is null",__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
if( hnd->ashmem_base != MAP_FAILED )
|
|
{
|
|
if ( munmap( hnd->ashmem_base, hnd->ashmem_size ) == 0 )
|
|
{
|
|
hnd->ashmem_base = MAP_FAILED;
|
|
rval = 0;
|
|
}
|
|
}
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
static inline int gralloc_rk_ashmem_read( struct private_handle_t *hnd, struct rk_ashmem_t *val )
|
|
{
|
|
int rval = -1;
|
|
|
|
if( !hnd || !val )
|
|
{
|
|
ALOGE("%s:parameters is null",__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
if( hnd->ashmem_base != MAP_FAILED )
|
|
{
|
|
memcpy(val, hnd->ashmem_base, sizeof(struct rk_ashmem_t));
|
|
rval = 0;
|
|
}
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
static inline int gralloc_rk_ashmem_write( struct private_handle_t *hnd, struct rk_ashmem_t *val )
|
|
{
|
|
int rval = -1;
|
|
|
|
if( !hnd || !val)
|
|
{
|
|
ALOGE("%s:parameters is null",__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
if( hnd->ashmem_base != MAP_FAILED )
|
|
{
|
|
memcpy(hnd->ashmem_base, val, sizeof(struct rk_ashmem_t));
|
|
rval = 0;
|
|
}
|
|
|
|
out:
|
|
return rval;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static bool is_buffer_unregistered(private_handle_t *handle)
|
|
{
|
|
return (handle->lockState & private_handle_t::LOCK_STATE_UNREGISTERED);
|
|
}
|
|
|
|
// "rk_ashmem_t": 定义在 hardware/libhardware/include/hardware/gralloc.h 中
|
|
// "buffer_handle_t": typedef const native_handle_t* buffer_handle_t;
|
|
static int get_rk_ashmem(buffer_handle_t _handle, struct rk_ashmem_t* rk_ashmem)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if ( NULL == handle )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
AERR("getting rk_ashmem on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (rk_ashmem)
|
|
{
|
|
ret = 0;
|
|
if ( gralloc_rk_ashmem_map(handle, 0) >= 0 )
|
|
{
|
|
if ( gralloc_rk_ashmem_read(handle, rk_ashmem) < 0 )
|
|
{
|
|
ALOGE("%s: gralloc_rk_ashmem_read fail",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
gralloc_rk_ashmem_unmap(handle);
|
|
} else {
|
|
ALOGE("%s: gralloc_rk_ashmem_map fail",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ALOGE("%s: rk_ashmem is null",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int set_rk_ashmem(buffer_handle_t _handle, struct rk_ashmem_t* rk_ashmem)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if ( NULL == handle )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("setting rk_ashmem on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (rk_ashmem)
|
|
{
|
|
ret = 0;
|
|
if ( gralloc_rk_ashmem_map(handle, 1) >= 0 )
|
|
{
|
|
if ( gralloc_rk_ashmem_write(handle, rk_ashmem) < 0 )
|
|
{
|
|
ALOGE("%s: gralloc_rk_ashmem_write fail",__FUNCTION__);
|
|
return -EINVAL;
|
|
}
|
|
gralloc_rk_ashmem_unmap(handle);
|
|
}
|
|
else
|
|
{
|
|
ALOGE("%s: gralloc_rk_ashmem_map fail",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ALOGE("%s: rk_ashmem is null",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int get_prime_fd(buffer_handle_t _handle, int *fd)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting prime_fd on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*fd = handle->share_fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_attributes(buffer_handle_t _handle, void *attrs)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
std::vector<int> *attributes = (std::vector<int> *)attrs;
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting attributes on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
attributes->clear();
|
|
attributes->push_back(handle->width);
|
|
attributes->push_back(handle->height);
|
|
attributes->push_back(handle->pixel_stride);
|
|
attributes->push_back(handle->format);
|
|
attributes->push_back(handle->size);
|
|
attributes->push_back(handle->stride);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_internal_format(buffer_handle_t _handle, uint64_t *internal_format)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting internal_format on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*internal_format = handle->alloc_format;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_width(buffer_handle_t _handle, int *width)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting width on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*width = handle->width;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_height(buffer_handle_t _handle, int *height)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting height on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*height = handle->height;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_pixel_stride(buffer_handle_t _handle, int *pixel_stride)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting pixel_stride on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*pixel_stride = handle->pixel_stride;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_byte_stride(buffer_handle_t _handle, int *byte_stride)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting byte_stride on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*byte_stride = handle->stride;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_format(buffer_handle_t _handle, int *format)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting format on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*format = handle->format;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_size(buffer_handle_t _handle, int *size)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting size on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*size = handle->size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_usage(buffer_handle_t _handle, int *usage)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting usage on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*usage = handle->usage;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int lock_rkvdec_scaling_metadata(buffer_handle_t _handle,
|
|
metadata_for_rkvdec_scaling_t** metadata)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if ( NULL == handle )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
AERR("lock rkvdec_scaling_metadata on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = gralloc_rsm_map(handle);
|
|
if ( ret != 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
*metadata = static_cast<metadata_for_rkvdec_scaling_t*>(handle->rsm_base);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int unlock_rkvdec_scaling_metadata(buffer_handle_t _handle)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if ( NULL == handle )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
AERR("unlock rkvdec_scaling_metadata on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = gralloc_rsm_unmap(handle);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int set_offset_of_dynamic_hdr_metadata(buffer_handle_t _handle, int64_t offset)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if ( NULL == handle )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
AERR("setting offset_of_dynamic_hdr_metadata on an unregistered buffer 0x%p", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( gralloc_rk_ashmem_map(handle, 1) >= 0 )
|
|
{
|
|
if( handle->ashmem_base != MAP_FAILED )
|
|
{
|
|
struct rk_ashmem_t *rk_ashmem = static_cast<struct rk_ashmem_t*>(handle->ashmem_base);
|
|
D("rk_ashmem: %p, "
|
|
"&(rk_ashmem->offset_of_dynamic_hdr_metadata): %p, "
|
|
"sizeof(struct rk_ashmem_t): %zd",
|
|
rk_ashmem,
|
|
&(rk_ashmem->offset_of_dynamic_hdr_metadata),
|
|
sizeof(struct rk_ashmem_t) );
|
|
rk_ashmem->offset_of_dynamic_hdr_metadata = offset;
|
|
}
|
|
|
|
gralloc_rk_ashmem_unmap(handle);
|
|
} else {
|
|
ALOGE("%s: gralloc_rk_ashmem_map fail",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int get_offset_of_dynamic_hdr_metadata(buffer_handle_t _handle, int64_t *offset)
|
|
{
|
|
int ret = 0;
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
struct rk_ashmem_t *rk_ashmem;
|
|
|
|
if ( NULL == handle || NULL == offset )
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
AERR("getting offset_of_dynamic_hdr_metadata on an unregistered buffer 0x%p", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( gralloc_rk_ashmem_map(handle, 0) >= 0 )
|
|
{
|
|
if( handle->ashmem_base != MAP_FAILED )
|
|
{
|
|
rk_ashmem = static_cast<struct rk_ashmem_t*>(handle->ashmem_base);
|
|
*offset = rk_ashmem->offset_of_dynamic_hdr_metadata;
|
|
}
|
|
|
|
gralloc_rk_ashmem_unmap(handle);
|
|
} else {
|
|
ALOGE("%s: gralloc_rk_ashmem_map fail",__FUNCTION__);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int get_buffer_id(buffer_handle_t _handle, uint64_t *buffer_id)
|
|
{
|
|
struct private_handle_t *handle = private_handle_t::dynamicCast(_handle);
|
|
|
|
if (!handle)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
if ( is_buffer_unregistered(handle) )
|
|
{
|
|
E("getting buffer_id on an unregistered buffer 0x%p, returning error", handle);
|
|
return -EINVAL;
|
|
}
|
|
|
|
*buffer_id = handle->backing_store_id;
|
|
|
|
return 0;
|
|
}
|
|
// .CP :
|
|
|
|
static int gralloc_perform(const struct gralloc_module_t *mod, int op, ...)
|
|
{
|
|
MALI_IGNORE(mod);
|
|
va_list args;
|
|
int err;
|
|
|
|
/*-------------------------------------------------------*/
|
|
|
|
va_start(args, op);
|
|
switch (op)
|
|
{
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_RK_ASHMEM):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
struct rk_ashmem_t* rk_ashmem = va_arg(args, struct rk_ashmem_t*);
|
|
|
|
err = get_rk_ashmem(hnd, rk_ashmem);
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_SET_RK_ASHMEM):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
struct rk_ashmem_t* rk_ashmem = va_arg(args, struct rk_ashmem_t*);
|
|
|
|
err = set_rk_ashmem(hnd,rk_ashmem);
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_PHY_ADDR:
|
|
{
|
|
#if 0
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
uint32_t *phy_addr = va_arg(args, uint32_t *);
|
|
|
|
if (phy_addr != NULL)
|
|
err = get_phy_addr(hnd,phy_addr);
|
|
else
|
|
err = -EINVAL;
|
|
#else
|
|
E("not implemented");
|
|
err = -1;
|
|
#endif
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *fd = va_arg(args, int *);
|
|
|
|
if (fd != NULL)
|
|
{
|
|
err = get_prime_fd(hnd, fd);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_ATTRIBUTES:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
std::vector<int> *attrs = va_arg(args, std::vector<int> *);
|
|
|
|
if (attrs != NULL)
|
|
{
|
|
err = get_attributes(hnd, static_cast<void*>(attrs) );
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_INTERNAL_FORMAT:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
uint64_t *internal_format = va_arg(args, uint64_t *);
|
|
|
|
if(internal_format != NULL)
|
|
{
|
|
err = get_internal_format(hnd, internal_format);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_WIDTH:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *width = va_arg(args, int *);
|
|
|
|
if(width != NULL)
|
|
{
|
|
err = get_width(hnd, width);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_HEIGHT:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *height = va_arg(args, int *);
|
|
|
|
if(height != NULL)
|
|
{
|
|
err = get_height(hnd, height);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_STRIDE:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *stride = va_arg(args, int *);
|
|
|
|
if(stride != NULL)
|
|
{
|
|
err = get_pixel_stride(hnd, stride);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_BYTE_STRIDE:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *byte_stride = va_arg(args, int *);
|
|
|
|
if(byte_stride != NULL)
|
|
err = get_byte_stride(hnd, byte_stride);
|
|
else
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_FORMAT:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *format = va_arg(args, int *);
|
|
|
|
if(format != NULL)
|
|
{
|
|
err = get_format(hnd, format);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_HADNLE_SIZE:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *size = va_arg(args, int *);
|
|
|
|
if(size != NULL)
|
|
{
|
|
err = get_size(hnd, size);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GRALLOC_MODULE_PERFORM_GET_USAGE:
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int *usage = va_arg(args, int *);
|
|
|
|
if(usage != NULL)
|
|
{
|
|
err = get_usage(hnd, usage);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_LOCK_RKVDEC_SCALING_METADATA):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
metadata_for_rkvdec_scaling_t** metadata = va_arg(args, metadata_for_rkvdec_scaling_t**);
|
|
|
|
if (metadata != NULL)
|
|
{
|
|
err = lock_rkvdec_scaling_metadata(hnd, metadata);
|
|
if ( err != 0)
|
|
{
|
|
E("err");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
E("err");
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_UNLOCK_RKVDEC_SCALING_METADATA):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
|
|
err = unlock_rkvdec_scaling_metadata(hnd);
|
|
if ( err != 0)
|
|
{
|
|
E("err");
|
|
}
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_SET_OFFSET_OF_DYNAMIC_HDR_METADATA):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int64_t offset = va_arg(args, int64_t);
|
|
|
|
D("offset: %" PRId64, offset);
|
|
err = set_offset_of_dynamic_hdr_metadata(hnd, offset);
|
|
if ( err != 0)
|
|
{
|
|
E("err");
|
|
}
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_OFFSET_OF_DYNAMIC_HDR_METADATA):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
int64_t *offset = va_arg(args, int64_t*);
|
|
|
|
err = get_offset_of_dynamic_hdr_metadata(hnd, offset);
|
|
if ( err != 0)
|
|
{
|
|
E("err");
|
|
}
|
|
|
|
break;
|
|
}
|
|
case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_BUFFER_ID):
|
|
{
|
|
buffer_handle_t hnd = va_arg(args, buffer_handle_t);
|
|
uint64_t *buffer_id = va_arg(args, uint64_t*);
|
|
|
|
if(buffer_id != NULL)
|
|
{
|
|
err = get_buffer_id(hnd, buffer_id);
|
|
}
|
|
else
|
|
{
|
|
err = -EINVAL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
#if 0 // .CP :
|
|
#endif
|
|
default:
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
va_end(args);
|
|
|
|
return err;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
// There is one global instance of the module
|
|
|
|
static struct hw_module_methods_t gralloc_module_methods =
|
|
{
|
|
.open = gralloc_device_open
|
|
};
|
|
|
|
private_module_t::private_module_t()
|
|
{
|
|
#define INIT_ZERO(obj) (memset(&(obj),0,sizeof((obj))))
|
|
|
|
base.common.tag = HARDWARE_MODULE_TAG;
|
|
base.common.version_major = 1;
|
|
base.common.version_minor = 0;
|
|
base.common.id = GRALLOC_HARDWARE_MODULE_ID;
|
|
base.common.name = "Graphics Memory Allocator Module";
|
|
base.common.author = "ARM Ltd.";
|
|
base.common.methods = &gralloc_module_methods;
|
|
base.common.dso = NULL;
|
|
INIT_ZERO(base.common.reserved);
|
|
|
|
base.registerBuffer = gralloc_register_buffer;
|
|
base.unregisterBuffer = gralloc_unregister_buffer;
|
|
base.lock = gralloc_lock;
|
|
base.lock_ycbcr = gralloc_lock_ycbcr;
|
|
base.unlock = gralloc_unlock;
|
|
base.perform = gralloc_perform;
|
|
INIT_ZERO(base.reserved_proc);
|
|
|
|
framebuffer = NULL;
|
|
numBuffers = 0;
|
|
bufferMask = 0;
|
|
pthread_mutex_init(&(lock), NULL);
|
|
currentBuffer = NULL;
|
|
INIT_ZERO(info);
|
|
INIT_ZERO(finfo);
|
|
xdpi = 0.0f;
|
|
ydpi = 0.0f;
|
|
fps = 0.0f;
|
|
|
|
#undef INIT_ZERO
|
|
};
|
|
|
|
/*
|
|
* HAL_MODULE_INFO_SYM will be initialized using the default constructor
|
|
* implemented above
|
|
*/
|
|
struct private_module_t HAL_MODULE_INFO_SYM;
|
|
|