2011-11-16 21:41:37 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
|
|
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above
|
|
|
|
* copyright notice, this list of conditions and the following
|
|
|
|
* disclaimer in the documentation and/or other materials provided
|
|
|
|
* with the distribution.
|
|
|
|
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
|
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <cutils/log.h>
|
|
|
|
#include <utils/RefBase.h>
|
2011-11-19 17:55:49 +00:00
|
|
|
#include <fcntl.h>
|
2011-11-16 21:41:37 +00:00
|
|
|
#include "gralloc_priv.h"
|
|
|
|
#include "alloc_controller.h"
|
|
|
|
#include "memalloc.h"
|
|
|
|
#include "ionalloc.h"
|
2011-11-19 17:55:49 +00:00
|
|
|
#include "pmemalloc.h"
|
|
|
|
#include "ashmemalloc.h"
|
2011-11-16 21:41:37 +00:00
|
|
|
|
|
|
|
using namespace gralloc;
|
|
|
|
using android::sp;
|
|
|
|
|
2011-11-19 17:55:49 +00:00
|
|
|
//Common functions
|
|
|
|
static bool canFallback(int compositionType, int usage, bool triedSystem)
|
2011-11-16 21:41:37 +00:00
|
|
|
{
|
|
|
|
// Fallback to system heap when alloc fails unless
|
|
|
|
// 1. Composition type is MDP
|
|
|
|
// 2. Earlier alloc attempt was from system heap
|
|
|
|
// 3. Contiguous heap requsted explicitly
|
|
|
|
|
|
|
|
if(compositionType == MDP_COMPOSITION)
|
|
|
|
return false;
|
2011-11-19 17:55:49 +00:00
|
|
|
if(triedSystem)
|
2011-11-16 21:41:37 +00:00
|
|
|
return false;
|
|
|
|
if(usage &(GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
|
|
|
|
GRALLOC_USAGE_PRIVATE_EBI_HEAP |
|
|
|
|
GRALLOC_USAGE_PRIVATE_SMI_HEAP))
|
|
|
|
return false;
|
|
|
|
//Return true by default
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-11-19 17:55:49 +00:00
|
|
|
sp<IAllocController> IAllocController::sController = NULL;
|
|
|
|
sp<IAllocController> IAllocController::getInstance(bool useMasterHeap)
|
|
|
|
{
|
|
|
|
if(sController == NULL) {
|
|
|
|
#ifdef USE_ION
|
|
|
|
sController = new IonController();
|
|
|
|
#else
|
|
|
|
if(useMasterHeap)
|
|
|
|
sController = new PmemAshmemController();
|
|
|
|
else
|
|
|
|
sController = new PmemKernelController();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return sController;
|
|
|
|
}
|
|
|
|
|
2011-12-06 04:42:07 +00:00
|
|
|
#ifdef USE_ION
|
2011-11-19 17:55:49 +00:00
|
|
|
|
|
|
|
//-------------- IonController-----------------------//
|
|
|
|
IonController::IonController()
|
|
|
|
{
|
|
|
|
mIonAlloc = new IonAlloc();
|
|
|
|
}
|
|
|
|
|
2011-11-16 21:41:37 +00:00
|
|
|
int IonController::allocate(alloc_data& data, int usage,
|
|
|
|
int compositionType)
|
|
|
|
{
|
|
|
|
int ionFlags = 0;
|
|
|
|
int ret;
|
2011-12-07 05:21:40 +00:00
|
|
|
bool noncontig = false;
|
2011-11-16 21:41:37 +00:00
|
|
|
|
|
|
|
//System heap cannot be uncached
|
|
|
|
if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED &&
|
|
|
|
!(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP))
|
|
|
|
data.uncached = true;
|
|
|
|
else
|
|
|
|
data.uncached = false;
|
|
|
|
|
|
|
|
if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
|
|
|
|
ionFlags |= 1 << ION_HEAP_ADSP_ID;
|
|
|
|
|
|
|
|
if(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)
|
|
|
|
ionFlags |= 1 << ION_HEAP_SMI_ID;
|
|
|
|
|
|
|
|
if(usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP)
|
|
|
|
ionFlags |= 1 << ION_HEAP_EBI_ID;
|
|
|
|
|
2011-12-07 05:21:40 +00:00
|
|
|
if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) {
|
2011-11-16 21:41:37 +00:00
|
|
|
ionFlags |= 1 << ION_HEAP_SYSTEM_ID;
|
2011-12-07 05:21:40 +00:00
|
|
|
noncontig = true;
|
|
|
|
}
|
2011-11-16 21:41:37 +00:00
|
|
|
|
|
|
|
// if no flags are set, default to
|
|
|
|
// EBI heap, so that bypass can work
|
|
|
|
// we can fall back to system heap if
|
|
|
|
// we run out.
|
|
|
|
if(!ionFlags)
|
|
|
|
ionFlags = 1 << ION_HEAP_EBI_ID;
|
|
|
|
|
|
|
|
data.flags = ionFlags;
|
|
|
|
ret = mIonAlloc->alloc_buffer(data);
|
|
|
|
// Fallback
|
2011-11-19 17:55:49 +00:00
|
|
|
if(ret < 0 && canFallback(compositionType,
|
|
|
|
usage,
|
|
|
|
(ionFlags & ION_HEAP_SYSTEM_ID)))
|
|
|
|
{
|
2011-11-16 21:41:37 +00:00
|
|
|
LOGW("Falling back to system heap");
|
|
|
|
data.flags = 1 << ION_HEAP_SYSTEM_ID;
|
2011-12-07 05:21:40 +00:00
|
|
|
noncontig = true;
|
2011-11-16 21:41:37 +00:00
|
|
|
ret = mIonAlloc->alloc_buffer(data);
|
|
|
|
}
|
|
|
|
|
2011-12-07 05:21:40 +00:00
|
|
|
if(ret >= 0 ) {
|
2011-11-16 21:41:37 +00:00
|
|
|
data.allocType = private_handle_t::PRIV_FLAGS_USES_ION;
|
2011-12-07 05:21:40 +00:00
|
|
|
if(noncontig)
|
|
|
|
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
|
|
|
|
}
|
2011-11-16 21:41:37 +00:00
|
|
|
|
2011-12-06 04:42:07 +00:00
|
|
|
|
2011-11-16 21:41:37 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<IMemAlloc> IonController::getAllocator(int flags)
|
|
|
|
{
|
|
|
|
sp<IMemAlloc> memalloc;
|
|
|
|
if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
|
|
|
|
memalloc = mIonAlloc;
|
|
|
|
} else {
|
|
|
|
LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
return memalloc;
|
|
|
|
}
|
2011-12-06 04:42:07 +00:00
|
|
|
#endif
|
2011-11-16 21:41:37 +00:00
|
|
|
|
2011-11-19 17:55:49 +00:00
|
|
|
//-------------- PmemKernelController-----------------------//
|
|
|
|
|
|
|
|
PmemKernelController::PmemKernelController()
|
|
|
|
{
|
|
|
|
mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP);
|
|
|
|
// XXX: Right now, there is no need to maintain an instance
|
|
|
|
// of the SMI allocator as we need it only in a few cases
|
|
|
|
}
|
|
|
|
|
|
|
|
PmemKernelController::~PmemKernelController()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int PmemKernelController::allocate(alloc_data& data, int usage,
|
2011-11-16 21:41:37 +00:00
|
|
|
int compositionType)
|
|
|
|
{
|
2011-11-19 17:55:49 +00:00
|
|
|
int ret = 0;
|
|
|
|
bool adspFallback = false;
|
2011-12-06 06:44:55 +00:00
|
|
|
if (!(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP))
|
|
|
|
adspFallback = true;
|
2011-11-19 17:55:49 +00:00
|
|
|
|
|
|
|
// Try SMI first
|
|
|
|
if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) ||
|
|
|
|
(usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
|
|
|
(usage & GRALLOC_USAGE_PROTECTED))
|
|
|
|
{
|
|
|
|
int tempFd = open(DEVICE_PMEM_SMIPOOL, O_RDWR, 0);
|
|
|
|
if(tempFd > 0) {
|
|
|
|
close(tempFd);
|
|
|
|
sp<IMemAlloc> memalloc;
|
|
|
|
memalloc = new PmemKernelAlloc(DEVICE_PMEM_SMIPOOL);
|
|
|
|
ret = memalloc->alloc_buffer(data);
|
|
|
|
if(ret >= 0)
|
|
|
|
return ret;
|
|
|
|
else {
|
2011-12-06 06:44:55 +00:00
|
|
|
if(adspFallback)
|
|
|
|
LOGW("Allocation from SMI failed, trying ADSP");
|
2011-11-19 17:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || adspFallback) {
|
|
|
|
ret = mPmemAdspAlloc->alloc_buffer(data);
|
|
|
|
}
|
|
|
|
return ret;
|
2011-11-16 21:41:37 +00:00
|
|
|
}
|
|
|
|
|
2011-11-19 17:55:49 +00:00
|
|
|
sp<IMemAlloc> PmemKernelController::getAllocator(int flags)
|
2011-11-16 21:41:37 +00:00
|
|
|
{
|
|
|
|
sp<IMemAlloc> memalloc;
|
2011-11-19 17:55:49 +00:00
|
|
|
if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)
|
|
|
|
memalloc = mPmemAdspAlloc;
|
|
|
|
else {
|
|
|
|
LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
|
2011-11-16 21:41:37 +00:00
|
|
|
memalloc = NULL;
|
2011-11-19 17:55:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return memalloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------- PmemAshmmemController-----------------------//
|
|
|
|
|
|
|
|
PmemAshmemController::PmemAshmemController()
|
|
|
|
{
|
|
|
|
mPmemUserspaceAlloc = new PmemUserspaceAlloc();
|
|
|
|
mAshmemAlloc = new AshmemAlloc();
|
|
|
|
mPmemKernelCtrl = new PmemKernelController();
|
|
|
|
}
|
|
|
|
|
|
|
|
PmemAshmemController::~PmemAshmemController()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int PmemAshmemController::allocate(alloc_data& data, int usage,
|
|
|
|
int compositionType)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
// Decide caching
|
|
|
|
// Decide based on usage
|
|
|
|
uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK;
|
|
|
|
uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
|
|
|
|
if (uread == GRALLOC_USAGE_SW_READ_OFTEN ||
|
|
|
|
uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) {
|
|
|
|
data.uncached = false;
|
2011-11-16 21:41:37 +00:00
|
|
|
} else {
|
2011-11-19 17:55:49 +00:00
|
|
|
data.uncached = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override if we explicitly need uncached buffers
|
|
|
|
if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
|
|
|
|
data.uncached = true;
|
|
|
|
|
|
|
|
// If ADSP or SMI is requested use the kernel controller
|
|
|
|
if(usage & (GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
|
|
|
|
GRALLOC_USAGE_PRIVATE_SMI_HEAP)) {
|
|
|
|
ret = mPmemKernelCtrl->allocate(data, usage, compositionType);
|
|
|
|
if(ret < 0)
|
|
|
|
LOGE("%s: Failed to allocate ADSP/SMI memory", __func__);
|
|
|
|
else
|
|
|
|
data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) {
|
|
|
|
ret = mAshmemAlloc->alloc_buffer(data);
|
2011-12-07 05:21:40 +00:00
|
|
|
if(ret >= 0) {
|
2011-11-19 17:55:49 +00:00
|
|
|
data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM;
|
2011-12-07 05:21:40 +00:00
|
|
|
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
|
|
|
|
}
|
2011-11-19 17:55:49 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if no memory specific flags are set,
|
|
|
|
// default to EBI heap, so that bypass
|
|
|
|
// can work. We can fall back to system
|
|
|
|
// heap if we run out.
|
|
|
|
ret = mPmemUserspaceAlloc->alloc_buffer(data);
|
|
|
|
|
|
|
|
// Fallback
|
|
|
|
if(ret >= 0 ) {
|
|
|
|
data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM;
|
|
|
|
} else if(ret < 0 && canFallback(compositionType, usage, false)) {
|
|
|
|
LOGW("Falling back to ashmem");
|
|
|
|
ret = mAshmemAlloc->alloc_buffer(data);
|
2011-12-07 05:21:40 +00:00
|
|
|
if(ret >= 0) {
|
2011-11-19 17:55:49 +00:00
|
|
|
data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM;
|
2011-12-07 05:21:40 +00:00
|
|
|
data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM;
|
|
|
|
}
|
2011-11-19 17:55:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp<IMemAlloc> PmemAshmemController::getAllocator(int flags)
|
|
|
|
{
|
|
|
|
sp<IMemAlloc> memalloc;
|
|
|
|
if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM)
|
|
|
|
memalloc = mPmemUserspaceAlloc;
|
|
|
|
else if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)
|
|
|
|
memalloc = mPmemKernelCtrl->getAllocator(flags);
|
|
|
|
else if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
|
|
|
|
memalloc = mAshmemAlloc;
|
|
|
|
else {
|
2011-11-16 21:41:37 +00:00
|
|
|
LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
|
|
|
|
memalloc = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return memalloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|