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