• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "ExynosResourceManagerModule.h"
18 
19 #include <cutils/properties.h>
20 
21 #include <list>
22 #include <utility>
23 
24 #include "ExynosLayer.h"
25 
26 using namespace zuma;
27 
28 constexpr uint32_t TDM_OVERLAP_MARGIN = 68;
29 
30 constexpr uint32_t kSramSBWCWidthAlign = 32;
31 constexpr uint32_t kSramSBWCWidthMargin = kSramSBWCWidthAlign - 1;
32 constexpr uint32_t kSramSBWCRotWidthAlign = 4;
33 constexpr uint32_t kSramAFBC8B4BAlign = 8;
34 constexpr uint32_t kSramAFBC8B4BMargin = kSramAFBC8B4BAlign - 1;
35 constexpr uint32_t kSramAFBC2BAlign = 16;
36 constexpr uint32_t kSramAFBC2BMargin = kSramAFBC2BAlign - 1;
37 
ExynosResourceManagerModule(ExynosDevice * device)38 ExynosResourceManagerModule::ExynosResourceManagerModule(ExynosDevice *device)
39 : gs201::ExynosResourceManagerModule(device)
40 {
41     // HW Resource Table for TDM based allocation
42     mHWResourceTables = &HWResourceTables;
43 
44     char value[PROPERTY_VALUE_MAX];
45     property_get("ro.boot.hw.soc.rev", value, "2");
46     const int socRev = atoi(value);
47     mConstraintRev = socRev < 2 ? CONSTRAINT_A0 : CONSTRAINT_B0;
48     HWAttrs.at(TDM_ATTR_WCG).loadSharing =
49             (mConstraintRev == CONSTRAINT_A0) ? LS_DPUF : LS_DPUF_AXI;
50     ALOGD("%s(): ro.boot.hw.soc.rev=%s ConstraintRev=%d", __func__, value, mConstraintRev);
51 }
52 
~ExynosResourceManagerModule()53 ExynosResourceManagerModule::~ExynosResourceManagerModule() {}
54 
checkTDMResource(ExynosDisplay * display,ExynosMPP * currentMPP,ExynosMPPSource * mppSrc)55 bool ExynosResourceManagerModule::checkTDMResource(ExynosDisplay *display, ExynosMPP *currentMPP,
56                                                    ExynosMPPSource *mppSrc) {
57     std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAmount{};
58     std::array<uint32_t, TDM_ATTR_MAX> accumulatedDPUFAXIAmount{};
59     const uint32_t blkId = currentMPP->getHWBlockId();
60     const uint32_t axiId = currentMPP->getAXIPortId();
61     HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s, compare with layers", __func__,
62                mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
63     ExynosLayer *layer = (mppSrc->mSourceType == MPP_SOURCE_LAYER) ? (ExynosLayer *)mppSrc : nullptr;
64 
65     for (auto compLayer : display->mLayers) {
66         ExynosMPP *otfMPP = compLayer->mOtfMPP;
67         if (!otfMPP || layer == compLayer) continue;
68         getAmounts(display, blkId, axiId, otfMPP, mppSrc, compLayer,
69                    accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
70     }
71 
72     if (display->mExynosCompositionInfo.mHasCompositionLayer) {
73         HDEBUGLOGD(eDebugTDM,
74                    "%s : %p trying to assign to %s, compare with ExynosComposition Target buffer",
75                    __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
76         ExynosMPP *otfMPP = display->mExynosCompositionInfo.mOtfMPP;
77         if (otfMPP)
78             getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mExynosCompositionInfo,
79                        accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
80     }
81 
82     if (display->mClientCompositionInfo.mHasCompositionLayer) {
83         HDEBUGLOGD(eDebugTDM,
84                    "%s : %p trying to assign to %s, compare with ClientComposition Target buffer",
85                    __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
86         ExynosMPP *otfMPP = display->mClientCompositionInfo.mOtfMPP;
87         if (otfMPP)
88             getAmounts(display, blkId, axiId, otfMPP, mppSrc, &display->mClientCompositionInfo,
89                        accumulatedDPUFAmount, accumulatedDPUFAXIAmount);
90     }
91 
92     for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
93         const LoadSharing_t &loadSharing = attr->second.loadSharing;
94         uint32_t currentAmount = mppSrc->getHWResourceAmount(attr->first);
95         auto &accumulatedAmount =
96                 (loadSharing == LS_DPUF) ? accumulatedDPUFAmount : accumulatedDPUFAXIAmount;
97         const auto &TDMInfoIdx =
98                 std::make_pair(blkId,
99                                (loadSharing == LS_DPUF) ? AXI_DONT_CARE : axiId);
100         int32_t totalAmount =
101                 display->mDisplayTDMInfo[TDMInfoIdx].getAvailableAmount(attr->first).totalAmount;
102         HDEBUGLOGD(eDebugTDM,
103                    "%s, layer[%p] -> %s attr[%s],ls=%d,accumulated:%d,current:%d,total: %d",
104                    __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string(),
105                    attr->second.name.string(), loadSharing, accumulatedAmount[attr->first],
106                    currentAmount, totalAmount);
107         if (accumulatedAmount[attr->first] + currentAmount > totalAmount) {
108             HDEBUGLOGD(eDebugTDM, "%s, %s could not assigned by attr[%s]", __func__,
109                        currentMPP->mName.string(), attr->second.name.string());
110             return false;
111         }
112     }
113 
114     HDEBUGLOGD(eDebugTDM, "%s : %p trying to assign to %s successfully", __func__,
115                mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string());
116     return true;
117 }
118 
isHWResourceAvailable(ExynosDisplay * display,ExynosMPP * currentMPP,ExynosMPPSource * mppSrc)119 bool ExynosResourceManagerModule::isHWResourceAvailable(ExynosDisplay *display,
120                                                         ExynosMPP *currentMPP,
121                                                         ExynosMPPSource *mppSrc) {
122     if (!checkTDMResource(display, currentMPP, mppSrc)) {
123         return false;
124     }
125 
126     std::list<ExynosLayer *> overlappedLayers;
127     uint32_t currentBlockId = currentMPP->getHWBlockId();
128     for (auto layer : display->mLayers) {
129         ExynosMPP *otfMPP = layer->mOtfMPP;
130         if (!otfMPP || dynamic_cast<ExynosMPPSource *>(layer) == mppSrc) continue;
131 
132         if ((currentBlockId == otfMPP->getHWBlockId()) && isOverlapped(display, mppSrc, layer))
133             overlappedLayers.push_back(layer);
134     }
135 
136     if (overlappedLayers.size()) {
137         HDEBUGLOGD(eDebugTDM,
138                    "%s : %p trying to assign to %s, check its overlapped layers(%zu) status",
139                    __func__, mppSrc->mSrcImg.bufferHandle, currentMPP->mName.string(),
140                    overlappedLayers.size());
141 
142         for (auto &overlappedLayer : overlappedLayers) {
143             HDEBUGLOGD(eDebugTDM, "%s : %p overlapped %p", __func__, mppSrc->mSrcImg.bufferHandle,
144                        overlappedLayer->mLayerBuffer);
145             if (!checkTDMResource(display, overlappedLayer->mOtfMPP, overlappedLayer)) {
146                 return false;
147             }
148         }
149     }
150     return true;
151 }
152 
setupHWResource(const tdm_attr_t & tdmAttrId,const String8 & name,const DPUblockId_t & blkId,const AXIPortId_t & axiId,ExynosDisplay * display,ExynosDisplay * addedDisplay,const ConstraintRev_t & constraintsRev)153 void ExynosResourceManagerModule::setupHWResource(const tdm_attr_t &tdmAttrId, const String8 &name,
154                                                   const DPUblockId_t &blkId,
155                                                   const AXIPortId_t &axiId, ExynosDisplay *display,
156                                                   ExynosDisplay *addedDisplay,
157                                                   const ConstraintRev_t &constraintsRev) {
158     const int32_t dispType = display->mType;
159     const auto &resourceIdx = HWResourceIndexes(tdmAttrId, blkId, axiId, dispType, constraintsRev);
160     const auto &iter = mHWResourceTables->find(resourceIdx);
161     if (iter != mHWResourceTables->end()) {
162         auto &hwResource = iter->second;
163         const auto &TDMInfoIdx = (HWAttrs.at(tdmAttrId).loadSharing == LS_DPUF)
164                 ? std::make_pair(blkId, AXI_DONT_CARE)
165                 : std::make_pair(blkId, axiId);
166         uint32_t amount = (addedDisplay == nullptr) ? hwResource.maxAssignedAmount
167                                                     : hwResource.totalAmount -
168                         addedDisplay->mDisplayTDMInfo[TDMInfoIdx]
169                                 .getAvailableAmount(tdmAttrId)
170                                 .totalAmount;
171         display->mDisplayTDMInfo[TDMInfoIdx].initTDMInfo(DisplayTDMInfo::ResourceAmount_t{amount},
172                                                          tdmAttrId);
173         if (addedDisplay == nullptr) {
174             HDEBUGLOGD(eDebugTDM, "(%s=>%s) : %s amount is updated to %d",
175                        resourceIdx.toString8().string(), iter->first.toString8().string(),
176                        name.string(), amount);
177         } else {
178             HDEBUGLOGD(eDebugTDM,
179                        "(%s=>%s) : hwResource.totalAmount=%d %s amount is updated to %d",
180                        resourceIdx.toString8().string(), iter->first.toString8().string(),
181                        hwResource.totalAmount, name.string(), amount);
182         }
183     } else {
184         ALOGW("(%s): cannot find resource for %s", resourceIdx.toString8().string(), name.string());
185     }
186 }
187 
setDisplaysTDMInfo()188 uint32_t ExynosResourceManagerModule::setDisplaysTDMInfo()
189 {
190     ExynosDisplay *addedDisplay = nullptr;
191 
192     /*
193      * Checking display connections,
194      * Assume that WFD and External are not connected at the same time
195      * If non-primary display is connected, primary display's HW resource is looted
196      */
197     for (auto &display : mDisplays) {
198         if (display->mType == HWC_DISPLAY_PRIMARY) continue;
199         if (display->isEnabled()) {
200             addedDisplay = display;
201             break;
202         }
203     }
204 
205     /*
206      * Update Primary's resource amount. primary = total - loot(other display's HW resource)
207      * Other's aready defined at initDisplaysTDMInfo()
208      */
209     ExynosDisplay *primaryDisplay = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
210     for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
211         for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
212             if (attr->second.loadSharing == LS_DPUF) {
213                 setupHWResource(attr->first, attr->second.name, blockId->first, AXI_DONT_CARE,
214                                 primaryDisplay, addedDisplay, mConstraintRev);
215             } else if (attr->second.loadSharing == LS_DPUF_AXI) {
216                 for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
217                     setupHWResource(attr->first, attr->second.name, blockId->first, axi->first,
218                                     primaryDisplay, addedDisplay, mConstraintRev);
219                 }
220             }
221         }
222     }
223 
224     if (hwcCheckDebugMessages(eDebugTDM)) {
225         for (auto &display : mDisplays) {
226             for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
227                 for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
228                     if (attr->second.loadSharing == LS_DPUF) {
229                         const auto &TDMInfoId = std::make_pair(blockId->first, AXI_DONT_CARE);
230                         int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
231                                                  .getAvailableAmount(attr->first)
232                                                  .totalAmount;
233                         HDEBUGLOGD(eDebugTDM, "%s : [%s] display:%d,block:%d, amount : %d(%s)",
234                                    __func__, attr->second.name.string(), display->mType,
235                                    blockId->first, amount,
236                                    display->isEnabled() ? "used" : "not used");
237                     } else {
238                         for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
239                             const auto &TDMInfoId = std::make_pair(blockId->first, axi->first);
240                             int32_t amount = display->mDisplayTDMInfo[TDMInfoId]
241                                                      .getAvailableAmount(attr->first)
242                                                      .totalAmount;
243                             HDEBUGLOGD(eDebugTDM,
244                                        "%s : [%s] display:%d,block:%d,axi:%d, amount:%d(%s)",
245                                        __func__, attr->second.name.string(), display->mType,
246                                        blockId->first, axi->first, amount,
247                                        display->isEnabled() ? "used" : "not used");
248                         }
249                     }
250                 }
251             }
252         }
253     }
254 
255     return 0;
256 }
257 
initDisplaysTDMInfo()258 uint32_t ExynosResourceManagerModule::initDisplaysTDMInfo()
259 {
260     /*
261      * Initialize as predefined value at table
262      * Primary's resource will be changed at setDisplaysTDMInfo() function
263      */
264     for (auto &display : mDisplays) {
265         for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
266             for (auto blockId = DPUBlocks.begin(); blockId != DPUBlocks.end(); blockId++) {
267                 if (attr->second.loadSharing == LS_DPUF) {
268                     setupHWResource(attr->first, attr->second.name, blockId->first, AXI_DONT_CARE,
269                                     display, nullptr, mConstraintRev);
270                 } else if (attr->second.loadSharing == LS_DPUF_AXI) {
271                     for (auto axi = AXIPorts.begin(); axi != AXIPorts.end(); ++axi) {
272                         setupHWResource(attr->first, attr->second.name, blockId->first, axi->first,
273                                         display, nullptr, mConstraintRev);
274                     }
275                 }
276             }
277         }
278     }
279 
280     return 0;
281 }
282 
getSramAmount(tdm_attr_t attr,uint32_t formatProperty,lbWidthIndex_t widthIndex)283 uint32_t getSramAmount(tdm_attr_t attr, uint32_t formatProperty, lbWidthIndex_t widthIndex) {
284     auto it = sramAmountMap.find(sramAmountParams(attr, formatProperty, widthIndex));
285     return (it != sramAmountMap.end()) ? it->second : 0;
286 }
287 
calculateHWResourceAmount(ExynosDisplay * display,ExynosMPPSource * mppSrc)288 uint32_t ExynosResourceManagerModule::calculateHWResourceAmount(ExynosDisplay *display,
289                                                                 ExynosMPPSource *mppSrc)
290 {
291     uint32_t SRAMtotal = 0;
292 
293     if (mppSrc == nullptr) return SRAMtotal;
294 
295     if (mppSrc->mSourceType == MPP_SOURCE_LAYER) {
296         ExynosLayer *layer = static_cast<ExynosLayer *>(mppSrc->mSource);
297         if (layer == nullptr) {
298             ALOGE("%s: cannot cast ExynosLayer", __func__);
299             return SRAMtotal;
300         }
301         exynos_image src_img;
302         exynos_image dst_img;
303         layer->setSrcExynosImage(&src_img);
304         layer->setDstExynosImage(&dst_img);
305         layer->setExynosImage(src_img, dst_img);
306     }
307 
308     int32_t transform = mppSrc->mSrcImg.transform;
309     int32_t compressType = mppSrc->mSrcImg.compressionInfo.type;
310     bool rotation = (transform & HAL_TRANSFORM_ROT_90) ? true : false;
311 
312     int32_t width = mppSrc->mSrcImg.w;
313     int32_t height = mppSrc->mSrcImg.h;
314     uint32_t format = mppSrc->mSrcImg.format;
315     uint32_t formatBPP = 0;
316     if (isFormat10Bit(format))
317         formatBPP = BIT10;
318     else if (isFormat8Bit(format))
319         formatBPP = BIT8;
320 
321     /** To find index **/
322     uint32_t formatIndex = 0;
323 
324     lbWidthIndex_t widthIndex = LB_W_3073_INF;
325 
326     auto findWidthIndex = [&](int32_t w) -> lbWidthIndex_t {
327         for (auto it = LB_WIDTH_INDEX_MAP.begin(); it != LB_WIDTH_INDEX_MAP.end(); it++) {
328             if (w >= it->second.widthDownto && w <= it->second.widthUpto) {
329                 return it->first;
330             }
331         }
332         return LB_W_3073_INF;
333     };
334 
335     /* Caluclate SRAM amount */
336     if (rotation) {
337         width = height;
338         /* Rotation amount, Only YUV rotation is supported */
339         if (compressType == COMP_TYPE_SBWC) {
340             /* Y and UV width should be aligned and should get sram for each Y and UV */
341             int32_t width_y = pixel_align(width + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
342             int32_t width_c =
343                     pixel_align(width / 2 + kSramSBWCRotWidthAlign, kSramSBWCRotWidthAlign);
344             SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_Y, findWidthIndex(width_y));
345             SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, SBWC_UV, findWidthIndex(width_c * 2));
346         } else {
347             /* sramAmountMap has SRAM for both Y and UV */
348             widthIndex = findWidthIndex(width);
349             SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_Y | formatBPP, widthIndex);
350             SRAMtotal += getSramAmount(TDM_ATTR_ROT_90, NON_SBWC_UV | formatBPP, widthIndex);
351         }
352         HDEBUGLOGD(eDebugTDM, "+ rotation : %d", SRAMtotal);
353     } else {
354         if (compressType == COMP_TYPE_SBWC) {
355             width = pixel_align(width + kSramSBWCWidthMargin, kSramSBWCWidthAlign);
356         } else if (compressType == COMP_TYPE_AFBC) {
357             /* Align for 8,4Byte/pixel formats */
358             if (formatToBpp(format) > 16) {
359                 width = pixel_align(width + kSramAFBC8B4BMargin, kSramAFBC8B4BAlign);
360             } else {
361                 /* Align for 2Byte/pixel formats */
362                 width = pixel_align(width + kSramAFBC2BMargin, kSramAFBC2BAlign);
363             }
364         }
365         widthIndex = findWidthIndex(width);
366 
367         /* AFBC amount */
368         if (compressType == COMP_TYPE_AFBC) {
369             formatIndex = (isFormatRgb(format) ? RGB : 0) | formatBPP;
370             SRAMtotal += getSramAmount(TDM_ATTR_AFBC, formatIndex, widthIndex);
371             HDEBUGLOGD(eDebugTDM, "+ AFBC : %d", SRAMtotal);
372         }
373 
374         /* SBWC amount */
375         if (compressType == COMP_TYPE_SBWC) {
376             SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_Y, widthIndex);
377             SRAMtotal += getSramAmount(TDM_ATTR_SBWC, SBWC_UV, widthIndex);
378             HDEBUGLOGD(eDebugTDM, "+ SBWC : %d", SRAMtotal);
379         }
380     }
381 
382     /* ITP (CSC) amount */
383     if (isFormatYUV(format)) {
384         /** ITP has no size difference, Use width index as LB_W_3073_INF **/
385         SRAMtotal += getSramAmount(TDM_ATTR_ITP, formatBPP, LB_W_3073_INF);
386         HDEBUGLOGD(eDebugTDM, "+ YUV : %d", SRAMtotal);
387     }
388 
389     /* Scale amount */
390     int srcW = mppSrc->mSrcImg.w;
391     int srcH = mppSrc->mSrcImg.h;
392     int dstW = mppSrc->mDstImg.w;
393     int dstH = mppSrc->mDstImg.h;
394 
395     if (!!(transform & HAL_TRANSFORM_ROT_90)) {
396         int tmp = dstW;
397         dstW = dstH;
398         dstH = tmp;
399     }
400 
401     bool isScaled = ((srcW != dstW) || (srcH != dstH));
402 
403     if (isScaled) {
404         if (formatHasAlphaChannel(format))
405             formatIndex = FORMAT_RGB_MASK;
406         else
407             formatIndex = FORMAT_YUV_MASK;
408 
409         /** Scale has no size difference, Use width index as LB_W_3073_INF **/
410         SRAMtotal += getSramAmount(TDM_ATTR_SCALE, formatIndex, LB_W_3073_INF);
411         HDEBUGLOGD(eDebugTDM, "+ Scale : %d", SRAMtotal);
412     }
413 
414     for (auto it = HWAttrs.begin(); it != HWAttrs.end(); it++) {
415         uint32_t amount = 0;
416         if (it->first == TDM_ATTR_SRAM_AMOUNT) {
417             amount = SRAMtotal;
418         } else {
419             amount = needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, it->first);
420         }
421         mppSrc->setHWResourceAmount(it->first, amount);
422     }
423 
424     HDEBUGLOGD(eDebugTDM,
425                "mppSrc(%p) needed SRAM(%d), SCALE(%d), AFBC(%d), CSC(%d), SBWC(%d), WCG(%d), "
426                "ROT(%d)",
427                mppSrc->mSrcImg.bufferHandle, SRAMtotal,
428                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SCALE),
429                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_AFBC),
430                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ITP),
431                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_SBWC),
432                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_WCG),
433                needHWResource(display, mppSrc->mSrcImg, mppSrc->mDstImg, TDM_ATTR_ROT_90));
434 
435     return SRAMtotal;
436 }
437 
otfMppReordering(ExynosDisplay * display,ExynosMPPVector & otfMPPs,struct exynos_image & src,struct exynos_image & dst)438 int32_t ExynosResourceManagerModule::otfMppReordering(ExynosDisplay *display,
439                                                       ExynosMPPVector &otfMPPs,
440                                                       struct exynos_image &src,
441                                                       struct exynos_image &dst)
442 {
443     int orderingType = isAFBCCompressed(src.bufferHandle)
444             ? ORDER_AFBC
445             : (needHdrProcessing(display, src, dst) ? ORDER_WCG : ORDER_AXI);
446 
447     int usedAFBCCount[DPU_BLOCK_CNT] = {0};
448     int usedWCGCount[DPU_BLOCK_CNT * AXI_PORT_MAX_CNT] = {0};
449     int usedBlockCount[DPU_BLOCK_CNT] = {0};
450     int usedAXIPortCount[AXI_PORT_MAX_CNT] = {0};
451 
452     auto orderPolicy = [&](const void *lhs, const void *rhs) -> bool {
453         if (lhs == NULL || rhs == NULL) {
454             return 0;
455         }
456 
457         const ExynosMPPModule *l = (ExynosMPPModule *)lhs;
458         const ExynosMPPModule *r = (ExynosMPPModule *)rhs;
459 
460         uint32_t assignedStateL = l->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
461         uint32_t assignedStateR = r->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED;
462 
463         if (assignedStateL != assignedStateR) return assignedStateL < assignedStateR;
464 
465         if (l->mPhysicalType != r->mPhysicalType) return l->mPhysicalType < r->mPhysicalType;
466 
467         if (orderingType == ORDER_AFBC) {
468             /* AFBC balancing */
469             if ((l->mAttr & MPP_ATTR_AFBC) != (r->mAttr & MPP_ATTR_AFBC))
470                 return (l->mAttr & MPP_ATTR_AFBC) > (r->mAttr & MPP_ATTR_AFBC);
471             if (l->mAttr & MPP_ATTR_AFBC) {
472                 /* If layer is AFBC, DPU block that AFBC HW block belongs
473                  * which has not been used much should be placed in the front */
474                 if (usedAFBCCount[l->mHWBlockId] != usedAFBCCount[r->mHWBlockId])
475                     return usedAFBCCount[l->mHWBlockId] < usedAFBCCount[r->mHWBlockId];
476             }
477         } else if (orderingType == ORDER_WCG) {
478             /* WCG balancing */
479             if ((l->mAttr & MPP_ATTR_WCG) != (r->mAttr & MPP_ATTR_WCG))
480                 return (l->mAttr & MPP_ATTR_WCG) > (r->mAttr & MPP_ATTR_WCG);
481             if (l->mAttr & MPP_ATTR_WCG) {
482                 /* If layer is WCG, DPU block that WCG HW block belongs
483                  * which has not been used much should be placed in the front */
484                 if (usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] !=
485                     usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId])
486                     return usedWCGCount[l->mHWBlockId * AXI_PORT_MAX_CNT + l->mAXIPortId] <
487                         usedWCGCount[r->mHWBlockId * AXI_PORT_MAX_CNT + r->mAXIPortId];
488             }
489         }
490 
491         /* AXI bus balancing */
492         /* AXI port which has not been used much should be placed in the front */
493         if (usedAXIPortCount[l->mAXIPortId] != usedAXIPortCount[r->mAXIPortId]) {
494             return usedAXIPortCount[l->mAXIPortId] < usedAXIPortCount[r->mAXIPortId];
495         }
496         /* IF MPP connected same AXI port, Block balancing should be regarded after */
497         if (usedBlockCount[l->mHWBlockId] != usedBlockCount[r->mHWBlockId])
498             return usedBlockCount[l->mHWBlockId] < usedBlockCount[r->mHWBlockId];
499 
500         return l->mPhysicalIndex < r->mPhysicalIndex;
501     };
502 
503     for (auto it : otfMPPs) {
504         ExynosMPPModule *mpp = (ExynosMPPModule *)it;
505         uint32_t bId = mpp->getHWBlockId();
506         uint32_t aId = mpp->getAXIPortId();
507         bool isAFBC = false;
508         bool isWCG = false;
509 
510         if (mpp->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) {
511             ExynosMPPSource *mppSrc = mpp->mAssignedSources[0];
512             if ((mppSrc->mSourceType == MPP_SOURCE_LAYER) &&
513                 (mppSrc->mSrcImg.bufferHandle != nullptr)) {
514                 if ((mpp->mAttr & MPP_ATTR_AFBC) &&
515                     (isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
516                     isAFBC = true;
517                     usedAFBCCount[bId]++;
518                 } else if ((mpp->mAttr & MPP_ATTR_WCG) &&
519                            (needHdrProcessing(display, mppSrc->mSrcImg, mppSrc->mDstImg))) {
520                     isWCG = true;
521                     usedWCGCount[bId]++;
522                 }
523             } else if (mppSrc->mSourceType == MPP_SOURCE_COMPOSITION_TARGET) {
524                 ExynosCompositionInfo *info = (ExynosCompositionInfo *)mppSrc;
525                 // ESTEVAN_TBD
526                 // if ((mpp->mAttr & MPP_ATTR_AFBC) && (info->mCompressionInfo.type ==
527                 // COMP_TYPE_AFBC)) {
528                 if ((mpp->mAttr & MPP_ATTR_AFBC) &&
529                     (isAFBCCompressed(mppSrc->mSrcImg.bufferHandle))) {
530                     isAFBC = true;
531                     usedAFBCCount[bId]++;
532                 } else if ((mpp->mAttr & MPP_ATTR_WCG) &&
533                            (needHdrProcessing(display, info->mSrcImg, info->mDstImg))) {
534                     isWCG = true;
535                     usedWCGCount[bId]++;
536                 }
537             }
538 
539             HDEBUGLOGD(eDebugLoadBalancing, "%s: %s is assigned (AFBC:%d, WCG:%d), is %s", __func__,
540                        mpp->mName.string(), isAFBC, isWCG,
541                        (mppSrc->mSourceType == MPP_SOURCE_LAYER) ? "Layer" : "Client Target");
542             usedBlockCount[bId]++;
543             usedAXIPortCount[aId]++;
544         }
545     }
546 
547     HDEBUGLOGD(eDebugLoadBalancing,
548                "Sorting by %s ordering, AFBC(used DPUF0:%d, DPUF1:%d), AXI(used AXI0:%d, AXI1:%d), "
549                "BLOCK(used DPUF0:%d, DPUF1:%d)",
550                (orderingType == ORDER_AFBC) ? "AFBC" : "_AXI", usedAFBCCount[DPUF0],
551                usedAFBCCount[DPUF1], usedAXIPortCount[AXI0], usedAXIPortCount[AXI1],
552                usedBlockCount[DPUF0], usedBlockCount[DPUF1]);
553 
554     std::sort(otfMPPs.begin(), otfMPPs.end(), orderPolicy);
555 
556     if (hwcCheckDebugMessages(eDebugLoadBalancing)) {
557         String8 after;
558         for (uint32_t i = 0; i < otfMPPs.size(); i++) {
559             ExynosMPPModule *mpp = (ExynosMPPModule *)otfMPPs[i];
560             after.appendFormat("(%s) -> ", mpp->mName.string());
561         }
562 
563         ALOGD("%s %p, %s", __func__, src.bufferHandle, after.string());
564     }
565 
566     return 0;
567 }
568 
isOverlapped(ExynosDisplay * display,ExynosMPPSource * current,ExynosMPPSource * compare)569 bool ExynosResourceManagerModule::isOverlapped(ExynosDisplay *display, ExynosMPPSource *current,
570                                                ExynosMPPSource *compare) {
571     int CT = current->mDstImg.y - TDM_OVERLAP_MARGIN;
572     CT = (CT < 0) ? 0 : CT;
573     int CB = current->mDstImg.y + current->mDstImg.h + TDM_OVERLAP_MARGIN;
574     CB = (CB > display->mYres) ? display->mYres : CB;
575     int LT = compare->mDstImg.y;
576     int LB = compare->mDstImg.y + compare->mDstImg.h;
577 
578     if (((LT <= CT && CT <= LB) || (LT <= CB && CB <= LB)) ||
579         ((CT <= LT && LT <= CB) || (CT < LB && LB <= CB))) {
580         HDEBUGLOGD(eDebugTDM, "%s, current %p and compare %p is overlaped", __func__,
581                    current->mSrcImg.bufferHandle, compare->mSrcImg.bufferHandle);
582         return true;
583     }
584 
585     return false;
586 }
587 
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)588 uint32_t ExynosResourceManagerModule::getAmounts(ExynosDisplay* display, uint32_t currentBlockId,
589                                                  uint32_t currentAXIId, ExynosMPP* compOtfMPP,
590                                                  ExynosMPPSource* curSrc, ExynosMPPSource* compSrc,
591                                                  std::array<uint32_t, TDM_ATTR_MAX>& DPUFAmounts,
592                                                  std::array<uint32_t, TDM_ATTR_MAX>& AXIAmounts) {
593     const uint32_t blockId = compOtfMPP->getHWBlockId();
594     const uint32_t AXIId = compOtfMPP->getAXIPortId();
595     if (currentBlockId == blockId && isOverlapped(display, curSrc, compSrc)) {
596         String8 log;
597         if (hwcCheckDebugMessages(eDebugTDM)) {
598             log.appendFormat("%s", compOtfMPP->mName.string());
599         }
600         for (auto attr = HWAttrs.begin(); attr != HWAttrs.end(); attr++) {
601             uint32_t compareAmount = compSrc->getHWResourceAmount(attr->first);
602             if (hwcCheckDebugMessages(eDebugTDM)) {
603                 log.appendFormat(", attr %s DPUF-%d(+ %d)", attr->second.name.string(),
604                                  DPUFAmounts[attr->first], compareAmount);
605             }
606             DPUFAmounts[attr->first] += compareAmount;
607             if (attr->second.loadSharing == LS_DPUF_AXI && currentAXIId == AXIId) {
608                 if (hwcCheckDebugMessages(eDebugTDM)) {
609                     log.appendFormat(",AXI-%d(+ %d)", AXIAmounts[attr->first], compareAmount);
610                 }
611                 AXIAmounts[attr->first] += compareAmount;
612             }
613         }
614         HDEBUGLOGD(eDebugTDM, "%s %s", __func__, log.string());
615     }
616 
617     return 0;
618 }
619