1 /*
2  * Copyright (C) 2012 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 /**
18  * Project HWC 2.0 Design
19  */
20 
21 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
22 #include "ExynosResourceManager.h"
23 
24 #include <cutils/properties.h>
25 
26 #include <numeric>
27 #include <unordered_set>
28 
29 #include "ExynosDeviceInterface.h"
30 #include "ExynosExternalDisplay.h"
31 #include "ExynosHWCDebug.h"
32 #include "ExynosLayer.h"
33 #include "ExynosMPPModule.h"
34 #include "ExynosPrimaryDisplayModule.h"
35 #include "ExynosVirtualDisplay.h"
36 #include "hardware/exynos/acryl.h"
37 
38 using namespace std::chrono_literals;
39 constexpr float msecsPerSec = std::chrono::milliseconds(1s).count();
40 
41 using namespace android;
42 using namespace vendor::graphics;
43 using namespace SOC_VERSION;
44 
45 ExynosMPPVector ExynosResourceManager::mOtfMPPs;
46 ExynosMPPVector ExynosResourceManager::mM2mMPPs;
47 extern struct exynos_hwc_control exynosHWCControl;
48 
ExynosMPPVector()49 ExynosMPPVector::ExynosMPPVector() {
50 }
51 
ExynosMPPVector(const ExynosMPPVector & rhs)52 ExynosMPPVector::ExynosMPPVector(const ExynosMPPVector& rhs)
53     : android::SortedVector<ExynosMPP* >(rhs) {
54 }
55 
do_compare(const void * lhs,const void * rhs) const56 int ExynosMPPVector::do_compare(const void* lhs, const void* rhs) const
57 {
58     if (lhs == NULL || rhs == NULL)
59         return 0;
60 
61     const ExynosMPP* l = *((ExynosMPP**)(lhs));
62     const ExynosMPP* r = *((ExynosMPP**)(rhs));
63 
64     if (l == NULL || r == NULL)
65         return 0;
66 
67     if (l->mPhysicalType != r->mPhysicalType) {
68         return l->mPhysicalType - r->mPhysicalType;
69     }
70 
71     if (l->mLogicalType != r->mLogicalType) {
72         return l->mLogicalType - r->mLogicalType;
73     }
74 
75     if (l->mPhysicalIndex != r->mPhysicalIndex) {
76         return l->mPhysicalIndex - r->mPhysicalIndex;
77     }
78 
79     return l->mLogicalIndex - r->mLogicalIndex;
80 }
81 /**
82  * ExynosResourceManager implementation
83  *
84  */
85 
DstBufMgrThread(ExynosResourceManager * exynosResourceManager)86 ExynosResourceManager::DstBufMgrThread::DstBufMgrThread(ExynosResourceManager *exynosResourceManager)
87 : mExynosResourceManager(exynosResourceManager),
88     mRunning(false),
89     mBufXres(0),
90     mBufYres(0)
91 {
92 }
93 
~DstBufMgrThread()94 ExynosResourceManager::DstBufMgrThread::~DstBufMgrThread()
95 {
96 }
97 
98 
ExynosResourceManager(ExynosDevice * device)99 ExynosResourceManager::ExynosResourceManager(ExynosDevice *device)
100 : mForceReallocState(DST_REALLOC_DONE),
101     mDevice(device),
102     hasHdrLayer(false),
103     hasDrmLayer(false),
104     mFormatRestrictionCnt(0),
105     mDstBufMgrThread(sp<DstBufMgrThread>::make(this)),
106     mResourceReserved(0x0)
107 {
108 
109     memset(mSizeRestrictionCnt, 0, sizeof(mSizeRestrictionCnt));
110     memset(mFormatRestrictions, 0, sizeof(mFormatRestrictions));
111     memset(mSizeRestrictions, 0, sizeof(mSizeRestrictions));
112 
113     size_t num_mpp_units = sizeof(available_otf_mpp_units)/sizeof(exynos_mpp_t);
114     for (size_t i = 0; i < num_mpp_units; i++) {
115         exynos_mpp_t exynos_mpp = available_otf_mpp_units[i];
116         ALOGI("otfMPP type(%d, %d), physical_index(%d), logical_index(%d)",
117                 exynos_mpp.physicalType, exynos_mpp.logicalType,
118                 exynos_mpp.physical_index, exynos_mpp.logical_index);
119         ExynosMPP* exynosMPP = new ExynosMPPModule(this, exynos_mpp.physicalType,
120                 exynos_mpp.logicalType, exynos_mpp.name, exynos_mpp.physical_index,
121                 exynos_mpp.logical_index, exynos_mpp.pre_assign_info);
122         exynosMPP->mMPPType = MPP_TYPE_OTF;
123         exynosMPP->initTDMInfo(exynos_mpp.hw_block_index, exynos_mpp.axi_port_index);
124         mOtfMPPs.add(exynosMPP);
125     }
126 
127     num_mpp_units = sizeof(AVAILABLE_M2M_MPP_UNITS)/sizeof(exynos_mpp_t);
128     for (size_t i = 0; i < num_mpp_units; i++) {
129         exynos_mpp_t exynos_mpp = AVAILABLE_M2M_MPP_UNITS[i];
130         ALOGI("m2mMPP type(%d, %d), physical_index(%d), logical_index(%d)",
131                 exynos_mpp.physicalType, exynos_mpp.logicalType,
132                 exynos_mpp.physical_index, exynos_mpp.logical_index);
133         ExynosMPP* exynosMPP = new ExynosMPPModule(this, exynos_mpp.physicalType,
134                 exynos_mpp.logicalType, exynos_mpp.name, exynos_mpp.physical_index,
135                 exynos_mpp.logical_index, exynos_mpp.pre_assign_info);
136         exynosMPP->mMPPType = MPP_TYPE_M2M;
137         mM2mMPPs.add(exynosMPP);
138     }
139 
140     ALOGI("mOtfMPPs(%zu), mM2mMPPs(%zu)", mOtfMPPs.size(), mM2mMPPs.size());
141     if (hwcCheckDebugMessages(eDebugResourceManager)) {
142         for (uint32_t i = 0; i < mOtfMPPs.size(); i++)
143         {
144             HDEBUGLOGD(eDebugResourceManager, "otfMPP[%d]", i);
145             String8 dumpMPP;
146             mOtfMPPs[i]->dump(dumpMPP);
147             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
148         }
149         for (uint32_t i = 0; i < mM2mMPPs.size(); i++)
150         {
151             HDEBUGLOGD(eDebugResourceManager, "m2mMPP[%d]", i);
152             String8 dumpMPP;
153             mM2mMPPs[i]->dump(dumpMPP);
154             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
155         }
156     }
157 
158     mDstBufMgrThread->mRunning = true;
159     mDstBufMgrThread->run("DstBufMgrThread");
160 
161     char value[PROPERTY_VALUE_MAX];
162     mMinimumSdrDimRatio = property_get("debug.hwc.min_sdr_dimming", value, nullptr) > 0
163                           ? std::atof(value) : 0.0f;
164     updateSupportWCG();
165 }
166 
~ExynosResourceManager()167 ExynosResourceManager::~ExynosResourceManager()
168 {
169     for (int32_t i = mOtfMPPs.size(); i-- > 0;) {
170         ExynosMPP *exynosMPP = mOtfMPPs[i];
171         delete exynosMPP;
172     }
173     mOtfMPPs.clear();
174     for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
175         ExynosMPP *exynosMPP = mM2mMPPs[i];
176         delete exynosMPP;
177     }
178     mM2mMPPs.clear();
179 
180     mDstBufMgrThread->mRunning = false;
181     mDstBufMgrThread->requestExitAndWait();
182 }
183 
reloadResourceForHWFC()184 void ExynosResourceManager::reloadResourceForHWFC()
185 {
186     for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
187         ExynosMPP *exynosMPP = mM2mMPPs[i];
188         if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
189                 (exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
190             exynosMPP->reloadResourceForHWFC();
191             break;
192         }
193     }
194 }
195 
setTargetDisplayLuminance(uint16_t min,uint16_t max)196 void ExynosResourceManager::setTargetDisplayLuminance(uint16_t min, uint16_t max)
197 {
198     for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
199         ExynosMPP *exynosMPP = mM2mMPPs[i];
200         if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
201                 (exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
202             exynosMPP->setTargetDisplayLuminance(min, max);
203             break;
204         }
205     }
206 }
207 
setTargetDisplayDevice(int device)208 void ExynosResourceManager::setTargetDisplayDevice(int device)
209 {
210     for (int32_t i = mM2mMPPs.size(); i-- > 0;) {
211         ExynosMPP *exynosMPP = mM2mMPPs[i];
212         if (exynosMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO &&
213                 (exynosMPP->mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
214             exynosMPP->setTargetDisplayDevice(device);
215             break;
216         }
217     }
218 }
219 
doPreProcessing()220 int32_t ExynosResourceManager::doPreProcessing()
221 {
222     int32_t ret = NO_ERROR;
223     /* Assign m2mMPP's out buffers */
224     ExynosDisplay *display = mDevice->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
225     if (display == NULL)
226         return -EINVAL;
227     ret = doAllocDstBufs(display->mXres, display->mYres);
228     return ret;
229 }
230 
doReallocDstBufs(uint32_t Xres,uint32_t Yres)231 void ExynosResourceManager::doReallocDstBufs(uint32_t Xres, uint32_t Yres)
232 {
233     HDEBUGLOGD(eDebugBuf, "M2M dst alloc call ");
234     mDstBufMgrThread->reallocDstBufs(Xres, Yres);
235 }
236 
needDstRealloc(uint32_t Xres,uint32_t Yres,ExynosMPP * m2mMPP)237 bool ExynosResourceManager::DstBufMgrThread::needDstRealloc(uint32_t Xres, uint32_t Yres, ExynosMPP *m2mMPP)
238 {
239     bool ret = false;
240     if (((Xres == 720 && Yres == 1480) && (m2mMPP->getDstAllocSize() != DST_SIZE_HD_PLUS)) ||
241             ((Xres == 720 && Yres == 1280) && (m2mMPP->getDstAllocSize() != DST_SIZE_HD)) ||
242             ((Xres == 1080 && Yres == 2220) && (m2mMPP->getDstAllocSize() != DST_SIZE_FHD_PLUS)) ||
243             ((Xres == 1080 && Yres == 1920) && (m2mMPP->getDstAllocSize() != DST_SIZE_FHD)) ||
244             ((Xres == 1440 && Yres == 2960) && (m2mMPP->getDstAllocSize() != DST_SIZE_WQHD_PLUS)) ||
245             ((Xres == 1440 && Yres == 2560) && (m2mMPP->getDstAllocSize() != DST_SIZE_WQHD))) {
246         ret = true;
247     }
248     return ret;
249 }
250 
reallocDstBufs(uint32_t Xres,uint32_t Yres)251 void ExynosResourceManager::DstBufMgrThread::reallocDstBufs(uint32_t Xres, uint32_t Yres)
252 {
253     bool needRealloc = false;
254     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
255         if (mM2mMPPs[i]->needPreAllocation())
256         {
257             if (needDstRealloc(Xres, Yres, mM2mMPPs[i])) {
258                 HDEBUGLOGD(eDebugBuf, "M2M dst alloc : %d Realloc Start ++++++", mM2mMPPs[i]->mLogicalType);
259                 needRealloc = true;
260             }
261             else HDEBUGLOGD(eDebugBuf, "M2M dst alloc : %d MPP's DST Realloc is not needed : Size is same", mM2mMPPs[i]->mLogicalType);
262         }
263     }
264 
265     if (needRealloc) {
266         Mutex::Autolock lock(mStateMutex);
267         if (mExynosResourceManager->mForceReallocState == DST_REALLOC_DONE) {
268             mExynosResourceManager->mForceReallocState = DST_REALLOC_START;
269             android::Mutex::Autolock lock(mMutex);
270             mCondition.signal();
271         } else {
272             HDEBUGLOGD(eDebugBuf, "M2M dst alloc thread : queue aready.");
273         }
274     }
275 }
276 
threadLoop()277 bool ExynosResourceManager::DstBufMgrThread::threadLoop()
278 {
279     while(mRunning) {
280         Mutex::Autolock lock(mMutex);
281         mCondition.wait(mMutex);
282 
283         ExynosDevice *device = mExynosResourceManager->mDevice;
284         if (device == NULL)
285             return false;
286 
287         /* TODO(b/265244856): to clarify which display size to alloc */
288         ExynosDisplay *display = device->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
289         if (display == NULL)
290             return false;
291 
292         do {
293             {
294                 HDEBUGLOGD(eDebugBuf, "M2M dst alloc %d, %d, %d, %d : Realloc On going ----------",
295                         mBufXres, display->mXres, mBufYres, display->mYres);
296                 Mutex::Autolock lock(mResInfoMutex);
297                 mBufXres = display->mXres;mBufYres = display->mYres;
298             }
299             mExynosResourceManager->doAllocDstBufs(mBufXres, mBufYres);
300         } while (mBufXres != display->mXres || mBufYres != display->mYres);
301 
302         {
303             Mutex::Autolock lock(mStateMutex);
304             mExynosResourceManager->mForceReallocState = DST_REALLOC_DONE;
305             HDEBUGLOGD(eDebugBuf, "M2M dst alloc %d, %d, %d, %d : Realloc On Done ----------",
306                     mBufXres, display->mXres, mBufYres, display->mYres);
307         }
308     }
309     return true;
310 }
311 
doAllocDstBufs(uint32_t Xres,uint32_t Yres)312 int32_t ExynosResourceManager::doAllocDstBufs(uint32_t Xres, uint32_t Yres)
313 {
314     ATRACE_CALL();
315     int32_t ret = NO_ERROR;
316     /* Assign m2mMPP's out buffers */
317 
318     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
319         if (mM2mMPPs[i]->needPreAllocation())
320         {
321             mM2mMPPs[i]->mFreeOutBufFlag = false;
322             for (uint32_t index = 0; index < NUM_MPP_DST_BUFS(mM2mMPPs[i]->mLogicalType); index++) {
323                 HDEBUGLOGD(eDebugBuf, "%s allocate dst buffer[%d]%p, x: %d, y: %d",
324                         __func__, index, mM2mMPPs[i]->mDstImgs[index].bufferHandle, Xres, Yres);
325                 uint32_t bufAlign = mM2mMPPs[i]->getOutBufAlign();
326                 ret = mM2mMPPs[i]->allocOutBuf(ALIGN_UP(Xres, bufAlign),
327                         ALIGN_UP(Yres, bufAlign),
328                         DEFAULT_MPP_DST_FORMAT, 0x0, index);
329                 if (ret < 0) {
330                     HWC_LOGE(NULL, "%s:: fail to allocate dst buffer[%d]",
331                             __func__, index);
332                     return ret;
333                 }
334                 mM2mMPPs[i]->mPrevAssignedDisplayType = HWC_DISPLAY_PRIMARY;
335             }
336             mM2mMPPs[i]->setDstAllocSize(Xres, Yres);
337         }
338     }
339     return ret;
340 }
341 
checkScenario(ExynosDisplay __unused * display)342 int32_t ExynosResourceManager::checkScenario(ExynosDisplay __unused *display) {
343     uint32_t prevResourceReserved = mResourceReserved;
344     mResourceReserved = 0x0;
345     /* Check whether camera preview is running */
346     ExynosDisplay *exynosDisplay = NULL;
347     for (uint32_t i = 0; i < mDevice->mDisplays.size(); i++) {
348         exynosDisplay = mDevice->mDisplays[i];
349         if ((exynosDisplay != NULL) && (exynosDisplay->mPlugState == true)) {
350             for (uint32_t i = 0; i < exynosDisplay->mLayers.size(); i++) {
351                 ExynosLayer *layer = exynosDisplay->mLayers[i];
352                 VendorGraphicBufferMeta gmeta(layer->mLayerBuffer);
353                 if ((layer->mLayerBuffer != NULL) &&
354                     (gmeta.producer_usage & BufferUsage::CAMERA_OUTPUT)) {
355                     mResourceReserved |= (MPP_LOGICAL_G2D_YUV | MPP_LOGICAL_G2D_RGB);
356                     break;
357                 }
358             }
359         }
360     }
361 
362     if (prevResourceReserved != mResourceReserved) {
363         mDevice->setGeometryChanged(GEOMETRY_DEVICE_SCENARIO_CHANGED);
364     }
365 
366     return NO_ERROR;
367 }
368 
369 /**
370  * @param * display
371  * @return int
372  */
assignResource(ExynosDisplay * display)373 int32_t ExynosResourceManager::assignResource(ExynosDisplay *display)
374 {
375     ATRACE_CALL();
376     int ret = 0;
377     if ((mDevice == NULL) || (display == NULL))
378         return -EINVAL;
379 
380     HDEBUGLOGD(eDebugResourceManager|eDebugSkipResourceAssign, "mGeometryChanged(0x%" PRIx64 "), display(%d)",
381             mDevice->mGeometryChanged, display->mType);
382 
383     if (mDevice->mGeometryChanged == 0) {
384         return NO_ERROR;
385     }
386 
387     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
388         display->mLayers[i]->resetValidateData();
389     }
390 
391     display->initializeValidateInfos();
392 
393     if ((ret = preProcessLayer(display)) != NO_ERROR) {
394         HWC_LOGE(display, "%s:: preProcessLayer() error (%d)",
395                 __func__, ret);
396         return ret;
397     }
398 
399     if ((ret = display->updateColorConversionInfo()) != NO_ERROR) {
400         HWC_LOGE(display, "%s:: updateColorConversionInfo() fail, ret(%d)", __func__, ret);
401         return ret;
402     }
403     display->checkPreblendingRequirement();
404 
405     HDEBUGLOGD(eDebugTDM, "%s layer's calculation start", __func__);
406     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
407         calculateHWResourceAmount(display, display->mLayers[i]);
408     }
409 
410     if (mDevice->isFirstValidate()) {
411         HDEBUGLOGD(eDebugResourceManager, "This is first validate");
412         if (exynosHWCControl.displayMode < DISPLAY_MODE_NUM)
413             mDevice->mDisplayMode = exynosHWCControl.displayMode;
414 
415         if ((ret = prepareResources()) != NO_ERROR) {
416             HWC_LOGE(display, "%s:: prepareResources() error (%d)",
417                     __func__, ret);
418             return ret;
419         }
420         preAssignWindows(display);
421 
422     }
423 
424     if ((ret = updateSupportedMPPFlag(display)) != NO_ERROR) {
425         HWC_LOGE(display, "%s:: updateSupportedMPPFlag() error (%d)",
426                 __func__, ret);
427         return ret;
428     }
429 
430     if ((ret = assignResourceInternal(display)) != NO_ERROR) {
431         HWC_LOGE(display, "%s:: assignResourceInternal() error (%d)",
432                 __func__, ret);
433         return ret;
434     }
435 
436     if ((ret = assignWindow(display)) != NO_ERROR) {
437         HWC_LOGE(display, "%s:: assignWindow() error (%d)",
438                 __func__, ret);
439         return ret;
440     }
441 
442     if (hwcCheckDebugMessages(eDebugResourceManager)) {
443         HDEBUGLOGD(eDebugResourceManager, "AssignResource result");
444         String8 result;
445         display->mClientCompositionInfo.dump(result);
446         HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
447         result.clear();
448         display->mExynosCompositionInfo.dump(result);
449         HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
450         for (uint32_t i = 0; i < display->mLayers.size(); i++) {
451             result.clear();
452             HDEBUGLOGD(eDebugResourceManager, "%d layer(%p) dump", i, display->mLayers[i]);
453             display->mLayers[i]->printLayer();
454             HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
455         }
456     }
457 
458     if (mDevice->isLastValidate(display)) {
459         if ((ret = finishAssignResourceWork()) != NO_ERROR) {
460             HWC_LOGE(display, "%s:: finishAssignResourceWork() error (%d)",
461                     __func__, ret);
462             return ret;
463         }
464     }
465 
466     if (!display->mUseDpu) {
467         if (display->mClientCompositionInfo.mHasCompositionLayer) {
468             if ((ret = display->mExynosCompositionInfo.mM2mMPP->assignMPP(display, &display->mClientCompositionInfo)) != NO_ERROR)
469             {
470                 ALOGE("%s:: %s MPP assignMPP() error (%d)",
471                         __func__, display->mExynosCompositionInfo.mM2mMPP->mName.c_str(), ret);
472                 return ret;
473             }
474             int prevHasCompositionLayer = display->mExynosCompositionInfo.mHasCompositionLayer;
475             display->mExynosCompositionInfo.mHasCompositionLayer = true;
476             // if prevHasCompositionLayer is false, setResourcePriority is not called
477             if (prevHasCompositionLayer == false)
478                 setResourcePriority(display);
479         }
480     }
481 
482     return NO_ERROR;
483 }
484 
setResourcePriority(ExynosDisplay * display)485 int32_t ExynosResourceManager::setResourcePriority(ExynosDisplay *display)
486 {
487     int ret = NO_ERROR;
488     int check_ret = NO_ERROR;
489     ExynosMPP *m2mMPP = NULL;
490 
491     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
492         ExynosLayer *layer = display->mLayers[i];
493         if ((layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) &&
494             (layer->mM2mMPP != NULL) && (layer->mM2mMPP->mPhysicalType == MPP_G2D) &&
495             ((check_ret = layer->mM2mMPP->prioritize(2)) != NO_ERROR)) {
496             if (check_ret < 0) {
497                 HWC_LOGE(display, "Fail to set exynoscomposition priority(%d)", ret);
498             } else {
499                 m2mMPP = layer->mM2mMPP;
500                 layer->resetAssignedResource();
501                 layer->updateValidateCompositionType(HWC2_COMPOSITION_DEVICE, eResourcePendingWork);
502                 ret = EXYNOS_ERROR_CHANGED;
503                 HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of panding work",
504                         m2mMPP->mName.c_str());
505                 m2mMPP->reserveMPP();
506                 layer->mCheckMPPFlag[m2mMPP->mLogicalType] = eMPPHWBusy;
507             }
508         }
509     }
510 
511     m2mMPP = display->mExynosCompositionInfo.mM2mMPP;
512     ExynosCompositionInfo &compositionInfo = display->mExynosCompositionInfo;
513     if (compositionInfo.mHasCompositionLayer == true)
514     {
515         if ((m2mMPP == NULL) || (m2mMPP->mAcrylicHandle == NULL)) {
516             HWC_LOGE(display, "There is exynos composition layers but resource is null (%p)",
517                     m2mMPP);
518         } else if ((check_ret = m2mMPP->prioritize(2)) != NO_ERROR) {
519             HDEBUGLOGD(eDebugResourceManager, "%s setting priority error(%d)", m2mMPP->mName.c_str(), check_ret);
520             if (check_ret < 0) {
521                 HWC_LOGE(display, "Fail to set exynoscomposition priority(%d)", ret);
522             } else {
523                 if (display->mExynosCompositionInfo.mFirstIndex >= 0) {
524                     uint32_t firstIndex = (uint32_t)display->mExynosCompositionInfo.mFirstIndex;
525                     uint32_t lastIndex = (uint32_t)display->mExynosCompositionInfo.mLastIndex;
526                     for (uint32_t i = firstIndex; i <= lastIndex; i++) {
527                         ExynosLayer *layer = display->mLayers[i];
528                         layer->resetAssignedResource();
529                         layer->updateValidateCompositionType(HWC2_COMPOSITION_DEVICE,
530                                                              eResourcePendingWork);
531                         layer->mCheckMPPFlag[m2mMPP->mLogicalType] = eMPPHWBusy;
532                     }
533                 }
534                 compositionInfo.initializeInfos(display);
535                 ret = EXYNOS_ERROR_CHANGED;
536                 m2mMPP->resetUsedCapacity();
537                 HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of pending work",
538                         m2mMPP->mName.c_str());
539                 m2mMPP->reserveMPP();
540             }
541         } else {
542             HDEBUGLOGD(eDebugResourceManager, "%s setting priority is ok", m2mMPP->mName.c_str());
543         }
544     }
545 
546     return ret;
547 }
548 
assignResourceInternal(ExynosDisplay * display)549 int32_t ExynosResourceManager::assignResourceInternal(ExynosDisplay *display)
550 {
551     int ret = NO_ERROR;
552     int retry_count = 0;
553 
554     Mutex::Autolock lock(mDstBufMgrThread->mStateMutex);
555 
556     /*
557      * First add layers that SF requested HWC2_COMPOSITION_CLIENT type
558      * to client composition
559      */
560     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
561         ExynosLayer *layer = display->mLayers[i];
562         if (layer->mCompositionType == HWC2_COMPOSITION_CLIENT) {
563             layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, eForceBySF);
564             if (((ret = display->addClientCompositionLayer(i)) != NO_ERROR) &&
565                  (ret != EXYNOS_ERROR_CHANGED)) {
566                 HWC_LOGE(display, "Handle HWC2_COMPOSITION_CLIENT type layers, but addClientCompositionLayer failed (%d)", ret);
567                 return ret;
568             }
569         }
570     }
571 
572     do {
573         HDEBUGLOGD(eDebugResourceAssigning, "%s:: retry_count(%d)", __func__, retry_count);
574         if ((ret = resetAssignedResources(display)) != NO_ERROR)
575             return ret;
576         if ((ret = assignCompositionTarget(display, COMPOSITION_CLIENT)) != NO_ERROR) {
577             HWC_LOGE(display, "%s:: Fail to assign resource for compositionTarget",
578                     __func__);
579             return ret;
580         }
581 
582         if ((ret = assignLayers(display, ePriorityMax)) != NO_ERROR) {
583             if (ret == EXYNOS_ERROR_CHANGED) {
584                 retry_count++;
585                 continue;
586             } else {
587                 HWC_LOGE(display, "%s:: Fail to assign resource for ePriorityMax layer",
588                         __func__);
589                 return ret;
590             }
591         }
592 
593         if ((ret = assignLayers(display, ePriorityHigh)) != NO_ERROR) {
594             if (ret == EXYNOS_ERROR_CHANGED) {
595                 retry_count++;
596                 continue;
597             } else {
598                 HWC_LOGE(display, "%s:: Fail to assign resource for ePriorityHigh layer",
599                         __func__);
600                 return ret;
601             }
602         }
603 
604         if ((ret = assignCompositionTarget(display, COMPOSITION_EXYNOS)) != NO_ERROR) {
605             if (ret == eInsufficientMPP) {
606                 /*
607                  * Change compositionTypes to HWC2_COMPOSITION_CLIENT
608                  */
609                 uint32_t firstIndex = (uint32_t)display->mExynosCompositionInfo.mFirstIndex;
610                 uint32_t lastIndex = (uint32_t)display->mExynosCompositionInfo.mLastIndex;
611                 for (uint32_t i = firstIndex; i <= lastIndex; i++) {
612                     ExynosLayer *layer = display->mLayers[i];
613                     layer->resetAssignedResource();
614                     layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, eInsufficientMPP);
615                     if (((ret = display->addClientCompositionLayer(i)) != NO_ERROR) &&
616                         (ret != EXYNOS_ERROR_CHANGED)) {
617                         HWC_LOGE(display, "Change compositionTypes to HWC2_COMPOSITION_CLIENT, but addClientCompositionLayer failed (%d)", ret);
618                         return ret;
619                     }
620                 }
621                 display->mExynosCompositionInfo.initializeInfos(display);
622                 ret = EXYNOS_ERROR_CHANGED;
623             } else {
624                 return ret;
625             }
626         }
627 
628         if (ret == NO_ERROR) {
629             for (int32_t i = ePriorityHigh - 1; i > ePriorityNone; i--) {
630                 if ((ret = assignLayers(display, i)) == EXYNOS_ERROR_CHANGED)
631                     break;
632                 if (ret != NO_ERROR)
633                     return ret;
634             }
635         }
636 
637         /* Assignment is done */
638         if (ret == NO_ERROR) {
639             ret = setResourcePriority(display);
640         }
641         retry_count++;
642     } while((ret == EXYNOS_ERROR_CHANGED) && (retry_count < ASSIGN_RESOURCE_TRY_COUNT));
643 
644     if (retry_count == ASSIGN_RESOURCE_TRY_COUNT) {
645         HWC_LOGE(display, "%s:: assign resources fail", __func__);
646         ret = eUnknown;
647         return ret;
648     } else {
649         if ((ret = updateExynosComposition(display)) != NO_ERROR)
650             return ret;
651         if ((ret = updateClientComposition(display)) != NO_ERROR)
652             return ret;
653     }
654 
655     if (hwcCheckDebugMessages(eDebugCapacity)) {
656         for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
657             if (mM2mMPPs[i]->mPhysicalType == MPP_G2D)
658             {
659                 String8 dumpMPP;
660                 mM2mMPPs[i]->dump(dumpMPP);
661                 HDEBUGLOGD(eDebugCapacity, "%s", dumpMPP.c_str());
662             }
663         }
664     }
665     return ret;
666 }
667 
updateExynosComposition(ExynosDisplay * display)668 int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
669 {
670     int ret = NO_ERROR;
671     /* Use Exynos composition as many as possible */
672     if ((display->mExynosCompositionInfo.mHasCompositionLayer == true) &&
673         (display->mExynosCompositionInfo.mM2mMPP != NULL)) {
674         if (display->mDisplayControl.useMaxG2DSrc == 1) {
675             ExynosMPP *m2mMPP = display->mExynosCompositionInfo.mM2mMPP;
676             uint32_t lastIndex = display->mExynosCompositionInfo.mLastIndex;
677             uint32_t firstIndex = display->mExynosCompositionInfo.mFirstIndex;
678             uint32_t remainNum = m2mMPP->mMaxSrcLayerNum - (lastIndex - firstIndex + 1);
679 
680             HDEBUGLOGD(eDebugResourceAssigning,
681                        "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d++++",
682                        firstIndex, lastIndex, remainNum);
683 
684             ExynosLayer *layer = NULL;
685             exynos_image src_img;
686             exynos_image dst_img;
687             if (remainNum > 0) {
688                 for (uint32_t i = (lastIndex + 1); i < display->mLayers.size(); i++)
689                 {
690                     layer = display->mLayers[i];
691                     layer->setSrcExynosImage(&src_img);
692                     layer->setDstExynosImage(&dst_img);
693                     layer->setExynosImage(src_img, dst_img);
694                     bool isAssignableState = false;
695                     if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
696                         isAssignableState = isAssignable(m2mMPP, display, src_img, dst_img, layer);
697 
698                     bool canChange =
699                             (layer->getValidateCompositionType() != HWC2_COMPOSITION_CLIENT) &&
700                             ((display->mDisplayControl.cursorSupport == false) ||
701                              (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
702                             (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
703 
704                     HDEBUGLOGD(eDebugResourceAssigning,
705                                "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, "
706                                "remainNum(%d)",
707                                i, layer->getValidateCompositionType(), layer->mSupportedMPPFlag,
708                                isAssignableState, canChange, remainNum);
709                     if (canChange) {
710                         layer->resetAssignedResource();
711                         if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
712                         {
713                             ALOGE("%s:: %s MPP assignMPP() error (%d)",
714                                     __func__, m2mMPP->mName.c_str(), ret);
715                             return ret;
716                         }
717                         layer->setExynosMidImage(dst_img);
718                         float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
719                         display->addExynosCompositionLayer(i, totalUsedCapacity);
720                         layer->updateValidateCompositionType(HWC2_COMPOSITION_EXYNOS,
721                                                              eUpdateExynosComposition);
722                         remainNum--;
723                     }
724                     if ((canChange == false) || (remainNum == 0))
725                         break;
726                 }
727             }
728             if (remainNum > 0) {
729                 for (int32_t i = (firstIndex - 1); i >= 0; i--)
730                 {
731                     layer = display->mLayers[i];
732                     layer->setSrcExynosImage(&src_img);
733                     layer->setDstExynosImage(&dst_img);
734                     layer->setExynosImage(src_img, dst_img);
735                     bool isAssignableState = false;
736                     if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
737                         isAssignableState = isAssignable(m2mMPP, display, src_img, dst_img, layer);
738 
739                     bool canChange =
740                             (layer->getValidateCompositionType() != HWC2_COMPOSITION_CLIENT) &&
741                             ((display->mDisplayControl.cursorSupport == false) ||
742                              (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
743                             (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
744 
745                     HDEBUGLOGD(eDebugResourceAssigning,
746                                "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, "
747                                "remainNum(%d)",
748                                i, layer->getValidateCompositionType(), layer->mSupportedMPPFlag,
749                                isAssignableState, canChange, remainNum);
750                     if (canChange) {
751                         layer->resetAssignedResource();
752                         layer->mOverlayInfo |= eUpdateExynosComposition;
753                         if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
754                         {
755                             ALOGE("%s:: %s MPP assignMPP() error (%d)",
756                                     __func__, m2mMPP->mName.c_str(), ret);
757                             return ret;
758                         }
759                         layer->setExynosMidImage(dst_img);
760                         float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
761                         display->addExynosCompositionLayer(i, totalUsedCapacity);
762                         layer->updateValidateCompositionType(HWC2_COMPOSITION_EXYNOS);
763                         remainNum--;
764                     }
765                     if ((canChange == false) || (remainNum == 0))
766                         break;
767                 }
768             }
769             HDEBUGLOGD(eDebugResourceAssigning,
770                        "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d-----",
771                        display->mExynosCompositionInfo.mFirstIndex,
772                        display->mExynosCompositionInfo.mLastIndex, remainNum);
773         }
774 
775         /*
776          * Check if there is only one exynos composition layer
777          * Then it is not composition and m2mMPP is not required
778          * if internalMPP can process the layer alone.
779          */
780         ExynosMPP *otfMPP = display->mExynosCompositionInfo.mOtfMPP;
781         if ((display->mDisplayControl.enableExynosCompositionOptimization == true) &&
782             (otfMPP != NULL) &&
783             (display->mExynosCompositionInfo.mFirstIndex >= 0) &&
784             (display->mExynosCompositionInfo.mFirstIndex == display->mExynosCompositionInfo.mLastIndex))
785         {
786             ExynosLayer* layer = display->mLayers[display->mExynosCompositionInfo.mFirstIndex];
787             if (layer->mSupportedMPPFlag & otfMPP->mLogicalType) {
788                 layer->resetAssignedResource();
789                 layer->updateValidateCompositionType(HWC2_COMPOSITION_DEVICE);
790                 display->mExynosCompositionInfo.initializeInfos(display);
791                 // reset otfMPP
792                 if ((ret = otfMPP->resetAssignedState()) != NO_ERROR)
793                 {
794                     ALOGE("%s:: %s MPP resetAssignedState() error (%d)",
795                             __func__, otfMPP->mName.c_str(), ret);
796                 }
797                 // assign otfMPP again
798                 if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
799                 {
800                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
801                             __func__, otfMPP->mName.c_str(), ret);
802                 }
803             }
804         }
805     }
806     return ret;
807 }
808 
changeLayerFromClientToDevice(ExynosDisplay * display,ExynosLayer * layer,uint32_t layer_index,const exynos_image & m2m_out_img,ExynosMPP * m2mMPP,ExynosMPP * otfMPP)809 int32_t ExynosResourceManager::changeLayerFromClientToDevice(ExynosDisplay* display,
810                                                              ExynosLayer* layer,
811                                                              uint32_t layer_index,
812                                                              const exynos_image& m2m_out_img,
813                                                              ExynosMPP* m2mMPP, ExynosMPP* otfMPP) {
814     int ret = NO_ERROR;
815     if ((ret = display->removeClientCompositionLayer(layer_index)) != NO_ERROR) {
816         ALOGD("removeClientCompositionLayer return error(%d)", ret);
817         return ret;
818     }
819     if (otfMPP != NULL) {
820         if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
821         {
822             ALOGE("%s:: %s MPP assignMPP() error (%d)",
823                     __func__, otfMPP->mName.c_str(), ret);
824             return ret;
825         }
826         HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", layer_index,
827                    otfMPP->mName.c_str());
828     }
829     if (m2mMPP != NULL) {
830         if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
831         {
832             ALOGE("%s:: %s MPP assignMPP() error (%d)",
833                     __func__, m2mMPP->mName.c_str(), ret);
834             return ret;
835         }
836         layer->setExynosMidImage(m2m_out_img);
837         HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", layer_index,
838                    m2mMPP->mName.c_str());
839     }
840     layer->updateValidateCompositionType(HWC2_COMPOSITION_DEVICE);
841     display->mWindowNumUsed++;
842     HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: mWindowNumUsed(%d)", layer_index,
843                display->mWindowNumUsed);
844 
845     return ret;
846 }
updateClientComposition(ExynosDisplay * display)847 int32_t ExynosResourceManager::updateClientComposition(ExynosDisplay *display)
848 {
849     int ret = NO_ERROR;
850 
851     if (display->mDisplayControl.enableClientCompositionOptimization == false)
852         return ret;
853 
854     if ((exynosHWCControl.forceGpu == 1) ||
855         (display->mClientCompositionInfo.mHasCompositionLayer == false))
856         return ret;
857 
858     /* Check if there is layer that can be handled by overlay */
859     int32_t firstIndex = display->mClientCompositionInfo.mFirstIndex;
860     int32_t lastIndex = display->mClientCompositionInfo.mLastIndex;
861 
862     /* Don't optimize if only low fps layers are composited by GLES */
863     if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
864         (display->mLowFpsLayerInfo.mFirstIndex == firstIndex) &&
865         (display->mLowFpsLayerInfo.mLastIndex == lastIndex))
866         return ret;
867 
868     for (int32_t i = firstIndex; i <= lastIndex; i++) {
869         ExynosMPP *m2mMPP = NULL;
870         ExynosMPP *otfMPP = NULL;
871         exynos_image m2m_out_img;
872         uint32_t overlayInfo = 0;
873         int32_t compositionType = 0;
874         ExynosLayer *layer = display->mLayers[i];
875         if ((layer->mOverlayPriority >= ePriorityHigh) &&
876             (layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)) {
877             display->mClientCompositionInfo.mFirstIndex++;
878             continue;
879         }
880         compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, overlayInfo);
881         if (compositionType == HWC2_COMPOSITION_DEVICE) {
882             /*
883              * Don't allocate G2D
884              * Execute can be fail because of other job
885              * Prioritizing is required to allocate G2D
886              */
887             if ((m2mMPP != NULL) && (m2mMPP->mPhysicalType == MPP_G2D))
888                 break;
889 
890             if ((ret = changeLayerFromClientToDevice(display, layer, i, m2m_out_img, m2mMPP, otfMPP)) != NO_ERROR)
891                 return ret;
892         } else {
893             break;
894         }
895     }
896 
897     firstIndex = display->mClientCompositionInfo.mFirstIndex;
898     lastIndex = display->mClientCompositionInfo.mLastIndex;
899     for (int32_t i = lastIndex; i >= 0; i--) {
900         ExynosMPP *m2mMPP = NULL;
901         ExynosMPP *otfMPP = NULL;
902         exynos_image m2m_out_img;
903         uint32_t overlayInfo = 0;
904         int32_t compositionType = 0;
905         ExynosLayer *layer = display->mLayers[i];
906         if ((layer->mOverlayPriority >= ePriorityHigh) &&
907             (layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)) {
908             display->mClientCompositionInfo.mLastIndex--;
909             continue;
910         }
911         compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, overlayInfo);
912         if (compositionType == HWC2_COMPOSITION_DEVICE) {
913             /*
914              * Don't allocate G2D
915              * Execute can be fail because of other job
916              * Prioritizing is required to allocate G2D
917              */
918             if ((m2mMPP != NULL) && (m2mMPP->mPhysicalType == MPP_G2D))
919                 break;
920             if ((ret = changeLayerFromClientToDevice(display, layer, i, m2m_out_img, m2mMPP, otfMPP)) != NO_ERROR)
921                 return ret;
922         } else {
923             break;
924         }
925     }
926 
927     return ret;
928 }
929 
resetAssignedResources(ExynosDisplay * display,bool forceReset)930 int32_t ExynosResourceManager::resetAssignedResources(ExynosDisplay * display, bool forceReset)
931 {
932     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
933         if (mOtfMPPs[i]->mAssignedDisplay != display)
934             continue;
935 
936         mOtfMPPs[i]->resetAssignedState();
937     }
938     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
939         if (mM2mMPPs[i]->mAssignedDisplay != display)
940             continue;
941         if ((forceReset == false) &&
942             ((mM2mMPPs[i]->mLogicalType == MPP_LOGICAL_G2D_RGB) ||
943              (mM2mMPPs[i]->mLogicalType == MPP_LOGICAL_G2D_COMBO)))
944         {
945             /*
946              * Don't reset assigned state
947              */
948             continue;
949         }
950         mM2mMPPs[i]->resetAssignedState();
951     }
952     display->mWindowNumUsed = 0;
953 
954     return NO_ERROR;
955 }
956 
assignCompositionTarget(ExynosDisplay * display,uint32_t targetType)957 int32_t ExynosResourceManager::assignCompositionTarget(ExynosDisplay * display, uint32_t targetType)
958 {
959     int32_t ret = NO_ERROR;
960     ExynosCompositionInfo *compositionInfo;
961 
962     HDEBUGLOGD(eDebugResourceManager, "%s:: display(%d), targetType(%d) +++++",
963             __func__, display->mType, targetType);
964 
965     if (targetType == COMPOSITION_CLIENT)
966         compositionInfo = &(display->mClientCompositionInfo);
967     else if (targetType == COMPOSITION_EXYNOS)
968         compositionInfo = &(display->mExynosCompositionInfo);
969     else
970         return -EINVAL;
971 
972     if (compositionInfo->mHasCompositionLayer == false)
973     {
974         HDEBUGLOGD(eDebugResourceManager, "\tthere is no composition layers");
975         return NO_ERROR;
976     }
977 
978     exynos_image src_img;
979     exynos_image dst_img;
980     display->setCompositionTargetExynosImage(targetType, &src_img, &dst_img);
981 
982     if (targetType == COMPOSITION_EXYNOS) {
983         for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
984             if ((display->mUseDpu == true) &&
985                 (mM2mMPPs[i]->mLogicalType != MPP_LOGICAL_G2D_RGB))
986                 continue;
987             if ((display->mUseDpu == false) &&
988                 (mM2mMPPs[i]->mLogicalType != MPP_LOGICAL_G2D_COMBO))
989                 continue;
990             if (mM2mMPPs[i]->isAssignableState(display, src_img, dst_img)) {
991                 /* assignMPP(display, compositionInfo) is not called hear
992                  * assignMPP() was called already during assigning layer
993                  * Source of M2mMPP should be Layer, not composition target buffer*/
994                 compositionInfo->mM2mMPP = mM2mMPPs[i];
995             }
996         }
997         if (compositionInfo->mM2mMPP == NULL) {
998             HWC_LOGE(display, "%s:: fail to assign M2mMPP (%d)",__func__, ret);
999             return eInsufficientMPP;
1000         }
1001     }
1002 
1003     if ((compositionInfo->mFirstIndex < 0) ||
1004         (compositionInfo->mLastIndex < 0)) {
1005         HWC_LOGE(display, "%s:: layer index is not valid mFirstIndex(%d), mLastIndex(%d)",
1006                 __func__, compositionInfo->mFirstIndex, compositionInfo->mLastIndex);
1007         return -EINVAL;
1008     }
1009 
1010     if (display->mUseDpu == false) {
1011         return NO_ERROR;
1012     }
1013 
1014     int64_t isSupported = 0;
1015     bool isAssignableState = false;
1016 
1017     otfMppReordering(display, mOtfMPPs, src_img, dst_img);
1018 
1019     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
1020         compositionInfo->setExynosImage(src_img, dst_img);
1021         compositionInfo->setExynosMidImage(dst_img);
1022         HDEBUGLOGD(eDebugTDM, "%s M2M target calculation start", __func__);
1023         calculateHWResourceAmount(display, compositionInfo);
1024 
1025         isSupported = mOtfMPPs[i]->isSupported(*display, src_img, dst_img);
1026         if (isSupported == NO_ERROR)
1027             isAssignableState =
1028                     isAssignable(mOtfMPPs[i], display, src_img, dst_img, compositionInfo);
1029 
1030         HDEBUGLOGD(eDebugResourceAssigning,
1031                    "\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
1032                    mOtfMPPs[i]->mName.c_str(), -isSupported, isAssignableState);
1033         if ((isSupported == NO_ERROR) && (isAssignableState)) {
1034             if ((ret = mOtfMPPs[i]->assignMPP(display, compositionInfo)) != NO_ERROR)
1035             {
1036                 HWC_LOGE(display, "%s:: %s MPP assignMPP() error (%d)",
1037                         __func__, mOtfMPPs[i]->mName.c_str(), ret);
1038                 return ret;
1039             }
1040             compositionInfo->mOtfMPP = mOtfMPPs[i];
1041             display->mWindowNumUsed++;
1042 
1043             HDEBUGLOGD(eDebugResourceManager, "%s:: %s is assigned", __func__, mOtfMPPs[i]->mName.c_str());
1044             return NO_ERROR;
1045         }
1046     }
1047 
1048     HDEBUGLOGD(eDebugResourceManager, "%s:: insufficient MPP", __func__);
1049     return eInsufficientMPP;
1050 }
1051 
validateLayer(uint32_t index,ExynosDisplay * display,ExynosLayer * layer)1052 int32_t ExynosResourceManager::validateLayer(uint32_t index, ExynosDisplay *display, ExynosLayer *layer)
1053 {
1054     if ((layer == NULL) || (display == NULL))
1055         return eUnknown;
1056 
1057     if (exynosHWCControl.forceGpu == 1) {
1058         if ((layer->mLayerBuffer == NULL) ||
1059             (getDrmMode(layer->mLayerBuffer) == NO_DRM))
1060             return eForceFbEnabled;
1061     }
1062 
1063     if ((display->mLayers.size() >= MAX_OVERLAY_LAYER_NUM) &&
1064         (layer->mOverlayPriority < ePriorityHigh))
1065         return eExceedMaxLayerNum;
1066 
1067     if ((layer->mLayerBuffer != NULL) &&
1068         (getDrmMode(layer->mLayerBuffer) == NO_DRM) &&
1069         (display->mDREnable == true) &&
1070         (display->mDynamicReCompMode == DEVICE_2_CLIENT))
1071         return eDynamicRecomposition;
1072 
1073     if ((layer->mLayerBuffer != NULL) &&
1074             (display->mType == HWC_DISPLAY_PRIMARY) &&
1075             (mForceReallocState != DST_REALLOC_DONE)) {
1076         ALOGI("Device type assign skipping by dst reallocation...... ");
1077         return eReallocOnGoingForDDI;
1078     }
1079 
1080     if (layer->mCompositionType == HWC2_COMPOSITION_CLIENT) return eForceBySF;
1081 
1082 #ifndef HWC_SUPPORT_COLOR_TRANSFORM
1083     if (display->mColorTransformHint != HAL_COLOR_TRANSFORM_IDENTITY) {
1084         HWC_LOGE(display, "unsupported color transform");
1085         return eUnSupportedColorTransform;
1086     }
1087 #else
1088     if ((display->mColorTransformHint < 0) &&
1089         (layer->mOverlayPriority < ePriorityHigh))
1090         return eUnSupportedColorTransform;
1091 #endif
1092 
1093     if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
1094         (display->mLowFpsLayerInfo.mFirstIndex <= (int32_t)index) &&
1095         ((int32_t)index <= display->mLowFpsLayerInfo.mLastIndex))
1096         return eLowFpsLayer;
1097 
1098     if(layer->isDimLayer() && layer->mLayerBuffer == NULL) {
1099         return eDimLayer;
1100     }
1101 
1102     if (!(display->mType == HWC_DISPLAY_VIRTUAL &&
1103         ((ExynosVirtualDisplay *)display)->mIsWFDState == (int)LLWFD))
1104 
1105     if (layer->mLayerBuffer == NULL)
1106         return eInvalidHandle;
1107     if (isSrcCropFloat(layer->mPreprocessedInfo.sourceCrop))
1108         return eHasFloatSrcCrop;
1109 
1110     if ((layer->mPreprocessedInfo.displayFrame.left < 0) ||
1111         (layer->mPreprocessedInfo.displayFrame.top < 0) ||
1112         (layer->mPreprocessedInfo.displayFrame.right > (int32_t)display->mXres) ||
1113         (layer->mPreprocessedInfo.displayFrame.bottom > (int32_t)display->mYres))
1114         return eInvalidDispFrame;
1115 
1116     if (layer->mPreprocessedInfo.sdrDimRatio < mMinimumSdrDimRatio)
1117         return eExceedSdrDimRatio;
1118 
1119     return NO_ERROR;
1120 }
1121 
validateRCDLayer(const ExynosDisplay & display,const ExynosLayer & layer,const uint32_t layerIndex,const exynos_image & srcImg,const exynos_image & dstImg)1122 int32_t ExynosResourceManager::validateRCDLayer(const ExynosDisplay &display,
1123                                                 const ExynosLayer &layer, const uint32_t layerIndex,
1124                                                 const exynos_image &srcImg,
1125                                                 const exynos_image &dstImg) {
1126     if (CC_UNLIKELY(srcImg.bufferHandle == NULL || srcImg.format != HAL_PIXEL_FORMAT_GOOGLE_R_8)) {
1127         return eInvalidHandle;
1128     }
1129 
1130     if (bool supported;
1131         CC_UNLIKELY(display.getRCDLayerSupport(supported) != NO_ERROR || !supported))
1132         return eUnSupportedUseCase;
1133 
1134     // no rotation
1135     if (srcImg.transform & (HAL_TRANSFORM_ROT_90 | HAL_TRANSFORM_ROT_180)) {
1136         return eMPPUnsupported;
1137     }
1138 
1139     // no scale
1140     if (srcImg.w != dstImg.w || srcImg.h != dstImg.h) {
1141         return eMPPUnsupported;
1142     }
1143 
1144     // only support RCD Layers on the top
1145     if (layerIndex != display.mLayers.size() - 1) {
1146         return eMPPUnsupported;
1147     }
1148 
1149     // b/215335109: IMG_SIZE must be equal or larger than display output
1150     if (dstImg.x != 0 || dstImg.y != 0 || dstImg.w != display.mXres || dstImg.h != display.mYres) {
1151         return eInvalidDispFrame;
1152     }
1153 
1154     return NO_ERROR;
1155 }
1156 
getAlignedImage(exynos_image image,const ExynosMPP * m2mMpp,const ExynosMPP * otfMpp) const1157 exynos_image ExynosResourceManager::getAlignedImage(exynos_image image, const ExynosMPP *m2mMpp,
1158                                                     const ExynosMPP *otfMpp) const {
1159     const auto srcCropWidthAlign = otfMpp ? otfMpp->getSrcCropWidthAlign(image) : 1;
1160     const auto srcCropHeightAlign = otfMpp ? otfMpp->getSrcCropHeightAlign(image) : 1;
1161     const auto dstwidthAlign = m2mMpp ? m2mMpp->getDstWidthAlign(image) : 1;
1162     const auto dstHeightAlign = m2mMpp ? m2mMpp->getDstHeightAlign(image) : 1;
1163 
1164     const auto widthAlign = std::lcm(srcCropWidthAlign, dstwidthAlign);
1165     const auto heighAlign = std::lcm(srcCropHeightAlign, dstHeightAlign);
1166 
1167     image.w = pixel_align(image.w, widthAlign);
1168     image.h = pixel_align(image.h, heighAlign);
1169 
1170     return image;
1171 }
1172 
getCandidateScalingM2mMPPOutImages(const ExynosDisplay * display,const exynos_image & src_img,const exynos_image & dst_img,std::vector<exynos_image> & image_lists)1173 void ExynosResourceManager::getCandidateScalingM2mMPPOutImages(
1174         const ExynosDisplay *display, const exynos_image &src_img, const exynos_image &dst_img,
1175         std::vector<exynos_image> &image_lists) {
1176     const bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90);
1177     const uint32_t srcWidth = isPerpendicular ? src_img.h : src_img.w;
1178     const uint32_t srcHeight = isPerpendicular ? src_img.w : src_img.h;
1179 
1180     const bool scaleUp = (srcWidth < dst_img.w && srcHeight < dst_img.h);
1181     const bool scaleDown = (srcWidth > dst_img.w && srcHeight > dst_img.h);
1182 
1183     if (!scaleUp && !scaleDown) {
1184         return;
1185     }
1186 
1187     /* otfMPP doesn't rotate image, m2mMPP rotates image */
1188     exynos_image dst_scale_img = dst_img;
1189 
1190     if (hasHdrInfo(src_img)) {
1191         if (isFormatYUV(src_img.format))
1192             dst_scale_img.format = HAL_PIXEL_FORMAT_YCBCR_P010;
1193         else
1194             dst_scale_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
1195     } else {
1196         if (isFormatYUV(src_img.format)) {
1197             dst_scale_img.format = DEFAULT_MPP_DST_YUV_FORMAT;
1198         }
1199     }
1200 
1201     ExynosMPP *otfMpp = nullptr;
1202     ExynosMPP *m2mMpp = nullptr;
1203     uint32_t otfMppRatio = 1;
1204     uint32_t m2mMppRatio = 1;
1205     if (scaleUp) {
1206         for (ExynosMPP *m : mOtfMPPs) {
1207             auto ratio = m->getMaxUpscale(dst_scale_img, dst_img);
1208             if (ratio > 1) {
1209                 otfMpp = m;
1210                 otfMppRatio = ratio;
1211                 break;
1212             }
1213         }
1214         const auto reqRatio = max(float(dst_img.w) / float(srcWidth * otfMppRatio),
1215                                   float(dst_img.h) / float(srcHeight * otfMppRatio));
1216         for (ExynosMPP *m : mM2mMPPs) {
1217             float ratio = float(m->getMaxUpscale(src_img, dst_scale_img));
1218             if (ratio > reqRatio) {
1219                 m2mMpp = m;
1220                 m2mMppRatio = ratio;
1221                 break;
1222             }
1223         }
1224     } else {
1225         for (ExynosMPP *m : mM2mMPPs) {
1226             auto ratio = m->getMaxDownscale(*display, src_img, dst_scale_img);
1227             if (ratio > 1) {
1228                 m2mMpp = m;
1229                 m2mMppRatio = ratio;
1230                 break;
1231             }
1232         }
1233         const float otfSrcWidth = float(srcWidth / m2mMppRatio);
1234         const float scaleRatio_H = otfSrcWidth / float(dst_img.w);
1235         const float otfSrcHeight = float(srcHeight / m2mMppRatio);
1236         const float scaleRatio_V = otfSrcHeight / float(dst_img.h);
1237         const float displayRatio_V = float(dst_img.h) / float(display->mYres);
1238         const float resolution = otfSrcWidth * otfSrcHeight * display->getBtsRefreshRate() / 1000;
1239 
1240         for (ExynosMPP *m : mOtfMPPs) {
1241             auto ratio = m->getDownscaleRestriction(dst_scale_img, dst_img);
1242 
1243             if (ratio >= scaleRatio_H && ratio >= scaleRatio_V &&
1244                 m->checkDownscaleCap(resolution, displayRatio_V)) {
1245                 otfMpp = m;
1246                 otfMppRatio = ratio;
1247                 break;
1248             }
1249         }
1250     }
1251 
1252     if (!otfMpp && !m2mMpp) {
1253         HDEBUGLOGD(eDebugResourceManager,
1254                    "Cannot find available MPP for scaling src %d x %d, dst %d x %d", src_img.w,
1255                    src_img.h, dst_img.w, dst_img.h);
1256         return;
1257     }
1258 
1259     dst_scale_img.x = 0;
1260     dst_scale_img.y = 0;
1261     dst_scale_img.w = scaleDown ? dst_img.w : srcWidth;
1262     dst_scale_img.h = scaleDown ? dst_img.h : srcHeight;
1263 
1264     HDEBUGLOGD(eDebugResourceManager,
1265                "scaling w: %d, h: %d, ratio = otfType %d - %d, m2mType %d - %d", dst_scale_img.w,
1266                dst_scale_img.h, otfMpp ? otfMpp->mLogicalType : -1, otfMppRatio,
1267                m2mMpp ? m2mMpp->mLogicalType : -1, m2mMppRatio);
1268     if (scaleUp) {
1269         if (dst_scale_img.w * otfMppRatio < dst_img.w) {
1270             dst_scale_img.w = uint32_t(ceilf(float(dst_img.w) / float(otfMppRatio)));
1271         }
1272         if (dst_scale_img.h * otfMppRatio < dst_img.h) {
1273             dst_scale_img.h = uint32_t(ceilf(float(dst_img.h) / float(otfMppRatio)));
1274         }
1275     } else {
1276         if (dst_scale_img.w * m2mMppRatio < srcWidth) {
1277             dst_scale_img.w = uint32_t(ceilf(float(srcWidth) / float(m2mMppRatio)));
1278         }
1279         if (dst_scale_img.h * m2mMppRatio < srcHeight) {
1280             dst_scale_img.h = uint32_t(ceilf(float(srcHeight) / float(m2mMppRatio)));
1281         }
1282     }
1283     HDEBUGLOGD(eDebugResourceAssigning,
1284                "\tsrc[%d, %d, %d,%d], dst[%d, %d, %d,%d], mid[%d, %d, %d, %d]", src_img.x,
1285                src_img.y, src_img.w, src_img.h, dst_img.x, dst_img.y, dst_img.w, dst_img.h,
1286                dst_scale_img.x, dst_scale_img.y, dst_scale_img.w, dst_scale_img.h);
1287 
1288     if (isFormatSBWC(dst_scale_img.format)) {
1289         image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp));
1290         /*
1291          * SBWC format could not be supported in specific dst size
1292          * Add uncompressed YUV format to cover this size
1293          */
1294         dst_scale_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT;
1295     }
1296 
1297     image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp));
1298 }
1299 
getCandidateM2mMPPOutImages(ExynosDisplay * display,ExynosLayer * layer,std::vector<exynos_image> & image_lists)1300 int32_t ExynosResourceManager::getCandidateM2mMPPOutImages(ExynosDisplay *display,
1301         ExynosLayer *layer, std::vector<exynos_image> &image_lists)
1302 {
1303     exynos_image src_img;
1304     exynos_image dst_img;
1305     layer->setSrcExynosImage(&src_img);
1306     layer->setDstExynosImage(&dst_img);
1307     /* Position is (0, 0) */
1308     dst_img.x = 0;
1309     dst_img.y = 0;
1310 
1311     /* Check original source format first */
1312     dst_img.format = src_img.format;
1313     dst_img.dataSpace = src_img.dataSpace;
1314 
1315     /* Copy origin source HDR metadata */
1316     dst_img.metaParcel = src_img.metaParcel;
1317 
1318     getCandidateScalingM2mMPPOutImages(display, src_img, dst_img, image_lists);
1319 
1320     if (isFormatYUV(src_img.format) && !hasHdrInfo(src_img)) {
1321         dst_img.format = DEFAULT_MPP_DST_YUV_FORMAT;
1322     }
1323 
1324     ExynosExternalDisplay *external_display =
1325         (ExynosExternalDisplay*)mDevice->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
1326 
1327     /* For HDR through MSC or G2D case but dataspace is not changed */
1328     if (hasHdrInfo(src_img)) {
1329         if (isFormatYUV(src_img.format))
1330             dst_img.format = HAL_PIXEL_FORMAT_YCBCR_P010;
1331         else
1332             dst_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
1333         dst_img.dataSpace = src_img.dataSpace;
1334 
1335         /*
1336          * Align dst size
1337          * HDR10Plus should able to be processed by VGRFS
1338          * HDR on primary display should be processed by VGRFS
1339          * when external display is connected
1340          * because G2D is used by external display
1341          */
1342         if (hasHdr10Plus(dst_img) ||
1343             ((external_display != NULL) && (external_display->mPlugState) &&
1344              (display->mType == HWC_DISPLAY_PRIMARY))) {
1345             ExynosMPP *otfMppForHDRPlus = nullptr;
1346             auto mpp_it = std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
1347                     [](auto m) {
1348                     return (m->mAttr & MPP_ATTR_HDR10PLUS);
1349                     });
1350             otfMppForHDRPlus = mpp_it == mOtfMPPs.end() ? nullptr : *mpp_it;
1351             uint32_t srcCropWidthAlign = 1;
1352             uint32_t srcCropHeightAlign = 1;
1353             if (otfMppForHDRPlus) {
1354                 srcCropWidthAlign = otfMppForHDRPlus->getSrcCropWidthAlign(dst_img);
1355                 srcCropHeightAlign = otfMppForHDRPlus->getSrcCropHeightAlign(dst_img);
1356             }
1357             dst_img.w = pixel_align(dst_img.w, srcCropWidthAlign);
1358             dst_img.h = pixel_align(dst_img.h, srcCropHeightAlign);
1359         }
1360     }
1361 
1362     image_lists.push_back(dst_img);
1363     if (isFormatSBWC(dst_img.format)) {
1364         /*
1365          * SBWC format could not be supported in specific dst size
1366          * Add uncompressed YUV format to cover this size
1367          */
1368         dst_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT;
1369         image_lists.push_back(dst_img);
1370     }
1371 
1372     /* For G2D HDR case */
1373     if (hasHdrInfo(src_img)) {
1374         bool isExternalPlugged = false;
1375         isHdrExternal = false;
1376 
1377         if (external_display != NULL) {
1378             if (external_display->mPlugState) isExternalPlugged = true;
1379             if (isExternalPlugged && (external_display->mExternalHdrSupported == true))
1380                 isHdrExternal = true;
1381         }
1382 
1383         if (isHdrExternal && (display->mType == HWC_DISPLAY_EXTERNAL)) {
1384             dst_img.format = HAL_PIXEL_FORMAT_RGBA_1010102;
1385             dst_img.dataSpace = src_img.dataSpace;
1386         } else {
1387             uint32_t dataspace = HAL_DATASPACE_UNKNOWN;
1388             if (display->mColorMode == HAL_COLOR_MODE_NATIVE) {
1389                 dataspace = HAL_DATASPACE_DCI_P3;
1390                 dataspace &= ~HAL_DATASPACE_TRANSFER_MASK;
1391                 dataspace |= HAL_DATASPACE_TRANSFER_GAMMA2_2;
1392                 dataspace &= ~HAL_DATASPACE_RANGE_MASK;
1393                 dataspace |= HAL_DATASPACE_RANGE_LIMITED;
1394             } else {
1395                 dataspace = colorModeToDataspace(display->mColorMode);
1396             }
1397             dst_img.format = HAL_PIXEL_FORMAT_RGBX_8888;
1398             dst_img.dataSpace = (android_dataspace)dataspace;
1399         }
1400 
1401         /*
1402          * This image is not pushed for primary display
1403          * if external display is connected
1404          * because G2D is used only for HDR on exernal display
1405          */
1406         if (!(isExternalPlugged && (display->mType == HWC_DISPLAY_PRIMARY))) {
1407             image_lists.push_back(dst_img);
1408         }
1409     }
1410 
1411     if (isFormatYUV(src_img.format) && !hasHdrInfo(src_img)) {
1412         /* Check RGB format */
1413         dst_img.format = DEFAULT_MPP_DST_FORMAT;
1414         if (display->mColorMode == HAL_COLOR_MODE_NATIVE) {
1415             /* Bypass dataSpace */
1416             dst_img.dataSpace = src_img.dataSpace;
1417         } else {
1418             /* Covert data space */
1419             dst_img.dataSpace = colorModeToDataspace(display->mColorMode);
1420         }
1421         image_lists.push_back(dst_img);
1422     }
1423 
1424     /*
1425      * image_lists[] would be src of otfMPP.
1426      * Layer color transform should be addressed
1427      * with dataspace conversion.
1428      * It should be addressed by m2mMPP if m2mMPP converts dataspace.
1429      * In other cases, m2mMPP ignores color transform setting and
1430      * otfMPP addresses layer color transform if it is necessary.
1431      */
1432     for (auto &image: image_lists) {
1433         if (image.dataSpace == src_img.dataSpace)
1434             image.needColorTransform = src_img.needColorTransform;
1435         else
1436             image.needColorTransform = false;
1437 
1438     }
1439 
1440     return static_cast<int32_t>(image_lists.size());
1441 }
1442 
assignLayer(ExynosDisplay * display,ExynosLayer * layer,uint32_t layer_index,exynos_image & m2m_out_img,ExynosMPP ** m2mMPP,ExynosMPP ** otfMPP,uint32_t & overlayInfo)1443 int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *layer, uint32_t layer_index,
1444         exynos_image &m2m_out_img, ExynosMPP **m2mMPP, ExynosMPP **otfMPP, uint32_t &overlayInfo)
1445 {
1446     int32_t ret = NO_ERROR;
1447     uint32_t validateFlag = 0;
1448 
1449     exynos_image src_img;
1450     exynos_image dst_img;
1451     layer->setSrcExynosImage(&src_img);
1452     layer->setDstExynosImage(&dst_img);
1453     layer->setExynosImage(src_img, dst_img);
1454     layer->setExynosMidImage(dst_img);
1455 
1456     validateFlag = validateLayer(layer_index, display, layer);
1457     if ((display->mUseDpu) &&
1458         (display->mWindowNumUsed >= display->mMaxWindowNum))
1459         validateFlag |= eInsufficientWindow;
1460 
1461     HDEBUGLOGD(eDebugResourceManager, "\t[%d] layer: validateFlag(0x%8x), supportedMPPFlag(0x%8x)",
1462             layer_index, validateFlag, layer->mSupportedMPPFlag);
1463 
1464     if (hwcCheckDebugMessages(eDebugResourceAssigning)) {
1465         layer->printLayer();
1466     }
1467 
1468     if ((validateFlag == NO_ERROR) || (validateFlag == eInsufficientWindow) ||
1469         (validateFlag == eDimLayer)) {
1470         bool isAssignableFlag = false;
1471         uint64_t isSupported = 0;
1472         /* 1. Find available otfMPP */
1473         if (validateFlag != eInsufficientWindow) {
1474             otfMppReordering(display, mOtfMPPs, src_img, dst_img);
1475 
1476             for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
1477                 if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) != 0)
1478                     isAssignableFlag = isAssignable(mOtfMPPs[j], display, src_img, dst_img, layer);
1479 
1480                 HDEBUGLOGD(eDebugResourceAssigning,
1481                            "\t\t check %s: flag (%d) supportedBit(%d), isAssignable(%d)",
1482                            mOtfMPPs[j]->mName.c_str(), layer->mSupportedMPPFlag,
1483                            (layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType),
1484                            isAssignableFlag);
1485                 // dim layer skip device composition if color native
1486                 if (display->mColorMode == HAL_COLOR_MODE_NATIVE && validateFlag == eDimLayer) {
1487                     ALOGD("%s::DimLayer & color native", __func__);
1488                     continue;
1489                 }
1490 
1491                 if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) && (isAssignableFlag)) {
1492                     isSupported = mOtfMPPs[j]->isSupported(*display, src_img, dst_img);
1493                     HDEBUGLOGD(eDebugResourceAssigning, "\t\t\t isSupported(%" PRIx64 ")",
1494                                -isSupported);
1495                     if (isSupported == NO_ERROR) {
1496                         *otfMPP = mOtfMPPs[j];
1497                         return HWC2_COMPOSITION_DEVICE;
1498                     }
1499                 }
1500             }
1501         }
1502 
1503         /* 2. Find available m2mMPP */
1504         for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
1505             if ((display->mUseDpu == true) &&
1506                 (mM2mMPPs[j]->mLogicalType == MPP_LOGICAL_G2D_COMBO))
1507                 continue;
1508             if ((display->mUseDpu == false) &&
1509                 (mM2mMPPs[j]->mLogicalType == MPP_LOGICAL_G2D_RGB))
1510                 continue;
1511 
1512             /* Only G2D can be assigned if layer is supported by G2D
1513              * when window is not sufficient
1514              */
1515             if ((validateFlag == eInsufficientWindow) &&
1516                 (mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
1517                 (mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
1518                 HDEBUGLOGD(eDebugResourceAssigning,
1519                            "\t\tInsufficient window but exynosComposition is not assigned");
1520                 continue;
1521             }
1522 
1523             bool isAssignableState = mM2mMPPs[j]->isAssignableState(display, src_img, dst_img);
1524 
1525             HDEBUGLOGD(eDebugResourceAssigning,
1526                        "\t\t check %s: supportedBit(%d), isAssignableState(%d)",
1527                        mM2mMPPs[j]->mName.c_str(),
1528                        (layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType), isAssignableState);
1529 
1530             float totalUsedCapa = ExynosResourceManager::getResourceUsedCapa(*mM2mMPPs[j]);
1531             if (isAssignableState) {
1532                 if ((mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
1533                     (mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
1534                     exynos_image otf_dst_img = dst_img;
1535 
1536                     otf_dst_img.format = DEFAULT_MPP_DST_FORMAT;
1537 
1538                     std::vector<exynos_image> image_lists;
1539                     if ((ret = getCandidateM2mMPPOutImages(display, layer, image_lists)) < 0)
1540                     {
1541                         HWC_LOGE(display, "Fail getCandidateM2mMPPOutImages (%d)", ret);
1542                         return ret;
1543                     }
1544                     HDEBUGLOGD(eDebugResourceAssigning, "candidate M2mMPPOutImage num: %zu",
1545                                image_lists.size());
1546                     for (auto &otf_src_img : image_lists) {
1547                         dumpExynosImage(eDebugResourceAssigning, otf_src_img);
1548                         exynos_image m2m_src_img = src_img;
1549                         /* transform is already handled by m2mMPP */
1550                         if (CC_UNLIKELY(otf_src_img.transform != 0 || otf_dst_img.transform != 0)) {
1551                             ALOGE("%s:: transform should be handled by m2mMPP. otf_src_img "
1552                                   "transform %d, otf_dst_img transform %d",
1553                                   __func__, otf_src_img.transform, otf_dst_img.transform);
1554                             otf_src_img.transform = 0;
1555                             otf_dst_img.transform = 0;
1556                         }
1557 
1558                         /*
1559                          * This is the case that layer color transform should be
1560                          * addressed by otfMPP not m2mMPP
1561                          */
1562                         if (otf_src_img.needColorTransform)
1563                             m2m_src_img.needColorTransform = false;
1564 
1565                         if (((isSupported = mM2mMPPs[j]->isSupported(*display, m2m_src_img,
1566                                                                      otf_src_img)) != NO_ERROR) ||
1567                             ((isAssignableFlag =
1568                                       mM2mMPPs[j]->hasEnoughCapa(display, m2m_src_img, otf_src_img,
1569                                                                  totalUsedCapa)) == false)) {
1570                             HDEBUGLOGD(eDebugResourceAssigning,
1571                                        "\t\t\t check %s: supportedBit(0x%" PRIx64
1572                                        "), hasEnoughCapa(%d)",
1573                                        mM2mMPPs[j]->mName.c_str(), -isSupported, isAssignableFlag);
1574                             continue;
1575                         }
1576 
1577                         otfMppReordering(display, mOtfMPPs, otf_src_img, otf_dst_img);
1578 
1579                         /* 3. Find available OtfMPP for output of m2mMPP */
1580                         for (uint32_t k = 0; k < mOtfMPPs.size(); k++) {
1581                             isSupported = mOtfMPPs[k]->isSupported(*display, otf_src_img, otf_dst_img);
1582                             isAssignableFlag = false;
1583                             if (isSupported == NO_ERROR) {
1584                                 /* to prevent HW resource execeeded */
1585                                 ExynosCompositionInfo dpuSrcInfo;
1586                                 dpuSrcInfo.mSrcImg = otf_src_img;
1587                                 dpuSrcInfo.mDstImg = otf_dst_img;
1588                                 HDEBUGLOGD(eDebugTDM,
1589                                            "%s Composition target calculation start (candidates)",
1590                                            __func__);
1591                                 calculateHWResourceAmount(display, &dpuSrcInfo);
1592 
1593                                 isAssignableFlag = isAssignable(mOtfMPPs[k], display, otf_src_img,
1594                                                                 otf_dst_img, &dpuSrcInfo);
1595                             }
1596 
1597                             HDEBUGLOGD(eDebugResourceAssigning,
1598                                        "\t\t\t check %s: supportedBit(0x%" PRIx64
1599                                        "), isAssignable(%d)",
1600                                        mOtfMPPs[k]->mName.c_str(), -isSupported, isAssignableFlag);
1601                             if ((isSupported == NO_ERROR) && isAssignableFlag) {
1602                                 *m2mMPP = mM2mMPPs[j];
1603                                 *otfMPP = mOtfMPPs[k];
1604                                 m2m_out_img = otf_src_img;
1605                                 return HWC2_COMPOSITION_DEVICE;
1606                             }
1607                         }
1608                     }
1609                 } else {
1610                     if ((layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType) &&
1611                         ((isAssignableFlag = mM2mMPPs[j]->hasEnoughCapa(display, src_img, dst_img,
1612                                                                         totalUsedCapa) == true))) {
1613                         *m2mMPP = mM2mMPPs[j];
1614                         return HWC2_COMPOSITION_EXYNOS;
1615                     } else {
1616                         HDEBUGLOGD(eDebugResourceManager,
1617                                    "\t\t\t check %s: layer's mSupportedMPPFlag(0x%8x), "
1618                                    "hasEnoughCapa(%d)",
1619                                    mM2mMPPs[j]->mName.c_str(), layer->mSupportedMPPFlag,
1620                                    isAssignableFlag);
1621                     }
1622                 }
1623             }
1624         }
1625     }
1626     /* Fail to assign resource */
1627     if (validateFlag != NO_ERROR)
1628         overlayInfo = validateFlag;
1629     else
1630         overlayInfo = eMPPUnsupported;
1631     return HWC2_COMPOSITION_CLIENT;
1632 }
1633 
assignLayers(ExynosDisplay * display,uint32_t priority)1634 int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t priority)
1635 {
1636     HDEBUGLOGD(eDebugResourceAssigning, "%s:: display(%d), priority(%d) +++++", __func__,
1637                display->mType, priority);
1638 
1639     int32_t ret = NO_ERROR;
1640     bool needReAssign = false;
1641     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
1642         ExynosLayer *layer = display->mLayers[i];
1643         ExynosMPP *m2mMPP = NULL;
1644         ExynosMPP *otfMPP = NULL;
1645         exynos_image m2m_out_img;
1646         uint32_t validateFlag = 0;
1647         int32_t compositionType = 0;
1648 
1649         if ((layer->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT) ||
1650             (layer->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS))
1651             continue;
1652         if (layer->mOverlayPriority != priority)
1653             continue;
1654 
1655         exynos_image src_img;
1656         exynos_image dst_img;
1657         layer->setSrcExynosImage(&src_img);
1658         layer->setDstExynosImage(&dst_img);
1659         layer->setExynosImage(src_img, dst_img);
1660         layer->setExynosMidImage(dst_img);
1661 
1662         // TODO: call validate function for RCD layer
1663         if (layer->mCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION &&
1664             validateRCDLayer(*display, *layer, i, src_img, dst_img) == NO_ERROR) {
1665             layer->updateValidateCompositionType(HWC2_COMPOSITION_DISPLAY_DECORATION);
1666             continue;
1667         }
1668 
1669         compositionType = assignLayer(display, layer, i, m2m_out_img, &m2mMPP, &otfMPP, validateFlag);
1670         if (compositionType == HWC2_COMPOSITION_DEVICE) {
1671             if (otfMPP != NULL) {
1672                 if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
1673                 {
1674                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
1675                             __func__, otfMPP->mName.c_str(), ret);
1676                     return ret;
1677                 }
1678                 HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
1679                            otfMPP->mName.c_str());
1680             }
1681             if (m2mMPP != NULL) {
1682                 if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
1683                 {
1684                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
1685                             __func__, m2mMPP->mName.c_str(), ret);
1686                     return ret;
1687                 }
1688                 layer->setExynosMidImage(m2m_out_img);
1689                 HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
1690                            m2mMPP->mName.c_str());
1691             }
1692             layer->updateValidateCompositionType(compositionType, validateFlag);
1693             display->mWindowNumUsed++;
1694             HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: mWindowNumUsed(%d)", i,
1695                        display->mWindowNumUsed);
1696         } else if (compositionType == HWC2_COMPOSITION_EXYNOS) {
1697             float totalUsedCapacity = 0;
1698             if (m2mMPP != NULL) {
1699                 if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
1700                 {
1701                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
1702                             __func__, m2mMPP->mName.c_str(), ret);
1703                     return ret;
1704                 }
1705                 totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
1706                 HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
1707                            m2mMPP->mName.c_str());
1708             }
1709             layer->updateValidateCompositionType(compositionType, validateFlag);
1710 
1711             HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: exynosComposition", i);
1712             /* G2D composition */
1713             if (((ret = display->addExynosCompositionLayer(i, totalUsedCapacity)) ==
1714                  EXYNOS_ERROR_CHANGED) ||
1715                 (ret < 0))
1716                 return ret;
1717             else {
1718                 /*
1719                  * If high fps layer should be composited by GLES then
1720                  * disable handling low fps feature and reassign resources
1721                  */
1722                 if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
1723                     (display->mClientCompositionInfo.mHasCompositionLayer == true) &&
1724                     ((display->mClientCompositionInfo.mFirstIndex < display->mLowFpsLayerInfo.mFirstIndex) ||
1725                      (display->mClientCompositionInfo.mLastIndex > display->mLowFpsLayerInfo.mLastIndex))) {
1726                     needReAssign = true;
1727                     break;
1728                 }
1729             }
1730         } else {
1731             /*
1732              * If high fps layer should be composited by GLES then
1733              * disable handling low fps feature and reassign resources
1734             */
1735             if ((display->mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
1736                 (((int32_t)i < display->mLowFpsLayerInfo.mFirstIndex) ||
1737                  (display->mLowFpsLayerInfo.mLastIndex < (int32_t)i))) {
1738                 needReAssign = true;
1739                 break;
1740             }
1741 
1742             /* Fail to assign resource, set HWC2_COMPOSITION_CLIENT */
1743             if (validateFlag != NO_ERROR) {
1744                 layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, validateFlag);
1745             } else {
1746                 layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, eMPPUnsupported);
1747             }
1748 
1749             if (((ret = display->addClientCompositionLayer(i)) == EXYNOS_ERROR_CHANGED) ||
1750                 (ret < 0))
1751                 return ret;
1752         }
1753     }
1754     if (needReAssign) {
1755         if ((display->mClientCompositionInfo.mHasCompositionLayer) &&
1756                 (display->mClientCompositionInfo.mOtfMPP != NULL))
1757             display->mClientCompositionInfo.mOtfMPP->resetAssignedState();
1758 
1759         if (display->mExynosCompositionInfo.mHasCompositionLayer) {
1760             if (display->mExynosCompositionInfo.mOtfMPP != NULL)
1761                 display->mExynosCompositionInfo.mOtfMPP->resetAssignedState();
1762             if (display->mExynosCompositionInfo.mM2mMPP != NULL)
1763                 display->mExynosCompositionInfo.mM2mMPP->resetAssignedState();
1764         }
1765 
1766         display->initializeValidateInfos();
1767         display->mLowFpsLayerInfo.initializeInfos();
1768         return EXYNOS_ERROR_CHANGED;
1769     }
1770     return ret;
1771 }
1772 
assignWindow(ExynosDisplay * display)1773 int32_t ExynosResourceManager::assignWindow(ExynosDisplay *display)
1774 {
1775     HDEBUGLOGD(eDebugResourceManager, "%s +++++", __func__);
1776     int ret = NO_ERROR;
1777     uint32_t windowIndex = 0;
1778 
1779     if (!display->mUseDpu)
1780         return ret;
1781 
1782     windowIndex = display->mBaseWindowIndex;
1783 
1784     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
1785         ExynosLayer *layer = display->mLayers[i];
1786         HDEBUGLOGD(eDebugResourceAssigning, "\t[%d] layer type: %d", i,
1787                    layer->getValidateCompositionType());
1788 
1789         if (layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) {
1790             layer->mWindowIndex = windowIndex;
1791             HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer windowIndex: %d", i, windowIndex);
1792         } else if ((layer->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT) ||
1793                    (layer->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS)) {
1794             ExynosCompositionInfo *compositionInfo;
1795             if (layer->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT)
1796                 compositionInfo = &display->mClientCompositionInfo;
1797             else
1798                 compositionInfo = &display->mExynosCompositionInfo;
1799 
1800             if ((compositionInfo->mHasCompositionLayer == false) ||
1801                 (compositionInfo->mFirstIndex < 0) ||
1802                 (compositionInfo->mLastIndex < 0)) {
1803                 HWC_LOGE(display, "%s:: Invalid %s CompositionInfo mHasCompositionLayer(%d), "
1804                         "mFirstIndex(%d), mLastIndex(%d) ",
1805                         __func__, compositionInfo->getTypeStr().c_str(),
1806                         compositionInfo->mHasCompositionLayer,
1807                         compositionInfo->mFirstIndex,
1808                         compositionInfo->mLastIndex);
1809                 continue;
1810             }
1811             if (i != (uint32_t)compositionInfo->mLastIndex)
1812                 continue;
1813             compositionInfo->mWindowIndex = windowIndex;
1814             HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] %s Composition windowIndex: %d",
1815                     i, compositionInfo->getTypeStr().c_str(), windowIndex);
1816         } else if (layer->getValidateCompositionType() == HWC2_COMPOSITION_DISPLAY_DECORATION) {
1817             layer->mWindowIndex = -1;
1818             continue;
1819         } else {
1820             HWC_LOGE(display, "%s:: Invalid layer compositionType layer(%d), compositionType(%d)",
1821                      __func__, i, layer->getValidateCompositionType());
1822             continue;
1823         }
1824         windowIndex++;
1825     }
1826     HDEBUGLOGD(eDebugResourceManager, "%s ------", __func__);
1827     return ret;
1828 }
1829 
1830 /**
1831  * @param * display
1832  * @return int
1833  */
updateSupportedMPPFlag(ExynosDisplay * display)1834 int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
1835 {
1836     int64_t ret = 0;
1837     HDEBUGLOGD(eDebugResourceAssigning, "%s++++++++++", __func__);
1838     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
1839         ExynosLayer *layer = display->mLayers[i];
1840         HDEBUGLOGD(eDebugResourceAssigning, "[%d] layer ", i);
1841 
1842         if (layer->mGeometryChanged == 0)
1843             continue;
1844 
1845         exynos_image src_img;
1846         exynos_image dst_img;
1847         exynos_image dst_img_yuv;
1848         layer->setSrcExynosImage(&src_img);
1849         layer->setDstExynosImage(&dst_img);
1850         layer->setDstExynosImage(&dst_img_yuv);
1851         dst_img.format = DEFAULT_MPP_DST_FORMAT;
1852         dst_img_yuv.format = DEFAULT_MPP_DST_YUV_FORMAT;
1853         HDEBUGLOGD(eDebugResourceAssigning, "\tsrc_img");
1854         dumpExynosImage(eDebugResourceAssigning, src_img);
1855         HDEBUGLOGD(eDebugResourceAssigning, "\tdst_img");
1856         dumpExynosImage(eDebugResourceAssigning, dst_img);
1857 
1858         /* Initialize flags */
1859         layer->mSupportedMPPFlag = 0;
1860         layer->mCheckMPPFlag.clear();
1861 
1862         /* Check OtfMPPs */
1863         for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
1864             if ((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
1865                 layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
1866                 HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported", mOtfMPPs[j]->mName.c_str());
1867             } else {
1868                 if (((-ret) == eMPPUnsupportedFormat) &&
1869                     ((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
1870                     layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
1871                     HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported with yuv dst",
1872                                mOtfMPPs[j]->mName.c_str());
1873                 }
1874             }
1875             if (ret < 0) {
1876                 HDEBUGLOGD(eDebugResourceAssigning, "\t%s: unsupported flag(0x%" PRIx64 ")",
1877                            mOtfMPPs[j]->mName.c_str(), -ret);
1878                 uint64_t checkFlag = 0x0;
1879                 if (layer->mCheckMPPFlag.find(mOtfMPPs[j]->mLogicalType) !=
1880                         layer->mCheckMPPFlag.end()) {
1881                     checkFlag = layer->mCheckMPPFlag.at(mOtfMPPs[j]->mLogicalType);
1882                 }
1883                 checkFlag |= (-ret);
1884                 layer->mCheckMPPFlag[mOtfMPPs[j]->mLogicalType] = checkFlag;
1885             }
1886         }
1887 
1888         /* Check M2mMPPs */
1889         for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
1890             if ((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
1891                 layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
1892                 HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported", mM2mMPPs[j]->mName.c_str());
1893             } else {
1894                 if (((-ret) == eMPPUnsupportedFormat) &&
1895                     ((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
1896                     layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
1897                     HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported with yuv dst",
1898                                mM2mMPPs[j]->mName.c_str());
1899                 }
1900             }
1901             if (ret < 0) {
1902                 HDEBUGLOGD(eDebugResourceAssigning, "\t%s: unsupported flag(0x%" PRIx64 ")",
1903                            mM2mMPPs[j]->mName.c_str(), -ret);
1904                 uint64_t checkFlag = 0x0;
1905                 if (layer->mCheckMPPFlag.find(mM2mMPPs[j]->mLogicalType) !=
1906                         layer->mCheckMPPFlag.end()) {
1907                     checkFlag = layer->mCheckMPPFlag.at(mM2mMPPs[j]->mLogicalType);
1908                 }
1909                 checkFlag |= (-ret);
1910                 layer->mCheckMPPFlag[mM2mMPPs[j]->mLogicalType] = checkFlag;
1911             }
1912         }
1913         HDEBUGLOGD(eDebugResourceAssigning, "[%d] layer mSupportedMPPFlag(0x%8x)", i,
1914                    layer->mSupportedMPPFlag);
1915     }
1916     HDEBUGLOGD(eDebugResourceAssigning, "%s-------------", __func__);
1917 
1918     return NO_ERROR;
1919 }
1920 
resetResources()1921 int32_t ExynosResourceManager::resetResources()
1922 {
1923     HDEBUGLOGD(eDebugResourceManager, "%s+++++++++", __func__);
1924 
1925     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
1926         mOtfMPPs[i]->resetMPP();
1927         if (hwcCheckDebugMessages(eDebugResourceManager)) {
1928             String8 dumpMPP;
1929             mOtfMPPs[i]->dump(dumpMPP);
1930             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
1931         }
1932     }
1933     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
1934         mM2mMPPs[i]->resetMPP();
1935         if (hwcCheckDebugMessages(eDebugResourceManager)) {
1936             String8 dumpMPP;
1937             mM2mMPPs[i]->dump(dumpMPP);
1938             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
1939         }
1940     }
1941 
1942     HDEBUGLOGD(eDebugResourceManager, "%s-----------",  __func__);
1943     return NO_ERROR;
1944 }
1945 
decideMainAndMinorDisplay(const int32_t willOnDispId) const1946 std::pair<ExynosDisplay*, ExynosDisplay*> ExynosResourceManager::decideMainAndMinorDisplay(
1947         const int32_t willOnDispId) const {
1948     ExynosDisplay *mainDisp = nullptr, *minorDisp = nullptr;
1949 
1950     auto rule = [](const ExynosDisplay* left, const ExynosDisplay* right) {
1951         if (left->mType == right->mType) return left->mIndex < right->mIndex;
1952         return left->mType > right->mType;
1953     };
1954 
1955     std::set<ExynosDisplay*, decltype(rule)> availableDisps(rule);
1956     for (auto& [disp_id, disp] : mDisplayMap) {
1957         if (disp == nullptr || !disp->mPlugState || !disp->mPowerModeState.has_value() ||
1958             (disp->mDisplayId != willOnDispId &&
1959              disp->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
1960             continue;
1961         availableDisps.insert(disp);
1962         HDEBUGLOGD(eDebugResourceManager, "%s: available display id: %d ", __func__,
1963                    disp->mDisplayId);
1964     }
1965     if (availableDisps.size() == 1) {
1966         mainDisp = *availableDisps.begin();
1967         HDEBUGLOGD(eDebugResourceManager, "%s: main display:%d ", __func__, mainDisp->mDisplayId);
1968     } else if (availableDisps.size() == 2) {
1969         mainDisp = *availableDisps.begin();
1970         minorDisp = *availableDisps.rbegin();
1971         HDEBUGLOGD(eDebugResourceManager, "%s: main display:%d minor display:%d ", __func__,
1972                    mainDisp->mDisplayId, minorDisp->mDisplayId);
1973     } else {
1974         ALOGE("%s(): wrong available display size:%zu", __func__, availableDisps.size());
1975     }
1976 
1977     return {mainDisp, minorDisp};
1978 }
1979 
updatePreAssignDisplayList(const ExynosDisplay * mainDisp,const ExynosDisplay * minorDisp)1980 void ExynosResourceManager::updatePreAssignDisplayList(const ExynosDisplay* mainDisp,
1981                                                        const ExynosDisplay* minorDisp) {
1982     auto updatePreAssignDisplay = [=](ExynosMPP* mpp, const ExynosDisplay* mainDisp,
1983                                       const ExynosDisplay* minorDisp) {
1984         if (mpp->mPreAssignDisplayInfo == HWC_RESERVE_DISPLAY_MAIN_BIT) {
1985             if (mainDisp != NULL)
1986                 mpp->mPreAssignDisplayList[DISPLAY_MODE_PRIMARY_MAIN] =
1987                         mainDisp->getDisplayPreAssignBit();
1988             else
1989                 ALOGE("Main display does not exist!");
1990         } else if (mpp->mPreAssignDisplayInfo == HWC_RESERVE_DISPLAY_MINOR_BIT) {
1991             if (minorDisp != NULL)
1992                 mpp->mPreAssignDisplayList[DISPLAY_MODE_PRIMARY_MAIN] =
1993                         minorDisp->getDisplayPreAssignBit();
1994             else if (mainDisp != NULL)
1995                 mpp->mPreAssignDisplayList[DISPLAY_MODE_PRIMARY_MAIN] =
1996                         mainDisp->getDisplayPreAssignBit();
1997             else
1998                 ALOGE("Main & minor display don't exist!");
1999         }
2000     };
2001 
2002     for (auto& mpp : mOtfMPPs) {
2003         updatePreAssignDisplay(mpp, mainDisp, minorDisp);
2004     }
2005     for (auto& mpp : mM2mMPPs) {
2006         updatePreAssignDisplay(mpp, mainDisp, minorDisp);
2007     }
2008 }
2009 
preAssignResources()2010 int32_t ExynosResourceManager::preAssignResources()
2011 {
2012     HDEBUGLOGD(eDebugResourceManager, "%s+++++++++", __func__);
2013     uint32_t displayMode = mDevice->mDisplayMode;
2014 
2015     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2016         if (mOtfMPPs[i]->mEnable == false) {
2017             mOtfMPPs[i]->reserveMPP();
2018             continue;
2019         }
2020 
2021         if (mOtfMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
2022             HDEBUGLOGD(eDebugResourceAssigning, "\t%s check, dispMode(%d), 0x%8x",
2023                        mOtfMPPs[i]->mName.c_str(), displayMode,
2024                        mOtfMPPs[i]->mPreAssignDisplayList[displayMode]);
2025 
2026             ExynosDisplay *display = NULL;
2027             for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
2028                 display = mDevice->mDisplays[j];
2029                 if (display == nullptr)
2030                     continue;
2031                 int checkBit = mOtfMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
2032                 HDEBUGLOGD(eDebugResourceAssigning, "\t\tdisplay index(%zu), checkBit(%d)", j,
2033                            checkBit);
2034                 if (checkBit) {
2035                     HDEBUGLOGD(eDebugResourceAssigning,
2036                                "\t\tdisplay index(%zu), displayId(%d), display(%p)", j,
2037                                display->mDisplayId, display);
2038                     if (display->mDisplayControl.forceReserveMPP ||
2039                         (display->mPlugState &&
2040                          ((display->mType != HWC_DISPLAY_PRIMARY) ||
2041                           (display->mPowerModeState.has_value() &&
2042                            (display->mPowerModeState.value() != HWC2_POWER_MODE_OFF))))) {
2043                         HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve to display %d",
2044                                    display->mDisplayId);
2045                         mOtfMPPs[i]->reserveMPP(display->mDisplayId);
2046                         break;
2047                     }
2048                 }
2049             }
2050         }
2051     }
2052     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2053         if (mM2mMPPs[i]->mEnable == false) {
2054             mM2mMPPs[i]->reserveMPP();
2055             continue;
2056         }
2057 
2058         if (mResourceReserved & mM2mMPPs[i]->mLogicalType) {
2059             /* MSC can't be used for rendering */
2060             HDEBUGLOGD(eDebugResourceManager, "\t\tMPP_MSC reserve without display because preview is running");
2061             mM2mMPPs[i]->reserveMPP();
2062             continue;
2063         }
2064         HDEBUGLOGD(eDebugResourceAssigning, "\t%s check, 0x%8x", mM2mMPPs[i]->mName.c_str(),
2065                    mM2mMPPs[i]->mPreAssignDisplayList[displayMode]);
2066         if (mM2mMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
2067             ExynosDisplay *display = NULL;
2068             for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
2069                 display = mDevice->mDisplays[j];
2070                 int checkBit = mM2mMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
2071                 HDEBUGLOGD(eDebugResourceAssigning, "\t\tdisplay index(%zu), checkBit(%d)", j,
2072                            checkBit);
2073                 if (checkBit) {
2074                     HDEBUGLOGD(eDebugResourceAssigning,
2075                                "\t\tdisplay index(%zu), displayId(%d), display(%p)", j,
2076                                display->mDisplayId, display);
2077                     if ((display != NULL) && (display->mPlugState == true)) {
2078                         HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve to display %d",
2079                                    display->mDisplayId);
2080                         mM2mMPPs[i]->reserveMPP(display->mDisplayId);
2081                         break;
2082                     } else {
2083                         HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve without display");
2084                         mM2mMPPs[i]->reserveMPP();
2085                     }
2086                 }
2087             }
2088         }
2089     }
2090     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2091         if (hwcCheckDebugMessages(eDebugResourceManager)) {
2092             String8 dumpMPP;
2093             mOtfMPPs[i]->dump(dumpMPP);
2094             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
2095         }
2096     }
2097     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2098         if (hwcCheckDebugMessages(eDebugResourceManager)) {
2099             String8 dumpMPP;
2100             mM2mMPPs[i]->dump(dumpMPP);
2101             HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
2102         }
2103     }
2104     HDEBUGLOGD(eDebugResourceManager, "%s-----------",  __func__);
2105     return NO_ERROR;
2106 }
2107 
preAssignWindows(ExynosDisplay * display)2108 void ExynosResourceManager::preAssignWindows(ExynosDisplay *display) {
2109     ExynosPrimaryDisplayModule *primaryDisplay = NULL;
2110 
2111     if (display->mType == HWC_DISPLAY_PRIMARY) {
2112         primaryDisplay = (ExynosPrimaryDisplayModule *)display;
2113     } else {
2114         primaryDisplay = (ExynosPrimaryDisplayModule *)mDevice->getDisplay(
2115                 getDisplayId(HWC_DISPLAY_PRIMARY, 0));
2116     }
2117 
2118     primaryDisplay->usePreDefinedWindow(false);
2119 }
2120 
preProcessLayer(ExynosDisplay * display)2121 int32_t ExynosResourceManager::preProcessLayer(ExynosDisplay * display)
2122 {
2123     int32_t ret = 0;
2124     hasHdrLayer = false;
2125     hasDrmLayer = false;
2126 
2127     for (uint32_t i = 0; i < display->mLayers.size(); i++) {
2128         ExynosLayer *layer = display->mLayers[i];
2129         if ((ret = layer->doPreProcess()) < 0) {
2130             HWC_LOGE(display, "%s:: doPreProcess() error, display(%d), layer %d", __func__, display->mType, i);
2131             return ret;
2132         }
2133         /* mIsHdrLayer is known after preprocess */
2134         if (layer->mIsHdrLayer) hasHdrLayer = true;
2135         if ((layer->mLayerBuffer != NULL) && (getDrmMode(layer->mLayerBuffer) != NO_DRM))
2136             hasDrmLayer = true;
2137     }
2138 
2139     // Re-align layer priority for max overlay resources
2140     uint32_t mNumMaxPriorityLayers = 0;
2141     for (int i = (display->mLayers.size()-1); i >= 0; i--) {
2142         ExynosLayer *layer = display->mLayers[i];
2143         HDEBUGLOGD(eDebugResourceManager, "Priority align: i:%d, layer priority:%d, Max:%d, mNumMaxPriorityAllowed:%d", i,
2144                 layer->mOverlayPriority, mNumMaxPriorityLayers, display->mNumMaxPriorityAllowed);
2145         if (layer->mOverlayPriority == ePriorityMax) {
2146             if (mNumMaxPriorityLayers >= display->mNumMaxPriorityAllowed) {
2147                 layer->mOverlayPriority = ePriorityHigh;
2148             }
2149             mNumMaxPriorityLayers++;
2150         }
2151     }
2152 
2153     return NO_ERROR;
2154 }
2155 
getExynosMPP(uint32_t type)2156 ExynosMPP* ExynosResourceManager::getExynosMPP(uint32_t type)
2157 {
2158     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2159         if (mOtfMPPs[i]->mLogicalType == type)
2160             return mOtfMPPs[i];
2161     }
2162     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2163         if (mM2mMPPs[i]->mLogicalType == type)
2164             return mM2mMPPs[i];
2165     }
2166 
2167     return NULL;
2168 }
2169 
getExynosMPP(uint32_t physicalType,uint32_t physicalIndex)2170 ExynosMPP* ExynosResourceManager::getExynosMPP(uint32_t physicalType, uint32_t physicalIndex)
2171 {
2172     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2173         if ((mOtfMPPs[i]->mPhysicalType == physicalType) &&
2174             (mOtfMPPs[i]->mPhysicalIndex == physicalIndex))
2175             return mOtfMPPs[i];
2176     }
2177     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2178         if ((mM2mMPPs[i]->mPhysicalType == physicalType) &&
2179             (mM2mMPPs[i]->mPhysicalIndex == physicalIndex))
2180             return mM2mMPPs[i];
2181     }
2182 
2183     return NULL;
2184 }
2185 
updateResourceState()2186 int32_t ExynosResourceManager::updateResourceState()
2187 {
2188     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2189         if (mOtfMPPs[i]->mAssignedSources.size() == 0)
2190             mOtfMPPs[i]->requestHWStateChange(MPP_HW_STATE_IDLE);
2191         mOtfMPPs[i]->mPrevAssignedState = mOtfMPPs[i]->mAssignedState;
2192     }
2193     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2194         if (mM2mMPPs[i]->mAssignedSources.size() == 0)
2195             mM2mMPPs[i]->requestHWStateChange(MPP_HW_STATE_IDLE);
2196         mM2mMPPs[i]->mPrevAssignedState = mM2mMPPs[i]->mAssignedState;
2197     }
2198     return NO_ERROR;
2199 }
2200 
2201 /*
2202  * This function is called every frame.
2203  * This base function does nothing.
2204  * Module that supports setting frame rate should implement this function
2205  * in the module source code (hardware/samsung_slsi/graphics/exynos...).
2206  */
setFrameRateForPerformance(ExynosMPP & mpp,AcrylicPerformanceRequestFrame * frame)2207 void ExynosResourceManager::setFrameRateForPerformance(ExynosMPP &mpp,
2208         AcrylicPerformanceRequestFrame *frame)
2209 {
2210     int fps = ceil(msecsPerSec / mpp.mCapacity);
2211     HDEBUGLOGD(eDebugResourceAssigning, "%s setFrameRate %d",
2212             mpp.mName.c_str(), fps);
2213     frame->setFrameRate(fps);
2214 }
2215 
deliverPerformanceInfo()2216 int32_t ExynosResourceManager::deliverPerformanceInfo()
2217 {
2218     int ret = NO_ERROR;
2219     for (uint32_t mpp_physical_type = 0; mpp_physical_type < MPP_P_TYPE_MAX; mpp_physical_type++) {
2220         /* Only G2D gets performance info in current version */
2221         if (mpp_physical_type != MPP_G2D)
2222             continue;
2223         AcrylicPerformanceRequest request;
2224         uint32_t assignedInstanceNum = 0;
2225         uint32_t assignedInstanceIndex = 0;
2226         ExynosMPP *mpp = NULL;
2227         bool canSkipSetting = true;
2228 
2229         for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2230             mpp = mM2mMPPs[i];
2231             if (mpp->mPhysicalType != mpp_physical_type)
2232                 continue;
2233             /* Performance setting can be skipped
2234              * if all of instance's mPrevAssignedState, mAssignedState
2235              * are MPP_ASSIGN_STATE_FREE
2236              */
2237             if ((mpp->mPrevAssignedState & MPP_ASSIGN_STATE_ASSIGNED) ||
2238                 (mpp->mAssignedState & MPP_ASSIGN_STATE_ASSIGNED))
2239             {
2240                 canSkipSetting = false;
2241             }
2242 
2243             if (mpp->canSkipProcessing())
2244                 continue;
2245 
2246             if ((mpp->mAssignedDisplay != NULL) &&
2247                 (mpp->mAssignedSources.size() > 0))
2248             {
2249                 assignedInstanceNum++;
2250             }
2251         }
2252         if ((canSkipSetting == true) && (assignedInstanceNum != 0)) {
2253             HWC_LOGE(NULL, "%s:: canSKip true but assignedInstanceNum(%d)",
2254                     __func__, assignedInstanceNum);
2255         }
2256         request.reset(assignedInstanceNum);
2257 
2258         if (canSkipSetting == true)
2259             continue;
2260 
2261         for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2262             mpp = mM2mMPPs[i];
2263             if ((mpp->mPhysicalType == mpp_physical_type) &&
2264                 (mpp->mAssignedDisplay != NULL) &&
2265                 (mpp->mAssignedSources.size() > 0))
2266             {
2267                 if (mpp->canSkipProcessing())
2268                     continue;
2269                 if (assignedInstanceIndex >= assignedInstanceNum) {
2270                     HWC_LOGE(NULL,"assignedInstanceIndex error (%d, %d)", assignedInstanceIndex, assignedInstanceNum);
2271                     break;
2272                 }
2273                 AcrylicPerformanceRequestFrame *frame = request.getFrame(assignedInstanceIndex);
2274                 if(frame->reset(mpp->mAssignedSources.size()) == false) {
2275                     HWC_LOGE(NULL,"%d frame reset fail (%zu)", assignedInstanceIndex, mpp->mAssignedSources.size());
2276                     break;
2277                 }
2278                 setFrameRateForPerformance(*mpp, frame);
2279 
2280                 for (uint32_t j = 0; j < mpp->mAssignedSources.size(); j++) {
2281                     ExynosMPPSource* mppSource = mpp->mAssignedSources[j];
2282                     frame->setSourceDimension(j,
2283                             mppSource->mSrcImg.w, mppSource->mSrcImg.h,
2284                             mppSource->mSrcImg.format);
2285 
2286                     if (mppSource->mSrcImg.compressionInfo.type == COMP_TYPE_AFBC)
2287                         frame->setAttribute(j, AcrylicCanvas::ATTR_COMPRESSED);
2288 
2289                     hwc_rect_t src_area;
2290                     src_area.left = mppSource->mSrcImg.x;
2291                     src_area.top = mppSource->mSrcImg.y;
2292                     src_area.right = mppSource->mSrcImg.x + mppSource->mSrcImg.w;
2293                     src_area.bottom = mppSource->mSrcImg.y + mppSource->mSrcImg.h;
2294 
2295                     hwc_rect_t out_area;
2296                     out_area.left = mppSource->mMidImg.x;
2297                     out_area.top = mppSource->mMidImg.y;
2298                     out_area.right = mppSource->mMidImg.x + mppSource->mMidImg.w;
2299                     out_area.bottom = mppSource->mMidImg.y + mppSource->mMidImg.h;
2300 
2301                     frame->setTransfer(j, src_area, out_area, mppSource->mSrcImg.transform);
2302                 }
2303                 uint32_t format = mpp->mAssignedSources[0]->mMidImg.format;
2304                 bool hasSolidColorLayer = false;
2305                 if (mpp->mNeedSolidColorLayer) {
2306                     format = DEFAULT_MPP_DST_FORMAT;
2307                     hasSolidColorLayer = true;
2308                 }
2309 
2310                 frame->setTargetDimension(mpp->mAssignedDisplay->mXres,
2311                         mpp->mAssignedDisplay->mYres, format, hasSolidColorLayer);
2312 
2313                 assignedInstanceIndex++;
2314             }
2315         }
2316         if ((mpp = getExynosMPP(MPP_LOGICAL_G2D_RGB)) != NULL)
2317             mpp->mAcrylicHandle->requestPerformanceQoS(&request);
2318         else
2319             HWC_LOGE(NULL,"getExynosMPP(MPP_LOGICAL_G2D_RGB) failed");
2320     }
2321     return ret;
2322 }
2323 
2324 /*
2325  * Get used capacity of the resource that abstracts same HW resource
2326  * but it is different instance with mpp
2327  */
getResourceUsedCapa(ExynosMPP & mpp)2328 float ExynosResourceManager::getResourceUsedCapa(ExynosMPP &mpp)
2329 {
2330     float usedCapa = 0;
2331     if (mpp.mCapacity < 0)
2332         return usedCapa;
2333 
2334     HDEBUGLOGD(eDebugResourceAssigning, "%s:: [%s][%d] mpp[%d, %d]", __func__, mpp.mName.c_str(),
2335                mpp.mLogicalIndex, mpp.mPhysicalType, mpp.mPhysicalIndex);
2336 
2337     if (mpp.mMPPType == MPP_TYPE_OTF) {
2338         for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2339             if ((mpp.mPhysicalType == mOtfMPPs[i]->mPhysicalType) &&
2340                 (mpp.mPhysicalIndex == mOtfMPPs[i]->mPhysicalIndex)) {
2341                 usedCapa += mOtfMPPs[i]->mUsedCapacity;
2342             }
2343         }
2344     } else {
2345         for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2346             if ((mpp.mPhysicalType == mM2mMPPs[i]->mPhysicalType) &&
2347                 (mpp.mPhysicalIndex == mM2mMPPs[i]->mPhysicalIndex)) {
2348                 usedCapa += mM2mMPPs[i]->mUsedCapacity;
2349             }
2350         }
2351     }
2352 
2353     HDEBUGLOGD(eDebugResourceAssigning, "\t[%s][%d] mpp usedCapa: %f", mpp.mName.c_str(),
2354                mpp.mLogicalIndex, usedCapa);
2355     return usedCapa;
2356 }
2357 
enableMPP(uint32_t physicalType,uint32_t physicalIndex,uint32_t logicalIndex,uint32_t enable)2358 void ExynosResourceManager::enableMPP(uint32_t physicalType, uint32_t physicalIndex, uint32_t logicalIndex, uint32_t enable)
2359 {
2360     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2361         if ((mOtfMPPs[i]->mPhysicalType == physicalType) &&
2362             (mOtfMPPs[i]->mPhysicalIndex == physicalIndex) &&
2363             (mOtfMPPs[i]->mLogicalIndex == logicalIndex)) {
2364             mOtfMPPs[i]->mEnable = !!(enable);
2365             return;
2366         }
2367     }
2368 
2369     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2370         if ((mM2mMPPs[i]->mPhysicalType == physicalType) &&
2371             (mM2mMPPs[i]->mPhysicalIndex == physicalIndex) &&
2372             (mM2mMPPs[i]->mLogicalIndex == logicalIndex)) {
2373             mM2mMPPs[i]->mEnable = !!(enable);
2374             return;
2375         }
2376     }
2377 }
2378 
setScaleDownRatio(uint32_t physicalType,uint32_t physicalIndex,uint32_t logicalIndex,uint32_t scaleDownRatio)2379 void ExynosResourceManager::setScaleDownRatio(uint32_t physicalType,
2380         uint32_t physicalIndex, uint32_t logicalIndex, uint32_t scaleDownRatio)
2381 {
2382     ExynosMPP *findMpp = nullptr;
2383 
2384     auto mpp_compare = [=](ExynosMPP *mpp)->bool {
2385         return ((mpp->mPhysicalType == physicalType) &&
2386                 (mpp->mPhysicalIndex == physicalIndex) &&
2387                 (mpp->mLogicalIndex == logicalIndex));
2388     };
2389 
2390     auto otfMPP = std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
2391             mpp_compare);
2392     if (otfMPP != mOtfMPPs.end()) {
2393         findMpp = *otfMPP;
2394     } else {
2395         auto m2mMPP = std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
2396                 mpp_compare);
2397         findMpp = m2mMPP == mM2mMPPs.end() ? nullptr : *m2mMPP;
2398     }
2399 
2400     if (findMpp == nullptr) {
2401         ALOGE("%s:: Invalid mpp (type: %d, index: %d, %d)",
2402                 __func__, physicalType, physicalIndex, logicalIndex);
2403         return;
2404     }
2405     for (uint32_t i = RESTRICTION_RGB; i < RESTRICTION_MAX; i++) {
2406         findMpp->mDstSizeRestrictions[i].maxDownScale = scaleDownRatio;
2407     }
2408 }
2409 
prepareResources(const int32_t willOnDispId)2410 int32_t ExynosResourceManager::prepareResources(const int32_t willOnDispId) {
2411     int ret = NO_ERROR;
2412     HDEBUGLOGD(eDebugResourceManager, "This is first validate");
2413     if ((ret = resetResources()) != NO_ERROR) {
2414         HWC_LOGE(NULL,"%s:: resetResources() error (%d)",
2415                 __func__, ret);
2416         return ret;
2417     }
2418     auto [mainDisp, minorDisp] = decideMainAndMinorDisplay(willOnDispId);
2419 
2420     if ((mDevice->mGeometryChanged & GEOMETRY_DISPLAY_POWER_ON) ||
2421         (mDevice->mGeometryChanged & GEOMETRY_DISPLAY_POWER_OFF) ||
2422         (mDevice->mGeometryChanged & GEOMETRY_DEVICE_DISPLAY_ADDED) ||
2423         (mDevice->mGeometryChanged & GEOMETRY_DEVICE_DISPLAY_REMOVED) || willOnDispId != -1)
2424         updatePreAssignDisplayList(mainDisp, minorDisp);
2425 
2426     if ((ret = preAssignResources()) != NO_ERROR) {
2427         HWC_LOGE(NULL,"%s:: preAssignResources() error (%d)",
2428                 __func__, ret);
2429         return ret;
2430     }
2431 
2432     setDisplaysTDMInfo(mainDisp, minorDisp);
2433 
2434     return ret;
2435 }
2436 
finishAssignResourceWork()2437 int32_t ExynosResourceManager::finishAssignResourceWork()
2438 {
2439 	int ret = NO_ERROR;
2440     if ((ret = updateResourceState()) != NO_ERROR) {
2441         HWC_LOGE(NULL,"%s:: stopUnAssignedResource() error (%d)",
2442                 __func__, ret);
2443         return ret;
2444     }
2445 
2446     mDevice->clearGeometryChanged();
2447     return ret;
2448 }
2449 
initResourcesState(ExynosDisplay * display)2450 int32_t ExynosResourceManager::initResourcesState(ExynosDisplay *display)
2451 {
2452     int ret = 0;
2453 
2454     if (mDevice->isFirstValidate()) {
2455         HDEBUGLOGD(eDebugResourceManager, "This is first validate");
2456         if (exynosHWCControl.displayMode < DISPLAY_MODE_NUM)
2457             mDevice->mDisplayMode = exynosHWCControl.displayMode;
2458 
2459         if ((ret = prepareResources()) != NO_ERROR) {
2460             HWC_LOGE(display, "%s:: prepareResources() error (%d)",
2461                     __func__, ret);
2462             return ret;
2463         }
2464         preAssignWindows(display);
2465 
2466     }
2467 
2468     return NO_ERROR;
2469 }
2470 
makeSizeRestrictions(uint32_t mppId,const restriction_size_t & size,restriction_classification_t format)2471 void ExynosResourceManager::makeSizeRestrictions(uint32_t mppId, const restriction_size_t &size,
2472                                                  restriction_classification_t format) {
2473     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.hwType = static_cast<mpp_phycal_type_t>(mppId);
2474     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.nodeType = NODE_SRC;
2475     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.format = HAL_PIXEL_FORMAT_NONE;
2476     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.reserved = 0;
2477     mSizeRestrictions[format][mSizeRestrictionCnt[format]++].sizeRestriction = size;
2478 
2479     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.hwType = static_cast<mpp_phycal_type_t>(mppId);
2480     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.nodeType = NODE_DST;
2481     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.format = HAL_PIXEL_FORMAT_NONE;
2482     mSizeRestrictions[format][mSizeRestrictionCnt[format]].key.reserved = 0;
2483     mSizeRestrictions[format][mSizeRestrictionCnt[format]++].sizeRestriction = size;
2484 
2485     HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
2486             getMPPStr(mppId).c_str(),
2487             size.maxDownScale,
2488             size.maxUpScale,
2489             size.maxFullWidth,
2490             size.maxFullHeight,
2491             size.minFullWidth,
2492             size.minFullHeight,
2493             size.fullWidthAlign,
2494             size.fullHeightAlign,
2495             size.maxCropWidth,
2496             size.maxCropHeight,
2497             size.minCropWidth,
2498             size.minCropHeight,
2499             size.cropXAlign,
2500             size.cropYAlign,
2501             size.cropWidthAlign,
2502             size.cropHeightAlign);
2503 }
2504 
makeFormatRestrictions(restriction_key_t table)2505 void ExynosResourceManager::makeFormatRestrictions(restriction_key_t table) {
2506 
2507     mFormatRestrictions[mFormatRestrictionCnt] = table;
2508 
2509     HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %s, %d",
2510                getMPPStr(mFormatRestrictions[mFormatRestrictionCnt].hwType).c_str(),
2511                mFormatRestrictions[mFormatRestrictionCnt].nodeType,
2512                getFormatStr(mFormatRestrictions[mFormatRestrictionCnt].format, COMP_TYPE_MASK)
2513                        .c_str(),
2514                mFormatRestrictions[mFormatRestrictionCnt].reserved);
2515     mFormatRestrictionCnt++;
2516 }
2517 
makeAcrylRestrictions(mpp_phycal_type_t type)2518 void ExynosResourceManager::makeAcrylRestrictions(mpp_phycal_type_t type){
2519 
2520     Acrylic *arc = NULL;
2521     const HW2DCapability *cap;
2522 
2523     if (type == MPP_MSC)
2524         arc = Acrylic::createScaler();
2525     else if (type == MPP_G2D)
2526         arc = Acrylic::createCompositor();
2527     else {
2528         ALOGE("Unknown MPP");
2529         return;
2530     }
2531 
2532     cap = &arc->getCapabilities();
2533 
2534     /* format restriction */
2535     std::unordered_set<int32_t> supportedHalFormats;
2536     for (uint32_t i = 0; i < FORMAT_MAX_CNT; i++) {
2537         if (cap->isFormatSupported(exynos_format_desc[i].halFormat)) {
2538             /* Not add same hal pixel format */
2539             if (supportedHalFormats.find(exynos_format_desc[i].halFormat) !=
2540                     supportedHalFormats.end())
2541                 continue;
2542             restriction_key_t queried_format;
2543             queried_format.hwType = type;
2544             queried_format.nodeType = NODE_NONE;
2545             queried_format.format = exynos_format_desc[i].halFormat;
2546             queried_format.reserved = 0;
2547             makeFormatRestrictions(queried_format);
2548             supportedHalFormats.insert(exynos_format_desc[i].halFormat);
2549         }
2550     }
2551 
2552     /* RGB size restrictions */
2553     restriction_size rSize;
2554     rSize.maxDownScale = cap->supportedMinMinification().hori;
2555     rSize.maxUpScale = cap->supportedMaxMagnification().hori;
2556     rSize.maxFullWidth = cap->supportedMaxSrcDimension().hori;
2557     rSize.maxFullHeight = cap->supportedMaxSrcDimension().vert;
2558     rSize.minFullWidth = cap->supportedMinSrcDimension().hori;
2559     rSize.minFullHeight = cap->supportedMinSrcDimension().vert;
2560     rSize.fullWidthAlign = cap->supportedDimensionAlign().hori;
2561     rSize.fullHeightAlign = cap->supportedDimensionAlign().vert;
2562     rSize.maxCropWidth = cap->supportedMaxSrcDimension().hori;
2563     rSize.maxCropHeight = cap->supportedMaxSrcDimension().vert;
2564     rSize.minCropWidth = cap->supportedMinSrcDimension().hori;
2565     rSize.minCropHeight = cap->supportedMinSrcDimension().vert;
2566     rSize.cropXAlign = cap->supportedDimensionAlign().hori;
2567     rSize.cropYAlign = cap->supportedDimensionAlign().vert;
2568     rSize.cropWidthAlign = cap->supportedDimensionAlign().hori;
2569     rSize.cropHeightAlign = cap->supportedDimensionAlign().vert;
2570 
2571     makeSizeRestrictions(type, rSize, RESTRICTION_RGB);
2572 
2573     /* YUV size restrictions */
2574     rSize.fullWidthAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
2575             YUV_CHROMA_H_SUBSAMPLE);
2576     rSize.fullHeightAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
2577             YUV_CHROMA_V_SUBSAMPLE);
2578     rSize.cropXAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
2579             YUV_CHROMA_H_SUBSAMPLE);
2580     rSize.cropYAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
2581             YUV_CHROMA_V_SUBSAMPLE);
2582     rSize.cropWidthAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().hori),
2583             YUV_CHROMA_H_SUBSAMPLE);
2584     rSize.cropHeightAlign = max(static_cast<uint32_t>(cap->supportedDimensionAlign().vert),
2585             YUV_CHROMA_V_SUBSAMPLE);
2586 
2587     makeSizeRestrictions(type, rSize, RESTRICTION_YUV);
2588 
2589     delete arc;
2590 }
2591 
getPhysicalType(int ch) const2592 mpp_phycal_type_t ExynosResourceManager::getPhysicalType(int ch) const {
2593 
2594     for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
2595         if(idma_channel_map[i].channel == ch)
2596             return idma_channel_map[i].type;
2597     }
2598 
2599     return MPP_P_TYPE_MAX;
2600 }
2601 
getOtfMPPWithChannel(int ch)2602 ExynosMPP* ExynosResourceManager::getOtfMPPWithChannel(int ch)
2603 {
2604     ExynosMPP *otfMPP = NULL;
2605 
2606     for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
2607         if(idma_channel_map[i].channel == ch) {
2608             otfMPP = getExynosMPP(idma_channel_map[i].type, idma_channel_map[i].index);
2609             break;
2610         }
2611     }
2612     return otfMPP;
2613 }
2614 
updateRestrictions()2615 void ExynosResourceManager::updateRestrictions() {
2616 
2617     if (mDevice->mDeviceInterface->getUseQuery() == true) {
2618         std::unordered_set<uint32_t> checkDuplicateMPP;
2619         for (const auto unit: AVAILABLE_M2M_MPP_UNITS) {
2620             if (checkDuplicateMPP.find(unit.physicalType) ==
2621                     checkDuplicateMPP.end())  {
2622                 makeAcrylRestrictions(static_cast<mpp_phycal_type_t>(unit.physicalType));
2623                 checkDuplicateMPP.insert(unit.physicalType);
2624             }
2625         }
2626     } else {
2627         mFormatRestrictionCnt = sizeof(restriction_format_table)/sizeof(restriction_key);
2628         for (uint32_t i = 0 ; i < mFormatRestrictionCnt; i++) {
2629             mFormatRestrictions[i].hwType = restriction_format_table[i].hwType;
2630             mFormatRestrictions[i].nodeType = restriction_format_table[i].nodeType;
2631             mFormatRestrictions[i].format = restriction_format_table[i].format;
2632             mFormatRestrictions[i].reserved = restriction_format_table[i].reserved;
2633         }
2634 
2635         // i = RGB, YUV
2636         // j = Size restriction count for each format (YUV, RGB)
2637         for (uint32_t i = 0; i < sizeof(restriction_tables)/sizeof(restriction_table_element); i++) {
2638             mSizeRestrictionCnt[i] = restriction_tables[i].table_element_size;
2639             for (uint32_t j = 0; j < mSizeRestrictionCnt[i]; j++) {
2640                 memcpy(&mSizeRestrictions[i][j], &restriction_tables[i].table[j],
2641                         sizeof(mSizeRestrictions[i][j]));
2642             }
2643         }
2644     }
2645 
2646     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2647         // mAttr should be updated with updated feature_table
2648         mOtfMPPs[i]->updateAttr();
2649         mOtfMPPs[i]->setupRestriction();
2650     }
2651 
2652     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2653         // mAttr should be updated with updated feature_table
2654         mM2mMPPs[i]->updateAttr();
2655         mM2mMPPs[i]->setupRestriction();
2656     }
2657 }
2658 
getFeatureTableSize() const2659 uint32_t ExynosResourceManager::getFeatureTableSize() const
2660 {
2661     return sizeof(feature_table)/sizeof(feature_support_t);
2662 }
2663 
hasHDR10PlusMPP()2664 bool ExynosResourceManager::hasHDR10PlusMPP() {
2665 
2666     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2667         if (mOtfMPPs[i] == NULL) continue;
2668         if (mOtfMPPs[i]->mAttr & MPP_ATTR_HDR10PLUS)
2669             return true;
2670     }
2671     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2672         if (mM2mMPPs[i] == NULL) continue;
2673         if (mM2mMPPs[i]->mAttr & MPP_ATTR_HDR10PLUS)
2674             return true;
2675     }
2676 
2677     return false;
2678 }
2679 
getAssignedCapacity(uint32_t physicalType)2680 float ExynosResourceManager::getAssignedCapacity(uint32_t physicalType)
2681 {
2682     float totalCapacity = 0;
2683 
2684     for (size_t i = 0; i < mM2mMPPs.size(); i++) {
2685         if (mM2mMPPs[i]->mPhysicalType == physicalType)
2686             totalCapacity += mM2mMPPs[i]->getAssignedCapacity();
2687     }
2688     return totalCapacity;
2689 }
2690 
getM2MCapa(uint32_t physicalType)2691 float ExynosResourceManager::getM2MCapa(uint32_t physicalType)
2692 {
2693     float ret = 0;
2694     for (size_t i = 0; i < mM2mMPPs.size(); i++) {
2695         if (mM2mMPPs[i]->mPhysicalType == physicalType)
2696             return mM2mMPPs[i]->mCapacity;
2697     }
2698 
2699     return ret;
2700 }
2701 
dump(String8 & result) const2702 void ExynosResourceManager::dump(String8 &result) const {
2703     result.appendFormat("Resource Manager:\n");
2704 
2705     result.appendFormat("[RGB Restrictions]\n");
2706     dump(RESTRICTION_RGB, result);
2707 
2708     result.appendFormat("[YUV Restrictions]\n");
2709     dump(RESTRICTION_YUV, result);
2710 
2711     result.appendFormat("[MPP Dump]\n");
2712     for (auto mpp : mOtfMPPs) {
2713         mpp->dump(result);
2714     }
2715     for (auto mpp : mM2mMPPs) {
2716         mpp->dump(result);
2717     }
2718 }
2719 
dump(const restriction_classification_t classification,String8 & result) const2720 void ExynosResourceManager::dump(const restriction_classification_t classification,
2721                                  String8 &result) const {
2722     const auto &restrictions = mSizeRestrictions[classification];
2723     const auto &restrictionCnt = mSizeRestrictionCnt[classification];
2724 
2725     for (int i = 0; i < restrictionCnt; ++i) {
2726         result.appendFormat("HW-Node %u-%u:\n", restrictions[i].key.hwType,
2727                             restrictions[i].key.nodeType);
2728         if (i > 0 && restrictions[i].sizeRestriction == restrictions[i - 1].sizeRestriction) {
2729             result.append("Same as above\n");
2730         } else {
2731             ::dump(restrictions[i].sizeRestriction, result);
2732         }
2733         result.appendFormat("\n");
2734     }
2735 }
2736 
setM2MCapa(uint32_t physicalType,uint32_t capa)2737 void ExynosResourceManager::setM2MCapa(uint32_t physicalType, uint32_t capa)
2738 {
2739     for (size_t i = 0; i < mM2mMPPs.size(); i++) {
2740         if (mM2mMPPs[i]->mPhysicalType == physicalType)
2741             mM2mMPPs[i]->mCapacity = capa;
2742     }
2743 }
2744 
isAssignable(ExynosMPP * candidateMPP,ExynosDisplay * display,struct exynos_image & src,struct exynos_image & dst,ExynosMPPSource * mppSrc)2745 bool ExynosResourceManager::isAssignable(ExynosMPP *candidateMPP, ExynosDisplay *display,
2746                                          struct exynos_image &src, struct exynos_image &dst,
2747                                          ExynosMPPSource *mppSrc)
2748 {
2749     bool ret = true;
2750 
2751     float totalUsedCapacity = getResourceUsedCapa(*candidateMPP);
2752     ret = candidateMPP->isAssignable(display, src, dst, totalUsedCapacity);
2753 
2754     if ((ret) && (mppSrc != nullptr)) {
2755         if ((candidateMPP->mMPPType == MPP_TYPE_OTF) &&
2756             (!isHWResourceAvailable(display, candidateMPP, mppSrc))) {
2757             if (mppSrc->mSourceType == MPP_SOURCE_LAYER) {
2758                 ExynosLayer *layer = (ExynosLayer *)mppSrc;
2759                 layer->mCheckMPPFlag[candidateMPP->mLogicalType] = eMPPExeedHWResource;
2760             }
2761             ret = false;
2762         }
2763     }
2764 
2765     return ret;
2766 }
2767 
updateSupportWCG()2768 void ExynosResourceManager::updateSupportWCG()
2769 {
2770     for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
2771         if (mOtfMPPs[i] == NULL) continue;
2772         if (mOtfMPPs[i]->mAttr & (MPP_ATTR_WCG | MPP_ATTR_HDR10)) mDeviceSupportWCG = true;
2773     }
2774     for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
2775         if (mM2mMPPs[i] == NULL) continue;
2776         if (mM2mMPPs[i]->mAttr & (MPP_ATTR_WCG | MPP_ATTR_HDR10)) mDeviceSupportWCG = true;
2777     }
2778 }
2779 
needHdrProcessing(ExynosDisplay * display,exynos_image & srcImg,exynos_image & dstImg)2780 bool ExynosResourceManager::needHdrProcessing(ExynosDisplay *display, exynos_image &srcImg,
2781                                               exynos_image &dstImg)
2782 {
2783     if (!deviceSupportWCG()) return false;
2784 
2785     return true;
2786 }
2787 
needHWResource(ExynosDisplay * display,exynos_image & srcImg,exynos_image & dstImg,tdm_attr_t attr)2788 uint32_t ExynosResourceManager::needHWResource(ExynosDisplay *display, exynos_image &srcImg,
2789                                                exynos_image &dstImg, tdm_attr_t attr)
2790 {
2791     uint32_t ret = 0;
2792 
2793     switch (attr) {
2794         case TDM_ATTR_SBWC:
2795             ret = (srcImg.compressionInfo.type == COMP_TYPE_SBWC) ? 1 : 0;
2796             break;
2797         case TDM_ATTR_AFBC:
2798             ret = (srcImg.compressionInfo.type == COMP_TYPE_AFBC) ? 1 : 0;
2799             break;
2800         case TDM_ATTR_ITP:
2801             ret = (isFormatYUV(srcImg.format)) ? 1 : 0;
2802             break;
2803         case TDM_ATTR_WCG:
2804             ret = (srcImg.needPreblending) ? 1 : 0;
2805             break;
2806         case TDM_ATTR_ROT_90:
2807             ret = ((srcImg.transform & HAL_TRANSFORM_ROT_90) == 0) ? 0 : 1;
2808             break;
2809         case TDM_ATTR_SCALE: {
2810             bool isPerpendicular = !!(srcImg.transform & HAL_TRANSFORM_ROT_90);
2811             if (isPerpendicular) {
2812                 ret = ((srcImg.w != dstImg.h) || (srcImg.h != dstImg.w)) ? 1 : 0;
2813             } else {
2814                 ret = ((srcImg.w != dstImg.w) || (srcImg.h != dstImg.h)) ? 1 : 0;
2815             }
2816         } break;
2817         default:
2818             ret = 0;
2819             break;
2820     }
2821 
2822     return ret;
2823 }
2824