blob: 0380f3d70a41607d12f6b8b0eb805747249593aa [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#include "ExynosResourceManagerModule.h"
#include <cutils/properties.h>
#include <list>
#include <utility>
#include "ExynosLayer.h"
using namespace zuma;
constexpr uint32_t TDM_OVERLAP_MARGIN = 68;
constexpr uint32_t kSramSBWCWidthAlign = 32;
constexpr uint32_t kSramSBWCWidthMargin = kSramSBWCWidthAlign - 1;
constexpr uint32_t kSramSBWCRotWidthAlign = 4;
constexpr uint32_t kSramAFBC8B4BAlign = 8;
constexpr uint32_t kSramAFBC8B4BMargin = kSramAFBC8B4BAlign - 1;
constexpr uint32_t kSramAFBC2BAlign = 16;
constexpr uint32_t kSramAFBC2BMargin = kSramAFBC2BAlign - 1;
ExynosResourceManagerModule::ExynosResourceManagerModule(ExynosDevice *device)
: gs201::ExynosResourceManagerModule(device)
{
// HW Resource Table for TDM based allocation
mHWResourceTables = &HWResourceTables;
char value[PROPERTY_VALUE_MAX];
property_get("ro.boot.hw.soc.rev", value, "2");
const int socRev = atoi(value);
mConstraintRev = socRev < 2 ? CONSTRAINT_A0 : CONSTRAINT_B0;
HWAttrs.at(TDM_ATTR_WCG).loadSharing =
(mConstraintRev == CONSTRAINT_A0) ? LS_DPUF : LS_DPUF_AXI;
ALOGD("%s(): ro.boot.hw.soc.rev=%s ConstraintRev=%d", __func__, value, mConstraintRev);
}
ExynosResourceManagerModule::~ExynosResourceManagerModule() {}
bool ExynosResourceManagerModule::checkTDMResource(ExynosDisplay *display, ExynosMPP *currentMPP,
ExynosMPPSource *mppSrc) {
std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAmount{};
std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAXIAmount{};
const uint32_t blkId = currentMPP->getHWBlockId();
const uint32_t axiId = currentMPP->getAXIPortId();
HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s, compare with layers", __func__,
mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str());
ExynosLayer *layer = (mppSrc->mSourceType == MPP_SOURCE_LAYER) ? (ExynosLayer *)mppSrc : nullptr;
for (auto compLayer : display->mLayers) {
ExynosMPP *otfMPP = compLayer->mOtfMPP;
if (!otfMPP || layer == compLayer) continue;
getAmounts(display, blkId, axiId, otfMPP, mppSrc, compLayer,
accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
}
if (display->mExynosCompositionInfo.mHasCompositionLayer) {
HDEBUGLOGD(eDebugTDM,
"%s : %p trying to assign to %s, compare with ExynosComposition Target buffer",
__func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str());
ExynosMPP *otfMPP = display->mExynosCompositionInfo.mOtfMPP;
if (otfMPP)
getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mExynosCompositionInfo,
accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
}
if (display->mClientCompositionInfo.mHasCompositionLayer) {
HDEBUGLOGD(eDebugTDM,
"%s : %p trying to assign to %s, compare with ClientComposition Target buffer",
__func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str());
ExynosMPP *otfMPP = display->mClientCompositionInfo.mOtfMPP;
if (otfMPP)
getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mClientCompositionInfo,
accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
}
for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
const LoadSharing_t &loadSharing = attr->second.loadSharing;
uint32_t currentAmount = mppSrc->getHWResourceAmount(attr->first);
auto &accumulatedAmount =
(loadSharing == LS_DPUF) ? accumulatedDPUFAmount : accumulatedDPUFAXIAmount;
const auto &TDMInfoIdx =
std::make_pair(blkId,
(loadSharing == LS_DPUF) ? AXI_DONT_CARE : axiId);
int32_t totalAmount =
display->mDisplayTDMInfo[TDMInfoIdx].getAvailableAmount(attr->first).totalAmount;
HDEBUGLOGD(eDebugTDM,
"%s, layer[%p] -> %s attr[%s],ls=%d,accumulated:%d,current:%d,total: %d",
__func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str(),
attr->second.name.c_str(), loadSharing, accumulatedAmount[attr->first],
currentAmount, totalAmount);
if (accumulatedAmount[attr->first] + currentAmount > totalAmount) {
HDEBUGLOGD(eDebugTDM, "%s, %s could not assigned by attr[%s]", __func__,
currentMPP->mName.c_str(), attr->second.name.c_str());
return false;
}
}
HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s successfully", __func__,
mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str());
return true;
}
bool ExynosResourceManagerModule::isHWResourceAvailable(ExynosDisplay *display,
ExynosMPP *currentMPP,
ExynosMPPSource *mppSrc) {
if (!checkTDMResource(display, currentMPP, mppSrc)) {
return false;
}
std::list<ExynosLayer *> overlappedLayers;
uint32_t currentBlockId = currentMPP->getHWBlockId();
for (auto layer : display->mLayers) {
ExynosMPP *otfMPP = layer->mOtfMPP;
if (!otfMPP || dynamic_cast<ExynosMPPSource *>(layer) == mppSrc) continue;
if ((currentBlockId == otfMPP->getHWBlockId()) && isOverlapped(display, mppSrc, layer))
overlappedLayers.push_back(layer);
}
if (overlappedLayers.size()) {
HDEBUGLOGD(eDebugTDM,
"%s : %p trying to assign to %s, check its overlapped layers(%zu) status",
__func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.c_str(),
overlappedLayers.size());
for (auto &overlappedLayer : overlappedLayers) {
HDEBUGLOGD(eDebugTDM, "%s : %p overlapped %p", __func__, mppSrc->mSrcImg.bufferHandle,
overlappedLayer->mLayerBuffer);
if (!checkTDMResource(display, overlappedLayer->mOtfMPP, overlappedLayer)) {
return false;
}
}
}
return true;
}
void ExynosResourceManagerModule::setupHWResource(const tdm_attr_t& tdmAttrId, const String8& name,
const DPUblockId_t& blkId,
const AXIPortId_t& axiId, ExynosDisplay* mainDisp,
ExynosDisplay* minorDisp,
const ConstraintRev_t& constraintsRev) {
const auto& resourceIdx = HWResourceIndexes(tdmAttrId, blkId, axiId, constraintsRev);
const auto &iter = mHWResourceTables->find(resourceIdx);
if (iter != mHWResourceTables->end()) {
auto &hwResource = iter->second;
const auto &TDMInfoIdx = (HWAttrs.at(tdmAttrId).loadSharing == LS_DPUF)
? std::make_pair(blkId, AXI_DONT_CARE)
: std::make_pair(blkId, axiId);
const uint32_t mainAmount =
(minorDisp != nullptr) ? hwResource.mainAmount
: hwResource.mainAmount + hwResource.minorAmount;
mainDisp->mDisplayTDMInfo[TDMInfoIdx]
.initTDMInfo(DisplayTDMInfo::ResourceAmount_t{mainAmount}, tdmAttrId);
if (minorDisp != nullptr) {
const uint32_t minorAmount = hwResource.minorAmount;
minorDisp->mDisplayTDMInfo[TDMInfoIdx]
.initTDMInfo(DisplayTDMInfo::ResourceAmount_t{minorAmount}, tdmAttrId);
}
} else {
ALOGW("(%s): cannot find resource for %s", resourceIdx.toString8().c_str(), name.c_str());
}
}
uint32_t ExynosResourceManagerModule::setDisplaysTDMInfo(ExynosDisplay* mainDisp,
ExynosDisplay* minorDisp) {
/*
* Update main/minor display resource amount
* If only one display exists, all TDM resources are allocated for the only display.
*/
for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
if (attr->second.loadSharing == LS_DPUF) {
setupHWResource(attr->first, attr->second.name, blockId->first, AXI_DONT_CARE,
mainDisp, minorDisp, mConstraintRev);
} else if (attr->second.loadSharing == LS_DPUF_AXI) {
for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
setupHWResource(attr->first, attr->second.name, blockId->first, axi->first,
mainDisp, minorDisp, mConstraintRev);
}
}
else {
ALOGE("%s attr[%s] wrong load sharing=%d", __func__, attr->second.name.c_str(),
attr->second.loadSharing);
return BAD_TYPE;
}
}
}
if (hwcCheckDebugMessages(eDebugTDM)) {
for (auto &display : mDisplays) {
if (!(display->mPlugState == true && display->mPowerModeState.has_value() &&
display->mPowerModeState.value() != (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
continue;
for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
if (attr->second.loadSharing == LS_DPUF) {
const auto &TDMInfoId = std::make_pair(blockId->first, AXI_DONT_CARE);
int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
.getAvailableAmount(attr->first)
.totalAmount;
HDEBUGLOGD(eDebugTDM, "%s : [%s] display:%d,block:%d, amount : %d(%s)",
__func__, attr->second.name.c_str(), display->mDisplayId,
blockId->first, amount,
display->isEnabled() ? "used" : "not used");
} else {
for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
const auto &TDMInfoId = std::make_pair(blockId->first, axi->first);
int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
.getAvailableAmount(attr->first)
.totalAmount;
HDEBUGLOGD(eDebugTDM,
"%s : [%s] display:%d,block:%d,axi:%d, amount:%d(%s)",
__func__, attr->second.name.c_str(), display->mType,
blockId->first, axi->first, amount,
display->isEnabled() ? "used" : "not used");
}
}
}
}
}
}
return NO_ERROR;
}
uint32_t getSramAmount(tdm_attr_t attr, uint32_t formatProperty, lbWidthIndex_t widthIndex) {
auto it = sramAmountMap.find(sramAmountParams(attr, formatProperty, widthIndex));
return (it != sramAmountMap.end()) ? it->second : 0;
}
uint32_t ExynosResourceManagerModule::calculateHWResourceAmount(ExynosDisplay *display,
ExynosMPPSource *mppSrc)
{
uint32_t SRAMtotal = 0;
if (mppSrc == nullptr) return SRAMtotal;
if (mppSrc->mSourceType == MPP_SOURCE_LAYER) {
ExynosLayer *layer = static_cast<ExynosLayer *>(mppSrc->mSource);
if (layer == nullptr) {
ALOGE("%s: cannot cast ExynosLayer", __func__);
return SRAMtotal;
}
exynos_image src_img;
exynos_image dst_img;
layer->setSrcExynosImage(&src_img);
layer->setDstExynosImage(&dst_img);
layer->setExynosImage(src_img, dst_img);
}
int32_t transform = mppSrc->mSrcImg.transform;
int32_t compressType = mppSrc->mSrcImg.compressionInfo.type;
bool rotation = (transform & HAL_TRANSFORM_ROT_90) ? true : false;
int32_t width = mppSrc->mSrcImg.w;
int32_t height = mppSrc->mSrcImg.h;
uint32_t format = mppSrc->mSrcImg.format;
uint32_t formatBPP = 0;
if (isFormat10Bit(format))
formatBPP = BIT10;
else if (isFormat8Bit(format))
formatBPP = BIT8;
/** To find index **/
uint32_t formatIndex = 0;
lbWidthIndex_t widthIndex = LB_W_3073_INF;
auto findWidthIndex = [&](int32_t w) -> lbWidthIndex_t {
for (auto it = LB_WIDTH_INDEX_MAP.begin(); it != LB_WIDTH_INDEX_MAP.end(); it++) {
if (w >= it->second.widthDownto && w <= it->second.widthUpto) {
return it->first;
}
}
return LB_W_3073_INF;
};
/* Caluclate SRAM amount */
if (rotation) {
width = height;
/* Rotation amount, Only YUV rotation is supported */
if (compressType == COMP_TYPE_SBWC) {
/* Y and UV width should be aligned and should get sram for each Y and UV */
int32_t width_y = pixel_align(width + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
int32_t width_c =
pixel_align(width / 2 + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_Y, findWidthIndex(width_y));
SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_UV, findWidthIndex(width_c * 2));
} else {
/* sramAmountMap has SRAM for both Y and UV */
widthIndex = findWidthIndex(width);
SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_Y | formatBPP, widthIndex);
SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_UV | formatBPP, widthIndex);
}
HDEBUGLOGD(eDebugTDM, "+ rotation : %d", SRAMtotal);
} else {
if (compressType == COMP_TYPE_SBWC) {
width = pixel_align(width + kSramSBWCWidthMargin, kSramSBWCWidthAlign);
} else if (compressType == COMP_TYPE_AFBC) {
/* Align for 8,4Byte/pixel formats */
if (formatToBpp(format) > 16) {
width = pixel_align(width + kSramAFBC8B4BMargin, kSramAFBC8B4BAlign);
} else {
/* Align for 2Byte/pixel formats */
width = pixel_align(width + kSramAFBC2BMargin, kSramAFBC2BAlign);
}
}
widthIndex = findWidthIndex(width);
/* AFBC amount */
if (compressType == COMP_TYPE_AFBC) {
formatIndex = (isFormatRgb(format) ? RGB : 0) | formatBPP;
SRAMtotal += getSramAmount(TDM_ATTR_AFBC, formatIndex, widthIndex);
HDEBUGLOGD(eDebugTDM, "+ AFBC : %d", SRAMtotal);
}
/* SBWC amount */
if (compressType == COMP_TYPE_SBWC) {
SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_Y, widthIndex);
SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_UV, widthIndex);
HDEBUGLOGD(eDebugTDM, "+ SBWC : %d", SRAMtotal);
}
}
/* ITP (CSC) amount */
if (isFormatYUV(format)) {
/** ITP has no size difference, Use width index as LB_W_3073_INF **/
SRAMtotal += getSramAmount(TDM_ATTR_ITP, formatBPP, LB_W_3073_INF);
HDEBUGLOGD(eDebugTDM, "+ YUV : %d", SRAMtotal);
}
/* Scale amount */
int srcW = mppSrc->mSrcImg.w;
int srcH = mppSrc->mSrcImg.h;
int dstW = mppSrc->mDstImg.w;
int dstH = mppSrc->mDstImg.h;
if (!!(transform & HAL_TRANSFORM_ROT_90)) {
int tmp = dstW;
dstW = dstH;
dstH = tmp;
}
bool isScaled = ((srcW != dstW) || (srcH != dstH));
if (isScaled) {
if (formatHasAlphaChannel(format))
formatIndex = FORMAT_RGB_MASK;
else
formatIndex = FORMAT_YUV_MASK;
/** Scale has no size difference, Use width index as LB_W_3073_INF **/
SRAMtotal += getSramAmount(TDM_ATTR_SCALE, formatIndex, LB_W_3073_INF);
HDEBUGLOGD(eDebugTDM, "+ Scale : %d", SRAMtotal);
}
for (auto it = HWAttrs.begin(); it != HWAttrs.end(); it++) {
uint32_t amount = 0;
if (it->first == TDM_ATTR_SRAM_AMOUNT) {
amount = SRAMtotal;
} else {
amount = needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, it->first);
}
mppSrc->setHWResourceAmount(it->first, amount);
}
HDEBUGLOGD(eDebugTDM,
"mppSrc(%p) needed SRAM(%d), SCALE(%d), AFBC(%d), CSC(%d), SBWC(%d), WCG(%d), "
"ROT(%d)",
mppSrc->mSrcImg.bufferHandle, SRAMtotal,
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SCALE),
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_AFBC),
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ITP),
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SBWC),
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_WCG),
needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ROT_90));
return SRAMtotal;
}
int32_t ExynosResourceManagerModule::otfMppReordering(ExynosDisplay *display,
ExynosMPPVector &otfMPPs,
struct exynos_image &src,
struct exynos_image &dst)
{
int orderingType = isAFBCCompressed(src.bufferHandle)
? ORDER_AFBC
: (needHdrProcessing(display, src, dst) ? ORDER_WCG : ORDER_AXI);
int usedAFBCCount[DPU_BLOCK_CNT] = {0};
int usedWCGCount[DPU_BLOCK_CNT * AXI_PORT_MAX_CNT] = {0};
int usedBlockCount[DPU_BLOCK_CNT] = {0};
int usedAXIPortCount[AXI_PORT_MAX_CNT] = {0};
auto orderPolicy = [&](const void *lhs, const void *rhs) -> bool {
if (lhs == NULL || rhs == NULL) {
return 0;
}
const ExynosMPPModule *l = (ExynosMPPModule *)lhs;
const ExynosMPPModule *r = (ExynosMPPModule *)rhs;
uint32_t assignedStateL = l->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
uint32_t assignedStateR = r->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
if (assignedStateL != assignedStateR) return assignedStateL < assignedStateR;
if (l->mPhysicalType != r->mPhysicalType) return l->mPhysicalType < r->mPhysicalType;
if (orderingType == ORDER_AFBC) {
/* AFBC balancing */
if ((l->mAttr & MPP_ATTR_AFBC) != (r->mAttr & MPP_ATTR_AFBC))
return (l->mAttr & MPP_ATTR_AFBC) > (r->mAttr & MPP_ATTR_AFBC);
if (l->mAttr & MPP_ATTR_AFBC) {
/* If layer is AFBC, DPU block that AFBC HW block belongs
* which has not been used much should be placed in the front */
if (usedAFBCCount[l->mHWBlockId] != usedAFBCCount[r->mHWBlockId])
return usedAFBCCount[l->mHWBlockId] < usedAFBCCount[r->mHWBlockId];
}
} else if (orderingType == ORDER_WCG) {
/* WCG balancing */
if ((l->mAttr & MPP_ATTR_WCG) != (r->mAttr & MPP_ATTR_WCG))
return (l->mAttr & MPP_ATTR_WCG) > (r->mAttr & MPP_ATTR_WCG);
if (l->mAttr & MPP_ATTR_WCG) {
/* If layer is WCG, DPU block that WCG HW block belongs
* which has not been used much should be placed in the front */
if (usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] !=
usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId])
return usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] <
usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId];
}
}
/* AXI bus balancing */
/* AXI port which has not been used much should be placed in the front */
if (usedAXIPortCount[l->mAXIPortId] != usedAXIPortCount[r->mAXIPortId]) {
return usedAXIPortCount[l->mAXIPortId] < usedAXIPortCount[r->mAXIPortId];
}
/* IF MPP connected same AXI port, Block balancing should be regarded after */
if (usedBlockCount[l->mHWBlockId] != usedBlockCount[r->mHWBlockId])
return usedBlockCount[l->mHWBlockId] < usedBlockCount[r->mHWBlockId];
return l->mPhysicalIndex < r->mPhysicalIndex;
};
for (auto it : otfMPPs) {
ExynosMPPModule *mpp = (ExynosMPPModule *)it;
uint32_t bId = mpp->getHWBlockId();
uint32_t aId = mpp->getAXIPortId();
bool isAFBC = false;
bool isWCG = false;
if (mpp->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) {
ExynosMPPSource *mppSrc = mpp->mAssignedSources[0];
if ((mppSrc->mSourceType == MPP_SOURCE_LAYER) &&
(mppSrc->mSrcImg.bufferHandle != nullptr)) {
if ((mpp->mAttr & MPP_ATTR_AFBC) &&
(isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
isAFBC = true;
usedAFBCCount[bId]++;
} else if ((mpp->mAttr & MPP_ATTR_WCG) &&
(needHdrProcessing(display, mppSrc->mSrcImg, mppSrc->mDstImg))) {
isWCG = true;
usedWCGCount[bId]++;
}
} else if (mppSrc->mSourceType == MPP_SOURCE_COMPOSITION_TARGET) {
ExynosCompositionInfo *info = (ExynosCompositionInfo *)mppSrc;
// ESTEVAN_TBD
// if ((mpp->mAttr & MPP_ATTR_AFBC) && (info->mCompressionInfo.type ==
// COMP_TYPE_AFBC)) {
if ((mpp->mAttr & MPP_ATTR_AFBC) &&
(isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
isAFBC = true;
usedAFBCCount[bId]++;
} else if ((mpp->mAttr & MPP_ATTR_WCG) &&
(needHdrProcessing(display, info->mSrcImg, info->mDstImg))) {
isWCG = true;
usedWCGCount[bId]++;
}
}
HDEBUGLOGD(eDebugLoadBalancing, "%s: %s is assigned (AFBC:%d, WCG:%d), is %s", __func__,
mpp->mName.c_str(), isAFBC, isWCG,
(mppSrc->mSourceType == MPP_SOURCE_LAYER) ? "Layer" : "Client Target");
usedBlockCount[bId]++;
usedAXIPortCount[aId]++;
}
}
HDEBUGLOGD(eDebugLoadBalancing,
"Sorting by %s ordering, AFBC(used DPUF0:%d, DPUF1:%d), AXI(used AXI0:%d, AXI1:%d), "
"BLOCK(used DPUF0:%d, DPUF1:%d)",
(orderingType == ORDER_AFBC) ? "AFBC" : "_AXI", usedAFBCCount[DPUF0],
usedAFBCCount[DPUF1], usedAXIPortCount[AXI0], usedAXIPortCount[AXI1],
usedBlockCount[DPUF0], usedBlockCount[DPUF1]);
std::sort(otfMPPs.begin(), otfMPPs.end(), orderPolicy);
if (hwcCheckDebugMessages(eDebugLoadBalancing)) {
String8 after;
for (uint32_t i = 0; i < otfMPPs.size(); i++) {
ExynosMPPModule *mpp = (ExynosMPPModule *)otfMPPs[i];
after.appendFormat("(%s) -> ", mpp->mName.c_str());
}
ALOGD("%s %p, %s", __func__, src.bufferHandle, after.c_str());
}
return 0;
}
bool ExynosResourceManagerModule::isOverlapped(ExynosDisplay *display, ExynosMPPSource *current,
ExynosMPPSource *compare) {
int CT = current->mDstImg.y - TDM_OVERLAP_MARGIN;
CT = (CT < 0) ? 0 : CT;
int CB = current->mDstImg.y + current->mDstImg.h + TDM_OVERLAP_MARGIN;
CB = (CB > display->mYres) ? display->mYres : CB;
int LT = compare->mDstImg.y;
int LB = compare->mDstImg.y + compare->mDstImg.h;
if (((LT <= CT && CT <= LB) || (LT <= CB && CB <= LB)) ||
((CT <= LT && LT <= CB) || (CT < LB && LB <= CB))) {
HDEBUGLOGD(eDebugTDM, "%s, current %p and compare %p is overlaped", __func__,
current->mSrcImg.bufferHandle, compare->mSrcImg.bufferHandle);
return true;
}
return false;
}
uint32_t ExynosResourceManagerModule::getAmounts(ExynosDisplay* display, uint32_t currentBlockId,
uint32_t currentAXIId, ExynosMPP* compOtfMPP,
ExynosMPPSource* curSrc, ExynosMPPSource* compSrc,
std::array<uint32_t, TDM_ATTR_MAX>& DPUFAmounts,
std::array<uint32_t, TDM_ATTR_MAX>& AXIAmounts) {
const uint32_t blockId = compOtfMPP->getHWBlockId();
const uint32_t AXIId = compOtfMPP->getAXIPortId();
if (currentBlockId == blockId && isOverlapped(display, curSrc, compSrc)) {
String8 log;
if (hwcCheckDebugMessages(eDebugTDM)) {
log.appendFormat("%s", compOtfMPP->mName.c_str());
}
for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
uint32_t compareAmount = compSrc->getHWResourceAmount(attr->first);
if (hwcCheckDebugMessages(eDebugTDM)) {
log.appendFormat(", attr %s DPUF-%d(+ %d)", attr->second.name.c_str(),
DPUFAmounts[attr->first], compareAmount);
}
DPUFAmounts[attr->first] += compareAmount;
if (attr->second.loadSharing == LS_DPUF_AXI && currentAXIId == AXIId) {
if (hwcCheckDebugMessages(eDebugTDM)) {
log.appendFormat(",AXI-%d(+ %d)", AXIAmounts[attr->first], compareAmount);
}
AXIAmounts[attr->first] += compareAmount;
}
}
HDEBUGLOGD(eDebugTDM, "%s %s", __func__, log.c_str());
}
return 0;
}