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 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18 //#include <linux/fb.h>
19 #include "ExynosDisplay.h"
20
21 #include <android/binder_manager.h>
22 #include <cutils/properties.h>
23 #include <hardware/hwcomposer_defs.h>
24 #include <linux/fb.h>
25 #include <processgroup/processgroup.h>
26 #include <sync/sync.h>
27 #include <sys/ioctl.h>
28 #include <utils/CallStack.h>
29
30 #include <map>
31
32 #include "ExynosExternalDisplay.h"
33 #include "ExynosLayer.h"
34 #include "exynos_format.h"
35
36 #include "VendorGraphicBuffer.h"
37
38 #include <aidl/android/hardware/power/IPower.h>
39 #include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
40
41 /**
42 * ExynosDisplay implementation
43 */
44
45 using namespace android;
46 using namespace vendor::graphics;
47 using namespace std::chrono_literals;
48
49 using ::aidl::android::hardware::power::IPower;
50 using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
51
52 extern struct exynos_hwc_control exynosHWCControl;
53 extern struct update_time_info updateTimeInfo;
54
55 constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
56 constexpr int64_t nsecsIdleHintTimeout = std::chrono::nanoseconds(100ms).count();
57
PowerHalHintWorker()58 ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker()
59 : Worker("DisplayHints", HAL_PRIORITY_URGENT_DISPLAY),
60 mNeedUpdateRefreshRateHint(false),
61 mPrevRefreshRate(0),
62 mPendingPrevRefreshRate(0),
63 mIdleHintIsEnabled(false),
64 mForceUpdateIdleHint(false),
65 mIdleHintDeadlineTime(0),
66 mIdleHintSupportIsChecked(false),
67 mIdleHintIsSupported(false),
68 mPowerModeState(HWC2_POWER_MODE_OFF),
69 mVsyncPeriod(16666666),
70 mPowerHalExtAidl(nullptr),
71 mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {}
72
~PowerHalHintWorker()73 ExynosDisplay::PowerHalHintWorker::~PowerHalHintWorker() {
74 Exit();
75 }
76
Init()77 int ExynosDisplay::PowerHalHintWorker::Init() {
78 return InitWorker();
79 }
80
BinderDiedCallback(void * cookie)81 void ExynosDisplay::PowerHalHintWorker::BinderDiedCallback(void *cookie) {
82 ALOGE("PowerHal is died");
83 auto powerHint = reinterpret_cast<PowerHalHintWorker *>(cookie);
84 powerHint->forceUpdateHints();
85 }
86
connectPowerHalExt()87 int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHalExt() {
88 if (mPowerHalExtAidl) {
89 return NO_ERROR;
90 }
91
92 const std::string kInstance = std::string(IPower::descriptor) + "/default";
93 ndk::SpAIBinder pwBinder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
94 ndk::SpAIBinder pwExtBinder;
95
96 AIBinder_getExtension(pwBinder.get(), pwExtBinder.getR());
97 mPowerHalExtAidl = IPowerExt::fromBinder(pwExtBinder);
98 if (!mPowerHalExtAidl) {
99 ALOGE("failed to connect power HAL extension");
100 return -EINVAL;
101 }
102
103 AIBinder_linkToDeath(pwExtBinder.get(), mDeathRecipient.get(), reinterpret_cast<void *>(this));
104
105 forceUpdateHints();
106 ALOGI("connect power HAL extension successfully");
107 return NO_ERROR;
108 }
109
checkPowerHalExtHintSupport(const std::string & mode)110 int32_t ExynosDisplay::PowerHalHintWorker::checkPowerHalExtHintSupport(const std::string &mode) {
111 if (mode.empty() || connectPowerHalExt() != NO_ERROR) {
112 return -EINVAL;
113 }
114
115 bool isSupported = false;
116 auto ret = mPowerHalExtAidl->isModeSupported(mode.c_str(), &isSupported);
117 if (!ret.isOk()) {
118 ALOGE("failed to check power HAL extension hint: mode=%s", mode.c_str());
119 if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
120 /*
121 * PowerHAL service may crash due to some reasons, this could end up
122 * binder transaction failure. Set nullptr here to trigger re-connection.
123 */
124 ALOGE("binder transaction failed for power HAL extension hint");
125 mPowerHalExtAidl = nullptr;
126 return -ENOTCONN;
127 }
128 return -EINVAL;
129 }
130
131 if (!isSupported) {
132 ALOGW("power HAL extension hint is not supported: mode=%s", mode.c_str());
133 return -EOPNOTSUPP;
134 }
135
136 ALOGI("power HAL extension hint is supported: mode=%s", mode.c_str());
137 return NO_ERROR;
138 }
139
sendPowerHalExtHint(const std::string & mode,bool enabled)140 int32_t ExynosDisplay::PowerHalHintWorker::sendPowerHalExtHint(const std::string &mode,
141 bool enabled) {
142 if (mode.empty() || connectPowerHalExt() != NO_ERROR) {
143 return -EINVAL;
144 }
145
146 auto ret = mPowerHalExtAidl->setMode(mode.c_str(), enabled);
147 if (!ret.isOk()) {
148 ALOGE("failed to send power HAL extension hint: mode=%s, enabled=%d", mode.c_str(),
149 enabled);
150 if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
151 /*
152 * PowerHAL service may crash due to some reasons, this could end up
153 * binder transaction failure. Set nullptr here to trigger re-connection.
154 */
155 ALOGE("binder transaction failed for power HAL extension hint");
156 mPowerHalExtAidl = nullptr;
157 return -ENOTCONN;
158 }
159 return -EINVAL;
160 }
161
162 return NO_ERROR;
163 }
164
checkRefreshRateHintSupport(int refreshRate)165 int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(int refreshRate) {
166 int32_t ret = NO_ERROR;
167 const auto its = mRefreshRateHintSupportMap.find(refreshRate);
168 if (its == mRefreshRateHintSupportMap.end()) {
169 /* check new hint */
170 std::string refreshRateHintStr = "REFRESH_" + std::to_string(refreshRate) + "FPS";
171 ret = checkPowerHalExtHintSupport(refreshRateHintStr);
172 if (ret == NO_ERROR || ret == -EOPNOTSUPP) {
173 mRefreshRateHintSupportMap[refreshRate] = (ret == NO_ERROR);
174 ALOGI("cache refresh rate hint %s: %d", refreshRateHintStr.c_str(), !ret);
175 } else {
176 ALOGE("failed to check the support of refresh rate hint, ret %d", ret);
177 }
178 } else {
179 /* check existing hint */
180 if (!its->second) {
181 ret = -EOPNOTSUPP;
182 }
183 }
184 return ret;
185 }
186
sendRefreshRateHint(int refreshRate,bool enabled)187 int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(int refreshRate, bool enabled) {
188 std::string hintStr = "REFRESH_" + std::to_string(refreshRate) + "FPS";
189 int32_t ret = sendPowerHalExtHint(hintStr, enabled);
190 if (ret == -ENOTCONN) {
191 /* Reset the hints when binder failure occurs */
192 mPrevRefreshRate = 0;
193 mPendingPrevRefreshRate = 0;
194 }
195 return ret;
196 }
197
updateRefreshRateHintInternal(hwc2_power_mode_t powerMode,uint32_t vsyncPeriod)198 int32_t ExynosDisplay::PowerHalHintWorker::updateRefreshRateHintInternal(
199 hwc2_power_mode_t powerMode, uint32_t vsyncPeriod) {
200 int32_t ret = NO_ERROR;
201 /* We should disable pending hint before other operations */
202 if (mPendingPrevRefreshRate) {
203 ret = sendRefreshRateHint(mPendingPrevRefreshRate, false);
204 if (ret == NO_ERROR) {
205 mPendingPrevRefreshRate = 0;
206 } else {
207 return ret;
208 }
209 }
210
211 if (powerMode != HWC2_POWER_MODE_ON) {
212 if (mPrevRefreshRate) {
213 ret = sendRefreshRateHint(mPrevRefreshRate, false);
214 if (ret == NO_ERROR) {
215 mPrevRefreshRate = 0;
216 }
217 }
218 return ret;
219 }
220
221 /* TODO: add refresh rate buckets, tracked in b/181100731 */
222 int refreshRate = round(nsecsPerSec / vsyncPeriod * 0.1f) * 10;
223 if (mPrevRefreshRate == refreshRate) {
224 return NO_ERROR;
225 }
226
227 ret = checkRefreshRateHintSupport(refreshRate);
228 if (ret != NO_ERROR) {
229 return ret;
230 }
231
232 /*
233 * According to PowerHAL design, while switching to next refresh rate, we
234 * have to enable the next hint first, then disable the previous one so
235 * that the next hint can take effect.
236 */
237 ret = sendRefreshRateHint(refreshRate, true);
238 if (ret != NO_ERROR) {
239 return ret;
240 }
241
242 if (mPrevRefreshRate) {
243 ret = sendRefreshRateHint(mPrevRefreshRate, false);
244 if (ret != NO_ERROR) {
245 if (ret != -ENOTCONN) {
246 /*
247 * We may fail to disable the previous hint and end up multiple
248 * hints enabled. Save the failed hint as pending hint here, we
249 * will try to disable it first while entering this function.
250 */
251 mPendingPrevRefreshRate = mPrevRefreshRate;
252 mPrevRefreshRate = refreshRate;
253 }
254 return ret;
255 }
256 }
257
258 mPrevRefreshRate = refreshRate;
259 return ret;
260 }
261
checkIdleHintSupport(void)262 int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
263 int32_t ret = NO_ERROR;
264 Lock();
265 if (mIdleHintSupportIsChecked) {
266 ret = mIdleHintIsSupported ? NO_ERROR : -EOPNOTSUPP;
267 Unlock();
268 return ret;
269 }
270 Unlock();
271
272 ret = checkPowerHalExtHintSupport("DISPLAY_IDLE");
273 Lock();
274 if (ret == NO_ERROR) {
275 mIdleHintIsSupported = true;
276 mIdleHintSupportIsChecked = true;
277 ALOGI("display idle hint is supported");
278 } else if (ret == -EOPNOTSUPP) {
279 mIdleHintSupportIsChecked = true;
280 ALOGI("display idle hint is unsupported");
281 } else {
282 ALOGW("failed to check the support of display idle hint, ret %d", ret);
283 }
284 Unlock();
285 return ret;
286 }
287
updateIdleHint(int64_t deadlineTime,bool forceUpdate)288 int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(int64_t deadlineTime, bool forceUpdate) {
289 int32_t ret = checkIdleHintSupport();
290 if (ret != NO_ERROR) {
291 return ret;
292 }
293
294 bool enableIdleHint =
295 (deadlineTime < systemTime(SYSTEM_TIME_MONOTONIC) && CC_LIKELY(deadlineTime > 0));
296 ATRACE_INT("HWCIdleHintTimer:", enableIdleHint);
297
298 if (mIdleHintIsEnabled != enableIdleHint || forceUpdate) {
299 ret = sendPowerHalExtHint("DISPLAY_IDLE", enableIdleHint);
300 if (ret == NO_ERROR) {
301 mIdleHintIsEnabled = enableIdleHint;
302 }
303 }
304 return ret;
305 }
306
forceUpdateHints(void)307 void ExynosDisplay::PowerHalHintWorker::forceUpdateHints(void) {
308 Lock();
309 mPrevRefreshRate = 0;
310 mNeedUpdateRefreshRateHint = true;
311 if (mIdleHintSupportIsChecked && mIdleHintIsSupported) {
312 mForceUpdateIdleHint = true;
313 }
314
315 Unlock();
316
317 Signal();
318 }
319
signalRefreshRate(hwc2_power_mode_t powerMode,uint32_t vsyncPeriod)320 void ExynosDisplay::PowerHalHintWorker::signalRefreshRate(hwc2_power_mode_t powerMode,
321 uint32_t vsyncPeriod) {
322 Lock();
323 mPowerModeState = powerMode;
324 mVsyncPeriod = vsyncPeriod;
325 mNeedUpdateRefreshRateHint = true;
326 Unlock();
327
328 Signal();
329 }
330
signalIdle()331 void ExynosDisplay::PowerHalHintWorker::signalIdle() {
332 ATRACE_CALL();
333
334 Lock();
335 if (mIdleHintSupportIsChecked && !mIdleHintIsSupported) {
336 Unlock();
337 return;
338 }
339
340 mIdleHintDeadlineTime = systemTime(SYSTEM_TIME_MONOTONIC) + nsecsIdleHintTimeout;
341 Unlock();
342
343 Signal();
344 }
345
needUpdateIdleHintLocked(int64_t & timeout)346 bool ExynosDisplay::PowerHalHintWorker::needUpdateIdleHintLocked(int64_t &timeout) {
347 if (!mIdleHintIsSupported) {
348 return false;
349 }
350
351 int64_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
352 bool shouldEnableIdleHint =
353 (mIdleHintDeadlineTime < currentTime) && CC_LIKELY(mIdleHintDeadlineTime > 0);
354 if (mIdleHintIsEnabled != shouldEnableIdleHint || mForceUpdateIdleHint) {
355 return true;
356 }
357
358 timeout = mIdleHintDeadlineTime - currentTime;
359 return false;
360 }
361
Routine()362 void ExynosDisplay::PowerHalHintWorker::Routine() {
363 Lock();
364 int ret = 0;
365 int64_t timeout = -1;
366 if (!mNeedUpdateRefreshRateHint && !needUpdateIdleHintLocked(timeout)) {
367 ret = WaitForSignalOrExitLocked(timeout);
368 }
369
370 if (ret == -EINTR) {
371 Unlock();
372 return;
373 }
374
375 bool needUpdateRefreshRateHint = mNeedUpdateRefreshRateHint;
376 int64_t deadlineTime = mIdleHintDeadlineTime;
377 hwc2_power_mode_t powerMode = mPowerModeState;
378 uint32_t vsyncPeriod = mVsyncPeriod;
379
380 /*
381 * Clear the flags here instead of clearing them after calling the hint
382 * update functions. The flags may be set by signals after Unlock() and
383 * before the hint update functions are done. Thus we may miss the newest
384 * hints if we clear the flags after the hint update functions work without
385 * errors.
386 */
387 mNeedUpdateRefreshRateHint = false;
388
389 bool forceUpdateIdleHint = mForceUpdateIdleHint;
390 mForceUpdateIdleHint = false;
391 Unlock();
392
393 updateIdleHint(deadlineTime, forceUpdateIdleHint);
394
395 if (needUpdateRefreshRateHint) {
396 int32_t rc = updateRefreshRateHintInternal(powerMode, vsyncPeriod);
397 if (rc != NO_ERROR && rc != -EOPNOTSUPP) {
398 Lock();
399 if (mPowerModeState == HWC2_POWER_MODE_ON) {
400 /* Set the flag to trigger update again for next loop */
401 mNeedUpdateRefreshRateHint = true;
402 }
403 Unlock();
404 }
405 }
406 }
407
compare(ExynosLayer * const * lhs,ExynosLayer * const * rhs)408 int ExynosSortedLayer::compare(ExynosLayer * const *lhs, ExynosLayer *const *rhs)
409 {
410 ExynosLayer *left = *((ExynosLayer**)(lhs));
411 ExynosLayer *right = *((ExynosLayer**)(rhs));
412 return left->mZOrder > right->mZOrder;
413 }
414
remove(const ExynosLayer * item)415 ssize_t ExynosSortedLayer::remove(const ExynosLayer *item)
416 {
417 for (size_t i = 0; i < size(); i++)
418 {
419 if (array()[i] == item)
420 {
421 removeAt(i);
422 return i;
423 }
424 }
425 return -1;
426 }
427
vector_sort()428 status_t ExynosSortedLayer::vector_sort()
429 {
430 return sort(compare);
431 }
432
ExynosLowFpsLayerInfo()433 ExynosLowFpsLayerInfo::ExynosLowFpsLayerInfo()
434 : mHasLowFpsLayer(false),
435 mFirstIndex(-1),
436 mLastIndex(-1)
437 {
438 }
439
initializeInfos()440 void ExynosLowFpsLayerInfo::initializeInfos()
441 {
442 mHasLowFpsLayer = false;
443 mFirstIndex = -1;
444 mLastIndex = -1;
445 }
446
addLowFpsLayer(uint32_t layerIndex)447 int32_t ExynosLowFpsLayerInfo::addLowFpsLayer(uint32_t layerIndex)
448 {
449 if (mHasLowFpsLayer == false) {
450 mFirstIndex = layerIndex;
451 mLastIndex = layerIndex;
452 mHasLowFpsLayer = true;
453 } else {
454 mFirstIndex = min(mFirstIndex, (int32_t)layerIndex);
455 mLastIndex = max(mLastIndex, (int32_t)layerIndex);
456 }
457 return NO_ERROR;
458 }
459
ExynosCompositionInfo(uint32_t type)460 ExynosCompositionInfo::ExynosCompositionInfo(uint32_t type)
461 : ExynosMPPSource(MPP_SOURCE_COMPOSITION_TARGET, this),
462 mType(type),
463 mHasCompositionLayer(false),
464 mFirstIndex(-1),
465 mLastIndex(-1),
466 mTargetBuffer(NULL),
467 mDataSpace(HAL_DATASPACE_UNKNOWN),
468 mAcquireFence(-1),
469 mReleaseFence(-1),
470 mEnableSkipStatic(false),
471 mSkipStaticInitFlag(false),
472 mSkipFlag(false),
473 mWindowIndex(-1)
474 {
475 /* If AFBC compression of mTargetBuffer is changed, */
476 /* mCompressed should be set properly before resource assigning */
477
478 char value[256];
479 int afbc_prop;
480 property_get("ro.vendor.ddk.set.afbc", value, "0");
481 afbc_prop = atoi(value);
482
483 if (afbc_prop == 0)
484 mCompressed = false;
485 else
486 mCompressed = true;
487
488 memset(&mSkipSrcInfo, 0, sizeof(mSkipSrcInfo));
489 for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
490 mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
491 mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
492 mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
493 mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
494 }
495
496 if(type == COMPOSITION_CLIENT)
497 mEnableSkipStatic = true;
498
499 memset(&mLastWinConfigData, 0x0, sizeof(mLastWinConfigData));
500 mLastWinConfigData.acq_fence = -1;
501 mLastWinConfigData.rel_fence = -1;
502 }
503
initializeInfos(ExynosDisplay * display)504 void ExynosCompositionInfo::initializeInfos(ExynosDisplay *display)
505 {
506 mHasCompositionLayer = false;
507 mFirstIndex = -1;
508 mLastIndex = -1;
509 if (mType != COMPOSITION_CLIENT) {
510 mTargetBuffer = NULL;
511 mDataSpace = HAL_DATASPACE_UNKNOWN;
512 if (mAcquireFence >= 0) {
513 ALOGD("ExynosCompositionInfo(%d):: mAcquire is not initialized(%d)", mType, mAcquireFence);
514 if (display != NULL)
515 fence_close(mAcquireFence, display, FENCE_TYPE_UNDEFINED, FENCE_IP_UNDEFINED);
516 }
517 mAcquireFence = -1;
518 }
519 if (mReleaseFence >= 0) {
520 ALOGD("ExynosCompositionInfo(%d):: mReleaseFence is not initialized(%d)", mType, mReleaseFence);
521 if (display!= NULL)
522 fence_close(mReleaseFence, display, FENCE_TYPE_UNDEFINED, FENCE_IP_UNDEFINED);
523 }
524 mReleaseFence = -1;
525 mWindowIndex = -1;
526 mOtfMPP = NULL;
527 mM2mMPP = NULL;
528 if ((display != NULL) &&
529 (display->mType == HWC_DISPLAY_VIRTUAL) &&
530 (mType == COMPOSITION_EXYNOS)) {
531 mM2mMPP = display->mResourceManager->getExynosMPP(MPP_LOGICAL_G2D_COMBO);
532 }
533 }
534
setTargetBuffer(ExynosDisplay * display,buffer_handle_t handle,int32_t acquireFence,android_dataspace dataspace)535 void ExynosCompositionInfo::setTargetBuffer(ExynosDisplay *display, buffer_handle_t handle,
536 int32_t acquireFence, android_dataspace dataspace)
537 {
538 mTargetBuffer = handle;
539 if (mType == COMPOSITION_CLIENT) {
540 if (display != NULL)
541 mAcquireFence = hwcCheckFenceDebug(display, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_FB, acquireFence);
542 } else {
543 if (display != NULL)
544 mAcquireFence = hwcCheckFenceDebug(display, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, acquireFence);
545 }
546 if ((display != NULL) && (mDataSpace != dataspace))
547 display->setGeometryChanged(GEOMETRY_DISPLAY_DATASPACE_CHANGED);
548 mDataSpace = dataspace;
549 }
550
setCompressed(bool compressed)551 void ExynosCompositionInfo::setCompressed(bool compressed)
552 {
553 mCompressed = compressed;
554 }
555
getCompressed()556 bool ExynosCompositionInfo::getCompressed()
557 {
558 return mCompressed;
559 }
560
dump(String8 & result)561 void ExynosCompositionInfo::dump(String8& result)
562 {
563 result.appendFormat("CompositionInfo (%d)\n", mType);
564 result.appendFormat("mHasCompositionLayer(%d)\n", mHasCompositionLayer);
565 if (mHasCompositionLayer) {
566 result.appendFormat("\tfirstIndex: %d, lastIndex: %d, dataSpace: 0x%8x, compressed: %d, windowIndex: %d\n",
567 mFirstIndex, mLastIndex, mDataSpace, mCompressed, mWindowIndex);
568 result.appendFormat("\thandle: %p, acquireFence: %d, releaseFence: %d, skipFlag: %d",
569 mTargetBuffer, mAcquireFence, mReleaseFence, mSkipFlag);
570 if ((mOtfMPP == NULL) && (mM2mMPP == NULL))
571 result.appendFormat("\tresource is not assigned\n");
572 if (mOtfMPP != NULL)
573 result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.string());
574 if (mM2mMPP != NULL)
575 result.appendFormat("\t%s\n", mM2mMPP->mName.string());
576 }
577 if (mTargetBuffer != NULL) {
578 uint64_t internal_format = 0;
579 internal_format = VendorGraphicBufferMeta::get_internal_format(mTargetBuffer);
580 result.appendFormat("\tinternal_format: 0x%" PRIx64 ", afbc: %d\n", internal_format,
581 isAFBCCompressed(mTargetBuffer));
582 }
583 uint32_t assignedSrcNum = 0;
584 if ((mM2mMPP != NULL) &&
585 ((assignedSrcNum = mM2mMPP->mAssignedSources.size()) > 0)) {
586 result.appendFormat("\tAssigned source num: %d\n", assignedSrcNum);
587 result.append("\t");
588 for (uint32_t i = 0; i < assignedSrcNum; i++) {
589 if (mM2mMPP->mAssignedSources[i]->mSourceType == MPP_SOURCE_LAYER) {
590 ExynosLayer* layer = (ExynosLayer*)(mM2mMPP->mAssignedSources[i]);
591 result.appendFormat("[%d]layer_%p ", i, layer->mLayerBuffer);
592 } else {
593 result.appendFormat("[%d]sourceType_%d ", i, mM2mMPP->mAssignedSources[i]->mSourceType);
594 }
595 }
596 result.append("\n");
597 }
598 result.append("\n");
599 }
600
getTypeStr()601 String8 ExynosCompositionInfo::getTypeStr()
602 {
603 switch(mType) {
604 case COMPOSITION_NONE:
605 return String8("COMPOSITION_NONE");
606 case COMPOSITION_CLIENT:
607 return String8("COMPOSITION_CLIENT");
608 case COMPOSITION_EXYNOS:
609 return String8("COMPOSITION_EXYNOS");
610 default:
611 return String8("InvalidType");
612 }
613 }
614
ExynosDisplay(uint32_t index,ExynosDevice * device)615 ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
616 : mDisplayId(HWC_DISPLAY_PRIMARY),
617 mType(HWC_NUM_DISPLAY_TYPES),
618 mIndex(index),
619 mDeconNodeName(""),
620 mXres(1440),
621 mYres(2960),
622 mXdpi(25400),
623 mYdpi(25400),
624 mVsyncPeriod(16666666),
625 mBtsVsyncPeriod(16666666),
626 mDevice(device),
627 mDisplayName(""),
628 mPlugState(false),
629 mHasSingleBuffer(false),
630 mResourceManager(NULL),
631 mClientCompositionInfo(COMPOSITION_CLIENT),
632 mExynosCompositionInfo(COMPOSITION_EXYNOS),
633 mGeometryChanged(0x0),
634 mRenderingState(RENDERING_STATE_NONE),
635 mHWCRenderingState(RENDERING_STATE_NONE),
636 mDisplayBW(0),
637 mDynamicReCompMode(NO_MODE_SWITCH),
638 mDREnable(false),
639 mDRDefault(false),
640 mLastFpsTime(0),
641 mFrameCount(0),
642 mLastFrameCount(0),
643 mErrorFrameCount(0),
644 mUpdateEventCnt(0),
645 mUpdateCallCnt(0),
646 mDefaultDMA(MAX_DECON_DMA_TYPE),
647 mLastRetireFence(-1),
648 mWindowNumUsed(0),
649 mBaseWindowIndex(0),
650 mNumMaxPriorityAllowed(1),
651 mCursorIndex(-1),
652 mColorTransformHint(HAL_COLOR_TRANSFORM_IDENTITY),
653 mMaxLuminance(0),
654 mMaxAverageLuminance(0),
655 mMinLuminance(0),
656 mHWC1LayerList(NULL),
657 /* Support DDI scalser */
658 mOldScalerMode(0),
659 mNewScaledWidth(0),
660 mNewScaledHeight(0),
661 mDeviceXres(0),
662 mDeviceYres(0),
663 mColorMode(HAL_COLOR_MODE_NATIVE),
664 mSkipFrame(false),
665 mBrightnessFd(NULL),
666 mEarlyWakeupFd(NULL),
667 mMaxBrightness(0),
668 mVsyncPeriodChangeConstraints{systemTime(SYSTEM_TIME_MONOTONIC), 0},
669 mVsyncAppliedTimeLine{false, 0, systemTime(SYSTEM_TIME_MONOTONIC)},
670 mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_NONE) {
671 mDisplayControl.enableCompositionCrop = true;
672 mDisplayControl.enableExynosCompositionOptimization = true;
673 mDisplayControl.enableClientCompositionOptimization = true;
674 mDisplayControl.useMaxG2DSrc = false;
675 mDisplayControl.handleLowFpsLayers = false;
676 mDisplayControl.earlyStartMPP = true;
677 mDisplayControl.adjustDisplayFrame = false;
678 mDisplayControl.cursorSupport = false;
679
680 mDisplayConfigs.clear();
681
682 mPowerModeState = HWC2_POWER_MODE_OFF;
683 mVsyncState = HWC2_VSYNC_DISABLE;
684
685 /* TODO : Exception handling here */
686
687 if (device == NULL) {
688 ALOGE("Display creation failed!");
689 return;
690 }
691
692 mResourceManager = device->mResourceManager;
693
694 /* The number of window is same with the number of otfMPP */
695 mMaxWindowNum = mResourceManager->getOtfMPPs().size();
696
697 mDpuData.init(mMaxWindowNum);
698 mLastDpuData.init(mMaxWindowNum);
699 ALOGI("window configs size(%zu)", mDpuData.configs.size());
700
701 mLowFpsLayerInfo.initializeInfos();
702
703 mPowerHalHint.Init();
704
705 mUseDpu = true;
706 mBrightnessState.reset();
707
708 return;
709 }
710
~ExynosDisplay()711 ExynosDisplay::~ExynosDisplay()
712 {
713 }
714
715 /**
716 * Member function for Dynamic AFBC Control solution.
717 */
comparePreferedLayers()718 bool ExynosDisplay::comparePreferedLayers() {
719 return false;
720 }
721
getId()722 int ExynosDisplay::getId() {
723 return mDisplayId;
724 }
725
initDisplay()726 void ExynosDisplay::initDisplay() {
727 mClientCompositionInfo.initializeInfos(this);
728 mClientCompositionInfo.mEnableSkipStatic = true;
729 mClientCompositionInfo.mSkipStaticInitFlag = false;
730 mClientCompositionInfo.mSkipFlag = false;
731 memset(&mClientCompositionInfo.mSkipSrcInfo, 0x0, sizeof(mClientCompositionInfo.mSkipSrcInfo));
732 for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
733 mClientCompositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
734 mClientCompositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
735 mClientCompositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
736 mClientCompositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
737 }
738 memset(&mClientCompositionInfo.mLastWinConfigData, 0x0, sizeof(mClientCompositionInfo.mLastWinConfigData));
739 mClientCompositionInfo.mLastWinConfigData.acq_fence = -1;
740 mClientCompositionInfo.mLastWinConfigData.rel_fence = -1;
741
742 mExynosCompositionInfo.initializeInfos(this);
743 mExynosCompositionInfo.mEnableSkipStatic = false;
744 mExynosCompositionInfo.mSkipStaticInitFlag = false;
745 mExynosCompositionInfo.mSkipFlag = false;
746 memset(&mExynosCompositionInfo.mSkipSrcInfo, 0x0, sizeof(mExynosCompositionInfo.mSkipSrcInfo));
747 for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
748 mExynosCompositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
749 mExynosCompositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
750 mExynosCompositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
751 mExynosCompositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
752 }
753
754 memset(&mExynosCompositionInfo.mLastWinConfigData, 0x0, sizeof(mExynosCompositionInfo.mLastWinConfigData));
755 mExynosCompositionInfo.mLastWinConfigData.acq_fence = -1;
756 mExynosCompositionInfo.mLastWinConfigData.rel_fence = -1;
757
758 mGeometryChanged = 0x0;
759 mRenderingState = RENDERING_STATE_NONE;
760 mDisplayBW = 0;
761 mDynamicReCompMode = NO_MODE_SWITCH;
762 mCursorIndex = -1;
763
764 mDpuData.reset();
765 mLastDpuData.reset();
766
767 if (mDisplayControl.earlyStartMPP == true) {
768 for (size_t i = 0; i < mLayers.size(); i++) {
769 exynos_image outImage;
770 ExynosMPP* m2mMPP = mLayers[i]->mM2mMPP;
771
772 /* Close release fence of dst buffer of last frame */
773 if ((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
774 (m2mMPP != NULL) &&
775 (m2mMPP->mAssignedDisplay == this) &&
776 (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
777 if (m2mMPP->mPhysicalType == MPP_MSC) {
778 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
779 } else if (m2mMPP->mPhysicalType == MPP_G2D) {
780 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
781 } else {
782 DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
783 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
784 }
785 m2mMPP->resetDstReleaseFence();
786 }
787 }
788 }
789 }
790
791 /**
792 * @param outLayer
793 * @return int32_t
794 */
destroyLayer(hwc2_layer_t outLayer)795 int32_t ExynosDisplay::destroyLayer(hwc2_layer_t outLayer) {
796
797 Mutex::Autolock lock(mDRMutex);
798 ExynosLayer *layer = (ExynosLayer *)outLayer;
799
800 if (layer == nullptr) {
801 return HWC2_ERROR_BAD_LAYER;
802 }
803
804 if (mLayers.remove(layer) < 0) {
805 auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), layer);
806 if (it == mIgnoreLayers.end()) {
807 ALOGE("%s:: There is no layer", __func__);
808 } else {
809 mIgnoreLayers.erase(it);
810 }
811 } else {
812 setGeometryChanged(GEOMETRY_DISPLAY_LAYER_REMOVED);
813 }
814
815 mDisplayInterface->destroyLayer(layer);
816
817 delete layer;
818
819 if (mPlugState == false) {
820 DISPLAY_LOGI("%s : destroyLayer is done. But display is already disconnected",
821 __func__);
822 return HWC2_ERROR_BAD_DISPLAY;
823 }
824
825 return HWC2_ERROR_NONE;
826 }
827
828 /**
829 * @return void
830 */
destroyLayers()831 void ExynosDisplay::destroyLayers() {
832 for (uint32_t index = 0; index < mLayers.size();) {
833 ExynosLayer *layer = mLayers[index];
834 mLayers.removeAt(index);
835 delete layer;
836 }
837
838 for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
839 ExynosLayer *layer = *it;
840 it = mIgnoreLayers.erase(it);
841 delete layer;
842 }
843 }
844
checkLayer(hwc2_layer_t addr)845 ExynosLayer *ExynosDisplay::checkLayer(hwc2_layer_t addr) {
846 ExynosLayer *temp = (ExynosLayer *)addr;
847 if (!mLayers.isEmpty()) {
848 for (size_t i = 0; i < mLayers.size(); i++) {
849 if (mLayers[i] == temp)
850 return mLayers[i];
851 }
852 }
853
854 if (mIgnoreLayers.size()) {
855 auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), temp);
856 return (it == mIgnoreLayers.end()) ? NULL : *it;
857 }
858
859 ALOGE("HWC2 : %s : %d, wrong layer request!", __func__, __LINE__);
860 return NULL;
861 }
862
checkIgnoreLayers()863 void ExynosDisplay::checkIgnoreLayers() {
864 for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
865 ExynosLayer *layer = *it;
866 if ((layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) == 0) {
867 mLayers.push_back(layer);
868 it = mIgnoreLayers.erase(it);
869 } else {
870 it++;
871 }
872 }
873
874 for (uint32_t index = 0; index < mLayers.size();) {
875 ExynosLayer *layer = mLayers[index];
876 if (layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) {
877 layer->resetValidateData();
878 layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
879 /*
880 * Directly close without counting down
881 * because it was not counted by validate
882 */
883 if (layer->mAcquireFence > 0) {
884 close(layer->mAcquireFence);
885 }
886 layer->mAcquireFence = -1;
887
888 layer->mReleaseFence = -1;
889 mIgnoreLayers.push_back(layer);
890 mLayers.removeAt(index);
891 } else {
892 index++;
893 }
894 }
895 }
896
897 /**
898 * @return void
899 */
doPreProcessing()900 void ExynosDisplay::doPreProcessing() {
901 /* Low persistence setting */
902 int ret = 0;
903 bool hasSingleBuffer = false;
904 bool hasClientLayer = false;
905
906 for (size_t i=0; i < mLayers.size(); i++) {
907 buffer_handle_t handle = mLayers[i]->mLayerBuffer;
908 VendorGraphicBufferMeta gmeta(handle);
909 if (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CLIENT) {
910 hasClientLayer = true;
911 }
912
913 exynos_image srcImg;
914 exynos_image dstImg;
915 mLayers[i]->setSrcExynosImage(&srcImg);
916 mLayers[i]->setDstExynosImage(&dstImg);
917 mLayers[i]->setExynosImage(srcImg, dstImg);
918 }
919
920 /*
921 * Disable skip static layer feature if there is the layer that's
922 * mCompositionType is HWC2_COMPOSITION_CLIENT
923 * HWC should not change compositionType if it is HWC2_COMPOSITION_CLIENT
924 */
925 if (mType != HWC_DISPLAY_VIRTUAL)
926 mClientCompositionInfo.mEnableSkipStatic = (!hasClientLayer && !hasSingleBuffer);
927
928 if (mHasSingleBuffer != hasSingleBuffer) {
929 if ((ret = mDisplayInterface->disableSelfRefresh(uint32_t(hasSingleBuffer))) < 0)
930 DISPLAY_LOGE("ioctl S3CFB_LOW_PERSISTENCE failed: %s ret(%d)", strerror(errno), ret);
931
932 mDisplayControl.skipM2mProcessing = !hasSingleBuffer;
933 mHasSingleBuffer = hasSingleBuffer;
934 setGeometryChanged(GEOMETRY_DISPLAY_SINGLEBUF_CHANGED);
935 }
936
937 if ((exynosHWCControl.displayMode < DISPLAY_MODE_NUM) &&
938 (mDevice->mDisplayMode != exynosHWCControl.displayMode))
939 setGeometryChanged(GEOMETRY_DEVICE_DISP_MODE_CHAGED);
940
941 if ((ret = mResourceManager->checkScenario(this)) != NO_ERROR)
942 DISPLAY_LOGE("checkScenario error ret(%d)", ret);
943
944 if (exynosHWCControl.skipResourceAssign == 0) {
945 /* Set any flag to mGeometryChanged */
946 setGeometryChanged(GEOMETRY_DEVICE_SCENARIO_CHANGED);
947 }
948 #ifndef HWC_SKIP_VALIDATE
949 if (mDevice->checkNonInternalConnection()) {
950 /* Set any flag to mGeometryChanged */
951 mDevice->mGeometryChanged = 0x10;
952 }
953 #endif
954
955 return;
956 }
957
958 /**
959 * @return int
960 */
checkLayerFps()961 int ExynosDisplay::checkLayerFps() {
962 mLowFpsLayerInfo.initializeInfos();
963
964 if (mDisplayControl.handleLowFpsLayers == false)
965 return NO_ERROR;
966
967 for (size_t i=0; i < mLayers.size(); i++) {
968 if ((mLayers[i]->mOverlayPriority < ePriorityHigh) &&
969 (mLayers[i]->getFps() < LOW_FPS_THRESHOLD)) {
970 mLowFpsLayerInfo.addLowFpsLayer(i);
971 } else {
972 if (mLowFpsLayerInfo.mHasLowFpsLayer == true)
973 break;
974 else
975 continue;
976 }
977 }
978 /* There is only one low fps layer, Overlay is better in this case */
979 if ((mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
980 (mLowFpsLayerInfo.mFirstIndex == mLowFpsLayerInfo.mLastIndex))
981 mLowFpsLayerInfo.initializeInfos();
982
983 return NO_ERROR;
984 }
985
986 /**
987 * @return int
988 */
checkDynamicReCompMode()989 int ExynosDisplay::checkDynamicReCompMode() {
990 unsigned int updateFps = 0;
991 unsigned int lcd_size = mXres * mYres;
992 uint64_t TimeStampDiff;
993 uint64_t w = 0, h = 0, incomingPixels = 0;
994 uint64_t maxFps = 0, layerFps = 0;
995
996 Mutex::Autolock lock(mDRMutex);
997
998 if (!exynosHWCControl.useDynamicRecomp) {
999 mLastModeSwitchTimeStamp = 0;
1000 mDynamicReCompMode = NO_MODE_SWITCH;
1001 return 0;
1002 }
1003
1004 /* initialize the Timestamps */
1005 if (!mLastModeSwitchTimeStamp) {
1006 mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1007 mDynamicReCompMode = NO_MODE_SWITCH;
1008 return 0;
1009 }
1010
1011 /* If video layer is there, skip the mode switch */
1012 for (size_t i = 0; i < mLayers.size(); i++) {
1013 if ((mLayers[i]->mOverlayPriority >= ePriorityHigh) ||
1014 mLayers[i]->mPreprocessedInfo.preProcessed) {
1015 if (mDynamicReCompMode != DEVICE_2_CLIENT) {
1016 return 0;
1017 } else {
1018 mDynamicReCompMode = CLIENT_2_DEVICE;
1019 mUpdateCallCnt = 0;
1020 mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1021 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by video layer");
1022 setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
1023 return CLIENT_2_DEVICE;
1024 }
1025 }
1026 }
1027
1028 for (size_t i = 0; i < mLayers.size(); i++) {
1029 w = WIDTH(mLayers[i]->mPreprocessedInfo.displayFrame);
1030 h = HEIGHT(mLayers[i]->mPreprocessedInfo.displayFrame);
1031 incomingPixels += w * h;
1032 }
1033
1034 /* Mode Switch is not required if total pixels are not more than the threshold */
1035 if (incomingPixels <= lcd_size) {
1036 if (mDynamicReCompMode != DEVICE_2_CLIENT) {
1037 return 0;
1038 } else {
1039 mDynamicReCompMode = CLIENT_2_DEVICE;
1040 mUpdateCallCnt = 0;
1041 mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1042 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by BW check");
1043 setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
1044 return CLIENT_2_DEVICE;
1045 }
1046 }
1047
1048 /*
1049 * There will be at least one composition call per one minute (because of time update)
1050 * To minimize the analysis overhead, just analyze it once in a second
1051 */
1052 TimeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mLastModeSwitchTimeStamp;
1053
1054 /*
1055 * previous CompModeSwitch was CLIENT_2_DEVICE: check fps every 250ms from mLastModeSwitchTimeStamp
1056 * previous CompModeSwitch was DEVICE_2_CLIENT: check immediately
1057 */
1058 if ((mDynamicReCompMode != DEVICE_2_CLIENT) && (TimeStampDiff < (VSYNC_INTERVAL * 15)))
1059 return 0;
1060
1061 mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1062 if ((mUpdateEventCnt != 1) &&
1063 (mDynamicReCompMode == DEVICE_2_CLIENT) && (mUpdateCallCnt == 1)) {
1064 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] first frame after DEVICE_2_CLIENT");
1065 updateFps = HWC_FPS_TH;
1066 } else {
1067 for (uint32_t i = 0; i < mLayers.size(); i++) {
1068 layerFps = mLayers[i]->getFps();
1069 if (maxFps < layerFps)
1070 maxFps = layerFps;
1071 }
1072 updateFps = maxFps;
1073 }
1074 mUpdateCallCnt = 0;
1075
1076 /*
1077 * FPS estimation.
1078 * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES
1079 */
1080 if (updateFps < HWC_FPS_TH) {
1081 if (mDynamicReCompMode != DEVICE_2_CLIENT) {
1082 mDynamicReCompMode = DEVICE_2_CLIENT;
1083 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] DEVICE_2_CLIENT by low FPS(%d)", updateFps);
1084 setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
1085 return DEVICE_2_CLIENT;
1086 } else {
1087 return 0;
1088 }
1089 } else {
1090 if (mDynamicReCompMode == DEVICE_2_CLIENT) {
1091 mDynamicReCompMode = CLIENT_2_DEVICE;
1092 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] CLIENT_2_HWC by high FPS(%d)", updateFps);
1093 setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
1094 return CLIENT_2_DEVICE;
1095 } else {
1096 return 0;
1097 }
1098 }
1099
1100 return 0;
1101 }
1102
1103 /**
1104 * @return int
1105 */
handleDynamicReCompMode()1106 int ExynosDisplay::handleDynamicReCompMode() {
1107 return 0;
1108 }
1109
1110 /**
1111 * @param changedBit
1112 * @return int
1113 */
setGeometryChanged(uint64_t changedBit)1114 void ExynosDisplay::setGeometryChanged(uint64_t changedBit) {
1115 mGeometryChanged |= changedBit;
1116 mDevice->setGeometryChanged(changedBit);
1117 }
1118
clearGeometryChanged()1119 void ExynosDisplay::clearGeometryChanged()
1120 {
1121 mGeometryChanged = 0;
1122 for (size_t i=0; i < mLayers.size(); i++) {
1123 mLayers[i]->clearGeometryChanged();
1124 }
1125 }
1126
handleStaticLayers(ExynosCompositionInfo & compositionInfo)1127 int ExynosDisplay::handleStaticLayers(ExynosCompositionInfo& compositionInfo)
1128 {
1129 if (compositionInfo.mType != COMPOSITION_CLIENT)
1130 return -EINVAL;
1131
1132 if (mType == HWC_DISPLAY_VIRTUAL)
1133 return NO_ERROR;
1134
1135 if (compositionInfo.mHasCompositionLayer == false) {
1136 DISPLAY_LOGD(eDebugSkipStaicLayer, "there is no client composition");
1137 return NO_ERROR;
1138 }
1139 if ((compositionInfo.mWindowIndex < 0) ||
1140 (compositionInfo.mWindowIndex >= (int32_t)mDpuData.configs.size()))
1141 {
1142 DISPLAY_LOGE("invalid mWindowIndex(%d)", compositionInfo.mWindowIndex);
1143 return -EINVAL;
1144 }
1145
1146 exynos_win_config_data &config = mDpuData.configs[compositionInfo.mWindowIndex];
1147
1148 /* Store configuration of client target configuration */
1149 if (compositionInfo.mSkipFlag == false) {
1150 compositionInfo.mLastWinConfigData = config;
1151 DISPLAY_LOGD(eDebugSkipStaicLayer, "config[%d] is stored",
1152 compositionInfo.mWindowIndex);
1153 } else {
1154 for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1155 if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) &&
1156 (mLayers[i]->mAcquireFence >= 0))
1157 fence_close(mLayers[i]->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1158 mLayers[i]->mAcquireFence = -1;
1159 mLayers[i]->mReleaseFence = -1;
1160 }
1161
1162 if (compositionInfo.mTargetBuffer == NULL) {
1163 fence_close(config.acq_fence, this,
1164 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1165
1166 config = compositionInfo.mLastWinConfigData;
1167 /* Assigned otfMPP for client target can be changed */
1168 config.assignedMPP = compositionInfo.mOtfMPP;
1169 /* acq_fence was closed by DPU driver in the previous frame */
1170 config.acq_fence = -1;
1171 } else {
1172 /* Check target buffer is same with previous frame */
1173 if (!std::equal(config.fd_idma, config.fd_idma+3, compositionInfo.mLastWinConfigData.fd_idma)) {
1174 DISPLAY_LOGE("Current config [%d][%d, %d, %d]",
1175 compositionInfo.mWindowIndex,
1176 config.fd_idma[0], config.fd_idma[1], config.fd_idma[2]);
1177 DISPLAY_LOGE("============================= dump last win configs ===================================");
1178 for (size_t i = 0; i <= mLastDpuData.configs.size(); i++) {
1179 android::String8 result;
1180 result.appendFormat("config[%zu]\n", i);
1181 dumpConfig(result, mLastDpuData.configs[i]);
1182 DISPLAY_LOGE("%s", result.string());
1183 }
1184 DISPLAY_LOGE("compositionInfo.mLastWinConfigData config [%d, %d, %d]",
1185 compositionInfo.mLastWinConfigData.fd_idma[0],
1186 compositionInfo.mLastWinConfigData.fd_idma[1],
1187 compositionInfo.mLastWinConfigData.fd_idma[2]);
1188 return -EINVAL;
1189 }
1190 }
1191
1192 DISPLAY_LOGD(eDebugSkipStaicLayer, "skipStaticLayer config[%d]", compositionInfo.mWindowIndex);
1193 dumpConfig(config);
1194 }
1195
1196 return NO_ERROR;
1197 }
1198
skipStaticLayerChanged(ExynosCompositionInfo & compositionInfo)1199 bool ExynosDisplay::skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo)
1200 {
1201 if ((int)compositionInfo.mSkipSrcInfo.srcNum !=
1202 (compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1)) {
1203 DISPLAY_LOGD(eDebugSkipStaicLayer, "Client composition number is changed (%d -> %d)",
1204 compositionInfo.mSkipSrcInfo.srcNum,
1205 compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1);
1206 return true;
1207 }
1208
1209 bool isChanged = false;
1210 for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1211 ExynosLayer *layer = mLayers[i];
1212 size_t index = i - compositionInfo.mFirstIndex;
1213 if ((layer->mLayerBuffer == NULL) ||
1214 (compositionInfo.mSkipSrcInfo.srcInfo[index].bufferHandle != layer->mLayerBuffer))
1215 {
1216 isChanged = true;
1217 DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] handle is changed"\
1218 " handle(%p -> %p), layerFlag(0x%8x)",
1219 i, compositionInfo.mSkipSrcInfo.srcInfo[index].bufferHandle,
1220 layer->mLayerBuffer, layer->mLayerFlag);
1221 break;
1222 } else if ((compositionInfo.mSkipSrcInfo.srcInfo[index].x != layer->mSrcImg.x) ||
1223 (compositionInfo.mSkipSrcInfo.srcInfo[index].y != layer->mSrcImg.y) ||
1224 (compositionInfo.mSkipSrcInfo.srcInfo[index].w != layer->mSrcImg.w) ||
1225 (compositionInfo.mSkipSrcInfo.srcInfo[index].h != layer->mSrcImg.h) ||
1226 (compositionInfo.mSkipSrcInfo.srcInfo[index].dataSpace != layer->mSrcImg.dataSpace) ||
1227 (compositionInfo.mSkipSrcInfo.srcInfo[index].blending != layer->mSrcImg.blending) ||
1228 (compositionInfo.mSkipSrcInfo.srcInfo[index].transform != layer->mSrcImg.transform) ||
1229 (compositionInfo.mSkipSrcInfo.srcInfo[index].planeAlpha != layer->mSrcImg.planeAlpha))
1230 {
1231 isChanged = true;
1232 DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] source info is changed, "\
1233 "x(%d->%d), y(%d->%d), w(%d->%d), h(%d->%d), dataSpace(%d->%d), "\
1234 "blending(%d->%d), transform(%d->%d), planeAlpha(%3.1f->%3.1f)", i,
1235 compositionInfo.mSkipSrcInfo.srcInfo[index].x, layer->mSrcImg.x,
1236 compositionInfo.mSkipSrcInfo.srcInfo[index].y, layer->mSrcImg.y,
1237 compositionInfo.mSkipSrcInfo.srcInfo[index].w, layer->mSrcImg.w,
1238 compositionInfo.mSkipSrcInfo.srcInfo[index].h, layer->mSrcImg.h,
1239 compositionInfo.mSkipSrcInfo.srcInfo[index].dataSpace, layer->mSrcImg.dataSpace,
1240 compositionInfo.mSkipSrcInfo.srcInfo[index].blending, layer->mSrcImg.blending,
1241 compositionInfo.mSkipSrcInfo.srcInfo[index].transform, layer->mSrcImg.transform,
1242 compositionInfo.mSkipSrcInfo.srcInfo[index].planeAlpha, layer->mSrcImg.planeAlpha);
1243 break;
1244 } else if ((compositionInfo.mSkipSrcInfo.dstInfo[index].x != layer->mDstImg.x) ||
1245 (compositionInfo.mSkipSrcInfo.dstInfo[index].y != layer->mDstImg.y) ||
1246 (compositionInfo.mSkipSrcInfo.dstInfo[index].w != layer->mDstImg.w) ||
1247 (compositionInfo.mSkipSrcInfo.dstInfo[index].h != layer->mDstImg.h))
1248 {
1249 isChanged = true;
1250 DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] dst info is changed, "\
1251 "x(%d->%d), y(%d->%d), w(%d->%d), h(%d->%d)", i,
1252 compositionInfo.mSkipSrcInfo.dstInfo[index].x, layer->mDstImg.x,
1253 compositionInfo.mSkipSrcInfo.dstInfo[index].y, layer->mDstImg.y,
1254 compositionInfo.mSkipSrcInfo.dstInfo[index].w, layer->mDstImg.w,
1255 compositionInfo.mSkipSrcInfo.dstInfo[index].h, layer->mDstImg.h);
1256 break;
1257 }
1258 }
1259 return isChanged;
1260 }
1261
1262 /**
1263 * @param compositionType
1264 * @return int
1265 */
skipStaticLayers(ExynosCompositionInfo & compositionInfo)1266 int ExynosDisplay::skipStaticLayers(ExynosCompositionInfo& compositionInfo)
1267 {
1268 compositionInfo.mSkipFlag = false;
1269
1270 if (compositionInfo.mType != COMPOSITION_CLIENT)
1271 return -EINVAL;
1272
1273 if ((exynosHWCControl.skipStaticLayers == 0) ||
1274 (compositionInfo.mEnableSkipStatic == false)) {
1275 DISPLAY_LOGD(eDebugSkipStaicLayer, "skipStaticLayers(%d), mEnableSkipStatic(%d)",
1276 exynosHWCControl.skipStaticLayers, compositionInfo.mEnableSkipStatic);
1277 compositionInfo.mSkipStaticInitFlag = false;
1278 return NO_ERROR;
1279 }
1280
1281 if ((compositionInfo.mHasCompositionLayer == false) ||
1282 (compositionInfo.mFirstIndex < 0) ||
1283 (compositionInfo.mLastIndex < 0) ||
1284 ((compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1) > NUM_SKIP_STATIC_LAYER)) {
1285 DISPLAY_LOGD(eDebugSkipStaicLayer, "mHasCompositionLayer(%d), mFirstIndex(%d), mLastIndex(%d)",
1286 compositionInfo.mHasCompositionLayer,
1287 compositionInfo.mFirstIndex, compositionInfo.mLastIndex);
1288 compositionInfo.mSkipStaticInitFlag = false;
1289 return NO_ERROR;
1290 }
1291
1292 if (compositionInfo.mSkipStaticInitFlag) {
1293 bool isChanged = skipStaticLayerChanged(compositionInfo);
1294 if (isChanged == true) {
1295 compositionInfo.mSkipStaticInitFlag = false;
1296 return NO_ERROR;
1297 }
1298
1299 for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1300 ExynosLayer *layer = mLayers[i];
1301 if (layer->mValidateCompositionType == COMPOSITION_CLIENT) {
1302 layer->mOverlayInfo |= eSkipStaticLayer;
1303 } else {
1304 compositionInfo.mSkipStaticInitFlag = false;
1305 if (layer->mOverlayPriority < ePriorityHigh) {
1306 DISPLAY_LOGE("[%zu] Invalid layer type: %d",
1307 i, layer->mValidateCompositionType);
1308 return -EINVAL;
1309 } else {
1310 return NO_ERROR;
1311 }
1312 }
1313 }
1314
1315 compositionInfo.mSkipFlag = true;
1316 DISPLAY_LOGD(eDebugSkipStaicLayer, "SkipStaicLayer is enabled");
1317 return NO_ERROR;
1318 }
1319
1320 compositionInfo.mSkipStaticInitFlag = true;
1321 memset(&compositionInfo.mSkipSrcInfo, 0, sizeof(compositionInfo.mSkipSrcInfo));
1322 for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
1323 compositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
1324 compositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
1325 compositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
1326 compositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
1327 }
1328
1329 for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1330 ExynosLayer *layer = mLayers[i];
1331 size_t index = i - compositionInfo.mFirstIndex;
1332 compositionInfo.mSkipSrcInfo.srcInfo[index] = layer->mSrcImg;
1333 compositionInfo.mSkipSrcInfo.dstInfo[index] = layer->mDstImg;
1334 DISPLAY_LOGD(eDebugSkipStaicLayer, "mSkipSrcInfo.srcInfo[%zu] is initialized, %p",
1335 index, layer->mSrcImg.bufferHandle);
1336 }
1337 compositionInfo.mSkipSrcInfo.srcNum = (compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1);
1338 return NO_ERROR;
1339 }
1340
skipSignalIdleForVideoLayer(void)1341 bool ExynosDisplay::skipSignalIdleForVideoLayer(void) {
1342 /* ignore the frame update in case we have video layer but ui layer is not updated */
1343 for (size_t i = 0; i < mLayers.size(); i++) {
1344 if (!mLayers[i]->isLayerFormatYuv() &&
1345 mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) {
1346 return false;
1347 }
1348 }
1349 return true;
1350 }
1351
1352 /**
1353 * @return int
1354 */
doPostProcessing()1355 int ExynosDisplay::doPostProcessing() {
1356
1357 for (size_t i=0; i < mLayers.size(); i++) {
1358 /* Layer handle back-up */
1359 mLayers[i]->mLastLayerBuffer = mLayers[i]->mLayerBuffer;
1360 }
1361 clearGeometryChanged();
1362
1363 return 0;
1364 }
1365
validateExynosCompositionLayer()1366 bool ExynosDisplay::validateExynosCompositionLayer()
1367 {
1368 bool isValid = true;
1369 ExynosMPP *m2mMpp = mExynosCompositionInfo.mM2mMPP;
1370
1371 int sourceSize = (int)m2mMpp->mAssignedSources.size();
1372 if ((mExynosCompositionInfo.mFirstIndex >= 0) &&
1373 (mExynosCompositionInfo.mLastIndex >= 0)) {
1374 sourceSize = mExynosCompositionInfo.mLastIndex - mExynosCompositionInfo.mFirstIndex + 1;
1375
1376 if (!mUseDpu && mClientCompositionInfo.mHasCompositionLayer)
1377 sourceSize++;
1378 }
1379
1380 if (m2mMpp->mAssignedSources.size() == 0) {
1381 DISPLAY_LOGE("No source images");
1382 isValid = false;
1383 } else if (mUseDpu && (((mExynosCompositionInfo.mFirstIndex < 0) ||
1384 (mExynosCompositionInfo.mLastIndex < 0)) ||
1385 (sourceSize != (int)m2mMpp->mAssignedSources.size()))) {
1386 DISPLAY_LOGE("Invalid index (%d, %d), size(%zu), sourceSize(%d)",
1387 mExynosCompositionInfo.mFirstIndex,
1388 mExynosCompositionInfo.mLastIndex,
1389 m2mMpp->mAssignedSources.size(),
1390 sourceSize);
1391 isValid = false;
1392 }
1393 if (isValid == false) {
1394 for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1395 /* break when only framebuffer target is assigned on ExynosCompositor */
1396 if (i == -1)
1397 break;
1398
1399 if (mLayers[i]->mAcquireFence >= 0)
1400 fence_close(mLayers[i]->mAcquireFence, this,
1401 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1402 mLayers[i]->mAcquireFence = -1;
1403 }
1404 mExynosCompositionInfo.mM2mMPP->requestHWStateChange(MPP_HW_STATE_IDLE);
1405 }
1406 return isValid;
1407 }
1408
1409 /**
1410 * @return int
1411 */
doExynosComposition()1412 int ExynosDisplay::doExynosComposition() {
1413 int ret = NO_ERROR;
1414 exynos_image src_img;
1415 exynos_image dst_img;
1416
1417 if (mExynosCompositionInfo.mHasCompositionLayer) {
1418 if (mExynosCompositionInfo.mM2mMPP == NULL) {
1419 DISPLAY_LOGE("mExynosCompositionInfo.mM2mMPP is NULL");
1420 return -EINVAL;
1421 }
1422 mExynosCompositionInfo.mM2mMPP->requestHWStateChange(MPP_HW_STATE_RUNNING);
1423 /* mAcquireFence is updated, Update image info */
1424 for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1425 /* break when only framebuffer target is assigned on ExynosCompositor */
1426 if (i == -1)
1427 break;
1428
1429 struct exynos_image srcImg, dstImg;
1430 mLayers[i]->setSrcExynosImage(&srcImg);
1431 dumpExynosImage(eDebugFence, srcImg);
1432 mLayers[i]->setDstExynosImage(&dstImg);
1433 mLayers[i]->setExynosImage(srcImg, dstImg);
1434 }
1435
1436 /* For debugging */
1437 if (validateExynosCompositionLayer() == false) {
1438 DISPLAY_LOGE("mExynosCompositionInfo is not valid");
1439 return -EINVAL;
1440 }
1441
1442 if ((ret = mExynosCompositionInfo.mM2mMPP->doPostProcessing(mExynosCompositionInfo.mSrcImg,
1443 mExynosCompositionInfo.mDstImg)) != NO_ERROR) {
1444 DISPLAY_LOGE("exynosComposition doPostProcessing fail ret(%d)", ret);
1445 return ret;
1446 }
1447
1448 for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1449 /* break when only framebuffer target is assigned on ExynosCompositor */
1450 if (i == -1)
1451 break;
1452 /* This should be closed by resource lib (libmpp or libacryl) */
1453 mLayers[i]->mAcquireFence = -1;
1454 }
1455
1456 exynos_image outImage;
1457 if ((ret = mExynosCompositionInfo.mM2mMPP->getDstImageInfo(&outImage)) != NO_ERROR) {
1458 DISPLAY_LOGE("exynosComposition getDstImageInfo fail ret(%d)", ret);
1459 return ret;
1460 }
1461
1462 android_dataspace dataspace = HAL_DATASPACE_UNKNOWN;
1463 if (mColorMode != HAL_COLOR_MODE_NATIVE)
1464 dataspace = colorModeToDataspace(mColorMode);
1465 mExynosCompositionInfo.setTargetBuffer(this, outImage.bufferHandle,
1466 outImage.releaseFenceFd, dataspace);
1467 /*
1468 * buffer handle, dataspace can be changed by setTargetBuffer()
1469 * ExynosImage should be set again according to changed handle and dataspace
1470 */
1471 setCompositionTargetExynosImage(COMPOSITION_EXYNOS, &src_img, &dst_img);
1472 mExynosCompositionInfo.setExynosImage(src_img, dst_img);
1473
1474 DISPLAY_LOGD(eDebugFence, "mExynosCompositionInfo acquireFencefd(%d)",
1475 mExynosCompositionInfo.mAcquireFence);
1476 // Test..
1477 // setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, "G2D_DST_ACQ", FENCE_FROM);
1478
1479 if ((ret = mExynosCompositionInfo.mM2mMPP->resetDstReleaseFence()) != NO_ERROR)
1480 {
1481 DISPLAY_LOGE("exynosComposition resetDstReleaseFence fail ret(%d)", ret);
1482 return ret;
1483 }
1484 }
1485
1486 return ret;
1487 }
1488
getHDRException(ExynosLayer * __unused layer)1489 bool ExynosDisplay::getHDRException(ExynosLayer* __unused layer)
1490 {
1491 return false;
1492 }
1493
configureHandle(ExynosLayer & layer,int fence_fd,exynos_win_config_data & cfg)1494 int32_t ExynosDisplay::configureHandle(ExynosLayer &layer, int fence_fd, exynos_win_config_data &cfg)
1495 {
1496 /* TODO : this is hardcoded */
1497 int32_t ret = NO_ERROR;
1498 buffer_handle_t handle = NULL;
1499 int32_t blending = 0x0100;
1500 uint32_t x = 0, y = 0;
1501 uint32_t w = WIDTH(layer.mPreprocessedInfo.displayFrame);
1502 uint32_t h = HEIGHT(layer.mPreprocessedInfo.displayFrame);
1503 ExynosMPP* otfMPP = NULL;
1504 ExynosMPP* m2mMPP = NULL;
1505 unsigned int luminanceMin = 0;
1506 unsigned int luminanceMax = 0;
1507
1508 blending = layer.mBlending;
1509 otfMPP = layer.mOtfMPP;
1510 m2mMPP = layer.mM2mMPP;
1511
1512 cfg.compression = layer.mCompressed;
1513 if (layer.mCompressed) {
1514 cfg.comp_src = DPP_COMP_SRC_GPU;
1515 }
1516 if (otfMPP == NULL) {
1517 HWC_LOGE(this, "%s:: otfMPP is NULL", __func__);
1518 return -EINVAL;
1519 }
1520 if (m2mMPP != NULL)
1521 handle = m2mMPP->mDstImgs[m2mMPP->mCurrentDstBuf].bufferHandle;
1522 else
1523 handle = layer.mLayerBuffer;
1524
1525 if ((!layer.isDimLayer()) && handle == NULL) {
1526 HWC_LOGE(this, "%s:: invalid handle", __func__);
1527 return -EINVAL;
1528 }
1529
1530 if (layer.mPreprocessedInfo.displayFrame.left < 0) {
1531 unsigned int crop = -layer.mPreprocessedInfo.displayFrame.left;
1532 DISPLAY_LOGD(eDebugWinConfig, "layer off left side of screen; cropping %u pixels from left edge",
1533 crop);
1534 x = 0;
1535 w -= crop;
1536 } else {
1537 x = layer.mPreprocessedInfo.displayFrame.left;
1538 }
1539
1540 if (layer.mPreprocessedInfo.displayFrame.right > (int)mXres) {
1541 unsigned int crop = layer.mPreprocessedInfo.displayFrame.right - mXres;
1542 DISPLAY_LOGD(eDebugWinConfig, "layer off right side of screen; cropping %u pixels from right edge",
1543 crop);
1544 w -= crop;
1545 }
1546
1547 if (layer.mPreprocessedInfo.displayFrame.top < 0) {
1548 unsigned int crop = -layer.mPreprocessedInfo.displayFrame.top;
1549 DISPLAY_LOGD(eDebugWinConfig, "layer off top side of screen; cropping %u pixels from top edge",
1550 crop);
1551 y = 0;
1552 h -= crop;
1553 } else {
1554 y = layer.mPreprocessedInfo.displayFrame.top;
1555 }
1556
1557 if (layer.mPreprocessedInfo.displayFrame.bottom > (int)mYres) {
1558 int crop = layer.mPreprocessedInfo.displayFrame.bottom - mYres;
1559 DISPLAY_LOGD(eDebugWinConfig, "layer off bottom side of screen; cropping %u pixels from bottom edge",
1560 crop);
1561 h -= crop;
1562 }
1563
1564 cfg.layer = &layer;
1565 if ((layer.mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
1566 (layer.mCompositionType == HWC2_COMPOSITION_CURSOR))
1567 cfg.state = cfg.WIN_STATE_CURSOR;
1568 else
1569 cfg.state = cfg.WIN_STATE_BUFFER;
1570 cfg.dst.x = x;
1571 cfg.dst.y = y;
1572 cfg.dst.w = w;
1573 cfg.dst.h = h;
1574 cfg.dst.f_w = mXres;
1575 cfg.dst.f_h = mYres;
1576
1577 cfg.plane_alpha = layer.mPlaneAlpha;
1578 cfg.blending = blending;
1579 cfg.assignedMPP = otfMPP;
1580
1581 if (layer.isDimLayer()) {
1582 cfg.state = cfg.WIN_STATE_COLOR;
1583 hwc_color_t color = layer.mColor;
1584 cfg.color = (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
1585 DISPLAY_LOGD(eDebugWinConfig, "HWC2: DIM layer is enabled, color: %d, alpha : %f",
1586 cfg.color, cfg.plane_alpha);
1587 return ret;
1588 }
1589
1590 VendorGraphicBufferMeta gmeta(handle);
1591
1592 if (!layer.mPreprocessedInfo.mUsePrivateFormat)
1593 cfg.format = gmeta.format;
1594 else
1595 cfg.format = layer.mPreprocessedInfo.mPrivateFormat;
1596
1597 cfg.buffer_id = gmeta.unique_id;
1598 cfg.fd_idma[0] = gmeta.fd;
1599 cfg.fd_idma[1] = gmeta.fd1;
1600 cfg.fd_idma[2] = gmeta.fd2;
1601 cfg.protection = (getDrmMode(gmeta.producer_usage) == SECURE_DRM) ? 1 : 0;
1602
1603 exynos_image src_img = layer.mSrcImg;
1604
1605 if (m2mMPP != NULL)
1606 {
1607 DISPLAY_LOGD(eDebugWinConfig, "\tUse m2mMPP, bufIndex: %d", m2mMPP->mCurrentDstBuf);
1608 dumpExynosImage(eDebugWinConfig, m2mMPP->mAssignedSources[0]->mMidImg);
1609 exynos_image mpp_dst_img;
1610 if (m2mMPP->getDstImageInfo(&mpp_dst_img) == NO_ERROR) {
1611 dumpExynosImage(eDebugWinConfig, mpp_dst_img);
1612 cfg.compression = mpp_dst_img.compressed;
1613 cfg.src.f_w = mpp_dst_img.fullWidth;
1614 cfg.src.f_h = mpp_dst_img.fullHeight;
1615 cfg.src.x = mpp_dst_img.x;
1616 cfg.src.y = mpp_dst_img.y;
1617 cfg.src.w = mpp_dst_img.w;
1618 cfg.src.h = mpp_dst_img.h;
1619 cfg.format = mpp_dst_img.format;
1620 cfg.acq_fence =
1621 hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, mpp_dst_img.releaseFenceFd);
1622
1623 if (m2mMPP->mPhysicalType == MPP_MSC) {
1624 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_MSC);
1625 } else if (m2mMPP->mPhysicalType == MPP_G2D) {
1626 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_G2D);
1627 } else {
1628 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_MPP);
1629 }
1630 m2mMPP->resetDstReleaseFence();
1631 } else {
1632 HWC_LOGE(this, "%s:: Failed to get dst info of m2mMPP", __func__);
1633 }
1634 cfg.dataspace = mpp_dst_img.dataSpace;
1635
1636 cfg.transform = 0;
1637
1638 if (hasHdrInfo(layer.mMidImg)) {
1639 bool hdr_exception = getHDRException(&layer);
1640 uint32_t parcelFdIndex =
1641 getBufferNumOfFormat(layer.mMidImg.format,
1642 getCompressionType(layer.mMidImg.bufferHandle));
1643 if (parcelFdIndex == 0) {
1644 DISPLAY_LOGE("%s:: failed to get parcelFdIndex for midImg with format: %d",
1645 __func__, layer.mMidImg.format);
1646 return -EINVAL;
1647 }
1648 if (layer.mBufferHasMetaParcel) {
1649 VendorGraphicBufferMeta layer_buffer_gmeta(layer.mLayerBuffer);
1650 if (layer_buffer_gmeta.flags & VendorGraphicBufferMeta::PRIV_FLAGS_USES_2PRIVATE_DATA)
1651 cfg.fd_idma[parcelFdIndex] = layer_buffer_gmeta.fd1;
1652 else if (layer_buffer_gmeta.flags & VendorGraphicBufferMeta::PRIV_FLAGS_USES_3PRIVATE_DATA)
1653 cfg.fd_idma[parcelFdIndex] = layer_buffer_gmeta.fd2;
1654 } else {
1655 cfg.fd_idma[parcelFdIndex] = layer.mMetaParcelFd;
1656 }
1657
1658 if (!hdr_exception)
1659 cfg.hdr_enable = true;
1660 else
1661 cfg.hdr_enable = false;
1662
1663 /* Min/Max luminance should be set as M2M MPP's HDR operations
1664 * If HDR is not processed by M2M MPP, M2M's dst image should have source's min/max luminance
1665 * */
1666 dstMetaInfo_t metaInfo = m2mMPP->getDstMetaInfo(mpp_dst_img.dataSpace);
1667 luminanceMin = metaInfo.minLuminance;
1668 luminanceMax = metaInfo.maxLuminance;
1669 DISPLAY_LOGD(eDebugMPP, "HWC2: DPP luminance min %d, max %d", luminanceMin, luminanceMax);
1670 } else {
1671 cfg.hdr_enable = true;
1672 }
1673
1674 src_img = layer.mMidImg;
1675 } else {
1676 cfg.src.f_w = src_img.fullWidth;
1677 cfg.src.f_h = src_img.fullHeight;
1678 cfg.src.x = layer.mPreprocessedInfo.sourceCrop.left;
1679 cfg.src.y = layer.mPreprocessedInfo.sourceCrop.top;
1680 cfg.src.w = WIDTH(layer.mPreprocessedInfo.sourceCrop) - (cfg.src.x - (uint32_t)layer.mPreprocessedInfo.sourceCrop.left);
1681 cfg.src.h = HEIGHT(layer.mPreprocessedInfo.sourceCrop) - (cfg.src.y - (uint32_t)layer.mPreprocessedInfo.sourceCrop.top);
1682 cfg.acq_fence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, fence_fd);
1683 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_LAYER);
1684
1685 cfg.dataspace = src_img.dataSpace;
1686 cfg.transform = src_img.transform;
1687
1688 if (hasHdrInfo(src_img)) {
1689 bool hdr_exception = getHDRException(&layer);
1690 if (!hdr_exception)
1691 cfg.hdr_enable = true;
1692 else
1693 cfg.hdr_enable = false;
1694
1695 if (layer.mBufferHasMetaParcel == false) {
1696 uint32_t parcelFdIndex =
1697 getBufferNumOfFormat(gmeta.format, getCompressionType(handle));
1698 if (parcelFdIndex == 0) {
1699 DISPLAY_LOGE("%s:: failed to get parcelFdIndex for srcImg with format: %d",
1700 __func__, gmeta.format);
1701 return -EINVAL;
1702 }
1703
1704 cfg.fd_idma[parcelFdIndex] = layer.mMetaParcelFd;
1705 }
1706
1707 /*
1708 * Static info uses 0.0001nit unit for luminace
1709 * Display uses 1nit unit for max luminance
1710 * and uses 0.0001nit unit for min luminance
1711 * Conversion is required
1712 */
1713 luminanceMin = src_img.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
1714 luminanceMax = src_img.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000;
1715 DISPLAY_LOGD(eDebugMPP, "HWC2: DPP luminance min %d, max %d", luminanceMin, luminanceMax);
1716 } else {
1717 cfg.hdr_enable = true;
1718 }
1719 }
1720
1721 cfg.min_luminance = luminanceMin;
1722 cfg.max_luminance = luminanceMax;
1723 cfg.needColorTransform = src_img.needColorTransform;
1724
1725 /* Adjust configuration */
1726 uint32_t srcMaxWidth, srcMaxHeight, srcWidthAlign, srcHeightAlign = 0;
1727 uint32_t srcXAlign, srcYAlign, srcMaxCropWidth, srcMaxCropHeight, srcCropWidthAlign, srcCropHeightAlign = 0;
1728 srcMaxWidth = otfMPP->getSrcMaxWidth(src_img);
1729 srcMaxHeight = otfMPP->getSrcMaxHeight(src_img);
1730 srcWidthAlign = otfMPP->getSrcWidthAlign(src_img);
1731 srcHeightAlign = otfMPP->getSrcHeightAlign(src_img);
1732 srcXAlign = otfMPP->getSrcXOffsetAlign(src_img);
1733 srcYAlign = otfMPP->getSrcYOffsetAlign(src_img);
1734 srcMaxCropWidth = otfMPP->getSrcMaxCropWidth(src_img);
1735 srcMaxCropHeight = otfMPP->getSrcMaxCropHeight(src_img);
1736 srcCropWidthAlign = otfMPP->getSrcCropWidthAlign(src_img);
1737 srcCropHeightAlign = otfMPP->getSrcCropHeightAlign(src_img);
1738
1739 if (cfg.src.x < 0)
1740 cfg.src.x = 0;
1741 if (cfg.src.y < 0)
1742 cfg.src.y = 0;
1743
1744 if (otfMPP != NULL) {
1745 if (cfg.src.f_w > srcMaxWidth)
1746 cfg.src.f_w = srcMaxWidth;
1747 if (cfg.src.f_h > srcMaxHeight)
1748 cfg.src.f_h = srcMaxHeight;
1749 cfg.src.f_w = pixel_align_down(cfg.src.f_w, srcWidthAlign);
1750 cfg.src.f_h = pixel_align_down(cfg.src.f_h, srcHeightAlign);
1751
1752 cfg.src.x = pixel_align(cfg.src.x, srcXAlign);
1753 cfg.src.y = pixel_align(cfg.src.y, srcYAlign);
1754 }
1755
1756 if (cfg.src.x + cfg.src.w > cfg.src.f_w)
1757 cfg.src.w = cfg.src.f_w - cfg.src.x;
1758 if (cfg.src.y + cfg.src.h > cfg.src.f_h)
1759 cfg.src.h = cfg.src.f_h - cfg.src.y;
1760
1761 if (otfMPP != NULL) {
1762 if (cfg.src.w > srcMaxCropWidth)
1763 cfg.src.w = srcMaxCropWidth;
1764 if (cfg.src.h > srcMaxCropHeight)
1765 cfg.src.h = srcMaxCropHeight;
1766 cfg.src.w = pixel_align_down(cfg.src.w, srcCropWidthAlign);
1767 cfg.src.h = pixel_align_down(cfg.src.h, srcCropHeightAlign);
1768 }
1769
1770 uint64_t bufSize = gmeta.size * formatToBpp(gmeta.format);
1771 uint64_t srcSize = cfg.src.f_w * cfg.src.f_h * formatToBpp(cfg.format);
1772
1773 if (!isFormatLossy(gmeta.format) && (bufSize < srcSize)) {
1774 DISPLAY_LOGE("%s:: buffer size is smaller than source size, buf(size: %d, format: %d), src(w: %d, h: %d, format: %d)",
1775 __func__, gmeta.size, gmeta.format, cfg.src.f_w, cfg.src.f_h, cfg.format);
1776 return -EINVAL;
1777 }
1778
1779 return ret;
1780 }
1781
1782
configureOverlay(ExynosLayer * layer,exynos_win_config_data & cfg)1783 int32_t ExynosDisplay::configureOverlay(ExynosLayer *layer, exynos_win_config_data &cfg)
1784 {
1785 int32_t ret = NO_ERROR;
1786 if(layer != NULL) {
1787 if ((ret = configureHandle(*layer, layer->mAcquireFence, cfg)) != NO_ERROR)
1788 return ret;
1789
1790 /* This will be closed by setReleaseFences() using config.acq_fence */
1791 layer->mAcquireFence = -1;
1792 }
1793 return ret;
1794 }
configureOverlay(ExynosCompositionInfo & compositionInfo)1795 int32_t ExynosDisplay::configureOverlay(ExynosCompositionInfo &compositionInfo)
1796 {
1797 int32_t windowIndex = compositionInfo.mWindowIndex;
1798 buffer_handle_t handle = compositionInfo.mTargetBuffer;
1799 VendorGraphicBufferMeta gmeta(compositionInfo.mTargetBuffer);
1800
1801 if ((windowIndex < 0) || (windowIndex >= (int32_t)mDpuData.configs.size()))
1802 {
1803 HWC_LOGE(this, "%s:: ExynosCompositionInfo(%d) has invalid data, windowIndex(%d)",
1804 __func__, compositionInfo.mType, windowIndex);
1805 return -EINVAL;
1806 }
1807
1808 exynos_win_config_data &config = mDpuData.configs[windowIndex];
1809
1810 if (handle == NULL) {
1811 /* config will be set by handleStaticLayers */
1812 if (compositionInfo.mSkipFlag)
1813 return NO_ERROR;
1814
1815 if (compositionInfo.mType == COMPOSITION_CLIENT) {
1816 ALOGW("%s:: ExynosCompositionInfo(%d) has invalid data, handle(%p)",
1817 __func__, compositionInfo.mType, handle);
1818 if (compositionInfo.mAcquireFence >= 0) {
1819 compositionInfo.mAcquireFence = fence_close(compositionInfo.mAcquireFence, this,
1820 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
1821 }
1822 config.state = config.WIN_STATE_DISABLED;
1823 return NO_ERROR;
1824 } else {
1825 HWC_LOGE(this, "%s:: ExynosCompositionInfo(%d) has invalid data, handle(%p)",
1826 __func__, compositionInfo.mType, handle);
1827 return -EINVAL;
1828 }
1829 }
1830
1831 config.buffer_id = gmeta.unique_id;
1832 config.fd_idma[0] = gmeta.fd;
1833 config.fd_idma[1] = gmeta.fd1;
1834 config.fd_idma[2] = gmeta.fd2;
1835 config.protection = (getDrmMode(gmeta.producer_usage) == SECURE_DRM) ? 1 : 0;
1836 config.state = config.WIN_STATE_BUFFER;
1837
1838 config.assignedMPP = compositionInfo.mOtfMPP;
1839
1840 config.dst.f_w = mXres;
1841 config.dst.f_h = mYres;
1842 config.format = gmeta.format;
1843 if (compositionInfo.mType == COMPOSITION_EXYNOS) {
1844 config.src.f_w = pixel_align(mXres, G2D_JUSTIFIED_DST_ALIGN);
1845 config.src.f_h = pixel_align(mYres, G2D_JUSTIFIED_DST_ALIGN);
1846 } else {
1847 config.src.f_w = gmeta.stride;
1848 config.src.f_h = gmeta.vstride;
1849 }
1850 config.compression = compositionInfo.mCompressed;
1851 if (compositionInfo.mCompressed) {
1852 if (compositionInfo.mType == COMPOSITION_EXYNOS)
1853 config.comp_src = DPP_COMP_SRC_G2D;
1854 else if (compositionInfo.mType == COMPOSITION_CLIENT)
1855 config.comp_src = DPP_COMP_SRC_GPU;
1856 else
1857 HWC_LOGE(this, "unknown composition type: %d", compositionInfo.mType);
1858 }
1859
1860 bool useCompositionCrop = true;
1861 if ((mDisplayControl.enableCompositionCrop) &&
1862 (compositionInfo.mHasCompositionLayer) &&
1863 (compositionInfo.mFirstIndex >= 0) &&
1864 (compositionInfo.mLastIndex >= 0)) {
1865 hwc_rect merged_rect, src_rect;
1866 merged_rect.left = mXres;
1867 merged_rect.top = mYres;
1868 merged_rect.right = 0;
1869 merged_rect.bottom = 0;
1870
1871 for (int i = compositionInfo.mFirstIndex; i <= compositionInfo.mLastIndex; i++) {
1872 ExynosLayer *layer = mLayers[i];
1873 src_rect.left = layer->mDisplayFrame.left;
1874 src_rect.top = layer->mDisplayFrame.top;
1875 src_rect.right = layer->mDisplayFrame.right;
1876 src_rect.bottom = layer->mDisplayFrame.bottom;
1877 merged_rect = expand(merged_rect, src_rect);
1878 DISPLAY_LOGD(eDebugWinConfig, "[%d] layer type: [%d, %d] dispFrame [l: %d, t: %d, r: %d, b: %d], mergedRect [l: %d, t: %d, r: %d, b: %d]",
1879 i,
1880 layer->mCompositionType,
1881 layer->mExynosCompositionType,
1882 layer->mDisplayFrame.left,
1883 layer->mDisplayFrame.top,
1884 layer->mDisplayFrame.right,
1885 layer->mDisplayFrame.bottom,
1886 merged_rect.left,
1887 merged_rect.top,
1888 merged_rect.right,
1889 merged_rect.bottom);
1890 }
1891
1892 config.src.x = merged_rect.left;
1893 config.src.y = merged_rect.top;
1894 config.src.w = merged_rect.right - merged_rect.left;
1895 config.src.h = merged_rect.bottom - merged_rect.top;
1896
1897 ExynosMPP* exynosMPP = config.assignedMPP;
1898 if (exynosMPP == NULL) {
1899 DISPLAY_LOGE("%s:: assignedMPP is NULL", __func__);
1900 useCompositionCrop = false;
1901 } else {
1902 /* Check size constraints */
1903 uint32_t restrictionIdx = getRestrictionIndex(config.format);
1904 uint32_t srcXAlign = exynosMPP->getSrcXOffsetAlign(restrictionIdx);
1905 uint32_t srcYAlign = exynosMPP->getSrcYOffsetAlign(restrictionIdx);
1906 uint32_t srcWidthAlign = exynosMPP->getSrcCropWidthAlign(restrictionIdx);
1907 uint32_t srcHeightAlign = exynosMPP->getSrcCropHeightAlign(restrictionIdx);
1908 uint32_t srcMinWidth = exynosMPP->getSrcMinWidth(restrictionIdx);
1909 uint32_t srcMinHeight = exynosMPP->getSrcMinHeight(restrictionIdx);
1910
1911 if (config.src.w < srcMinWidth) {
1912 config.src.x -= (srcMinWidth - config.src.w);
1913 if (config.src.x < 0)
1914 config.src.x = 0;
1915 config.src.w = srcMinWidth;
1916 }
1917 if (config.src.h < srcMinHeight) {
1918 config.src.y -= (srcMinHeight - config.src.h);
1919 if (config.src.y < 0)
1920 config.src.y = 0;
1921 config.src.h = srcMinHeight;
1922 }
1923
1924 int32_t alignedSrcX = pixel_align_down(config.src.x, srcXAlign);
1925 int32_t alignedSrcY = pixel_align_down(config.src.y, srcYAlign);
1926 config.src.w += (config.src.x - alignedSrcX);
1927 config.src.h += (config.src.y - alignedSrcY);
1928 config.src.x = alignedSrcX;
1929 config.src.y = alignedSrcY;
1930 config.src.w = pixel_align(config.src.w, srcWidthAlign);
1931 config.src.h = pixel_align(config.src.h, srcHeightAlign);
1932 }
1933
1934 config.dst.x = config.src.x;
1935 config.dst.y = config.src.y;
1936 config.dst.w = config.src.w;
1937 config.dst.h = config.src.h;
1938
1939 if ((config.src.x < 0) ||
1940 (config.src.y < 0) ||
1941 ((config.src.x + config.src.w) > mXres) ||
1942 ((config.src.y + config.src.h) > mYres)) {
1943 useCompositionCrop = false;
1944 ALOGW("Invalid composition target crop size: (%d, %d, %d, %d)",
1945 config.src.x, config.src.y,
1946 config.src.w, config.src.h);
1947 }
1948
1949 DISPLAY_LOGD(eDebugWinConfig, "composition(%d) config[%d] x : %d, y : %d, w : %d, h : %d",
1950 compositionInfo.mType, windowIndex,
1951 config.dst.x, config.dst.y,
1952 config.dst.w, config.dst.h);
1953 } else {
1954 useCompositionCrop = false;
1955 }
1956
1957 if (useCompositionCrop == false) {
1958 config.src.x = 0;
1959 config.src.y = 0;
1960 config.src.w = mXres;
1961 config.src.h = mYres;
1962 config.dst.x = 0;
1963 config.dst.y = 0;
1964 config.dst.w = mXres;
1965 config.dst.h = mYres;
1966 }
1967
1968 config.blending = HWC2_BLEND_MODE_PREMULTIPLIED;
1969
1970 config.acq_fence =
1971 hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, compositionInfo.mAcquireFence);
1972 config.plane_alpha = 1;
1973 config.dataspace = compositionInfo.mSrcImg.dataSpace;
1974 config.hdr_enable = true;
1975
1976 /* This will be closed by setReleaseFences() using config.acq_fence */
1977 compositionInfo.mAcquireFence = -1;
1978 DISPLAY_LOGD(eDebugSkipStaicLayer, "Configure composition target[%d], config[%d]!!!!",
1979 compositionInfo.mType, windowIndex);
1980 dumpConfig(config);
1981
1982 uint64_t bufSize = gmeta.size * formatToBpp(gmeta.format);
1983 uint64_t srcSize = config.src.f_w * config.src.f_h * formatToBpp(config.format);
1984 if (!isFormatLossy(gmeta.format) && (bufSize < srcSize)) {
1985 DISPLAY_LOGE("%s:: buffer size is smaller than source size, buf(size: %d, format: %d), src(w: %d, h: %d, format: %d)",
1986 __func__, gmeta.size, gmeta.format, config.src.f_w, config.src.f_h, config.format);
1987 return -EINVAL;
1988 }
1989
1990 return NO_ERROR;
1991 }
1992
1993 /**
1994 * @return int
1995 */
setWinConfigData()1996 int ExynosDisplay::setWinConfigData() {
1997 int ret = NO_ERROR;
1998 mDpuData.reset();
1999
2000 if (mClientCompositionInfo.mHasCompositionLayer) {
2001 if ((ret = configureOverlay(mClientCompositionInfo)) != NO_ERROR)
2002 return ret;
2003 }
2004 if (mExynosCompositionInfo.mHasCompositionLayer) {
2005 if ((ret = configureOverlay(mExynosCompositionInfo)) != NO_ERROR) {
2006 /* TEST */
2007 //return ret;
2008 HWC_LOGE(this, "configureOverlay(ExynosCompositionInfo) is failed");
2009 }
2010 }
2011
2012 /* TODO loop for number of layers */
2013 for (size_t i = 0; i < mLayers.size(); i++) {
2014 if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) ||
2015 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT))
2016 continue;
2017 int32_t windowIndex = mLayers[i]->mWindowIndex;
2018 if ((windowIndex < 0) || (windowIndex >= (int32_t)mDpuData.configs.size())) {
2019 DISPLAY_LOGE("%s:: %zu layer has invalid windowIndex(%d)",
2020 __func__, i, windowIndex);
2021 return -EINVAL;
2022 }
2023 DISPLAY_LOGD(eDebugWinConfig, "%zu layer, config[%d]", i, windowIndex);
2024 if ((ret = configureOverlay(mLayers[i], mDpuData.configs[windowIndex])) != NO_ERROR)
2025 return ret;
2026 }
2027
2028 return 0;
2029 }
2030
printDebugInfos(String8 & reason)2031 void ExynosDisplay::printDebugInfos(String8 &reason)
2032 {
2033 bool writeFile = true;
2034 FILE *pFile = NULL;
2035 struct timeval tv;
2036 struct tm* localTime;
2037 gettimeofday(&tv, NULL);
2038 localTime = (struct tm*)localtime((time_t*)&tv.tv_sec);
2039 reason.appendFormat("errFrameNumber: %" PRId64 " time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)\n",
2040 mErrorFrameCount,
2041 localTime->tm_mon+1, localTime->tm_mday,
2042 localTime->tm_hour, localTime->tm_min,
2043 localTime->tm_sec, tv.tv_usec/1000,
2044 ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
2045 ALOGD("%s", reason.string());
2046
2047 if (mErrorFrameCount >= HWC_PRINT_FRAME_NUM)
2048 writeFile = false;
2049 else {
2050 char filePath[128];
2051 sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH0, mDisplayName.string(), (int)mErrorFrameCount);
2052 pFile = fopen(filePath, "wb");
2053 if (pFile == NULL) {
2054 ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
2055 sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH1, mDisplayName.string(), (int)mErrorFrameCount);
2056 pFile = fopen(filePath, "wb");
2057 }
2058 if (pFile == NULL) {
2059 ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
2060 } else {
2061 ALOGI("%s was created", filePath);
2062 fwrite(reason.string(), 1, reason.size(), pFile);
2063 }
2064 }
2065 mErrorFrameCount++;
2066
2067 android::String8 result;
2068 result.appendFormat("Device mGeometryChanged(%" PRIx64 "), mGeometryChanged(%" PRIx64 "), mRenderingState(%d)\n",
2069 mDevice->mGeometryChanged, mGeometryChanged, mRenderingState);
2070 result.appendFormat("======================= dump composition infos ================================\n");
2071 ExynosCompositionInfo clientCompInfo = mClientCompositionInfo;
2072 ExynosCompositionInfo exynosCompInfo = mExynosCompositionInfo;
2073 clientCompInfo.dump(result);
2074 exynosCompInfo.dump(result);
2075 ALOGD("%s", result.string());
2076 if (pFile != NULL) {
2077 fwrite(result.string(), 1, result.size(), pFile);
2078 }
2079 result.clear();
2080
2081 result.appendFormat("======================= dump exynos layers (%zu) ================================\n",
2082 mLayers.size());
2083 ALOGD("%s", result.string());
2084 if (pFile != NULL) {
2085 fwrite(result.string(), 1, result.size(), pFile);
2086 }
2087 result.clear();
2088 for (uint32_t i = 0; i < mLayers.size(); i++) {
2089 ExynosLayer *layer = mLayers[i];
2090 layer->printLayer();
2091 if (pFile != NULL) {
2092 layer->dump(result);
2093 fwrite(result.string(), 1, result.size(), pFile);
2094 result.clear();
2095 }
2096 }
2097
2098 if (mIgnoreLayers.size()) {
2099 result.appendFormat("======================= dump ignore layers (%zu) ================================\n",
2100 mIgnoreLayers.size());
2101 ALOGD("%s", result.string());
2102 if (pFile != NULL) {
2103 fwrite(result.string(), 1, result.size(), pFile);
2104 }
2105 result.clear();
2106 for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
2107 ExynosLayer *layer = mIgnoreLayers[i];
2108 layer->printLayer();
2109 if (pFile != NULL) {
2110 layer->dump(result);
2111 fwrite(result.string(), 1, result.size(), pFile);
2112 result.clear();
2113 }
2114 }
2115 }
2116
2117 result.appendFormat("============================= dump win configs ===================================\n");
2118 ALOGD("%s", result.string());
2119 if (pFile != NULL) {
2120 fwrite(result.string(), 1, result.size(), pFile);
2121 }
2122 result.clear();
2123 for (size_t i = 0; i <= mDpuData.configs.size(); i++) {
2124 ALOGD("config[%zu]", i);
2125 printConfig(mDpuData.configs[i]);
2126 if (pFile != NULL) {
2127 result.appendFormat("config[%zu]\n", i);
2128 dumpConfig(result, mDpuData.configs[i]);
2129 fwrite(result.string(), 1, result.size(), pFile);
2130 result.clear();
2131 }
2132 }
2133 if (pFile != NULL) {
2134 fclose(pFile);
2135 }
2136 }
2137
validateWinConfigData()2138 int32_t ExynosDisplay::validateWinConfigData()
2139 {
2140 bool flagValidConfig = true;
2141 int bufferStateCnt = 0;
2142
2143 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2144 exynos_win_config_data &config = mDpuData.configs[i];
2145 if (config.state == config.WIN_STATE_BUFFER) {
2146 bool configInvalid = false;
2147 /* multiple dma mapping */
2148 for (size_t j = (i+1); j < mDpuData.configs.size(); j++) {
2149 exynos_win_config_data &compare_config = mDpuData.configs[j];
2150 if ((config.state == config.WIN_STATE_BUFFER) &&
2151 (compare_config.state == compare_config.WIN_STATE_BUFFER)) {
2152 if ((config.assignedMPP != NULL) &&
2153 (config.assignedMPP == compare_config.assignedMPP)) {
2154 DISPLAY_LOGE("WIN_CONFIG error: duplicated assignedMPP(%s) between win%zu, win%zu",
2155 config.assignedMPP->mName.string(), i, j);
2156 compare_config.state = compare_config.WIN_STATE_DISABLED;
2157 flagValidConfig = false;
2158 continue;
2159 }
2160 }
2161 }
2162 if ((config.src.x < 0) || (config.src.y < 0)||
2163 (config.dst.x < 0) || (config.dst.y < 0)||
2164 (config.src.w <= 0) || (config.src.h <= 0)||
2165 (config.dst.w <= 0) || (config.dst.h <= 0)||
2166 (config.dst.x + config.dst.w > (uint32_t)mXres) ||
2167 (config.dst.y + config.dst.h > (uint32_t)mYres)) {
2168 DISPLAY_LOGE("WIN_CONFIG error: invalid pos or size win%zu", i);
2169 configInvalid = true;
2170 }
2171
2172 if ((config.src.w > config.src.f_w) ||
2173 (config.src.h > config.src.f_h)) {
2174 DISPLAY_LOGE("WIN_CONFIG error: invalid size %zu, %d, %d, %d, %d", i,
2175 config.src.w, config.src.f_w, config.src.h, config.src.f_h);
2176 configInvalid = true;
2177 }
2178
2179 /* Source alignment check */
2180 ExynosMPP* exynosMPP = config.assignedMPP;
2181 if (exynosMPP == NULL) {
2182 DISPLAY_LOGE("WIN_CONFIG error: config %zu assigendMPP is NULL", i);
2183 configInvalid = true;
2184 } else {
2185 uint32_t restrictionIdx = getRestrictionIndex(config.format);
2186 uint32_t srcXAlign = exynosMPP->getSrcXOffsetAlign(restrictionIdx);
2187 uint32_t srcYAlign = exynosMPP->getSrcYOffsetAlign(restrictionIdx);
2188 uint32_t srcWidthAlign = exynosMPP->getSrcCropWidthAlign(restrictionIdx);
2189 uint32_t srcHeightAlign = exynosMPP->getSrcCropHeightAlign(restrictionIdx);
2190 if ((config.src.x % srcXAlign != 0) ||
2191 (config.src.y % srcYAlign != 0) ||
2192 (config.src.w % srcWidthAlign != 0) ||
2193 (config.src.h % srcHeightAlign != 0))
2194 {
2195 DISPLAY_LOGE("WIN_CONFIG error: invalid src alignment : %zu, "\
2196 "assignedMPP: %s, mppType:%d, format(%d), s_x: %d(%d), s_y: %d(%d), s_w : %d(%d), s_h : %d(%d)", i,
2197 config.assignedMPP->mName.string(), exynosMPP->mLogicalType, config.format, config.src.x, srcXAlign,
2198 config.src.y, srcYAlign, config.src.w, srcWidthAlign, config.src.h, srcHeightAlign);
2199 configInvalid = true;
2200 }
2201 }
2202
2203 if (configInvalid) {
2204 config.state = config.WIN_STATE_DISABLED;
2205 flagValidConfig = false;
2206 }
2207
2208 bufferStateCnt++;
2209 }
2210
2211 if ((config.state == config.WIN_STATE_COLOR) ||
2212 (config.state == config.WIN_STATE_CURSOR))
2213 bufferStateCnt++;
2214 }
2215
2216 if (bufferStateCnt == 0) {
2217 DISPLAY_LOGE("WIN_CONFIG error: has no buffer window");
2218 flagValidConfig = false;
2219 }
2220
2221 if (flagValidConfig)
2222 return NO_ERROR;
2223 else
2224 return -EINVAL;
2225 }
2226
2227 /**
2228 * @return int
2229 */
setDisplayWinConfigData()2230 int ExynosDisplay::setDisplayWinConfigData() {
2231 return 0;
2232 }
2233
checkConfigChanged(const exynos_dpu_data & lastConfigsData,const exynos_dpu_data & newConfigsData)2234 bool ExynosDisplay::checkConfigChanged(const exynos_dpu_data &lastConfigsData, const exynos_dpu_data &newConfigsData)
2235 {
2236 if (exynosHWCControl.skipWinConfig == 0)
2237 return true;
2238
2239 /* HWC doesn't skip WIN_CONFIG if other display is connected */
2240 if ((mDevice->checkNonInternalConnection()) && (mType == HWC_DISPLAY_PRIMARY))
2241 return true;
2242
2243 for (size_t i = 0; i < lastConfigsData.configs.size(); i++) {
2244 if ((lastConfigsData.configs[i].state != newConfigsData.configs[i].state) ||
2245 (lastConfigsData.configs[i].fd_idma[0] != newConfigsData.configs[i].fd_idma[0]) ||
2246 (lastConfigsData.configs[i].fd_idma[1] != newConfigsData.configs[i].fd_idma[1]) ||
2247 (lastConfigsData.configs[i].fd_idma[2] != newConfigsData.configs[i].fd_idma[2]) ||
2248 (lastConfigsData.configs[i].dst.x != newConfigsData.configs[i].dst.x) ||
2249 (lastConfigsData.configs[i].dst.y != newConfigsData.configs[i].dst.y) ||
2250 (lastConfigsData.configs[i].dst.w != newConfigsData.configs[i].dst.w) ||
2251 (lastConfigsData.configs[i].dst.h != newConfigsData.configs[i].dst.h) ||
2252 (lastConfigsData.configs[i].src.x != newConfigsData.configs[i].src.x) ||
2253 (lastConfigsData.configs[i].src.y != newConfigsData.configs[i].src.y) ||
2254 (lastConfigsData.configs[i].src.w != newConfigsData.configs[i].src.w) ||
2255 (lastConfigsData.configs[i].src.h != newConfigsData.configs[i].src.h) ||
2256 (lastConfigsData.configs[i].format != newConfigsData.configs[i].format) ||
2257 (lastConfigsData.configs[i].blending != newConfigsData.configs[i].blending) ||
2258 (lastConfigsData.configs[i].plane_alpha != newConfigsData.configs[i].plane_alpha))
2259 return true;
2260 }
2261
2262 /* To cover buffer payload changed case */
2263 for (size_t i = 0; i < mLayers.size(); i++) {
2264 if(mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer)
2265 return true;
2266 }
2267
2268 return false;
2269 }
2270
checkConfigDstChanged(const exynos_dpu_data & lastConfigsData,const exynos_dpu_data & newConfigsData,uint32_t index)2271 int ExynosDisplay::checkConfigDstChanged(const exynos_dpu_data &lastConfigsData, const exynos_dpu_data &newConfigsData, uint32_t index)
2272 {
2273 if ((lastConfigsData.configs[index].state != newConfigsData.configs[index].state) ||
2274 (lastConfigsData.configs[index].fd_idma[0] != newConfigsData.configs[index].fd_idma[0]) ||
2275 (lastConfigsData.configs[index].fd_idma[1] != newConfigsData.configs[index].fd_idma[1]) ||
2276 (lastConfigsData.configs[index].fd_idma[2] != newConfigsData.configs[index].fd_idma[2]) ||
2277 (lastConfigsData.configs[index].format != newConfigsData.configs[index].format) ||
2278 (lastConfigsData.configs[index].blending != newConfigsData.configs[index].blending) ||
2279 (lastConfigsData.configs[index].plane_alpha != newConfigsData.configs[index].plane_alpha)) {
2280 DISPLAY_LOGD(eDebugWindowUpdate, "damage region is skip, but other configuration except dst was changed");
2281 DISPLAY_LOGD(eDebugWindowUpdate, "\tstate[%d, %d], fd[%d, %d], format[0x%8x, 0x%8x], blending[%d, %d], plane_alpha[%f, %f]",
2282 lastConfigsData.configs[index].state, newConfigsData.configs[index].state,
2283 lastConfigsData.configs[index].fd_idma[0], newConfigsData.configs[index].fd_idma[0],
2284 lastConfigsData.configs[index].format, newConfigsData.configs[index].format,
2285 lastConfigsData.configs[index].blending, newConfigsData.configs[index].blending,
2286 lastConfigsData.configs[index].plane_alpha, newConfigsData.configs[index].plane_alpha);
2287 return -1;
2288 }
2289 if ((lastConfigsData.configs[index].dst.x != newConfigsData.configs[index].dst.x) ||
2290 (lastConfigsData.configs[index].dst.y != newConfigsData.configs[index].dst.y) ||
2291 (lastConfigsData.configs[index].dst.w != newConfigsData.configs[index].dst.w) ||
2292 (lastConfigsData.configs[index].dst.h != newConfigsData.configs[index].dst.h) ||
2293 (lastConfigsData.configs[index].src.x != newConfigsData.configs[index].src.x) ||
2294 (lastConfigsData.configs[index].src.y != newConfigsData.configs[index].src.y) ||
2295 (lastConfigsData.configs[index].src.w != newConfigsData.configs[index].src.w) ||
2296 (lastConfigsData.configs[index].src.h != newConfigsData.configs[index].src.h))
2297 return 1;
2298
2299 else
2300 return 0;
2301 }
2302
2303 /**
2304 * @return int
2305 */
deliverWinConfigData()2306 int ExynosDisplay::deliverWinConfigData() {
2307
2308 ATRACE_CALL();
2309 String8 errString;
2310 int ret = NO_ERROR;
2311 struct timeval tv_s, tv_e;
2312 long timediff;
2313
2314 ret = validateWinConfigData();
2315 if (ret != NO_ERROR) {
2316 errString.appendFormat("Invalid WIN_CONFIG\n");
2317 goto err;
2318 }
2319
2320 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2321 DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "deliver config[%zu]", i);
2322 dumpConfig(mDpuData.configs[i]);
2323 }
2324
2325 if (checkConfigChanged(mDpuData, mLastDpuData) == false) {
2326 DISPLAY_LOGD(eDebugWinConfig, "Winconfig : same");
2327 #ifndef DISABLE_FENCE
2328 if (mLastRetireFence > 0) {
2329 mDpuData.retire_fence =
2330 hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP,
2331 hwc_dup(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP));
2332 } else
2333 mDpuData.retire_fence = -1;
2334 #endif
2335 ret = 0;
2336 } else {
2337 /* wait for 5 vsync */
2338 int32_t waitTime = mVsyncPeriod / 1000000 * 5;
2339 gettimeofday(&tv_s, NULL);
2340 if (fence_valid(mLastRetireFence)) {
2341 ATRACE_NAME("waitLastRetireFence");
2342 if (sync_wait(mLastRetireFence, waitTime) < 0) {
2343 DISPLAY_LOGE("%s:: mLastRetireFence(%d) is not released during (%d ms)",
2344 __func__, mLastRetireFence, waitTime);
2345 if (sync_wait(mLastRetireFence, 1000 - waitTime) < 0) {
2346 DISPLAY_LOGE("%s:: mLastRetireFence sync wait error (%d)", __func__, mLastRetireFence);
2347 }
2348 else {
2349 gettimeofday(&tv_e, NULL);
2350 tv_e.tv_usec += (tv_e.tv_sec - tv_s.tv_sec) * 1000000;
2351 timediff = tv_e.tv_usec - tv_s.tv_usec;
2352 DISPLAY_LOGE("%s:: winconfig is delayed over 5 vysnc (fence:%d)(time:%ld)",
2353 __func__, mLastRetireFence, timediff);
2354 }
2355 }
2356 }
2357
2358 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2359 setFenceInfo(mDpuData.configs[i].acq_fence, this,
2360 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, FENCE_TO);
2361 }
2362
2363 if ((ret = mDisplayInterface->deliverWinConfigData()) < 0) {
2364 errString.appendFormat("interface's deliverWinConfigData() failed: %s ret(%d)\n", strerror(errno), ret);
2365 goto err;
2366 } else {
2367 mLastDpuData = mDpuData;
2368 }
2369
2370 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2371 setFenceInfo(mDpuData.configs[i].rel_fence, this,
2372 FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, FENCE_FROM);
2373 }
2374 setFenceInfo(mDpuData.retire_fence, this,
2375 FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_FROM);
2376 }
2377
2378 return ret;
2379 err:
2380 printDebugInfos(errString);
2381 closeFences();
2382 clearDisplay();
2383 mDisplayInterface->setForcePanic();
2384
2385 return ret;
2386 }
2387
2388 /**
2389 * @return int
2390 */
setReleaseFences()2391 int ExynosDisplay::setReleaseFences() {
2392
2393 int release_fd = -1;
2394 String8 errString;
2395
2396 /*
2397 * Close release fence for client target buffer
2398 * SurfaceFlinger doesn't get release fence for client target buffer
2399 */
2400 if ((mClientCompositionInfo.mHasCompositionLayer) &&
2401 (mClientCompositionInfo.mWindowIndex >= 0) &&
2402 (mClientCompositionInfo.mWindowIndex < (int32_t)mDpuData.configs.size())) {
2403
2404 exynos_win_config_data &config = mDpuData.configs[mClientCompositionInfo.mWindowIndex];
2405
2406 for (int i = mClientCompositionInfo.mFirstIndex; i <= mClientCompositionInfo.mLastIndex; i++) {
2407 if (mLayers[i]->mExynosCompositionType != HWC2_COMPOSITION_CLIENT) {
2408 if(mLayers[i]->mOverlayPriority < ePriorityHigh) {
2409 errString.appendFormat("%d layer compositionType is not client(%d)\n", i, mLayers[i]->mExynosCompositionType);
2410 goto err;
2411 } else {
2412 continue;
2413 }
2414 }
2415 if (mType == HWC_DISPLAY_VIRTUAL)
2416 mLayers[i]->mReleaseFence = -1;
2417 else
2418 mLayers[i]->mReleaseFence =
2419 hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2420 hwc_dup(config.rel_fence, this,
2421 FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP));
2422 }
2423 config.rel_fence = fence_close(config.rel_fence, this,
2424 FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB);
2425 }
2426
2427 // DPU doesn't close acq_fence, HWC should close it.
2428 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2429 if (mDpuData.configs[i].acq_fence != -1)
2430 fence_close(mDpuData.configs[i].acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
2431 mDpuData.configs[i].acq_fence = -1;
2432 }
2433 // DPU doesn't close rel_fence of readback buffer, HWC should close it
2434 if (mDpuData.readback_info.rel_fence >= 0) {
2435 mDpuData.readback_info.rel_fence =
2436 fence_close(mDpuData.readback_info.rel_fence, this,
2437 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
2438 }
2439
2440 for (size_t i = 0; i < mLayers.size(); i++) {
2441 if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) ||
2442 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS))
2443 continue;
2444 if ((mLayers[i]->mWindowIndex < 0) ||
2445 (mLayers[i]->mWindowIndex >= mDpuData.configs.size())) {
2446 errString.appendFormat("%s:: layer[%zu] has invalid window index(%d)\n",
2447 __func__, i, mLayers[i]->mWindowIndex);
2448 goto err;
2449 }
2450 exynos_win_config_data &config = mDpuData.configs[mLayers[i]->mWindowIndex];
2451 if (mLayers[i]->mOtfMPP != NULL) {
2452 mLayers[i]->mOtfMPP->setHWStateFence(-1);
2453 }
2454 if (mLayers[i]->mM2mMPP != NULL) {
2455 if (mLayers[i]->mM2mMPP->mUseM2MSrcFence)
2456 mLayers[i]->mReleaseFence = mLayers[i]->mM2mMPP->getSrcReleaseFence(0);
2457 else {
2458 mLayers[i]->mReleaseFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2459 hwc_dup(config.rel_fence, this,
2460 FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER));
2461 }
2462
2463 mLayers[i]->mM2mMPP->resetSrcReleaseFence();
2464 #ifdef DISABLE_FENCE
2465 mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2466 #else
2467 DISPLAY_LOGD(eDebugFence, "m2m : win_index(%d), releaseFencefd(%d)",
2468 mLayers[i]->mWindowIndex, config.rel_fence);
2469 if (config.rel_fence > 0) {
2470 release_fd = config.rel_fence;
2471 if (release_fd >= 0) {
2472 setFenceName(release_fd,
2473 this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true);
2474 mLayers[i]->mM2mMPP->setDstAcquireFence(release_fd);
2475 } else {
2476 DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2477 mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2478 }
2479 } else {
2480 mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2481 }
2482 DISPLAY_LOGD(eDebugFence, "mM2mMPP is used, layer[%zu].releaseFencefd(%d)",
2483 i, mLayers[i]->mReleaseFence);
2484 #endif
2485 } else {
2486 #ifdef DISABLE_FENCE
2487 mLayers[i]->mReleaseFence = -1;
2488 #else
2489 DISPLAY_LOGD(eDebugFence, "other : win_index(%d), releaseFencefd(%d)",
2490 mLayers[i]->mWindowIndex, config.rel_fence);
2491 if (config.rel_fence > 0) {
2492 release_fd = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, config.rel_fence);
2493 if (release_fd >= 0)
2494 mLayers[i]->mReleaseFence = release_fd;
2495 else {
2496 DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2497 mLayers[i]->mReleaseFence = -1;
2498 }
2499 } else {
2500 mLayers[i]->mReleaseFence = -1;
2501 }
2502 DISPLAY_LOGD(eDebugFence, "Direct overlay layer[%zu].releaseFencefd(%d)",
2503 i, mLayers[i]->mReleaseFence);
2504 #endif
2505 }
2506 }
2507
2508 if (mExynosCompositionInfo.mHasCompositionLayer) {
2509 if (mExynosCompositionInfo.mM2mMPP == NULL)
2510 {
2511 errString.appendFormat("There is exynos composition, but m2mMPP is NULL\n");
2512 goto err;
2513 }
2514 if (mUseDpu &&
2515 ((mExynosCompositionInfo.mWindowIndex < 0) ||
2516 (mExynosCompositionInfo.mWindowIndex >= (int32_t)mDpuData.configs.size()))) {
2517 errString.appendFormat("%s:: exynosComposition has invalid window index(%d)\n",
2518 __func__, mExynosCompositionInfo.mWindowIndex);
2519 goto err;
2520 }
2521 exynos_win_config_data &config = mDpuData.configs[mExynosCompositionInfo.mWindowIndex];
2522 for (int i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
2523 /* break when only framebuffer target is assigned on ExynosCompositor */
2524 if (i == -1)
2525 break;
2526
2527 if (mLayers[i]->mExynosCompositionType != HWC2_COMPOSITION_EXYNOS) {
2528 errString.appendFormat("%d layer compositionType is not exynos(%d)\n", i, mLayers[i]->mExynosCompositionType);
2529 goto err;
2530 }
2531
2532 if (mExynosCompositionInfo.mM2mMPP->mUseM2MSrcFence)
2533 mLayers[i]->mReleaseFence =
2534 mExynosCompositionInfo.mM2mMPP->getSrcReleaseFence(i-mExynosCompositionInfo.mFirstIndex);
2535 else {
2536 mLayers[i]->mReleaseFence =
2537 hwc_dup(config.rel_fence,
2538 this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
2539 }
2540
2541 DISPLAY_LOGD(eDebugFence, "exynos composition layer[%d].releaseFencefd(%d)",
2542 i, mLayers[i]->mReleaseFence);
2543 }
2544 mExynosCompositionInfo.mM2mMPP->resetSrcReleaseFence();
2545 if(mUseDpu) {
2546 #ifdef DISABLE_FENCE
2547 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2548 #else
2549 if (config.rel_fence > 0) {
2550 setFenceName(config.rel_fence,
2551 this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true);
2552 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(config.rel_fence);
2553 } else {
2554 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2555 }
2556 #endif
2557 }
2558 }
2559 return 0;
2560
2561 err:
2562 printDebugInfos(errString);
2563 closeFences();
2564 mDisplayInterface->setForcePanic();
2565 return -EINVAL;
2566 }
2567
2568 /**
2569 * If display uses outbuf and outbuf is invalid, this function return false.
2570 * Otherwise, this function return true.
2571 * If outbuf is invalid, display should handle fence of layers.
2572 */
checkFrameValidation()2573 bool ExynosDisplay::checkFrameValidation() {
2574 return true;
2575 }
2576
acceptDisplayChanges()2577 int32_t ExynosDisplay::acceptDisplayChanges() {
2578 int32_t type = 0;
2579 if (mRenderingState != RENDERING_STATE_VALIDATED) {
2580 DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
2581 return HWC2_ERROR_NOT_VALIDATED;
2582 }
2583
2584 for (size_t i = 0; i < mLayers.size(); i++) {
2585 if (mLayers[i] != NULL) {
2586 HDEBUGLOGD(eDebugDefault, "%s, Layer %zu : %d, %d", __func__, i,
2587 mLayers[i]->mExynosCompositionType, mLayers[i]->mValidateCompositionType);
2588 type = getLayerCompositionTypeForValidationType(i);
2589
2590 /* update compositionType
2591 * SF updates their state and doesn't call back into HWC HAL
2592 */
2593 mLayers[i]->mCompositionType = type;
2594 mLayers[i]->mExynosCompositionType = mLayers[i]->mValidateCompositionType;
2595 }
2596 else {
2597 HWC_LOGE(this, "Layer %zu is NULL", i);
2598 }
2599 }
2600 mRenderingState = RENDERING_STATE_ACCEPTED_CHANGE;
2601
2602 return HWC2_ERROR_NONE;
2603 }
2604
createLayer(hwc2_layer_t * outLayer)2605 int32_t ExynosDisplay::createLayer(hwc2_layer_t* outLayer) {
2606
2607 Mutex::Autolock lock(mDRMutex);
2608 if (mPlugState == false) {
2609 DISPLAY_LOGI("%s : skip createLayer. Display is already disconnected", __func__);
2610 return HWC2_ERROR_BAD_DISPLAY;
2611 }
2612
2613 /* TODO : Implementation here */
2614 ExynosLayer *layer = new ExynosLayer(this);
2615
2616 /* TODO : Sort sequence should be added to somewhere */
2617 mLayers.add((ExynosLayer*)layer);
2618
2619 /* TODO : Set z-order to max, check outLayer address? */
2620 layer->setLayerZOrder(1000);
2621
2622 *outLayer = (hwc2_layer_t)layer;
2623 setGeometryChanged(GEOMETRY_DISPLAY_LAYER_ADDED);
2624
2625 return HWC2_ERROR_NONE;
2626 }
2627
getActiveConfig(hwc2_config_t * outConfig)2628 int32_t ExynosDisplay::getActiveConfig(hwc2_config_t* outConfig)
2629 {
2630 Mutex::Autolock lock(mDisplayMutex);
2631 return getActiveConfigInternal(outConfig);
2632 }
2633
getActiveConfigInternal(hwc2_config_t * outConfig)2634 int32_t ExynosDisplay::getActiveConfigInternal(hwc2_config_t* outConfig)
2635 {
2636 *outConfig = mActiveConfig;
2637
2638 return HWC2_ERROR_NONE;
2639 }
2640
getLayerCompositionTypeForValidationType(uint32_t layerIndex)2641 int32_t ExynosDisplay::getLayerCompositionTypeForValidationType(uint32_t layerIndex)
2642 {
2643 int32_t type = -1;
2644
2645 if (layerIndex >= mLayers.size())
2646 {
2647 DISPLAY_LOGE("invalid layer index (%d)", layerIndex);
2648 return type;
2649 }
2650 if ((mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_CLIENT) &&
2651 (mClientCompositionInfo.mSkipFlag) &&
2652 (mClientCompositionInfo.mFirstIndex <= (int32_t)layerIndex) &&
2653 ((int32_t)layerIndex <= mClientCompositionInfo.mLastIndex)) {
2654 type = HWC2_COMPOSITION_DEVICE;
2655 } else if (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
2656 type = HWC2_COMPOSITION_DEVICE;
2657 } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_CURSOR) &&
2658 (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
2659 if (mDisplayControl.cursorSupport == true)
2660 type = HWC2_COMPOSITION_CURSOR;
2661 else
2662 type = HWC2_COMPOSITION_DEVICE;
2663 } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_SOLID_COLOR) &&
2664 (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
2665 type = HWC2_COMPOSITION_SOLID_COLOR;
2666 } else {
2667 type = mLayers[layerIndex]->mValidateCompositionType;
2668 }
2669
2670 return type;
2671 }
2672
getChangedCompositionTypes(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outTypes)2673 int32_t ExynosDisplay::getChangedCompositionTypes(
2674 uint32_t* outNumElements, hwc2_layer_t* outLayers,
2675 int32_t* /*hwc2_composition_t*/ outTypes) {
2676
2677 if (mRenderingState != RENDERING_STATE_VALIDATED) {
2678 DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
2679 return HWC2_ERROR_NOT_VALIDATED;
2680 }
2681
2682 uint32_t count = 0;
2683
2684 auto set_out_param = [](ExynosLayer *layer, int32_t type, uint32_t &count, uint32_t num,
2685 hwc2_layer_t *out_layers, int32_t *out_types) -> int32_t {
2686 if (type == layer->mCompositionType) {
2687 return 0;
2688 }
2689 if (out_layers == NULL || out_types == NULL) {
2690 count++;
2691 } else {
2692 if (count < num) {
2693 out_layers[count] = (hwc2_layer_t)layer;
2694 out_types[count] = type;
2695 count++;
2696 } else {
2697 return -1;
2698 }
2699 }
2700 return 0;
2701 };
2702
2703 int32_t ret = 0;
2704 for (size_t i = 0; i < mLayers.size(); i++) {
2705 DISPLAY_LOGD(eDebugHWC, "[%zu] layer: mCompositionType(%d), mValidateCompositionType(%d), mExynosCompositionType(%d), skipFlag(%d)",
2706 i, mLayers[i]->mCompositionType, mLayers[i]->mValidateCompositionType,
2707 mLayers[i]->mExynosCompositionType, mClientCompositionInfo.mSkipFlag);
2708 if ((ret = set_out_param(mLayers[i], getLayerCompositionTypeForValidationType(i), count,
2709 *outNumElements, outLayers, outTypes)) < 0) {
2710 break;
2711 }
2712 }
2713 if (ret == 0) {
2714 for (size_t i = 0; i < mIgnoreLayers.size(); i++) {
2715 DISPLAY_LOGD(eDebugHWC,
2716 "[%zu] ignore layer: mCompositionType(%d), mValidateCompositionType(%d)",
2717 i, mIgnoreLayers[i]->mCompositionType,
2718 mIgnoreLayers[i]->mValidateCompositionType);
2719 if ((ret = set_out_param(mIgnoreLayers[i], mIgnoreLayers[i]->mValidateCompositionType,
2720 count, *outNumElements, outLayers, outTypes)) < 0) {
2721 break;
2722 }
2723 }
2724 }
2725 if (ret < 0) {
2726 DISPLAY_LOGE("array size is not valid (%d, %d)", count, *outNumElements);
2727 String8 errString;
2728 errString.appendFormat("array size is not valid (%d, %d)", count, *outNumElements);
2729 printDebugInfos(errString);
2730 return ret;
2731 }
2732
2733 if ((outLayers == NULL) || (outTypes == NULL))
2734 *outNumElements = count;
2735
2736 return HWC2_ERROR_NONE;
2737 }
2738
getClientTargetSupport(uint32_t width,uint32_t height,int32_t format,int32_t dataspace)2739 int32_t ExynosDisplay::getClientTargetSupport(uint32_t width, uint32_t height,
2740 int32_t /*android_pixel_format_t*/ format,
2741 int32_t /*android_dataspace_t*/ dataspace)
2742 {
2743 if (width != mXres)
2744 return HWC2_ERROR_UNSUPPORTED;
2745 if (height != mYres)
2746 return HWC2_ERROR_UNSUPPORTED;
2747 if (format != HAL_PIXEL_FORMAT_RGBA_8888)
2748 return HWC2_ERROR_UNSUPPORTED;
2749 if ((dataspace != HAL_DATASPACE_UNKNOWN) &&
2750 (!mDisplayInterface->supportDataspace(dataspace)))
2751 return HWC2_ERROR_UNSUPPORTED;
2752
2753 return HWC2_ERROR_NONE;
2754 }
2755
getColorModes(uint32_t * outNumModes,int32_t * outModes)2756 int32_t ExynosDisplay::getColorModes(uint32_t *outNumModes, int32_t * /*android_color_mode_t*/ outModes)
2757 {
2758 return mDisplayInterface->getColorModes(outNumModes, outModes);
2759 }
2760
getDisplayAttribute(hwc2_config_t config,int32_t attribute,int32_t * outValue)2761 int32_t ExynosDisplay::getDisplayAttribute(
2762 hwc2_config_t config,
2763 int32_t /*hwc2_attribute_t*/ attribute, int32_t* outValue) {
2764
2765 switch (attribute) {
2766 case HWC2_ATTRIBUTE_VSYNC_PERIOD:
2767 *outValue = mDisplayConfigs[config].vsyncPeriod;
2768 break;
2769
2770 case HWC2_ATTRIBUTE_WIDTH:
2771 *outValue = mDisplayConfigs[config].width;
2772 break;
2773
2774 case HWC2_ATTRIBUTE_HEIGHT:
2775 *outValue = mDisplayConfigs[config].height;
2776 break;
2777
2778 case HWC2_ATTRIBUTE_DPI_X:
2779 *outValue = mDisplayConfigs[config].Xdpi;
2780 break;
2781
2782 case HWC2_ATTRIBUTE_DPI_Y:
2783 *outValue = mDisplayConfigs[config].Ydpi;
2784 break;
2785
2786 case HWC2_ATTRIBUTE_CONFIG_GROUP:
2787 *outValue = mDisplayConfigs[config].groupId;
2788 break;
2789
2790 default:
2791 ALOGE("unknown display attribute %u", attribute);
2792 return HWC2_ERROR_BAD_CONFIG;
2793 }
2794
2795 return HWC2_ERROR_NONE;
2796 }
2797
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)2798 int32_t ExynosDisplay::getDisplayConfigs(
2799 uint32_t* outNumConfigs,
2800 hwc2_config_t* outConfigs) {
2801 return mDisplayInterface->getDisplayConfigs(outNumConfigs, outConfigs);
2802 }
2803
getDisplayName(uint32_t * outSize,char * outName)2804 int32_t ExynosDisplay::getDisplayName(uint32_t* outSize, char* outName)
2805 {
2806 if (outName == NULL) {
2807 *outSize = mDisplayName.size();
2808 return HWC2_ERROR_NONE;
2809 }
2810
2811 uint32_t strSize = mDisplayName.size();
2812 if (*outSize < strSize) {
2813 DISPLAY_LOGE("Invalide outSize(%d), mDisplayName.size(%d)",
2814 *outSize, strSize);
2815 strSize = *outSize;
2816 }
2817 std::strncpy(outName, mDisplayName, strSize);
2818 *outSize = strSize;
2819
2820 return HWC2_ERROR_NONE;
2821 }
2822
getDisplayRequests(int32_t * outDisplayRequests,uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outLayerRequests)2823 int32_t ExynosDisplay::getDisplayRequests(
2824 int32_t* /*hwc2_display_request_t*/ outDisplayRequests,
2825 uint32_t* outNumElements, hwc2_layer_t* outLayers,
2826 int32_t* /*hwc2_layer_request_t*/ outLayerRequests) {
2827 /*
2828 * This function doesn't check mRenderingState
2829 * This can be called in the below rendering state
2830 * RENDERING_STATE_PRESENTED: when it is called by canSkipValidate()
2831 * RENDERING_STATE_ACCEPTED_CHANGE: when it is called by SF
2832 * RENDERING_STATE_VALIDATED: when it is called by validateDisplay()
2833 */
2834
2835 String8 errString;
2836 *outDisplayRequests = 0;
2837
2838 uint32_t requestNum = 0;
2839 if (mClientCompositionInfo.mHasCompositionLayer == true) {
2840 if ((mClientCompositionInfo.mFirstIndex < 0) ||
2841 (mClientCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
2842 (mClientCompositionInfo.mLastIndex < 0) ||
2843 (mClientCompositionInfo.mLastIndex >= (int)mLayers.size())) {
2844 errString.appendFormat("%s:: mClientCompositionInfo.mHasCompositionLayer is true "
2845 "but index is not valid (firstIndex: %d, lastIndex: %d)\n",
2846 __func__, mClientCompositionInfo.mFirstIndex,
2847 mClientCompositionInfo.mLastIndex);
2848 goto err;
2849 }
2850
2851 for (int32_t i = mClientCompositionInfo.mFirstIndex; i < mClientCompositionInfo.mLastIndex; i++) {
2852 ExynosLayer *layer = mLayers[i];
2853 if (layer->mOverlayPriority >= ePriorityHigh) {
2854 if ((outLayers != NULL) && (outLayerRequests != NULL)) {
2855 if (requestNum >= *outNumElements)
2856 return -1;
2857 outLayers[requestNum] = (hwc2_layer_t)layer;
2858 outLayerRequests[requestNum] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET;
2859 }
2860 requestNum++;
2861 }
2862 }
2863 }
2864 if ((outLayers == NULL) || (outLayerRequests == NULL))
2865 *outNumElements = requestNum;
2866
2867 return HWC2_ERROR_NONE;
2868
2869 err:
2870 printDebugInfos(errString);
2871 *outNumElements = 0;
2872 mDisplayInterface->setForcePanic();
2873 return -EINVAL;
2874 }
2875
getDisplayType(int32_t * outType)2876 int32_t ExynosDisplay::getDisplayType(
2877 int32_t* /*hwc2_display_type_t*/ outType) {
2878 switch (mType) {
2879 case HWC_DISPLAY_PRIMARY:
2880 case HWC_DISPLAY_EXTERNAL:
2881 *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
2882 return HWC2_ERROR_NONE;
2883 case HWC_DISPLAY_VIRTUAL:
2884 *outType = HWC2_DISPLAY_TYPE_VIRTUAL;
2885 return HWC2_ERROR_NONE;
2886 default:
2887 DISPLAY_LOGE("Invalid display type(%d)", mType);
2888 *outType = HWC2_DISPLAY_TYPE_INVALID;
2889 return HWC2_ERROR_NONE;
2890 }
2891 }
2892
getDozeSupport(int32_t * outSupport)2893 int32_t ExynosDisplay::getDozeSupport(
2894 int32_t* outSupport) {
2895 if (mDisplayInterface->isDozeModeAvailable()) {
2896 *outSupport = 1;
2897 } else {
2898 *outSupport = 0;
2899 }
2900
2901 return 0;
2902 }
2903
getReleaseFences(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outFences)2904 int32_t ExynosDisplay::getReleaseFences(
2905 uint32_t* outNumElements,
2906 hwc2_layer_t* outLayers, int32_t* outFences) {
2907
2908 Mutex::Autolock lock(mDisplayMutex);
2909 if (outLayers == NULL || outFences == NULL)
2910 {
2911 uint32_t deviceLayerNum = 0;
2912 deviceLayerNum = mLayers.size() + mIgnoreLayers.size();
2913 *outNumElements = deviceLayerNum;
2914 } else {
2915 uint32_t deviceLayerNum = 0;
2916 for (size_t i = 0; i < mLayers.size(); i++) {
2917 outLayers[deviceLayerNum] = (hwc2_layer_t)mLayers[i];
2918 outFences[deviceLayerNum] = mLayers[i]->mReleaseFence;
2919 /*
2920 * layer's release fence will be closed by caller of this function.
2921 * HWC should not close this fence after this function is returned.
2922 */
2923 mLayers[i]->mReleaseFence = -1;
2924
2925 DISPLAY_LOGD(eDebugHWC, "[%zu] layer deviceLayerNum(%d), release fence: %d", i, deviceLayerNum, outFences[deviceLayerNum]);
2926 deviceLayerNum++;
2927
2928 if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) {
2929 setFenceName(mLayers[i]->mReleaseFence, FENCE_LAYER_RELEASE_DPP);
2930 } else if (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CLIENT) {
2931 setFenceName(mLayers[i]->mReleaseFence, FENCE_LAYER_RELEASE_DPP);
2932 } else {
2933 setFenceName(mLayers[i]->mReleaseFence, FENCE_LAYER_RELEASE_DPP);
2934 }
2935 }
2936 for (size_t i = 0; i < mIgnoreLayers.size(); i++) {
2937 outLayers[deviceLayerNum] = (hwc2_layer_t)mIgnoreLayers[i];
2938 outFences[deviceLayerNum] = -1;
2939
2940 DISPLAY_LOGD(eDebugHWC, "[%zu] ignore layer deviceLayerNum(%d), release fence: -1", i,
2941 deviceLayerNum);
2942 deviceLayerNum++;
2943 }
2944 }
2945 return 0;
2946 }
2947
canSkipValidate()2948 int32_t ExynosDisplay::canSkipValidate() {
2949 if (exynosHWCControl.skipResourceAssign == 0)
2950 return SKIP_ERR_CONFIG_DISABLED;
2951
2952 /* This is first frame. validateDisplay can't be skipped */
2953 if (mRenderingState == RENDERING_STATE_NONE)
2954 return SKIP_ERR_FIRST_FRAME;
2955
2956 if (mDevice->mGeometryChanged != 0) {
2957 /* validateDisplay() should be called */
2958 return SKIP_ERR_GEOMETRY_CHAGNED;
2959 } else {
2960 for (uint32_t i = 0; i < mLayers.size(); i++) {
2961 if (getLayerCompositionTypeForValidationType(i) ==
2962 HWC2_COMPOSITION_CLIENT) {
2963 return SKIP_ERR_HAS_CLIENT_COMP;
2964 }
2965 }
2966
2967 if ((mClientCompositionInfo.mSkipStaticInitFlag == true) &&
2968 (mClientCompositionInfo.mSkipFlag == true)) {
2969 if (skipStaticLayerChanged(mClientCompositionInfo) == true)
2970 return SKIP_ERR_SKIP_STATIC_CHANGED;
2971 }
2972
2973 if (mClientCompositionInfo.mHasCompositionLayer &&
2974 mClientCompositionInfo.mTargetBuffer == NULL) {
2975 return SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER;
2976 }
2977
2978 /*
2979 * If there is hwc2_layer_request_t
2980 * validateDisplay() can't be skipped
2981 */
2982 int32_t displayRequests = 0;
2983 uint32_t outNumRequests = 0;
2984 if ((getDisplayRequests(&displayRequests, &outNumRequests, NULL, NULL) != NO_ERROR) ||
2985 (outNumRequests != 0))
2986 return SKIP_ERR_HAS_REQUEST;
2987 }
2988 return NO_ERROR;
2989 }
2990
presentDisplay(int32_t * outRetireFence)2991 int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
2992
2993 ATRACE_CALL();
2994 gettimeofday(&updateTimeInfo.lastPresentTime, NULL);
2995
2996 int ret = HWC2_ERROR_NONE;
2997 String8 errString;
2998 thread_local bool setTaskProfileDone = false;
2999
3000 if (setTaskProfileDone == false) {
3001 if (!SetTaskProfiles(gettid(), {"SFMainPolicy"})) {
3002 ALOGW("Failed to add `%d` into SFMainPolicy", gettid());
3003 }
3004 setTaskProfileDone = true;
3005 }
3006
3007 Mutex::Autolock lock(mDisplayMutex);
3008
3009 if (mPauseDisplay || mDevice->isInTUI()) {
3010 closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3011 *outRetireFence = -1;
3012 mRenderingState = RENDERING_STATE_PRESENTED;
3013 return ret;
3014 }
3015
3016 /*
3017 * buffer handle, dataspace were set by setClientTarget() after validateDisplay
3018 * ExynosImage should be set again according to changed handle and dataspace
3019 */
3020 exynos_image src_img;
3021 exynos_image dst_img;
3022 setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
3023 mClientCompositionInfo.setExynosImage(src_img, dst_img);
3024 mClientCompositionInfo.setExynosMidImage(dst_img);
3025
3026 funcReturnCallback presentRetCallback([&]() {
3027 if (ret != HWC2_ERROR_NOT_VALIDATED)
3028 presentPostProcessing();
3029 });
3030
3031 if (mSkipFrame) {
3032 ALOGI("[%d] presentDisplay is skipped by mSkipFrame", mDisplayId);
3033 closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3034 setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE);
3035 *outRetireFence = -1;
3036 for (size_t i=0; i < mLayers.size(); i++) {
3037 mLayers[i]->mReleaseFence = -1;
3038 }
3039 if (mRenderingState == RENDERING_STATE_NONE) {
3040 ALOGD("\tThis is the first frame after power on");
3041 ret = HWC2_ERROR_NONE;
3042 } else {
3043 ALOGD("\tThis is the second frame after power on");
3044 ret = HWC2_ERROR_NOT_VALIDATED;
3045 }
3046 mRenderingState = RENDERING_STATE_PRESENTED;
3047 mDevice->invalidate();
3048 return ret;
3049 }
3050
3051 if (mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE) {
3052 /*
3053 * presentDisplay() can be called before validateDisplay()
3054 * when HWC2_CAPABILITY_SKIP_VALIDATE is supported
3055 */
3056 #ifndef HWC_SKIP_VALIDATE
3057 DISPLAY_LOGE("%s:: Skip validate is not supported. Invalid rendering state : %d", __func__, mRenderingState);
3058 goto err;
3059 #endif
3060 if ((mRenderingState != RENDERING_STATE_NONE) &&
3061 (mRenderingState != RENDERING_STATE_PRESENTED)) {
3062 DISPLAY_LOGE("%s:: invalid rendering state : %d", __func__, mRenderingState);
3063 goto err;
3064 }
3065
3066 if (mDevice->canSkipValidate() == false)
3067 goto not_validated;
3068 else {
3069 // Reset current frame flags for Fence Tracer
3070 resetFenceCurFlag(this);
3071 for (size_t i=0; i < mLayers.size(); i++) {
3072 // Layer's acquire fence from SF
3073 mLayers[i]->setSrcAcquireFence();
3074 }
3075 DISPLAY_LOGD(eDebugSkipValidate, "validate is skipped");
3076 }
3077
3078 updateBrightnessState();
3079
3080 if (updateColorConversionInfo() != NO_ERROR) {
3081 ALOGE("%s:: updateColorConversionInfo() fail, ret(%d)",
3082 __func__, ret);
3083 }
3084 if (mDisplayControl.earlyStartMPP == true) {
3085 /*
3086 * HWC should update performanceInfo when validate is skipped
3087 * HWC excludes the layer from performance calculation
3088 * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
3089 * Therefore performanceInfo should be calculated again if the buffer is updated.
3090 */
3091 if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
3092 DISPLAY_LOGE("deliverPerformanceInfo() error (%d) in validateSkip case", ret);
3093 }
3094 startPostProcessing();
3095 }
3096 }
3097
3098 mDpuData.reset();
3099
3100 if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
3101 if ((ret = doDisplayConfigPostProcess(mDevice)) != NO_ERROR) {
3102 DISPLAY_LOGE("doDisplayConfigPostProcess error (%d)", ret);
3103 }
3104 }
3105
3106 if (updatePresentColorConversionInfo() != NO_ERROR) {
3107 ALOGE("%s:: updatePresentColorConversionInfo() fail, ret(%d)",
3108 __func__, ret);
3109 }
3110
3111 if ((mLayers.size() == 0) &&
3112 (mType != HWC_DISPLAY_VIRTUAL)) {
3113 clearDisplay();
3114 *outRetireFence = -1;
3115 mLastRetireFence = fence_close(mLastRetireFence, this,
3116 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3117 mRenderingState = RENDERING_STATE_PRESENTED;
3118 ret = 0;
3119 return ret;
3120 }
3121
3122 if (!checkFrameValidation()) {
3123 clearDisplay();
3124 *outRetireFence = -1;
3125 mLastRetireFence = fence_close(mLastRetireFence, this,
3126 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3127 mRenderingState = RENDERING_STATE_PRESENTED;
3128 return ret;
3129 }
3130
3131 if ((mDisplayControl.earlyStartMPP == false) &&
3132 ((ret = doExynosComposition()) != NO_ERROR)) {
3133 errString.appendFormat("exynosComposition fail (%d)\n", ret);
3134 goto err;
3135 }
3136
3137 // loop for all layer
3138 for (size_t i=0; i < mLayers.size(); i++) {
3139 /* mAcquireFence is updated, Update image info */
3140 struct exynos_image srcImg, dstImg, midImg;
3141 mLayers[i]->setSrcExynosImage(&srcImg);
3142 mLayers[i]->setDstExynosImage(&dstImg);
3143 mLayers[i]->setExynosImage(srcImg, dstImg);
3144
3145 if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
3146 mLayers[i]->mReleaseFence = -1;
3147 mLayers[i]->mAcquireFence =
3148 fence_close(mLayers[i]->mAcquireFence, this,
3149 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3150 } else if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) {
3151 continue;
3152 } else {
3153 if (mLayers[i]->mOtfMPP != NULL) {
3154 mLayers[i]->mOtfMPP->requestHWStateChange(MPP_HW_STATE_RUNNING);
3155 }
3156
3157 if ((mDisplayControl.earlyStartMPP == false) &&
3158 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
3159 (mLayers[i]->mM2mMPP != NULL)) {
3160 ExynosMPP *m2mMpp = mLayers[i]->mM2mMPP;
3161 srcImg = mLayers[i]->mSrcImg;
3162 midImg = mLayers[i]->mMidImg;
3163 m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
3164 if ((ret = m2mMpp->doPostProcessing(srcImg, midImg)) != NO_ERROR) {
3165 HWC_LOGE(this, "%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
3166 __func__, i, ret);
3167 errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
3168 __func__, i, ret);
3169 goto err;
3170 } else {
3171 /* This should be closed by lib for each resource */
3172 mLayers[i]->mAcquireFence = -1;
3173 }
3174 }
3175 }
3176 }
3177
3178 if ((ret = setWinConfigData()) != NO_ERROR) {
3179 errString.appendFormat("setWinConfigData fail (%d)\n", ret);
3180 goto err;
3181 }
3182
3183 if ((ret = handleStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
3184 mClientCompositionInfo.mSkipStaticInitFlag = false;
3185 errString.appendFormat("handleStaticLayers error\n");
3186 goto err;
3187 }
3188
3189 if (mGeometryChanged != 0 || !skipSignalIdleForVideoLayer()) {
3190 mPowerHalHint.signalIdle();
3191 }
3192
3193 handleWindowUpdate();
3194
3195 setDisplayWinConfigData();
3196
3197 if ((ret = deliverWinConfigData()) != NO_ERROR) {
3198 HWC_LOGE(this, "%s:: fail to deliver win_config (%d)", __func__, ret);
3199 if (mDpuData.retire_fence > 0)
3200 fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3201 mDpuData.retire_fence = -1;
3202 }
3203
3204 setReleaseFences();
3205
3206 if (mDpuData.retire_fence != -1) {
3207 #ifdef DISABLE_FENCE
3208 if (mDpuData.retire_fence >= 0)
3209 fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3210 *outRetireFence = -1;
3211 #else
3212 *outRetireFence =
3213 hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, mDpuData.retire_fence);
3214 #endif
3215 setFenceInfo(mDpuData.retire_fence, this,
3216 FENCE_TYPE_RETIRE, FENCE_IP_LAYER, FENCE_TO);
3217 } else
3218 *outRetireFence = -1;
3219
3220 /* Update last retire fence */
3221 mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3222 mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3223 setFenceName(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_DUP, true);
3224 setFenceName(mLastRetireFence, FENCE_RETIRE);
3225
3226 increaseMPPDstBufIndex();
3227
3228 /* Check all of acquireFence are closed */
3229 for (size_t i=0; i < mLayers.size(); i++) {
3230 if (mLayers[i]->mAcquireFence != -1) {
3231 DISPLAY_LOGE("layer[%zu] fence(%d) type(%d, %d, %d) is not closed",
3232 i, mLayers[i]->mAcquireFence,
3233 mLayers[i]->mCompositionType,
3234 mLayers[i]->mExynosCompositionType,
3235 mLayers[i]->mValidateCompositionType);
3236 if (mLayers[i]->mM2mMPP != NULL)
3237 DISPLAY_LOGE("\t%s is assigned", mLayers[i]->mM2mMPP->mName.string());
3238 if (mLayers[i]->mAcquireFence > 0)
3239 fence_close(mLayers[i]->mAcquireFence, this,
3240 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3241 mLayers[i]->mAcquireFence = -1;
3242 }
3243 }
3244 if (mExynosCompositionInfo.mAcquireFence >= 0) {
3245 DISPLAY_LOGE("mExynosCompositionInfo mAcquireFence(%d) is not initialized", mExynosCompositionInfo.mAcquireFence);
3246 fence_close(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
3247 mExynosCompositionInfo.mAcquireFence = -1;
3248 }
3249 if (mClientCompositionInfo.mAcquireFence >= 0) {
3250 DISPLAY_LOGE("mClientCompositionInfo mAcquireFence(%d) is not initialized", mClientCompositionInfo.mAcquireFence);
3251 fence_close(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
3252 mClientCompositionInfo.mAcquireFence = -1;
3253 }
3254
3255 /* All of release fences are tranferred */
3256 for (size_t i=0; i < mLayers.size(); i++) {
3257 setFenceInfo(mLayers[i]->mReleaseFence, this,
3258 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO);
3259 }
3260
3261 doPostProcessing();
3262
3263 if (!mDevice->validateFences(this)){
3264 String8 errString;
3265 errString.appendFormat("%s:: validate fence failed. \n", __func__);
3266 printDebugInfos(errString);
3267 }
3268
3269 mDpuData.reset();
3270
3271 mRenderingState = RENDERING_STATE_PRESENTED;
3272
3273 if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3274 /* Do not update mVsyncPeriod */
3275 updateInternalDisplayConfigVariables(mDesiredConfig, false);
3276 }
3277
3278 return ret;
3279 err:
3280 printDebugInfos(errString);
3281 closeFences();
3282 *outRetireFence = -1;
3283 mLastRetireFence = -1;
3284 mRenderingState = RENDERING_STATE_PRESENTED;
3285 setGeometryChanged(GEOMETRY_ERROR_CASE);
3286
3287 mLastDpuData.reset();
3288
3289 mClientCompositionInfo.mSkipStaticInitFlag = false;
3290 mExynosCompositionInfo.mSkipStaticInitFlag = false;
3291
3292 mDpuData.reset();
3293
3294 if (!mDevice->validateFences(this)){
3295 errString.appendFormat("%s:: validate fence failed. \n", __func__);
3296 printDebugInfos(errString);
3297 }
3298 mDisplayInterface->setForcePanic();
3299
3300 mBrightnessState.reset();
3301
3302 ret = -EINVAL;
3303 return ret;
3304
3305 not_validated:
3306 DISPLAY_LOGD(eDebugSkipValidate, "display need validate");
3307 mRenderingState = RENDERING_STATE_NONE;
3308 ret = HWC2_ERROR_NOT_VALIDATED;
3309 return ret;
3310 }
3311
presentPostProcessing()3312 int32_t ExynosDisplay::presentPostProcessing()
3313 {
3314 setReadbackBufferInternal(NULL, -1, false);
3315 if (mDpuData.enable_readback)
3316 mDevice->signalReadbackDone();
3317 mDpuData.enable_readback = false;
3318
3319 for (auto it : mIgnoreLayers) {
3320 /*
3321 * Directly close without counting down
3322 * because it was not counted by validate
3323 */
3324 if (it->mAcquireFence > 0) {
3325 close(it->mAcquireFence);
3326 }
3327 it->mAcquireFence = -1;
3328 }
3329 return NO_ERROR;
3330 }
3331
setActiveConfig(hwc2_config_t config)3332 int32_t ExynosDisplay::setActiveConfig(hwc2_config_t config)
3333 {
3334 Mutex::Autolock lock(mDisplayMutex);
3335 DISPLAY_LOGD(eDebugDisplayConfig, "%s:: config(%d)", __func__, config);
3336 return setActiveConfigInternal(config, false);
3337 }
3338
setActiveConfigInternal(hwc2_config_t config,bool force)3339 int32_t ExynosDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
3340 if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
3341
3342 if (!force && needNotChangeConfig(config)) {
3343 ALOGI("skip same config %d (force %d)", config, force);
3344 return HWC2_ERROR_NONE;
3345 }
3346
3347 DISPLAY_LOGD(eDebugDisplayConfig, "(current %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", mActiveConfig,
3348 mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
3349 DISPLAY_LOGD(eDebugDisplayConfig, "(requested %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", config,
3350 mDisplayConfigs[config].width, mDisplayConfigs[config].height, mDisplayConfigs[config].vsyncPeriod,
3351 mDisplayConfigs[config].Xdpi, mDisplayConfigs[config].Ydpi);
3352
3353 if (mDisplayInterface->setActiveConfig(config) < 0) {
3354 ALOGE("%s bad config request", __func__);
3355 return HWC2_ERROR_BAD_CONFIG;
3356 }
3357
3358 updateInternalDisplayConfigVariables(config);
3359 return HWC2_ERROR_NONE;
3360 }
3361
setClientTarget(buffer_handle_t target,int32_t acquireFence,int32_t dataspace)3362 int32_t ExynosDisplay::setClientTarget(
3363 buffer_handle_t target,
3364 int32_t acquireFence, int32_t /*android_dataspace_t*/ dataspace) {
3365 buffer_handle_t handle = NULL;
3366 if (target != NULL)
3367 handle = target;
3368
3369 #ifdef DISABLE_FENCE
3370 if (acquireFence >= 0)
3371 fence_close(acquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
3372 acquireFence = -1;
3373 #endif
3374 acquireFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, acquireFence);
3375 if (handle == NULL) {
3376 DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget is NULL, skipStaic (%d)",
3377 mClientCompositionInfo.mSkipFlag);
3378 if (mClientCompositionInfo.mSkipFlag == false) {
3379 DISPLAY_LOGE("ClientTarget is NULL");
3380 DISPLAY_LOGE("\t%s:: mRenderingState(%d)",__func__, mRenderingState);
3381 }
3382 } else {
3383 VendorGraphicBufferMeta gmeta(handle);
3384
3385 DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget handle: %p [fd: %d, %d, %d]",
3386 handle, gmeta.fd, gmeta.fd1, gmeta.fd2);
3387 if ((mClientCompositionInfo.mSkipFlag == true) &&
3388 ((mClientCompositionInfo.mLastWinConfigData.fd_idma[0] != gmeta.fd) ||
3389 (mClientCompositionInfo.mLastWinConfigData.fd_idma[1] != gmeta.fd1) ||
3390 (mClientCompositionInfo.mLastWinConfigData.fd_idma[2] != gmeta.fd2))) {
3391 String8 errString;
3392 DISPLAY_LOGE("skip flag is enabled but buffer is updated lastConfig[%d, %d, %d], handle[%d, %d, %d]\n",
3393 mClientCompositionInfo.mLastWinConfigData.fd_idma[0],
3394 mClientCompositionInfo.mLastWinConfigData.fd_idma[1],
3395 mClientCompositionInfo.mLastWinConfigData.fd_idma[2],
3396 gmeta.fd, gmeta.fd1, gmeta.fd2);
3397 DISPLAY_LOGE("last win config");
3398 for (size_t i = 0; i < mLastDpuData.configs.size(); i++) {
3399 errString.appendFormat("config[%zu]\n", i);
3400 dumpConfig(errString, mLastDpuData.configs[i]);
3401 DISPLAY_LOGE("\t%s", errString.string());
3402 errString.clear();
3403 }
3404 errString.appendFormat("%s:: skip flag is enabled but buffer is updated\n",
3405 __func__);
3406 printDebugInfos(errString);
3407 }
3408 }
3409 mClientCompositionInfo.setTargetBuffer(this, handle, acquireFence, (android_dataspace)dataspace);
3410 setFenceInfo(acquireFence, this,
3411 FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, FENCE_FROM);
3412
3413 if (handle) {
3414 mClientCompositionInfo.mCompressed = isAFBCCompressed(handle);
3415 }
3416
3417 return 0;
3418 }
3419
setColorTransform(const float * matrix,int32_t hint)3420 int32_t ExynosDisplay::setColorTransform(
3421 const float* matrix,
3422 int32_t /*android_color_transform_t*/ hint) {
3423 if ((hint < HAL_COLOR_TRANSFORM_IDENTITY) ||
3424 (hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA))
3425 return HWC2_ERROR_BAD_PARAMETER;
3426 ALOGI("%s:: %d, %d", __func__, mColorTransformHint, hint);
3427 if (mColorTransformHint != hint)
3428 setGeometryChanged(GEOMETRY_DISPLAY_COLOR_TRANSFORM_CHANGED);
3429 mColorTransformHint = hint;
3430 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
3431 int ret = mDisplayInterface->setColorTransform(matrix, hint);
3432 if (ret < 0)
3433 mColorTransformHint = ret;
3434 return ret;
3435 #else
3436 return HWC2_ERROR_NONE;
3437 #endif
3438 }
3439
setColorMode(int32_t mode)3440 int32_t ExynosDisplay::setColorMode(int32_t /*android_color_mode_t*/ mode)
3441 {
3442 if (mDisplayInterface->setColorMode(mode) < 0) {
3443 if (mode == HAL_COLOR_MODE_NATIVE)
3444 return HWC2_ERROR_NONE;
3445
3446 ALOGE("%s:: is not supported", __func__);
3447 return HWC2_ERROR_UNSUPPORTED;
3448 }
3449
3450 ALOGI("%s:: %d, %d", __func__, mColorMode, mode);
3451 if (mColorMode != mode)
3452 setGeometryChanged(GEOMETRY_DISPLAY_COLOR_MODE_CHANGED);
3453 mColorMode = (android_color_mode_t)mode;
3454 return HWC2_ERROR_NONE;
3455 }
3456
getRenderIntents(int32_t mode,uint32_t * outNumIntents,int32_t * outIntents)3457 int32_t ExynosDisplay::getRenderIntents(int32_t mode, uint32_t* outNumIntents,
3458 int32_t* /*android_render_intent_v1_1_t*/ outIntents)
3459 {
3460 ALOGI("%s:: mode(%d), outNum(%d), outIntents(%p)",
3461 __func__, mode, *outNumIntents, outIntents);
3462
3463 return mDisplayInterface->getRenderIntents(mode, outNumIntents, outIntents);
3464 }
3465
setColorModeWithRenderIntent(int32_t mode,int32_t intent)3466 int32_t ExynosDisplay::setColorModeWithRenderIntent(int32_t /*android_color_mode_t*/ mode,
3467 int32_t /*android_render_intent_v1_1_t */ intent)
3468 {
3469 ALOGI("%s:: mode(%d), intent(%d)", __func__, mode, intent);
3470
3471 return mDisplayInterface->setColorModeWithRenderIntent(mode, intent);
3472 }
3473
getDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)3474 int32_t ExynosDisplay::getDisplayIdentificationData(uint8_t* outPort,
3475 uint32_t* outDataSize, uint8_t* outData)
3476 {
3477 return mDisplayInterface->getDisplayIdentificationData(outPort, outDataSize, outData);
3478 }
3479
getDisplayCapabilities(uint32_t * outNumCapabilities,uint32_t * outCapabilities)3480 int32_t ExynosDisplay::getDisplayCapabilities(uint32_t* outNumCapabilities,
3481 uint32_t* outCapabilities)
3482 {
3483 /* If each display has their own capabilities,
3484 * this should be described in display module codes */
3485
3486 uint32_t capabilityNum = 0;
3487 if (mBrightnessFd != NULL)
3488 capabilityNum++;
3489
3490 if (mDisplayInterface->isDozeModeAvailable()) {
3491 capabilityNum++;
3492 }
3493
3494 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
3495 capabilityNum++;
3496 #endif
3497
3498 if (outCapabilities == NULL) {
3499 *outNumCapabilities = capabilityNum;
3500 return HWC2_ERROR_NONE;
3501 }
3502 if (capabilityNum != *outNumCapabilities) {
3503 ALOGE("%s:: invalid outNumCapabilities(%d), should be(%d)", __func__, *outNumCapabilities, capabilityNum);
3504 return HWC2_ERROR_BAD_PARAMETER;
3505 }
3506
3507 uint32_t index = 0;
3508 if (mBrightnessFd != NULL)
3509 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
3510
3511 if (mDisplayInterface->isDozeModeAvailable()) {
3512 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
3513 }
3514
3515 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
3516 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
3517 #endif
3518
3519 return HWC2_ERROR_NONE;
3520 }
3521
getDisplayBrightnessSupport(bool * outSupport)3522 int32_t ExynosDisplay::getDisplayBrightnessSupport(bool* outSupport)
3523 {
3524 if (mBrightnessFd == NULL) {
3525 *outSupport = false;
3526 } else {
3527 *outSupport = true;
3528 }
3529
3530 return HWC2_ERROR_NONE;
3531 }
3532
setDisplayBrightness(float brightness)3533 int32_t ExynosDisplay::setDisplayBrightness(float brightness)
3534 {
3535 if (mBrightnessFd == NULL)
3536 return HWC2_ERROR_UNSUPPORTED;
3537
3538 mBrightnessState.brightness_value = brightness;
3539 int32_t ret = mDisplayInterface->updateBrightness(false /* syncFrame */);
3540
3541 if (ret == HWC2_ERROR_NONE) return ret;
3542
3543 if (ret != HWC2_ERROR_UNSUPPORTED) {
3544 ALOGE("Fail to update brightness, ret(%d), brightness =%f", ret, brightness);
3545 return ret;
3546 }
3547
3548 char val[MAX_BRIGHTNESS_LEN]= {0};
3549 uint32_t scaledBrightness = static_cast<uint32_t>(round(brightness * mMaxBrightness));
3550
3551 if ((ret = snprintf(val, MAX_BRIGHTNESS_LEN, "%d", scaledBrightness)) > 0) {
3552 fwrite(val, sizeof(val), 1, mBrightnessFd);
3553 if (ferror(mBrightnessFd)){
3554 ALOGE("brightness write failed");
3555 clearerr(mBrightnessFd);
3556 }
3557 rewind(mBrightnessFd);
3558 } else {
3559 ALOGE("Fail to set brightness, ret(%d), brightness(%f, %d)",
3560 ret, brightness, scaledBrightness);
3561 }
3562
3563 return HWC2_ERROR_NONE;
3564 }
3565
getDisplayConnectionType(uint32_t * outType)3566 int32_t ExynosDisplay::getDisplayConnectionType(uint32_t* outType)
3567 {
3568 if (mType == HWC_DISPLAY_PRIMARY)
3569 *outType = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL;
3570 else if (mType == HWC_DISPLAY_EXTERNAL)
3571 *outType = HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL;
3572 else
3573 return HWC2_ERROR_BAD_DISPLAY;
3574
3575 return HWC2_ERROR_NONE;
3576 }
3577
getDisplayVsyncPeriod(hwc2_vsync_period_t * __unused outVsyncPeriod)3578 int32_t ExynosDisplay::getDisplayVsyncPeriod(hwc2_vsync_period_t* __unused outVsyncPeriod)
3579 {
3580 Mutex::Autolock lock(mDisplayMutex);
3581 return getDisplayVsyncPeriodInternal(outVsyncPeriod);
3582 }
3583
getConfigAppliedTime(const uint64_t desiredTime,const uint64_t actualChangeTime,int64_t & appliedTime,int64_t & refreshTime)3584 int32_t ExynosDisplay::getConfigAppliedTime(const uint64_t desiredTime,
3585 const uint64_t actualChangeTime,
3586 int64_t &appliedTime, int64_t &refreshTime)
3587 {
3588 uint32_t transientDuration = mDisplayInterface->getConfigChangeDuration();
3589 appliedTime = actualChangeTime;
3590
3591 if (desiredTime > appliedTime) {
3592 const int64_t originalAppliedTime = appliedTime;
3593 const int64_t diff = desiredTime - appliedTime;
3594 appliedTime += (diff + mVsyncPeriod - 1) / mVsyncPeriod * mVsyncPeriod;
3595 DISPLAY_LOGD(eDebugDisplayConfig,
3596 "desired time(%" PRId64 "), applied time(%" PRId64 "->%" PRId64 ")",
3597 desiredTime, originalAppliedTime, appliedTime);
3598 } else {
3599 DISPLAY_LOGD(eDebugDisplayConfig, "desired time(%" PRId64 "), applied time(%" PRId64 ")",
3600 desiredTime, appliedTime);
3601 }
3602
3603 refreshTime = appliedTime - (transientDuration * mVsyncPeriod);
3604
3605 return NO_ERROR;
3606 }
3607
calculateTimeline(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)3608 void ExynosDisplay::calculateTimeline(
3609 hwc2_config_t config, hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
3610 hwc_vsync_period_change_timeline_t *outTimeline) {
3611 int64_t actualChangeTime = 0;
3612 /* actualChangeTime includes transient duration */
3613 mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
3614
3615 outTimeline->refreshRequired = true;
3616 getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
3617 outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
3618
3619 DISPLAY_LOGD(eDebugDisplayConfig,
3620 "requested config : %d(%d)->%d(%d), "
3621 "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
3622 mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
3623 mDisplayConfigs[config].vsyncPeriod,
3624 mVsyncPeriodChangeConstraints.desiredTimeNanos,
3625 outTimeline->newVsyncAppliedTimeNanos);
3626 }
3627
setActiveConfigWithConstraints(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)3628 int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
3629 hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
3630 hwc_vsync_period_change_timeline_t* outTimeline)
3631 {
3632 ATRACE_CALL();
3633 Mutex::Autolock lock(mDisplayMutex);
3634
3635 DISPLAY_LOGD(eDebugDisplayConfig,
3636 "config(%d), seamless(%d), "
3637 "desiredTime(%" PRId64 ")",
3638 config, vsyncPeriodChangeConstraints->seamlessRequired,
3639 vsyncPeriodChangeConstraints->desiredTimeNanos);
3640
3641 if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
3642
3643 if (needNotChangeConfig(config)) {
3644 outTimeline->refreshRequired = false;
3645 outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
3646 return HWC2_ERROR_NONE;
3647 }
3648
3649 if (vsyncPeriodChangeConstraints->seamlessRequired) {
3650 if (mDisplayConfigs[mActiveConfig].groupId != mDisplayConfigs[config].groupId) {
3651 DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not allowed");
3652 return HWC2_ERROR_SEAMLESS_NOT_ALLOWED;
3653 }
3654 if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
3655 DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not possible");
3656 return HWC2_ERROR_SEAMLESS_NOT_POSSIBLE;
3657 }
3658 }
3659
3660 DISPLAY_LOGD(eDebugDisplayConfig, "%s : %dx%d, %dms, %d Xdpi, %d Ydpi", __func__,
3661 mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
3662
3663 if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3664 DISPLAY_LOGI("%s, previous request config is processing", __func__);
3665 }
3666 /* Config would be requested on present time */
3667 mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING;
3668 mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
3669 mDesiredConfig = config;
3670
3671 calculateTimeline(config, vsyncPeriodChangeConstraints, outTimeline);
3672
3673 /* mActiveConfig should be changed immediately for internal status */
3674 mActiveConfig = config;
3675 mVsyncAppliedTimeLine = *outTimeline;
3676 uint32_t vsync_period = getDisplayVsyncPeriodFromConfig(config);
3677 updateBtsVsyncPeriod(vsync_period);
3678
3679 bool earlyWakeupNeeded = checkRrCompensationEnabled();
3680 if (earlyWakeupNeeded && mEarlyWakeupFd != NULL) {
3681 char val = '1';
3682 fwrite(&val, sizeof(val), 1, mEarlyWakeupFd);
3683 if (ferror(mEarlyWakeupFd)){
3684 ALOGE("early wakup fd write failed");
3685 clearerr(mEarlyWakeupFd);
3686 }
3687 rewind(mEarlyWakeupFd);
3688 }
3689
3690 return HWC2_ERROR_NONE;
3691 }
3692
setAutoLowLatencyMode(bool __unused on)3693 int32_t ExynosDisplay::setAutoLowLatencyMode(bool __unused on)
3694 {
3695 return HWC2_ERROR_UNSUPPORTED;
3696 }
3697
getSupportedContentTypes(uint32_t * __unused outNumSupportedContentTypes,uint32_t * __unused outSupportedContentTypes)3698 int32_t ExynosDisplay::getSupportedContentTypes(uint32_t* __unused outNumSupportedContentTypes,
3699 uint32_t* __unused outSupportedContentTypes)
3700 {
3701 if (outSupportedContentTypes == NULL)
3702 outNumSupportedContentTypes = 0;
3703 return HWC2_ERROR_NONE;
3704 }
3705
setContentType(int32_t contentType)3706 int32_t ExynosDisplay::setContentType(int32_t /* hwc2_content_type_t */ contentType)
3707 {
3708 if (contentType == HWC2_CONTENT_TYPE_NONE)
3709 return HWC2_ERROR_NONE;
3710
3711 return HWC2_ERROR_UNSUPPORTED;
3712 }
3713
getClientTargetProperty(hwc_client_target_property_t * outClientTargetProperty)3714 int32_t ExynosDisplay::getClientTargetProperty(hwc_client_target_property_t* outClientTargetProperty)
3715 {
3716 outClientTargetProperty->pixelFormat = HAL_PIXEL_FORMAT_RGBA_8888;
3717 outClientTargetProperty->dataspace = HAL_DATASPACE_UNKNOWN;
3718 return HWC2_ERROR_NONE;
3719 }
3720
isBadConfig(hwc2_config_t config)3721 bool ExynosDisplay::isBadConfig(hwc2_config_t config)
3722 {
3723 /* Check invalid config */
3724 const auto its = mDisplayConfigs.find(config);
3725 if (its == mDisplayConfigs.end()) {
3726 DISPLAY_LOGE("%s, invalid config : %d", __func__, config);
3727 return true;
3728 }
3729
3730 return false;
3731 }
3732
needNotChangeConfig(hwc2_config_t config)3733 bool ExynosDisplay::needNotChangeConfig(hwc2_config_t config)
3734 {
3735 /* getting current config and compare */
3736 /* If same value, return */
3737 if (mActiveConfig == config) {
3738 DISPLAY_LOGI("%s, Same config change requested : %d", __func__, config);
3739 return true;
3740 }
3741
3742 return false;
3743 }
3744
updateInternalDisplayConfigVariables(hwc2_config_t config,bool updateVsync)3745 int32_t ExynosDisplay::updateInternalDisplayConfigVariables(
3746 hwc2_config_t config, bool updateVsync)
3747 {
3748 mActiveConfig = config;
3749
3750 /* Update internal variables */
3751 getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_WIDTH, (int32_t*)&mXres);
3752 getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_HEIGHT, (int32_t*)&mYres);
3753 getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_X, (int32_t*)&mXdpi);
3754 getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_Y, (int32_t*)&mYdpi);
3755 mHdrFullScrenAreaThreshold = mXres * mYres * kHdrFullScreen;
3756 if (updateVsync) {
3757 mVsyncPeriod = getDisplayVsyncPeriodFromConfig(mActiveConfig);
3758 updateBtsVsyncPeriod(mVsyncPeriod, true);
3759 }
3760
3761 return NO_ERROR;
3762 }
3763
updateBtsVsyncPeriod(uint32_t vsyncPeriod,bool forceUpdate)3764 void ExynosDisplay::updateBtsVsyncPeriod(uint32_t vsyncPeriod, bool forceUpdate) {
3765 if (vsyncPeriod < mBtsVsyncPeriod) {
3766 mBtsVsyncPeriod = vsyncPeriod;
3767
3768 if (mType == HWC_DISPLAY_PRIMARY) {
3769 uint32_t btsRefreshRate = getBtsRefreshRate();
3770
3771 for (size_t i = 0; i < mLayers.size(); i++) {
3772 if (!mLayers[i]->checkDownscaleCap(btsRefreshRate)) {
3773 setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
3774 break;
3775 }
3776 }
3777 }
3778 } else if (forceUpdate) {
3779 /* TODO: add check for resource can re-assign to Device */
3780 mBtsVsyncPeriod = vsyncPeriod;
3781 }
3782 }
3783
getBtsRefreshRate() const3784 uint32_t ExynosDisplay::getBtsRefreshRate() const {
3785 return static_cast<uint32_t>(round(nsecsPerSec / mBtsVsyncPeriod * 0.1f) * 10);
3786 }
3787
updateRefreshRateHint()3788 void ExynosDisplay::updateRefreshRateHint() {
3789 if (mVsyncPeriod) {
3790 mPowerHalHint.signalRefreshRate(mPowerModeState, mVsyncPeriod);
3791 }
3792 }
3793
3794 /* This function must be called within a mDisplayMutex protection */
resetConfigRequestStateLocked()3795 int32_t ExynosDisplay::resetConfigRequestStateLocked() {
3796 mVsyncPeriod = getDisplayVsyncPeriodFromConfig(mActiveConfig);
3797 updateBtsVsyncPeriod(mVsyncPeriod, true);
3798 DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by mActiveConfig(%d)", mVsyncPeriod,
3799 mActiveConfig);
3800
3801 updateRefreshRateHint();
3802
3803 if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3804 DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
3805 mConfigRequestState);
3806 } else {
3807 DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to NONE",
3808 __func__, mConfigRequestState);
3809 mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_NONE;
3810 updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
3811 }
3812 return NO_ERROR;
3813 }
3814
updateConfigRequestAppliedTime()3815 int32_t ExynosDisplay::updateConfigRequestAppliedTime()
3816 {
3817 if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED)
3818 return NO_ERROR;
3819
3820 /*
3821 * config change was requested but
3822 * it is not applied until newVsyncAppliedTimeNanos
3823 * Update time information
3824 */
3825 int64_t actualChangeTime = 0;
3826 mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
3827 return updateVsyncAppliedTimeLine(actualChangeTime);
3828 }
3829
updateVsyncAppliedTimeLine(int64_t actualChangeTime)3830 int32_t ExynosDisplay::updateVsyncAppliedTimeLine(int64_t actualChangeTime)
3831 {
3832 ExynosDevice *dev = mDevice;
3833 hwc2_callback_data_t vsync_callbackData = nullptr;
3834 HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED vsync_callbackFunc = nullptr;
3835 if (dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer != NULL) {
3836 vsync_callbackData =
3837 dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData;
3838 vsync_callbackFunc =
3839 (HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED)dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer;
3840 }
3841
3842 DISPLAY_LOGD(eDebugDisplayConfig,"Vsync applied time is changed (%" PRId64 "-> %" PRId64 ")",
3843 mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
3844 actualChangeTime);
3845 getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos,
3846 actualChangeTime,
3847 mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
3848 mVsyncAppliedTimeLine.refreshTimeNanos);
3849 if (mConfigRequestState ==
3850 hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3851 mVsyncAppliedTimeLine.refreshRequired = false;
3852 } else {
3853 mVsyncAppliedTimeLine.refreshRequired = true;
3854 }
3855
3856 DISPLAY_LOGD(eDebugDisplayConfig,"refresh required(%d), newVsyncAppliedTimeNanos (%" PRId64 ")",
3857 mVsyncAppliedTimeLine.refreshRequired,
3858 mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos);
3859
3860 if (vsync_callbackFunc != nullptr)
3861 vsync_callbackFunc(vsync_callbackData, getId(),
3862 &mVsyncAppliedTimeLine);
3863 else {
3864 ALOGD("callback function is null");
3865 }
3866
3867 return NO_ERROR;
3868 }
3869
getDisplayVsyncPeriodInternal(hwc2_vsync_period_t * outVsyncPeriod)3870 int32_t ExynosDisplay::getDisplayVsyncPeriodInternal(hwc2_vsync_period_t* outVsyncPeriod)
3871 {
3872 /* Getting actual config from DPU */
3873 if (mDisplayInterface->getDisplayVsyncPeriod(outVsyncPeriod) == HWC2_ERROR_NONE) {
3874 DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period : %ld",
3875 (long)*outVsyncPeriod);
3876 } else {
3877 *outVsyncPeriod = mVsyncPeriod;
3878 DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period is mVsyncPeriod: %d",
3879 mVsyncPeriod);
3880 }
3881 return HWC2_ERROR_NONE;
3882 }
3883
doDisplayConfigInternal(hwc2_config_t config)3884 int32_t ExynosDisplay::doDisplayConfigInternal(hwc2_config_t config) {
3885 return mDisplayInterface->setActiveConfigWithConstraints(config);
3886 }
3887
doDisplayConfigPostProcess(ExynosDevice * dev)3888 int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
3889 {
3890 uint64_t current = systemTime(SYSTEM_TIME_MONOTONIC);
3891
3892 int64_t actualChangeTime = 0;
3893 mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
3894 bool needSetActiveConfig = false;
3895
3896 DISPLAY_LOGD(eDebugDisplayConfig,
3897 "Check time for setActiveConfig (curr: %" PRId64
3898 ", actualChangeTime: %" PRId64 ", desiredTime: %" PRId64 "",
3899 current, actualChangeTime,
3900 mVsyncPeriodChangeConstraints.desiredTimeNanos);
3901 if (actualChangeTime >= mVsyncPeriodChangeConstraints.desiredTimeNanos) {
3902 DISPLAY_LOGD(eDebugDisplayConfig, "Request setActiveConfig");
3903 needSetActiveConfig = true;
3904 ATRACE_INT("Pending ActiveConfig", 0);
3905 } else {
3906 DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending");
3907 ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
3908 }
3909
3910 if (needSetActiveConfig) {
3911 int32_t ret = NO_ERROR;
3912 if ((ret = doDisplayConfigInternal(mDesiredConfig)) != NO_ERROR) {
3913 return ret;
3914 }
3915
3916 mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_REQUESTED;
3917 }
3918
3919 return updateVsyncAppliedTimeLine(actualChangeTime);
3920 }
3921
setOutputBuffer(buffer_handle_t __unused buffer,int32_t __unused releaseFence)3922 int32_t ExynosDisplay::setOutputBuffer( buffer_handle_t __unused buffer, int32_t __unused releaseFence)
3923 {
3924 return HWC2_ERROR_NONE;
3925 }
3926
clearDisplay(bool needModeClear)3927 int ExynosDisplay::clearDisplay(bool needModeClear) {
3928
3929 const int ret = mDisplayInterface->clearDisplay(needModeClear);
3930 if (ret)
3931 DISPLAY_LOGE("fail to clear display");
3932
3933 mClientCompositionInfo.mSkipStaticInitFlag = false;
3934 mClientCompositionInfo.mSkipFlag = false;
3935
3936 mLastDpuData.reset();
3937
3938 /* Update last retire fence */
3939 mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3940
3941 mBrightnessState.reset();
3942 return ret;
3943 }
3944
setPowerMode(int32_t mode)3945 int32_t ExynosDisplay::setPowerMode(
3946 int32_t /*hwc2_power_mode_t*/ mode) {
3947 Mutex::Autolock lock(mDisplayMutex);
3948
3949 if (!mDisplayInterface->isDozeModeAvailable() &&
3950 (mode == HWC2_POWER_MODE_DOZE || mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
3951 return HWC2_ERROR_UNSUPPORTED;
3952 }
3953
3954 if (mode == HWC_POWER_MODE_OFF) {
3955 mDevice->mPrimaryBlank = true;
3956 clearDisplay(true);
3957 ALOGV("HWC2: Clear display (power off)");
3958 } else {
3959 mDevice->mPrimaryBlank = false;
3960 }
3961
3962 if (mode == HWC_POWER_MODE_OFF)
3963 mDREnable = false;
3964 else
3965 mDREnable = mDRDefault;
3966
3967 // check the dynamic recomposition thread by following display power status;
3968 mDevice->checkDynamicRecompositionThread();
3969
3970
3971 /* TODO: Call display interface */
3972 mDisplayInterface->setPowerMode(mode);
3973
3974 ALOGD("%s:: mode(%d))", __func__, mode);
3975
3976 mPowerModeState = (hwc2_power_mode_t)mode;
3977
3978 if (mode == HWC_POWER_MODE_OFF) {
3979 /* It should be called from validate() when the screen is on */
3980 mSkipFrame = true;
3981 setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
3982 if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
3983 (mRenderingState < RENDERING_STATE_PRESENTED))
3984 closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
3985 mRenderingState = RENDERING_STATE_NONE;
3986 } else {
3987 setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
3988 }
3989
3990 return HWC2_ERROR_NONE;
3991 }
3992
setVsyncEnabled(int32_t enabled)3993 int32_t ExynosDisplay::setVsyncEnabled(
3994 int32_t /*hwc2_vsync_t*/ enabled) {
3995 Mutex::Autolock lock(mDisplayMutex);
3996 return setVsyncEnabledInternal(enabled);
3997 }
3998
setVsyncEnabledInternal(int32_t enabled)3999 int32_t ExynosDisplay::setVsyncEnabledInternal(
4000 int32_t enabled) {
4001
4002 uint32_t val = 0;
4003
4004 if (enabled < 0 || enabled > HWC2_VSYNC_DISABLE)
4005 return HWC2_ERROR_BAD_PARAMETER;
4006
4007
4008 if (enabled == HWC2_VSYNC_ENABLE) {
4009 gettimeofday(&updateTimeInfo.lastEnableVsyncTime, NULL);
4010 val = 1;
4011 if (mVsyncState != HWC2_VSYNC_ENABLE) {
4012 /* TODO: remove it once driver can handle on its own */
4013 setWakeupDisplay();
4014 }
4015 } else {
4016 gettimeofday(&updateTimeInfo.lastDisableVsyncTime, NULL);
4017 }
4018
4019 if (mDisplayInterface->setVsyncEnabled(val) < 0) {
4020 HWC_LOGE(this, "vsync ioctl failed errno : %d", errno);
4021 return HWC2_ERROR_BAD_DISPLAY;
4022 }
4023
4024 mVsyncState = (hwc2_vsync_t)enabled;
4025
4026 return HWC2_ERROR_NONE;
4027 }
4028
validateDisplay(uint32_t * outNumTypes,uint32_t * outNumRequests)4029 int32_t ExynosDisplay::validateDisplay(
4030 uint32_t* outNumTypes, uint32_t* outNumRequests) {
4031
4032 ATRACE_CALL();
4033 gettimeofday(&updateTimeInfo.lastValidateTime, NULL);
4034 Mutex::Autolock lock(mDisplayMutex);
4035
4036 if (mPauseDisplay)
4037 return HWC2_ERROR_NONE;
4038
4039 int ret = NO_ERROR;
4040 bool validateError = false;
4041 mUpdateEventCnt++;
4042 mUpdateCallCnt++;
4043 mLastUpdateTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
4044
4045 checkIgnoreLayers();
4046 if (mLayers.size() == 0)
4047 DISPLAY_LOGI("%s:: validateDisplay layer size is 0", __func__);
4048 else
4049 mLayers.vector_sort();
4050
4051 // Reset current frame flags for Fence Tracer
4052 resetFenceCurFlag(this);
4053
4054 for (size_t i = 0; i < mLayers.size(); i++) mLayers[i]->setSrcAcquireFence();
4055
4056 doPreProcessing();
4057 checkLayerFps();
4058 if (exynosHWCControl.useDynamicRecomp == true && mDREnable)
4059 checkDynamicReCompMode();
4060
4061 if (exynosHWCControl.useDynamicRecomp == true &&
4062 mDevice->isDynamicRecompositionThreadAlive() == false &&
4063 mDevice->mDRLoopStatus == false) {
4064 mDevice->dynamicRecompositionThreadCreate();
4065 }
4066
4067 if ((ret = mResourceManager->assignResource(this)) != NO_ERROR) {
4068 validateError = true;
4069 HWC_LOGE(this, "%s:: assignResource() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4070 String8 errString;
4071 errString.appendFormat("%s:: assignResource() fail, display(%d), ret(%d)\n",
4072 __func__, mDisplayId, ret);
4073 printDebugInfos(errString);
4074 mDisplayInterface->setForcePanic();
4075 }
4076
4077 updateBrightnessState();
4078
4079 if ((ret = updateColorConversionInfo()) != NO_ERROR) {
4080 validateError = true;
4081 DISPLAY_LOGE("%s:: updateColorConversionInfo() fail, ret(%d)",
4082 __func__, ret);
4083 }
4084
4085 if ((ret = skipStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
4086 validateError = true;
4087 HWC_LOGE(this, "%s:: skipStaticLayers() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4088 } else {
4089 if ((mClientCompositionInfo.mHasCompositionLayer) &&
4090 (mClientCompositionInfo.mSkipFlag == false)) {
4091 /* Initialize compositionType */
4092 for (size_t i = (size_t)mClientCompositionInfo.mFirstIndex; i <= (size_t)mClientCompositionInfo.mLastIndex; i++) {
4093 if (mLayers[i]->mOverlayPriority >= ePriorityHigh)
4094 continue;
4095 mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4096 }
4097 }
4098 }
4099
4100 mRenderingState = RENDERING_STATE_VALIDATED;
4101
4102 /*
4103 * HWC should update performanceInfo even if assignResource is skipped
4104 * HWC excludes the layer from performance calculation
4105 * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
4106 * Therefore performanceInfo should be calculated again if only the buffer is updated.
4107 */
4108 if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
4109 HWC_LOGE(NULL,"%s:: deliverPerformanceInfo() error (%d)",
4110 __func__, ret);
4111 }
4112
4113 if ((validateError == false) && (mDisplayControl.earlyStartMPP == true)) {
4114 if ((ret = startPostProcessing()) != NO_ERROR)
4115 validateError = true;
4116 }
4117
4118 if (validateError) {
4119 setGeometryChanged(GEOMETRY_ERROR_CASE);
4120 mClientCompositionInfo.mSkipStaticInitFlag = false;
4121 mExynosCompositionInfo.mSkipStaticInitFlag = false;
4122 mResourceManager->resetAssignedResources(this, true);
4123 mClientCompositionInfo.initializeInfos(this);
4124 mExynosCompositionInfo.initializeInfos(this);
4125 for (uint32_t i = 0; i < mLayers.size(); i++) {
4126 ExynosLayer *layer = mLayers[i];
4127 layer->mOverlayInfo |= eResourceAssignFail;
4128 layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4129 addClientCompositionLayer(i);
4130 }
4131 mResourceManager->assignCompositionTarget(this, COMPOSITION_CLIENT);
4132 mResourceManager->assignWindow(this);
4133 }
4134
4135 int32_t displayRequests = 0;
4136 if ((ret = getChangedCompositionTypes(outNumTypes, NULL, NULL)) != NO_ERROR) {
4137 HWC_LOGE(this, "%s:: getChangedCompositionTypes() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4138 setGeometryChanged(GEOMETRY_ERROR_CASE);
4139 }
4140 if ((ret = getDisplayRequests(&displayRequests, outNumRequests, NULL, NULL)) != NO_ERROR) {
4141 HWC_LOGE(this, "%s:: getDisplayRequests() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4142 setGeometryChanged(GEOMETRY_ERROR_CASE);
4143 }
4144
4145 mSkipFrame = false;
4146
4147 if ((*outNumTypes == 0) && (*outNumRequests == 0))
4148 return HWC2_ERROR_NONE;
4149
4150 return HWC2_ERROR_HAS_CHANGES;
4151 }
4152
startPostProcessing()4153 int32_t ExynosDisplay::startPostProcessing()
4154 {
4155 int ret = NO_ERROR;
4156 String8 errString;
4157
4158 float assignedCapacity = mResourceManager->getAssignedCapacity(MPP_G2D);
4159
4160 if (assignedCapacity > (mResourceManager->getM2MCapa(MPP_G2D) * MPP_CAPA_OVER_THRESHOLD)) {
4161 errString.appendFormat("Assigned capacity for exynos composition is over restriction (%f)",
4162 assignedCapacity);
4163 goto err;
4164 }
4165
4166 if ((ret = doExynosComposition()) != NO_ERROR) {
4167 errString.appendFormat("exynosComposition fail (%d)\n", ret);
4168 goto err;
4169 }
4170
4171 // loop for all layer
4172 for (size_t i=0; i < mLayers.size(); i++) {
4173 if((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
4174 (mLayers[i]->mM2mMPP != NULL)) {
4175 /* mAcquireFence is updated, Update image info */
4176 struct exynos_image srcImg, dstImg, midImg;
4177 mLayers[i]->setSrcExynosImage(&srcImg);
4178 mLayers[i]->setDstExynosImage(&dstImg);
4179 mLayers[i]->setExynosImage(srcImg, dstImg);
4180 ExynosMPP *m2mMpp = mLayers[i]->mM2mMPP;
4181 srcImg = mLayers[i]->mSrcImg;
4182 midImg = mLayers[i]->mMidImg;
4183 m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
4184 if ((ret = m2mMpp->doPostProcessing(srcImg, midImg)) != NO_ERROR) {
4185 DISPLAY_LOGE("%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
4186 __func__, i, ret);
4187 errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
4188 __func__, i, ret);
4189 goto err;
4190 } else {
4191 /* This should be closed by lib for each resource */
4192 mLayers[i]->mAcquireFence = -1;
4193 }
4194 }
4195 }
4196 return ret;
4197 err:
4198 printDebugInfos(errString);
4199 closeFences();
4200 mDisplayInterface->setForcePanic();
4201 return -EINVAL;
4202 }
4203
setCursorPositionAsync(uint32_t x_pos,uint32_t y_pos)4204 int32_t ExynosDisplay::setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos) {
4205 mDisplayInterface->setCursorPositionAsync(x_pos, y_pos);
4206 return HWC2_ERROR_NONE;
4207 }
4208
dumpConfig(const exynos_win_config_data & c)4209 void ExynosDisplay::dumpConfig(const exynos_win_config_data &c)
4210 {
4211 DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\tstate = %u", c.state);
4212 if (c.state == c.WIN_STATE_COLOR) {
4213 DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer,
4214 "\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
4215 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
4216 } else/* if (c.state != c.WIN_STATE_DISABLED) */{
4217 DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
4218 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
4219 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
4220 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
4221 "protection = %u, compression = %d, compression_src = %d, transparent(x:%d, y:%d, w:%d, h:%d), "
4222 "block(x:%d, y:%d, w:%d, h:%d)",
4223 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
4224 c.acq_fence, c.rel_fence,
4225 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
4226 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
4227 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable,
4228 c.blending, c.protection, c.compression, c.comp_src,
4229 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
4230 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
4231 }
4232 }
4233
dump(String8 & result)4234 void ExynosDisplay::dump(String8& result)
4235 {
4236 Mutex::Autolock lock(mDisplayMutex);
4237 result.appendFormat("[%s] display information size: %d x %d, vsyncState: %d, colorMode: %d, colorTransformHint: %d\n",
4238 mDisplayName.string(),
4239 mXres, mYres, mVsyncState, mColorMode, mColorTransformHint);
4240 mClientCompositionInfo.dump(result);
4241 mExynosCompositionInfo.dump(result);
4242
4243 result.appendFormat("PanelGammaSource (%d)\n\n", GetCurrentPanelGammaSource());
4244
4245 if (mLayers.size()) {
4246 result.appendFormat("============================== dump layers ===========================================\n");
4247 for (uint32_t i = 0; i < mLayers.size(); i++) {
4248 ExynosLayer *layer = mLayers[i];
4249 layer->dump(result);
4250 }
4251 }
4252 if (mIgnoreLayers.size()) {
4253 result.appendFormat("\n============================== dump ignore layers ===========================================\n");
4254 for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
4255 ExynosLayer *layer = mIgnoreLayers[i];
4256 layer->dump(result);
4257 }
4258 }
4259 result.appendFormat("\n");
4260 }
4261
dumpConfig(String8 & result,const exynos_win_config_data & c)4262 void ExynosDisplay::dumpConfig(String8 &result, const exynos_win_config_data &c)
4263 {
4264 result.appendFormat("\tstate = %u\n", c.state);
4265 if (c.state == c.WIN_STATE_COLOR) {
4266 result.appendFormat("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
4267 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
4268 } else/* if (c.state != c.WIN_STATE_DISABLED) */{
4269 result.appendFormat("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
4270 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
4271 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
4272 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
4273 "protection = %u, compression = %d, compression_src = %d, transparent(x:%d, y:%d, w:%d, h:%d), "
4274 "block(x:%d, y:%d, w:%d, h:%d)\n",
4275 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
4276 c.acq_fence, c.rel_fence,
4277 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
4278 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
4279 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
4280 c.compression, c.comp_src,
4281 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
4282 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
4283 }
4284 }
4285
printConfig(exynos_win_config_data & c)4286 void ExynosDisplay::printConfig(exynos_win_config_data &c)
4287 {
4288 ALOGD("\tstate = %u", c.state);
4289 if (c.state == c.WIN_STATE_COLOR) {
4290 ALOGD("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
4291 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
4292 } else/* if (c.state != c.WIN_STATE_DISABLED) */{
4293 ALOGD("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
4294 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
4295 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
4296 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
4297 "protection = %u, compression = %d, compression_src = %d, transparent(x:%d, y:%d, w:%d, h:%d), "
4298 "block(x:%d, y:%d, w:%d, h:%d)",
4299 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
4300 c.acq_fence, c.rel_fence,
4301 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
4302 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
4303 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
4304 c.compression, c.comp_src,
4305 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
4306 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
4307 }
4308 }
4309
setCompositionTargetExynosImage(uint32_t targetType,exynos_image * src_img,exynos_image * dst_img)4310 int32_t ExynosDisplay::setCompositionTargetExynosImage(uint32_t targetType, exynos_image *src_img, exynos_image *dst_img)
4311 {
4312 ExynosCompositionInfo compositionInfo;
4313
4314 if (targetType == COMPOSITION_CLIENT)
4315 compositionInfo = mClientCompositionInfo;
4316 else if (targetType == COMPOSITION_EXYNOS)
4317 compositionInfo = mExynosCompositionInfo;
4318 else
4319 return -EINVAL;
4320
4321 src_img->fullWidth = mXres;
4322 src_img->fullHeight = mYres;
4323 /* To do */
4324 /* Fb crop should be set hear */
4325 src_img->x = 0;
4326 src_img->y = 0;
4327 src_img->w = mXres;
4328 src_img->h = mYres;
4329
4330 if (compositionInfo.mTargetBuffer != NULL) {
4331 src_img->bufferHandle = compositionInfo.mTargetBuffer;
4332
4333 VendorGraphicBufferMeta gmeta(compositionInfo.mTargetBuffer);
4334 src_img->format = gmeta.format;
4335 src_img->usageFlags = gmeta.producer_usage;
4336 } else {
4337 src_img->bufferHandle = NULL;
4338 src_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
4339 src_img->usageFlags = 0;
4340 }
4341 src_img->layerFlags = 0x0;
4342 src_img->acquireFenceFd = compositionInfo.mAcquireFence;
4343 src_img->releaseFenceFd = -1;
4344 src_img->dataSpace = compositionInfo.mDataSpace;
4345 src_img->blending = HWC2_BLEND_MODE_PREMULTIPLIED;
4346 src_img->transform = 0;
4347 src_img->compressed = compositionInfo.mCompressed;
4348 src_img->planeAlpha = 1;
4349 src_img->zOrder = 0;
4350 if ((targetType == COMPOSITION_CLIENT) && (mType == HWC_DISPLAY_VIRTUAL)) {
4351 if (compositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)
4352 src_img->zOrder = 0;
4353 else
4354 src_img->zOrder = 1000;
4355 }
4356
4357 dst_img->fullWidth = mXres;
4358 dst_img->fullHeight = mYres;
4359 /* To do */
4360 /* Fb crop should be set hear */
4361 dst_img->x = 0;
4362 dst_img->y = 0;
4363 dst_img->w = mXres;
4364 dst_img->h = mYres;
4365
4366 dst_img->bufferHandle = NULL;
4367 dst_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
4368 dst_img->usageFlags = 0;
4369
4370 dst_img->layerFlags = 0x0;
4371 dst_img->acquireFenceFd = -1;
4372 dst_img->releaseFenceFd = -1;
4373 dst_img->dataSpace = src_img->dataSpace;
4374 if (mColorMode != HAL_COLOR_MODE_NATIVE)
4375 dst_img->dataSpace = colorModeToDataspace(mColorMode);
4376 dst_img->blending = HWC2_BLEND_MODE_NONE;
4377 dst_img->transform = 0;
4378 dst_img->compressed = compositionInfo.mCompressed;
4379 dst_img->planeAlpha = 1;
4380 dst_img->zOrder = src_img->zOrder;
4381
4382 return NO_ERROR;
4383 }
4384
initializeValidateInfos()4385 int32_t ExynosDisplay::initializeValidateInfos()
4386 {
4387 mCursorIndex = -1;
4388 for (uint32_t i = 0; i < mLayers.size(); i++) {
4389 ExynosLayer *layer = mLayers[i];
4390 layer->mValidateCompositionType = HWC2_COMPOSITION_INVALID;
4391 layer->mOverlayInfo = 0;
4392 if ((mDisplayControl.cursorSupport == true) &&
4393 (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CURSOR))
4394 mCursorIndex = i;
4395 }
4396
4397 exynos_image src_img;
4398 exynos_image dst_img;
4399
4400 mClientCompositionInfo.initializeInfos(this);
4401 setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
4402 mClientCompositionInfo.setExynosImage(src_img, dst_img);
4403
4404 mExynosCompositionInfo.initializeInfos(this);
4405 setCompositionTargetExynosImage(COMPOSITION_EXYNOS, &src_img, &dst_img);
4406 mExynosCompositionInfo.setExynosImage(src_img, dst_img);
4407
4408 return NO_ERROR;
4409 }
4410
addClientCompositionLayer(uint32_t layerIndex)4411 int32_t ExynosDisplay::addClientCompositionLayer(uint32_t layerIndex)
4412 {
4413 bool exynosCompositionChanged = false;
4414 int32_t ret = NO_ERROR;
4415
4416 DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to client composition", layerIndex);
4417
4418 if (mClientCompositionInfo.mHasCompositionLayer == false) {
4419 mClientCompositionInfo.mFirstIndex = layerIndex;
4420 mClientCompositionInfo.mLastIndex = layerIndex;
4421 mClientCompositionInfo.mHasCompositionLayer = true;
4422 return EXYNOS_ERROR_CHANGED;
4423 } else {
4424 mClientCompositionInfo.mFirstIndex = min(mClientCompositionInfo.mFirstIndex, (int32_t)layerIndex);
4425 mClientCompositionInfo.mLastIndex = max(mClientCompositionInfo.mLastIndex, (int32_t)layerIndex);
4426 }
4427 DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
4428 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
4429
4430 if ((mClientCompositionInfo.mFirstIndex < 0) || (mClientCompositionInfo.mLastIndex < 0))
4431 {
4432 HWC_LOGE(this, "%s:: mClientCompositionInfo.mHasCompositionLayer is true "
4433 "but index is not valid (firstIndex: %d, lastIndex: %d)",
4434 __func__, mClientCompositionInfo.mFirstIndex,
4435 mClientCompositionInfo.mLastIndex);
4436 return -EINVAL;
4437 }
4438
4439 /* handle sandwiched layers */
4440 for (uint32_t i = (uint32_t)mClientCompositionInfo.mFirstIndex + 1; i < (uint32_t)mClientCompositionInfo.mLastIndex; i++) {
4441 ExynosLayer *layer = mLayers[i];
4442 if (layer->mOverlayPriority >= ePriorityHigh) {
4443 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high or max priority (%d)", i, layer->mOverlayPriority);
4444 continue;
4445 }
4446 if (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT)
4447 {
4448 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
4449 if (layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS)
4450 exynosCompositionChanged = true;
4451 else {
4452 if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
4453 }
4454 layer->resetAssignedResource();
4455 layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4456 layer->mOverlayInfo |= eSandwitchedBetweenGLES;
4457 }
4458 }
4459
4460 /* Check Exynos Composition info is changed */
4461 if (exynosCompositionChanged) {
4462 DISPLAY_LOGD(eDebugResourceManager, "exynos composition [%d] - [%d] is changed",
4463 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
4464 uint32_t newFirstIndex = ~0;
4465 int32_t newLastIndex = -1;
4466
4467 if ((mExynosCompositionInfo.mFirstIndex < 0) || (mExynosCompositionInfo.mLastIndex < 0))
4468 {
4469 HWC_LOGE(this, "%s:: mExynosCompositionInfo.mHasCompositionLayer should be true(%d) "
4470 "but index is not valid (firstIndex: %d, lastIndex: %d)",
4471 __func__, mExynosCompositionInfo.mHasCompositionLayer,
4472 mExynosCompositionInfo.mFirstIndex,
4473 mExynosCompositionInfo.mLastIndex);
4474 return -EINVAL;
4475 }
4476
4477 for (uint32_t i = 0; i < mLayers.size(); i++)
4478 {
4479 ExynosLayer *exynosLayer = mLayers[i];
4480 if (exynosLayer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
4481 newFirstIndex = min(newFirstIndex, i);
4482 newLastIndex = max(newLastIndex, (int32_t)i);
4483 }
4484 }
4485
4486 DISPLAY_LOGD(eDebugResourceManager, "changed exynos composition [%d] - [%d]",
4487 newFirstIndex, newLastIndex);
4488
4489 /* There is no exynos composition layer */
4490 if (newFirstIndex == (uint32_t)~0)
4491 {
4492 mExynosCompositionInfo.initializeInfos(this);
4493 ret = EXYNOS_ERROR_CHANGED;
4494 } else {
4495 mExynosCompositionInfo.mFirstIndex = newFirstIndex;
4496 mExynosCompositionInfo.mLastIndex = newLastIndex;
4497 }
4498 }
4499
4500 DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", ret);
4501 DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
4502 mClientCompositionInfo.mHasCompositionLayer,
4503 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
4504 DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition(%d) range [%d] - [%d]",
4505 mExynosCompositionInfo.mHasCompositionLayer,
4506 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
4507
4508 return ret;
4509 }
removeClientCompositionLayer(uint32_t layerIndex)4510 int32_t ExynosDisplay::removeClientCompositionLayer(uint32_t layerIndex)
4511 {
4512 int32_t ret = NO_ERROR;
4513
4514 DISPLAY_LOGD(eDebugResourceManager, "[%d] - [%d] [%d] layer is removed from client composition",
4515 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
4516 layerIndex);
4517
4518 /* Only first layer or last layer can be removed */
4519 if ((mClientCompositionInfo.mHasCompositionLayer == false) ||
4520 ((mClientCompositionInfo.mFirstIndex != (int32_t)layerIndex) &&
4521 (mClientCompositionInfo.mLastIndex != (int32_t)layerIndex))) {
4522 DISPLAY_LOGE("removeClientCompositionLayer() error, [%d] - [%d], layer[%d]",
4523 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
4524 layerIndex);
4525 return -EINVAL;
4526 }
4527
4528 if (mClientCompositionInfo.mFirstIndex == mClientCompositionInfo.mLastIndex) {
4529 ExynosMPP *otfMPP = mClientCompositionInfo.mOtfMPP;
4530 if (otfMPP != NULL)
4531 otfMPP->resetAssignedState();
4532 else {
4533 DISPLAY_LOGE("mClientCompositionInfo.mOtfMPP is NULL");
4534 return -EINVAL;
4535 }
4536 mClientCompositionInfo.initializeInfos(this);
4537 mWindowNumUsed--;
4538 } else if ((int32_t)layerIndex == mClientCompositionInfo.mFirstIndex)
4539 mClientCompositionInfo.mFirstIndex++;
4540 else
4541 mClientCompositionInfo.mLastIndex--;
4542
4543 DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
4544 mClientCompositionInfo.mHasCompositionLayer,
4545 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
4546
4547 return ret;
4548 }
4549
4550
addExynosCompositionLayer(uint32_t layerIndex)4551 int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex)
4552 {
4553 bool invalidFlag = false;
4554 int32_t changeFlag = NO_ERROR;
4555 int ret = 0;
4556 int32_t startIndex;
4557 int32_t endIndex;
4558
4559 DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to exynos composition", layerIndex);
4560
4561 if (mExynosCompositionInfo.mHasCompositionLayer == false) {
4562 mExynosCompositionInfo.mFirstIndex = layerIndex;
4563 mExynosCompositionInfo.mLastIndex = layerIndex;
4564 mExynosCompositionInfo.mHasCompositionLayer = true;
4565 return EXYNOS_ERROR_CHANGED;
4566 } else {
4567 mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)layerIndex);
4568 mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)layerIndex);
4569 }
4570
4571 DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
4572 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
4573
4574 ExynosMPP *m2mMPP = mExynosCompositionInfo.mM2mMPP;
4575
4576 if (m2mMPP == NULL) {
4577 DISPLAY_LOGE("exynosComposition m2mMPP is NULL");
4578 return -EINVAL;
4579 }
4580
4581 startIndex = mExynosCompositionInfo.mFirstIndex;
4582 endIndex = mExynosCompositionInfo.mLastIndex;
4583
4584 if ((startIndex < 0) || (endIndex < 0) ||
4585 (startIndex >= (int32_t)mLayers.size()) || (endIndex >= (int32_t)mLayers.size())) {
4586 DISPLAY_LOGE("exynosComposition invalid index (%d), (%d)", startIndex, endIndex);
4587 return -EINVAL;
4588 }
4589
4590 int32_t maxPriorityIndex = -1;
4591
4592 uint32_t highPriorityIndex = 0;
4593 uint32_t highPriorityNum = 0;
4594 int32_t highPriorityCheck = 0;
4595 std::vector<int32_t> highPriority;
4596 highPriority.assign(mLayers.size(), -1);
4597 /* handle sandwiched layers */
4598 for (int32_t i = startIndex; i <= endIndex; i++) {
4599 ExynosLayer *layer = mLayers[i];
4600 if (layer == NULL) {
4601 DISPLAY_LOGE("layer[%d] layer is null", i);
4602 continue;
4603 }
4604
4605 if (layer->mOverlayPriority == ePriorityMax &&
4606 m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO) {
4607 DISPLAY_LOGD(eDebugResourceManager, "\tG2D will be assgined for only [%d] layer", i);
4608 invalidFlag = true;
4609 maxPriorityIndex = i;
4610 continue;
4611 }
4612
4613 if (layer->mOverlayPriority >= ePriorityHigh)
4614 {
4615 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high priority", i);
4616 highPriority[highPriorityIndex++] = i;
4617 highPriorityNum++;
4618 continue;
4619 }
4620
4621 if (layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS)
4622 continue;
4623
4624 exynos_image src_img;
4625 exynos_image dst_img;
4626 layer->setSrcExynosImage(&src_img);
4627 layer->setDstExynosImage(&dst_img);
4628 layer->setExynosMidImage(dst_img);
4629 bool isAssignable = false;
4630 if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
4631 isAssignable = m2mMPP->isAssignable(this, src_img, dst_img);
4632
4633 if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
4634 {
4635 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is client composition", i);
4636 invalidFlag = true;
4637 } else if (((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) == 0) ||
4638 (isAssignable == false))
4639 {
4640 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is not supported by G2D", i);
4641 invalidFlag = true;
4642 layer->resetAssignedResource();
4643 layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4644 if ((ret = addClientCompositionLayer(i)) < 0)
4645 return ret;
4646 changeFlag |= ret;
4647 } else if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) ||
4648 (layer->mValidateCompositionType == HWC2_COMPOSITION_INVALID)) {
4649 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
4650 layer->mOverlayInfo |= eSandwitchedBetweenEXYNOS;
4651 layer->resetAssignedResource();
4652 if ((ret = m2mMPP->assignMPP(this, layer)) != NO_ERROR)
4653 {
4654 HWC_LOGE(this, "%s:: %s MPP assignMPP() error (%d)",
4655 __func__, m2mMPP->mName.string(), ret);
4656 return ret;
4657 }
4658 if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
4659 layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
4660 mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)i);
4661 mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)i);
4662 } else {
4663 DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has known type (%d)", i,
4664 layer->mValidateCompositionType);
4665 }
4666 }
4667
4668 if (invalidFlag) {
4669 DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
4670 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
4671 DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d], highPriorityNum[%d]",
4672 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, highPriorityNum);
4673
4674 if (m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO && maxPriorityIndex >= 0) {
4675 startIndex = mExynosCompositionInfo.mFirstIndex;
4676 endIndex = mExynosCompositionInfo.mLastIndex;
4677
4678 for (int32_t i = startIndex; i <= endIndex; i++) {
4679 if (mLayers[i]->mOverlayPriority == ePriorityMax ||
4680 mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
4681 continue;
4682 mLayers[i]->resetAssignedResource();
4683 mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4684 if ((ret = addClientCompositionLayer(i)) < 0)
4685 return ret;
4686 changeFlag |= ret;
4687 }
4688
4689 if (mLayers[maxPriorityIndex]->mValidateCompositionType
4690 != HWC2_COMPOSITION_EXYNOS) {
4691 mLayers[maxPriorityIndex]->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
4692 mLayers[maxPriorityIndex]->resetAssignedResource();
4693 if ((ret = m2mMPP->assignMPP(this, mLayers[maxPriorityIndex])) != NO_ERROR)
4694 {
4695 ALOGE("%s:: %s MPP assignMPP() error (%d)",
4696 __func__, m2mMPP->mName.string(), ret);
4697 return ret;
4698 }
4699 }
4700
4701 mExynosCompositionInfo.mFirstIndex = maxPriorityIndex;
4702 mExynosCompositionInfo.mLastIndex = maxPriorityIndex;
4703 }
4704
4705 /* Check if exynos comosition nests GLES composition */
4706 if ((mClientCompositionInfo.mHasCompositionLayer) &&
4707 (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mFirstIndex) &&
4708 (mClientCompositionInfo.mFirstIndex < mExynosCompositionInfo.mLastIndex) &&
4709 (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mLastIndex) &&
4710 (mClientCompositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)) {
4711
4712 if ((mClientCompositionInfo.mFirstIndex - mExynosCompositionInfo.mFirstIndex) <
4713 (mExynosCompositionInfo.mLastIndex - mClientCompositionInfo.mLastIndex)) {
4714 mLayers[mExynosCompositionInfo.mFirstIndex]->resetAssignedResource();
4715 mLayers[mExynosCompositionInfo.mFirstIndex]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4716 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mFirstIndex)) < 0)
4717 return ret;
4718 mExynosCompositionInfo.mFirstIndex = mClientCompositionInfo.mLastIndex + 1;
4719 changeFlag |= ret;
4720 } else {
4721 mLayers[mExynosCompositionInfo.mLastIndex]->resetAssignedResource();
4722 mLayers[mExynosCompositionInfo.mLastIndex]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4723 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mLastIndex)) < 0)
4724 return ret;
4725 mExynosCompositionInfo.mLastIndex = (mClientCompositionInfo.mFirstIndex - 1);
4726 changeFlag |= ret;
4727 }
4728 }
4729 }
4730
4731 if (highPriorityNum > 0 && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
4732 for (uint32_t i = 0; i < highPriorityNum; i++) {
4733 if ((int32_t)highPriority[i] == mExynosCompositionInfo.mFirstIndex)
4734 mExynosCompositionInfo.mFirstIndex++;
4735 else if ((int32_t)highPriority[i] == mExynosCompositionInfo.mLastIndex)
4736 mExynosCompositionInfo.mLastIndex--;
4737 }
4738 }
4739
4740 if ((mExynosCompositionInfo.mFirstIndex < 0) ||
4741 (mExynosCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
4742 (mExynosCompositionInfo.mLastIndex < 0) ||
4743 (mExynosCompositionInfo.mLastIndex >= (int)mLayers.size()) ||
4744 (mExynosCompositionInfo.mFirstIndex > mExynosCompositionInfo.mLastIndex))
4745 {
4746 DISPLAY_LOGD(eDebugResourceManager, "\texynos composition is disabled, because of invalid index (%d, %d), size(%zu)",
4747 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, mLayers.size());
4748 mExynosCompositionInfo.initializeInfos(this);
4749 changeFlag = EXYNOS_ERROR_CHANGED;
4750 }
4751
4752 for (uint32_t i = 0; i < highPriorityNum; i++) {
4753 if ((mExynosCompositionInfo.mFirstIndex < (int32_t)highPriority[i]) &&
4754 ((int32_t)highPriority[i] < mExynosCompositionInfo.mLastIndex)) {
4755 highPriorityCheck = 1;
4756 break;
4757 }
4758 }
4759
4760
4761 if (highPriorityCheck && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
4762 startIndex = mExynosCompositionInfo.mFirstIndex;
4763 endIndex = mExynosCompositionInfo.mLastIndex;
4764 DISPLAY_LOGD(eDebugResourceManager, "\texynos composition is disabled because of sandwitched max priority layer (%d, %d)",
4765 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
4766 for (int32_t i = startIndex; i <= endIndex; i++) {
4767 int32_t checkPri = 0;
4768 for (uint32_t j = 0; j < highPriorityNum; j++) {
4769 if (i == (int32_t)highPriority[j]) {
4770 checkPri = 1;
4771 break;
4772 }
4773 }
4774
4775 if (checkPri)
4776 continue;
4777
4778 mLayers[i]->resetAssignedResource();
4779 mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4780 if ((ret = addClientCompositionLayer(i)) < 0)
4781 HWC_LOGE(this, "%d layer: addClientCompositionLayer() fail", i);
4782 }
4783 mExynosCompositionInfo.initializeInfos(this);
4784 changeFlag = EXYNOS_ERROR_CHANGED;
4785 }
4786
4787 DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", changeFlag);
4788 DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
4789 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
4790 DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
4791 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
4792
4793 return changeFlag;
4794 }
4795
windowUpdateExceptions()4796 bool ExynosDisplay::windowUpdateExceptions()
4797 {
4798
4799 if (mExynosCompositionInfo.mHasCompositionLayer) {
4800 DISPLAY_LOGD(eDebugWindowUpdate, "has exynos composition");
4801 return true;
4802 }
4803 if (mClientCompositionInfo.mHasCompositionLayer) {
4804 DISPLAY_LOGD(eDebugWindowUpdate, "has client composition");
4805 return true;
4806 }
4807
4808 for (size_t i = 0; i < mLayers.size(); i++) {
4809 if (mLayers[i]->mM2mMPP != NULL) return true;
4810 if (mLayers[i]->mLayerBuffer == NULL) return true;
4811 if (mLayers[i]->mTransform != 0) return true;
4812 }
4813
4814 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
4815 exynos_win_config_data &config = mDpuData.configs[i];
4816 if (config.state == config.WIN_STATE_BUFFER) {
4817 if (config.src.w/config.dst.w != 1 || config.src.h/config.dst.h != 1) {
4818 DISPLAY_LOGD(eDebugWindowUpdate, "Skip reason : scaled");
4819 return true;
4820 }
4821 }
4822 }
4823
4824 return false;
4825 }
4826
handleWindowUpdate()4827 int ExynosDisplay::handleWindowUpdate()
4828 {
4829 int ret = NO_ERROR;
4830 // TODO will be implemented
4831 unsigned int excp;
4832
4833 mDpuData.enable_win_update = false;
4834 /* Init with full size */
4835 mDpuData.win_update_region.x = 0;
4836 mDpuData.win_update_region.w = mXres;
4837 mDpuData.win_update_region.y = 0;
4838 mDpuData.win_update_region.h = mYres;
4839
4840 if (exynosHWCControl.windowUpdate != 1) return 0;
4841
4842 if (mGeometryChanged != 0) {
4843 DISPLAY_LOGD(eDebugWindowUpdate, "GEOMETRY chnaged 0x%" PRIx64 "",
4844 mGeometryChanged);
4845 return 0;
4846 }
4847
4848 if ((mCursorIndex >= 0) && (mCursorIndex < (int32_t)mLayers.size())) {
4849 ExynosLayer *layer = mLayers[mCursorIndex];
4850 /* Cursor layer is enabled */
4851 if (layer->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) {
4852 return 0;
4853 }
4854 }
4855
4856 /* exceptions */
4857 if (windowUpdateExceptions())
4858 return 0;
4859
4860 hwc_rect mergedRect = {(int)mXres, (int)mYres, 0, 0};
4861 hwc_rect damageRect = {(int)mXres, (int)mYres, 0, 0};
4862
4863 for (size_t i = 0; i < mLayers.size(); i++) {
4864 excp = getLayerRegion(mLayers[i], &damageRect, eDamageRegionByDamage);
4865 if (excp == eDamageRegionPartial) {
4866 DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) partial : %d, %d, %d, %d", i,
4867 damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
4868 mergedRect = expand(mergedRect, damageRect);
4869 }
4870 else if (excp == eDamageRegionSkip) {
4871 int32_t windowIndex = mLayers[i]->mWindowIndex;
4872 if ((ret = checkConfigDstChanged(mDpuData, mLastDpuData, windowIndex)) < 0) {
4873 return 0;
4874 } else if (ret > 0) {
4875 damageRect.left = mLayers[i]->mDisplayFrame.left;
4876 damageRect.right = mLayers[i]->mDisplayFrame.right;
4877 damageRect.top = mLayers[i]->mDisplayFrame.top;
4878 damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
4879 DISPLAY_LOGD(eDebugWindowUpdate, "Skip layer (origin) : %d, %d, %d, %d",
4880 damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
4881 mergedRect = expand(mergedRect, damageRect);
4882 hwc_rect prevDst = {mLastDpuData.configs[i].dst.x, mLastDpuData.configs[i].dst.y,
4883 mLastDpuData.configs[i].dst.x + (int)mLastDpuData.configs[i].dst.w,
4884 mLastDpuData.configs[i].dst.y + (int)mLastDpuData.configs[i].dst.h};
4885 mergedRect = expand(mergedRect, prevDst);
4886 } else {
4887 DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) skip", i);
4888 continue;
4889 }
4890 }
4891 else if (excp == eDamageRegionFull) {
4892 damageRect.left = mLayers[i]->mDisplayFrame.left;
4893 damageRect.top = mLayers[i]->mDisplayFrame.top;
4894 damageRect.right = mLayers[i]->mDisplayFrame.right;
4895 damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
4896 DISPLAY_LOGD(eDebugWindowUpdate, "Full layer update : %d, %d, %d, %d", mLayers[i]->mDisplayFrame.left,
4897 mLayers[i]->mDisplayFrame.top, mLayers[i]->mDisplayFrame.right, mLayers[i]->mDisplayFrame.bottom);
4898 mergedRect = expand(mergedRect, damageRect);
4899 }
4900 else {
4901 DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, Skip reason (layer %zu) : %d", i, excp);
4902 return 0;
4903 }
4904 }
4905
4906 if (mergedRect.left == (int32_t)mXres && mergedRect.right == 0 &&
4907 mergedRect.top == (int32_t)mYres && mergedRect.bottom == 0) {
4908 DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, All layer skiped" );
4909 return 0;
4910 }
4911
4912 DISPLAY_LOGD(eDebugWindowUpdate, "Partial(origin) : %d, %d, %d, %d",
4913 mergedRect.left, mergedRect.top, mergedRect.right, mergedRect.bottom);
4914
4915 if (mergedRect.left < 0) mergedRect.left = 0;
4916 if (mergedRect.right > (int32_t)mXres) mergedRect.right = mXres;
4917 if (mergedRect.top < 0) mergedRect.top = 0;
4918 if (mergedRect.bottom > (int32_t)mYres) mergedRect.bottom = mYres;
4919
4920 if (mergedRect.left == 0 && mergedRect.right == (int32_t)mXres &&
4921 mergedRect.top == 0 && mergedRect.bottom == (int32_t)mYres) {
4922 DISPLAY_LOGD(eDebugWindowUpdate, "Partial : Full size");
4923 mDpuData.enable_win_update = true;
4924 mDpuData.win_update_region.x = 0;
4925 mDpuData.win_update_region.w = mXres;
4926 mDpuData.win_update_region.y = 0;
4927 mDpuData.win_update_region.h = mYres;
4928 DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
4929 return 0;
4930 }
4931
4932 mDpuData.enable_win_update = true;
4933 mDpuData.win_update_region.x = mergedRect.left;
4934 mDpuData.win_update_region.w = WIDTH(mergedRect);
4935 mDpuData.win_update_region.y = mergedRect.top;
4936 mDpuData.win_update_region.h = HEIGHT(mergedRect);
4937
4938 DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
4939 return 0;
4940 }
4941
getLayerRegion(ExynosLayer * layer,hwc_rect * rect_area,uint32_t regionType)4942 unsigned int ExynosDisplay::getLayerRegion(ExynosLayer *layer, hwc_rect *rect_area, uint32_t regionType) {
4943
4944 android::Vector <hwc_rect_t> hwcRects;
4945 size_t numRects = 0;
4946
4947 rect_area->left = INT_MAX;
4948 rect_area->top = INT_MAX;
4949 rect_area->right = rect_area->bottom = 0;
4950
4951 hwcRects = layer->mDamageRects;
4952 numRects = layer->mDamageNum;
4953
4954 if ((numRects == 0) || (hwcRects.size() == 0))
4955 return eDamageRegionFull;
4956
4957 if ((numRects == 1) && (hwcRects[0].left == 0) && (hwcRects[0].top == 0) &&
4958 (hwcRects[0].right == 0) && (hwcRects[0].bottom == 0))
4959 return eDamageRegionSkip;
4960
4961 switch (regionType) {
4962 case eDamageRegionByDamage:
4963 for (size_t j = 0; j < hwcRects.size(); j++) {
4964 hwc_rect_t rect;
4965
4966 if ((hwcRects[j].left < 0) || (hwcRects[j].top < 0) ||
4967 (hwcRects[j].right < 0) || (hwcRects[j].bottom < 0) ||
4968 (hwcRects[j].left >= hwcRects[j].right) || (hwcRects[j].top >= hwcRects[j].bottom) ||
4969 (hwcRects[j].right - hwcRects[j].left > WIDTH(layer->mSourceCrop)) ||
4970 (hwcRects[j].bottom - hwcRects[j].top > HEIGHT(layer->mSourceCrop))) {
4971 rect_area->left = INT_MAX;
4972 rect_area->top = INT_MAX;
4973 rect_area->right = rect_area->bottom = 0;
4974 return eDamageRegionFull;
4975 }
4976
4977 rect.left = layer->mDisplayFrame.left + hwcRects[j].left - layer->mSourceCrop.left;
4978 rect.top = layer->mDisplayFrame.top + hwcRects[j].top - layer->mSourceCrop.top;
4979 rect.right = layer->mDisplayFrame.left + hwcRects[j].right - layer->mSourceCrop.left;
4980 rect.bottom = layer->mDisplayFrame.top + hwcRects[j].bottom - layer->mSourceCrop.top;
4981 DISPLAY_LOGD(eDebugWindowUpdate, "Display frame : %d, %d, %d, %d", layer->mDisplayFrame.left,
4982 layer->mDisplayFrame.top, layer->mDisplayFrame.right, layer->mDisplayFrame.bottom);
4983 DISPLAY_LOGD(eDebugWindowUpdate, "hwcRects : %d, %d, %d, %d", hwcRects[j].left,
4984 hwcRects[j].top, hwcRects[j].right, hwcRects[j].bottom);
4985 adjustRect(rect, INT_MAX, INT_MAX);
4986 /* Get sums of rects */
4987 *rect_area = expand(*rect_area, rect);
4988 }
4989 return eDamageRegionPartial;
4990 break;
4991 case eDamageRegionByLayer:
4992 if (layer->mLastLayerBuffer != layer->mLayerBuffer)
4993 return eDamageRegionFull;
4994 else
4995 return eDamageRegionSkip;
4996 break;
4997 default:
4998 HWC_LOGE(this, "%s:: Invalid regionType (%d)", __func__, regionType);
4999 return eDamageRegionError;
5000 break;
5001 }
5002
5003 return eDamageRegionFull;
5004 }
5005
getRestrictionIndex(int halFormat)5006 uint32_t ExynosDisplay::getRestrictionIndex(int halFormat)
5007 {
5008 if (isFormatRgb(halFormat))
5009 return RESTRICTION_RGB;
5010 else
5011 return RESTRICTION_YUV;
5012 }
5013
closeFencesForSkipFrame(rendering_state renderingState)5014 void ExynosDisplay::closeFencesForSkipFrame(rendering_state renderingState)
5015 {
5016 for (size_t i=0; i < mLayers.size(); i++) {
5017 if (mLayers[i]->mAcquireFence != -1) {
5018 mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
5019 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
5020 }
5021 }
5022
5023 if (mDpuData.readback_info.rel_fence >= 0) {
5024 mDpuData.readback_info.rel_fence =
5025 fence_close(mDpuData.readback_info.rel_fence, this,
5026 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5027 }
5028 if (mDpuData.readback_info.acq_fence >= 0) {
5029 mDpuData.readback_info.acq_fence =
5030 fence_close(mDpuData.readback_info.acq_fence, this,
5031 FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
5032 }
5033
5034 if (renderingState >= RENDERING_STATE_VALIDATED) {
5035 if (mDisplayControl.earlyStartMPP == true) {
5036 if (mExynosCompositionInfo.mHasCompositionLayer) {
5037 /*
5038 * m2mMPP's release fence for dst buffer was set to
5039 * mExynosCompositionInfo.mAcquireFence by startPostProcessing()
5040 * in validate time.
5041 * This fence should be passed to display driver
5042 * but it wont't because this frame will not be presented.
5043 * So fence should be closed.
5044 */
5045 mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence,
5046 this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5047 }
5048
5049 for (size_t i = 0; i < mLayers.size(); i++) {
5050 exynos_image outImage;
5051 ExynosMPP* m2mMPP = mLayers[i]->mM2mMPP;
5052 if ((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
5053 (m2mMPP != NULL) &&
5054 (m2mMPP->mAssignedDisplay == this) &&
5055 (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
5056 if (m2mMPP->mPhysicalType == MPP_MSC) {
5057 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
5058 } else if (m2mMPP->mPhysicalType == MPP_G2D) {
5059 ALOGD("close(%d)", outImage.releaseFenceFd);
5060 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5061 } else {
5062 DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
5063 fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
5064 }
5065 m2mMPP->resetDstReleaseFence();
5066 ALOGD("reset buf[%d], %d", m2mMPP->mCurrentDstBuf,
5067 m2mMPP->mDstImgs[m2mMPP->mCurrentDstBuf].acrylicReleaseFenceFd);
5068 }
5069 }
5070 }
5071 }
5072
5073 if (renderingState >= RENDERING_STATE_PRESENTED) {
5074 /* mAcquireFence is set after validate */
5075 mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
5076 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
5077 }
5078 }
closeFences()5079 void ExynosDisplay::closeFences()
5080 {
5081 for (size_t i = 0; i < mDpuData.configs.size(); i++) {
5082 if (mDpuData.configs[i].acq_fence != -1)
5083 fence_close(mDpuData.configs[i].acq_fence, this,
5084 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
5085 mDpuData.configs[i].acq_fence = -1;
5086 if (mDpuData.configs[i].rel_fence >= 0)
5087 fence_close(mDpuData.configs[i].rel_fence, this,
5088 FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP);
5089 mDpuData.configs[i].rel_fence = -1;
5090 }
5091 for (size_t i = 0; i < mLayers.size(); i++) {
5092 if (mLayers[i]->mReleaseFence > 0) {
5093 fence_close(mLayers[i]->mReleaseFence, this,
5094 FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
5095 mLayers[i]->mReleaseFence = -1;
5096 }
5097 if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
5098 (mLayers[i]->mM2mMPP != NULL)) {
5099 mLayers[i]->mM2mMPP->closeFences();
5100 }
5101 }
5102 if (mExynosCompositionInfo.mHasCompositionLayer) {
5103 if (mExynosCompositionInfo.mM2mMPP == NULL)
5104 {
5105 DISPLAY_LOGE("There is exynos composition, but m2mMPP is NULL");
5106 return;
5107 }
5108 mExynosCompositionInfo.mM2mMPP->closeFences();
5109 }
5110
5111 for (size_t i=0; i < mLayers.size(); i++) {
5112 if (mLayers[i]->mAcquireFence != -1) {
5113 mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
5114 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
5115 }
5116 }
5117
5118 mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence, this,
5119 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
5120 mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
5121 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
5122
5123 if (mDpuData.retire_fence > 0)
5124 fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
5125 mDpuData.retire_fence = -1;
5126
5127 mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
5128
5129 if (mDpuData.readback_info.rel_fence >= 0) {
5130 mDpuData.readback_info.rel_fence =
5131 fence_close(mDpuData.readback_info.rel_fence, this,
5132 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5133 }
5134 if (mDpuData.readback_info.acq_fence >= 0) {
5135 mDpuData.readback_info.acq_fence =
5136 fence_close(mDpuData.readback_info.acq_fence, this,
5137 FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
5138 }
5139 }
5140
setHWCControl(uint32_t ctrl,int32_t val)5141 void ExynosDisplay::setHWCControl(uint32_t ctrl, int32_t val)
5142 {
5143 switch (ctrl) {
5144 case HWC_CTL_ENABLE_COMPOSITION_CROP:
5145 mDisplayControl.enableCompositionCrop = (unsigned int)val;
5146 break;
5147 case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
5148 mDisplayControl.enableExynosCompositionOptimization = (unsigned int)val;
5149 break;
5150 case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
5151 mDisplayControl.enableClientCompositionOptimization = (unsigned int)val;
5152 break;
5153 case HWC_CTL_USE_MAX_G2D_SRC:
5154 mDisplayControl.useMaxG2DSrc = (unsigned int)val;
5155 break;
5156 case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
5157 mDisplayControl.handleLowFpsLayers = (unsigned int)val;
5158 break;
5159 case HWC_CTL_ENABLE_EARLY_START_MPP:
5160 mDisplayControl.earlyStartMPP = (unsigned int)val;
5161 break;
5162 default:
5163 ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
5164 break;
5165 }
5166 }
5167
getHdrCapabilities(uint32_t * outNumTypes,int32_t * outTypes,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)5168 int32_t ExynosDisplay::getHdrCapabilities(uint32_t* outNumTypes,
5169 int32_t* outTypes, float* outMaxLuminance,
5170 float* outMaxAverageLuminance, float* outMinLuminance)
5171 {
5172 DISPLAY_LOGD(eDebugHWC, "HWC2: %s, %d", __func__, __LINE__);
5173
5174 if (outNumTypes == NULL || outMaxLuminance == NULL ||
5175 outMaxAverageLuminance == NULL || outMinLuminance == NULL) {
5176 return HWC2_ERROR_BAD_PARAMETER;
5177 }
5178
5179 if (outTypes == NULL) {
5180 /*
5181 * This function is always called twice.
5182 * outTypes is NULL in the first call and
5183 * outType is valid pointer in the second call.
5184 * Get information only in the first call.
5185 * Use saved information in the second call.
5186 */
5187 if (mDisplayInterface->updateHdrCapabilities() != NO_ERROR)
5188 return HWC2_ERROR_BAD_CONFIG;
5189 }
5190
5191 *outMaxLuminance = mMaxLuminance;
5192 *outMaxAverageLuminance = mMaxAverageLuminance;
5193 *outMinLuminance = mMinLuminance;
5194
5195 if (outTypes == NULL) {
5196 *outNumTypes = mHdrTypes.size();
5197 } else {
5198 if (*outNumTypes != mHdrTypes.size()) {
5199 ALOGE("%s:: Invalid parameter (outNumTypes: %d, mHdrTypes size: %zu",
5200 __func__, *outNumTypes, mHdrTypes.size());
5201 return HWC2_ERROR_BAD_PARAMETER;
5202 }
5203 for(uint32_t i = 0; i < *outNumTypes; i++) {
5204 outTypes[i] = mHdrTypes[i];
5205 }
5206 }
5207 return HWC2_ERROR_NONE;
5208 }
5209
5210 // Support DDI scalser
setDDIScalerEnable(int __unused width,int __unused height)5211 void ExynosDisplay::setDDIScalerEnable(int __unused width, int __unused height) {
5212 }
5213
getDDIScalerMode(int __unused width,int __unused height)5214 int ExynosDisplay::getDDIScalerMode(int __unused width, int __unused height) {
5215 return 1; // WQHD
5216 }
5217
increaseMPPDstBufIndex()5218 void ExynosDisplay::increaseMPPDstBufIndex() {
5219 for (size_t i=0; i < mLayers.size(); i++) {
5220 if((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
5221 (mLayers[i]->mM2mMPP != NULL)) {
5222 mLayers[i]->mM2mMPP->increaseDstBuffIndex();
5223 }
5224 }
5225
5226 if ((mExynosCompositionInfo.mHasCompositionLayer) &&
5227 (mExynosCompositionInfo.mM2mMPP != NULL)) {
5228 mExynosCompositionInfo.mM2mMPP->increaseDstBuffIndex();
5229 }
5230 }
5231
getReadbackBufferAttributes(int32_t * outFormat,int32_t * outDataspace)5232 int32_t ExynosDisplay::getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
5233 int32_t* /*android_dataspace_t*/ outDataspace)
5234 {
5235 int32_t ret = mDisplayInterface->getReadbackBufferAttributes(outFormat, outDataspace);
5236 if (ret == NO_ERROR) {
5237 /* Interface didn't specific set dataspace */
5238 if (*outDataspace == HAL_DATASPACE_UNKNOWN)
5239 *outDataspace = colorModeToDataspace(mColorMode);
5240 /* Set default value */
5241 if (*outDataspace == HAL_DATASPACE_UNKNOWN)
5242 *outDataspace = HAL_DATASPACE_V0_SRGB;
5243
5244 mDisplayControl.readbackSupport = true;
5245 ALOGI("readback info: format(0x%8x), dataspace(0x%8x)", *outFormat, *outDataspace);
5246 } else {
5247 mDisplayControl.readbackSupport = false;
5248 ALOGI("readback is not supported, ret(%d)", ret);
5249 ret = HWC2_ERROR_UNSUPPORTED;
5250 }
5251 return ret;
5252 }
5253
setReadbackBuffer(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)5254 int32_t ExynosDisplay::setReadbackBuffer(buffer_handle_t buffer,
5255 int32_t releaseFence, bool requestedService)
5256 {
5257 Mutex::Autolock lock(mDisplayMutex);
5258 int32_t ret = NO_ERROR;
5259
5260 if (buffer == nullptr)
5261 return HWC2_ERROR_BAD_PARAMETER;
5262
5263 if (mDisplayControl.readbackSupport) {
5264 mDpuData.enable_readback = true;
5265 } else {
5266 DISPLAY_LOGE("readback is not supported but setReadbackBuffer is called, buffer(%p), releaseFence(%d)",
5267 buffer, releaseFence);
5268 if (releaseFence >= 0)
5269 releaseFence = fence_close(releaseFence, this,
5270 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5271 mDpuData.enable_readback = false;
5272 ret = HWC2_ERROR_UNSUPPORTED;
5273 }
5274 setReadbackBufferInternal(buffer, releaseFence, requestedService);
5275 return ret;
5276 }
5277
setReadbackBufferInternal(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)5278 void ExynosDisplay::setReadbackBufferInternal(buffer_handle_t buffer,
5279 int32_t releaseFence, bool requestedService)
5280 {
5281 if (mDpuData.readback_info.rel_fence >= 0) {
5282 mDpuData.readback_info.rel_fence =
5283 fence_close(mDpuData.readback_info.rel_fence, this,
5284 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5285 DISPLAY_LOGE("previous readback release fence is not delivered to display device");
5286 }
5287 if (releaseFence >= 0) {
5288 setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE,
5289 FENCE_IP_FB, FENCE_FROM);
5290 }
5291 mDpuData.readback_info.rel_fence = releaseFence;
5292
5293 if (buffer != NULL)
5294 mDpuData.readback_info.handle = buffer;
5295
5296 mDpuData.readback_info.requested_from_service = requestedService;
5297 }
5298
getReadbackBufferFence(int32_t * outFence)5299 int32_t ExynosDisplay::getReadbackBufferFence(int32_t* outFence)
5300 {
5301 /*
5302 * acq_fence was not set or
5303 * it was already closed by error or frame skip
5304 */
5305 if (mDpuData.readback_info.acq_fence < 0) {
5306 *outFence = -1;
5307 return HWC2_ERROR_UNSUPPORTED;
5308 }
5309
5310 *outFence = mDpuData.readback_info.acq_fence;
5311 /* Fence will be closed by caller of this function */
5312 mDpuData.readback_info.acq_fence = -1;
5313 return NO_ERROR;
5314 }
5315
setReadbackBufferAcqFence(int32_t acqFence)5316 int32_t ExynosDisplay::setReadbackBufferAcqFence(int32_t acqFence) {
5317 if (mDpuData.readback_info.acq_fence >= 0) {
5318 mDpuData.readback_info.acq_fence =
5319 fence_close(mDpuData.readback_info.acq_fence, this,
5320 FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
5321 DISPLAY_LOGE("previous readback out fence is not delivered to framework");
5322 }
5323 mDpuData.readback_info.acq_fence = acqFence;
5324 if (acqFence >= 0) {
5325 /*
5326 * Requtester of readback will get acqFence after presentDisplay
5327 * so validateFences should not check this fence
5328 * in presentDisplay so this function sets pendingAllowed parameter.
5329 */
5330 setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE,
5331 FENCE_IP_DPP, FENCE_FROM, true);
5332 }
5333
5334 return NO_ERROR;
5335 }
5336
initDisplayInterface(uint32_t __unused interfaceType)5337 void ExynosDisplay::initDisplayInterface(uint32_t __unused interfaceType)
5338 {
5339 mDisplayInterface = std::make_unique<ExynosDisplayInterface>();
5340 mDisplayInterface->init(this);
5341 }
5342
traceLayerTypes()5343 void ExynosDisplay::traceLayerTypes() {
5344 size_t g2d_count = 0;
5345 size_t dpu_count = 0;
5346 size_t gpu_count = 0;
5347 size_t skip_count = 0;
5348 for(auto const& layer: mLayers) {
5349 switch (layer->mExynosCompositionType) {
5350 case HWC2_COMPOSITION_EXYNOS:
5351 g2d_count++;
5352 break;
5353 case HWC2_COMPOSITION_CLIENT:
5354 if (layer->mCompositionType == HWC2_COMPOSITION_DEVICE) {
5355 skip_count++;
5356 } else {
5357 gpu_count++;
5358 }
5359 break;
5360 case HWC2_COMPOSITION_DEVICE:
5361 dpu_count++;
5362 break;
5363 default:
5364 break;
5365 }
5366 }
5367 ATRACE_INT("HWComposer: DPU Layer", dpu_count);
5368 ATRACE_INT("HWComposer: G2D Layer", g2d_count);
5369 ATRACE_INT("HWComposer: GPU Layer", gpu_count);
5370 ATRACE_INT("HWComposer: DPU Cached Layer", skip_count);
5371 ATRACE_INT("HWComposer: SF Cached Layer", mIgnoreLayers.size());
5372 ATRACE_INT("HWComposer: Total Layer", mLayers.size() + mIgnoreLayers.size());
5373 }
5374
updateBrightnessState()5375 void ExynosDisplay::updateBrightnessState() {
5376 static constexpr float kMaxCll = 10000.0;
5377 bool client_rgb_hdr = false;
5378
5379 mBrightnessState.reset();
5380 for (size_t i = 0; i < mLayers.size(); i++) {
5381 if (mLayers[i]->mIsHdrLayer) {
5382 if (mLayers[i]->isLayerFormatRgb()) {
5383 auto meta = mLayers[i]->getMetaParcel();
5384 if ((meta != nullptr) && (meta->eType & VIDEO_INFO_TYPE_HDR_STATIC) &&
5385 meta->sHdrStaticInfo.sType1.mMaxContentLightLevel >= kMaxCll) {
5386 // if there are one or more such layers and any one of them
5387 // is composed by GPU, we won't dim sdr layers
5388 if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
5389 client_rgb_hdr = true;
5390 }
5391 mBrightnessState.peak_hbm = true;
5392 mBrightnessState.instant_hbm = true;
5393 }
5394 }
5395 if (mLayers[i]->getDisplayFrameArea() >= mHdrFullScrenAreaThreshold) {
5396 mBrightnessState.hdr_full_screen = true;
5397 }
5398 }
5399 }
5400
5401 if (mBrightnessState.instant_hbm && !client_rgb_hdr) {
5402 // SDR dim ratio = display_nit_current / display_nit_after_hbm_on
5403 // mDisplayInterface has the panel caps to calculate current nits.
5404 float dim_sdr_ratio = mDisplayInterface->getSdrDimRatio();
5405 if (dim_sdr_ratio < kGhbmMinDimRatio) {
5406 ALOGW("sdr dim ratio %f too small", dim_sdr_ratio);
5407 dim_sdr_ratio = kGhbmMinDimRatio;
5408 }
5409 char value[PROPERTY_VALUE_MAX];
5410 const float ratio = property_get("debug.hwc.dim_sdr", value, nullptr) > 0 ?
5411 std::atof(value) : dim_sdr_ratio;
5412
5413 mBrightnessState.dim_sdr_target_ratio = ratio;
5414 }
5415
5416 mBrightnessState.local_hbm = mReqLhbm;
5417 mBrightnessState.instant_hbm |= mBrightnessState.local_hbm;
5418
5419 if (mDisplayInterface->updateBrightness(true /* syncFrame */) != HWC2_ERROR_NONE) {
5420 ALOGW("Failed to update brighntess");
5421 }
5422 }
5423
cleanupAfterClientDeath()5424 void ExynosDisplay::cleanupAfterClientDeath() {
5425 // Invalidate the client target buffer because it will be freed when the client dies
5426 mClientCompositionInfo.mTargetBuffer = NULL;
5427 // Invalidate the skip static flag so that we have to get a new target buffer first
5428 // before we can skip the static layers
5429 mClientCompositionInfo.mSkipStaticInitFlag = false;
5430 mClientCompositionInfo.mSkipFlag = false;
5431 }
5432