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