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