|
|
/* |
|
|
// Copyright (c) 2014 Intel Corporation |
|
|
// |
|
|
// 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. |
|
|
*/ |
|
|
|
|
|
#include <HwcTrace.h> |
|
|
#include <hardware/hwcomposer.h> |
|
|
#include <BufferManager.h> |
|
|
#include <hal_public.h> |
|
|
#include <DrmConfig.h> |
|
|
|
|
|
namespace android { |
|
|
namespace intel { |
|
|
|
|
|
BufferManager::BufferManager() |
|
|
: mGralloc(NULL), |
|
|
mFrameBuffers(), |
|
|
mBufferPool(NULL), |
|
|
mDataBuffer(NULL), |
|
|
mDataBufferLock(), |
|
|
mInitialized(false) |
|
|
{ |
|
|
CTRACE(); |
|
|
} |
|
|
|
|
|
BufferManager::~BufferManager() |
|
|
{ |
|
|
WARN_IF_NOT_DEINIT(); |
|
|
} |
|
|
|
|
|
bool BufferManager::initCheck() const |
|
|
{ |
|
|
return mInitialized; |
|
|
} |
|
|
|
|
|
bool BufferManager::initialize() |
|
|
{ |
|
|
CTRACE(); |
|
|
|
|
|
// create buffer pool |
|
|
mBufferPool = new BufferCache(DEFAULT_BUFFER_POOL_SIZE); |
|
|
if (!mBufferPool) { |
|
|
ETRACE("failed to create gralloc buffer cache"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
// init gralloc module |
|
|
if (gralloc_open_img(&mGralloc)) { |
|
|
DEINIT_AND_RETURN_FALSE("failed to get gralloc module"); |
|
|
} |
|
|
|
|
|
// create a dummy data buffer |
|
|
mDataBuffer = createDataBuffer(0); |
|
|
if (!mDataBuffer) { |
|
|
DEINIT_AND_RETURN_FALSE("failed to create data buffer"); |
|
|
} |
|
|
|
|
|
mInitialized = true; |
|
|
return true; |
|
|
} |
|
|
|
|
|
void BufferManager::deinitialize() |
|
|
{ |
|
|
mInitialized = false; |
|
|
|
|
|
if (mBufferPool) { |
|
|
// unmap & delete all cached buffer mappers |
|
|
for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) { |
|
|
BufferMapper *mapper = mBufferPool->getMapper(i); |
|
|
mapper->unmap(); |
|
|
delete mapper; |
|
|
} |
|
|
|
|
|
delete mBufferPool; |
|
|
mBufferPool = NULL; |
|
|
} |
|
|
|
|
|
for (size_t j = 0; j < mFrameBuffers.size(); j++) { |
|
|
BufferMapper *mapper = mFrameBuffers.valueAt(j); |
|
|
mapper->unmap(); |
|
|
delete mapper; |
|
|
} |
|
|
mFrameBuffers.clear(); |
|
|
|
|
|
if (mGralloc) { |
|
|
gralloc_close_img(mGralloc); |
|
|
mGralloc = NULL; |
|
|
} |
|
|
|
|
|
if (mDataBuffer) { |
|
|
delete mDataBuffer; |
|
|
mDataBuffer = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
void BufferManager::dump(Dump& d) |
|
|
{ |
|
|
d.append("Buffer Manager status: pool size %d\n", mBufferPool->getCacheSize()); |
|
|
d.append("-------------------------------------------------------------\n"); |
|
|
for (uint32_t i = 0; i < mBufferPool->getCacheSize(); i++) { |
|
|
BufferMapper *mapper = mBufferPool->getMapper(i); |
|
|
d.append("Buffer %d: handle %#x, (%dx%d), format %d, refCount %d\n", |
|
|
i, |
|
|
mapper->getHandle(), |
|
|
mapper->getWidth(), |
|
|
mapper->getHeight(), |
|
|
mapper->getFormat(), |
|
|
mapper->getRef()); |
|
|
} |
|
|
return; |
|
|
} |
|
|
|
|
|
DataBuffer* BufferManager::lockDataBuffer(buffer_handle_t handle) |
|
|
{ |
|
|
mDataBufferLock.lock(); |
|
|
mDataBuffer->resetBuffer(handle); |
|
|
return mDataBuffer; |
|
|
} |
|
|
|
|
|
void BufferManager::unlockDataBuffer(DataBuffer *buffer) |
|
|
{ |
|
|
mDataBufferLock.unlock(); |
|
|
} |
|
|
|
|
|
DataBuffer* BufferManager::get(buffer_handle_t handle) |
|
|
{ |
|
|
return createDataBuffer(handle); |
|
|
} |
|
|
|
|
|
void BufferManager::put(DataBuffer *buffer) |
|
|
{ |
|
|
delete buffer; |
|
|
} |
|
|
|
|
|
BufferMapper* BufferManager::map(DataBuffer& buffer) |
|
|
{ |
|
|
bool ret; |
|
|
BufferMapper* mapper; |
|
|
|
|
|
CTRACE(); |
|
|
Mutex::Autolock _l(mLock); |
|
|
//try to get mapper from pool |
|
|
mapper = mBufferPool->getMapper(buffer.getKey()); |
|
|
if (mapper) { |
|
|
// increase mapper ref count |
|
|
mapper->incRef(); |
|
|
return mapper; |
|
|
} |
|
|
|
|
|
// create a new buffer mapper and add it to pool |
|
|
do { |
|
|
VTRACE("new buffer, will add it"); |
|
|
mapper = createBufferMapper(buffer); |
|
|
if (!mapper) { |
|
|
ETRACE("failed to allocate mapper"); |
|
|
break; |
|
|
} |
|
|
ret = mapper->map(); |
|
|
if (!ret) { |
|
|
ETRACE("failed to map"); |
|
|
delete mapper; |
|
|
mapper = NULL; |
|
|
break; |
|
|
} |
|
|
ret = mBufferPool->addMapper(buffer.getKey(), mapper); |
|
|
if (!ret) { |
|
|
ETRACE("failed to add mapper"); |
|
|
break; |
|
|
} |
|
|
// increase mapper ref count |
|
|
mapper->incRef(); |
|
|
return mapper; |
|
|
} while (0); |
|
|
|
|
|
// error handling |
|
|
if (mapper) { |
|
|
mapper->unmap(); |
|
|
delete mapper; |
|
|
} |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
void BufferManager::unmap(BufferMapper *mapper) |
|
|
{ |
|
|
Mutex::Autolock _l(mLock); |
|
|
if (!mapper) { |
|
|
ETRACE("invalid mapper"); |
|
|
return; |
|
|
} |
|
|
|
|
|
// unmap & remove this mapper from buffer when refCount = 0 |
|
|
int refCount = mapper->decRef(); |
|
|
if (refCount < 0) { |
|
|
ETRACE("invalid ref count"); |
|
|
} else if (!refCount) { |
|
|
// remove mapper from buffer pool |
|
|
mBufferPool->removeMapper(mapper); |
|
|
mapper->unmap(); |
|
|
delete mapper; |
|
|
} |
|
|
} |
|
|
|
|
|
buffer_handle_t BufferManager::allocFrameBuffer(int width, int height, int *stride) |
|
|
{ |
|
|
RETURN_NULL_IF_NOT_INIT(); |
|
|
|
|
|
if (!mGralloc) { |
|
|
WTRACE("Alloc device is not available"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
if (!width || !height || !stride) { |
|
|
ETRACE("invalid input parameter"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
ITRACE("size of frame buffer to create: %dx%d", width, height); |
|
|
buffer_handle_t handle = 0; |
|
|
status_t err = gralloc_device_alloc_img( |
|
|
mGralloc, |
|
|
width, |
|
|
height, |
|
|
DrmConfig::getFrameBufferFormat(), |
|
|
0, // GRALLOC_USAGE_HW_FB |
|
|
&handle, |
|
|
stride); |
|
|
|
|
|
if (err != 0) { |
|
|
ETRACE("failed to allocate frame buffer, error = %d", err); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
DataBuffer *buffer = NULL; |
|
|
BufferMapper *mapper = NULL; |
|
|
|
|
|
do { |
|
|
buffer = lockDataBuffer(handle); |
|
|
if (!buffer) { |
|
|
ETRACE("failed to get data buffer, handle = %p", handle); |
|
|
break; |
|
|
} |
|
|
|
|
|
mapper = createBufferMapper(*buffer); |
|
|
if (!mapper) { |
|
|
ETRACE("failed to create buffer mapper"); |
|
|
break; |
|
|
} |
|
|
|
|
|
buffer_handle_t fbHandle; |
|
|
if (!(fbHandle = mapper->getFbHandle(0))) { |
|
|
ETRACE("failed to get Fb handle"); |
|
|
break; |
|
|
} |
|
|
|
|
|
mFrameBuffers.add(fbHandle, mapper); |
|
|
unlockDataBuffer(buffer); |
|
|
return fbHandle; |
|
|
} while (0); |
|
|
|
|
|
// error handling, release all allocated resources |
|
|
if (buffer) { |
|
|
unlockDataBuffer(buffer); |
|
|
} |
|
|
if (mapper) { |
|
|
delete mapper; |
|
|
} |
|
|
gralloc_device_free_img(mGralloc, handle); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
void BufferManager::freeFrameBuffer(buffer_handle_t fbHandle) |
|
|
{ |
|
|
RETURN_VOID_IF_NOT_INIT(); |
|
|
|
|
|
if (!mGralloc) { |
|
|
WTRACE("Alloc device is not available"); |
|
|
return; |
|
|
} |
|
|
|
|
|
ssize_t index = mFrameBuffers.indexOfKey(fbHandle); |
|
|
if (index < 0) { |
|
|
ETRACE("invalid kernel handle"); |
|
|
return; |
|
|
} |
|
|
|
|
|
BufferMapper *mapper = mFrameBuffers.valueAt(index); |
|
|
buffer_handle_t handle = mapper->getHandle(); |
|
|
mapper->putFbHandle(); |
|
|
delete mapper; |
|
|
mFrameBuffers.removeItem(fbHandle); |
|
|
gralloc_device_free_img(mGralloc, handle); |
|
|
} |
|
|
|
|
|
buffer_handle_t BufferManager::allocGrallocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage) |
|
|
{ |
|
|
RETURN_NULL_IF_NOT_INIT(); |
|
|
|
|
|
if (!mGralloc) { |
|
|
WTRACE("Alloc device is not available"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
if (!width || !height) { |
|
|
ETRACE("invalid input parameter"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
ITRACE("size of graphic buffer to create: %dx%d", width, height); |
|
|
buffer_handle_t handle = 0; |
|
|
int stride; |
|
|
status_t err = gralloc_device_alloc_img( |
|
|
mGralloc, |
|
|
width, |
|
|
height, |
|
|
format, |
|
|
usage, |
|
|
&handle, |
|
|
&stride); |
|
|
if (err != 0) { |
|
|
ETRACE("failed to allocate gralloc buffer, error = %d", err); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
return handle; |
|
|
} |
|
|
|
|
|
void BufferManager::freeGrallocBuffer(buffer_handle_t handle) |
|
|
{ |
|
|
RETURN_VOID_IF_NOT_INIT(); |
|
|
if (!mGralloc) { |
|
|
WTRACE("Alloc device is not available"); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (handle) |
|
|
gralloc_device_free_img(mGralloc, handle); |
|
|
} |
|
|
|
|
|
} // namespace intel |
|
|
} // namespace android
|
|
|
|