You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2588 lines
102 KiB
2588 lines
102 KiB
/*
|
|
* Copyright (C) 2012 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.
|
|
*/
|
|
|
|
/**
|
|
* Project HWC 2.0 Design
|
|
*/
|
|
|
|
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
|
|
#include "ExynosResourceManager.h"
|
|
|
|
#include <cutils/properties.h>
|
|
|
|
#include <numeric>
|
|
#include <unordered_set>
|
|
|
|
#include "ExynosDeviceInterface.h"
|
|
#include "ExynosExternalDisplay.h"
|
|
#include "ExynosHWCDebug.h"
|
|
#include "ExynosLayer.h"
|
|
#include "ExynosMPPModule.h"
|
|
#include "ExynosPrimaryDisplayModule.h"
|
|
#include "ExynosVirtualDisplay.h"
|
|
#include "hardware/exynos/acryl.h"
|
|
|
|
using namespace std::chrono_literals;
|
|
constexpr float msecsPerSec = std::chrono::milliseconds(1s).count();
|
|
|
|
#ifndef USE_MODULE_ATTR
|
|
/* Basic supported features */
|
|
feature_support_t feature_table[] =
|
|
{
|
|
{MPP_DPP_G,
|
|
MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_GF,
|
|
MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_VG,
|
|
MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_VGS,
|
|
MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_VGF,
|
|
MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_VGFS,
|
|
MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE | MPP_ATTR_DIM
|
|
},
|
|
|
|
{MPP_DPP_VGRFS,
|
|
MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE |
|
|
MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90 |
|
|
MPP_ATTR_DIM | MPP_ATTR_HDR10
|
|
},
|
|
|
|
{MPP_MSC,
|
|
MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90
|
|
},
|
|
|
|
{MPP_G2D,
|
|
MPP_ATTR_AFBC | MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90 |
|
|
MPP_ATTR_HDR10 | MPP_ATTR_USE_CAPA
|
|
}
|
|
};
|
|
#endif
|
|
|
|
using namespace android;
|
|
using namespace vendor::graphics;
|
|
using namespace SOC_VERSION;
|
|
|
|
ExynosMPPVector ExynosResourceManager::mOtfMPPs;
|
|
ExynosMPPVector ExynosResourceManager::mM2mMPPs;
|
|
extern struct exynos_hwc_control exynosHWCControl;
|
|
|
|
ExynosMPPVector::ExynosMPPVector() {
|
|
}
|
|
|
|
ExynosMPPVector::ExynosMPPVector(const ExynosMPPVector& rhs)
|
|
: android::SortedVector<ExynosMPP* >(rhs) {
|
|
}
|
|
|
|
int ExynosMPPVector::do_compare(const void* lhs, const void* rhs) const
|
|
{
|
|
if (lhs == NULL || rhs == NULL)
|
|
return 0;
|
|
|
|
const ExynosMPP* l = *((ExynosMPP**)(lhs));
|
|
const ExynosMPP* r = *((ExynosMPP**)(rhs));
|
|
|
|
if (l == NULL || r == NULL)
|
|
return 0;
|
|
|
|
if (l->mPhysicalType != r->mPhysicalType) {
|
|
return l->mPhysicalType - r->mPhysicalType;
|
|
}
|
|
|
|
if (l->mLogicalType != r->mLogicalType) {
|
|
return l->mLogicalType - r->mLogicalType;
|
|
}
|
|
|
|
if (l->mPhysicalIndex != r->mPhysicalIndex) {
|
|
return l->mPhysicalIndex - r->mPhysicalIndex;
|
|
}
|
|
|
|
return l->mLogicalIndex - r->mLogicalIndex;
|
|
}
|
|
/**
|
|
* ExynosResourceManager implementation
|
|
*
|
|
*/
|
|
|
|
ExynosResourceManager::DstBufMgrThread::DstBufMgrThread(ExynosResourceManager *exynosResourceManager)
|
|
: mExynosResourceManager(exynosResourceManager),
|
|
mRunning(false),
|
|
mBufXres(0),
|
|
mBufYres(0)
|
|
{
|
|
}
|
|
|
|
ExynosResourceManager::DstBufMgrThread::~DstBufMgrThread()
|
|
{
|
|
}
|
|
|
|
|
|
ExynosResourceManager::ExynosResourceManager(ExynosDevice *device)
|
|
: mForceReallocState(DST_REALLOC_DONE),
|
|
mDevice(device),
|
|
hasHdrLayer(false),
|
|
hasDrmLayer(false),
|
|
mFormatRestrictionCnt(0),
|
|
mDstBufMgrThread(sp<DstBufMgrThread>::make(this)),
|
|
mResourceReserved(0x0)
|
|
{
|
|
|
|
memset(mSizeRestrictionCnt, 0, sizeof(mSizeRestrictionCnt));
|
|
memset(mFormatRestrictions, 0, sizeof(mFormatRestrictions));
|
|
memset(mSizeRestrictions, 0, sizeof(mSizeRestrictions));
|
|
|
|
size_t num_mpp_units = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t);
|
|
for (size_t i = 0; i < num_mpp_units; i++) {
|
|
exynos_mpp_t exynos_mpp = AVAILABLE_OTF_MPP_UNITS[i];
|
|
ALOGI("otfMPP type(%d, %d), physical_index(%d), logical_index(%d)",
|
|
exynos_mpp.physicalType, exynos_mpp.logicalType,
|
|
exynos_mpp.physical_index, exynos_mpp.logical_index);
|
|
ExynosMPP* exynosMPP = new ExynosMPPModule(this, exynos_mpp.physicalType,
|
|
exynos_mpp.logicalType, exynos_mpp.name, exynos_mpp.physical_index,
|
|
exynos_mpp.logical_index, exynos_mpp.pre_assign_info);
|
|
exynosMPP->mMPPType = MPP_TYPE_OTF;
|
|
mOtfMPPs.add(exynosMPP);
|
|
}
|
|
|
|
num_mpp_units = sizeof(AVAILABLE_M2M_MPP_UNITS)/sizeof(exynos_mpp_t);
|
|
for (size_t i = 0; i < num_mpp_units; i++) {
|
|
exynos_mpp_t exynos_mpp = AVAILABLE_M2M_MPP_UNITS[i];
|
|
ALOGI("m2mMPP type(%d, %d), physical_index(%d), logical_index(%d)",
|
|
exynos_mpp.physicalType, exynos_mpp.logicalType,
|
|
exynos_mpp.physical_index, exynos_mpp.logical_index);
|
|
ExynosMPP* exynosMPP = new ExynosMPPModule(this, exynos_mpp.physicalType,
|
|
exynos_mpp.logicalType, exynos_mpp.name, exynos_mpp.physical_index,
|
|
exynos_mpp.logical_index, exynos_mpp.pre_assign_info);
|
|
exynosMPP->mMPPType = MPP_TYPE_M2M;
|
|
mM2mMPPs.add(exynosMPP);
|
|
}
|
|
|
|
ALOGI("mOtfMPPs(%zu), mM2mMPPs(%zu)", mOtfMPPs.size(), mM2mMPPs.size());
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++)
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "otfMPP[%d]", i);
|
|
String8 dumpMPP;
|
|
mOtfMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++)
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "m2mMPP[%d]", i);
|
|
String8 dumpMPP;
|
|
mM2mMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
|
|
mDstBufMgrThread->mRunning = true;
|
|
mDstBufMgrThread->run("DstBufMgrThread");
|
|
}
|
|
|
|
ExynosResourceManager::~ExynosResourceManager()
|
|
{
|
|
for (int32_t i = mOtfMPPs.size(); i-- > 0;) {
|
|
ExynosMPP *exynosMPP = mOtfMPPs[i];
|
|
delete exynosMPP;
|
|
}
|
|
mOtfMPPs.clear();
|
|
for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
|
|
ExynosMPP *exynosMPP = mM2mMPPs[i];
|
|
delete exynosMPP;
|
|
}
|
|
mM2mMPPs.clear();
|
|
|
|
mDstBufMgrThread->mRunning = false;
|
|
mDstBufMgrThread->requestExitAndWait();
|
|
}
|
|
|
|
void ExynosResourceManager::reloadResourceForHWFC()
|
|
{
|
|
for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
|
|
ExynosMPP *exynosMPP = mM2mMPPs[i];
|
|
if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
|
|
(exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
|
|
exynosMPP->reloadResourceForHWFC();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExynosResourceManager::setTargetDisplayLuminance(uint16_t min, uint16_t max)
|
|
{
|
|
for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
|
|
ExynosMPP *exynosMPP = mM2mMPPs[i];
|
|
if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
|
|
(exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
|
|
exynosMPP->setTargetDisplayLuminance(min, max);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExynosResourceManager::setTargetDisplayDevice(int device)
|
|
{
|
|
for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
|
|
ExynosMPP *exynosMPP = mM2mMPPs[i];
|
|
if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
|
|
(exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
|
|
exynosMPP->setTargetDisplayDevice(device);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t ExynosResourceManager::doPreProcessing()
|
|
{
|
|
int32_t ret = NO_ERROR;
|
|
/* Assign m2mMPP's out buffers */
|
|
ExynosDisplay *display = mDevice->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
|
|
if (display == NULL)
|
|
return -EINVAL;
|
|
ret = doAllocDstBufs(display->mXres, display->mYres);
|
|
return ret;
|
|
}
|
|
|
|
void ExynosResourceManager::doReallocDstBufs(uint32_t Xres, uint32_t Yres)
|
|
{
|
|
HDEBUGLOGD(eDebugBuf, "M2M dst alloc call ");
|
|
mDstBufMgrThread->reallocDstBufs(Xres, Yres);
|
|
}
|
|
|
|
bool ExynosResourceManager::DstBufMgrThread::needDstRealloc(uint32_t Xres, uint32_t Yres, ExynosMPP *m2mMPP)
|
|
{
|
|
bool ret = false;
|
|
if (((Xres == 720 && Yres == 1480) && (m2mMPP->getDstAllocSize() != DST_SIZE_HD_PLUS)) ||
|
|
((Xres == 720 && Yres == 1280) && (m2mMPP->getDstAllocSize() != DST_SIZE_HD)) ||
|
|
((Xres == 1080 && Yres == 2220) && (m2mMPP->getDstAllocSize() != DST_SIZE_FHD_PLUS)) ||
|
|
((Xres == 1080 && Yres == 1920) && (m2mMPP->getDstAllocSize() != DST_SIZE_FHD)) ||
|
|
((Xres == 1440 && Yres == 2960) && (m2mMPP->getDstAllocSize() != DST_SIZE_WQHD_PLUS)) ||
|
|
((Xres == 1440 && Yres == 2560) && (m2mMPP->getDstAllocSize() != DST_SIZE_WQHD))) {
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ExynosResourceManager::DstBufMgrThread::reallocDstBufs(uint32_t Xres, uint32_t Yres)
|
|
{
|
|
bool needRealloc = false;
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->needPreAllocation())
|
|
{
|
|
if (needDstRealloc(Xres, Yres, mM2mMPPs[i])) {
|
|
HDEBUGLOGD(eDebugBuf, "M2M dst alloc : %d Realloc Start ++++++", mM2mMPPs[i]->mLogicalType);
|
|
needRealloc = true;
|
|
}
|
|
else HDEBUGLOGD(eDebugBuf, "M2M dst alloc : %d MPP's DST Realloc is not needed : Size is same", mM2mMPPs[i]->mLogicalType);
|
|
}
|
|
}
|
|
|
|
if (needRealloc) {
|
|
Mutex::Autolock lock(mStateMutex);
|
|
if (mExynosResourceManager->mForceReallocState == DST_REALLOC_DONE) {
|
|
mExynosResourceManager->mForceReallocState = DST_REALLOC_START;
|
|
android::Mutex::Autolock lock(mMutex);
|
|
mCondition.signal();
|
|
} else {
|
|
HDEBUGLOGD(eDebugBuf, "M2M dst alloc thread : queue aready.");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ExynosResourceManager::DstBufMgrThread::threadLoop()
|
|
{
|
|
while(mRunning) {
|
|
Mutex::Autolock lock(mMutex);
|
|
mCondition.wait(mMutex);
|
|
|
|
ExynosDevice *device = mExynosResourceManager->mDevice;
|
|
if (device == NULL)
|
|
return false;
|
|
ExynosDisplay *display = device->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
|
|
if (display == NULL)
|
|
return false;
|
|
|
|
do {
|
|
{
|
|
HDEBUGLOGD(eDebugBuf, "M2M dst alloc %d, %d, %d, %d : Realloc On going ----------",
|
|
mBufXres, display->mXres, mBufYres, display->mYres);
|
|
Mutex::Autolock lock(mResInfoMutex);
|
|
mBufXres = display->mXres;mBufYres = display->mYres;
|
|
}
|
|
mExynosResourceManager->doAllocDstBufs(mBufXres, mBufYres);
|
|
} while (mBufXres != display->mXres || mBufYres != display->mYres);
|
|
|
|
{
|
|
Mutex::Autolock lock(mStateMutex);
|
|
mExynosResourceManager->mForceReallocState = DST_REALLOC_DONE;
|
|
HDEBUGLOGD(eDebugBuf, "M2M dst alloc %d, %d, %d, %d : Realloc On Done ----------",
|
|
mBufXres, display->mXres, mBufYres, display->mYres);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::doAllocDstBufs(uint32_t Xres, uint32_t Yres)
|
|
{
|
|
ATRACE_CALL();
|
|
int32_t ret = NO_ERROR;
|
|
/* Assign m2mMPP's out buffers */
|
|
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->needPreAllocation())
|
|
{
|
|
mM2mMPPs[i]->mFreeOutBufFlag = false;
|
|
for (uint32_t index = 0; index < NUM_MPP_DST_BUFS(mM2mMPPs[i]->mLogicalType); index++) {
|
|
HDEBUGLOGD(eDebugBuf, "%s allocate dst buffer[%d]%p, x: %d, y: %d",
|
|
__func__, index, mM2mMPPs[i]->mDstImgs[index].bufferHandle, Xres, Yres);
|
|
uint32_t bufAlign = mM2mMPPs[i]->getOutBufAlign();
|
|
ret = mM2mMPPs[i]->allocOutBuf(ALIGN_UP(Xres, bufAlign),
|
|
ALIGN_UP(Yres, bufAlign),
|
|
DEFAULT_MPP_DST_FORMAT, 0x0, index);
|
|
if (ret < 0) {
|
|
HWC_LOGE(NULL, "%s:: fail to allocate dst buffer[%d]",
|
|
__func__, index);
|
|
return ret;
|
|
}
|
|
mM2mMPPs[i]->mPrevAssignedDisplayType = HWC_DISPLAY_PRIMARY;
|
|
}
|
|
mM2mMPPs[i]->setDstAllocSize(Xres, Yres);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::checkScenario(ExynosDisplay __unused *display)
|
|
{
|
|
uint32_t prevResourceReserved = mResourceReserved;
|
|
mResourceReserved = 0x0;
|
|
/* Check whether camera preview is running */
|
|
ExynosDisplay *exynosDisplay = NULL;
|
|
for (uint32_t i = 0; i < mDevice->mDisplays.size(); i++) {
|
|
exynosDisplay = mDevice->mDisplays[i];
|
|
if ((exynosDisplay != NULL) && (exynosDisplay->mPlugState == true)) {
|
|
for (uint32_t i = 0; i < exynosDisplay->mLayers.size(); i++) {
|
|
ExynosLayer *layer = exynosDisplay->mLayers[i];
|
|
VendorGraphicBufferMeta gmeta(layer->mLayerBuffer);
|
|
if ((layer->mLayerBuffer != NULL) &&
|
|
(gmeta.producer_usage & BufferUsage::CAMERA_OUTPUT)) {
|
|
mResourceReserved |= (MPP_LOGICAL_G2D_YUV | MPP_LOGICAL_G2D_RGB);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
char value[PROPERTY_VALUE_MAX];
|
|
bool preview;
|
|
property_get("persist.vendor.sys.camera.preview", value, "0");
|
|
preview = !!atoi(value);
|
|
if (preview)
|
|
mResourceReserved |= (MPP_LOGICAL_G2D_YUV | MPP_LOGICAL_G2D_RGB);
|
|
|
|
if (prevResourceReserved != mResourceReserved) {
|
|
mDevice->setGeometryChanged(GEOMETRY_DEVICE_SCENARIO_CHANGED);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/**
|
|
* @param * display
|
|
* @return int
|
|
*/
|
|
int32_t ExynosResourceManager::assignResource(ExynosDisplay *display)
|
|
{
|
|
ATRACE_CALL();
|
|
int ret = 0;
|
|
if ((mDevice == NULL) || (display == NULL))
|
|
return -EINVAL;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager|eDebugSkipResourceAssign, "mGeometryChanged(0x%" PRIx64 "), display(%d)",
|
|
mDevice->mGeometryChanged, display->mType);
|
|
|
|
if (mDevice->mGeometryChanged == 0) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
display->mLayers[i]->resetValidateData();
|
|
}
|
|
|
|
display->initializeValidateInfos();
|
|
|
|
if ((ret = preProcessLayer(display)) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: preProcessLayer() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (mDevice->isFirstValidate()) {
|
|
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
|
|
if (exynosHWCControl.displayMode < DISPLAY_MODE_NUM)
|
|
mDevice->mDisplayMode = exynosHWCControl.displayMode;
|
|
|
|
if ((ret = prepareResources()) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: prepareResources() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
preAssignWindows();
|
|
|
|
}
|
|
|
|
if ((ret = updateSupportedMPPFlag(display)) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: updateSupportedMPPFlag() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
if ((ret = assignResourceInternal(display)) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: assignResourceInternal() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
if ((ret = assignWindow(display)) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: assignWindow() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
HDEBUGLOGD(eDebugResourceManager, "AssignResource result");
|
|
String8 result;
|
|
display->mClientCompositionInfo.dump(result);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
|
|
result.clear();
|
|
display->mExynosCompositionInfo.dump(result);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
result.clear();
|
|
HDEBUGLOGD(eDebugResourceManager, "%d layer(%p) dump", i, display->mLayers[i]);
|
|
display->mLayers[i]->printLayer();
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
|
|
}
|
|
}
|
|
|
|
if (mDevice->isLastValidate(display)) {
|
|
if ((ret = finishAssignResourceWork()) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: finishAssignResourceWork() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if (!display->mUseDpu) {
|
|
if (display->mClientCompositionInfo.mHasCompositionLayer) {
|
|
if ((ret = display->mExynosCompositionInfo.mM2mMPP->assignMPP(display, &display->mClientCompositionInfo)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, display->mExynosCompositionInfo.mM2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
int prevHasCompositionLayer = display->mExynosCompositionInfo.mHasCompositionLayer;
|
|
display->mExynosCompositionInfo.mHasCompositionLayer = true;
|
|
// if prevHasCompositionLayer is false, setResourcePriority is not called
|
|
if (prevHasCompositionLayer == false)
|
|
setResourcePriority(display);
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::setResourcePriority(ExynosDisplay *display)
|
|
{
|
|
int ret = NO_ERROR;
|
|
int check_ret = NO_ERROR;
|
|
ExynosMPP *m2mMPP = NULL;
|
|
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
|
|
(layer->mM2mMPP != NULL) &&
|
|
(layer->mM2mMPP->mPhysicalType == MPP_G2D) &&
|
|
((check_ret = layer->mM2mMPP->prioritize(2)) != NO_ERROR)) {
|
|
if (check_ret < 0) {
|
|
HWC_LOGE(display, "Fail to set exynoscomposition priority(%d)", ret);
|
|
} else {
|
|
m2mMPP = layer->mM2mMPP;
|
|
layer->resetAssignedResource();
|
|
layer->mOverlayInfo |= eResourcePendingWork;
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
|
|
ret = EXYNOS_ERROR_CHANGED;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of panding work",
|
|
m2mMPP->mName.string());
|
|
m2mMPP->reserveMPP();
|
|
layer->mCheckMPPFlag[m2mMPP->mLogicalType] = eMPPHWBusy;
|
|
}
|
|
}
|
|
}
|
|
|
|
m2mMPP = display->mExynosCompositionInfo.mM2mMPP;
|
|
ExynosCompositionInfo &compositionInfo = display->mExynosCompositionInfo;
|
|
if (compositionInfo.mHasCompositionLayer == true)
|
|
{
|
|
if ((m2mMPP == NULL) || (m2mMPP->mAcrylicHandle == NULL)) {
|
|
HWC_LOGE(display, "There is exynos composition layers but resource is null (%p)",
|
|
m2mMPP);
|
|
} else if ((check_ret = m2mMPP->prioritize(2)) != NO_ERROR) {
|
|
HDEBUGLOGD(eDebugResourceManager, "%s setting priority error(%d)", m2mMPP->mName.string(), check_ret);
|
|
if (check_ret < 0) {
|
|
HWC_LOGE(display, "Fail to set exynoscomposition priority(%d)", ret);
|
|
} else {
|
|
if (display->mExynosCompositionInfo.mFirstIndex >= 0) {
|
|
uint32_t firstIndex = (uint32_t)display->mExynosCompositionInfo.mFirstIndex;
|
|
uint32_t lastIndex = (uint32_t)display->mExynosCompositionInfo.mLastIndex;
|
|
for (uint32_t i = firstIndex; i <= lastIndex; i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
layer->resetAssignedResource();
|
|
layer->mOverlayInfo |= eResourcePendingWork;
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
|
|
layer->mCheckMPPFlag[m2mMPP->mLogicalType] = eMPPHWBusy;
|
|
}
|
|
}
|
|
compositionInfo.initializeInfos(display);
|
|
ret = EXYNOS_ERROR_CHANGED;
|
|
m2mMPP->resetUsedCapacity();
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of pending work",
|
|
m2mMPP->mName.string());
|
|
m2mMPP->reserveMPP();
|
|
}
|
|
} else {
|
|
HDEBUGLOGD(eDebugResourceManager, "%s setting priority is ok", m2mMPP->mName.string());
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::assignResourceInternal(ExynosDisplay *display)
|
|
{
|
|
int ret = NO_ERROR;
|
|
int retry_count = 0;
|
|
|
|
Mutex::Autolock lock(mDstBufMgrThread->mStateMutex);
|
|
|
|
/*
|
|
* First add layers that SF requested HWC2_COMPOSITION_CLIENT type
|
|
* to client composition
|
|
*/
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
if (layer->mCompositionType == HWC2_COMPOSITION_CLIENT) {
|
|
layer->mOverlayInfo |= eSkipLayer;
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
|
|
if (((ret = display->addClientCompositionLayer(i)) != NO_ERROR) &&
|
|
(ret != EXYNOS_ERROR_CHANGED)) {
|
|
HWC_LOGE(display, "Handle HWC2_COMPOSITION_CLIENT type layers, but addClientCompositionLayer failed (%d)", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
do {
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: retry_count(%d)", __func__, retry_count);
|
|
if ((ret = resetAssignedResources(display)) != NO_ERROR)
|
|
return ret;
|
|
if ((ret = assignCompositionTarget(display, COMPOSITION_CLIENT)) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: Fail to assign resource for compositionTarget",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
|
|
if ((ret = assignLayers(display, ePriorityMax)) != NO_ERROR) {
|
|
if (ret == EXYNOS_ERROR_CHANGED) {
|
|
retry_count++;
|
|
continue;
|
|
} else {
|
|
HWC_LOGE(display, "%s:: Fail to assign resource for ePriorityMax layer",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if ((ret = assignLayers(display, ePriorityHigh)) != NO_ERROR) {
|
|
if (ret == EXYNOS_ERROR_CHANGED) {
|
|
retry_count++;
|
|
continue;
|
|
} else {
|
|
HWC_LOGE(display, "%s:: Fail to assign resource for ePriorityHigh layer",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if ((ret = assignCompositionTarget(display, COMPOSITION_EXYNOS)) != NO_ERROR) {
|
|
if (ret == eInsufficientMPP) {
|
|
/*
|
|
* Change compositionTypes to HWC2_COMPOSITION_CLIENT
|
|
*/
|
|
uint32_t firstIndex = (uint32_t)display->mExynosCompositionInfo.mFirstIndex;
|
|
uint32_t lastIndex = (uint32_t)display->mExynosCompositionInfo.mLastIndex;
|
|
for (uint32_t i = firstIndex; i <= lastIndex; i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
layer->resetAssignedResource();
|
|
layer->mOverlayInfo |= eInsufficientMPP;
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
|
|
if (((ret = display->addClientCompositionLayer(i)) != NO_ERROR) &&
|
|
(ret != EXYNOS_ERROR_CHANGED)) {
|
|
HWC_LOGE(display, "Change compositionTypes to HWC2_COMPOSITION_CLIENT, but addClientCompositionLayer failed (%d)", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
display->mExynosCompositionInfo.initializeInfos(display);
|
|
ret = EXYNOS_ERROR_CHANGED;
|
|
} else {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if (ret == NO_ERROR) {
|
|
for (int32_t i = ePriorityHigh - 1; i > ePriorityNone; i--) {
|
|
if ((ret = assignLayers(display, i)) == EXYNOS_ERROR_CHANGED)
|
|
break;
|
|
if (ret != NO_ERROR)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* Assignment is done */
|
|
if (ret == NO_ERROR) {
|
|
ret = setResourcePriority(display);
|
|
}
|
|
retry_count++;
|
|
} while((ret == EXYNOS_ERROR_CHANGED) && (retry_count < ASSIGN_RESOURCE_TRY_COUNT));
|
|
|
|
if (retry_count == ASSIGN_RESOURCE_TRY_COUNT) {
|
|
HWC_LOGE(display, "%s:: assign resources fail", __func__);
|
|
ret = eUnknown;
|
|
return ret;
|
|
} else {
|
|
if ((ret = updateExynosComposition(display)) != NO_ERROR)
|
|
return ret;
|
|
if ((ret = updateClientComposition(display)) != NO_ERROR)
|
|
return ret;
|
|
}
|
|
|
|
if (hwcCheckDebugMessages(eDebugCapacity)) {
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mPhysicalType == MPP_G2D)
|
|
{
|
|
String8 dumpMPP;
|
|
mM2mMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugCapacity, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
|
|
{
|
|
int ret = NO_ERROR;
|
|
/* Use Exynos composition as many as possible */
|
|
if ((display->mExynosCompositionInfo.mHasCompositionLayer == true) &&
|
|
(display->mExynosCompositionInfo.mM2mMPP != NULL)) {
|
|
if (display->mDisplayControl.useMaxG2DSrc == 1) {
|
|
ExynosMPP *m2mMPP = display->mExynosCompositionInfo.mM2mMPP;
|
|
uint32_t lastIndex = display->mExynosCompositionInfo.mLastIndex;
|
|
uint32_t firstIndex = display->mExynosCompositionInfo.mFirstIndex;
|
|
uint32_t remainNum = m2mMPP->mMaxSrcLayerNum - (lastIndex - firstIndex + 1);
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d++++",
|
|
firstIndex, lastIndex, remainNum);
|
|
|
|
ExynosLayer *layer = NULL;
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
if (remainNum > 0) {
|
|
for (uint32_t i = (lastIndex + 1); i < display->mLayers.size(); i++)
|
|
{
|
|
layer = display->mLayers[i];
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
layer->setExynosImage(src_img, dst_img);
|
|
bool isAssignable = false;
|
|
if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
|
|
isAssignable = m2mMPP->isAssignable(display, src_img, dst_img);
|
|
|
|
bool canChange = (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT) &&
|
|
((display->mDisplayControl.cursorSupport == false) ||
|
|
(layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
|
|
(layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignable;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
|
|
i, layer->mValidateCompositionType,
|
|
layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
|
|
if (canChange) {
|
|
layer->resetAssignedResource();
|
|
layer->mOverlayInfo |= eUpdateExynosComposition;
|
|
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, m2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
layer->setExynosMidImage(dst_img);
|
|
display->addExynosCompositionLayer(i);
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
|
|
remainNum--;
|
|
}
|
|
if ((canChange == false) || (remainNum == 0))
|
|
break;
|
|
}
|
|
}
|
|
if (remainNum > 0) {
|
|
for (int32_t i = (firstIndex - 1); i >= 0; i--)
|
|
{
|
|
layer = display->mLayers[i];
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
layer->setExynosImage(src_img, dst_img);
|
|
bool isAssignable = false;
|
|
if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
|
|
isAssignable = m2mMPP->isAssignable(display, src_img, dst_img);
|
|
|
|
bool canChange = (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT) &&
|
|
((display->mDisplayControl.cursorSupport == false) ||
|
|
(layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
|
|
(layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignable;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
|
|
i, layer->mValidateCompositionType,
|
|
layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
|
|
if (canChange) {
|
|
layer->resetAssignedResource();
|
|
layer->mOverlayInfo |= eUpdateExynosComposition;
|
|
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, m2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
layer->setExynosMidImage(dst_img);
|
|
display->addExynosCompositionLayer(i);
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
|
|
remainNum--;
|
|
}
|
|
if ((canChange == false) || (remainNum == 0))
|
|
break;
|
|
}
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d-----",
|
|
display->mExynosCompositionInfo.mFirstIndex, display->mExynosCompositionInfo.mLastIndex, remainNum);
|
|
}
|
|
|
|
/*
|
|
* Check if there is only one exynos composition layer
|
|
* Then it is not composition and m2mMPP is not required
|
|
* if internalMPP can process the layer alone.
|
|
*/
|
|
ExynosMPP *otfMPP = display->mExynosCompositionInfo.mOtfMPP;
|
|
if ((display->mDisplayControl.enableExynosCompositionOptimization == true) &&
|
|
(otfMPP != NULL) &&
|
|
(display->mExynosCompositionInfo.mFirstIndex >= 0) &&
|
|
(display->mExynosCompositionInfo.mFirstIndex == display->mExynosCompositionInfo.mLastIndex))
|
|
{
|
|
ExynosLayer* layer = display->mLayers[display->mExynosCompositionInfo.mFirstIndex];
|
|
if (layer->mSupportedMPPFlag & otfMPP->mLogicalType) {
|
|
layer->resetAssignedResource();
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
|
|
display->mExynosCompositionInfo.initializeInfos(display);
|
|
// reset otfMPP
|
|
if ((ret = otfMPP->resetAssignedState()) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP resetAssignedState() error (%d)",
|
|
__func__, otfMPP->mName.string(), ret);
|
|
}
|
|
// assign otfMPP again
|
|
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, otfMPP->mName.string(), ret);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::changeLayerFromClientToDevice(ExynosDisplay *display, ExynosLayer *layer,
|
|
uint32_t layer_index, exynos_image m2m_out_img, ExynosMPP *m2mMPP, ExynosMPP *otfMPP)
|
|
{
|
|
int ret = NO_ERROR;
|
|
if ((ret = display->removeClientCompositionLayer(layer_index)) != NO_ERROR) {
|
|
ALOGD("removeClientCompositionLayer return error(%d)", ret);
|
|
return ret;
|
|
}
|
|
if (otfMPP != NULL) {
|
|
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, otfMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
|
|
layer_index, otfMPP->mName.string());
|
|
}
|
|
if (m2mMPP != NULL) {
|
|
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, m2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
layer->setExynosMidImage(m2m_out_img);
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
|
|
layer_index, m2mMPP->mName.string());
|
|
}
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
|
|
display->mWindowNumUsed++;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: mWindowNumUsed(%d)",
|
|
layer_index, display->mWindowNumUsed);
|
|
|
|
return ret;
|
|
}
|
|
int32_t ExynosResourceManager::updateClientComposition(ExynosDisplay *display)
|
|
{
|
|
int ret = NO_ERROR;
|
|
|
|
if (display->mDisplayControl.enableClientCompositionOptimization == false)
|
|
return ret;
|
|
|
|
if ((exynosHWCControl.forceGpu == 1) ||
|
|
(display->mClientCompositionInfo.mHasCompositionLayer == false))
|
|
return ret;
|
|
|
|
/* Check if there is layer that can be handled by overlay */
|
|
int32_t firstIndex = display->mClientCompositionInfo.mFirstIndex;
|
|
int32_t lastIndex = display->mClientCompositionInfo.mLastIndex;
|
|
|
|
/* Don't optimize if only low fps layers are composited by GLES */
|
|
if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
|
|
(display->mLowFpsLayerInfo.mFirstIndex == firstIndex) &&
|
|
(display->mLowFpsLayerInfo.mLastIndex == lastIndex))
|
|
return ret;
|
|
|
|
for (int32_t i = firstIndex; i <= lastIndex; i++) {
|
|
ExynosMPP *m2mMPP = NULL;
|
|
ExynosMPP *otfMPP = NULL;
|
|
exynos_image m2m_out_img;
|
|
uint32_t overlayInfo = 0;
|
|
int32_t compositionType = 0;
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
if ((layer->mOverlayPriority >= ePriorityHigh) &&
|
|
(layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
|
|
display->mClientCompositionInfo.mFirstIndex++;
|
|
continue;
|
|
}
|
|
compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, overlayInfo);
|
|
if (compositionType == HWC2_COMPOSITION_DEVICE) {
|
|
/*
|
|
* Don't allocate G2D
|
|
* Execute can be fail because of other job
|
|
* Prioritizing is required to allocate G2D
|
|
*/
|
|
if ((m2mMPP != NULL) && (m2mMPP->mPhysicalType == MPP_G2D))
|
|
break;
|
|
|
|
if ((ret = changeLayerFromClientToDevice(display, layer, i, m2m_out_img, m2mMPP, otfMPP)) != NO_ERROR)
|
|
return ret;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
firstIndex = display->mClientCompositionInfo.mFirstIndex;
|
|
lastIndex = display->mClientCompositionInfo.mLastIndex;
|
|
for (int32_t i = lastIndex; i >= 0; i--) {
|
|
ExynosMPP *m2mMPP = NULL;
|
|
ExynosMPP *otfMPP = NULL;
|
|
exynos_image m2m_out_img;
|
|
uint32_t overlayInfo = 0;
|
|
int32_t compositionType = 0;
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
if ((layer->mOverlayPriority >= ePriorityHigh) &&
|
|
(layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
|
|
display->mClientCompositionInfo.mLastIndex--;
|
|
continue;
|
|
}
|
|
compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, overlayInfo);
|
|
if (compositionType == HWC2_COMPOSITION_DEVICE) {
|
|
/*
|
|
* Don't allocate G2D
|
|
* Execute can be fail because of other job
|
|
* Prioritizing is required to allocate G2D
|
|
*/
|
|
if ((m2mMPP != NULL) && (m2mMPP->mPhysicalType == MPP_G2D))
|
|
break;
|
|
if ((ret = changeLayerFromClientToDevice(display, layer, i, m2m_out_img, m2mMPP, otfMPP)) != NO_ERROR)
|
|
return ret;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::resetAssignedResources(ExynosDisplay * display, bool forceReset)
|
|
{
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (mOtfMPPs[i]->mAssignedDisplay != display)
|
|
continue;
|
|
|
|
mOtfMPPs[i]->resetAssignedState();
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mAssignedDisplay != display)
|
|
continue;
|
|
if ((forceReset == false) &&
|
|
((mM2mMPPs[i]->mLogicalType == MPP_LOGICAL_G2D_RGB) ||
|
|
(mM2mMPPs[i]->mLogicalType == MPP_LOGICAL_G2D_COMBO)))
|
|
{
|
|
/*
|
|
* Don't reset assigned state
|
|
*/
|
|
continue;
|
|
}
|
|
mM2mMPPs[i]->resetAssignedState();
|
|
}
|
|
display->mWindowNumUsed = 0;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::assignCompositionTarget(ExynosDisplay * display, uint32_t targetType)
|
|
{
|
|
int32_t ret = NO_ERROR;
|
|
ExynosCompositionInfo *compositionInfo;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: display(%d), targetType(%d) +++++",
|
|
__func__, display->mType, targetType);
|
|
|
|
if (targetType == COMPOSITION_CLIENT)
|
|
compositionInfo = &(display->mClientCompositionInfo);
|
|
else if (targetType == COMPOSITION_EXYNOS)
|
|
compositionInfo = &(display->mExynosCompositionInfo);
|
|
else
|
|
return -EINVAL;
|
|
|
|
if (compositionInfo->mHasCompositionLayer == false)
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "\tthere is no composition layers");
|
|
return NO_ERROR;
|
|
}
|
|
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
display->setCompositionTargetExynosImage(targetType, &src_img, &dst_img);
|
|
|
|
if (targetType == COMPOSITION_EXYNOS) {
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if ((display->mUseDpu == true) &&
|
|
(mM2mMPPs[i]->mLogicalType != MPP_LOGICAL_G2D_RGB))
|
|
continue;
|
|
if ((display->mUseDpu == false) &&
|
|
(mM2mMPPs[i]->mLogicalType != MPP_LOGICAL_G2D_COMBO))
|
|
continue;
|
|
if (mM2mMPPs[i]->isAssignableState(display, src_img, dst_img)) {
|
|
/* assignMPP(display, compositionInfo) is not called hear
|
|
* assignMPP() was called already during assigning layer
|
|
* Source of M2mMPP should be Layer, not composition target buffer*/
|
|
compositionInfo->mM2mMPP = mM2mMPPs[i];
|
|
}
|
|
}
|
|
if (compositionInfo->mM2mMPP == NULL) {
|
|
HWC_LOGE(display, "%s:: fail to assign M2mMPP (%d)",__func__, ret);
|
|
return eInsufficientMPP;
|
|
}
|
|
}
|
|
|
|
if ((compositionInfo->mFirstIndex < 0) ||
|
|
(compositionInfo->mLastIndex < 0)) {
|
|
HWC_LOGE(display, "%s:: layer index is not valid mFirstIndex(%d), mLastIndex(%d)",
|
|
__func__, compositionInfo->mFirstIndex, compositionInfo->mLastIndex);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (display->mUseDpu == false) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int64_t isSupported = 0;
|
|
bool isAssignable = false;
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
isSupported = mOtfMPPs[i]->isSupported(*display, src_img, dst_img);
|
|
if (isSupported == NO_ERROR)
|
|
isAssignable = mOtfMPPs[i]->isAssignable(display, src_img, dst_img);
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
|
|
mOtfMPPs[i]->mName.string(), -isSupported, isAssignable);
|
|
if ((isSupported == NO_ERROR) && (isAssignable)) {
|
|
if ((ret = mOtfMPPs[i]->assignMPP(display, compositionInfo)) != NO_ERROR)
|
|
{
|
|
HWC_LOGE(display, "%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, mOtfMPPs[i]->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
compositionInfo->setExynosImage(src_img, dst_img);
|
|
compositionInfo->setExynosMidImage(dst_img);
|
|
compositionInfo->mOtfMPP = mOtfMPPs[i];
|
|
display->mWindowNumUsed++;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: %s is assigned", __func__, mOtfMPPs[i]->mName.string());
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: insufficient MPP", __func__);
|
|
return eInsufficientMPP;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::validateLayer(uint32_t index, ExynosDisplay *display, ExynosLayer *layer)
|
|
{
|
|
if ((layer == NULL) || (display == NULL))
|
|
return eUnknown;
|
|
|
|
if (exynosHWCControl.forceGpu == 1) {
|
|
if ((layer->mLayerBuffer == NULL) ||
|
|
(getDrmMode(layer->mLayerBuffer) == NO_DRM))
|
|
return eForceFbEnabled;
|
|
}
|
|
|
|
if ((display->mLayers.size() >= MAX_OVERLAY_LAYER_NUM) &&
|
|
(layer->mOverlayPriority < ePriorityHigh))
|
|
return eExceedMaxLayerNum;
|
|
|
|
if ((layer->mLayerBuffer != NULL) &&
|
|
(getDrmMode(layer->mLayerBuffer) == NO_DRM) &&
|
|
(display->mDREnable == true) &&
|
|
(display->mDynamicReCompMode == DEVICE_2_CLIENT))
|
|
return eDynamicRecomposition;
|
|
|
|
if ((layer->mLayerBuffer != NULL) &&
|
|
(display->mDisplayId == getDisplayId(HWC_DISPLAY_PRIMARY, 0)) &&
|
|
(mForceReallocState != DST_REALLOC_DONE)) {
|
|
ALOGI("Device type assign skipping by dst reallocation...... ");
|
|
return eReallocOnGoingForDDI;
|
|
}
|
|
|
|
if (layer->mCompositionType == HWC2_COMPOSITION_CLIENT)
|
|
return eSkipLayer;
|
|
|
|
#ifndef HWC_SUPPORT_COLOR_TRANSFORM
|
|
if (display->mColorTransformHint != HAL_COLOR_TRANSFORM_IDENTITY) {
|
|
HWC_LOGE(display, "unsupported color transform");
|
|
return eUnSupportedColorTransform;
|
|
}
|
|
#else
|
|
if ((display->mColorTransformHint < 0) &&
|
|
(layer->mOverlayPriority < ePriorityHigh))
|
|
return eUnSupportedColorTransform;
|
|
#endif
|
|
|
|
if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
|
|
(display->mLowFpsLayerInfo.mFirstIndex <= (int32_t)index) &&
|
|
((int32_t)index <= display->mLowFpsLayerInfo.mLastIndex))
|
|
return eLowFpsLayer;
|
|
|
|
if(layer->isDimLayer() && layer->mLayerBuffer == NULL) {
|
|
return eDimLayer;
|
|
}
|
|
|
|
if (!(display->mType == HWC_DISPLAY_VIRTUAL &&
|
|
((ExynosVirtualDisplay *)display)->mIsWFDState == (int)LLWFD))
|
|
|
|
if (layer->mLayerBuffer == NULL)
|
|
return eInvalidHandle;
|
|
if (isSrcCropFloat(layer->mPreprocessedInfo.sourceCrop))
|
|
return eHasFloatSrcCrop;
|
|
|
|
if ((layer->mPreprocessedInfo.displayFrame.left < 0) ||
|
|
(layer->mPreprocessedInfo.displayFrame.top < 0) ||
|
|
(layer->mPreprocessedInfo.displayFrame.right > (int32_t)display->mXres) ||
|
|
(layer->mPreprocessedInfo.displayFrame.bottom > (int32_t)display->mYres))
|
|
return eInvalidDispFrame;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
exynos_image ExynosResourceManager::getAlignedImage(exynos_image image, const ExynosMPP *m2mMpp,
|
|
const ExynosMPP *otfMpp) const {
|
|
const auto srcCropWidthAlign = otfMpp ? otfMpp->getSrcCropWidthAlign(image) : 1;
|
|
const auto srcCropHeightAlign = otfMpp ? otfMpp->getSrcCropHeightAlign(image) : 1;
|
|
const auto dstwidthAlign = m2mMpp ? m2mMpp->getDstWidthAlign(image) : 1;
|
|
const auto dstHeightAlign = m2mMpp ? m2mMpp->getDstHeightAlign(image) : 1;
|
|
|
|
const auto widthAlign = std::lcm(srcCropWidthAlign, dstwidthAlign);
|
|
const auto heighAlign = std::lcm(srcCropHeightAlign, dstHeightAlign);
|
|
|
|
image.w = pixel_align(image.w, widthAlign);
|
|
image.h = pixel_align(image.h, heighAlign);
|
|
|
|
return image;
|
|
}
|
|
|
|
void ExynosResourceManager::getCandidateScalingM2mMPPOutImages(
|
|
const ExynosDisplay *display, const exynos_image &src_img, const exynos_image &dst_img,
|
|
std::vector<exynos_image> &image_lists) {
|
|
const bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90);
|
|
const uint32_t srcWidth = isPerpendicular ? src_img.h : src_img.w;
|
|
const uint32_t srcHeight = isPerpendicular ? src_img.w : src_img.h;
|
|
|
|
const bool scaleUp = (srcWidth < dst_img.w && srcHeight < dst_img.h);
|
|
const bool scaleDown = (srcWidth > dst_img.w && srcHeight > dst_img.h);
|
|
|
|
if (!scaleUp && !scaleDown) {
|
|
return;
|
|
}
|
|
|
|
/* otfMPP doesn't rotate image, m2mMPP rotates image */
|
|
exynos_image dst_scale_img = dst_img;
|
|
|
|
if (hasHdrInfo(src_img)) {
|
|
if (isFormatYUV(src_img.format))
|
|
dst_scale_img.format = HAL_PIXEL_FORMAT_YCBCR_P010;
|
|
else
|
|
dst_scale_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
|
|
} else {
|
|
if (isFormatYUV(src_img.format)) {
|
|
dst_scale_img.format = DEFAULT_MPP_DST_YUV_FORMAT;
|
|
}
|
|
}
|
|
|
|
ExynosMPP *otfMpp = nullptr;
|
|
ExynosMPP *m2mMpp = nullptr;
|
|
uint32_t otfMppRatio = 1;
|
|
uint32_t m2mMppRatio = 1;
|
|
if (scaleUp) {
|
|
std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
|
|
[&dst_scale_img, &dst_img, &otfMpp, &otfMppRatio](auto m) {
|
|
auto ratio = m->getMaxUpscale(dst_scale_img, dst_img);
|
|
if (ratio > 1) {
|
|
otfMpp = m;
|
|
otfMppRatio = ratio;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
const auto reqRatio = max(float(dst_img.w) / float(srcWidth * otfMppRatio),
|
|
float(dst_img.h) / float(srcHeight * otfMppRatio));
|
|
std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
|
|
[&src_img, &dst_scale_img, reqRatio, &m2mMpp, &m2mMppRatio](auto m) {
|
|
float ratio = float(m->getMaxUpscale(src_img, dst_scale_img));
|
|
if (ratio > reqRatio) {
|
|
m2mMpp = m;
|
|
m2mMppRatio = ratio;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
} else {
|
|
std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
|
|
[&src_img, &dst_scale_img, display, &m2mMpp, &m2mMppRatio](auto m) {
|
|
auto ratio = m->getMaxDownscale(*display, src_img, dst_scale_img);
|
|
if (ratio > 1) {
|
|
m2mMpp = m;
|
|
m2mMppRatio = ratio;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
const float otfSrcWidth = float(srcWidth / m2mMppRatio);
|
|
const float scaleRatio_H = otfSrcWidth / float(dst_img.w);
|
|
const float otfSrcHeight = float(srcWidth / m2mMppRatio);
|
|
const float scaleRatio_V = otfSrcHeight / float(dst_img.h);
|
|
const float displayRatio_V = float(dst_img.h) / float(display->mYres);
|
|
const float resolution = otfSrcWidth * otfSrcHeight * display->getBtsRefreshRate() / 1000;
|
|
|
|
std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
|
|
[&dst_scale_img, &dst_img, resolution, scaleRatio_H, scaleRatio_V,
|
|
displayRatio_V, &otfMpp, &otfMppRatio](auto m) {
|
|
auto ratio = m->getDownscaleRestriction(dst_scale_img, dst_img);
|
|
|
|
if (ratio >= scaleRatio_H && ratio >= scaleRatio_V &&
|
|
m->checkDownscaleCap(resolution, displayRatio_V)) {
|
|
otfMpp = m;
|
|
otfMppRatio = ratio;
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
if (!otfMpp && !m2mMpp) {
|
|
HDEBUGLOGD(eDebugResourceManager,
|
|
"Cannot find available MPP for scaling src %d x %d, dst %d x %d", src_img.w,
|
|
src_img.h, dst_img.w, dst_img.h);
|
|
return;
|
|
}
|
|
|
|
dst_scale_img.x = 0;
|
|
dst_scale_img.y = 0;
|
|
dst_scale_img.w = scaleDown ? dst_img.w : srcWidth;
|
|
dst_scale_img.h = scaleDown ? dst_img.h : srcHeight;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager,
|
|
"scaling w: %d, h: %d, ratio = otfType %d - %d, m2mType %d - %d", dst_scale_img.w,
|
|
dst_scale_img.h, otfMpp ? otfMpp->mLogicalType : -1, otfMppRatio,
|
|
m2mMpp ? m2mMpp->mLogicalType : -1, m2mMppRatio);
|
|
if (scaleUp) {
|
|
if (dst_scale_img.w * otfMppRatio < dst_img.w) {
|
|
dst_scale_img.w = uint32_t(ceilf(float(dst_img.w) / float(otfMppRatio)));
|
|
}
|
|
if (dst_scale_img.h * otfMppRatio < dst_img.h) {
|
|
dst_scale_img.h = uint32_t(ceilf(float(dst_img.h) / float(otfMppRatio)));
|
|
}
|
|
} else {
|
|
if (dst_scale_img.w * m2mMppRatio < srcWidth) {
|
|
dst_scale_img.w = uint32_t(ceilf(float(srcWidth) / float(m2mMppRatio)));
|
|
}
|
|
if (dst_scale_img.h * m2mMppRatio < srcHeight) {
|
|
dst_scale_img.h = uint32_t(ceilf(float(srcHeight) / float(m2mMppRatio)));
|
|
}
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager,
|
|
"\tsrc[%d, %d, %d,%d], dst[%d, %d, %d,%d], mid[%d, %d, %d, %d]", src_img.x,
|
|
src_img.y, src_img.w, src_img.h, dst_img.x, dst_img.y, dst_img.w, dst_img.h,
|
|
dst_scale_img.x, dst_scale_img.y, dst_scale_img.w, dst_scale_img.h);
|
|
|
|
if (isFormatSBWC(dst_scale_img.format)) {
|
|
image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp));
|
|
/*
|
|
* SBWC format could not be supported in specific dst size
|
|
* Add uncompressed YUV format to cover this size
|
|
*/
|
|
dst_scale_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT;
|
|
}
|
|
|
|
image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp));
|
|
}
|
|
|
|
int32_t ExynosResourceManager::getCandidateM2mMPPOutImages(ExynosDisplay *display,
|
|
ExynosLayer *layer, std::vector<exynos_image> &image_lists)
|
|
{
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
/* Position is (0, 0) */
|
|
dst_img.x = 0;
|
|
dst_img.y = 0;
|
|
|
|
/* Check original source format first */
|
|
dst_img.format = src_img.format;
|
|
dst_img.dataSpace = src_img.dataSpace;
|
|
|
|
/* Copy origin source HDR metadata */
|
|
dst_img.metaParcel = src_img.metaParcel;
|
|
|
|
getCandidateScalingM2mMPPOutImages(display, src_img, dst_img, image_lists);
|
|
|
|
if (isFormatYUV(src_img.format) && !hasHdrInfo(src_img)) {
|
|
dst_img.format = DEFAULT_MPP_DST_YUV_FORMAT;
|
|
}
|
|
|
|
ExynosExternalDisplay *external_display =
|
|
(ExynosExternalDisplay*)mDevice->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
|
|
|
|
/* For HDR through MSC or G2D case but dataspace is not changed */
|
|
if (hasHdrInfo(src_img)) {
|
|
if (isFormatYUV(src_img.format))
|
|
dst_img.format = HAL_PIXEL_FORMAT_YCBCR_P010;
|
|
else
|
|
dst_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
|
|
dst_img.dataSpace = src_img.dataSpace;
|
|
|
|
/*
|
|
* Align dst size
|
|
* HDR10Plus should able to be processed by VGRFS
|
|
* HDR on primary display should be processed by VGRFS
|
|
* when external display is connected
|
|
* because G2D is used by external display
|
|
*/
|
|
if (hasHdr10Plus(dst_img) ||
|
|
((external_display != NULL) && (external_display->mPlugState) &&
|
|
(display->mType == HWC_DISPLAY_PRIMARY))) {
|
|
ExynosMPP *otfMppForHDRPlus = nullptr;
|
|
auto mpp_it = std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
|
|
[](auto m) {
|
|
return (m->mAttr & MPP_ATTR_HDR10PLUS);
|
|
});
|
|
otfMppForHDRPlus = mpp_it == mOtfMPPs.end() ? nullptr : *mpp_it;
|
|
uint32_t srcCropWidthAlign = 1;
|
|
uint32_t srcCropHeightAlign = 1;
|
|
if (otfMppForHDRPlus) {
|
|
srcCropWidthAlign = otfMppForHDRPlus->getSrcCropWidthAlign(dst_img);
|
|
srcCropHeightAlign = otfMppForHDRPlus->getSrcCropHeightAlign(dst_img);
|
|
}
|
|
dst_img.w = pixel_align(dst_img.w, srcCropWidthAlign);
|
|
dst_img.h = pixel_align(dst_img.h, srcCropHeightAlign);
|
|
}
|
|
}
|
|
|
|
image_lists.push_back(dst_img);
|
|
if (isFormatSBWC(dst_img.format)) {
|
|
/*
|
|
* SBWC format could not be supported in specific dst size
|
|
* Add uncompressed YUV format to cover this size
|
|
*/
|
|
dst_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT;
|
|
image_lists.push_back(dst_img);
|
|
}
|
|
|
|
/* For G2D HDR case */
|
|
if (hasHdrInfo(src_img)) {
|
|
bool isExternalPlugged = false;
|
|
isHdrExternal = false;
|
|
|
|
if (external_display != NULL) {
|
|
if (external_display->mPlugState) isExternalPlugged = true;
|
|
if (isExternalPlugged && (external_display->mExternalHdrSupported == true))
|
|
isHdrExternal = true;
|
|
}
|
|
|
|
if (isHdrExternal && (display->mType == HWC_DISPLAY_EXTERNAL)) {
|
|
dst_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
|
|
dst_img.dataSpace = src_img.dataSpace;
|
|
} else {
|
|
uint32_t dataspace = HAL_DATASPACE_UNKNOWN;
|
|
if (display->mColorMode == HAL_COLOR_MODE_NATIVE) {
|
|
dataspace = HAL_DATASPACE_DCI_P3;
|
|
dataspace &= ~HAL_DATASPACE_TRANSFER_MASK;
|
|
dataspace |= HAL_DATASPACE_TRANSFER_GAMMA2_2;
|
|
dataspace &= ~HAL_DATASPACE_RANGE_MASK;
|
|
dataspace |= HAL_DATASPACE_RANGE_LIMITED;
|
|
} else {
|
|
dataspace = colorModeToDataspace(display->mColorMode);
|
|
}
|
|
dst_img.format = HAL_PIXEL_FORMAT_RGBX_8888;
|
|
dst_img.dataSpace = (android_dataspace)dataspace;
|
|
}
|
|
|
|
/*
|
|
* This image is not pushed for primary display
|
|
* if external display is connected
|
|
* because G2D is used only for HDR on exernal display
|
|
*/
|
|
if (!(isExternalPlugged && (display->mType == HWC_DISPLAY_PRIMARY))) {
|
|
image_lists.push_back(dst_img);
|
|
}
|
|
}
|
|
|
|
if (isFormatYUV(src_img.format) && !hasHdrInfo(src_img)) {
|
|
/* Check RGB format */
|
|
dst_img.format = DEFAULT_MPP_DST_FORMAT;
|
|
if (display->mColorMode == HAL_COLOR_MODE_NATIVE) {
|
|
/* Bypass dataSpace */
|
|
dst_img.dataSpace = src_img.dataSpace;
|
|
} else {
|
|
/* Covert data space */
|
|
dst_img.dataSpace = colorModeToDataspace(display->mColorMode);
|
|
}
|
|
image_lists.push_back(dst_img);
|
|
}
|
|
|
|
/*
|
|
* image_lists[] would be src of otfMPP.
|
|
* Layer color transform should be addressed
|
|
* with dataspace conversion.
|
|
* It should be addressed by m2mMPP if m2mMPP converts dataspace.
|
|
* In other cases, m2mMPP ignores color transform setting and
|
|
* otfMPP addresses layer color transform if it is necessary.
|
|
*/
|
|
for (auto &image: image_lists) {
|
|
if (image.dataSpace == src_img.dataSpace)
|
|
image.needColorTransform = src_img.needColorTransform;
|
|
else
|
|
image.needColorTransform = false;
|
|
|
|
}
|
|
|
|
return static_cast<int32_t>(image_lists.size());
|
|
}
|
|
|
|
int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *layer, uint32_t layer_index,
|
|
exynos_image &m2m_out_img, ExynosMPP **m2mMPP, ExynosMPP **otfMPP, uint32_t &overlayInfo)
|
|
{
|
|
int32_t ret = NO_ERROR;
|
|
uint32_t validateFlag = 0;
|
|
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
layer->setExynosImage(src_img, dst_img);
|
|
layer->setExynosMidImage(dst_img);
|
|
|
|
validateFlag = validateLayer(layer_index, display, layer);
|
|
if ((display->mUseDpu) &&
|
|
(display->mWindowNumUsed >= display->mMaxWindowNum))
|
|
validateFlag |= eInsufficientWindow;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t[%d] layer: validateFlag(0x%8x), supportedMPPFlag(0x%8x)",
|
|
layer_index, validateFlag, layer->mSupportedMPPFlag);
|
|
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
layer->printLayer();
|
|
}
|
|
|
|
if ((validateFlag == NO_ERROR) || (validateFlag == eInsufficientWindow) ||
|
|
(validateFlag == eDimLayer)) {
|
|
bool isAssignable = false;
|
|
uint64_t isSupported = 0;
|
|
/* 1. Find available otfMPP */
|
|
if (validateFlag != eInsufficientWindow) {
|
|
for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
|
|
if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) != 0)
|
|
isAssignable = mOtfMPPs[j]->isAssignable(display, src_img, dst_img);
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: flag (%d) supportedBit(%d), isAssignable(%d)",
|
|
mOtfMPPs[j]->mName.string(),layer->mSupportedMPPFlag,
|
|
(layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType), isAssignable);
|
|
if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) && (isAssignable)) {
|
|
isSupported = mOtfMPPs[j]->isSupported(*display, src_img, dst_img);
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t\t isSuported(%" PRIx64 ")", -isSupported);
|
|
if (isSupported == NO_ERROR) {
|
|
*otfMPP = mOtfMPPs[j];
|
|
return HWC2_COMPOSITION_DEVICE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 2. Find available m2mMPP */
|
|
for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
|
|
|
|
if ((display->mUseDpu == true) &&
|
|
(mM2mMPPs[j]->mLogicalType == MPP_LOGICAL_G2D_COMBO))
|
|
continue;
|
|
if ((display->mUseDpu == false) &&
|
|
(mM2mMPPs[j]->mLogicalType == MPP_LOGICAL_G2D_RGB))
|
|
continue;
|
|
|
|
/* Only G2D can be assigned if layer is supported by G2D
|
|
* when window is not sufficient
|
|
*/
|
|
if ((validateFlag == eInsufficientWindow) &&
|
|
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
|
|
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tInsufficient window but exynosComposition is not assigned");
|
|
continue;
|
|
}
|
|
|
|
bool isAssignableState = mM2mMPPs[j]->isAssignableState(display, src_img, dst_img);
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: supportedBit(%d), isAssignableState(%d)",
|
|
mM2mMPPs[j]->mName.string(),
|
|
(layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType), isAssignableState);
|
|
|
|
if (isAssignableState) {
|
|
if ((mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
|
|
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
|
|
exynos_image otf_dst_img = dst_img;
|
|
|
|
otf_dst_img.format = DEFAULT_MPP_DST_FORMAT;
|
|
|
|
std::vector<exynos_image> image_lists;
|
|
if ((ret = getCandidateM2mMPPOutImages(display, layer, image_lists)) < 0)
|
|
{
|
|
HWC_LOGE(display, "Fail getCandidateM2mMPPOutImages (%d)", ret);
|
|
return ret;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "candidate M2mMPPOutImage num: %zu", image_lists.size());
|
|
for (auto &otf_src_img : image_lists) {
|
|
dumpExynosImage(eDebugResourceManager, otf_src_img);
|
|
exynos_image m2m_src_img = src_img;
|
|
/* transform is already handled by m2mMPP */
|
|
if (CC_UNLIKELY(otf_src_img.transform != 0 || otf_dst_img.transform != 0)) {
|
|
ALOGE("%s:: transform should be handled by m2mMPP. otf_src_img "
|
|
"transform %d, otf_dst_img transform %d",
|
|
__func__, otf_src_img.transform, otf_dst_img.transform);
|
|
otf_src_img.transform = 0;
|
|
otf_dst_img.transform = 0;
|
|
}
|
|
|
|
/*
|
|
* This is the case that layer color transform should be
|
|
* addressed by otfMPP not m2mMPP
|
|
*/
|
|
if (otf_src_img.needColorTransform)
|
|
m2m_src_img.needColorTransform = false;
|
|
|
|
if (((isSupported = mM2mMPPs[j]->isSupported(*display, m2m_src_img, otf_src_img)) != NO_ERROR) ||
|
|
((isAssignable = mM2mMPPs[j]->hasEnoughCapa(display, m2m_src_img, otf_src_img)) == false))
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: supportedBit(0x%" PRIx64 "), hasEnoughCapa(%d)",
|
|
mM2mMPPs[j]->mName.string(), -isSupported, isAssignable);
|
|
continue;
|
|
}
|
|
|
|
/* 3. Find available OtfMPP for output of m2mMPP */
|
|
for (uint32_t k = 0; k < mOtfMPPs.size(); k++) {
|
|
isSupported = mOtfMPPs[k]->isSupported(*display, otf_src_img, otf_dst_img);
|
|
isAssignable = false;
|
|
if (isSupported == NO_ERROR)
|
|
isAssignable = mOtfMPPs[k]->isAssignable(display, otf_src_img, otf_dst_img);
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
|
|
mOtfMPPs[k]->mName.string(), -isSupported, isAssignable);
|
|
if ((isSupported == NO_ERROR) && isAssignable) {
|
|
*m2mMPP = mM2mMPPs[j];
|
|
*otfMPP = mOtfMPPs[k];
|
|
m2m_out_img = otf_src_img;
|
|
return HWC2_COMPOSITION_DEVICE;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if ((layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType) &&
|
|
((isAssignable = mM2mMPPs[j]->hasEnoughCapa(display, src_img, dst_img) == true))) {
|
|
*m2mMPP = mM2mMPPs[j];
|
|
return HWC2_COMPOSITION_EXYNOS;
|
|
} else {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: layer's mSupportedMPPFlag(0x%8x), hasEnoughCapa(%d)",
|
|
mM2mMPPs[j]->mName.string(), layer->mSupportedMPPFlag, isAssignable);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Fail to assign resource */
|
|
if (validateFlag != NO_ERROR)
|
|
overlayInfo = validateFlag;
|
|
else
|
|
overlayInfo = eMPPUnsupported;
|
|
return HWC2_COMPOSITION_CLIENT;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t priority)
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: display(%d), priority(%d) +++++",
|
|
__func__, display->mType, priority);
|
|
|
|
int32_t ret = NO_ERROR;
|
|
bool needReAssign = false;
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
ExynosMPP *m2mMPP = NULL;
|
|
ExynosMPP *otfMPP = NULL;
|
|
exynos_image m2m_out_img;
|
|
uint32_t validateFlag = 0;
|
|
int32_t compositionType = 0;
|
|
|
|
if ((layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT) ||
|
|
(layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS))
|
|
continue;
|
|
if (layer->mOverlayPriority != priority)
|
|
continue;
|
|
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
layer->setExynosImage(src_img, dst_img);
|
|
layer->setExynosMidImage(dst_img);
|
|
|
|
compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, validateFlag);
|
|
if (compositionType == HWC2_COMPOSITION_DEVICE) {
|
|
if (otfMPP != NULL) {
|
|
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, otfMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
|
|
i, otfMPP->mName.string());
|
|
}
|
|
if (m2mMPP != NULL) {
|
|
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, m2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
layer->setExynosMidImage(m2m_out_img);
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
|
|
i, m2mMPP->mName.string());
|
|
}
|
|
layer->mValidateCompositionType = compositionType;
|
|
display->mWindowNumUsed++;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: mWindowNumUsed(%d)",
|
|
i, display->mWindowNumUsed);
|
|
} else if (compositionType == HWC2_COMPOSITION_EXYNOS) {
|
|
if (m2mMPP != NULL) {
|
|
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
|
|
{
|
|
ALOGE("%s:: %s MPP assignMPP() error (%d)",
|
|
__func__, m2mMPP->mName.string(), ret);
|
|
return ret;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
|
|
i, m2mMPP->mName.string());
|
|
}
|
|
layer->mValidateCompositionType = compositionType;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: exynosComposition", i);
|
|
/* G2D composition */
|
|
if (((ret = display->addExynosCompositionLayer(i)) == EXYNOS_ERROR_CHANGED) ||
|
|
(ret < 0))
|
|
return ret;
|
|
else {
|
|
/*
|
|
* If high fps layer should be composited by GLES then
|
|
* disable handling low fps feature and reassign resources
|
|
*/
|
|
if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
|
|
(display->mClientCompositionInfo.mHasCompositionLayer == true) &&
|
|
((display->mClientCompositionInfo.mFirstIndex < display->mLowFpsLayerInfo.mFirstIndex) ||
|
|
(display->mClientCompositionInfo.mLastIndex > display->mLowFpsLayerInfo.mLastIndex))) {
|
|
needReAssign = true;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
/*
|
|
* If high fps layer should be composited by GLES then
|
|
* disable handling low fps feature and reassign resources
|
|
*/
|
|
if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
|
|
(((int32_t)i < display->mLowFpsLayerInfo.mFirstIndex) ||
|
|
(display->mLowFpsLayerInfo.mLastIndex < (int32_t)i))) {
|
|
needReAssign = true;
|
|
break;
|
|
}
|
|
|
|
/* Fail to assign resource, set HWC2_COMPOSITION_CLIENT */
|
|
if (validateFlag != NO_ERROR)
|
|
layer->mOverlayInfo |= validateFlag;
|
|
else
|
|
layer->mOverlayInfo |= eMPPUnsupported;
|
|
|
|
layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
|
|
if (((ret = display->addClientCompositionLayer(i)) == EXYNOS_ERROR_CHANGED) ||
|
|
(ret < 0))
|
|
return ret;
|
|
}
|
|
}
|
|
if (needReAssign) {
|
|
if ((display->mClientCompositionInfo.mHasCompositionLayer) &&
|
|
(display->mClientCompositionInfo.mOtfMPP != NULL))
|
|
display->mClientCompositionInfo.mOtfMPP->resetAssignedState();
|
|
|
|
if (display->mExynosCompositionInfo.mHasCompositionLayer) {
|
|
if (display->mExynosCompositionInfo.mOtfMPP != NULL)
|
|
display->mExynosCompositionInfo.mOtfMPP->resetAssignedState();
|
|
if (display->mExynosCompositionInfo.mM2mMPP != NULL)
|
|
display->mExynosCompositionInfo.mM2mMPP->resetAssignedState();
|
|
}
|
|
|
|
display->initializeValidateInfos();
|
|
display->mLowFpsLayerInfo.initializeInfos();
|
|
return EXYNOS_ERROR_CHANGED;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::assignWindow(ExynosDisplay *display)
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "%s +++++", __func__);
|
|
int ret = NO_ERROR;
|
|
uint32_t windowIndex = 0;
|
|
|
|
if (!display->mUseDpu)
|
|
return ret;
|
|
|
|
windowIndex = display->mBaseWindowIndex;
|
|
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
HDEBUGLOGD(eDebugResourceManager, "\t[%d] layer type: %d", i, layer->mValidateCompositionType);
|
|
|
|
if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) {
|
|
layer->mWindowIndex = windowIndex;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer windowIndex: %d", i, windowIndex);
|
|
} else if ((layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT) ||
|
|
(layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS)) {
|
|
ExynosCompositionInfo *compositionInfo;
|
|
if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
|
|
compositionInfo = &display->mClientCompositionInfo;
|
|
else
|
|
compositionInfo = &display->mExynosCompositionInfo;
|
|
|
|
if ((compositionInfo->mHasCompositionLayer == false) ||
|
|
(compositionInfo->mFirstIndex < 0) ||
|
|
(compositionInfo->mLastIndex < 0)) {
|
|
HWC_LOGE(display, "%s:: Invalid %s CompositionInfo mHasCompositionLayer(%d), "
|
|
"mFirstIndex(%d), mLastIndex(%d) ",
|
|
__func__, compositionInfo->getTypeStr().string(),
|
|
compositionInfo->mHasCompositionLayer,
|
|
compositionInfo->mFirstIndex,
|
|
compositionInfo->mLastIndex);
|
|
continue;
|
|
}
|
|
if (i != (uint32_t)compositionInfo->mLastIndex)
|
|
continue;
|
|
compositionInfo->mWindowIndex = windowIndex;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] %s Composition windowIndex: %d",
|
|
i, compositionInfo->getTypeStr().string(), windowIndex);
|
|
} else {
|
|
HWC_LOGE(display, "%s:: Invalid layer compositionType layer(%d), compositionType(%d)",
|
|
__func__, i, layer->mValidateCompositionType);
|
|
continue;
|
|
}
|
|
windowIndex++;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "%s ------", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @param * display
|
|
* @return int
|
|
*/
|
|
int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
|
|
{
|
|
int64_t ret = 0;
|
|
HDEBUGLOGD(eDebugResourceManager, "%s++++++++++", __func__);
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
HDEBUGLOGD(eDebugResourceManager, "[%d] layer ", i);
|
|
|
|
if (layer->mGeometryChanged == 0)
|
|
continue;
|
|
|
|
exynos_image src_img;
|
|
exynos_image dst_img;
|
|
exynos_image dst_img_yuv;
|
|
layer->setSrcExynosImage(&src_img);
|
|
layer->setDstExynosImage(&dst_img);
|
|
layer->setDstExynosImage(&dst_img_yuv);
|
|
dst_img.format = DEFAULT_MPP_DST_FORMAT;
|
|
dst_img_yuv.format = DEFAULT_MPP_DST_YUV_FORMAT;
|
|
HDEBUGLOGD(eDebugResourceManager, "\tsrc_img");
|
|
dumpExynosImage(eDebugResourceManager, src_img);
|
|
HDEBUGLOGD(eDebugResourceManager, "\tdst_img");
|
|
dumpExynosImage(eDebugResourceManager, dst_img);
|
|
|
|
/* Initialize flags */
|
|
layer->mSupportedMPPFlag = 0;
|
|
layer->mCheckMPPFlag.clear();
|
|
|
|
/* Check OtfMPPs */
|
|
for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
|
|
if ((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
|
|
layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: supported", mOtfMPPs[j]->mName.string());
|
|
} else {
|
|
if (((-ret) == eMPPUnsupportedFormat) &&
|
|
((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
|
|
layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: supported with yuv dst", mOtfMPPs[j]->mName.string());
|
|
}
|
|
}
|
|
if (ret < 0) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: unsupported flag(0x%" PRIx64 ")", mOtfMPPs[j]->mName.string(), -ret);
|
|
uint64_t checkFlag = 0x0;
|
|
if (layer->mCheckMPPFlag.find(mOtfMPPs[j]->mLogicalType) !=
|
|
layer->mCheckMPPFlag.end()) {
|
|
checkFlag = layer->mCheckMPPFlag.at(mOtfMPPs[j]->mLogicalType);
|
|
}
|
|
checkFlag |= (-ret);
|
|
layer->mCheckMPPFlag[mOtfMPPs[j]->mLogicalType] = checkFlag;
|
|
}
|
|
}
|
|
|
|
/* Check M2mMPPs */
|
|
for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
|
|
if ((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
|
|
layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: supported", mM2mMPPs[j]->mName.string());
|
|
} else {
|
|
if (((-ret) == eMPPUnsupportedFormat) &&
|
|
((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
|
|
layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: supported with yuv dst", mM2mMPPs[j]->mName.string());
|
|
}
|
|
}
|
|
if (ret < 0) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s: unsupported flag(0x%" PRIx64 ")", mM2mMPPs[j]->mName.string(), -ret);
|
|
uint64_t checkFlag = 0x0;
|
|
if (layer->mCheckMPPFlag.find(mM2mMPPs[j]->mLogicalType) !=
|
|
layer->mCheckMPPFlag.end()) {
|
|
checkFlag = layer->mCheckMPPFlag.at(mM2mMPPs[j]->mLogicalType);
|
|
}
|
|
checkFlag |= (-ret);
|
|
layer->mCheckMPPFlag[mM2mMPPs[j]->mLogicalType] = checkFlag;
|
|
}
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "[%d] layer mSupportedMPPFlag(0x%8x)", i, layer->mSupportedMPPFlag);
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "%s-------------", __func__);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::resetResources()
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "%s+++++++++", __func__);
|
|
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
mOtfMPPs[i]->resetMPP();
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
String8 dumpMPP;
|
|
mOtfMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
mM2mMPPs[i]->resetMPP();
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
String8 dumpMPP;
|
|
mM2mMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "%s-----------", __func__);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::preAssignResources()
|
|
{
|
|
HDEBUGLOGD(eDebugResourceManager, "%s+++++++++", __func__);
|
|
uint32_t displayMode = mDevice->mDisplayMode;
|
|
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (mOtfMPPs[i]->mEnable == false) {
|
|
mOtfMPPs[i]->reserveMPP();
|
|
continue;
|
|
}
|
|
|
|
if (mOtfMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s check, dispMode(%d), 0x%8x", mOtfMPPs[i]->mName.string(), displayMode, mOtfMPPs[i]->mPreAssignDisplayList[displayMode]);
|
|
|
|
ExynosDisplay *display = NULL;
|
|
for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
|
|
display = mDevice->mDisplays[j];
|
|
if (display == nullptr)
|
|
continue;
|
|
int checkBit = mOtfMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), checkBit(%d)", j, checkBit);
|
|
if (checkBit) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), displayId(%d), display(%p)", j, display->mDisplayId, display);
|
|
if (display->mDisplayControl.forceReserveMPP ||
|
|
(display->mPlugState &&
|
|
((display->mType != HWC_DISPLAY_PRIMARY) ||
|
|
(display->mPowerModeState != HWC2_POWER_MODE_OFF)))) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\treserve to display %d", display->mDisplayId);
|
|
mOtfMPPs[i]->reserveMPP(display->mDisplayId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mEnable == false) {
|
|
mM2mMPPs[i]->reserveMPP();
|
|
continue;
|
|
}
|
|
|
|
if (mResourceReserved & mM2mMPPs[i]->mLogicalType) {
|
|
/* MSC can't be used for rendering */
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tMPP_MSC reserve without display because preview is running");
|
|
mM2mMPPs[i]->reserveMPP();
|
|
continue;
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "\t%s check, 0x%8x", mM2mMPPs[i]->mName.string(), mM2mMPPs[i]->mPreAssignDisplayList[displayMode]);
|
|
if (mM2mMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
|
|
ExynosDisplay *display = NULL;
|
|
for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
|
|
display = mDevice->mDisplays[j];
|
|
int checkBit = mM2mMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), checkBit(%d)", j, checkBit);
|
|
if (checkBit) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), displayId(%d), display(%p)", j, display->mDisplayId, display);
|
|
if ((display != NULL) && (display->mPlugState == true)) {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\treserve to display %d", display->mDisplayId);
|
|
mM2mMPPs[i]->reserveMPP(display->mDisplayId);
|
|
break;
|
|
} else {
|
|
HDEBUGLOGD(eDebugResourceManager, "\t\treserve without display");
|
|
mM2mMPPs[i]->reserveMPP();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
String8 dumpMPP;
|
|
mOtfMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (hwcCheckDebugMessages(eDebugResourceManager)) {
|
|
String8 dumpMPP;
|
|
mM2mMPPs[i]->dump(dumpMPP);
|
|
HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
|
|
}
|
|
}
|
|
HDEBUGLOGD(eDebugResourceManager, "%s-----------", __func__);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
void ExynosResourceManager::preAssignWindows()
|
|
{
|
|
ExynosDisplay *display = NULL;
|
|
ExynosPrimaryDisplayModule *primaryDisplay =
|
|
(ExynosPrimaryDisplayModule *)mDevice->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
|
|
primaryDisplay->usePreDefinedWindow(false);
|
|
|
|
for (size_t i = 1; i < mDevice->mDisplays.size(); i++) {
|
|
display = mDevice->mDisplays[i];
|
|
if ((display == NULL) || (display->mType != HWC_DISPLAY_EXTERNAL))
|
|
continue;
|
|
if (display->mPlugState == true) {
|
|
primaryDisplay->usePreDefinedWindow(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t ExynosResourceManager::preProcessLayer(ExynosDisplay * display)
|
|
{
|
|
int32_t ret = 0;
|
|
hasHdrLayer = false;
|
|
hasDrmLayer = false;
|
|
|
|
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
if ((ret = layer->doPreProcess()) < 0) {
|
|
HWC_LOGE(display, "%s:: doPreProcess() error, display(%d), layer %d", __func__, display->mType, i);
|
|
return ret;
|
|
}
|
|
/* mIsHdrLayer is known after preprocess */
|
|
if (layer->mIsHdrLayer) hasHdrLayer = true;
|
|
if ((layer->mLayerBuffer != NULL) && (getDrmMode(layer->mLayerBuffer) != NO_DRM))
|
|
hasDrmLayer = true;
|
|
}
|
|
|
|
// Re-align layer priority for max overlay resources
|
|
uint32_t mNumMaxPriorityLayers = 0;
|
|
for (int i = (display->mLayers.size()-1); i >= 0; i--) {
|
|
ExynosLayer *layer = display->mLayers[i];
|
|
HDEBUGLOGD(eDebugResourceManager, "Priority align: i:%d, layer priority:%d, Max:%d, mNumMaxPriorityAllowed:%d", i,
|
|
layer->mOverlayPriority, mNumMaxPriorityLayers, display->mNumMaxPriorityAllowed);
|
|
if (layer->mOverlayPriority == ePriorityMax) {
|
|
if (mNumMaxPriorityLayers >= display->mNumMaxPriorityAllowed) {
|
|
layer->mOverlayPriority = ePriorityHigh;
|
|
}
|
|
mNumMaxPriorityLayers++;
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ExynosMPP* ExynosResourceManager::getExynosMPP(uint32_t type)
|
|
{
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (mOtfMPPs[i]->mLogicalType == type)
|
|
return mOtfMPPs[i];
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mLogicalType == type)
|
|
return mM2mMPPs[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ExynosMPP* ExynosResourceManager::getExynosMPP(uint32_t physicalType, uint32_t physicalIndex)
|
|
{
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if ((mOtfMPPs[i]->mPhysicalType == physicalType) &&
|
|
(mOtfMPPs[i]->mPhysicalIndex == physicalIndex))
|
|
return mOtfMPPs[i];
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if ((mM2mMPPs[i]->mPhysicalType == physicalType) &&
|
|
(mM2mMPPs[i]->mPhysicalIndex == physicalIndex))
|
|
return mM2mMPPs[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::updateResourceState()
|
|
{
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (mOtfMPPs[i]->mAssignedSources.size() == 0)
|
|
mOtfMPPs[i]->requestHWStateChange(MPP_HW_STATE_IDLE);
|
|
mOtfMPPs[i]->mPrevAssignedState = mOtfMPPs[i]->mAssignedState;
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mAssignedSources.size() == 0)
|
|
mM2mMPPs[i]->requestHWStateChange(MPP_HW_STATE_IDLE);
|
|
mM2mMPPs[i]->mPrevAssignedState = mM2mMPPs[i]->mAssignedState;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* This function is called every frame.
|
|
* This base function does nothing.
|
|
* Module that supports setting frame rate should implement this function
|
|
* in the module source code (hardware/samsung_slsi/graphics/exynos...).
|
|
*/
|
|
void ExynosResourceManager::setFrameRateForPerformance(ExynosMPP &mpp,
|
|
AcrylicPerformanceRequestFrame *frame)
|
|
{
|
|
int fps = ceil(msecsPerSec / mpp.mCapacity);
|
|
HDEBUGLOGD(eDebugResourceAssigning, "%s setFrameRate %d",
|
|
mpp.mName.string(), fps);
|
|
frame->setFrameRate(fps);
|
|
}
|
|
|
|
int32_t ExynosResourceManager::deliverPerformanceInfo()
|
|
{
|
|
int ret = NO_ERROR;
|
|
for (uint32_t mpp_physical_type = 0; mpp_physical_type < MPP_P_TYPE_MAX; mpp_physical_type++) {
|
|
/* Only G2D gets performance info in current version */
|
|
if (mpp_physical_type != MPP_G2D)
|
|
continue;
|
|
AcrylicPerformanceRequest request;
|
|
uint32_t assignedInstanceNum = 0;
|
|
uint32_t assignedInstanceIndex = 0;
|
|
ExynosMPP *mpp = NULL;
|
|
bool canSkipSetting = true;
|
|
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
mpp = mM2mMPPs[i];
|
|
if (mpp->mPhysicalType != mpp_physical_type)
|
|
continue;
|
|
/* Performance setting can be skipped
|
|
* if all of instance's mPrevAssignedState, mAssignedState
|
|
* are MPP_ASSIGN_STATE_FREE
|
|
*/
|
|
if ((mpp->mPrevAssignedState & MPP_ASSIGN_STATE_ASSIGNED) ||
|
|
(mpp->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED))
|
|
{
|
|
canSkipSetting = false;
|
|
}
|
|
|
|
if (mpp->canSkipProcessing())
|
|
continue;
|
|
|
|
if ((mpp->mAssignedDisplay != NULL) &&
|
|
(mpp->mAssignedSources.size() > 0))
|
|
{
|
|
assignedInstanceNum++;
|
|
}
|
|
}
|
|
if ((canSkipSetting == true) && (assignedInstanceNum != 0)) {
|
|
HWC_LOGE(NULL, "%s:: canSKip true but assignedInstanceNum(%d)",
|
|
__func__, assignedInstanceNum);
|
|
}
|
|
request.reset(assignedInstanceNum);
|
|
|
|
if (canSkipSetting == true)
|
|
continue;
|
|
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
mpp = mM2mMPPs[i];
|
|
if ((mpp->mPhysicalType == mpp_physical_type) &&
|
|
(mpp->mAssignedDisplay != NULL) &&
|
|
(mpp->mAssignedSources.size() > 0))
|
|
{
|
|
if (mpp->canSkipProcessing())
|
|
continue;
|
|
if (assignedInstanceIndex >= assignedInstanceNum) {
|
|
HWC_LOGE(NULL,"assignedInstanceIndex error (%d, %d)", assignedInstanceIndex, assignedInstanceNum);
|
|
break;
|
|
}
|
|
AcrylicPerformanceRequestFrame *frame = request.getFrame(assignedInstanceIndex);
|
|
if(frame->reset(mpp->mAssignedSources.size()) == false) {
|
|
HWC_LOGE(NULL,"%d frame reset fail (%zu)", assignedInstanceIndex, mpp->mAssignedSources.size());
|
|
break;
|
|
}
|
|
setFrameRateForPerformance(*mpp, frame);
|
|
|
|
for (uint32_t j = 0; j < mpp->mAssignedSources.size(); j++) {
|
|
ExynosMPPSource* mppSource = mpp->mAssignedSources[j];
|
|
frame->setSourceDimension(j,
|
|
mppSource->mSrcImg.w, mppSource->mSrcImg.h,
|
|
mppSource->mSrcImg.format);
|
|
|
|
if (mppSource->mSrcImg.compressed == 1)
|
|
frame->setAttribute(j, AcrylicCanvas::ATTR_COMPRESSED);
|
|
|
|
hwc_rect_t src_area;
|
|
src_area.left = mppSource->mSrcImg.x;
|
|
src_area.top = mppSource->mSrcImg.y;
|
|
src_area.right = mppSource->mSrcImg.x + mppSource->mSrcImg.w;
|
|
src_area.bottom = mppSource->mSrcImg.y + mppSource->mSrcImg.h;
|
|
|
|
hwc_rect_t out_area;
|
|
out_area.left = mppSource->mMidImg.x;
|
|
out_area.top = mppSource->mMidImg.y;
|
|
out_area.right = mppSource->mMidImg.x + mppSource->mMidImg.w;
|
|
out_area.bottom = mppSource->mMidImg.y + mppSource->mMidImg.h;
|
|
|
|
frame->setTransfer(j, src_area, out_area, mppSource->mSrcImg.transform);
|
|
}
|
|
uint32_t format = mpp->mAssignedSources[0]->mMidImg.format;
|
|
bool hasSolidColorLayer = false;
|
|
if (mpp->mNeedSolidColorLayer) {
|
|
format = DEFAULT_MPP_DST_FORMAT;
|
|
hasSolidColorLayer = true;
|
|
}
|
|
|
|
frame->setTargetDimension(mpp->mAssignedDisplay->mXres,
|
|
mpp->mAssignedDisplay->mYres, format, hasSolidColorLayer);
|
|
|
|
assignedInstanceIndex++;
|
|
}
|
|
}
|
|
if ((mpp = getExynosMPP(MPP_LOGICAL_G2D_RGB)) != NULL)
|
|
mpp->mAcrylicHandle->requestPerformanceQoS(&request);
|
|
else
|
|
HWC_LOGE(NULL,"getExynosMPP(MPP_LOGICAL_G2D_RGB) failed");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Get used capacity of the resource that abstracts same HW resource
|
|
* but it is different instance with mpp
|
|
*/
|
|
float ExynosResourceManager::getResourceUsedCapa(ExynosMPP &mpp)
|
|
{
|
|
float usedCapa = 0;
|
|
if (mpp.mCapacity < 0)
|
|
return usedCapa;
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "%s:: [%s][%d] mpp[%d, %d]",
|
|
__func__, mpp.mName.string(), mpp.mLogicalIndex,
|
|
mpp.mPhysicalType, mpp.mPhysicalIndex);
|
|
|
|
if (mpp.mMPPType == MPP_TYPE_OTF) {
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if ((mpp.mPhysicalType == mOtfMPPs[i]->mPhysicalType) &&
|
|
(mpp.mPhysicalIndex == mOtfMPPs[i]->mPhysicalIndex)) {
|
|
usedCapa += mOtfMPPs[i]->mUsedCapacity;
|
|
}
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if ((mpp.mPhysicalType == mM2mMPPs[i]->mPhysicalType) &&
|
|
(mpp.mPhysicalIndex == mM2mMPPs[i]->mPhysicalIndex)) {
|
|
usedCapa += mM2mMPPs[i]->mUsedCapacity;
|
|
}
|
|
}
|
|
}
|
|
|
|
HDEBUGLOGD(eDebugResourceManager, "\t[%s][%d] mpp usedCapa: %f",
|
|
mpp.mName.string(), mpp.mLogicalIndex, usedCapa);
|
|
return usedCapa;
|
|
}
|
|
|
|
void ExynosResourceManager::enableMPP(uint32_t physicalType, uint32_t physicalIndex, uint32_t logicalIndex, uint32_t enable)
|
|
{
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if ((mOtfMPPs[i]->mPhysicalType == physicalType) &&
|
|
(mOtfMPPs[i]->mPhysicalIndex == physicalIndex) &&
|
|
(mOtfMPPs[i]->mLogicalIndex == logicalIndex)) {
|
|
mOtfMPPs[i]->mEnable = !!(enable);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if ((mM2mMPPs[i]->mPhysicalType == physicalType) &&
|
|
(mM2mMPPs[i]->mPhysicalIndex == physicalIndex) &&
|
|
(mM2mMPPs[i]->mLogicalIndex == logicalIndex)) {
|
|
mM2mMPPs[i]->mEnable = !!(enable);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExynosResourceManager::setScaleDownRatio(uint32_t physicalType,
|
|
uint32_t physicalIndex, uint32_t logicalIndex, uint32_t scaleDownRatio)
|
|
{
|
|
ExynosMPP *findMpp = nullptr;
|
|
|
|
auto mpp_compare = [=](ExynosMPP *mpp)->bool {
|
|
return ((mpp->mPhysicalType == physicalType) &&
|
|
(mpp->mPhysicalIndex == physicalIndex) &&
|
|
(mpp->mLogicalIndex == logicalIndex));
|
|
};
|
|
|
|
auto otfMPP = std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
|
|
mpp_compare);
|
|
if (otfMPP != mOtfMPPs.end()) {
|
|
findMpp = *otfMPP;
|
|
} else {
|
|
auto m2mMPP = std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
|
|
mpp_compare);
|
|
findMpp = m2mMPP == mM2mMPPs.end() ? nullptr : *m2mMPP;
|
|
}
|
|
|
|
if (findMpp == nullptr) {
|
|
ALOGE("%s:: Invalid mpp (type: %d, index: %d, %d)",
|
|
__func__, physicalType, physicalIndex, logicalIndex);
|
|
return;
|
|
}
|
|
for (uint32_t i = RESTRICTION_RGB; i < RESTRICTION_MAX; i++) {
|
|
findMpp->mDstSizeRestrictions[i].maxDownScale = scaleDownRatio;
|
|
}
|
|
}
|
|
|
|
int32_t ExynosResourceManager::prepareResources()
|
|
{
|
|
int ret = NO_ERROR;
|
|
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
|
|
if ((ret = resetResources()) != NO_ERROR) {
|
|
HWC_LOGE(NULL,"%s:: resetResources() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
if ((ret = preAssignResources()) != NO_ERROR) {
|
|
HWC_LOGE(NULL,"%s:: preAssignResources() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::finishAssignResourceWork()
|
|
{
|
|
int ret = NO_ERROR;
|
|
if ((ret = updateResourceState()) != NO_ERROR) {
|
|
HWC_LOGE(NULL,"%s:: stopUnAssignedResource() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
mDevice->clearGeometryChanged();
|
|
return ret;
|
|
}
|
|
|
|
int32_t ExynosResourceManager::initResourcesState(ExynosDisplay *display)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (mDevice->isFirstValidate()) {
|
|
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
|
|
if (exynosHWCControl.displayMode < DISPLAY_MODE_NUM)
|
|
mDevice->mDisplayMode = exynosHWCControl.displayMode;
|
|
|
|
if ((ret = prepareResources()) != NO_ERROR) {
|
|
HWC_LOGE(display, "%s:: prepareResources() error (%d)",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
preAssignWindows();
|
|
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
void ExynosResourceManager::makeSizeRestrictions(uint32_t mppId, const restriction_size_t &size,
|
|
restriction_classification_t format) {
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.hwType = static_cast<mpp_phycal_type_t>(mppId);
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.nodeType = NODE_SRC;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.format = HAL_PIXEL_FORMAT_NONE;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.reserved = 0;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]++].sizeRestriction = size;
|
|
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.hwType = static_cast<mpp_phycal_type_t>(mppId);
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.nodeType = NODE_DST;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.format = HAL_PIXEL_FORMAT_NONE;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.reserved = 0;
|
|
mSizeRestrictions[format][mSizeRestrictionCnt[format]++].sizeRestriction = size;
|
|
|
|
HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
|
|
getMPPStr(mppId).string(),
|
|
size.maxDownScale,
|
|
size.maxUpScale,
|
|
size.maxFullWidth,
|
|
size.maxFullHeight,
|
|
size.minFullWidth,
|
|
size.minFullHeight,
|
|
size.fullWidthAlign,
|
|
size.fullHeightAlign,
|
|
size.maxCropWidth,
|
|
size.maxCropHeight,
|
|
size.minCropWidth,
|
|
size.minCropHeight,
|
|
size.cropXAlign,
|
|
size.cropYAlign,
|
|
size.cropWidthAlign,
|
|
size.cropHeightAlign);
|
|
}
|
|
|
|
void ExynosResourceManager::makeFormatRestrictions(restriction_key_t table) {
|
|
|
|
mFormatRestrictions[mFormatRestrictionCnt] = table;
|
|
|
|
HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %s, %d",
|
|
getMPPStr(mFormatRestrictions[mFormatRestrictionCnt].hwType).string(),
|
|
mFormatRestrictions[mFormatRestrictionCnt].nodeType,
|
|
getFormatStr(mFormatRestrictions[mFormatRestrictionCnt].format, COMP_ANY).string(),
|
|
mFormatRestrictions[mFormatRestrictionCnt].reserved);
|
|
mFormatRestrictionCnt++;
|
|
}
|
|
|
|
void ExynosResourceManager::makeAcrylRestrictions(mpp_phycal_type_t type){
|
|
|
|
Acrylic *arc = NULL;
|
|
const HW2DCapability *cap;
|
|
|
|
if (type == MPP_MSC)
|
|
arc = Acrylic::createScaler();
|
|
else if (type == MPP_G2D)
|
|
arc = Acrylic::createCompositor();
|
|
else {
|
|
ALOGE("Unknown MPP");
|
|
return;
|
|
}
|
|
|
|
cap = &arc->getCapabilities();
|
|
|
|
/* format restriction */
|
|
std::unordered_set<int32_t> supportedHalFormats;
|
|
for (uint32_t i = 0; i < FORMAT_MAX_CNT; i++) {
|
|
if (cap->isFormatSupported(exynos_format_desc[i].halFormat)) {
|
|
/* Not add same hal pixel format */
|
|
if (supportedHalFormats.find(exynos_format_desc[i].halFormat) !=
|
|
supportedHalFormats.end())
|
|
continue;
|
|
restriction_key_t queried_format;
|
|
queried_format.hwType = type;
|
|
queried_format.nodeType = NODE_NONE;
|
|
queried_format.format = exynos_format_desc[i].halFormat;
|
|
queried_format.reserved = 0;
|
|
makeFormatRestrictions(queried_format);
|
|
supportedHalFormats.insert(exynos_format_desc[i].halFormat);
|
|
}
|
|
}
|
|
|
|
/* RGB size restrictions */
|
|
restriction_size rSize;
|
|
rSize.maxDownScale = cap->supportedMinMinification().hori;
|
|
rSize.maxUpScale = cap->supportedMaxMagnification().hori;
|
|
rSize.maxFullWidth = cap->supportedMaxSrcDimension().hori;
|
|
rSize.maxFullHeight = cap->supportedMaxSrcDimension().vert;
|
|
rSize.minFullWidth = cap->supportedMinSrcDimension().hori;
|
|
rSize.minFullHeight = cap->supportedMinSrcDimension().vert;
|
|
rSize.fullWidthAlign = cap->supportedDimensionAlign().hori;
|
|
rSize.fullHeightAlign = cap->supportedDimensionAlign().vert;
|
|
rSize.maxCropWidth = cap->supportedMaxSrcDimension().hori;
|
|
rSize.maxCropHeight = cap->supportedMaxSrcDimension().vert;
|
|
rSize.minCropWidth = cap->supportedMinSrcDimension().hori;
|
|
rSize.minCropHeight = cap->supportedMinSrcDimension().vert;
|
|
rSize.cropXAlign = cap->supportedDimensionAlign().hori;
|
|
rSize.cropYAlign = cap->supportedDimensionAlign().vert;
|
|
rSize.cropWidthAlign = cap->supportedDimensionAlign().hori;
|
|
rSize.cropHeightAlign = cap->supportedDimensionAlign().vert;
|
|
|
|
makeSizeRestrictions(type, rSize, RESTRICTION_RGB);
|
|
|
|
/* YUV size restrictions */
|
|
rSize.fullWidthAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
|
|
YUV_CHROMA_H_SUBSAMPLE);
|
|
rSize.fullHeightAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
|
|
YUV_CHROMA_V_SUBSAMPLE);
|
|
rSize.cropXAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
|
|
YUV_CHROMA_H_SUBSAMPLE);
|
|
rSize.cropYAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
|
|
YUV_CHROMA_V_SUBSAMPLE);
|
|
rSize.cropWidthAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
|
|
YUV_CHROMA_H_SUBSAMPLE);
|
|
rSize.cropHeightAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
|
|
YUV_CHROMA_V_SUBSAMPLE);
|
|
|
|
makeSizeRestrictions(type, rSize, RESTRICTION_YUV);
|
|
|
|
delete arc;
|
|
}
|
|
|
|
mpp_phycal_type_t ExynosResourceManager::getPhysicalType(int ch) const {
|
|
|
|
for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
|
|
if(IDMA_CHANNEL_MAP[i].channel == ch)
|
|
return IDMA_CHANNEL_MAP[i].type;
|
|
}
|
|
|
|
return MPP_P_TYPE_MAX;
|
|
}
|
|
|
|
ExynosMPP* ExynosResourceManager::getOtfMPPWithChannel(int ch)
|
|
{
|
|
ExynosMPP *otfMPP = NULL;
|
|
|
|
for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
|
|
if(IDMA_CHANNEL_MAP[i].channel == ch) {
|
|
otfMPP = getExynosMPP(IDMA_CHANNEL_MAP[i].type, IDMA_CHANNEL_MAP[i].index);
|
|
break;
|
|
}
|
|
}
|
|
return otfMPP;
|
|
}
|
|
|
|
void ExynosResourceManager::updateRestrictions() {
|
|
|
|
if (mDevice->mDeviceInterface->getUseQuery() == true) {
|
|
std::unordered_set<uint32_t> checkDuplicateMPP;
|
|
for (const auto unit: AVAILABLE_M2M_MPP_UNITS) {
|
|
if (checkDuplicateMPP.find(unit.physicalType) ==
|
|
checkDuplicateMPP.end()) {
|
|
makeAcrylRestrictions(static_cast<mpp_phycal_type_t>(unit.physicalType));
|
|
checkDuplicateMPP.insert(unit.physicalType);
|
|
}
|
|
}
|
|
} else {
|
|
mFormatRestrictionCnt = sizeof(restriction_format_table)/sizeof(restriction_key);
|
|
for (uint32_t i = 0 ; i < mFormatRestrictionCnt; i++) {
|
|
mFormatRestrictions[i].hwType = restriction_format_table[i].hwType;
|
|
mFormatRestrictions[i].nodeType = restriction_format_table[i].nodeType;
|
|
mFormatRestrictions[i].format = restriction_format_table[i].format;
|
|
mFormatRestrictions[i].reserved = restriction_format_table[i].reserved;
|
|
}
|
|
|
|
// i = RGB, YUV
|
|
// j = Size restriction count for each format (YUV, RGB)
|
|
for (uint32_t i = 0; i < sizeof(restriction_tables)/sizeof(restriction_table_element); i++) {
|
|
mSizeRestrictionCnt[i] = restriction_tables[i].table_element_size;
|
|
for (uint32_t j = 0; j < mSizeRestrictionCnt[i]; j++) {
|
|
memcpy(&mSizeRestrictions[i][j], &restriction_tables[i].table[j],
|
|
sizeof(mSizeRestrictions[i][j]));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
// mAttr should be updated with updated feature_table
|
|
mOtfMPPs[i]->updateAttr();
|
|
mOtfMPPs[i]->setupRestriction();
|
|
}
|
|
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
// mAttr should be updated with updated feature_table
|
|
mM2mMPPs[i]->updateAttr();
|
|
mM2mMPPs[i]->setupRestriction();
|
|
}
|
|
}
|
|
|
|
uint32_t ExynosResourceManager::getFeatureTableSize() const
|
|
{
|
|
return sizeof(feature_table)/sizeof(feature_support_t);
|
|
}
|
|
|
|
bool ExynosResourceManager::hasHDR10PlusMPP() {
|
|
|
|
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
|
|
if (mOtfMPPs[i] == NULL) continue;
|
|
if (mOtfMPPs[i]->mAttr & MPP_ATTR_HDR10PLUS)
|
|
return true;
|
|
}
|
|
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i] == NULL) continue;
|
|
if (mM2mMPPs[i]->mAttr & MPP_ATTR_HDR10PLUS)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
float ExynosResourceManager::getAssignedCapacity(uint32_t physicalType)
|
|
{
|
|
float totalCapacity = 0;
|
|
|
|
for (size_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mPhysicalType == physicalType)
|
|
totalCapacity += mM2mMPPs[i]->getAssignedCapacity();
|
|
}
|
|
return totalCapacity;
|
|
}
|
|
|
|
float ExynosResourceManager::getM2MCapa(uint32_t physicalType)
|
|
{
|
|
float ret = 0;
|
|
for (size_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mPhysicalType == physicalType)
|
|
return mM2mMPPs[i]->mCapacity;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ExynosResourceManager::dump(String8 &result) const {
|
|
result.appendFormat("Resource Manager:\n");
|
|
|
|
result.appendFormat("[RGB Restrictions]\n");
|
|
dump(RESTRICTION_RGB, result);
|
|
|
|
result.appendFormat("[YUV Restrictions]\n");
|
|
dump(RESTRICTION_YUV, result);
|
|
}
|
|
|
|
void ExynosResourceManager::dump(const restriction_classification_t classification,
|
|
String8 &result) const {
|
|
const auto &restrictions = mSizeRestrictions[classification];
|
|
const auto &restrictionCnt = mSizeRestrictionCnt[classification];
|
|
|
|
for (int i = 0; i < restrictionCnt; ++i) {
|
|
result.appendFormat("HW-Node %u-%u:\n", restrictions[i].key.hwType,
|
|
restrictions[i].key.nodeType);
|
|
if (i > 0 && restrictions[i].sizeRestriction == restrictions[i - 1].sizeRestriction) {
|
|
result.append("Same as above\n");
|
|
} else {
|
|
::dump(restrictions[i].sizeRestriction, result);
|
|
}
|
|
result.appendFormat("\n");
|
|
}
|
|
}
|
|
|
|
void ExynosResourceManager::setM2MCapa(uint32_t physicalType, uint32_t capa)
|
|
{
|
|
for (size_t i = 0; i < mM2mMPPs.size(); i++) {
|
|
if (mM2mMPPs[i]->mPhysicalType == physicalType)
|
|
mM2mMPPs[i]->mCapacity = capa;
|
|
}
|
|
}
|