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