• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <aidl/android/hardware/graphics/common/Transform.h>
22 #include <aidl/android/hardware/graphics/composer3/ColorMode.h>
23 #include <aidl/android/hardware/power/IPower.h>
24 #include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
25 #include <android-base/parsebool.h>
26 #include <android-base/properties.h>
27 #include <android/binder_manager.h>
28 #include <cutils/properties.h>
29 #include <hardware/hwcomposer_defs.h>
30 #include <linux/fb.h>
31 #include <processgroup/processgroup.h>
32 #include <sync/sync.h>
33 #include <sys/ioctl.h>
34 #include <utils/CallStack.h>
35 
36 #include <charconv>
37 #include <future>
38 #include <map>
39 
40 #include "BrightnessController.h"
41 #include "DisplayTe2Manager.h"
42 #include "ExynosExternalDisplay.h"
43 #include "ExynosLayer.h"
44 #include "HistogramController.h"
45 #include "VendorGraphicBuffer.h"
46 #include "exynos_format.h"
47 #include "utils/Timers.h"
48 
49 /**
50  * ExynosDisplay implementation
51  */
52 
53 using namespace android;
54 using namespace vendor::graphics;
55 using namespace std::chrono_literals;
56 
57 using ::aidl::android::hardware::power::IPower;
58 using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
59 namespace AidlComposer3 = ::aidl::android::hardware::graphics::composer3;
60 namespace AidlCommon = ::aidl::android::hardware::graphics::common;
61 
62 extern struct exynos_hwc_control exynosHWCControl;
63 extern struct update_time_info updateTimeInfo;
64 
65 constexpr const char* kBufferDumpPath = "/data/vendor/log/hwc";
66 
67 constexpr float kDynamicRecompFpsThreshold = 1.0 / 5.0; // 1 frame update per 5 second
68 
69 constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
70 constexpr int64_t nsecsIdleHintTimeout = std::chrono::nanoseconds(100ms).count();
71 
PowerHalHintWorker(uint32_t displayId,const String8 & displayTraceName)72 ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId,
73                                                       const String8& displayTraceName)
74       : Worker("DisplayHints", HAL_PRIORITY_URGENT_DISPLAY),
75         mNeedUpdateRefreshRateHint(false),
76         mLastRefreshRateHint(0),
77         mIdleHintIsEnabled(false),
78         mForceUpdateIdleHint(false),
79         mIdleHintDeadlineTime(0),
80         mIdleHintSupportIsChecked(false),
81         mIdleHintIsSupported(false),
82         mDisplayTraceName(displayTraceName),
83         mPowerModeState(HWC2_POWER_MODE_OFF),
84         mRefreshRate(kDefaultRefreshRateFrequency),
85         mConnectRetryCount(0),
86         mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
87         mPowerHalExtAidl(nullptr),
88         mPowerHalAidl(nullptr),
89         mPowerHintSession(nullptr) {
90     if (property_get_bool("vendor.display.powerhal_hint_per_display", false)) {
91         std::string displayIdStr = std::to_string(displayId);
92         mIdleHintStr = "DISPLAY_" + displayIdStr + "_IDLE";
93         mRefreshRateHintPrefixStr = "DISPLAY_" + displayIdStr + "_";
94     } else {
95         mIdleHintStr = "DISPLAY_IDLE";
96         mRefreshRateHintPrefixStr = "REFRESH_";
97     }
98 }
99 
~PowerHalHintWorker()100 ExynosDisplay::PowerHalHintWorker::~PowerHalHintWorker() {
101     Exit();
102 }
103 
Init()104 int ExynosDisplay::PowerHalHintWorker::Init() {
105     return InitWorker();
106 }
107 
BinderDiedCallback(void * cookie)108 void ExynosDisplay::PowerHalHintWorker::BinderDiedCallback(void *cookie) {
109     ALOGE("PowerHal is died");
110     auto powerHint = reinterpret_cast<PowerHalHintWorker *>(cookie);
111     powerHint->forceUpdateHints();
112 }
113 
connectPowerHal()114 int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHal() {
115     if (mPowerHalAidl && mPowerHalExtAidl) {
116         return NO_ERROR;
117     }
118 
119     const std::string kInstance = std::string(IPower::descriptor) + "/default";
120     ndk::SpAIBinder pwBinder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
121 
122     mPowerHalAidl = IPower::fromBinder(pwBinder);
123 
124     if (!mPowerHalAidl) {
125         ALOGE("failed to connect power HAL (retry %u)", mConnectRetryCount);
126         mConnectRetryCount++;
127         return -EINVAL;
128     }
129 
130     ndk::SpAIBinder pwExtBinder;
131     AIBinder_getExtension(pwBinder.get(), pwExtBinder.getR());
132 
133     mPowerHalExtAidl = IPowerExt::fromBinder(pwExtBinder);
134 
135     if (!mPowerHalExtAidl) {
136         mPowerHalAidl = nullptr;
137         ALOGE("failed to connect power HAL extension (retry %u)", mConnectRetryCount);
138         mConnectRetryCount++;
139         return -EINVAL;
140     }
141 
142     mConnectRetryCount = 0;
143     AIBinder_linkToDeath(pwExtBinder.get(), mDeathRecipient.get(), reinterpret_cast<void *>(this));
144     // ensure the hint session is recreated every time powerhal is recreated
145     mPowerHintSession = nullptr;
146     forceUpdateHints();
147     ALOGI("connected power HAL successfully");
148     return NO_ERROR;
149 }
150 
checkPowerHalExtHintSupport(const std::string & mode)151 int32_t ExynosDisplay::PowerHalHintWorker::checkPowerHalExtHintSupport(const std::string &mode) {
152     if (mode.empty() || connectPowerHal() != NO_ERROR) {
153         return -EINVAL;
154     }
155 
156     bool isSupported = false;
157     auto ret = mPowerHalExtAidl->isModeSupported(mode.c_str(), &isSupported);
158     if (!ret.isOk()) {
159         ALOGE("failed to check power HAL extension hint: mode=%s", mode.c_str());
160         if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
161             /*
162              * PowerHAL service may crash due to some reasons, this could end up
163              * binder transaction failure. Set nullptr here to trigger re-connection.
164              */
165             ALOGE("binder transaction failed for power HAL extension hint");
166             mPowerHalExtAidl = nullptr;
167             return -ENOTCONN;
168         }
169         return -EINVAL;
170     }
171 
172     if (!isSupported) {
173         ALOGW("power HAL extension hint is not supported: mode=%s", mode.c_str());
174         return -EOPNOTSUPP;
175     }
176 
177     ALOGI("power HAL extension hint is supported: mode=%s", mode.c_str());
178     return NO_ERROR;
179 }
180 
sendPowerHalExtHint(const std::string & mode,bool enabled)181 int32_t ExynosDisplay::PowerHalHintWorker::sendPowerHalExtHint(const std::string &mode,
182                                                                bool enabled) {
183     if (mode.empty() || connectPowerHal() != NO_ERROR) {
184         return -EINVAL;
185     }
186 
187     auto ret = mPowerHalExtAidl->setMode(mode.c_str(), enabled);
188     if (!ret.isOk()) {
189         ALOGE("failed to send power HAL extension hint: mode=%s, enabled=%d", mode.c_str(),
190               enabled);
191         if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
192             /*
193              * PowerHAL service may crash due to some reasons, this could end up
194              * binder transaction failure. Set nullptr here to trigger re-connection.
195              */
196             ALOGE("binder transaction failed for power HAL extension hint");
197             mPowerHalExtAidl = nullptr;
198             return -ENOTCONN;
199         }
200         return -EINVAL;
201     }
202 
203     return NO_ERROR;
204 }
205 
checkRefreshRateHintSupport(const int32_t refreshRate)206 int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(const int32_t refreshRate) {
207     int32_t ret = NO_ERROR;
208 
209     if (!isPowerHalExist()) {
210         return -EOPNOTSUPP;
211     }
212     const auto its = mRefreshRateHintSupportMap.find(refreshRate);
213     if (its == mRefreshRateHintSupportMap.end()) {
214         /* check new hint */
215         std::string refreshRateHintStr =
216                 mRefreshRateHintPrefixStr + std::to_string(refreshRate) + "FPS";
217         ret = checkPowerHalExtHintSupport(refreshRateHintStr);
218         if (ret == NO_ERROR || ret == -EOPNOTSUPP) {
219             mRefreshRateHintSupportMap[refreshRate] = (ret == NO_ERROR);
220             ALOGI("cache refresh rate hint %s: %d", refreshRateHintStr.c_str(), !ret);
221         } else {
222             ALOGE("failed to check the support of refresh rate hint, ret %d", ret);
223         }
224     } else {
225         /* check existing hint */
226         if (!its->second) {
227             ret = -EOPNOTSUPP;
228         }
229     }
230     return ret;
231 }
232 
sendRefreshRateHint(const int32_t refreshRate,bool enabled)233 int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(const int32_t refreshRate,
234                                                                bool enabled) {
235     std::string hintStr = mRefreshRateHintPrefixStr + std::to_string(refreshRate) + "FPS";
236     int32_t ret = sendPowerHalExtHint(hintStr, enabled);
237     if (ret == -ENOTCONN) {
238         /* Reset the hints when binder failure occurs */
239         mLastRefreshRateHint = 0;
240     }
241     return ret;
242 }
243 
updateRefreshRateHintInternal(const hwc2_power_mode_t powerMode,const int32_t refreshRate)244 int32_t ExynosDisplay::PowerHalHintWorker::updateRefreshRateHintInternal(
245         const hwc2_power_mode_t powerMode, const int32_t refreshRate) {
246     int32_t ret = NO_ERROR;
247 
248     /* TODO: add refresh rate buckets, tracked in b/181100731 */
249     // skip sending unnecessary hint if it's still the same.
250     if (mLastRefreshRateHint == refreshRate && powerMode == HWC2_POWER_MODE_ON) {
251         return NO_ERROR;
252     }
253 
254     if (mLastRefreshRateHint) {
255         ret = sendRefreshRateHint(mLastRefreshRateHint, false);
256         if (ret == NO_ERROR) {
257             mLastRefreshRateHint = 0;
258         } else {
259             return ret;
260         }
261     }
262 
263     // disable all refresh rate hints if power mode is not ON.
264     if (powerMode != HWC2_POWER_MODE_ON) {
265         return ret;
266     }
267 
268     ret = checkRefreshRateHintSupport(refreshRate);
269     if (ret != NO_ERROR) {
270         return ret;
271     }
272 
273     ret = sendRefreshRateHint(refreshRate, true);
274     if (ret != NO_ERROR) {
275         return ret;
276     }
277 
278     mLastRefreshRateHint = refreshRate;
279     return ret;
280 }
281 
checkIdleHintSupport(void)282 int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
283     int32_t ret = NO_ERROR;
284 
285     if (!isPowerHalExist()) {
286         return -EOPNOTSUPP;
287     }
288 
289     Lock();
290     if (mIdleHintSupportIsChecked) {
291         ret = mIdleHintIsSupported ? NO_ERROR : -EOPNOTSUPP;
292         Unlock();
293         return ret;
294     }
295     Unlock();
296 
297     ret = checkPowerHalExtHintSupport(mIdleHintStr);
298     Lock();
299     if (ret == NO_ERROR) {
300         mIdleHintIsSupported = true;
301         mIdleHintSupportIsChecked = true;
302         ALOGI("display idle hint is supported");
303     } else if (ret == -EOPNOTSUPP) {
304         mIdleHintSupportIsChecked = true;
305         ALOGI("display idle hint is unsupported");
306     } else {
307         ALOGW("failed to check the support of display idle hint, ret %d", ret);
308     }
309     Unlock();
310     return ret;
311 }
312 
checkPowerHintSessionSupport()313 int32_t ExynosDisplay::PowerHalHintWorker::checkPowerHintSessionSupport() {
314     std::scoped_lock lock(sSharedDisplayMutex);
315     if (sSharedDisplayData.hintSessionSupported.has_value()) {
316         mHintSessionSupportChecked = true;
317         return *(sSharedDisplayData.hintSessionSupported);
318     }
319 
320     if (!isPowerHalExist()) {
321         return -EOPNOTSUPP;
322     }
323 
324     if (connectPowerHal() != NO_ERROR) {
325         ALOGW("Error connecting to the PowerHAL");
326         return -EINVAL;
327     }
328 
329     int64_t rate;
330     // Try to get preferred rate to determine if it's supported
331     auto ret = mPowerHalAidl->getHintSessionPreferredRate(&rate);
332 
333     int32_t out;
334     if (ret.isOk()) {
335         ALOGV("Power hint session is supported");
336         out = NO_ERROR;
337     } else if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
338         ALOGW("Power hint session unsupported");
339         out = -EOPNOTSUPP;
340     } else {
341         ALOGW("Error checking power hint status");
342         out = -EINVAL;
343     }
344 
345     mHintSessionSupportChecked = true;
346     sSharedDisplayData.hintSessionSupported = out;
347     return out;
348 }
349 
updateIdleHint(const int64_t deadlineTime,const bool forceUpdate)350 int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(const int64_t deadlineTime,
351                                                           const bool forceUpdate) {
352     int32_t ret = checkIdleHintSupport();
353     if (ret != NO_ERROR) {
354         return ret;
355     }
356 
357     bool enableIdleHint =
358             (deadlineTime < systemTime(SYSTEM_TIME_MONOTONIC) && CC_LIKELY(deadlineTime > 0));
359     DISPLAY_ATRACE_INT("HWCIdleHintTimer", enableIdleHint);
360 
361     if (mIdleHintIsEnabled != enableIdleHint || forceUpdate) {
362         ret = sendPowerHalExtHint(mIdleHintStr, enableIdleHint);
363         if (ret == NO_ERROR) {
364             mIdleHintIsEnabled = enableIdleHint;
365         }
366     }
367     return ret;
368 }
369 
forceUpdateHints(void)370 void ExynosDisplay::PowerHalHintWorker::forceUpdateHints(void) {
371     Lock();
372     mLastRefreshRateHint = 0;
373     mNeedUpdateRefreshRateHint = true;
374     mLastErrorSent = std::nullopt;
375     if (mIdleHintSupportIsChecked && mIdleHintIsSupported) {
376         mForceUpdateIdleHint = true;
377     }
378 
379     Unlock();
380 
381     Signal();
382 }
383 
sendActualWorkDuration()384 int32_t ExynosDisplay::PowerHalHintWorker::sendActualWorkDuration() {
385     Lock();
386     if (mPowerHintSession == nullptr) {
387         Unlock();
388         return -EINVAL;
389     }
390 
391     if (!needSendActualWorkDurationLocked()) {
392         Unlock();
393         return NO_ERROR;
394     }
395 
396     if (mActualWorkDuration.has_value()) {
397         mLastErrorSent = *mActualWorkDuration - mTargetWorkDuration;
398     }
399 
400     std::vector<WorkDuration> hintQueue(std::move(mPowerHintQueue));
401     mPowerHintQueue.clear();
402     Unlock();
403 
404     ALOGV("Sending hint update batch");
405     mLastActualReportTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
406     auto ret = mPowerHintSession->reportActualWorkDuration(hintQueue);
407     if (!ret.isOk()) {
408         ALOGW("Failed to report power hint session timing:  %s %s", ret.getMessage(),
409               ret.getDescription().c_str());
410         if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
411             Lock();
412             mPowerHalExtAidl = nullptr;
413             Unlock();
414         }
415     }
416     return ret.isOk() ? NO_ERROR : -EINVAL;
417 }
418 
updateTargetWorkDuration()419 int32_t ExynosDisplay::PowerHalHintWorker::updateTargetWorkDuration() {
420     if (sNormalizeTarget) {
421         return NO_ERROR;
422     }
423 
424     if (mPowerHintSession == nullptr) {
425         return -EINVAL;
426     }
427 
428     Lock();
429 
430     if (!needUpdateTargetWorkDurationLocked()) {
431         Unlock();
432         return NO_ERROR;
433     }
434 
435     nsecs_t targetWorkDuration = mTargetWorkDuration;
436     mLastTargetDurationReported = targetWorkDuration;
437     Unlock();
438 
439     ALOGV("Sending target time: %lld ns", static_cast<long long>(targetWorkDuration));
440     auto ret = mPowerHintSession->updateTargetWorkDuration(targetWorkDuration);
441     if (!ret.isOk()) {
442         ALOGW("Failed to send power hint session target:  %s %s", ret.getMessage(),
443               ret.getDescription().c_str());
444         if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
445             Lock();
446             mPowerHalExtAidl = nullptr;
447             Unlock();
448         }
449     }
450     return ret.isOk() ? NO_ERROR : -EINVAL;
451 }
452 
signalActualWorkDuration(nsecs_t actualDurationNanos)453 void ExynosDisplay::PowerHalHintWorker::signalActualWorkDuration(nsecs_t actualDurationNanos) {
454     ATRACE_CALL();
455 
456     if (!usePowerHintSession()) {
457         return;
458     }
459     Lock();
460     nsecs_t reportedDurationNs = actualDurationNanos;
461     if (sNormalizeTarget) {
462         reportedDurationNs += mLastTargetDurationReported - mTargetWorkDuration;
463     } else {
464         if (mLastTargetDurationReported != kDefaultTarget.count() && mTargetWorkDuration != 0) {
465             reportedDurationNs =
466                     static_cast<int64_t>(static_cast<long double>(mLastTargetDurationReported) /
467                                          mTargetWorkDuration * actualDurationNanos);
468         }
469     }
470 
471     mActualWorkDuration = reportedDurationNs;
472     WorkDuration duration = {.timeStampNanos = systemTime(), .durationNanos = reportedDurationNs};
473 
474     if (sTraceHintSessionData) {
475         DISPLAY_ATRACE_INT64("Measured duration", actualDurationNanos);
476         DISPLAY_ATRACE_INT64("Target error term", mTargetWorkDuration - actualDurationNanos);
477 
478         DISPLAY_ATRACE_INT64("Reported duration", reportedDurationNs);
479         DISPLAY_ATRACE_INT64("Reported target", mLastTargetDurationReported);
480         DISPLAY_ATRACE_INT64("Reported target error term",
481                              mLastTargetDurationReported - reportedDurationNs);
482     }
483     ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
484           " with error: %" PRId64,
485           reportedDurationNs, mLastTargetDurationReported,
486           mLastTargetDurationReported - reportedDurationNs);
487 
488     mPowerHintQueue.push_back(duration);
489 
490     bool shouldSignal = needSendActualWorkDurationLocked();
491     Unlock();
492     if (shouldSignal) {
493         Signal();
494     }
495 }
496 
signalTargetWorkDuration(nsecs_t targetDurationNanos)497 void ExynosDisplay::PowerHalHintWorker::signalTargetWorkDuration(nsecs_t targetDurationNanos) {
498     ATRACE_CALL();
499     if (!usePowerHintSession()) {
500         return;
501     }
502     Lock();
503     mTargetWorkDuration = targetDurationNanos - kTargetSafetyMargin.count();
504 
505     if (sTraceHintSessionData) DISPLAY_ATRACE_INT64("Time target", mTargetWorkDuration);
506     bool shouldSignal = false;
507     if (!sNormalizeTarget) {
508         shouldSignal = needUpdateTargetWorkDurationLocked();
509         if (shouldSignal && mActualWorkDuration.has_value() && sTraceHintSessionData) {
510             DISPLAY_ATRACE_INT64("Target error term", *mActualWorkDuration - mTargetWorkDuration);
511         }
512     }
513     Unlock();
514     if (shouldSignal) {
515         Signal();
516     }
517 }
518 
signalRefreshRate(hwc2_power_mode_t powerMode,int32_t refreshRate)519 void ExynosDisplay::PowerHalHintWorker::signalRefreshRate(hwc2_power_mode_t powerMode,
520                                                           int32_t refreshRate) {
521     Lock();
522     mPowerModeState = powerMode;
523     mRefreshRate = refreshRate;
524     mNeedUpdateRefreshRateHint = true;
525     Unlock();
526 
527     Signal();
528 }
529 
signalNonIdle()530 void ExynosDisplay::PowerHalHintWorker::signalNonIdle() {
531     ATRACE_CALL();
532 
533     Lock();
534     if (mIdleHintSupportIsChecked && !mIdleHintIsSupported) {
535         Unlock();
536         return;
537     }
538 
539     mIdleHintDeadlineTime = systemTime(SYSTEM_TIME_MONOTONIC) + nsecsIdleHintTimeout;
540     Unlock();
541 
542     Signal();
543 }
544 
needUpdateIdleHintLocked(int64_t & timeout)545 bool ExynosDisplay::PowerHalHintWorker::needUpdateIdleHintLocked(int64_t &timeout) {
546     if (!mIdleHintIsSupported) {
547         return false;
548     }
549 
550     int64_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
551     bool shouldEnableIdleHint =
552             (mIdleHintDeadlineTime < currentTime) && CC_LIKELY(mIdleHintDeadlineTime > 0);
553     if (mIdleHintIsEnabled != shouldEnableIdleHint || mForceUpdateIdleHint) {
554         return true;
555     }
556 
557     timeout = mIdleHintDeadlineTime - currentTime;
558     return false;
559 }
560 
Routine()561 void ExynosDisplay::PowerHalHintWorker::Routine() {
562     Lock();
563     bool useHintSession = usePowerHintSession();
564     // if the tids have updated, we restart the session
565     if (mTidsUpdated && useHintSession) mPowerHintSession = nullptr;
566     bool needStartHintSession =
567             (mPowerHintSession == nullptr) && useHintSession && !mBinderTids.empty();
568     int ret = 0;
569     int64_t timeout = -1;
570     if (!mNeedUpdateRefreshRateHint && !needUpdateIdleHintLocked(timeout) &&
571         !needSendActualWorkDurationLocked() && !needStartHintSession &&
572         !needUpdateTargetWorkDurationLocked()) {
573         ret = WaitForSignalOrExitLocked(timeout);
574     }
575 
576     // exit() signal received
577     if (ret == -EINTR) {
578         Unlock();
579         return;
580     }
581 
582     // store internal values so they are consistent after Unlock()
583     // some defined earlier also might have changed during the wait
584     useHintSession = usePowerHintSession();
585     needStartHintSession = (mPowerHintSession == nullptr) && useHintSession && !mBinderTids.empty();
586 
587     bool needUpdateRefreshRateHint = mNeedUpdateRefreshRateHint;
588     int64_t deadlineTime = mIdleHintDeadlineTime;
589     hwc2_power_mode_t powerMode = mPowerModeState;
590 
591     /*
592      * Clear the flags here instead of clearing them after calling the hint
593      * update functions. The flags may be set by signals after Unlock() and
594      * before the hint update functions are done. Thus we may miss the newest
595      * hints if we clear the flags after the hint update functions work without
596      * errors.
597      */
598     mTidsUpdated = false;
599     mNeedUpdateRefreshRateHint = false;
600 
601     bool forceUpdateIdleHint = mForceUpdateIdleHint;
602     mForceUpdateIdleHint = false;
603     Unlock();
604 
605     if (!mHintSessionSupportChecked) {
606         checkPowerHintSessionSupport();
607     }
608 
609     updateIdleHint(deadlineTime, forceUpdateIdleHint);
610 
611     if (needUpdateRefreshRateHint) {
612         int32_t rc = updateRefreshRateHintInternal(powerMode, mRefreshRate);
613         if (rc != NO_ERROR && rc != -EOPNOTSUPP) {
614             Lock();
615             if (mPowerModeState == HWC2_POWER_MODE_ON) {
616                 /* Set the flag to trigger update again for next loop */
617                 mNeedUpdateRefreshRateHint = true;
618             }
619             Unlock();
620         }
621     }
622 
623     if (useHintSession) {
624         if (needStartHintSession) {
625             startHintSession();
626         }
627         sendActualWorkDuration();
628         updateTargetWorkDuration();
629     }
630 }
631 
addBinderTid(pid_t tid)632 void ExynosDisplay::PowerHalHintWorker::addBinderTid(pid_t tid) {
633     Lock();
634     if (mBinderTids.count(tid) != 0) {
635         Unlock();
636         return;
637     }
638     mTidsUpdated = true;
639     mBinderTids.emplace(tid);
640     Unlock();
641     Signal();
642 }
643 
removeBinderTid(pid_t tid)644 void ExynosDisplay::PowerHalHintWorker::removeBinderTid(pid_t tid) {
645     Lock();
646     if (mBinderTids.erase(tid) == 0) {
647         Unlock();
648         return;
649     }
650     mTidsUpdated = true;
651     Unlock();
652     Signal();
653 }
654 
startHintSession()655 int32_t ExynosDisplay::PowerHalHintWorker::startHintSession() {
656     Lock();
657     std::vector<int> tids(mBinderTids.begin(), mBinderTids.end());
658     nsecs_t targetWorkDuration =
659             sNormalizeTarget ? mLastTargetDurationReported : mTargetWorkDuration;
660     // we want to stay locked during this one since it assigns "mPowerHintSession"
661     auto ret = mPowerHalAidl->createHintSession(getpid(), static_cast<uid_t>(getuid()), tids,
662                                                 targetWorkDuration, &mPowerHintSession);
663     if (!ret.isOk()) {
664         ALOGW("Failed to start power hal hint session with error  %s %s", ret.getMessage(),
665               ret.getDescription().c_str());
666         if (ret.getExceptionCode() == EX_TRANSACTION_FAILED) {
667             mPowerHalExtAidl = nullptr;
668         }
669         Unlock();
670         return -EINVAL;
671     } else {
672         mLastTargetDurationReported = targetWorkDuration;
673     }
674     Unlock();
675     return NO_ERROR;
676 }
677 
checkPowerHintSessionReady()678 bool ExynosDisplay::PowerHalHintWorker::checkPowerHintSessionReady() {
679     static constexpr const std::chrono::milliseconds maxFlagWaitTime = 20s;
680     static const std::string propName =
681             "persist.device_config.surface_flinger_native_boot.AdpfFeature__adpf_cpu_hint";
682     static std::once_flag hintSessionFlag;
683     // wait once for 20 seconds in another thread for the value to become available, or give up
684     std::call_once(hintSessionFlag, [&] {
685         std::thread hintSessionChecker([&] {
686             std::optional<std::string> flagValue =
687                     waitForPropertyValue(propName, maxFlagWaitTime.count());
688             bool enabled = flagValue.has_value() &&
689                     (base::ParseBool(flagValue->c_str()) == base::ParseBoolResult::kTrue);
690             std::scoped_lock lock(sSharedDisplayMutex);
691             sSharedDisplayData.hintSessionEnabled = enabled;
692         });
693         hintSessionChecker.detach();
694     });
695     std::scoped_lock lock(sSharedDisplayMutex);
696     return sSharedDisplayData.hintSessionEnabled.has_value() &&
697             sSharedDisplayData.hintSessionSupported.has_value();
698 }
699 
usePowerHintSession()700 bool ExynosDisplay::PowerHalHintWorker::usePowerHintSession() {
701     std::optional<bool> useSessionCached{mUsePowerHintSession.load()};
702     if (useSessionCached.has_value()) {
703         return *useSessionCached;
704     }
705     if (!checkPowerHintSessionReady()) return false;
706     std::scoped_lock lock(sSharedDisplayMutex);
707     bool out = *(sSharedDisplayData.hintSessionEnabled) &&
708             (*(sSharedDisplayData.hintSessionSupported) == NO_ERROR);
709     mUsePowerHintSession.store(out);
710     return out;
711 }
712 
needUpdateTargetWorkDurationLocked()713 bool ExynosDisplay::PowerHalHintWorker::needUpdateTargetWorkDurationLocked() {
714     if (!usePowerHintSession() || sNormalizeTarget) return false;
715     // to disable the rate limiter we just use a max deviation of 1
716     nsecs_t maxDeviation = sUseRateLimiter ? kAllowedDeviation.count() : 1;
717     // report if the change in target from our last submission to now exceeds the threshold
718     return abs(mTargetWorkDuration - mLastTargetDurationReported) >= maxDeviation;
719 }
720 
needSendActualWorkDurationLocked()721 bool ExynosDisplay::PowerHalHintWorker::needSendActualWorkDurationLocked() {
722     if (!usePowerHintSession() || mPowerHintQueue.size() == 0 || !mActualWorkDuration.has_value()) {
723         return false;
724     }
725     if (!mLastErrorSent.has_value() ||
726         (systemTime(SYSTEM_TIME_MONOTONIC) - mLastActualReportTimestamp) > kStaleTimeout.count()) {
727         return true;
728     }
729     // to effectively disable the rate limiter we just use a max deviation of 1
730     nsecs_t maxDeviation = sUseRateLimiter ? kAllowedDeviation.count() : 1;
731     // report if the change in error term from our last submission to now exceeds the threshold
732     return abs((*mActualWorkDuration - mTargetWorkDuration) - *mLastErrorSent) >= maxDeviation;
733 }
734 
735 // track the tid of any thread that calls in and remove it on thread death
trackThisThread()736 void ExynosDisplay::PowerHalHintWorker::trackThisThread() {
737     thread_local struct TidTracker {
738         TidTracker(PowerHalHintWorker *worker) : mWorker(worker) {
739             mTid = gettid();
740             mWorker->addBinderTid(mTid);
741         }
742         ~TidTracker() { mWorker->removeBinderTid(mTid); }
743         pid_t mTid;
744         PowerHalHintWorker *mWorker;
745     } tracker(this);
746 }
747 
748 const bool ExynosDisplay::PowerHalHintWorker::sTraceHintSessionData =
749         base::GetBoolProperty(std::string("debug.hwc.trace_hint_sessions"), false);
750 
751 const bool ExynosDisplay::PowerHalHintWorker::sNormalizeTarget =
752         base::GetBoolProperty(std::string("debug.hwc.normalize_hint_session_durations"), false);
753 
754 const bool ExynosDisplay::PowerHalHintWorker::sUseRateLimiter =
755         base::GetBoolProperty(std::string("debug.hwc.use_rate_limiter"), true);
756 
757 ExynosDisplay::PowerHalHintWorker::SharedDisplayData
758         ExynosDisplay::PowerHalHintWorker::sSharedDisplayData;
759 
760 std::mutex ExynosDisplay::PowerHalHintWorker::sSharedDisplayMutex;
761 
compare(void const * lhs,void const * rhs)762 int ExynosSortedLayer::compare(void const *lhs, void const *rhs)
763 {
764     ExynosLayer *left = *((ExynosLayer**)(lhs));
765     ExynosLayer *right = *((ExynosLayer**)(rhs));
766     return left->mZOrder > right->mZOrder;
767 }
768 
remove(const ExynosLayer * item)769 ssize_t ExynosSortedLayer::remove(const ExynosLayer *item)
770 {
771     for (size_t i = 0; i < size(); i++)
772     {
773         if (array()[i] == item)
774         {
775             removeAt(i);
776             return i;
777         }
778     }
779     return -1;
780 }
781 
vector_sort()782 status_t ExynosSortedLayer::vector_sort()
783 {
784     int (*cmp)(ExynosLayer *const *, ExynosLayer *const *);
785     cmp = (int (*)(ExynosLayer *const *, ExynosLayer *const *)) &compare;
786     return sort(cmp);
787 }
788 
ExynosLowFpsLayerInfo()789 ExynosLowFpsLayerInfo::ExynosLowFpsLayerInfo()
790     : mHasLowFpsLayer(false),
791     mFirstIndex(-1),
792     mLastIndex(-1)
793 {
794 }
795 
initializeInfos()796 void ExynosLowFpsLayerInfo::initializeInfos()
797 {
798     mHasLowFpsLayer = false;
799     mFirstIndex = -1;
800     mLastIndex = -1;
801 }
802 
addLowFpsLayer(uint32_t layerIndex)803 int32_t ExynosLowFpsLayerInfo::addLowFpsLayer(uint32_t layerIndex)
804 {
805     if (mHasLowFpsLayer == false) {
806         mFirstIndex = layerIndex;
807         mLastIndex = layerIndex;
808         mHasLowFpsLayer = true;
809     } else {
810         mFirstIndex = min(mFirstIndex, (int32_t)layerIndex);
811         mLastIndex = max(mLastIndex, (int32_t)layerIndex);
812     }
813     return NO_ERROR;
814 }
815 
ExynosCompositionInfo(uint32_t type)816 ExynosCompositionInfo::ExynosCompositionInfo(uint32_t type)
817     : ExynosMPPSource(MPP_SOURCE_COMPOSITION_TARGET, this),
818     mType(type),
819     mHasCompositionLayer(false),
820     mFirstIndex(-1),
821     mLastIndex(-1),
822     mTargetBuffer(NULL),
823     mDataSpace(HAL_DATASPACE_UNKNOWN),
824     mAcquireFence(-1),
825     mReleaseFence(-1),
826     mEnableSkipStatic(false),
827     mSkipStaticInitFlag(false),
828     mSkipFlag(false),
829     mWindowIndex(-1)
830 {
831     /* If AFBC compression of mTargetBuffer is changed, */
832     /* mCompressionInfo should be set properly before resource assigning */
833 
834     char value[256];
835     int afbc_prop;
836     property_get("ro.vendor.ddk.set.afbc", value, "0");
837     afbc_prop = atoi(value);
838 
839     if (afbc_prop == 0)
840         mCompressionInfo.type = COMP_TYPE_NONE;
841     else
842         mCompressionInfo.type = COMP_TYPE_AFBC;
843 
844     memset(&mSkipSrcInfo, 0, sizeof(mSkipSrcInfo));
845     for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
846         mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
847         mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
848         mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
849         mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
850     }
851 
852     if(type == COMPOSITION_CLIENT)
853         mEnableSkipStatic = true;
854 
855     memset(&mLastWinConfigData, 0x0, sizeof(mLastWinConfigData));
856     mLastWinConfigData.acq_fence = -1;
857     mLastWinConfigData.rel_fence = -1;
858 }
859 
initializeInfosComplete(ExynosDisplay * display)860 void ExynosCompositionInfo::initializeInfosComplete(ExynosDisplay *display)
861 {
862     mTargetBuffer = NULL;
863     mDataSpace = HAL_DATASPACE_UNKNOWN;
864     if (mAcquireFence >= 0) {
865         ALOGD("ExynosCompositionInfo(%d):: mAcquire is not initialized(%d)", mType, mAcquireFence);
866         if (display != NULL)
867             fence_close(mAcquireFence, display, FENCE_TYPE_UNDEFINED, FENCE_IP_UNDEFINED);
868     }
869     mAcquireFence = -1;
870     initializeInfos(display);
871 }
872 
initializeInfos(ExynosDisplay * display)873 void ExynosCompositionInfo::initializeInfos(ExynosDisplay *display)
874 {
875     mHasCompositionLayer = false;
876     mFirstIndex = -1;
877     mLastIndex = -1;
878 
879     if (mType != COMPOSITION_CLIENT) {
880         mTargetBuffer = NULL;
881         mDataSpace = HAL_DATASPACE_UNKNOWN;
882         if (mAcquireFence >= 0) {
883             ALOGD("ExynosCompositionInfo(%d):: mAcquire is not initialized(%d)", mType, mAcquireFence);
884             if (display != NULL)
885                 fence_close(mAcquireFence, display, FENCE_TYPE_UNDEFINED, FENCE_IP_UNDEFINED);
886         }
887         mAcquireFence = -1;
888     }
889 
890     if (mReleaseFence >= 0) {
891         ALOGD("ExynosCompositionInfo(%d):: mReleaseFence is not initialized(%d)", mType, mReleaseFence);
892         if (display!= NULL)
893             fence_close(mReleaseFence, display, FENCE_TYPE_UNDEFINED, FENCE_IP_UNDEFINED);
894     }
895     mReleaseFence = -1;
896 
897     mWindowIndex = -1;
898     mOtfMPP = NULL;
899     mM2mMPP = NULL;
900     if ((display != NULL) &&
901         (display->mType == HWC_DISPLAY_VIRTUAL) &&
902         (mType == COMPOSITION_EXYNOS)) {
903         mM2mMPP = display->mResourceManager->getExynosMPP(MPP_LOGICAL_G2D_COMBO);
904     }
905 }
906 
setTargetBuffer(ExynosDisplay * display,buffer_handle_t handle,int32_t acquireFence,android_dataspace dataspace)907 void ExynosCompositionInfo::setTargetBuffer(ExynosDisplay *display, buffer_handle_t handle,
908         int32_t acquireFence, android_dataspace dataspace)
909 {
910     mTargetBuffer = handle;
911     if (mType == COMPOSITION_CLIENT) {
912         if (display != NULL) {
913             if (mAcquireFence >= 0) {
914                 mAcquireFence =
915                         fence_close(mAcquireFence, display, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
916             }
917             mAcquireFence = hwcCheckFenceDebug(display, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_FB, acquireFence);
918         }
919     } else {
920         if (display != NULL) {
921             if (mAcquireFence >= 0) {
922                 mAcquireFence =
923                         fence_close(mAcquireFence, display, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
924             }
925             mAcquireFence = hwcCheckFenceDebug(display, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, acquireFence);
926         }
927     }
928     if ((display != NULL) && (mDataSpace != dataspace))
929         display->setGeometryChanged(GEOMETRY_DISPLAY_DATASPACE_CHANGED);
930     mDataSpace = dataspace;
931 }
932 
setCompressionType(uint32_t compressionType)933 void ExynosCompositionInfo::setCompressionType(uint32_t compressionType) {
934     mCompressionInfo.type = compressionType;
935 }
936 
dump(String8 & result) const937 void ExynosCompositionInfo::dump(String8& result) const {
938     result.appendFormat("CompositionInfo (%d)\n", mType);
939     result.appendFormat("mHasCompositionLayer(%d)\n", mHasCompositionLayer);
940     if (mHasCompositionLayer) {
941         result.appendFormat("\tfirstIndex: %d, lastIndex: %d, dataSpace: 0x%8x, compression: %s, "
942                             "windowIndex: %d\n",
943                             mFirstIndex, mLastIndex, mDataSpace,
944                             getCompressionStr(mCompressionInfo).c_str(), mWindowIndex);
945         result.appendFormat("\thandle: %p, acquireFence: %d, releaseFence: %d, skipFlag: %d",
946                 mTargetBuffer, mAcquireFence, mReleaseFence, mSkipFlag);
947         if ((mOtfMPP == NULL) && (mM2mMPP == NULL))
948             result.appendFormat("\tresource is not assigned\n");
949         if (mOtfMPP != NULL)
950             result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.c_str());
951         if (mM2mMPP != NULL)
952             result.appendFormat("\t%s\n", mM2mMPP->mName.c_str());
953     }
954     if (mTargetBuffer != NULL) {
955         uint64_t internal_format = 0;
956         internal_format = VendorGraphicBufferMeta::get_internal_format(mTargetBuffer);
957         result.appendFormat("\tinternal_format: 0x%" PRIx64 ", afbc: %d\n", internal_format,
958                             isAFBCCompressed(mTargetBuffer));
959     }
960     uint32_t assignedSrcNum = 0;
961     if ((mM2mMPP != NULL) &&
962         ((assignedSrcNum = mM2mMPP->mAssignedSources.size()) > 0)) {
963         result.appendFormat("\tAssigned source num: %d\n", assignedSrcNum);
964         result.append("\t");
965         for (uint32_t i = 0; i < assignedSrcNum; i++) {
966             if (mM2mMPP->mAssignedSources[i]->mSourceType == MPP_SOURCE_LAYER) {
967                 ExynosLayer* layer = (ExynosLayer*)(mM2mMPP->mAssignedSources[i]);
968                 result.appendFormat("[%d]layer_%p ", i, layer->mLayerBuffer);
969             } else {
970                 result.appendFormat("[%d]sourceType_%d ", i, mM2mMPP->mAssignedSources[i]->mSourceType);
971             }
972         }
973         result.append("\n");
974     }
975     result.append("\n");
976 }
977 
getTypeStr()978 String8 ExynosCompositionInfo::getTypeStr()
979 {
980     switch(mType) {
981     case COMPOSITION_NONE:
982         return String8("COMPOSITION_NONE");
983     case COMPOSITION_CLIENT:
984         return String8("COMPOSITION_CLIENT");
985     case COMPOSITION_EXYNOS:
986         return String8("COMPOSITION_EXYNOS");
987     default:
988         return String8("InvalidType");
989     }
990 }
991 
ExynosDisplay(uint32_t type,uint32_t index,ExynosDevice * device,const std::string & displayName)992 ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice* device,
993                              const std::string& displayName)
994       : mDisplayId(getDisplayId(type, index)),
995         mType(type),
996         mIndex(index),
997         mDeconNodeName(""),
998         mXres(1440),
999         mYres(2960),
1000         mXdpi(25400),
1001         mYdpi(25400),
1002         mVsyncPeriod(kDefaultVsyncPeriodNanoSecond),
1003         mBtsFrameScanoutPeriod(kDefaultVsyncPeriodNanoSecond),
1004         mBtsPendingOperationRatePeriod(0),
1005         mDevice(device),
1006         mDisplayName(displayName.c_str()),
1007         mDisplayTraceName(String8::format("%s(%d)", displayName.c_str(), mDisplayId)),
1008         mPlugState(false),
1009         mHasSingleBuffer(false),
1010         mResourceManager(NULL),
1011         mClientCompositionInfo(COMPOSITION_CLIENT),
1012         mExynosCompositionInfo(COMPOSITION_EXYNOS),
1013         mGeometryChanged(0x0),
1014         mBufferUpdates(0),
1015         mRenderingState(RENDERING_STATE_NONE),
1016         mHWCRenderingState(RENDERING_STATE_NONE),
1017         mDisplayBW(0),
1018         mDynamicReCompMode(CLIENT_2_DEVICE),
1019         mDREnable(false),
1020         mDRDefault(false),
1021         mLastFpsTime(0),
1022         mFrameCount(0),
1023         mLastFrameCount(0),
1024         mErrorFrameCount(0),
1025         mUpdateEventCnt(0),
1026         mUpdateCallCnt(0),
1027         mDefaultDMA(MAX_DECON_DMA_TYPE),
1028         mLastRetireFence(-1),
1029         mWindowNumUsed(0),
1030         mBaseWindowIndex(0),
1031         mNumMaxPriorityAllowed(1),
1032         mCursorIndex(-1),
1033         mColorTransformHint(HAL_COLOR_TRANSFORM_IDENTITY),
1034         mMaxLuminance(0),
1035         mMaxAverageLuminance(0),
1036         mMinLuminance(0),
1037         mDisplayTe2Manager(nullptr),
1038         mHWC1LayerList(NULL),
1039         /* Support DDI scalser */
1040         mOldScalerMode(0),
1041         mNewScaledWidth(0),
1042         mNewScaledHeight(0),
1043         mDeviceXres(0),
1044         mDeviceYres(0),
1045         mColorMode(HAL_COLOR_MODE_NATIVE),
1046         mSkipFrame(false),
1047         mVsyncPeriodChangeConstraints{systemTime(SYSTEM_TIME_MONOTONIC), 0},
1048         mVsyncAppliedTimeLine{false, 0, systemTime(SYSTEM_TIME_MONOTONIC)},
1049         mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_DONE),
1050         mPowerHalHint(mDisplayId, mDisplayTraceName),
1051         mErrLogFileWriter(2, ERR_LOG_SIZE),
1052         mDebugDumpFileWriter(10, 1, ".dump"),
1053         mFenceFileWriter(2, FENCE_ERR_LOG_SIZE),
1054         mOperationRateManager(nullptr) {
1055     mDisplayControl.enableCompositionCrop = true;
1056     mDisplayControl.enableExynosCompositionOptimization = true;
1057     mDisplayControl.enableClientCompositionOptimization = true;
1058     mDisplayControl.useMaxG2DSrc = false;
1059     mDisplayControl.handleLowFpsLayers = false;
1060     mDisplayControl.earlyStartMPP = true;
1061     mDisplayControl.adjustDisplayFrame = false;
1062     mDisplayControl.cursorSupport = false;
1063 
1064     mDisplayConfigs.clear();
1065 
1066     mPowerModeState = std::nullopt;
1067 
1068     mVsyncState = HWC2_VSYNC_DISABLE;
1069 
1070     /* TODO : Exception handling here */
1071 
1072     if (device == NULL) {
1073         ALOGE("Display creation failed!");
1074         return;
1075     }
1076 
1077     mResourceManager = device->mResourceManager;
1078 
1079     /* The number of window is same with the number of otfMPP */
1080     mMaxWindowNum = mResourceManager->getOtfMPPs().size();
1081 
1082     mDpuData.init(mMaxWindowNum, 0);
1083     mLastDpuData.init(mMaxWindowNum, 0);
1084     ALOGI("window configs size(%zu)", mDpuData.configs.size());
1085 
1086     mLowFpsLayerInfo.initializeInfos();
1087 
1088     mPowerHalHint.Init();
1089 
1090     mUseDpu = true;
1091     mHpdStatus = false;
1092 
1093     return;
1094 }
1095 
~ExynosDisplay()1096 ExynosDisplay::~ExynosDisplay()
1097 {
1098 }
1099 
1100 /**
1101  * Member function for Dynamic AFBC Control solution.
1102  */
comparePreferedLayers()1103 bool ExynosDisplay::comparePreferedLayers() {
1104     return false;
1105 }
1106 
getId()1107 int ExynosDisplay::getId() {
1108     return mDisplayId;
1109 }
1110 
initDisplay()1111 void ExynosDisplay::initDisplay() {
1112     mClientCompositionInfo.initializeInfos(this);
1113     mClientCompositionInfo.mEnableSkipStatic = true;
1114     mClientCompositionInfo.mSkipStaticInitFlag = false;
1115     mClientCompositionInfo.mSkipFlag = false;
1116     memset(&mClientCompositionInfo.mSkipSrcInfo, 0x0, sizeof(mClientCompositionInfo.mSkipSrcInfo));
1117     for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
1118         mClientCompositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
1119         mClientCompositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
1120         mClientCompositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
1121         mClientCompositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
1122     }
1123     memset(&mClientCompositionInfo.mLastWinConfigData, 0x0, sizeof(mClientCompositionInfo.mLastWinConfigData));
1124     mClientCompositionInfo.mLastWinConfigData.acq_fence = -1;
1125     mClientCompositionInfo.mLastWinConfigData.rel_fence = -1;
1126 
1127     mExynosCompositionInfo.initializeInfos(this);
1128     mExynosCompositionInfo.mEnableSkipStatic = false;
1129     mExynosCompositionInfo.mSkipStaticInitFlag = false;
1130     mExynosCompositionInfo.mSkipFlag = false;
1131     memset(&mExynosCompositionInfo.mSkipSrcInfo, 0x0, sizeof(mExynosCompositionInfo.mSkipSrcInfo));
1132     for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
1133         mExynosCompositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
1134         mExynosCompositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
1135         mExynosCompositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
1136         mExynosCompositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
1137     }
1138 
1139     memset(&mExynosCompositionInfo.mLastWinConfigData, 0x0, sizeof(mExynosCompositionInfo.mLastWinConfigData));
1140     mExynosCompositionInfo.mLastWinConfigData.acq_fence = -1;
1141     mExynosCompositionInfo.mLastWinConfigData.rel_fence = -1;
1142 
1143     mGeometryChanged = 0x0;
1144     mRenderingState = RENDERING_STATE_NONE;
1145     mDisplayBW = 0;
1146     mDynamicReCompMode = CLIENT_2_DEVICE;
1147     mCursorIndex = -1;
1148 
1149     mDpuData.reset();
1150     mLastDpuData.reset();
1151 
1152     if (mDisplayControl.earlyStartMPP == true) {
1153         for (size_t i = 0; i < mLayers.size(); i++) {
1154             exynos_image outImage;
1155             ExynosMPP* m2mMPP = mLayers[i]->mM2mMPP;
1156 
1157             /* Close release fence of dst buffer of last frame */
1158             if ((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
1159                 (m2mMPP != NULL) &&
1160                 (m2mMPP->mAssignedDisplay == this) &&
1161                 (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
1162                 if (m2mMPP->mPhysicalType == MPP_MSC) {
1163                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
1164                 } else if (m2mMPP->mPhysicalType == MPP_G2D) {
1165                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
1166                 } else {
1167                     DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
1168                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
1169                 }
1170                 m2mMPP->resetDstReleaseFence();
1171             }
1172         }
1173     }
1174 }
1175 
1176 /**
1177  * @param outLayer
1178  * @return int32_t
1179  */
destroyLayer(hwc2_layer_t outLayer)1180 int32_t ExynosDisplay::destroyLayer(hwc2_layer_t outLayer) {
1181 
1182     Mutex::Autolock lock(mDRMutex);
1183     ExynosLayer *layer = (ExynosLayer *)outLayer;
1184 
1185     if (layer == nullptr) {
1186         return HWC2_ERROR_BAD_LAYER;
1187     }
1188 
1189     if (mLayers.remove(layer) < 0) {
1190         auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), layer);
1191         if (it == mIgnoreLayers.end()) {
1192             ALOGE("%s:: There is no layer", __func__);
1193         } else {
1194             mIgnoreLayers.erase(it);
1195         }
1196     } else {
1197         setGeometryChanged(GEOMETRY_DISPLAY_LAYER_REMOVED);
1198     }
1199 
1200     mDisplayInterface->destroyLayer(layer);
1201     layer->resetAssignedResource();
1202 
1203     delete layer;
1204 
1205     if (mPlugState == false) {
1206         DISPLAY_LOGI("%s : destroyLayer is done. But display is already disconnected",
1207                 __func__);
1208         return HWC2_ERROR_BAD_DISPLAY;
1209     }
1210 
1211     return HWC2_ERROR_NONE;
1212 }
1213 
1214 /**
1215  * @return void
1216  */
destroyLayers()1217 void ExynosDisplay::destroyLayers() {
1218     Mutex::Autolock lock(mDRMutex);
1219     for (uint32_t index = 0; index < mLayers.size();) {
1220         ExynosLayer *layer = mLayers[index];
1221         mLayers.removeAt(index);
1222         delete layer;
1223     }
1224 
1225     for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
1226         ExynosLayer *layer = *it;
1227         it = mIgnoreLayers.erase(it);
1228         delete layer;
1229     }
1230 }
1231 
checkLayer(hwc2_layer_t addr)1232 ExynosLayer *ExynosDisplay::checkLayer(hwc2_layer_t addr) {
1233     ExynosLayer *temp = (ExynosLayer *)addr;
1234     if (!mLayers.isEmpty()) {
1235         for (size_t i = 0; i < mLayers.size(); i++) {
1236             if (mLayers[i] == temp)
1237                 return mLayers[i];
1238         }
1239     }
1240 
1241     if (mIgnoreLayers.size()) {
1242         auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), temp);
1243         return (it == mIgnoreLayers.end()) ? NULL : *it;
1244     }
1245 
1246     ALOGE("HWC2 : %s : %d, wrong layer request!", __func__, __LINE__);
1247     return NULL;
1248 }
1249 
checkIgnoreLayers()1250 void ExynosDisplay::checkIgnoreLayers() {
1251     Mutex::Autolock lock(mDRMutex);
1252     for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
1253         ExynosLayer *layer = *it;
1254         if ((layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) == 0) {
1255             mLayers.push_back(layer);
1256             it = mIgnoreLayers.erase(it);
1257         } else {
1258             it++;
1259         }
1260     }
1261 
1262     for (uint32_t index = 0; index < mLayers.size();) {
1263         ExynosLayer *layer = mLayers[index];
1264         if (layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) {
1265             layer->resetValidateData();
1266             layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
1267             /*
1268              * Directly close without counting down
1269              * because it was not counted by validate
1270              */
1271             if (layer->mAcquireFence > 0) {
1272                 close(layer->mAcquireFence);
1273             }
1274             layer->mAcquireFence = -1;
1275 
1276             layer->mReleaseFence = -1;
1277             mIgnoreLayers.push_back(layer);
1278             mLayers.removeAt(index);
1279         } else {
1280             index++;
1281         }
1282     }
1283 }
1284 
1285 /**
1286  * @return void
1287  */
doPreProcessing()1288 void ExynosDisplay::doPreProcessing() {
1289     /* Low persistence setting */
1290     int ret = 0;
1291     bool hasSingleBuffer = false;
1292     bool hasClientLayer = false;
1293 
1294     for (size_t i=0; i < mLayers.size(); i++) {
1295         buffer_handle_t handle = mLayers[i]->mLayerBuffer;
1296         VendorGraphicBufferMeta gmeta(handle);
1297         if (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CLIENT) {
1298             hasClientLayer = true;
1299         }
1300 
1301         exynos_image srcImg;
1302         exynos_image dstImg;
1303         mLayers[i]->setSrcExynosImage(&srcImg);
1304         mLayers[i]->setDstExynosImage(&dstImg);
1305         mLayers[i]->setExynosImage(srcImg, dstImg);
1306     }
1307 
1308     /*
1309      * Disable skip static layer feature if there is the layer that's
1310      * mCompositionType  is HWC2_COMPOSITION_CLIENT
1311      * HWC should not change compositionType if it is HWC2_COMPOSITION_CLIENT
1312      */
1313     if (mType != HWC_DISPLAY_VIRTUAL)
1314         mClientCompositionInfo.mEnableSkipStatic = (!hasClientLayer && !hasSingleBuffer);
1315 
1316     if (mHasSingleBuffer != hasSingleBuffer) {
1317         if ((ret = mDisplayInterface->disableSelfRefresh(uint32_t(hasSingleBuffer))) < 0)
1318             DISPLAY_LOGE("ioctl S3CFB_LOW_PERSISTENCE failed: %s ret(%d)", strerror(errno), ret);
1319 
1320         mDisplayControl.skipM2mProcessing = !hasSingleBuffer;
1321         mHasSingleBuffer = hasSingleBuffer;
1322         setGeometryChanged(GEOMETRY_DISPLAY_SINGLEBUF_CHANGED);
1323     }
1324 
1325     if ((exynosHWCControl.displayMode < DISPLAY_MODE_NUM) &&
1326         (mDevice->mDisplayMode != exynosHWCControl.displayMode))
1327         setGeometryChanged(GEOMETRY_DEVICE_DISP_MODE_CHAGED);
1328 
1329     if ((ret = mResourceManager->checkScenario(this)) != NO_ERROR)
1330         DISPLAY_LOGE("checkScenario error ret(%d)", ret);
1331 
1332     if (exynosHWCControl.skipResourceAssign == 0) {
1333         /* Set any flag to mGeometryChanged */
1334         setGeometryChanged(GEOMETRY_DEVICE_SCENARIO_CHANGED);
1335     }
1336 #ifdef HWC_NO_SUPPORT_SKIP_VALIDATE
1337     if (mDevice->checkNonInternalConnection()) {
1338         /* Set any flag to mGeometryChanged */
1339         mDevice->mGeometryChanged = 0x10;
1340     }
1341 #endif
1342 
1343     return;
1344 }
1345 
1346 /**
1347  * @return int
1348  */
checkLayerFps()1349 int ExynosDisplay::checkLayerFps() {
1350     mLowFpsLayerInfo.initializeInfos();
1351 
1352     if (mDisplayControl.handleLowFpsLayers == false)
1353         return NO_ERROR;
1354 
1355     Mutex::Autolock lock(mDRMutex);
1356 
1357     for (size_t i=0; i < mLayers.size(); i++) {
1358         if ((mLayers[i]->mOverlayPriority < ePriorityHigh) &&
1359             (mLayers[i]->getFps() < LOW_FPS_THRESHOLD)) {
1360             mLowFpsLayerInfo.addLowFpsLayer(i);
1361         } else if (mLowFpsLayerInfo.mHasLowFpsLayer == true) {
1362             break;
1363         }
1364     }
1365     /* There is only one low fps layer, Overlay is better in this case */
1366     if ((mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
1367         (mLowFpsLayerInfo.mFirstIndex == mLowFpsLayerInfo.mLastIndex))
1368         mLowFpsLayerInfo.initializeInfos();
1369 
1370     return NO_ERROR;
1371 }
1372 
switchDynamicReCompMode(dynamic_recomp_mode mode)1373 int ExynosDisplay::switchDynamicReCompMode(dynamic_recomp_mode mode) {
1374     if (mDynamicReCompMode == mode) return NO_MODE_SWITCH;
1375 
1376     ATRACE_INT("Force client composition by DR", (mode == DEVICE_2_CLIENT));
1377     mDynamicReCompMode = mode;
1378     setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
1379     return mode;
1380 }
1381 
1382 /**
1383  * @return int
1384  */
checkDynamicReCompMode()1385 int ExynosDisplay::checkDynamicReCompMode() {
1386     ATRACE_CALL();
1387     Mutex::Autolock lock(mDRMutex);
1388 
1389     if (!exynosHWCControl.useDynamicRecomp) {
1390         mLastModeSwitchTimeStamp = 0;
1391         return switchDynamicReCompMode(CLIENT_2_DEVICE);
1392     }
1393 
1394     /* initialize the Timestamps */
1395     if (!mLastModeSwitchTimeStamp) {
1396         mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1397         return switchDynamicReCompMode(CLIENT_2_DEVICE);
1398     }
1399 
1400     /* Avoid to use DEVICE_2_CLIENT if there's a layer with priority >= ePriorityHigh such as:
1401      * front buffer, video layer, HDR, DRM layer, etc.
1402      */
1403     for (size_t i = 0; i < mLayers.size(); i++) {
1404         if ((mLayers[i]->mOverlayPriority >= ePriorityHigh) ||
1405             mLayers[i]->mPreprocessedInfo.preProcessed) {
1406             auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
1407             if (ret) {
1408                 mUpdateCallCnt = 0;
1409                 mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1410                 DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by video layer");
1411             }
1412             return ret;
1413         }
1414     }
1415 
1416     unsigned int incomingPixels = 0;
1417     hwc_rect_t dispRect = {INT_MAX, INT_MAX, 0, 0};
1418     for (size_t i = 0; i < mLayers.size(); i++) {
1419         auto& r = mLayers[i]->mPreprocessedInfo.displayFrame;
1420         if (r.top < dispRect.top) dispRect.top = r.top;
1421         if (r.left < dispRect.left) dispRect.left = r.left;
1422         if (r.bottom > dispRect.bottom) dispRect.bottom = r.bottom;
1423         if (r.right > dispRect.right) dispRect.right = r.right;
1424         auto w = WIDTH(r);
1425         auto h = HEIGHT(r);
1426         incomingPixels += w * h;
1427     }
1428 
1429     /* Mode Switch is not required if total pixels are not more than the threshold */
1430     unsigned int mergedDisplayFrameSize = WIDTH(dispRect) * HEIGHT(dispRect);
1431     if (incomingPixels <= mergedDisplayFrameSize) {
1432         auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
1433         if (ret) {
1434             mUpdateCallCnt = 0;
1435             mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1436             DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by BW check");
1437         }
1438         return ret;
1439     }
1440 
1441     /*
1442      * There will be at least one composition call per one minute (because of time update)
1443      * To minimize the analysis overhead, just analyze it once in 5 second
1444      */
1445     auto timeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mLastModeSwitchTimeStamp;
1446 
1447     /*
1448      * previous CompModeSwitch was CLIENT_2_DEVICE: check fps after 5s from mLastModeSwitchTimeStamp
1449      * previous CompModeSwitch was DEVICE_2_CLIENT: check immediately
1450      */
1451     if ((mDynamicReCompMode != DEVICE_2_CLIENT) && (timeStampDiff < kLayerFpsStableTimeNs))
1452         return 0;
1453 
1454     mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
1455     float updateFps = 0;
1456     if ((mUpdateEventCnt != 1) &&
1457         (mDynamicReCompMode == DEVICE_2_CLIENT) && (mUpdateCallCnt == 1)) {
1458         DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] first frame after DEVICE_2_CLIENT");
1459         updateFps = kDynamicRecompFpsThreshold + 1;
1460     } else {
1461         float maxFps = 0;
1462         for (uint32_t i = 0; i < mLayers.size(); i++) {
1463             float layerFps = mLayers[i]->checkFps(/* increaseCount */ false);
1464             if (maxFps < layerFps) maxFps = layerFps;
1465         }
1466         updateFps = maxFps;
1467     }
1468     mUpdateCallCnt = 0;
1469 
1470     /*
1471      * FPS estimation.
1472      * If FPS is lower than kDynamicRecompFpsThreshold, try to switch the mode to GLES
1473      */
1474     if (updateFps < kDynamicRecompFpsThreshold) {
1475         auto ret = switchDynamicReCompMode(DEVICE_2_CLIENT);
1476         if (ret) {
1477             DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] DEVICE_2_CLIENT by low FPS(%.2f)",
1478                          updateFps);
1479         }
1480         return ret;
1481     } else {
1482         auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
1483         if (ret) {
1484             DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] CLIENT_2_HWC by high FPS((%.2f)",
1485                          updateFps);
1486         }
1487         return ret;
1488     }
1489 
1490     return 0;
1491 }
1492 
1493 /**
1494  * @return int
1495  */
handleDynamicReCompMode()1496 int ExynosDisplay::handleDynamicReCompMode() {
1497     return 0;
1498 }
1499 
1500 /**
1501  * @param changedBit
1502  * @return int
1503  */
setGeometryChanged(uint64_t changedBit)1504 void ExynosDisplay::setGeometryChanged(uint64_t changedBit) {
1505     mGeometryChanged |= changedBit;
1506     mDevice->setGeometryChanged(changedBit);
1507 }
1508 
clearGeometryChanged()1509 void ExynosDisplay::clearGeometryChanged()
1510 {
1511     mGeometryChanged = 0;
1512     mBufferUpdates = 0;
1513     for (size_t i=0; i < mLayers.size(); i++) {
1514         mLayers[i]->clearGeometryChanged();
1515     }
1516 }
1517 
handleStaticLayers(ExynosCompositionInfo & compositionInfo)1518 int ExynosDisplay::handleStaticLayers(ExynosCompositionInfo& compositionInfo)
1519 {
1520     if (compositionInfo.mType != COMPOSITION_CLIENT)
1521         return -EINVAL;
1522 
1523     if (mType == HWC_DISPLAY_VIRTUAL)
1524         return NO_ERROR;
1525 
1526     if (compositionInfo.mHasCompositionLayer == false) {
1527         DISPLAY_LOGD(eDebugSkipStaicLayer, "there is no client composition");
1528         return NO_ERROR;
1529     }
1530     if ((compositionInfo.mWindowIndex < 0) ||
1531         (compositionInfo.mWindowIndex >= (int32_t)mDpuData.configs.size()))
1532     {
1533         DISPLAY_LOGE("invalid mWindowIndex(%d)", compositionInfo.mWindowIndex);
1534         return -EINVAL;
1535     }
1536 
1537     exynos_win_config_data &config = mDpuData.configs[compositionInfo.mWindowIndex];
1538 
1539     /* Store configuration of client target configuration */
1540     if (compositionInfo.mSkipFlag == false) {
1541         compositionInfo.mLastWinConfigData = config;
1542         DISPLAY_LOGD(eDebugSkipStaicLayer, "config[%d] is stored",
1543                 compositionInfo.mWindowIndex);
1544     } else {
1545         for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1546             if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) &&
1547                 (mLayers[i]->mAcquireFence >= 0))
1548                 fence_close(mLayers[i]->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1549             mLayers[i]->mAcquireFence = -1;
1550             mLayers[i]->mReleaseFence = -1;
1551         }
1552 
1553         if (compositionInfo.mTargetBuffer == NULL) {
1554             fence_close(config.acq_fence, this,
1555                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1556 
1557             config = compositionInfo.mLastWinConfigData;
1558             /* Assigned otfMPP for client target can be changed */
1559             config.assignedMPP = compositionInfo.mOtfMPP;
1560             /* acq_fence was closed by DPU driver in the previous frame */
1561             config.acq_fence = -1;
1562         } else {
1563             /* Check target buffer is same with previous frame */
1564             if (!std::equal(config.fd_idma, config.fd_idma+3, compositionInfo.mLastWinConfigData.fd_idma)) {
1565                 DISPLAY_LOGE("Current config [%d][%d, %d, %d]",
1566                         compositionInfo.mWindowIndex,
1567                         config.fd_idma[0], config.fd_idma[1], config.fd_idma[2]);
1568                 DISPLAY_LOGE("=============================  dump last win configs  ===================================");
1569                 for (size_t i = 0; i < mLastDpuData.configs.size(); i++) {
1570                     android::String8 result;
1571                     result.appendFormat("config[%zu]\n", i);
1572                     dumpConfig(result, mLastDpuData.configs[i]);
1573                     DISPLAY_LOGE("%s", result.c_str());
1574                 }
1575                 DISPLAY_LOGE("compositionInfo.mLastWinConfigData config [%d, %d, %d]",
1576                         compositionInfo.mLastWinConfigData.fd_idma[0],
1577                         compositionInfo.mLastWinConfigData.fd_idma[1],
1578                         compositionInfo.mLastWinConfigData.fd_idma[2]);
1579                 return -EINVAL;
1580             }
1581         }
1582 
1583         DISPLAY_LOGD(eDebugSkipStaicLayer, "skipStaticLayer config[%d]", compositionInfo.mWindowIndex);
1584         dumpConfig(config);
1585     }
1586 
1587     return NO_ERROR;
1588 }
1589 
skipStaticLayerChanged(ExynosCompositionInfo & compositionInfo)1590 bool ExynosDisplay::skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo)
1591 {
1592     if ((int)compositionInfo.mSkipSrcInfo.srcNum !=
1593             (compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1)) {
1594         DISPLAY_LOGD(eDebugSkipStaicLayer, "Client composition number is changed (%d -> %d)",
1595                 compositionInfo.mSkipSrcInfo.srcNum,
1596                 compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1);
1597         return true;
1598     }
1599 
1600     bool isChanged = false;
1601     for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1602         ExynosLayer *layer = mLayers[i];
1603         size_t index = i - compositionInfo.mFirstIndex;
1604         if ((layer->mLayerBuffer == NULL) ||
1605             (compositionInfo.mSkipSrcInfo.srcInfo[index].bufferHandle != layer->mLayerBuffer))
1606         {
1607             isChanged = true;
1608             DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] handle is changed"\
1609                     " handle(%p -> %p), layerFlag(0x%8x)",
1610                     i, compositionInfo.mSkipSrcInfo.srcInfo[index].bufferHandle,
1611                     layer->mLayerBuffer, layer->mLayerFlag);
1612             break;
1613         } else if ((compositionInfo.mSkipSrcInfo.srcInfo[index].x != layer->mSrcImg.x) ||
1614                 (compositionInfo.mSkipSrcInfo.srcInfo[index].y != layer->mSrcImg.y) ||
1615                 (compositionInfo.mSkipSrcInfo.srcInfo[index].w != layer->mSrcImg.w) ||
1616                 (compositionInfo.mSkipSrcInfo.srcInfo[index].h != layer->mSrcImg.h) ||
1617                 (compositionInfo.mSkipSrcInfo.srcInfo[index].dataSpace != layer->mSrcImg.dataSpace) ||
1618                 (compositionInfo.mSkipSrcInfo.srcInfo[index].blending != layer->mSrcImg.blending) ||
1619                 (compositionInfo.mSkipSrcInfo.srcInfo[index].transform != layer->mSrcImg.transform) ||
1620                 (compositionInfo.mSkipSrcInfo.srcInfo[index].planeAlpha != layer->mSrcImg.planeAlpha))
1621         {
1622             isChanged = true;
1623             DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] source info is changed, "\
1624                     "x(%d->%d), y(%d->%d), w(%d->%d), h(%d->%d), dataSpace(%d->%d), "\
1625                     "blending(%d->%d), transform(%d->%d), planeAlpha(%3.1f->%3.1f)", i,
1626                     compositionInfo.mSkipSrcInfo.srcInfo[index].x, layer->mSrcImg.x,
1627                     compositionInfo.mSkipSrcInfo.srcInfo[index].y, layer->mSrcImg.y,
1628                     compositionInfo.mSkipSrcInfo.srcInfo[index].w,  layer->mSrcImg.w,
1629                     compositionInfo.mSkipSrcInfo.srcInfo[index].h,  layer->mSrcImg.h,
1630                     compositionInfo.mSkipSrcInfo.srcInfo[index].dataSpace, layer->mSrcImg.dataSpace,
1631                     compositionInfo.mSkipSrcInfo.srcInfo[index].blending, layer->mSrcImg.blending,
1632                     compositionInfo.mSkipSrcInfo.srcInfo[index].transform, layer->mSrcImg.transform,
1633                     compositionInfo.mSkipSrcInfo.srcInfo[index].planeAlpha, layer->mSrcImg.planeAlpha);
1634             break;
1635         } else if ((compositionInfo.mSkipSrcInfo.dstInfo[index].x != layer->mDstImg.x) ||
1636                 (compositionInfo.mSkipSrcInfo.dstInfo[index].y != layer->mDstImg.y) ||
1637                 (compositionInfo.mSkipSrcInfo.dstInfo[index].w != layer->mDstImg.w) ||
1638                 (compositionInfo.mSkipSrcInfo.dstInfo[index].h != layer->mDstImg.h))
1639         {
1640             isChanged = true;
1641             DISPLAY_LOGD(eDebugSkipStaicLayer, "layer[%zu] dst info is changed, "\
1642                     "x(%d->%d), y(%d->%d), w(%d->%d), h(%d->%d)", i,
1643                     compositionInfo.mSkipSrcInfo.dstInfo[index].x, layer->mDstImg.x,
1644                     compositionInfo.mSkipSrcInfo.dstInfo[index].y, layer->mDstImg.y,
1645                     compositionInfo.mSkipSrcInfo.dstInfo[index].w, layer->mDstImg.w,
1646                     compositionInfo.mSkipSrcInfo.dstInfo[index].h, layer->mDstImg.h);
1647             break;
1648         }
1649     }
1650     return isChanged;
1651 }
1652 
requestLhbm(bool on)1653 void ExynosDisplay::requestLhbm(bool on) {
1654     mDevice->onRefresh(mDisplayId);
1655     if (mBrightnessController) {
1656         mBrightnessController->processLocalHbm(on);
1657     }
1658 }
1659 
1660 /**
1661  * @param compositionType
1662  * @return int
1663  */
skipStaticLayers(ExynosCompositionInfo & compositionInfo)1664 int ExynosDisplay::skipStaticLayers(ExynosCompositionInfo& compositionInfo)
1665 {
1666     compositionInfo.mSkipFlag = false;
1667 
1668     if (compositionInfo.mType != COMPOSITION_CLIENT)
1669         return -EINVAL;
1670 
1671     if ((exynosHWCControl.skipStaticLayers == 0) ||
1672         (compositionInfo.mEnableSkipStatic == false)) {
1673         DISPLAY_LOGD(eDebugSkipStaicLayer, "skipStaticLayers(%d), mEnableSkipStatic(%d)",
1674                 exynosHWCControl.skipStaticLayers, compositionInfo.mEnableSkipStatic);
1675         compositionInfo.mSkipStaticInitFlag = false;
1676         return NO_ERROR;
1677     }
1678 
1679     if ((compositionInfo.mHasCompositionLayer == false) ||
1680         (compositionInfo.mFirstIndex < 0) ||
1681         (compositionInfo.mLastIndex < 0) ||
1682         ((compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1) > NUM_SKIP_STATIC_LAYER)) {
1683         DISPLAY_LOGD(eDebugSkipStaicLayer, "mHasCompositionLayer(%d), mFirstIndex(%d), mLastIndex(%d)",
1684                 compositionInfo.mHasCompositionLayer,
1685                 compositionInfo.mFirstIndex, compositionInfo.mLastIndex);
1686         compositionInfo.mSkipStaticInitFlag = false;
1687         return NO_ERROR;
1688     }
1689 
1690     if (compositionInfo.mSkipStaticInitFlag) {
1691         bool isChanged = skipStaticLayerChanged(compositionInfo);
1692         if (isChanged == true) {
1693             compositionInfo.mSkipStaticInitFlag = false;
1694             return NO_ERROR;
1695         }
1696 
1697         for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1698             ExynosLayer *layer = mLayers[i];
1699             if (layer->mValidateCompositionType == COMPOSITION_CLIENT) {
1700                 layer->mOverlayInfo |= eSkipStaticLayer;
1701             } else {
1702                 compositionInfo.mSkipStaticInitFlag = false;
1703                 if (layer->mOverlayPriority < ePriorityHigh) {
1704                     DISPLAY_LOGE("[%zu] Invalid layer type: %d",
1705                             i, layer->mValidateCompositionType);
1706                     return -EINVAL;
1707                 } else {
1708                     return NO_ERROR;
1709                 }
1710             }
1711         }
1712 
1713         compositionInfo.mSkipFlag = true;
1714         DISPLAY_LOGD(eDebugSkipStaicLayer, "SkipStaicLayer is enabled");
1715         return NO_ERROR;
1716     }
1717 
1718     compositionInfo.mSkipStaticInitFlag = true;
1719     memset(&compositionInfo.mSkipSrcInfo, 0, sizeof(compositionInfo.mSkipSrcInfo));
1720     for (int i = 0; i < NUM_SKIP_STATIC_LAYER; i++) {
1721         compositionInfo.mSkipSrcInfo.srcInfo[i].acquireFenceFd = -1;
1722         compositionInfo.mSkipSrcInfo.srcInfo[i].releaseFenceFd = -1;
1723         compositionInfo.mSkipSrcInfo.dstInfo[i].acquireFenceFd = -1;
1724         compositionInfo.mSkipSrcInfo.dstInfo[i].releaseFenceFd = -1;
1725     }
1726 
1727     for (size_t i = (size_t)compositionInfo.mFirstIndex; i <= (size_t)compositionInfo.mLastIndex; i++) {
1728         ExynosLayer *layer = mLayers[i];
1729         size_t index = i - compositionInfo.mFirstIndex;
1730         compositionInfo.mSkipSrcInfo.srcInfo[index] = layer->mSrcImg;
1731         compositionInfo.mSkipSrcInfo.dstInfo[index] = layer->mDstImg;
1732         DISPLAY_LOGD(eDebugSkipStaicLayer, "mSkipSrcInfo.srcInfo[%zu] is initialized, %p",
1733                 index, layer->mSrcImg.bufferHandle);
1734     }
1735     compositionInfo.mSkipSrcInfo.srcNum = (compositionInfo.mLastIndex - compositionInfo.mFirstIndex + 1);
1736     return NO_ERROR;
1737 }
1738 
shouldSignalNonIdle(void)1739 bool ExynosDisplay::shouldSignalNonIdle(void) {
1740     // Some cases such that we can skip calling mPowerHalHint.signalNonIdle():
1741     // 1. Updating source crop or buffer for video layer
1742     // 2. Updating refresh rate indicator layer
1743     uint64_t exclude = GEOMETRY_LAYER_SOURCECROP_CHANGED;
1744     if ((mGeometryChanged & ~exclude) != 0) {
1745         return true;
1746     }
1747     for (size_t i = 0; i < mLayers.size(); i++) {
1748         // Frame update for refresh rate overlay indicator layer can be ignored
1749         if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
1750             continue;
1751         // Frame update for video layer can be ignored
1752         if (mLayers[i]->isLayerFormatYuv()) continue;
1753         if (mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer ||
1754             mLayers[i]->mGeometryChanged != 0) {
1755             return true;
1756         }
1757     }
1758     return false;
1759 }
1760 
1761 /**
1762  * @return int
1763  */
doPostProcessing()1764 int ExynosDisplay::doPostProcessing() {
1765 
1766     for (size_t i=0; i < mLayers.size(); i++) {
1767         /* Layer handle back-up */
1768         mLayers[i]->mLastLayerBuffer = mLayers[i]->mLayerBuffer;
1769     }
1770     clearGeometryChanged();
1771 
1772     return 0;
1773 }
1774 
validateExynosCompositionLayer()1775 bool ExynosDisplay::validateExynosCompositionLayer()
1776 {
1777     bool isValid = true;
1778     ExynosMPP *m2mMpp = mExynosCompositionInfo.mM2mMPP;
1779 
1780     int sourceSize = (int)m2mMpp->mAssignedSources.size();
1781     if ((mExynosCompositionInfo.mFirstIndex >= 0) &&
1782         (mExynosCompositionInfo.mLastIndex >= 0)) {
1783         sourceSize = mExynosCompositionInfo.mLastIndex - mExynosCompositionInfo.mFirstIndex + 1;
1784 
1785         if (!mUseDpu && mClientCompositionInfo.mHasCompositionLayer)
1786             sourceSize++;
1787     }
1788 
1789     if (m2mMpp->mAssignedSources.size() == 0) {
1790         DISPLAY_LOGE("No source images");
1791         isValid = false;
1792     } else if (mUseDpu && (((mExynosCompositionInfo.mFirstIndex < 0) ||
1793                (mExynosCompositionInfo.mLastIndex < 0)) ||
1794                (sourceSize != (int)m2mMpp->mAssignedSources.size()))) {
1795         DISPLAY_LOGE("Invalid index (%d, %d), size(%zu), sourceSize(%d)",
1796                 mExynosCompositionInfo.mFirstIndex,
1797                 mExynosCompositionInfo.mLastIndex,
1798                 m2mMpp->mAssignedSources.size(),
1799                 sourceSize);
1800         isValid = false;
1801     }
1802     if (isValid == false) {
1803         for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1804             /* break when only framebuffer target is assigned on ExynosCompositor */
1805             if (i == -1)
1806                 break;
1807 
1808             if (mLayers[i]->mAcquireFence >= 0)
1809                 fence_close(mLayers[i]->mAcquireFence, this,
1810                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1811             mLayers[i]->mAcquireFence = -1;
1812         }
1813         mExynosCompositionInfo.mM2mMPP->requestHWStateChange(MPP_HW_STATE_IDLE);
1814     }
1815     return isValid;
1816 }
1817 
1818 /**
1819  * @return int
1820  */
doExynosComposition()1821 int ExynosDisplay::doExynosComposition() {
1822     int ret = NO_ERROR;
1823     exynos_image src_img;
1824     exynos_image dst_img;
1825 
1826     if (mExynosCompositionInfo.mHasCompositionLayer) {
1827         if (mExynosCompositionInfo.mM2mMPP == NULL) {
1828             DISPLAY_LOGE("mExynosCompositionInfo.mM2mMPP is NULL");
1829             return -EINVAL;
1830         }
1831         mExynosCompositionInfo.mM2mMPP->requestHWStateChange(MPP_HW_STATE_RUNNING);
1832         /* mAcquireFence is updated, Update image info */
1833         for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1834             /* break when only framebuffer target is assigned on ExynosCompositor */
1835             if (i == -1)
1836                 break;
1837 
1838             struct exynos_image srcImg, dstImg;
1839             mLayers[i]->setSrcExynosImage(&srcImg);
1840             dumpExynosImage(eDebugFence, srcImg);
1841             mLayers[i]->setDstExynosImage(&dstImg);
1842             mLayers[i]->setExynosImage(srcImg, dstImg);
1843         }
1844 
1845         /* For debugging */
1846         if (validateExynosCompositionLayer() == false) {
1847             DISPLAY_LOGE("mExynosCompositionInfo is not valid");
1848             return -EINVAL;
1849         }
1850 
1851         if ((ret = mExynosCompositionInfo.mM2mMPP->doPostProcessing(
1852                      mExynosCompositionInfo.mDstImg)) != NO_ERROR) {
1853             DISPLAY_LOGE("exynosComposition doPostProcessing fail ret(%d)", ret);
1854             return ret;
1855         }
1856 
1857         for (int32_t i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
1858             /* break when only framebuffer target is assigned on ExynosCompositor */
1859             if (i == -1)
1860                 break;
1861             /* This should be closed by resource lib (libmpp or libacryl) */
1862             mLayers[i]->mAcquireFence = -1;
1863         }
1864 
1865         exynos_image outImage;
1866         if ((ret = mExynosCompositionInfo.mM2mMPP->getDstImageInfo(&outImage)) != NO_ERROR) {
1867             DISPLAY_LOGE("exynosComposition getDstImageInfo fail ret(%d)", ret);
1868             return ret;
1869         }
1870 
1871         android_dataspace dataspace = HAL_DATASPACE_UNKNOWN;
1872         if (mColorMode != HAL_COLOR_MODE_NATIVE)
1873             dataspace = colorModeToDataspace(mColorMode);
1874         mExynosCompositionInfo.setTargetBuffer(this, outImage.bufferHandle,
1875                 outImage.releaseFenceFd, dataspace);
1876         /*
1877          * buffer handle, dataspace can be changed by setTargetBuffer()
1878          * ExynosImage should be set again according to changed handle and dataspace
1879          */
1880         setCompositionTargetExynosImage(COMPOSITION_EXYNOS, &src_img, &dst_img);
1881         mExynosCompositionInfo.setExynosImage(src_img, dst_img);
1882 
1883         DISPLAY_LOGD(eDebugFence, "mExynosCompositionInfo acquireFencefd(%d)",
1884                      mExynosCompositionInfo.mAcquireFence);
1885 
1886         if ((ret =  mExynosCompositionInfo.mM2mMPP->resetDstReleaseFence()) != NO_ERROR)
1887         {
1888             DISPLAY_LOGE("exynosComposition resetDstReleaseFence fail ret(%d)", ret);
1889             return ret;
1890         }
1891     }
1892 
1893     return ret;
1894 }
1895 
getHDRException(ExynosLayer * __unused layer)1896 bool ExynosDisplay::getHDRException(ExynosLayer* __unused layer)
1897 {
1898     return false;
1899 }
1900 
configureHandle(ExynosLayer & layer,int fence_fd,exynos_win_config_data & cfg)1901 int32_t ExynosDisplay::configureHandle(ExynosLayer &layer, int fence_fd, exynos_win_config_data &cfg)
1902 {
1903     /* TODO : this is hardcoded */
1904     int32_t ret = NO_ERROR;
1905     buffer_handle_t handle = NULL;
1906     int32_t blending = 0x0100;
1907     uint32_t x = 0, y = 0;
1908     uint32_t w = WIDTH(layer.mPreprocessedInfo.displayFrame);
1909     uint32_t h = HEIGHT(layer.mPreprocessedInfo.displayFrame);
1910     ExynosMPP* otfMPP = NULL;
1911     ExynosMPP* m2mMPP = NULL;
1912     unsigned int luminanceMin = 0;
1913     unsigned int luminanceMax = 0;
1914 
1915     blending = layer.mBlending;
1916     otfMPP = layer.mOtfMPP;
1917     m2mMPP = layer.mM2mMPP;
1918 
1919     cfg.compressionInfo = layer.mCompressionInfo;
1920     if (layer.mCompressionInfo.type == COMP_TYPE_AFBC) {
1921         cfg.comp_src = DPP_COMP_SRC_GPU;
1922     }
1923     if (otfMPP == nullptr && layer.mExynosCompositionType != HWC2_COMPOSITION_DISPLAY_DECORATION) {
1924         HWC_LOGE(this, "%s:: otfMPP is NULL", __func__);
1925         return -EINVAL;
1926     }
1927     if (m2mMPP != NULL)
1928         handle = m2mMPP->mDstImgs[m2mMPP->mCurrentDstBuf].bufferHandle;
1929     else
1930         handle = layer.mLayerBuffer;
1931 
1932     if ((!layer.isDimLayer()) && handle == NULL) {
1933         HWC_LOGE(this, "%s:: invalid handle", __func__);
1934         return -EINVAL;
1935     }
1936 
1937     if (layer.mPreprocessedInfo.displayFrame.left < 0) {
1938         unsigned int crop = -layer.mPreprocessedInfo.displayFrame.left;
1939         DISPLAY_LOGD(eDebugWinConfig, "layer off left side of screen; cropping %u pixels from left edge",
1940                 crop);
1941         x = 0;
1942         w -= crop;
1943     } else {
1944         x = layer.mPreprocessedInfo.displayFrame.left;
1945     }
1946 
1947     if (layer.mPreprocessedInfo.displayFrame.right > (int)mXres) {
1948         unsigned int crop = layer.mPreprocessedInfo.displayFrame.right - mXres;
1949         DISPLAY_LOGD(eDebugWinConfig, "layer off right side of screen; cropping %u pixels from right edge",
1950                 crop);
1951         w -= crop;
1952     }
1953 
1954     if (layer.mPreprocessedInfo.displayFrame.top < 0) {
1955         unsigned int crop = -layer.mPreprocessedInfo.displayFrame.top;
1956         DISPLAY_LOGD(eDebugWinConfig, "layer off top side of screen; cropping %u pixels from top edge",
1957                 crop);
1958         y = 0;
1959         h -= crop;
1960     } else {
1961         y = layer.mPreprocessedInfo.displayFrame.top;
1962     }
1963 
1964     if (layer.mPreprocessedInfo.displayFrame.bottom > (int)mYres) {
1965         int crop = layer.mPreprocessedInfo.displayFrame.bottom - mYres;
1966         DISPLAY_LOGD(eDebugWinConfig, "layer off bottom side of screen; cropping %u pixels from bottom edge",
1967                 crop);
1968         h -= crop;
1969     }
1970 
1971     cfg.layer = &layer;
1972     if ((layer.mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
1973         (layer.mCompositionType == HWC2_COMPOSITION_CURSOR)) {
1974         cfg.state = cfg.WIN_STATE_CURSOR;
1975     } else if (layer.mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION) {
1976         cfg.state = cfg.WIN_STATE_RCD;
1977         assign(cfg.block_area, layer.mBlockingRect.left, layer.mBlockingRect.top,
1978                layer.mBlockingRect.right - layer.mBlockingRect.left,
1979                layer.mBlockingRect.bottom - layer.mBlockingRect.top);
1980     } else {
1981         cfg.state = cfg.WIN_STATE_BUFFER;
1982     }
1983 
1984     cfg.dst.x = x;
1985     cfg.dst.y = y;
1986     cfg.dst.w = w;
1987     cfg.dst.h = h;
1988     cfg.dst.f_w = mXres;
1989     cfg.dst.f_h = mYres;
1990 
1991     cfg.plane_alpha = layer.mPlaneAlpha;
1992     cfg.blending = blending;
1993     cfg.assignedMPP = otfMPP;
1994 
1995     if (layer.isDimLayer()) {
1996         if (fence_fd >= 0) {
1997             fence_fd = fence_close(fence_fd, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
1998         }
1999         cfg.state = cfg.WIN_STATE_COLOR;
2000         hwc_color_t color = layer.mColor;
2001         cfg.color = (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
2002         DISPLAY_LOGD(eDebugWinConfig, "HWC2: DIM layer is enabled, color: %d, alpha : %f",
2003                 cfg.color, cfg.plane_alpha);
2004         return ret;
2005     }
2006 
2007     VendorGraphicBufferMeta gmeta(handle);
2008 
2009     if (!layer.mPreprocessedInfo.mUsePrivateFormat)
2010         cfg.format = gmeta.format;
2011     else
2012         cfg.format = layer.mPreprocessedInfo.mPrivateFormat;
2013 
2014     cfg.buffer_id = gmeta.unique_id;
2015     cfg.fd_idma[0] = gmeta.fd;
2016     cfg.fd_idma[1] = gmeta.fd1;
2017     cfg.fd_idma[2] = gmeta.fd2;
2018     cfg.protection = (getDrmMode(gmeta.producer_usage) == SECURE_DRM) ? 1 : 0;
2019 
2020     exynos_image src_img = layer.mSrcImg;
2021 
2022     if (m2mMPP != NULL)
2023     {
2024         DISPLAY_LOGD(eDebugWinConfig, "\tUse m2mMPP, bufIndex: %d", m2mMPP->mCurrentDstBuf);
2025         dumpExynosImage(eDebugWinConfig, m2mMPP->mAssignedSources[0]->mMidImg);
2026         exynos_image mpp_dst_img;
2027         if (m2mMPP->getDstImageInfo(&mpp_dst_img) == NO_ERROR) {
2028             dumpExynosImage(eDebugWinConfig, mpp_dst_img);
2029             cfg.compressionInfo = mpp_dst_img.compressionInfo;
2030             cfg.src.f_w = mpp_dst_img.fullWidth;
2031             cfg.src.f_h = mpp_dst_img.fullHeight;
2032             cfg.src.x = mpp_dst_img.x;
2033             cfg.src.y = mpp_dst_img.y;
2034             cfg.src.w = mpp_dst_img.w;
2035             cfg.src.h = mpp_dst_img.h;
2036             cfg.format = mpp_dst_img.format;
2037             cfg.acq_fence =
2038                 hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, mpp_dst_img.releaseFenceFd);
2039 
2040             if (m2mMPP->mPhysicalType == MPP_MSC) {
2041                 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_MSC);
2042             } else if (m2mMPP->mPhysicalType == MPP_G2D) {
2043                 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_G2D);
2044             } else {
2045                 setFenceName(cfg.acq_fence, FENCE_DPP_SRC_MPP);
2046             }
2047             m2mMPP->resetDstReleaseFence();
2048         } else {
2049             HWC_LOGE(this, "%s:: Failed to get dst info of m2mMPP", __func__);
2050         }
2051         cfg.dataspace = mpp_dst_img.dataSpace;
2052 
2053         cfg.transform = 0;
2054 
2055         if (hasHdrInfo(layer.mMidImg)) {
2056             bool hdr_exception = getHDRException(&layer);
2057             uint32_t parcelFdIndex =
2058                     getBufferNumOfFormat(layer.mMidImg.format,
2059                                          getCompressionType(layer.mMidImg.bufferHandle));
2060             if (parcelFdIndex == 0) {
2061                 DISPLAY_LOGE("%s:: failed to get parcelFdIndex for midImg with format: %d",
2062                              __func__, layer.mMidImg.format);
2063                 return -EINVAL;
2064             }
2065             if (layer.mBufferHasMetaParcel) {
2066                 VendorGraphicBufferMeta layer_buffer_gmeta(layer.mLayerBuffer);
2067                 if (layer_buffer_gmeta.flags & VendorGraphicBufferMeta::PRIV_FLAGS_USES_2PRIVATE_DATA)
2068                     cfg.fd_idma[parcelFdIndex] = layer_buffer_gmeta.fd1;
2069                 else if (layer_buffer_gmeta.flags & VendorGraphicBufferMeta::PRIV_FLAGS_USES_3PRIVATE_DATA)
2070                     cfg.fd_idma[parcelFdIndex] = layer_buffer_gmeta.fd2;
2071             } else {
2072                 cfg.fd_idma[parcelFdIndex] = layer.mMetaParcelFd;
2073             }
2074 
2075             if (!hdr_exception)
2076                 cfg.hdr_enable = true;
2077             else
2078                 cfg.hdr_enable = false;
2079 
2080             /* Min/Max luminance should be set as M2M MPP's HDR operations
2081              * If HDR is not processed by M2M MPP, M2M's dst image should have source's min/max luminance
2082              * */
2083             dstMetaInfo_t metaInfo = m2mMPP->getDstMetaInfo(mpp_dst_img.dataSpace);
2084             luminanceMin = metaInfo.minLuminance;
2085             luminanceMax = metaInfo.maxLuminance;
2086             DISPLAY_LOGD(eDebugMPP, "HWC2: DPP luminance min %d, max %d", luminanceMin, luminanceMax);
2087         } else {
2088             cfg.hdr_enable = true;
2089         }
2090 
2091         src_img = layer.mMidImg;
2092     } else {
2093         cfg.src.f_w = src_img.fullWidth;
2094         cfg.src.f_h = src_img.fullHeight;
2095         cfg.src.x = layer.mPreprocessedInfo.sourceCrop.left;
2096         cfg.src.y = layer.mPreprocessedInfo.sourceCrop.top;
2097         cfg.src.w = WIDTH(layer.mPreprocessedInfo.sourceCrop) - (cfg.src.x - (uint32_t)layer.mPreprocessedInfo.sourceCrop.left);
2098         cfg.src.h = HEIGHT(layer.mPreprocessedInfo.sourceCrop) - (cfg.src.y - (uint32_t)layer.mPreprocessedInfo.sourceCrop.top);
2099         cfg.acq_fence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, fence_fd);
2100         setFenceName(cfg.acq_fence, FENCE_DPP_SRC_LAYER);
2101 
2102         cfg.dataspace = src_img.dataSpace;
2103         cfg.transform = src_img.transform;
2104 
2105         if (hasHdrInfo(src_img)) {
2106             bool hdr_exception = getHDRException(&layer);
2107             if (!hdr_exception)
2108                 cfg.hdr_enable = true;
2109             else
2110                 cfg.hdr_enable = false;
2111 
2112             if (layer.mBufferHasMetaParcel == false) {
2113                 uint32_t parcelFdIndex =
2114                         getBufferNumOfFormat(gmeta.format, getCompressionType(handle));
2115                 if (parcelFdIndex == 0) {
2116                     DISPLAY_LOGE("%s:: failed to get parcelFdIndex for srcImg with format: %d",
2117                                  __func__, gmeta.format);
2118                     return -EINVAL;
2119                 }
2120 
2121                 cfg.fd_idma[parcelFdIndex] = layer.mMetaParcelFd;
2122             }
2123 
2124             /*
2125              * Static info uses 0.0001nit unit for luminace
2126              * Display uses 1nit unit for max luminance
2127              * and uses 0.0001nit unit for min luminance
2128              * Conversion is required
2129              */
2130             luminanceMin = src_img.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
2131             luminanceMax = src_img.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000;
2132             DISPLAY_LOGD(eDebugMPP, "HWC2: DPP luminance min %d, max %d", luminanceMin, luminanceMax);
2133         } else {
2134             cfg.hdr_enable = true;
2135         }
2136     }
2137 
2138     cfg.min_luminance = luminanceMin;
2139     cfg.max_luminance = luminanceMax;
2140     cfg.needColorTransform = src_img.needColorTransform;
2141 
2142     /* Adjust configuration */
2143     uint32_t srcMaxWidth, srcMaxHeight, srcWidthAlign, srcHeightAlign = 0;
2144     uint32_t srcXAlign, srcYAlign, srcMaxCropWidth, srcMaxCropHeight, srcCropWidthAlign, srcCropHeightAlign = 0;
2145 
2146     if (otfMPP != nullptr) {
2147         srcMaxWidth = otfMPP->getSrcMaxWidth(src_img);
2148         srcMaxHeight = otfMPP->getSrcMaxHeight(src_img);
2149         srcWidthAlign = otfMPP->getSrcWidthAlign(src_img);
2150         srcHeightAlign = otfMPP->getSrcHeightAlign(src_img);
2151         srcXAlign = otfMPP->getSrcXOffsetAlign(src_img);
2152         srcYAlign = otfMPP->getSrcYOffsetAlign(src_img);
2153         srcMaxCropWidth = otfMPP->getSrcMaxCropWidth(src_img);
2154         srcMaxCropHeight = otfMPP->getSrcMaxCropHeight(src_img);
2155         srcCropWidthAlign = otfMPP->getSrcCropWidthAlign(src_img);
2156         srcCropHeightAlign = otfMPP->getSrcCropHeightAlign(src_img);
2157     }
2158 
2159     if (cfg.src.x < 0)
2160         cfg.src.x = 0;
2161     if (cfg.src.y < 0)
2162         cfg.src.y = 0;
2163 
2164     if (otfMPP != NULL) {
2165         if (cfg.src.f_w > srcMaxWidth)
2166             cfg.src.f_w = srcMaxWidth;
2167         if (cfg.src.f_h > srcMaxHeight)
2168             cfg.src.f_h = srcMaxHeight;
2169         cfg.src.f_w = pixel_align_down(cfg.src.f_w, srcWidthAlign);
2170         cfg.src.f_h = pixel_align_down(cfg.src.f_h, srcHeightAlign);
2171 
2172         cfg.src.x = pixel_align(cfg.src.x, srcXAlign);
2173         cfg.src.y = pixel_align(cfg.src.y, srcYAlign);
2174     }
2175 
2176     if (cfg.src.x + cfg.src.w > cfg.src.f_w)
2177         cfg.src.w = cfg.src.f_w - cfg.src.x;
2178     if (cfg.src.y + cfg.src.h > cfg.src.f_h)
2179         cfg.src.h = cfg.src.f_h - cfg.src.y;
2180 
2181     if (otfMPP != NULL) {
2182         if (cfg.src.w > srcMaxCropWidth)
2183             cfg.src.w = srcMaxCropWidth;
2184         if (cfg.src.h > srcMaxCropHeight)
2185             cfg.src.h = srcMaxCropHeight;
2186         cfg.src.w = pixel_align_down(cfg.src.w, srcCropWidthAlign);
2187         cfg.src.h = pixel_align_down(cfg.src.h, srcCropHeightAlign);
2188     }
2189 
2190     uint64_t bufSize = gmeta.size * formatToBpp(gmeta.format);
2191     uint64_t srcSize = cfg.src.f_w * cfg.src.f_h * formatToBpp(cfg.format);
2192 
2193     if (!isFormatLossy(gmeta.format) && (bufSize < srcSize)) {
2194         DISPLAY_LOGE("%s:: buffer size is smaller than source size, buf(size: %d, format: %d), src(w: %d, h: %d, format: %d)",
2195                 __func__, gmeta.size, gmeta.format, cfg.src.f_w, cfg.src.f_h, cfg.format);
2196         return -EINVAL;
2197     }
2198 
2199     return ret;
2200 }
2201 
2202 
configureOverlay(ExynosLayer * layer,exynos_win_config_data & cfg)2203 int32_t ExynosDisplay::configureOverlay(ExynosLayer *layer, exynos_win_config_data &cfg)
2204 {
2205     int32_t ret = NO_ERROR;
2206     if(layer != NULL) {
2207         if ((ret = configureHandle(*layer, layer->mAcquireFence, cfg)) != NO_ERROR)
2208             return ret;
2209 
2210         /* This will be closed by setReleaseFences() using config.acq_fence */
2211         layer->mAcquireFence = -1;
2212     }
2213     return ret;
2214 }
configureOverlay(ExynosCompositionInfo & compositionInfo)2215 int32_t ExynosDisplay::configureOverlay(ExynosCompositionInfo &compositionInfo)
2216 {
2217     int32_t windowIndex = compositionInfo.mWindowIndex;
2218     buffer_handle_t handle = compositionInfo.mTargetBuffer;
2219     VendorGraphicBufferMeta gmeta(compositionInfo.mTargetBuffer);
2220 
2221     if ((windowIndex < 0) || (windowIndex >= (int32_t)mDpuData.configs.size()))
2222     {
2223         HWC_LOGE(this, "%s:: ExynosCompositionInfo(%d) has invalid data, windowIndex(%d)",
2224                 __func__, compositionInfo.mType, windowIndex);
2225         return -EINVAL;
2226     }
2227 
2228     exynos_win_config_data &config = mDpuData.configs[windowIndex];
2229 
2230     if (handle == NULL) {
2231         /* config will be set by handleStaticLayers */
2232         if (compositionInfo.mSkipFlag)
2233             return NO_ERROR;
2234 
2235         if (compositionInfo.mType == COMPOSITION_CLIENT) {
2236             ALOGW("%s:: ExynosCompositionInfo(%d) has invalid data, handle(%p)",
2237                     __func__, compositionInfo.mType, handle);
2238             if (compositionInfo.mAcquireFence >= 0) {
2239                 compositionInfo.mAcquireFence = fence_close(compositionInfo.mAcquireFence, this,
2240                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
2241             }
2242             config.state = config.WIN_STATE_DISABLED;
2243             return NO_ERROR;
2244         } else {
2245             HWC_LOGE(this, "%s:: ExynosCompositionInfo(%d) has invalid data, handle(%p)",
2246                     __func__, compositionInfo.mType, handle);
2247             return -EINVAL;
2248         }
2249     }
2250 
2251     config.buffer_id = gmeta.unique_id;
2252     config.fd_idma[0] = gmeta.fd;
2253     config.fd_idma[1] = gmeta.fd1;
2254     config.fd_idma[2] = gmeta.fd2;
2255     config.protection = (getDrmMode(gmeta.producer_usage) == SECURE_DRM) ? 1 : 0;
2256     config.state = config.WIN_STATE_BUFFER;
2257 
2258     config.assignedMPP = compositionInfo.mOtfMPP;
2259 
2260     config.dst.f_w = mXres;
2261     config.dst.f_h = mYres;
2262     config.format = gmeta.format;
2263     if (compositionInfo.mType == COMPOSITION_EXYNOS) {
2264         config.src.f_w = pixel_align(mXres, G2D_JUSTIFIED_DST_ALIGN);
2265         config.src.f_h = pixel_align(mYres, G2D_JUSTIFIED_DST_ALIGN);
2266     } else {
2267         config.src.f_w = gmeta.stride;
2268         config.src.f_h = gmeta.vstride;
2269     }
2270     config.compressionInfo = compositionInfo.mCompressionInfo;
2271     if (compositionInfo.mCompressionInfo.type == COMP_TYPE_AFBC) {
2272         if (compositionInfo.mType == COMPOSITION_EXYNOS)
2273             config.comp_src = DPP_COMP_SRC_G2D;
2274         else if (compositionInfo.mType == COMPOSITION_CLIENT)
2275             config.comp_src = DPP_COMP_SRC_GPU;
2276         else
2277             HWC_LOGE(this, "unknown composition type: %d", compositionInfo.mType);
2278     }
2279 
2280     bool useCompositionCrop = true;
2281     if ((mDisplayControl.enableCompositionCrop) &&
2282         (compositionInfo.mHasCompositionLayer) &&
2283         (compositionInfo.mFirstIndex >= 0) &&
2284         (compositionInfo.mLastIndex >= 0)) {
2285         hwc_rect merged_rect, src_rect;
2286         merged_rect.left = mXres;
2287         merged_rect.top = mYres;
2288         merged_rect.right = 0;
2289         merged_rect.bottom = 0;
2290 
2291         for (int i = compositionInfo.mFirstIndex; i <= compositionInfo.mLastIndex; i++) {
2292             ExynosLayer *layer = mLayers[i];
2293             src_rect.left = layer->mDisplayFrame.left;
2294             src_rect.top = layer->mDisplayFrame.top;
2295             src_rect.right = layer->mDisplayFrame.right;
2296             src_rect.bottom = layer->mDisplayFrame.bottom;
2297             merged_rect = expand(merged_rect, src_rect);
2298             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]",
2299                     i,
2300                     layer->mCompositionType,
2301                     layer->mExynosCompositionType,
2302                     layer->mDisplayFrame.left,
2303                     layer->mDisplayFrame.top,
2304                     layer->mDisplayFrame.right,
2305                     layer->mDisplayFrame.bottom,
2306                     merged_rect.left,
2307                     merged_rect.top,
2308                     merged_rect.right,
2309                     merged_rect.bottom);
2310         }
2311 
2312         config.src.x = merged_rect.left;
2313         config.src.y = merged_rect.top;
2314         config.src.w = merged_rect.right - merged_rect.left;
2315         config.src.h = merged_rect.bottom - merged_rect.top;
2316 
2317         ExynosMPP* exynosMPP = config.assignedMPP;
2318         if (exynosMPP == NULL) {
2319             DISPLAY_LOGE("%s:: assignedMPP is NULL", __func__);
2320             useCompositionCrop = false;
2321         } else {
2322             /* Check size constraints */
2323             uint32_t restrictionIdx = getRestrictionIndex(config.format);
2324             uint32_t srcXAlign = exynosMPP->getSrcXOffsetAlign(restrictionIdx);
2325             uint32_t srcYAlign = exynosMPP->getSrcYOffsetAlign(restrictionIdx);
2326             uint32_t srcWidthAlign = exynosMPP->getSrcCropWidthAlign(restrictionIdx);
2327             uint32_t srcHeightAlign = exynosMPP->getSrcCropHeightAlign(restrictionIdx);
2328             uint32_t srcMinWidth = exynosMPP->getSrcMinWidth(restrictionIdx);
2329             uint32_t srcMinHeight = exynosMPP->getSrcMinHeight(restrictionIdx);
2330 
2331             if (config.src.w < srcMinWidth) {
2332                 config.src.x -= (srcMinWidth - config.src.w);
2333                 if (config.src.x < 0)
2334                     config.src.x = 0;
2335                 config.src.w = srcMinWidth;
2336             }
2337             if (config.src.h < srcMinHeight) {
2338                 config.src.y -= (srcMinHeight - config.src.h);
2339                 if (config.src.y < 0)
2340                     config.src.y = 0;
2341                 config.src.h = srcMinHeight;
2342             }
2343 
2344             int32_t alignedSrcX = pixel_align_down(config.src.x, srcXAlign);
2345             int32_t alignedSrcY = pixel_align_down(config.src.y, srcYAlign);
2346             config.src.w += (config.src.x - alignedSrcX);
2347             config.src.h += (config.src.y - alignedSrcY);
2348             config.src.x = alignedSrcX;
2349             config.src.y = alignedSrcY;
2350             config.src.w = pixel_align(config.src.w, srcWidthAlign);
2351             config.src.h = pixel_align(config.src.h, srcHeightAlign);
2352         }
2353 
2354         config.dst.x = config.src.x;
2355         config.dst.y = config.src.y;
2356         config.dst.w = config.src.w;
2357         config.dst.h = config.src.h;
2358 
2359         if ((config.src.x < 0) ||
2360             (config.src.y < 0) ||
2361             ((config.src.x + config.src.w) > mXres) ||
2362             ((config.src.y + config.src.h) > mYres)) {
2363             useCompositionCrop = false;
2364             ALOGW("Invalid composition target crop size: (%d, %d, %d, %d)",
2365                     config.src.x, config.src.y,
2366                     config.src.w, config.src.h);
2367         }
2368 
2369         DISPLAY_LOGD(eDebugWinConfig, "composition(%d) config[%d] x : %d, y : %d, w : %d, h : %d",
2370                 compositionInfo.mType, windowIndex,
2371                 config.dst.x, config.dst.y,
2372                 config.dst.w, config.dst.h);
2373     } else {
2374         useCompositionCrop = false;
2375     }
2376 
2377     if (useCompositionCrop == false) {
2378         config.src.x = 0;
2379         config.src.y = 0;
2380         config.src.w = mXres;
2381         config.src.h = mYres;
2382         config.dst.x = 0;
2383         config.dst.y = 0;
2384         config.dst.w = mXres;
2385         config.dst.h = mYres;
2386     }
2387 
2388     config.blending = HWC2_BLEND_MODE_PREMULTIPLIED;
2389 
2390     config.acq_fence =
2391         hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, compositionInfo.mAcquireFence);
2392     config.plane_alpha = 1;
2393     config.dataspace = compositionInfo.mSrcImg.dataSpace;
2394     config.hdr_enable = true;
2395 
2396     /* This will be closed by setReleaseFences() using config.acq_fence */
2397     compositionInfo.mAcquireFence = -1;
2398     DISPLAY_LOGD(eDebugSkipStaicLayer, "Configure composition target[%d], config[%d]!!!!",
2399             compositionInfo.mType, windowIndex);
2400     dumpConfig(config);
2401 
2402     uint64_t bufSize = gmeta.size * formatToBpp(gmeta.format);
2403     uint64_t srcSize = config.src.f_w * config.src.f_h * formatToBpp(config.format);
2404     if (!isFormatLossy(gmeta.format) && (bufSize < srcSize)) {
2405         DISPLAY_LOGE("%s:: buffer size is smaller than source size, buf(size: %d, format: %d), src(w: %d, h: %d, format: %d)",
2406                 __func__, gmeta.size, gmeta.format, config.src.f_w, config.src.f_h, config.format);
2407         return -EINVAL;
2408     }
2409 
2410     return NO_ERROR;
2411 }
2412 
2413 /**
2414  * @return int
2415  */
setWinConfigData()2416 int ExynosDisplay::setWinConfigData() {
2417     int ret = NO_ERROR;
2418     mDpuData.reset();
2419 
2420     if (mClientCompositionInfo.mHasCompositionLayer) {
2421         if ((ret = configureOverlay(mClientCompositionInfo)) != NO_ERROR)
2422             return ret;
2423     }
2424     if (mExynosCompositionInfo.mHasCompositionLayer) {
2425         if ((ret = configureOverlay(mExynosCompositionInfo)) != NO_ERROR) {
2426             /* TEST */
2427             //return ret;
2428             HWC_LOGE(this, "configureOverlay(ExynosCompositionInfo) is failed");
2429         }
2430     }
2431 
2432     /* TODO loop for number of layers */
2433     for (size_t i = 0; i < mLayers.size(); i++) {
2434         if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) ||
2435                 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT))
2436             continue;
2437         if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION) {
2438             if (CC_UNLIKELY(mDpuData.rcdConfigs.size() == 0)) {
2439                 DISPLAY_LOGE("%s:: %zu layer has invalid COMPOSITION_TYPE(%d)", __func__, i,
2440                              mLayers[i]->mExynosCompositionType);
2441                 return -EINVAL;
2442             }
2443 
2444             if ((ret = configureOverlay(mLayers[i], mDpuData.rcdConfigs[0])) != NO_ERROR)
2445                 return ret;
2446             continue;
2447         }
2448         int32_t windowIndex =  mLayers[i]->mWindowIndex;
2449         if ((windowIndex < 0) || (windowIndex >= (int32_t)mDpuData.configs.size())) {
2450             DISPLAY_LOGE("%s:: %zu layer has invalid windowIndex(%d)",
2451                     __func__, i, windowIndex);
2452             return -EINVAL;
2453         }
2454         DISPLAY_LOGD(eDebugWinConfig, "%zu layer, config[%d]", i, windowIndex);
2455         if ((ret = configureOverlay(mLayers[i], mDpuData.configs[windowIndex])) != NO_ERROR)
2456             return ret;
2457     }
2458 
2459     return 0;
2460 }
2461 
printDebugInfos(String8 & reason)2462 void ExynosDisplay::printDebugInfos(String8 &reason) {
2463     struct timeval tv;
2464     gettimeofday(&tv, NULL);
2465     reason.appendFormat("errFrameNumber: %" PRId64 " time:%s\n", mErrorFrameCount,
2466                         getLocalTimeStr(tv).c_str());
2467     ALOGD("%s", reason.c_str());
2468 
2469     bool fileOpened = mDebugDumpFileWriter.chooseOpenedFile();
2470     mDebugDumpFileWriter.write(reason);
2471     mErrorFrameCount++;
2472 
2473     android::String8 result;
2474     result.appendFormat("Device mGeometryChanged(%" PRIx64 "), mGeometryChanged(%" PRIx64 "), mRenderingState(%d)\n",
2475             mDevice->mGeometryChanged, mGeometryChanged, mRenderingState);
2476     result.appendFormat("=======================  dump composition infos  ================================\n");
2477     const ExynosCompositionInfo& clientCompInfo = mClientCompositionInfo;
2478     const ExynosCompositionInfo& exynosCompInfo = mExynosCompositionInfo;
2479     clientCompInfo.dump(result);
2480     exynosCompInfo.dump(result);
2481     ALOGD("%s", result.c_str());
2482     mDebugDumpFileWriter.write(result);
2483     result.clear();
2484 
2485     result.appendFormat("=======================  dump exynos layers (%zu)  ================================\n",
2486             mLayers.size());
2487     ALOGD("%s", result.c_str());
2488     mDebugDumpFileWriter.write(result);
2489     result.clear();
2490     for (uint32_t i = 0; i < mLayers.size(); i++) {
2491         ExynosLayer *layer = mLayers[i];
2492         layer->printLayer();
2493         if (fileOpened) {
2494             layer->dump(result);
2495             mDebugDumpFileWriter.write(result);
2496             result.clear();
2497         }
2498     }
2499 
2500     if (mIgnoreLayers.size()) {
2501         result.appendFormat("=======================  dump ignore layers (%zu)  ================================\n",
2502                             mIgnoreLayers.size());
2503         ALOGD("%s", result.c_str());
2504         mDebugDumpFileWriter.write(result);
2505         result.clear();
2506         for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
2507             ExynosLayer *layer = mIgnoreLayers[i];
2508             layer->printLayer();
2509             if (fileOpened) {
2510                 layer->dump(result);
2511                 mDebugDumpFileWriter.write(result);
2512                 result.clear();
2513             }
2514         }
2515     }
2516 
2517     result.appendFormat("=============================  dump win configs  ===================================\n");
2518     ALOGD("%s", result.c_str());
2519     mDebugDumpFileWriter.write(result);
2520     result.clear();
2521     for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2522         ALOGD("config[%zu]", i);
2523         printConfig(mDpuData.configs[i]);
2524         if (fileOpened) {
2525             result.appendFormat("config[%zu]\n", i);
2526             dumpConfig(result, mDpuData.configs[i]);
2527             mDebugDumpFileWriter.write(result);
2528             result.clear();
2529         }
2530     }
2531     mDebugDumpFileWriter.flush();
2532 }
2533 
validateWinConfigData()2534 int32_t ExynosDisplay::validateWinConfigData()
2535 {
2536     bool flagValidConfig = true;
2537     int bufferStateCnt = 0;
2538 
2539     for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2540         exynos_win_config_data &config = mDpuData.configs[i];
2541         if (config.state == config.WIN_STATE_BUFFER) {
2542             bool configInvalid = false;
2543             /* multiple dma mapping */
2544             for (size_t j = (i+1); j < mDpuData.configs.size(); j++) {
2545                 exynos_win_config_data &compare_config = mDpuData.configs[j];
2546                 if ((config.state == config.WIN_STATE_BUFFER) &&
2547                     (compare_config.state == compare_config.WIN_STATE_BUFFER)) {
2548                     if ((config.assignedMPP != NULL) &&
2549                         (config.assignedMPP == compare_config.assignedMPP)) {
2550                         DISPLAY_LOGE("WIN_CONFIG error: duplicated assignedMPP(%s) between win%zu, win%zu",
2551                                 config.assignedMPP->mName.c_str(), i, j);
2552                         compare_config.state = compare_config.WIN_STATE_DISABLED;
2553                         flagValidConfig = false;
2554                         continue;
2555                     }
2556                 }
2557             }
2558             if ((config.src.x < 0) || (config.src.y < 0)||
2559                 (config.dst.x < 0) || (config.dst.y < 0)||
2560                 (config.src.w <= 0) || (config.src.h <= 0)||
2561                 (config.dst.w <= 0) || (config.dst.h <= 0)||
2562                 (config.dst.x + config.dst.w > (uint32_t)mXres) ||
2563                 (config.dst.y + config.dst.h > (uint32_t)mYres)) {
2564                 DISPLAY_LOGE("WIN_CONFIG error: invalid pos or size win%zu", i);
2565                 configInvalid = true;
2566             }
2567 
2568             if ((config.src.w > config.src.f_w) ||
2569                 (config.src.h > config.src.f_h)) {
2570                 DISPLAY_LOGE("WIN_CONFIG error: invalid size %zu, %d, %d, %d, %d", i,
2571                         config.src.w, config.src.f_w, config.src.h, config.src.f_h);
2572                 configInvalid = true;
2573             }
2574 
2575             /* Source alignment check */
2576             ExynosMPP* exynosMPP = config.assignedMPP;
2577             if (exynosMPP == NULL) {
2578                 DISPLAY_LOGE("WIN_CONFIG error: config %zu assigendMPP is NULL", i);
2579                 configInvalid = true;
2580             } else {
2581                 uint32_t restrictionIdx = getRestrictionIndex(config.format);
2582                 uint32_t srcXAlign = exynosMPP->getSrcXOffsetAlign(restrictionIdx);
2583                 uint32_t srcYAlign = exynosMPP->getSrcYOffsetAlign(restrictionIdx);
2584                 uint32_t srcWidthAlign = exynosMPP->getSrcCropWidthAlign(restrictionIdx);
2585                 uint32_t srcHeightAlign = exynosMPP->getSrcCropHeightAlign(restrictionIdx);
2586                 if ((config.src.x % srcXAlign != 0) ||
2587                     (config.src.y % srcYAlign != 0) ||
2588                     (config.src.w % srcWidthAlign != 0) ||
2589                     (config.src.h % srcHeightAlign != 0))
2590                 {
2591                     DISPLAY_LOGE("WIN_CONFIG error: invalid src alignment : %zu, "\
2592                             "assignedMPP: %s, mppType:%d, format(%d), s_x: %d(%d), s_y: %d(%d), s_w : %d(%d), s_h : %d(%d)", i,
2593                             config.assignedMPP->mName.c_str(), exynosMPP->mLogicalType, config.format, config.src.x, srcXAlign,
2594                             config.src.y, srcYAlign, config.src.w, srcWidthAlign, config.src.h, srcHeightAlign);
2595                     configInvalid = true;
2596                 }
2597             }
2598 
2599             if (configInvalid) {
2600                 config.state = config.WIN_STATE_DISABLED;
2601                 flagValidConfig = false;
2602             }
2603 
2604             bufferStateCnt++;
2605         }
2606 
2607         if ((config.state == config.WIN_STATE_COLOR) ||
2608             (config.state == config.WIN_STATE_CURSOR))
2609             bufferStateCnt++;
2610     }
2611 
2612     if (bufferStateCnt == 0) {
2613         DISPLAY_LOGE("WIN_CONFIG error: has no buffer window");
2614         flagValidConfig = false;
2615     }
2616 
2617     if (flagValidConfig)
2618         return NO_ERROR;
2619     else
2620         return -EINVAL;
2621 }
2622 
2623 /**
2624  * @return int
2625  */
setDisplayWinConfigData()2626 int ExynosDisplay::setDisplayWinConfigData() {
2627     return 0;
2628 }
2629 
checkConfigChanged(const exynos_dpu_data & lastConfigsData,const exynos_dpu_data & newConfigsData)2630 bool ExynosDisplay::checkConfigChanged(const exynos_dpu_data &lastConfigsData, const exynos_dpu_data &newConfigsData)
2631 {
2632     if (exynosHWCControl.skipWinConfig == 0)
2633         return true;
2634 
2635     /* HWC doesn't skip WIN_CONFIG if other display is connected */
2636     if ((mDevice->checkNonInternalConnection()) && (mType == HWC_DISPLAY_PRIMARY))
2637         return true;
2638 
2639     for (size_t i = 0; i < lastConfigsData.configs.size(); i++) {
2640         if ((lastConfigsData.configs[i].state != newConfigsData.configs[i].state) ||
2641             (lastConfigsData.configs[i].fd_idma[0] != newConfigsData.configs[i].fd_idma[0]) ||
2642             (lastConfigsData.configs[i].fd_idma[1] != newConfigsData.configs[i].fd_idma[1]) ||
2643             (lastConfigsData.configs[i].fd_idma[2] != newConfigsData.configs[i].fd_idma[2]) ||
2644             (lastConfigsData.configs[i].dst.x != newConfigsData.configs[i].dst.x) ||
2645             (lastConfigsData.configs[i].dst.y != newConfigsData.configs[i].dst.y) ||
2646             (lastConfigsData.configs[i].dst.w != newConfigsData.configs[i].dst.w) ||
2647             (lastConfigsData.configs[i].dst.h != newConfigsData.configs[i].dst.h) ||
2648             (lastConfigsData.configs[i].src.x != newConfigsData.configs[i].src.x) ||
2649             (lastConfigsData.configs[i].src.y != newConfigsData.configs[i].src.y) ||
2650             (lastConfigsData.configs[i].src.w != newConfigsData.configs[i].src.w) ||
2651             (lastConfigsData.configs[i].src.h != newConfigsData.configs[i].src.h) ||
2652             (lastConfigsData.configs[i].format != newConfigsData.configs[i].format) ||
2653             (lastConfigsData.configs[i].blending != newConfigsData.configs[i].blending) ||
2654             (lastConfigsData.configs[i].plane_alpha != newConfigsData.configs[i].plane_alpha))
2655             return true;
2656     }
2657 
2658     /* To cover buffer payload changed case */
2659     for (size_t i = 0; i < mLayers.size(); i++) {
2660         if(mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer)
2661             return true;
2662     }
2663 
2664     return false;
2665 }
2666 
checkConfigDstChanged(const exynos_dpu_data & lastConfigsData,const exynos_dpu_data & newConfigsData,uint32_t index)2667 int ExynosDisplay::checkConfigDstChanged(const exynos_dpu_data &lastConfigsData, const exynos_dpu_data &newConfigsData, uint32_t index)
2668 {
2669     if ((lastConfigsData.configs[index].state != newConfigsData.configs[index].state) ||
2670         (lastConfigsData.configs[index].fd_idma[0] != newConfigsData.configs[index].fd_idma[0]) ||
2671         (lastConfigsData.configs[index].fd_idma[1] != newConfigsData.configs[index].fd_idma[1]) ||
2672         (lastConfigsData.configs[index].fd_idma[2] != newConfigsData.configs[index].fd_idma[2]) ||
2673         (lastConfigsData.configs[index].format != newConfigsData.configs[index].format) ||
2674         (lastConfigsData.configs[index].blending != newConfigsData.configs[index].blending) ||
2675         (lastConfigsData.configs[index].plane_alpha != newConfigsData.configs[index].plane_alpha)) {
2676         DISPLAY_LOGD(eDebugWindowUpdate, "damage region is skip, but other configuration except dst was changed");
2677         DISPLAY_LOGD(eDebugWindowUpdate, "\tstate[%d, %d], fd[%d, %d], format[0x%8x, 0x%8x], blending[%d, %d], plane_alpha[%f, %f]",
2678                 lastConfigsData.configs[index].state, newConfigsData.configs[index].state,
2679                 lastConfigsData.configs[index].fd_idma[0], newConfigsData.configs[index].fd_idma[0],
2680                 lastConfigsData.configs[index].format, newConfigsData.configs[index].format,
2681                 lastConfigsData.configs[index].blending, newConfigsData.configs[index].blending,
2682                 lastConfigsData.configs[index].plane_alpha, newConfigsData.configs[index].plane_alpha);
2683         return -1;
2684     }
2685     if ((lastConfigsData.configs[index].dst.x != newConfigsData.configs[index].dst.x) ||
2686         (lastConfigsData.configs[index].dst.y != newConfigsData.configs[index].dst.y) ||
2687         (lastConfigsData.configs[index].dst.w != newConfigsData.configs[index].dst.w) ||
2688         (lastConfigsData.configs[index].dst.h != newConfigsData.configs[index].dst.h) ||
2689         (lastConfigsData.configs[index].src.x != newConfigsData.configs[index].src.x) ||
2690         (lastConfigsData.configs[index].src.y != newConfigsData.configs[index].src.y) ||
2691         (lastConfigsData.configs[index].src.w != newConfigsData.configs[index].src.w) ||
2692         (lastConfigsData.configs[index].src.h != newConfigsData.configs[index].src.h))
2693         return 1;
2694 
2695     else
2696         return 0;
2697 }
2698 
2699 /**
2700  * @return int
2701  */
deliverWinConfigData()2702 int ExynosDisplay::deliverWinConfigData() {
2703 
2704     ATRACE_CALL();
2705     String8 errString;
2706     int ret = NO_ERROR;
2707     struct timeval tv_s, tv_e;
2708     long timediff;
2709 
2710     ret = validateWinConfigData();
2711     if (ret != NO_ERROR) {
2712         errString.appendFormat("Invalid WIN_CONFIG\n");
2713         goto err;
2714     }
2715 
2716     for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2717         DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "deliver config[%zu]", i);
2718         dumpConfig(mDpuData.configs[i]);
2719     }
2720 
2721     if (checkConfigChanged(mDpuData, mLastDpuData) == false) {
2722         DISPLAY_LOGD(eDebugWinConfig, "Winconfig : same");
2723 #ifndef DISABLE_FENCE
2724         if (mLastRetireFence > 0) {
2725             mDpuData.retire_fence =
2726                 hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP,
2727                         hwc_dup(mLastRetireFence, this,  FENCE_TYPE_RETIRE, FENCE_IP_DPP));
2728         } else
2729             mDpuData.retire_fence = -1;
2730 #endif
2731         ret = 0;
2732     } else {
2733         /* wait for 5 vsync */
2734         int32_t waitTime = mVsyncPeriod / 1000000 * 5;
2735         gettimeofday(&tv_s, NULL);
2736         if (mUsePowerHints) {
2737             mRetireFenceWaitTime = systemTime();
2738         }
2739         if (fence_valid(mLastRetireFence)) {
2740             ATRACE_NAME("waitLastRetireFence");
2741             if (sync_wait(mLastRetireFence, waitTime) < 0) {
2742                 DISPLAY_LOGE("%s:: mLastRetireFence(%d) is not released during (%d ms)",
2743                         __func__, mLastRetireFence, waitTime);
2744                 if (sync_wait(mLastRetireFence, 1000 - waitTime) < 0) {
2745                     DISPLAY_LOGE("%s:: mLastRetireFence sync wait error (%d)", __func__, mLastRetireFence);
2746                 }
2747                 else {
2748                     gettimeofday(&tv_e, NULL);
2749                     tv_e.tv_usec += (tv_e.tv_sec - tv_s.tv_sec) * 1000000;
2750                     timediff = tv_e.tv_usec - tv_s.tv_usec;
2751                     DISPLAY_LOGE("%s:: winconfig is delayed over 5 vysnc (fence:%d)(time:%ld)",
2752                             __func__, mLastRetireFence, timediff);
2753                 }
2754             }
2755         }
2756         if (mUsePowerHints) {
2757             mRetireFenceAcquireTime = systemTime();
2758         }
2759         for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2760             setFenceInfo(mDpuData.configs[i].acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP,
2761                          HwcFenceDirection::TO);
2762         }
2763 
2764         if ((ret = mDisplayInterface->deliverWinConfigData()) < 0) {
2765             errString.appendFormat("interface's deliverWinConfigData() failed: %s ret(%d)\n", strerror(errno), ret);
2766             goto err;
2767         } else {
2768             mLastDpuData = mDpuData;
2769         }
2770 
2771         for (size_t i = 0; i < mDpuData.configs.size(); i++) {
2772             setFenceInfo(mDpuData.configs[i].rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2773                          HwcFenceDirection::FROM);
2774         }
2775         setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP,
2776                      HwcFenceDirection::FROM);
2777     }
2778 
2779     return ret;
2780 err:
2781     printDebugInfos(errString);
2782     closeFences();
2783     clearDisplay();
2784     mDisplayInterface->setForcePanic();
2785 
2786     return ret;
2787 }
2788 
2789 /**
2790  * @return int
2791  */
setReleaseFences()2792 int ExynosDisplay::setReleaseFences() {
2793 
2794     int release_fd = -1;
2795     String8 errString;
2796 
2797     /*
2798      * Close release fence for client target buffer
2799      * SurfaceFlinger doesn't get release fence for client target buffer
2800      */
2801     if ((mClientCompositionInfo.mHasCompositionLayer) &&
2802         (mClientCompositionInfo.mWindowIndex >= 0) &&
2803         (mClientCompositionInfo.mWindowIndex < (int32_t)mDpuData.configs.size())) {
2804 
2805         exynos_win_config_data &config = mDpuData.configs[mClientCompositionInfo.mWindowIndex];
2806 
2807         for (int i = mClientCompositionInfo.mFirstIndex; i <= mClientCompositionInfo.mLastIndex; i++) {
2808             if (mLayers[i]->mExynosCompositionType != HWC2_COMPOSITION_CLIENT) {
2809                 if(mLayers[i]->mOverlayPriority < ePriorityHigh) {
2810                     errString.appendFormat("%d layer compositionType is not client(%d)\n", i, mLayers[i]->mExynosCompositionType);
2811                     goto err;
2812                 } else {
2813                     continue;
2814                 }
2815             }
2816             if (mType == HWC_DISPLAY_VIRTUAL)
2817                 mLayers[i]->mReleaseFence = -1;
2818             else
2819                 mLayers[i]->mReleaseFence =
2820                     hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2821                             hwc_dup(config.rel_fence, this,
2822                                 FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP));
2823         }
2824         config.rel_fence = fence_close(config.rel_fence, this,
2825                    FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB);
2826     }
2827 
2828     // DPU doesn't close acq_fence, HWC should close it.
2829     for (auto &config : mDpuData.configs) {
2830         if (config.acq_fence != -1)
2831             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
2832         config.acq_fence = -1;
2833     }
2834     for (auto &config : mDpuData.rcdConfigs) {
2835         if (config.acq_fence != -1)
2836             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
2837         config.acq_fence = -1;
2838     }
2839     // DPU doesn't close rel_fence of readback buffer, HWC should close it
2840     if (mDpuData.readback_info.rel_fence >= 0) {
2841         mDpuData.readback_info.rel_fence =
2842             fence_close(mDpuData.readback_info.rel_fence, this,
2843                 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
2844     }
2845 
2846     for (size_t i = 0; i < mLayers.size(); i++) {
2847         if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) ||
2848             (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) ||
2849             (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION))
2850             continue;
2851         if ((mLayers[i]->mWindowIndex < 0) ||
2852             (mLayers[i]->mWindowIndex >= mDpuData.configs.size())) {
2853             errString.appendFormat("%s:: layer[%zu] has invalid window index(%d)\n",
2854                     __func__, i, mLayers[i]->mWindowIndex);
2855             goto err;
2856         }
2857         exynos_win_config_data &config = mDpuData.configs[mLayers[i]->mWindowIndex];
2858         if (mLayers[i]->mOtfMPP != NULL) {
2859             mLayers[i]->mOtfMPP->setHWStateFence(-1);
2860         }
2861         if (mLayers[i]->mM2mMPP != NULL) {
2862             if (mLayers[i]->mM2mMPP->mUseM2MSrcFence)
2863                 mLayers[i]->mReleaseFence = mLayers[i]->mM2mMPP->getSrcReleaseFence(0);
2864             else {
2865                 mLayers[i]->mReleaseFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2866                     hwc_dup(config.rel_fence, this,
2867                         FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER));
2868             }
2869 
2870             mLayers[i]->mM2mMPP->resetSrcReleaseFence();
2871 #ifdef DISABLE_FENCE
2872             mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2873 #else
2874             DISPLAY_LOGD(eDebugFence, "m2m : win_index(%d), releaseFencefd(%d)",
2875                     mLayers[i]->mWindowIndex, config.rel_fence);
2876             if (config.rel_fence > 0) {
2877                 release_fd = config.rel_fence;
2878                 if (release_fd >= 0) {
2879                     setFenceInfo(release_fd, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP,
2880                                  HwcFenceDirection::UPDATE, true);
2881                     mLayers[i]->mM2mMPP->setDstAcquireFence(release_fd);
2882                 } else {
2883                     DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2884                     mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2885                 }
2886             } else {
2887                 mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2888             }
2889             DISPLAY_LOGD(eDebugFence, "mM2mMPP is used, layer[%zu].releaseFencefd(%d)",
2890                     i, mLayers[i]->mReleaseFence);
2891 #endif
2892         } else {
2893 #ifdef DISABLE_FENCE
2894             mLayers[i]->mReleaseFence = -1;
2895 #else
2896             DISPLAY_LOGD(eDebugFence, "other : win_index(%d), releaseFencefd(%d)",
2897                     mLayers[i]->mWindowIndex, config.rel_fence);
2898             if (config.rel_fence > 0) {
2899                 release_fd = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, config.rel_fence);
2900                 if (release_fd >= 0)
2901                     mLayers[i]->mReleaseFence = release_fd;
2902                 else {
2903                     DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2904                     mLayers[i]->mReleaseFence = -1;
2905                 }
2906             } else {
2907                 mLayers[i]->mReleaseFence = -1;
2908             }
2909             DISPLAY_LOGD(eDebugFence, "Direct overlay layer[%zu].releaseFencefd(%d)",
2910                 i, mLayers[i]->mReleaseFence);
2911 #endif
2912         }
2913     }
2914 
2915     if (mExynosCompositionInfo.mHasCompositionLayer) {
2916         if (mExynosCompositionInfo.mM2mMPP == NULL)
2917         {
2918             errString.appendFormat("There is exynos composition, but m2mMPP is NULL\n");
2919             goto err;
2920         }
2921         if (mUseDpu &&
2922             ((mExynosCompositionInfo.mWindowIndex < 0) ||
2923              (mExynosCompositionInfo.mWindowIndex >= (int32_t)mDpuData.configs.size()))) {
2924             errString.appendFormat("%s:: exynosComposition has invalid window index(%d)\n",
2925                     __func__, mExynosCompositionInfo.mWindowIndex);
2926             goto err;
2927         }
2928         exynos_win_config_data &config = mDpuData.configs[mExynosCompositionInfo.mWindowIndex];
2929         for (int i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
2930             /* break when only framebuffer target is assigned on ExynosCompositor */
2931             if (i == -1)
2932                 break;
2933 
2934             if (mLayers[i]->mExynosCompositionType != HWC2_COMPOSITION_EXYNOS) {
2935                 errString.appendFormat("%d layer compositionType is not exynos(%d)\n", i, mLayers[i]->mExynosCompositionType);
2936                 goto err;
2937             }
2938 
2939             if (mExynosCompositionInfo.mM2mMPP->mUseM2MSrcFence)
2940                 mLayers[i]->mReleaseFence =
2941                     mExynosCompositionInfo.mM2mMPP->getSrcReleaseFence(i-mExynosCompositionInfo.mFirstIndex);
2942             else {
2943                 mLayers[i]->mReleaseFence =
2944                     hwc_dup(config.rel_fence,
2945                             this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
2946             }
2947 
2948             DISPLAY_LOGD(eDebugFence, "exynos composition layer[%d].releaseFencefd(%d)",
2949                     i, mLayers[i]->mReleaseFence);
2950         }
2951         mExynosCompositionInfo.mM2mMPP->resetSrcReleaseFence();
2952         if(mUseDpu) {
2953 #ifdef DISABLE_FENCE
2954             mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2955 #else
2956             if (config.rel_fence > 0) {
2957                 setFenceInfo(config.rel_fence, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP,
2958                              HwcFenceDirection::UPDATE, true);
2959                 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(config.rel_fence);
2960             } else {
2961                 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2962             }
2963 #endif
2964         }
2965     }
2966     return 0;
2967 
2968 err:
2969     printDebugInfos(errString);
2970     closeFences();
2971     mDisplayInterface->setForcePanic();
2972     return -EINVAL;
2973 }
2974 
2975 /**
2976  * If display uses outbuf and outbuf is invalid, this function return false.
2977  * Otherwise, this function return true.
2978  * If outbuf is invalid, display should handle fence of layers.
2979  */
checkFrameValidation()2980 bool ExynosDisplay::checkFrameValidation() {
2981     return true;
2982 }
2983 
acceptDisplayChanges()2984 int32_t ExynosDisplay::acceptDisplayChanges() {
2985     int32_t type = 0;
2986     if (mDropFrameDuringResSwitch) {
2987         return HWC2_ERROR_NONE;
2988     }
2989     if (mRenderingState != RENDERING_STATE_VALIDATED) {
2990         DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
2991         return HWC2_ERROR_NOT_VALIDATED;
2992     }
2993 
2994     for (size_t i = 0; i < mLayers.size(); i++) {
2995         if (mLayers[i] != NULL) {
2996             HDEBUGLOGD(eDebugDefault, "%s, Layer %zu : %d, %d", __func__, i,
2997                     mLayers[i]->mExynosCompositionType, mLayers[i]->mValidateCompositionType);
2998             type = getLayerCompositionTypeForValidationType(i);
2999 
3000             /* update compositionType
3001              * SF updates their state and doesn't call back into HWC HAL
3002              */
3003             mLayers[i]->mCompositionType = type;
3004             mLayers[i]->mExynosCompositionType = mLayers[i]->mValidateCompositionType;
3005         }
3006         else {
3007             HWC_LOGE(this, "Layer %zu is NULL", i);
3008         }
3009     }
3010     mRenderingState = RENDERING_STATE_ACCEPTED_CHANGE;
3011 
3012     return HWC2_ERROR_NONE;
3013 }
3014 
createLayer(hwc2_layer_t * outLayer)3015 int32_t ExynosDisplay::createLayer(hwc2_layer_t* outLayer) {
3016 
3017     Mutex::Autolock lock(mDRMutex);
3018     if (mPlugState == false) {
3019         DISPLAY_LOGI("%s : skip createLayer. Display is already disconnected", __func__);
3020         return HWC2_ERROR_BAD_DISPLAY;
3021     }
3022 
3023     /* TODO : Implementation here */
3024     ExynosLayer *layer = new ExynosLayer(this);
3025 
3026     /* TODO : Sort sequence should be added to somewhere */
3027     mLayers.add((ExynosLayer*)layer);
3028 
3029     /* TODO : Set z-order to max, check outLayer address? */
3030     layer->setLayerZOrder(1000);
3031 
3032     *outLayer = (hwc2_layer_t)layer;
3033     setGeometryChanged(GEOMETRY_DISPLAY_LAYER_ADDED);
3034 
3035     return HWC2_ERROR_NONE;
3036 }
3037 
getActiveConfig(hwc2_config_t * outConfig)3038 int32_t ExynosDisplay::getActiveConfig(hwc2_config_t* outConfig)
3039 {
3040     Mutex::Autolock lock(mDisplayMutex);
3041     return getActiveConfigInternal(outConfig);
3042 }
3043 
getActiveConfigInternal(hwc2_config_t * outConfig)3044 int32_t ExynosDisplay::getActiveConfigInternal(hwc2_config_t* outConfig)
3045 {
3046     *outConfig = mActiveConfig;
3047 
3048     return HWC2_ERROR_NONE;
3049 }
3050 
getLayerCompositionTypeForValidationType(uint32_t layerIndex)3051 int32_t ExynosDisplay::getLayerCompositionTypeForValidationType(uint32_t layerIndex)
3052 {
3053     int32_t type = -1;
3054 
3055     if (layerIndex >= mLayers.size())
3056     {
3057         DISPLAY_LOGE("invalid layer index (%d)", layerIndex);
3058         return type;
3059     }
3060     if ((mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_CLIENT) &&
3061         (mClientCompositionInfo.mSkipFlag) &&
3062         (mClientCompositionInfo.mFirstIndex <= (int32_t)layerIndex) &&
3063         ((int32_t)layerIndex <= mClientCompositionInfo.mLastIndex)) {
3064         type = HWC2_COMPOSITION_DEVICE;
3065     } else if (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
3066         type = HWC2_COMPOSITION_DEVICE;
3067     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_CURSOR) &&
3068                (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
3069         if (mDisplayControl.cursorSupport == true)
3070             type = HWC2_COMPOSITION_CURSOR;
3071         else
3072             type = HWC2_COMPOSITION_DEVICE;
3073     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_SOLID_COLOR) &&
3074                (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
3075         type = HWC2_COMPOSITION_SOLID_COLOR;
3076     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) &&
3077                (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
3078         type = HWC2_COMPOSITION_REFRESH_RATE_INDICATOR;
3079     } else {
3080         type = mLayers[layerIndex]->mValidateCompositionType;
3081     }
3082 
3083     return type;
3084 }
3085 
getChangedCompositionTypes(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outTypes)3086 int32_t ExynosDisplay::getChangedCompositionTypes(
3087         uint32_t* outNumElements, hwc2_layer_t* outLayers,
3088         int32_t* /*hwc2_composition_t*/ outTypes) {
3089     if (mDropFrameDuringResSwitch) {
3090         if ((outLayers == NULL) || (outTypes == NULL)) {
3091             *outNumElements = 0;
3092         }
3093         return HWC2_ERROR_NONE;
3094     }
3095 
3096     if (mRenderingState != RENDERING_STATE_VALIDATED) {
3097         DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
3098         return HWC2_ERROR_NOT_VALIDATED;
3099     }
3100 
3101     uint32_t count = 0;
3102 
3103     auto set_out_param = [](ExynosLayer *layer, int32_t type, uint32_t &count, uint32_t num,
3104                             hwc2_layer_t *out_layers, int32_t *out_types) -> int32_t {
3105         if (type == layer->mCompositionType) {
3106             return 0;
3107         }
3108         if (out_layers == NULL || out_types == NULL) {
3109             count++;
3110         } else {
3111             if (count < num) {
3112                 out_layers[count] = (hwc2_layer_t)layer;
3113                 out_types[count] = type;
3114                 count++;
3115             } else {
3116                 return -1;
3117             }
3118         }
3119         return 0;
3120     };
3121 
3122     int32_t ret = 0;
3123     for (size_t i = 0; i < mLayers.size(); i++) {
3124         DISPLAY_LOGD(eDebugHWC, "[%zu] layer: mCompositionType(%d), mValidateCompositionType(%d), mExynosCompositionType(%d), skipFlag(%d)",
3125                 i, mLayers[i]->mCompositionType, mLayers[i]->mValidateCompositionType,
3126                 mLayers[i]->mExynosCompositionType, mClientCompositionInfo.mSkipFlag);
3127         if ((ret = set_out_param(mLayers[i], getLayerCompositionTypeForValidationType(i), count,
3128                                  *outNumElements, outLayers, outTypes)) < 0) {
3129             break;
3130         }
3131     }
3132     if (ret == 0) {
3133         for (size_t i = 0; i < mIgnoreLayers.size(); i++) {
3134             DISPLAY_LOGD(eDebugHWC,
3135                          "[%zu] ignore layer: mCompositionType(%d), mValidateCompositionType(%d)",
3136                          i, mIgnoreLayers[i]->mCompositionType,
3137                          mIgnoreLayers[i]->mValidateCompositionType);
3138             if ((ret = set_out_param(mIgnoreLayers[i], mIgnoreLayers[i]->mValidateCompositionType,
3139                                      count, *outNumElements, outLayers, outTypes)) < 0) {
3140                 break;
3141             }
3142         }
3143     }
3144     if (ret < 0) {
3145         DISPLAY_LOGE("array size is not valid (%d, %d)", count, *outNumElements);
3146         String8 errString;
3147         errString.appendFormat("array size is not valid (%d, %d)", count, *outNumElements);
3148         printDebugInfos(errString);
3149         return ret;
3150     }
3151 
3152     if ((outLayers == NULL) || (outTypes == NULL))
3153         *outNumElements = count;
3154 
3155     return HWC2_ERROR_NONE;
3156 }
3157 
getClientTargetSupport(uint32_t width,uint32_t height,int32_t format,int32_t dataspace)3158 int32_t ExynosDisplay::getClientTargetSupport(uint32_t width, uint32_t height,
3159                                               int32_t /*android_pixel_format_t*/ format,
3160                                               int32_t /*android_dataspace_t*/ dataspace)
3161 {
3162     if (width != mXres)
3163         return HWC2_ERROR_UNSUPPORTED;
3164     if (height != mYres)
3165         return HWC2_ERROR_UNSUPPORTED;
3166     if (format != HAL_PIXEL_FORMAT_RGBA_8888)
3167         return HWC2_ERROR_UNSUPPORTED;
3168     if ((dataspace != HAL_DATASPACE_UNKNOWN) &&
3169         (!mDisplayInterface->supportDataspace(dataspace)))
3170         return HWC2_ERROR_UNSUPPORTED;
3171 
3172     return HWC2_ERROR_NONE;
3173 }
3174 
getColorModes(uint32_t * outNumModes,int32_t * outModes)3175 int32_t ExynosDisplay::getColorModes(uint32_t *outNumModes, int32_t * /*android_color_mode_t*/ outModes)
3176 {
3177     return mDisplayInterface->getColorModes(outNumModes, outModes);
3178 }
3179 
getDisplayAttribute(hwc2_config_t config,int32_t attribute,int32_t * outValue)3180 int32_t ExynosDisplay::getDisplayAttribute(
3181         hwc2_config_t config,
3182         int32_t /*hwc2_attribute_t*/ attribute, int32_t* outValue) {
3183 
3184     switch (attribute) {
3185     case HWC2_ATTRIBUTE_VSYNC_PERIOD:
3186         *outValue = mDisplayConfigs[config].vsyncPeriod;
3187         break;
3188 
3189     case HWC2_ATTRIBUTE_WIDTH:
3190         *outValue = mDisplayConfigs[config].width;
3191         break;
3192 
3193     case HWC2_ATTRIBUTE_HEIGHT:
3194         *outValue = mDisplayConfigs[config].height;
3195         break;
3196 
3197     case HWC2_ATTRIBUTE_DPI_X:
3198         *outValue = mDisplayConfigs[config].Xdpi;
3199         break;
3200 
3201     case HWC2_ATTRIBUTE_DPI_Y:
3202         *outValue = mDisplayConfigs[config].Ydpi;
3203         break;
3204 
3205     case HWC2_ATTRIBUTE_CONFIG_GROUP:
3206         *outValue = mDisplayConfigs[config].groupId;
3207         break;
3208 
3209     default:
3210         ALOGE("unknown display attribute %u", attribute);
3211         return HWC2_ERROR_BAD_CONFIG;
3212     }
3213 
3214     return HWC2_ERROR_NONE;
3215 }
3216 
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)3217 int32_t ExynosDisplay::getDisplayConfigs(
3218         uint32_t* outNumConfigs,
3219         hwc2_config_t* outConfigs) {
3220     return mDisplayInterface->getDisplayConfigs(outNumConfigs, outConfigs);
3221 }
3222 
getDisplayName(uint32_t * outSize,char * outName)3223 int32_t ExynosDisplay::getDisplayName(uint32_t* outSize, char* outName)
3224 {
3225     if (outName == NULL) {
3226         *outSize = mDisplayName.size();
3227         return HWC2_ERROR_NONE;
3228     }
3229 
3230     uint32_t strSize = mDisplayName.size();
3231     if (*outSize < strSize) {
3232         DISPLAY_LOGE("Invalide outSize(%d), mDisplayName.size(%d)",
3233                 *outSize, strSize);
3234         strSize = *outSize;
3235     }
3236     std::strncpy(outName, mDisplayName.c_str(), strSize);
3237     *outSize = strSize;
3238 
3239     return HWC2_ERROR_NONE;
3240 }
3241 
getDisplayRequests(int32_t * outDisplayRequests,uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outLayerRequests)3242 int32_t ExynosDisplay::getDisplayRequests(
3243         int32_t* /*hwc2_display_request_t*/ outDisplayRequests,
3244         uint32_t* outNumElements, hwc2_layer_t* outLayers,
3245         int32_t* /*hwc2_layer_request_t*/ outLayerRequests) {
3246     /*
3247      * This function doesn't check mRenderingState
3248      * This can be called in the below rendering state
3249      * RENDERING_STATE_PRESENTED: when it is called by canSkipValidate()
3250      * RENDERING_STATE_ACCEPTED_CHANGE: when it is called by SF
3251      * RENDERING_STATE_VALIDATED:  when it is called by validateDisplay()
3252      */
3253 
3254     String8 errString;
3255     *outDisplayRequests = 0;
3256 
3257     if (mDropFrameDuringResSwitch) {
3258         if ((outLayers == NULL) || (outLayerRequests == NULL)) {
3259             *outNumElements = 0;
3260         }
3261         return HWC2_ERROR_NONE;
3262     }
3263 
3264     uint32_t requestNum = 0;
3265     if (mClientCompositionInfo.mHasCompositionLayer == true) {
3266         if ((mClientCompositionInfo.mFirstIndex < 0) ||
3267             (mClientCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
3268             (mClientCompositionInfo.mLastIndex < 0) ||
3269             (mClientCompositionInfo.mLastIndex >= (int)mLayers.size())) {
3270             errString.appendFormat("%s:: mClientCompositionInfo.mHasCompositionLayer is true "
3271                     "but index is not valid (firstIndex: %d, lastIndex: %d)\n",
3272                     __func__, mClientCompositionInfo.mFirstIndex,
3273                     mClientCompositionInfo.mLastIndex);
3274             goto err;
3275         }
3276 
3277         for (int32_t i = mClientCompositionInfo.mFirstIndex; i < mClientCompositionInfo.mLastIndex; i++) {
3278             ExynosLayer *layer = mLayers[i];
3279             if (layer->needClearClientTarget()) {
3280                 if ((outLayers != NULL) && (outLayerRequests != NULL)) {
3281                     if (requestNum >= *outNumElements)
3282                         return -1;
3283                     outLayers[requestNum] = (hwc2_layer_t)layer;
3284                     outLayerRequests[requestNum] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET;
3285                 }
3286                 requestNum++;
3287             }
3288         }
3289     }
3290     if ((outLayers == NULL) || (outLayerRequests == NULL))
3291         *outNumElements = requestNum;
3292 
3293     return HWC2_ERROR_NONE;
3294 
3295 err:
3296     printDebugInfos(errString);
3297     *outNumElements = 0;
3298     mDisplayInterface->setForcePanic();
3299     return -EINVAL;
3300 }
3301 
getDisplayType(int32_t * outType)3302 int32_t ExynosDisplay::getDisplayType(
3303         int32_t* /*hwc2_display_type_t*/ outType) {
3304     switch (mType) {
3305     case HWC_DISPLAY_PRIMARY:
3306     case HWC_DISPLAY_EXTERNAL:
3307         *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
3308         return HWC2_ERROR_NONE;
3309     case HWC_DISPLAY_VIRTUAL:
3310         *outType = HWC2_DISPLAY_TYPE_VIRTUAL;
3311         return HWC2_ERROR_NONE;
3312     default:
3313         DISPLAY_LOGE("Invalid display type(%d)", mType);
3314         *outType = HWC2_DISPLAY_TYPE_INVALID;
3315         return HWC2_ERROR_NONE;
3316     }
3317 }
3318 
getDozeSupport(int32_t * outSupport)3319 int32_t ExynosDisplay::getDozeSupport(
3320         int32_t* outSupport) {
3321     if (mDisplayInterface->isDozeModeAvailable()) {
3322         *outSupport = 1;
3323     } else {
3324         *outSupport = 0;
3325     }
3326 
3327     return 0;
3328 }
3329 
getReleaseFences(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outFences)3330 int32_t ExynosDisplay::getReleaseFences(
3331         uint32_t* outNumElements,
3332         hwc2_layer_t* outLayers, int32_t* outFences) {
3333 
3334     if (outNumElements == NULL) {
3335         return HWC2_ERROR_BAD_PARAMETER;
3336     }
3337 
3338     Mutex::Autolock lock(mDisplayMutex);
3339     uint32_t deviceLayerNum = 0;
3340     if (outLayers != NULL && outFences != NULL) {
3341         // second pass call
3342         for (size_t i = 0; i < mLayers.size(); i++) {
3343             if (mLayers[i]->mReleaseFence >= 0) {
3344                 if (deviceLayerNum < *outNumElements) {
3345                     // transfer fence ownership to the caller
3346                     setFenceName(mLayers[i]->mReleaseFence, FENCE_LAYER_RELEASE_DPP);
3347                     outLayers[deviceLayerNum] = (hwc2_layer_t)mLayers[i];
3348                     outFences[deviceLayerNum] = mLayers[i]->mReleaseFence;
3349                     mLayers[i]->mReleaseFence = -1;
3350 
3351                     DISPLAY_LOGD(eDebugHWC, "[%zu] layer deviceLayerNum(%d), release fence: %d", i,
3352                                  deviceLayerNum, outFences[deviceLayerNum]);
3353                 } else {
3354                     // *outNumElements is not from the first pass call.
3355                     DISPLAY_LOGE("%s: outNumElements %d too small", __func__, *outNumElements);
3356                     return HWC2_ERROR_BAD_PARAMETER;
3357                 }
3358                 deviceLayerNum++;
3359             }
3360         }
3361     } else {
3362         // first pass call
3363         for (size_t i = 0; i < mLayers.size(); i++) {
3364             if (mLayers[i]->mReleaseFence >= 0) {
3365                 deviceLayerNum++;
3366             }
3367         }
3368     }
3369     *outNumElements = deviceLayerNum;
3370 
3371     return 0;
3372 }
3373 
canSkipValidate()3374 int32_t ExynosDisplay::canSkipValidate() {
3375     if (exynosHWCControl.skipResourceAssign == 0)
3376         return SKIP_ERR_CONFIG_DISABLED;
3377 
3378     /* This is first frame. validateDisplay can't be skipped */
3379     if (mRenderingState == RENDERING_STATE_NONE)
3380         return SKIP_ERR_FIRST_FRAME;
3381 
3382     if (mDevice->mGeometryChanged != 0) {
3383         /* validateDisplay() should be called */
3384         return SKIP_ERR_GEOMETRY_CHAGNED;
3385     } else {
3386         for (uint32_t i = 0; i < mLayers.size(); i++) {
3387             if (getLayerCompositionTypeForValidationType(i) ==
3388                     HWC2_COMPOSITION_CLIENT) {
3389                 return SKIP_ERR_HAS_CLIENT_COMP;
3390             }
3391         }
3392 
3393         if ((mClientCompositionInfo.mSkipStaticInitFlag == true) &&
3394             (mClientCompositionInfo.mSkipFlag == true)) {
3395             if (skipStaticLayerChanged(mClientCompositionInfo) == true)
3396                 return SKIP_ERR_SKIP_STATIC_CHANGED;
3397         }
3398 
3399         if (mClientCompositionInfo.mHasCompositionLayer &&
3400             mClientCompositionInfo.mTargetBuffer == NULL) {
3401             return SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER;
3402         }
3403 
3404         /*
3405          * If there is hwc2_layer_request_t
3406          * validateDisplay() can't be skipped
3407          */
3408         int32_t displayRequests = 0;
3409         uint32_t outNumRequests = 0;
3410         if ((getDisplayRequests(&displayRequests, &outNumRequests, NULL, NULL) != NO_ERROR) ||
3411             (outNumRequests != 0))
3412             return SKIP_ERR_HAS_REQUEST;
3413     }
3414     return NO_ERROR;
3415 }
3416 
isFullScreenComposition()3417 bool ExynosDisplay::isFullScreenComposition() {
3418     hwc_rect_t dispRect = { INT_MAX, INT_MAX, 0, 0 };
3419     for (auto layer : mLayers) {
3420         auto &r = layer->mDisplayFrame;
3421 
3422         if (r.top < dispRect.top)
3423             dispRect.top = r.top;
3424         if (r.left < dispRect.left)
3425             dispRect.left = r.left;
3426         if (r.bottom > dispRect.bottom)
3427             dispRect.bottom = r.bottom;
3428         if (r.right > dispRect.right)
3429             dispRect.right = r.right;
3430     }
3431 
3432     if ((dispRect.right != mXres) || (dispRect.bottom != mYres)) {
3433         ALOGD("invalid displayFrame disp=[%d %d %d %d] expected=%dx%d",
3434                 dispRect.left, dispRect.top, dispRect.right, dispRect.bottom,
3435                 mXres, mYres);
3436         return false;
3437     }
3438 
3439     return true;
3440 }
3441 
dumpBuffer(const String8 & prefix,const exynos_image & image,std::ofstream & configFile)3442 void dumpBuffer(const String8& prefix, const exynos_image& image, std::ofstream& configFile) {
3443     ATRACE_NAME(prefix.c_str());
3444     if (image.bufferHandle == nullptr) {
3445         ALOGE("%s: Buffer handle for %s is NULL", __func__, prefix.c_str());
3446         return;
3447     }
3448     ALOGI("%s: dumping buffer for %s", __func__, prefix.c_str());
3449 
3450     bool failFenceSync = false;
3451     String8 infoDump;
3452     if (image.acquireFenceFd > 0 && sync_wait(image.acquireFenceFd, 1000) < 0) {
3453         infoDump.appendFormat("Failed to sync acquire fence\n");
3454         ALOGE("%s: Failed to wait acquire fence %d, errno=(%d, %s)", __func__, image.acquireFenceFd,
3455               errno, strerror(errno));
3456         failFenceSync = true;
3457     }
3458     if (image.releaseFenceFd > 0 && sync_wait(image.releaseFenceFd, 1000) < 0) {
3459         infoDump.appendFormat("Failed to sync release fence\n");
3460 
3461         ALOGE("%s: Failed to wait release fence %d, errno=(%d, %s)", __func__, image.releaseFenceFd,
3462               errno, strerror(errno));
3463         failFenceSync = true;
3464     }
3465 
3466     VendorGraphicBufferMeta gmeta(image.bufferHandle);
3467     String8 infoPath = String8::format("%s/%s-info.txt", kBufferDumpPath, prefix.c_str());
3468     std::ofstream infoFile(infoPath.c_str());
3469     if (!infoFile) {
3470         ALOGE("%s: failed to open file %s", __func__, infoPath.c_str());
3471         return;
3472     }
3473 
3474     // TODO(b/261232489): Fix fence sync errors
3475     // We currently ignore the fence errors and just dump the buffers
3476 
3477     // dump buffer info
3478     dumpExynosImage(infoDump, image);
3479     infoDump.appendFormat("\nfd[%d, %d, %d] size[%d, %d, %d]\n", gmeta.fd, gmeta.fd1, gmeta.fd2,
3480                           gmeta.size, gmeta.size1, gmeta.size2);
3481     infoDump.appendFormat(" offset[%d, %d, %d] format:%d framework_format:%d\n", gmeta.offset,
3482                           gmeta.offset1, gmeta.offset2, gmeta.format, gmeta.frameworkFormat);
3483     infoDump.appendFormat(" width:%d height:%d stride:%d vstride:%d\n", gmeta.width, gmeta.height,
3484                           gmeta.stride, gmeta.vstride);
3485     infoDump.appendFormat(" producer: 0x%" PRIx64 " consumer: 0x%" PRIx64 " flags: 0x%" PRIx32 "\n",
3486                           gmeta.producer_usage, gmeta.consumer_usage, gmeta.flags);
3487     infoFile << infoDump << std::endl;
3488 
3489     String8 bufferPath =
3490             String8::format("%s/%s-%s.raw", kBufferDumpPath, prefix.c_str(),
3491                             getFormatStr(image.format, image.compressionInfo.type).c_str());
3492     std::ofstream bufferFile(bufferPath.c_str(), std::ios::binary);
3493     if (!bufferFile) {
3494         ALOGE("%s: failed to open file %s", __func__, bufferPath.c_str());
3495         return;
3496     }
3497 
3498     // dump info that can be loaded by hwc-tester
3499     configFile << "buffers {\n";
3500     configFile << "    key: \"" << prefix << "\"\n";
3501     configFile << "    format: " << getFormatStr(image.format, image.compressionInfo.type) << "\n";
3502     configFile << "    width: " << gmeta.width << "\n";
3503     configFile << "    height: " << gmeta.height << "\n";
3504     auto usage = gmeta.producer_usage | gmeta.consumer_usage;
3505     configFile << "    usage: 0x" << std::hex << usage << std::dec << "\n";
3506     configFile << "    filepath: \"" << bufferPath << "\"\n";
3507     configFile << "}\n" << std::endl;
3508 
3509     int bufferNumber = getBufferNumOfFormat(image.format, image.compressionInfo.type);
3510     for (int i = 0; i < bufferNumber; ++i) {
3511         if (gmeta.fds[i] <= 0) {
3512             ALOGE("%s: gmeta.fds[%d]=%d is invalid", __func__, i, gmeta.fds[i]);
3513             continue;
3514         }
3515         if (gmeta.sizes[i] <= 0) {
3516             ALOGE("%s: gmeta.sizes[%d]=%d is invalid", __func__, i, gmeta.sizes[i]);
3517             continue;
3518         }
3519         auto addr = mmap(0, gmeta.sizes[i], PROT_READ | PROT_WRITE, MAP_SHARED, gmeta.fds[i], 0);
3520         if (addr != MAP_FAILED && addr != NULL) {
3521             bufferFile.write(static_cast<char*>(addr), gmeta.sizes[i]);
3522             munmap(addr, gmeta.sizes[i]);
3523         } else {
3524             ALOGE("%s: failed to mmap fds[%d]:%d for %s", __func__, i, gmeta.fds[i]);
3525         }
3526     }
3527 }
3528 
dumpAllBuffers()3529 void ExynosDisplay::dumpAllBuffers() {
3530     ATRACE_CALL();
3531     // dump layers info
3532     String8 infoPath = String8::format("%s/%03d-display-info.txt", kBufferDumpPath, mBufferDumpNum);
3533     std::ofstream infoFile(infoPath.c_str());
3534     if (!infoFile) {
3535         DISPLAY_LOGE("%s: failed to open file %s", __func__, infoPath.c_str());
3536         ++mBufferDumpNum;
3537         return;
3538     }
3539     String8 displayDump;
3540     dumpLocked(displayDump);
3541     infoFile << displayDump << std::endl;
3542 
3543     // dump buffer contents & infos
3544     std::vector<String8> allLayerKeys;
3545     String8 testerConfigPath =
3546             String8::format("%s/%03d-hwc-tester-config.textproto", kBufferDumpPath, mBufferDumpNum);
3547     std::ofstream configFile(testerConfigPath.c_str());
3548     configFile << std::string(15, '#')
3549                << " You can load this config file using hwc-tester to reproduce this frame "
3550                << std::string(15, '#') << std::endl;
3551     {
3552         std::scoped_lock lock(mDRMutex);
3553         for (int i = 0; i < mLayers.size(); ++i) {
3554             String8 prefix = String8::format("%03d-%d-src", mBufferDumpNum, i);
3555             dumpBuffer(prefix, mLayers[i]->mSrcImg, configFile);
3556             if (mLayers[i]->mM2mMPP != nullptr) {
3557                 String8 midPrefix = String8::format("%03d-%d-mid", mBufferDumpNum, i);
3558                 exynos_image image = mLayers[i]->mMidImg;
3559                 mLayers[i]->mM2mMPP->getDstImageInfo(&image);
3560                 dumpBuffer(midPrefix, image, configFile);
3561             }
3562             configFile << "layers {\n";
3563             configFile << "    key: \"" << prefix << "\"\n";
3564             configFile << "    composition: "
3565                        << AidlComposer3::toString(static_cast<AidlComposer3::Composition>(
3566                                   mLayers[i]->mRequestedCompositionType))
3567                        << "\n";
3568             configFile << "    source_crop: {\n";
3569             configFile << "        left: " << mLayers[i]->mPreprocessedInfo.sourceCrop.left << "\n";
3570             configFile << "        top: " << mLayers[i]->mPreprocessedInfo.sourceCrop.top << "\n";
3571             configFile << "        right: " << mLayers[i]->mPreprocessedInfo.sourceCrop.right
3572                        << "\n";
3573             configFile << "        bottom: " << mLayers[i]->mPreprocessedInfo.sourceCrop.bottom
3574                        << "\n";
3575             configFile << "    }\n";
3576             configFile << "    display_frame: {\n";
3577             configFile << "        left: " << mLayers[i]->mPreprocessedInfo.displayFrame.left
3578                        << "\n";
3579             configFile << "        top: " << mLayers[i]->mPreprocessedInfo.displayFrame.top << "\n";
3580             configFile << "        right: " << mLayers[i]->mPreprocessedInfo.displayFrame.right
3581                        << "\n";
3582             configFile << "        bottom: " << mLayers[i]->mPreprocessedInfo.displayFrame.bottom
3583                        << "\n";
3584             configFile << "    }\n";
3585             configFile << "    dataspace: "
3586                        << AidlCommon::toString(
3587                                   static_cast<AidlCommon::Dataspace>(mLayers[i]->mDataSpace))
3588                        << "\n";
3589             configFile << "    blend: "
3590                        << AidlCommon::toString(
3591                                   static_cast<AidlCommon::BlendMode>(mLayers[i]->mBlending))
3592                        << "\n";
3593             configFile << "    transform: "
3594                        << AidlCommon::toString(
3595                                   static_cast<AidlCommon::Transform>(mLayers[i]->mTransform))
3596                        << "\n";
3597             configFile << "    plane_alpha: " << mLayers[i]->mPlaneAlpha << "\n";
3598             configFile << "    z_order: " << mLayers[i]->mZOrder << "\n";
3599             if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_SOLID_COLOR) {
3600                 configFile << "    color: {\n";
3601                 configFile << "        r: " << mLayers[i]->mColor.r << "\n";
3602                 configFile << "        g: " << mLayers[i]->mColor.g << "\n";
3603                 configFile << "        b: " << mLayers[i]->mColor.b << "\n";
3604                 configFile << "        a: " << mLayers[i]->mColor.a << "\n";
3605                 configFile << "    }\n";
3606             } else if (mLayers[i]->mSrcImg.bufferHandle != nullptr) {
3607                 configFile << "    buffer_key: \"" << prefix << "\"\n";
3608             }
3609             configFile << "}\n" << std::endl;
3610             allLayerKeys.push_back(prefix);
3611         }
3612     }
3613 
3614     if (mClientCompositionInfo.mHasCompositionLayer) {
3615         String8 prefix = String8::format("%03d-client-target", mBufferDumpNum);
3616         exynos_image src, dst;
3617         setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src, &dst);
3618         dumpBuffer(prefix, src, configFile);
3619     }
3620 
3621     configFile << "timelines {\n";
3622     configFile << "    display_id: " << mDisplayId << "\n";
3623     configFile << "    width: " << mXres << "\n";
3624     configFile << "    height: " << mYres << "\n";
3625     configFile << "    color_mode: "
3626                << AidlComposer3::toString(static_cast<AidlComposer3::ColorMode>(mColorMode))
3627                << "\n";
3628     configFile << std::endl;
3629     for (auto& layerKey : allLayerKeys) {
3630         configFile << "    layers: {\n";
3631         configFile << "        layer_key: \"" << layerKey << "\"\n";
3632         configFile << "    }\n";
3633     }
3634     configFile << "}" << std::endl;
3635 
3636     ++mBufferDumpNum;
3637 }
3638 
presentDisplay(int32_t * outRetireFence)3639 int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
3640     DISPLAY_ATRACE_CALL();
3641     gettimeofday(&updateTimeInfo.lastPresentTime, NULL);
3642 
3643     const bool mixedComposition = isMixedComposition();
3644     // store this once here for the whole frame so it's consistent
3645     mUsePowerHints = usePowerHintSession();
3646     if (mUsePowerHints) {
3647         // adds + removes the tid for adpf tracking
3648         mPowerHalHint.trackThisThread();
3649         mPresentStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
3650         if (!mValidateStartTime.has_value()) {
3651             mValidationDuration = std::nullopt;
3652             // load target time here if validation was skipped
3653             mExpectedPresentTime = getExpectedPresentTime(mPresentStartTime);
3654             auto target = min(mExpectedPresentTime - mPresentStartTime,
3655                               static_cast<nsecs_t>(mVsyncPeriod));
3656             mPowerHalHint.signalTargetWorkDuration(target);
3657             // if we did not validate (have not sent hint yet) and have data for this case
3658             std::optional<nsecs_t> predictedDuration = getPredictedDuration(false);
3659             if (predictedDuration.has_value()) {
3660                 mPowerHalHint.signalActualWorkDuration(*predictedDuration);
3661             }
3662         }
3663         mRetireFenceWaitTime = std::nullopt;
3664         mValidateStartTime = std::nullopt;
3665     }
3666 
3667     int ret = HWC2_ERROR_NONE;
3668     String8 errString;
3669     thread_local bool setTaskProfileDone = false;
3670 
3671     if (setTaskProfileDone == false) {
3672         if (!SetTaskProfiles(gettid(), {"SFMainPolicy"})) {
3673             ALOGW("Failed to add `%d` into SFMainPolicy", gettid());
3674         }
3675         setTaskProfileDone = true;
3676     }
3677 
3678     Mutex::Autolock lock(mDisplayMutex);
3679 
3680     if (!mHpdStatus) {
3681         ALOGD("presentDisplay: drop frame: mHpdStatus == false");
3682     }
3683 
3684     mDropFrameDuringResSwitch =
3685             (mGeometryChanged & GEOMETRY_DISPLAY_RESOLUTION_CHANGED) && !isFullScreenComposition();
3686     if (mDropFrameDuringResSwitch) {
3687         ALOGD("presentDisplay: drop invalid frame during resolution switch");
3688     }
3689 
3690     if (!mHpdStatus || mDropFrameDuringResSwitch || mPauseDisplay || mDevice->isInTUI()) {
3691         closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3692         *outRetireFence = -1;
3693         mRenderingState = RENDERING_STATE_PRESENTED;
3694         applyExpectedPresentTime();
3695         return ret;
3696     }
3697 
3698     /*
3699      * buffer handle, dataspace were set by setClientTarget() after validateDisplay
3700      * ExynosImage should be set again according to changed handle and dataspace
3701      */
3702     exynos_image src_img;
3703     exynos_image dst_img;
3704     setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
3705     mClientCompositionInfo.setExynosImage(src_img, dst_img);
3706     mClientCompositionInfo.setExynosMidImage(dst_img);
3707 
3708     funcReturnCallback presentRetCallback([&]() {
3709         if (ret != HWC2_ERROR_NOT_VALIDATED)
3710             presentPostProcessing();
3711     });
3712 
3713     if (mSkipFrame) {
3714         ALOGI("[%d] presentDisplay is skipped by mSkipFrame", mDisplayId);
3715         closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3716         setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE);
3717         *outRetireFence = -1;
3718         for (size_t i=0; i < mLayers.size(); i++) {
3719             mLayers[i]->mReleaseFence = -1;
3720         }
3721         if (mRenderingState == RENDERING_STATE_NONE) {
3722             ALOGD("\tThis is the first frame after power on");
3723             ret = HWC2_ERROR_NONE;
3724         } else {
3725             ALOGD("\tThis is the second frame after power on");
3726             ret = HWC2_ERROR_NOT_VALIDATED;
3727         }
3728         mRenderingState = RENDERING_STATE_PRESENTED;
3729         mDevice->onRefresh(mDisplayId);
3730         return ret;
3731     }
3732 
3733     tryUpdateBtsFromOperationRate(true);
3734 
3735     if (mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE) {
3736         /*
3737          * presentDisplay() can be called before validateDisplay()
3738          * when HWC2_CAPABILITY_SKIP_VALIDATE is supported
3739          */
3740 #ifdef HWC_NO_SUPPORT_SKIP_VALIDATE
3741         DISPLAY_LOGE("%s:: Skip validate is not supported. Invalid rendering state : %d", __func__, mRenderingState);
3742         goto err;
3743 #endif
3744         if ((mRenderingState != RENDERING_STATE_NONE) &&
3745             (mRenderingState != RENDERING_STATE_PRESENTED)) {
3746             DISPLAY_LOGE("%s:: invalid rendering state : %d", __func__, mRenderingState);
3747             goto err;
3748         }
3749 
3750         if (mDevice->canSkipValidate() == false)
3751             goto not_validated;
3752         else {
3753             for (size_t i=0; i < mLayers.size(); i++) {
3754                 // Layer's acquire fence from SF
3755                 mLayers[i]->setSrcAcquireFence();
3756             }
3757             DISPLAY_LOGD(eDebugSkipValidate, "validate is skipped");
3758         }
3759 
3760         if (updateColorConversionInfo() != NO_ERROR) {
3761             ALOGE("%s:: updateColorConversionInfo() fail, ret(%d)",
3762                     __func__, ret);
3763         }
3764         if (mDisplayControl.earlyStartMPP == true) {
3765             /*
3766              * HWC should update performanceInfo when validate is skipped
3767              * HWC excludes the layer from performance calculation
3768              * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
3769              * Therefore performanceInfo should be calculated again if the buffer is updated.
3770              */
3771             if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
3772                 DISPLAY_LOGE("deliverPerformanceInfo() error (%d) in validateSkip case", ret);
3773             }
3774             startPostProcessing();
3775         }
3776     }
3777     mRetireFenceAcquireTime = std::nullopt;
3778     mDpuData.reset();
3779 
3780     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
3781         if ((ret = doDisplayConfigPostProcess(mDevice)) != NO_ERROR) {
3782             DISPLAY_LOGE("doDisplayConfigPostProcess error (%d)", ret);
3783         }
3784     }
3785 
3786     if (updatePresentColorConversionInfo() != NO_ERROR) {
3787         ALOGE("%s:: updatePresentColorConversionInfo() fail, ret(%d)",
3788                 __func__, ret);
3789     }
3790 
3791     if ((mLayers.size() == 0) &&
3792         (mType != HWC_DISPLAY_VIRTUAL)) {
3793         ALOGI("%s:: layer size is 0", __func__);
3794         clearDisplay();
3795         *outRetireFence = -1;
3796         mLastRetireFence = fence_close(mLastRetireFence, this,
3797                 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3798         mRenderingState = RENDERING_STATE_PRESENTED;
3799         ret = 0;
3800         return ret;
3801     }
3802 
3803     if (!checkFrameValidation()) {
3804         ALOGW("%s: checkFrameValidation fail", __func__);
3805         clearDisplay();
3806         *outRetireFence = -1;
3807         mLastRetireFence = fence_close(mLastRetireFence, this,
3808                 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3809         mRenderingState = RENDERING_STATE_PRESENTED;
3810         return ret;
3811     }
3812 
3813     if ((mDisplayControl.earlyStartMPP == false) &&
3814         ((ret = doExynosComposition()) != NO_ERROR)) {
3815         errString.appendFormat("exynosComposition fail (%d)\n", ret);
3816         goto err;
3817     }
3818 
3819     // loop for all layer
3820     for (size_t i=0; i < mLayers.size(); i++) {
3821         /* mAcquireFence is updated, Update image info */
3822         struct exynos_image srcImg, dstImg, midImg;
3823         mLayers[i]->setSrcExynosImage(&srcImg);
3824         mLayers[i]->setDstExynosImage(&dstImg);
3825         mLayers[i]->setExynosImage(srcImg, dstImg);
3826 
3827         if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
3828             mLayers[i]->mReleaseFence = -1;
3829             mLayers[i]->mAcquireFence =
3830                 fence_close(mLayers[i]->mAcquireFence, this,
3831                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3832         } else if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) {
3833             continue;
3834         } else {
3835             if (mLayers[i]->mOtfMPP != NULL) {
3836                 mLayers[i]->mOtfMPP->requestHWStateChange(MPP_HW_STATE_RUNNING);
3837             }
3838 
3839             if ((mDisplayControl.earlyStartMPP == false) &&
3840                 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
3841                 (mLayers[i]->mM2mMPP != NULL)) {
3842                 ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
3843                 midImg = mLayers[i]->mMidImg;
3844                 m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
3845                 if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
3846                     HWC_LOGE(this, "%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
3847                             __func__, i, ret);
3848                     errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
3849                             __func__, i, ret);
3850                     goto err;
3851                 } else {
3852                     /* This should be closed by lib for each resource */
3853                     mLayers[i]->mAcquireFence = -1;
3854                 }
3855             }
3856         }
3857     }
3858 
3859     if ((ret = setWinConfigData()) != NO_ERROR) {
3860         errString.appendFormat("setWinConfigData fail (%d)\n", ret);
3861         goto err;
3862     }
3863 
3864     if ((ret = handleStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
3865         mClientCompositionInfo.mSkipStaticInitFlag = false;
3866         errString.appendFormat("handleStaticLayers error\n");
3867         goto err;
3868     }
3869 
3870     if (shouldSignalNonIdle()) {
3871         mPowerHalHint.signalNonIdle();
3872     }
3873 
3874     if (!checkUpdateRRIndicatorOnly()) {
3875         if (mRefreshRateIndicatorHandler) {
3876             mRefreshRateIndicatorHandler->checkOnPresentDisplay();
3877         }
3878     }
3879 
3880     handleWindowUpdate();
3881 
3882     setDisplayWinConfigData();
3883 
3884     if ((ret = deliverWinConfigData()) != NO_ERROR) {
3885         HWC_LOGE(this, "%s:: fail to deliver win_config (%d)", __func__, ret);
3886         if (mDpuData.retire_fence > 0)
3887             fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3888         mDpuData.retire_fence = -1;
3889     }
3890 
3891     setReleaseFences();
3892 
3893     if (mBufferDumpNum < mBufferDumpCount) {
3894         dumpAllBuffers();
3895     }
3896 
3897     if (mDpuData.retire_fence != -1) {
3898 #ifdef DISABLE_FENCE
3899         if (mDpuData.retire_fence >= 0)
3900             fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3901         *outRetireFence = -1;
3902 #else
3903         *outRetireFence =
3904             hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, mDpuData.retire_fence);
3905 #endif
3906         setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_LAYER,
3907                      HwcFenceDirection::TO);
3908     } else
3909         *outRetireFence = -1;
3910 
3911     /* Update last retire fence */
3912     mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3913     mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, true);
3914     setFenceName(mLastRetireFence, FENCE_RETIRE);
3915 
3916     increaseMPPDstBufIndex();
3917 
3918     /* Check all of acquireFence are closed */
3919     for (size_t i=0; i < mLayers.size(); i++) {
3920         if (mLayers[i]->mAcquireFence != -1) {
3921             DISPLAY_LOGE("layer[%zu] fence(%d) type(%d, %d, %d) is not closed",
3922                     i, mLayers[i]->mAcquireFence,
3923                     mLayers[i]->mCompositionType,
3924                     mLayers[i]->mExynosCompositionType,
3925                     mLayers[i]->mValidateCompositionType);
3926             if (mLayers[i]->mM2mMPP != NULL)
3927                 DISPLAY_LOGE("\t%s is assigned", mLayers[i]->mM2mMPP->mName.c_str());
3928             if (mLayers[i]->mAcquireFence > 0)
3929                 fence_close(mLayers[i]->mAcquireFence, this,
3930                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3931             mLayers[i]->mAcquireFence = -1;
3932         }
3933     }
3934     if (mExynosCompositionInfo.mAcquireFence >= 0) {
3935         DISPLAY_LOGE("mExynosCompositionInfo mAcquireFence(%d) is not initialized", mExynosCompositionInfo.mAcquireFence);
3936         fence_close(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
3937         mExynosCompositionInfo.mAcquireFence = -1;
3938     }
3939     if (mClientCompositionInfo.mAcquireFence >= 0) {
3940         DISPLAY_LOGE("mClientCompositionInfo mAcquireFence(%d) is not initialized", mClientCompositionInfo.mAcquireFence);
3941         fence_close(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
3942         mClientCompositionInfo.mAcquireFence = -1;
3943     }
3944 
3945     /* All of release fences are tranferred */
3946     for (size_t i=0; i < mLayers.size(); i++) {
3947         setFenceInfo(mLayers[i]->mReleaseFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER,
3948                      HwcFenceDirection::TO);
3949     }
3950 
3951     doPostProcessing();
3952 
3953     if (!mDevice->validateFences(this)) {
3954         ALOGE("%s:: validate fence failed.", __func__);
3955     }
3956 
3957     mDpuData.reset();
3958 
3959     mRenderingState = RENDERING_STATE_PRESENTED;
3960 
3961     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3962         /* Do not update mVsyncPeriod */
3963         updateInternalDisplayConfigVariables(mDesiredConfig, false);
3964     }
3965 
3966     if (mUsePowerHints) {
3967         // update the "last present" now that we know for sure when this frame is due
3968         mLastExpectedPresentTime = mExpectedPresentTime;
3969 
3970         // we add an offset here to keep the flinger and HWC error terms roughly the same
3971         static const constexpr std::chrono::nanoseconds kFlingerOffset = 300us;
3972         nsecs_t now = systemTime() + kFlingerOffset.count();
3973 
3974         updateAverages(now);
3975         nsecs_t duration = now - mPresentStartTime;
3976         if (mRetireFenceWaitTime.has_value() && mRetireFenceAcquireTime.has_value()) {
3977             duration = now - *mRetireFenceAcquireTime + *mRetireFenceWaitTime - mPresentStartTime;
3978         }
3979         mPowerHalHint.signalActualWorkDuration(duration + mValidationDuration.value_or(0));
3980     }
3981 
3982     mPriorFrameMixedComposition = mixedComposition;
3983 
3984     tryUpdateBtsFromOperationRate(false);
3985 
3986     return ret;
3987 err:
3988     printDebugInfos(errString);
3989     closeFences();
3990     *outRetireFence = -1;
3991     mLastRetireFence = -1;
3992     mRenderingState = RENDERING_STATE_PRESENTED;
3993     setGeometryChanged(GEOMETRY_ERROR_CASE);
3994 
3995     mLastDpuData.reset();
3996 
3997     mClientCompositionInfo.mSkipStaticInitFlag = false;
3998     mExynosCompositionInfo.mSkipStaticInitFlag = false;
3999 
4000     mDpuData.reset();
4001 
4002     if (!mDevice->validateFences(this)) {
4003         ALOGE("%s:: validate fence failed.", __func__);
4004     }
4005     mDisplayInterface->setForcePanic();
4006 
4007     ret = -EINVAL;
4008     return ret;
4009 
4010 not_validated:
4011     DISPLAY_LOGD(eDebugSkipValidate, "display need validate");
4012     mRenderingState = RENDERING_STATE_NONE;
4013     ret = HWC2_ERROR_NOT_VALIDATED;
4014     return ret;
4015 }
4016 
presentPostProcessing()4017 int32_t ExynosDisplay::presentPostProcessing()
4018 {
4019     setReadbackBufferInternal(NULL, -1, false);
4020     if (mDpuData.enable_readback)
4021         mDevice->signalReadbackDone();
4022     mDpuData.enable_readback = false;
4023 
4024     for (auto it : mIgnoreLayers) {
4025         /*
4026          * Directly close without counting down
4027          * because it was not counted by validate
4028          */
4029         if (it->mAcquireFence > 0) {
4030             close(it->mAcquireFence);
4031         }
4032         it->mAcquireFence = -1;
4033     }
4034     return NO_ERROR;
4035 }
4036 
setActiveConfig(hwc2_config_t config)4037 int32_t ExynosDisplay::setActiveConfig(hwc2_config_t config)
4038 {
4039     Mutex::Autolock lock(mDisplayMutex);
4040     DISPLAY_LOGD(eDebugDisplayConfig, "%s:: config(%d)", __func__, config);
4041     return setActiveConfigInternal(config, false);
4042 }
4043 
setActiveConfigInternal(hwc2_config_t config,bool force)4044 int32_t ExynosDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
4045     if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
4046 
4047     if (!force && needNotChangeConfig(config)) {
4048         ALOGI("skip same config %d (force %d)", config, force);
4049         return HWC2_ERROR_NONE;
4050     }
4051 
4052     DISPLAY_LOGD(eDebugDisplayConfig, "(current %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", mActiveConfig,
4053             mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
4054     DISPLAY_LOGD(eDebugDisplayConfig, "(requested %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", config,
4055             mDisplayConfigs[config].width, mDisplayConfigs[config].height, mDisplayConfigs[config].vsyncPeriod,
4056             mDisplayConfigs[config].Xdpi, mDisplayConfigs[config].Ydpi);
4057 
4058     if (mDisplayInterface->setActiveConfig(config) < 0) {
4059         ALOGE("%s bad config request", __func__);
4060         return HWC2_ERROR_BAD_CONFIG;
4061     }
4062 
4063     if ((mXres != mDisplayConfigs[config].width) ||
4064         (mYres != mDisplayConfigs[config].height)) {
4065         mRenderingState = RENDERING_STATE_NONE;
4066         setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
4067     }
4068 
4069     updateInternalDisplayConfigVariables(config);
4070     return HWC2_ERROR_NONE;
4071 }
4072 
setClientTarget(buffer_handle_t target,int32_t acquireFence,int32_t dataspace)4073 int32_t ExynosDisplay::setClientTarget(
4074         buffer_handle_t target,
4075         int32_t acquireFence, int32_t /*android_dataspace_t*/ dataspace) {
4076     buffer_handle_t handle = NULL;
4077     if (target != NULL)
4078         handle = target;
4079 
4080 #ifdef DISABLE_FENCE
4081     if (acquireFence >= 0)
4082         fence_close(acquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
4083     acquireFence = -1;
4084 #endif
4085     acquireFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, acquireFence);
4086     if (handle == NULL) {
4087         DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget is NULL, skipStaic (%d)",
4088                 mClientCompositionInfo.mSkipFlag);
4089         if (mClientCompositionInfo.mSkipFlag == false) {
4090             DISPLAY_LOGE("ClientTarget is NULL");
4091             DISPLAY_LOGE("\t%s:: mRenderingState(%d)",__func__, mRenderingState);
4092         }
4093     } else {
4094         VendorGraphicBufferMeta gmeta(handle);
4095 
4096         DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget handle: %p [fd: %d, %d, %d]",
4097                 handle, gmeta.fd, gmeta.fd1, gmeta.fd2);
4098         if ((mClientCompositionInfo.mSkipFlag == true) &&
4099                 ((mClientCompositionInfo.mLastWinConfigData.fd_idma[0] != gmeta.fd) ||
4100                  (mClientCompositionInfo.mLastWinConfigData.fd_idma[1] != gmeta.fd1) ||
4101                  (mClientCompositionInfo.mLastWinConfigData.fd_idma[2] != gmeta.fd2))) {
4102             String8 errString;
4103             DISPLAY_LOGE("skip flag is enabled but buffer is updated lastConfig[%d, %d, %d], handle[%d, %d, %d]\n",
4104                     mClientCompositionInfo.mLastWinConfigData.fd_idma[0],
4105                     mClientCompositionInfo.mLastWinConfigData.fd_idma[1],
4106                     mClientCompositionInfo.mLastWinConfigData.fd_idma[2],
4107                     gmeta.fd, gmeta.fd1, gmeta.fd2);
4108             DISPLAY_LOGE("last win config");
4109             for (size_t i = 0; i < mLastDpuData.configs.size(); i++) {
4110                 errString.appendFormat("config[%zu]\n", i);
4111                 dumpConfig(errString, mLastDpuData.configs[i]);
4112                 DISPLAY_LOGE("\t%s", errString.c_str());
4113                 errString.clear();
4114             }
4115             errString.appendFormat("%s:: skip flag is enabled but buffer is updated\n",
4116                     __func__);
4117             printDebugInfos(errString);
4118         }
4119     }
4120     mClientCompositionInfo.setTargetBuffer(this, handle, acquireFence, (android_dataspace)dataspace);
4121     setFenceInfo(acquireFence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, HwcFenceDirection::FROM);
4122 
4123     if (handle) {
4124         mClientCompositionInfo.mCompressionInfo = getCompressionInfo(handle);
4125         mExynosCompositionInfo.mCompressionInfo = getCompressionInfo(handle);
4126     }
4127 
4128     return 0;
4129 }
4130 
setColorTransform(const float * matrix,int32_t hint)4131 int32_t ExynosDisplay::setColorTransform(
4132         const float* matrix,
4133         int32_t /*android_color_transform_t*/ hint) {
4134     if ((hint < HAL_COLOR_TRANSFORM_IDENTITY) ||
4135         (hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA))
4136         return HWC2_ERROR_BAD_PARAMETER;
4137     ALOGI("%s:: %d, %d", __func__, mColorTransformHint, hint);
4138     if (mColorTransformHint != hint)
4139         setGeometryChanged(GEOMETRY_DISPLAY_COLOR_TRANSFORM_CHANGED);
4140     mColorTransformHint = hint;
4141 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4142     int ret = mDisplayInterface->setColorTransform(matrix, hint);
4143     if (ret < 0)
4144         mColorTransformHint = ret;
4145     return ret;
4146 #else
4147     return HWC2_ERROR_NONE;
4148 #endif
4149 }
4150 
setColorMode(int32_t mode)4151 int32_t ExynosDisplay::setColorMode(int32_t /*android_color_mode_t*/ mode)
4152 {
4153     if (mDisplayInterface->setColorMode(mode) < 0) {
4154         if (mode == HAL_COLOR_MODE_NATIVE)
4155             return HWC2_ERROR_NONE;
4156 
4157         ALOGE("%s:: is not supported", __func__);
4158         return HWC2_ERROR_UNSUPPORTED;
4159     }
4160 
4161     ALOGI("%s:: %d, %d", __func__, mColorMode, mode);
4162     if (mColorMode != mode)
4163         setGeometryChanged(GEOMETRY_DISPLAY_COLOR_MODE_CHANGED);
4164     mColorMode = (android_color_mode_t)mode;
4165     return HWC2_ERROR_NONE;
4166 }
4167 
getRenderIntents(int32_t mode,uint32_t * outNumIntents,int32_t * outIntents)4168 int32_t ExynosDisplay::getRenderIntents(int32_t mode, uint32_t* outNumIntents,
4169         int32_t* /*android_render_intent_v1_1_t*/ outIntents)
4170 {
4171     ALOGI("%s:: mode(%d), outNum(%d), outIntents(%p)",
4172             __func__, mode, *outNumIntents, outIntents);
4173 
4174     return mDisplayInterface->getRenderIntents(mode, outNumIntents, outIntents);
4175 }
4176 
setColorModeWithRenderIntent(int32_t mode,int32_t intent)4177 int32_t ExynosDisplay::setColorModeWithRenderIntent(int32_t /*android_color_mode_t*/ mode,
4178         int32_t /*android_render_intent_v1_1_t */ intent)
4179 {
4180     ALOGI("%s:: mode(%d), intent(%d)", __func__, mode, intent);
4181 
4182     return mDisplayInterface->setColorModeWithRenderIntent(mode, intent);
4183 }
4184 
getDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)4185 int32_t ExynosDisplay::getDisplayIdentificationData(uint8_t* outPort,
4186         uint32_t* outDataSize, uint8_t* outData)
4187 {
4188     return mDisplayInterface->getDisplayIdentificationData(outPort, outDataSize, outData);
4189 }
4190 
getDisplayCapabilities(uint32_t * outNumCapabilities,uint32_t * outCapabilities)4191 int32_t ExynosDisplay::getDisplayCapabilities(uint32_t* outNumCapabilities,
4192         uint32_t* outCapabilities)
4193 {
4194     /* If each display has their own capabilities,
4195      * this should be described in display module codes */
4196 
4197     uint32_t capabilityNum = 0;
4198     bool isBrightnessSupported = false;
4199     int32_t isDozeSupported = 0;
4200 
4201     auto ret = getDisplayBrightnessSupport(&isBrightnessSupported);
4202     if (ret != HWC2_ERROR_NONE) {
4203         ALOGE("%s: failed to getDisplayBrightnessSupport: %d", __func__, ret);
4204         return ret;
4205     }
4206     if (isBrightnessSupported) {
4207         capabilityNum++;
4208     }
4209 
4210     ret = getDozeSupport(&isDozeSupported);
4211     if (ret != HWC2_ERROR_NONE) {
4212         ALOGE("%s: failed to getDozeSupport: %d", __func__, ret);
4213         return ret;
4214     }
4215     if (isDozeSupported) {
4216         capabilityNum++;
4217     }
4218 
4219 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4220     capabilityNum++;
4221 #endif
4222 
4223     if (outCapabilities == NULL) {
4224         *outNumCapabilities = capabilityNum;
4225         return HWC2_ERROR_NONE;
4226     }
4227     if (capabilityNum != *outNumCapabilities) {
4228         ALOGE("%s:: invalid outNumCapabilities(%d), should be(%d)", __func__, *outNumCapabilities, capabilityNum);
4229         return HWC2_ERROR_BAD_PARAMETER;
4230     }
4231 
4232     uint32_t index = 0;
4233     if (isBrightnessSupported) {
4234         outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
4235     }
4236 
4237     if (isDozeSupported) {
4238         outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
4239     }
4240 
4241 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4242     outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
4243 #endif
4244 
4245     return HWC2_ERROR_NONE;
4246 }
4247 
getDisplayBrightnessSupport(bool * outSupport)4248 int32_t ExynosDisplay::getDisplayBrightnessSupport(bool* outSupport)
4249 {
4250     if (!mBrightnessController || !mBrightnessController->isSupported()) {
4251         *outSupport = false;
4252     } else {
4253         *outSupport = true;
4254     }
4255 
4256     return HWC2_ERROR_NONE;
4257 }
4258 
handleTargetOperationRate()4259 void ExynosDisplay::handleTargetOperationRate() {
4260     int32_t targetOpRate = mOperationRateManager->getTargetOperationRate();
4261     if (targetOpRate == mBrightnessController->getOperationRate()) return;
4262 
4263     mDevice->onRefresh(mDisplayId);
4264     mBrightnessController->processOperationRate(targetOpRate);
4265 }
4266 
setDisplayBrightness(float brightness,bool waitPresent)4267 int32_t ExynosDisplay::setDisplayBrightness(float brightness, bool waitPresent)
4268 {
4269     if (mBrightnessController) {
4270         int32_t ret;
4271 
4272         ret = mBrightnessController->processDisplayBrightness(brightness, mVsyncPeriod,
4273                                                               waitPresent);
4274         if (ret == NO_ERROR) {
4275             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4276             if (mOperationRateManager) {
4277                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4278                 handleTargetOperationRate();
4279             }
4280         }
4281         return ret;
4282     }
4283 
4284     return HWC2_ERROR_UNSUPPORTED;
4285 }
4286 
ignoreBrightnessUpdateRequests(bool ignore)4287 int32_t ExynosDisplay::ignoreBrightnessUpdateRequests(bool ignore) {
4288     if (mBrightnessController)
4289         return mBrightnessController->ignoreBrightnessUpdateRequests(ignore);
4290 
4291     return HWC2_ERROR_UNSUPPORTED;
4292 }
4293 
setBrightnessNits(const float nits)4294 int32_t ExynosDisplay::setBrightnessNits(const float nits)
4295 {
4296     if (mBrightnessController) {
4297         int32_t ret = mBrightnessController->setBrightnessNits(nits, mVsyncPeriod);
4298 
4299         if (ret == NO_ERROR) {
4300             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4301             if (mOperationRateManager)
4302                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4303         }
4304 
4305         return ret;
4306     }
4307 
4308     return HWC2_ERROR_UNSUPPORTED;
4309 }
4310 
setBrightnessDbv(const uint32_t dbv)4311 int32_t ExynosDisplay::setBrightnessDbv(const uint32_t dbv) {
4312     if (mBrightnessController) {
4313         int32_t ret = mBrightnessController->setBrightnessDbv(dbv, mVsyncPeriod);
4314 
4315         if (ret == NO_ERROR) {
4316             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4317             if (mOperationRateManager) {
4318                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4319             }
4320         }
4321 
4322         return ret;
4323     }
4324 
4325     return HWC2_ERROR_UNSUPPORTED;
4326 }
4327 
getDisplayConnectionType(uint32_t * outType)4328 int32_t ExynosDisplay::getDisplayConnectionType(uint32_t* outType)
4329 {
4330     if (mType == HWC_DISPLAY_PRIMARY)
4331         *outType = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL;
4332     else if (mType == HWC_DISPLAY_EXTERNAL)
4333         *outType = HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL;
4334     else
4335         return HWC2_ERROR_BAD_DISPLAY;
4336 
4337     return HWC2_ERROR_NONE;
4338 }
4339 
getDisplayVsyncPeriod(hwc2_vsync_period_t * __unused outVsyncPeriod)4340 int32_t ExynosDisplay::getDisplayVsyncPeriod(hwc2_vsync_period_t* __unused outVsyncPeriod)
4341 {
4342     Mutex::Autolock lock(mDisplayMutex);
4343     return getDisplayVsyncPeriodInternal(outVsyncPeriod);
4344 }
4345 
getConfigAppliedTime(const uint64_t desiredTime,const uint64_t actualChangeTime,int64_t & appliedTime,int64_t & refreshTime)4346 int32_t ExynosDisplay::getConfigAppliedTime(const uint64_t desiredTime,
4347         const uint64_t actualChangeTime,
4348         int64_t &appliedTime, int64_t &refreshTime)
4349 {
4350     uint32_t transientDuration = mDisplayInterface->getConfigChangeDuration();
4351     appliedTime = actualChangeTime;
4352 
4353     if (desiredTime > appliedTime) {
4354         const int64_t originalAppliedTime = appliedTime;
4355         const int64_t diff = desiredTime - appliedTime;
4356         appliedTime += (diff + mVsyncPeriod - 1) / mVsyncPeriod * mVsyncPeriod;
4357         DISPLAY_LOGD(eDebugDisplayConfig,
4358                      "desired time(%" PRId64 "), applied time(%" PRId64 "->%" PRId64 ")",
4359                      desiredTime, originalAppliedTime, appliedTime);
4360     } else {
4361         DISPLAY_LOGD(eDebugDisplayConfig, "desired time(%" PRId64 "), applied time(%" PRId64 ")",
4362                      desiredTime, appliedTime);
4363     }
4364 
4365     refreshTime = appliedTime - (transientDuration * mVsyncPeriod);
4366 
4367     return NO_ERROR;
4368 }
4369 
calculateTimelineLocked(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)4370 void ExynosDisplay::calculateTimelineLocked(
4371         hwc2_config_t config, hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
4372         hwc_vsync_period_change_timeline_t* outTimeline) {
4373     int64_t actualChangeTime = 0;
4374     /* actualChangeTime includes transient duration */
4375     mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
4376 
4377     outTimeline->refreshRequired = true;
4378     getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
4379                          outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
4380 
4381     DISPLAY_LOGD(eDebugDisplayConfig,
4382                  "requested config : %d(%d)->%d(%d), "
4383                  "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
4384                  mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
4385                  mDisplayConfigs[config].vsyncPeriod,
4386                  mVsyncPeriodChangeConstraints.desiredTimeNanos,
4387                  outTimeline->newVsyncAppliedTimeNanos);
4388 }
4389 
setActiveConfigWithConstraints(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)4390 int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
4391         hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
4392         hwc_vsync_period_change_timeline_t* outTimeline)
4393 {
4394     DISPLAY_ATRACE_CALL();
4395     Mutex::Autolock lock(mDisplayMutex);
4396     const nsecs_t current = systemTime(SYSTEM_TIME_MONOTONIC);
4397     const nsecs_t diffMs = ns2ms(vsyncPeriodChangeConstraints->desiredTimeNanos - current);
4398     DISPLAY_LOGD(eDebugDisplayConfig, "config(%d->%d), seamless(%d), diff(%" PRId64 ")",
4399                  mActiveConfig, config, vsyncPeriodChangeConstraints->seamlessRequired, diffMs);
4400 
4401     if (CC_UNLIKELY(ATRACE_ENABLED())) ATRACE_NAME(("diff:" + std::to_string(diffMs)).c_str());
4402 
4403     if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
4404 
4405     if (!isConfigSettingEnabled()) {
4406         mPendingConfig = config;
4407         DISPLAY_LOGI("%s: config setting disabled, set pending config=%d", __func__, config);
4408         return HWC2_ERROR_NONE;
4409     }
4410 
4411     if (mDisplayConfigs[mActiveConfig].groupId != mDisplayConfigs[config].groupId) {
4412         if (vsyncPeriodChangeConstraints->seamlessRequired) {
4413             DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not allowed");
4414             return HWC2_ERROR_SEAMLESS_NOT_ALLOWED;
4415         }
4416 
4417         outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
4418         outTimeline->refreshRequired = true;
4419     }
4420 
4421     if (needNotChangeConfig(config)) {
4422         outTimeline->refreshRequired = false;
4423         outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
4424         return HWC2_ERROR_NONE;
4425     }
4426 
4427     if ((mXres != mDisplayConfigs[config].width) || (mYres != mDisplayConfigs[config].height)) {
4428         if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
4429             ALOGW("Mode change not possible");
4430             return HWC2_ERROR_BAD_CONFIG;
4431         }
4432         mRenderingState = RENDERING_STATE_NONE;
4433         setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
4434         updateInternalDisplayConfigVariables(config, false);
4435     } else if (vsyncPeriodChangeConstraints->seamlessRequired) {
4436         if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
4437             DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not possible");
4438             return HWC2_ERROR_SEAMLESS_NOT_POSSIBLE;
4439         }
4440     }
4441 
4442     DISPLAY_LOGD(eDebugDisplayConfig, "%s : %dx%d, %dms, %d Xdpi, %d Ydpi", __func__,
4443             mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
4444 
4445     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4446         DISPLAY_LOGI("%s, previous request config is processing (desird %d, new request %d)",
4447                      __func__, mDesiredConfig, config);
4448     }
4449     /* Config would be requested on present time */
4450     mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING;
4451     mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
4452     mDesiredConfig = config;
4453     DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
4454 
4455     calculateTimelineLocked(config, vsyncPeriodChangeConstraints, outTimeline);
4456 
4457     /* mActiveConfig should be changed immediately for internal status */
4458     mActiveConfig = config;
4459     mVsyncAppliedTimeLine = *outTimeline;
4460     updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config));
4461 
4462     bool earlyWakeupNeeded = checkRrCompensationEnabled();
4463     if (earlyWakeupNeeded) {
4464         setEarlyWakeupDisplay();
4465     }
4466     if (mRefreshRateIndicatorHandler) {
4467         mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
4468     }
4469 
4470     return HWC2_ERROR_NONE;
4471 }
4472 
setBootDisplayConfig(int32_t config)4473 int32_t ExynosDisplay::setBootDisplayConfig(int32_t config) {
4474     return HWC2_ERROR_UNSUPPORTED;
4475 }
4476 
clearBootDisplayConfig()4477 int32_t ExynosDisplay::clearBootDisplayConfig() {
4478     return HWC2_ERROR_UNSUPPORTED;
4479 }
4480 
getPreferredBootDisplayConfig(int32_t * outConfig)4481 int32_t ExynosDisplay::getPreferredBootDisplayConfig(int32_t *outConfig) {
4482     return getPreferredDisplayConfigInternal(outConfig);
4483 }
4484 
getPreferredDisplayConfigInternal(int32_t * outConfig)4485 int32_t ExynosDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
4486     return HWC2_ERROR_UNSUPPORTED;
4487 }
4488 
setAutoLowLatencyMode(bool __unused on)4489 int32_t ExynosDisplay::setAutoLowLatencyMode(bool __unused on)
4490 {
4491     return HWC2_ERROR_UNSUPPORTED;
4492 }
4493 
getSupportedContentTypes(uint32_t * __unused outNumSupportedContentTypes,uint32_t * __unused outSupportedContentTypes)4494 int32_t ExynosDisplay::getSupportedContentTypes(uint32_t* __unused outNumSupportedContentTypes,
4495         uint32_t* __unused outSupportedContentTypes)
4496 {
4497     if (outSupportedContentTypes == NULL)
4498         outNumSupportedContentTypes = 0;
4499     return HWC2_ERROR_NONE;
4500 }
4501 
setContentType(int32_t contentType)4502 int32_t ExynosDisplay::setContentType(int32_t /* hwc2_content_type_t */ contentType)
4503 {
4504     if (contentType == HWC2_CONTENT_TYPE_NONE)
4505         return HWC2_ERROR_NONE;
4506 
4507     return HWC2_ERROR_UNSUPPORTED;
4508 }
4509 
getClientTargetProperty(hwc_client_target_property_t * outClientTargetProperty,HwcDimmingStage * outDimmingStage)4510 int32_t ExynosDisplay::getClientTargetProperty(
4511                         hwc_client_target_property_t *outClientTargetProperty,
4512                         HwcDimmingStage *outDimmingStage) {
4513     outClientTargetProperty->pixelFormat = HAL_PIXEL_FORMAT_RGBA_8888;
4514     outClientTargetProperty->dataspace = HAL_DATASPACE_UNKNOWN;
4515     if (outDimmingStage != nullptr)
4516         *outDimmingStage = HwcDimmingStage::DIMMING_NONE;
4517 
4518     return HWC2_ERROR_NONE;
4519 }
4520 
isBadConfig(hwc2_config_t config)4521 bool ExynosDisplay::isBadConfig(hwc2_config_t config)
4522 {
4523     /* Check invalid config */
4524     const auto its = mDisplayConfigs.find(config);
4525     if (its == mDisplayConfigs.end()) {
4526         DISPLAY_LOGE("%s, invalid config : %d", __func__, config);
4527         return true;
4528     }
4529 
4530     return false;
4531 }
4532 
needNotChangeConfig(hwc2_config_t config)4533 bool ExynosDisplay::needNotChangeConfig(hwc2_config_t config)
4534 {
4535     /* getting current config and compare */
4536     /* If same value, return */
4537     if (mActiveConfig == config) {
4538         DISPLAY_LOGI("%s, Same config change requested : %d", __func__, config);
4539         return true;
4540     }
4541 
4542     return false;
4543 }
4544 
updateInternalDisplayConfigVariables(hwc2_config_t config,bool updateVsync)4545 int32_t ExynosDisplay::updateInternalDisplayConfigVariables(
4546         hwc2_config_t config, bool updateVsync)
4547 {
4548     mActiveConfig = config;
4549 
4550     /* Update internal variables */
4551     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_WIDTH, (int32_t*)&mXres);
4552     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_HEIGHT, (int32_t*)&mYres);
4553     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_X, (int32_t*)&mXdpi);
4554     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_Y, (int32_t*)&mYdpi);
4555     mHdrFullScrenAreaThreshold = mXres * mYres * kHdrFullScreen;
4556     if (updateVsync) {
4557         resetConfigRequestStateLocked(config);
4558     }
4559     if (mRefreshRateIndicatorHandler) {
4560         mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
4561     }
4562 
4563     return NO_ERROR;
4564 }
4565 
updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod,bool configApplied)4566 void ExynosDisplay::updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod, bool configApplied) {
4567     if (mBtsFrameScanoutPeriod == frameScanoutPeriod) {
4568         return;
4569     }
4570 
4571     if (configApplied || frameScanoutPeriod < mBtsFrameScanoutPeriod) {
4572         checkBtsReassignResource(frameScanoutPeriod, mBtsFrameScanoutPeriod);
4573         mBtsFrameScanoutPeriod = frameScanoutPeriod;
4574         ATRACE_INT("btsFrameScanoutPeriod", mBtsFrameScanoutPeriod);
4575     }
4576 }
4577 
tryUpdateBtsFromOperationRate(bool beforeValidateDisplay)4578 void ExynosDisplay::tryUpdateBtsFromOperationRate(bool beforeValidateDisplay) {
4579     if (mOperationRateManager == nullptr || mBrightnessController == nullptr ||
4580         mActiveConfig == UINT_MAX) {
4581         return;
4582     }
4583 
4584     if (!mDisplayConfigs[mActiveConfig].isOperationRateToBts) {
4585         return;
4586     }
4587 
4588     if (beforeValidateDisplay && mBrightnessController->isOperationRatePending()) {
4589         uint32_t opRate = mBrightnessController->getOperationRate();
4590         if (opRate) {
4591             int32_t operationRatePeriod = nsecsPerSec / opRate;
4592             if (operationRatePeriod < mBtsFrameScanoutPeriod) {
4593                 updateBtsFrameScanoutPeriod(opRate);
4594                 mBtsPendingOperationRatePeriod = 0;
4595             } else if (operationRatePeriod != mBtsFrameScanoutPeriod) {
4596                 mBtsPendingOperationRatePeriod = operationRatePeriod;
4597             }
4598         }
4599     }
4600 
4601     if (!beforeValidateDisplay && mBtsPendingOperationRatePeriod &&
4602         !mBrightnessController->isOperationRatePending()) {
4603         /* Do not update during rr transition, it will be updated after setting config done */
4604         if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4605             updateBtsFrameScanoutPeriod(mBtsPendingOperationRatePeriod, true);
4606         }
4607         mBtsPendingOperationRatePeriod = 0;
4608     }
4609 }
4610 
getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config)4611 inline int32_t ExynosDisplay::getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config) {
4612     int32_t frameScanoutPeriodNs;
4613     auto vrrConfig = getVrrConfigs(config);
4614     if (vrrConfig.has_value() && vrrConfig->isFullySupported) {
4615         frameScanoutPeriodNs = vrrConfig->minFrameIntervalNs;
4616     } else {
4617         getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &frameScanoutPeriodNs);
4618         if (mOperationRateManager && mBrightnessController &&
4619             mDisplayConfigs[config].isOperationRateToBts) {
4620             uint32_t opRate = mBrightnessController->getOperationRate();
4621             if (opRate) {
4622                 uint32_t opPeriodNs = nsecsPerSec / opRate;
4623                 frameScanoutPeriodNs =
4624                         (frameScanoutPeriodNs <= opPeriodNs) ? frameScanoutPeriodNs : opPeriodNs;
4625             }
4626         }
4627     }
4628 
4629     assert(frameScanoutPeriodNs > 0);
4630     return frameScanoutPeriodNs;
4631 }
4632 
getBtsRefreshRate() const4633 uint32_t ExynosDisplay::getBtsRefreshRate() const {
4634     return static_cast<uint32_t>(round(nsecsPerSec / mBtsFrameScanoutPeriod * 0.1f) * 10);
4635 }
4636 
updateRefreshRateHint()4637 void ExynosDisplay::updateRefreshRateHint() {
4638     if (mRefreshRate) {
4639         mPowerHalHint.signalRefreshRate(mPowerModeState.value_or(HWC2_POWER_MODE_OFF),
4640                                         mRefreshRate);
4641     }
4642 }
4643 
4644 /* This function must be called within a mDisplayMutex protection */
resetConfigRequestStateLocked(hwc2_config_t config)4645 int32_t ExynosDisplay::resetConfigRequestStateLocked(hwc2_config_t config) {
4646     ATRACE_CALL();
4647 
4648     assert(isBadConfig(config) == false);
4649 
4650     mRefreshRate = mDisplayConfigs[config].refreshRate;
4651     mVsyncPeriod = getDisplayVsyncPeriodFromConfig(config);
4652     updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config), true);
4653     DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by config(%d)", mVsyncPeriod, config);
4654 
4655     updateRefreshRateHint();
4656 
4657     if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4658         DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
4659                      mConfigRequestState);
4660     } else {
4661         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to DONE",
4662                      __func__, mConfigRequestState);
4663         mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
4664         updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
4665     }
4666     return NO_ERROR;
4667 }
4668 
updateConfigRequestAppliedTime()4669 int32_t ExynosDisplay::updateConfigRequestAppliedTime()
4670 {
4671     if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4672         DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
4673                      mConfigRequestState);
4674         return NO_ERROR;
4675     }
4676 
4677     /*
4678      * config change was requested but
4679      * it is not applied until newVsyncAppliedTimeNanos
4680      * Update time information
4681      */
4682     int64_t actualChangeTime = 0;
4683     mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
4684     return updateVsyncAppliedTimeLine(actualChangeTime);
4685 }
4686 
updateVsyncAppliedTimeLine(int64_t actualChangeTime)4687 int32_t ExynosDisplay::updateVsyncAppliedTimeLine(int64_t actualChangeTime)
4688 {
4689     ExynosDevice *dev = mDevice;
4690 
4691     DISPLAY_LOGD(eDebugDisplayConfig,"Vsync applied time is changed (%" PRId64 "-> %" PRId64 ")",
4692             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
4693             actualChangeTime);
4694     getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos,
4695             actualChangeTime,
4696             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
4697             mVsyncAppliedTimeLine.refreshTimeNanos);
4698     if (mConfigRequestState ==
4699             hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4700         mVsyncAppliedTimeLine.refreshRequired = false;
4701     } else {
4702         mVsyncAppliedTimeLine.refreshRequired = true;
4703     }
4704 
4705     DISPLAY_LOGD(eDebugDisplayConfig,"refresh required(%d), newVsyncAppliedTimeNanos (%" PRId64 ")",
4706             mVsyncAppliedTimeLine.refreshRequired,
4707             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos);
4708 
4709     dev->onVsyncPeriodTimingChanged(getId(), &mVsyncAppliedTimeLine);
4710 
4711     return NO_ERROR;
4712 }
4713 
getDisplayVsyncPeriodInternal(hwc2_vsync_period_t * outVsyncPeriod)4714 int32_t ExynosDisplay::getDisplayVsyncPeriodInternal(hwc2_vsync_period_t* outVsyncPeriod)
4715 {
4716     /* Getting actual config from DPU */
4717     if (mDisplayInterface->getDisplayVsyncPeriod(outVsyncPeriod) == HWC2_ERROR_NONE) {
4718         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period : %ld",
4719                 (long)*outVsyncPeriod);
4720     } else {
4721         *outVsyncPeriod = mVsyncPeriod;
4722         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period is mVsyncPeriod: %d",
4723                 mVsyncPeriod);
4724     }
4725     return HWC2_ERROR_NONE;
4726 }
4727 
doDisplayConfigInternal(hwc2_config_t config)4728 int32_t ExynosDisplay::doDisplayConfigInternal(hwc2_config_t config) {
4729     return mDisplayInterface->setActiveConfigWithConstraints(config);
4730 }
4731 
doDisplayConfigPostProcess(ExynosDevice * dev)4732 int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
4733 {
4734     ATRACE_CALL();
4735     uint64_t current = systemTime(SYSTEM_TIME_MONOTONIC);
4736 
4737     int64_t actualChangeTime = 0;
4738     mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
4739     bool needSetActiveConfig = false;
4740 
4741     DISPLAY_LOGD(eDebugDisplayConfig,
4742             "Check time for setActiveConfig (curr: %" PRId64
4743             ", actualChangeTime: %" PRId64 ", desiredTime: %" PRId64 "",
4744             current, actualChangeTime,
4745             mVsyncPeriodChangeConstraints.desiredTimeNanos);
4746     if (actualChangeTime >= mVsyncPeriodChangeConstraints.desiredTimeNanos) {
4747         DISPLAY_LOGD(eDebugDisplayConfig, "Request setActiveConfig %d", mDesiredConfig);
4748         needSetActiveConfig = true;
4749         DISPLAY_ATRACE_INT("Pending ActiveConfig", 0);
4750         DISPLAY_ATRACE_INT64("TimeToApplyConfig", 0);
4751     } else {
4752         DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending (mDesiredConfig %d)",
4753                      mDesiredConfig);
4754         DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
4755         DISPLAY_ATRACE_INT64("TimeToApplyConfig",
4756                              ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - current));
4757     }
4758 
4759     if (needSetActiveConfig) {
4760         int32_t ret = NO_ERROR;
4761         if ((ret = doDisplayConfigInternal(mDesiredConfig)) != NO_ERROR) {
4762             return ret;
4763         }
4764 
4765         mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_REQUESTED;
4766     }
4767 
4768     return updateVsyncAppliedTimeLine(actualChangeTime);
4769 }
4770 
setOutputBuffer(buffer_handle_t __unused buffer,int32_t __unused releaseFence)4771 int32_t ExynosDisplay::setOutputBuffer( buffer_handle_t __unused buffer, int32_t __unused releaseFence)
4772 {
4773     return HWC2_ERROR_NONE;
4774 }
4775 
clearDisplay(bool needModeClear)4776 int ExynosDisplay::clearDisplay(bool needModeClear) {
4777 
4778     const int ret = mDisplayInterface->clearDisplay(needModeClear);
4779     if (ret)
4780         DISPLAY_LOGE("fail to clear display");
4781 
4782     mClientCompositionInfo.mSkipStaticInitFlag = false;
4783     mClientCompositionInfo.mSkipFlag = false;
4784 
4785     mLastDpuData.reset();
4786 
4787     /* Update last retire fence */
4788     mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
4789 
4790     if (mBrightnessController) {
4791         mBrightnessController->onClearDisplay(needModeClear);
4792     }
4793     return ret;
4794 }
4795 
setPowerMode(int32_t mode)4796 int32_t ExynosDisplay::setPowerMode(
4797         int32_t /*hwc2_power_mode_t*/ mode) {
4798     Mutex::Autolock lock(mDisplayMutex);
4799 
4800     if (!mDisplayInterface->isDozeModeAvailable() &&
4801         (mode == HWC2_POWER_MODE_DOZE || mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
4802         return HWC2_ERROR_UNSUPPORTED;
4803     }
4804 
4805     if (mode == HWC_POWER_MODE_OFF) {
4806         mDevice->mPrimaryBlank = true;
4807         clearDisplay(true);
4808         ALOGV("HWC2: Clear display (power off)");
4809     } else {
4810         mDevice->mPrimaryBlank = false;
4811     }
4812 
4813     if (mode == HWC_POWER_MODE_OFF)
4814         mDREnable = false;
4815     else
4816         mDREnable = mDRDefault;
4817 
4818     // check the dynamic recomposition thread by following display power status;
4819     mDevice->checkDynamicRecompositionThread();
4820 
4821 
4822     /* TODO: Call display interface */
4823     mDisplayInterface->setPowerMode(mode);
4824 
4825     ALOGD("%s:: mode(%d))", __func__, mode);
4826 
4827     mPowerModeState = (hwc2_power_mode_t)mode;
4828 
4829     if (mode == HWC_POWER_MODE_OFF) {
4830         /* It should be called from validate() when the screen is on */
4831         mSkipFrame = true;
4832         setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
4833         if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
4834             (mRenderingState < RENDERING_STATE_PRESENTED))
4835             closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
4836         mRenderingState = RENDERING_STATE_NONE;
4837     } else {
4838         setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
4839     }
4840 
4841     return HWC2_ERROR_NONE;
4842 }
4843 
setVsyncEnabled(int32_t enabled)4844 int32_t ExynosDisplay::setVsyncEnabled(
4845         int32_t /*hwc2_vsync_t*/ enabled) {
4846     Mutex::Autolock lock(mDisplayMutex);
4847     return setVsyncEnabledInternal(enabled);
4848 }
4849 
setVsyncEnabledInternal(int32_t enabled)4850 int32_t ExynosDisplay::setVsyncEnabledInternal(
4851         int32_t enabled) {
4852 
4853     uint32_t val = 0;
4854 
4855     if (enabled < 0 || enabled > HWC2_VSYNC_DISABLE)
4856         return HWC2_ERROR_BAD_PARAMETER;
4857 
4858 
4859     if (enabled == HWC2_VSYNC_ENABLE) {
4860         gettimeofday(&updateTimeInfo.lastEnableVsyncTime, NULL);
4861         val = 1;
4862         if (mVsyncState != HWC2_VSYNC_ENABLE) {
4863             /* TODO: remove it once driver can handle on its own */
4864             setEarlyWakeupDisplay();
4865         }
4866     } else {
4867         gettimeofday(&updateTimeInfo.lastDisableVsyncTime, NULL);
4868     }
4869 
4870     if (mDisplayInterface->setVsyncEnabled(val) < 0) {
4871         HWC_LOGE(this, "vsync ioctl failed errno : %d", errno);
4872         return HWC2_ERROR_BAD_DISPLAY;
4873     }
4874 
4875     mVsyncState = (hwc2_vsync_t)enabled;
4876 
4877     return HWC2_ERROR_NONE;
4878 }
4879 
validateDisplay(uint32_t * outNumTypes,uint32_t * outNumRequests)4880 int32_t ExynosDisplay::validateDisplay(
4881         uint32_t* outNumTypes, uint32_t* outNumRequests) {
4882     DISPLAY_ATRACE_CALL();
4883     gettimeofday(&updateTimeInfo.lastValidateTime, NULL);
4884     Mutex::Autolock lock(mDisplayMutex);
4885 
4886     if (!mHpdStatus) {
4887         ALOGD("validateDisplay: drop frame: mHpdStatus == false");
4888         return HWC2_ERROR_NONE;
4889     }
4890 
4891     if (mPauseDisplay) return HWC2_ERROR_NONE;
4892 
4893     mDropFrameDuringResSwitch =
4894             (mGeometryChanged & GEOMETRY_DISPLAY_RESOLUTION_CHANGED) && !isFullScreenComposition();
4895     if (mDropFrameDuringResSwitch) {
4896         ALOGD("validateDisplay: drop invalid frame during resolution switch");
4897         *outNumTypes = 0;
4898         *outNumRequests = 0;
4899         return HWC2_ERROR_NONE;
4900     }
4901 
4902     int ret = NO_ERROR;
4903     bool validateError = false;
4904     mUpdateEventCnt++;
4905     mUpdateCallCnt++;
4906     mLastUpdateTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
4907 
4908     if (usePowerHintSession()) {
4909         mValidateStartTime = mLastUpdateTimeStamp;
4910         mExpectedPresentTime = getExpectedPresentTime(*mValidateStartTime);
4911         auto target =
4912                 min(mExpectedPresentTime - *mValidateStartTime, static_cast<nsecs_t>(mVsyncPeriod));
4913         mPowerHalHint.signalTargetWorkDuration(target);
4914         std::optional<nsecs_t> predictedDuration = getPredictedDuration(true);
4915         if (predictedDuration.has_value()) {
4916             mPowerHalHint.signalActualWorkDuration(*predictedDuration);
4917         }
4918     }
4919 
4920     checkIgnoreLayers();
4921     if (mLayers.size() == 0)
4922         DISPLAY_LOGI("%s:: validateDisplay layer size is 0", __func__);
4923     else
4924         mLayers.vector_sort();
4925 
4926     for (size_t i = 0; i < mLayers.size(); i++) mLayers[i]->setSrcAcquireFence();
4927 
4928     tryUpdateBtsFromOperationRate(true);
4929     doPreProcessing();
4930     checkLayerFps();
4931     if (exynosHWCControl.useDynamicRecomp == true && mDREnable) {
4932         checkDynamicReCompMode();
4933         if (mDevice->isDynamicRecompositionThreadAlive() == false &&
4934             mDevice->mDRLoopStatus == false)
4935             mDevice->dynamicRecompositionThreadCreate();
4936     }
4937 
4938     if ((ret = mResourceManager->assignResource(this)) != NO_ERROR) {
4939         validateError = true;
4940         HWC_LOGE(this, "%s:: assignResource() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4941         String8 errString;
4942         errString.appendFormat("%s:: assignResource() fail, display(%d), ret(%d)\n",
4943                 __func__, mDisplayId, ret);
4944         printDebugInfos(errString);
4945         mDisplayInterface->setForcePanic();
4946     }
4947 
4948     if ((ret = skipStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
4949         validateError = true;
4950         HWC_LOGE(this, "%s:: skipStaticLayers() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4951     } else {
4952         if ((mClientCompositionInfo.mHasCompositionLayer) &&
4953             (mClientCompositionInfo.mSkipFlag == false)) {
4954             /* Initialize compositionType */
4955             for (size_t i = (size_t)mClientCompositionInfo.mFirstIndex; i <= (size_t)mClientCompositionInfo.mLastIndex; i++) {
4956                 if (mLayers[i]->mOverlayPriority >= ePriorityHigh)
4957                     continue;
4958                 mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4959             }
4960         }
4961     }
4962 
4963     mRenderingState = RENDERING_STATE_VALIDATED;
4964 
4965     /*
4966      * HWC should update performanceInfo even if assignResource is skipped
4967      * HWC excludes the layer from performance calculation
4968      * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
4969      * Therefore performanceInfo should be calculated again if only the buffer is updated.
4970      */
4971     if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
4972         HWC_LOGE(NULL,"%s:: deliverPerformanceInfo() error (%d)",
4973                 __func__, ret);
4974     }
4975 
4976     if ((validateError == false) && (mDisplayControl.earlyStartMPP == true)) {
4977         if ((ret = startPostProcessing()) != NO_ERROR)
4978             validateError = true;
4979     }
4980 
4981     if (validateError) {
4982         setGeometryChanged(GEOMETRY_ERROR_CASE);
4983         mClientCompositionInfo.mSkipStaticInitFlag = false;
4984         mExynosCompositionInfo.mSkipStaticInitFlag = false;
4985         mResourceManager->resetAssignedResources(this, true);
4986         mClientCompositionInfo.initializeInfos(this);
4987         mExynosCompositionInfo.initializeInfos(this);
4988         for (uint32_t i = 0; i < mLayers.size(); i++) {
4989             ExynosLayer *layer = mLayers[i];
4990             layer->mOverlayInfo |= eResourceAssignFail;
4991             layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
4992             addClientCompositionLayer(i);
4993         }
4994         mResourceManager->assignCompositionTarget(this, COMPOSITION_CLIENT);
4995         mResourceManager->assignWindow(this);
4996     }
4997 
4998     resetColorMappingInfoForClientComp();
4999     storePrevValidateCompositionType();
5000 
5001     int32_t displayRequests = 0;
5002     if ((ret = getChangedCompositionTypes(outNumTypes, NULL, NULL)) != NO_ERROR) {
5003         HWC_LOGE(this, "%s:: getChangedCompositionTypes() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
5004         setGeometryChanged(GEOMETRY_ERROR_CASE);
5005     }
5006     if ((ret = getDisplayRequests(&displayRequests, outNumRequests, NULL, NULL)) != NO_ERROR) {
5007         HWC_LOGE(this, "%s:: getDisplayRequests() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
5008         setGeometryChanged(GEOMETRY_ERROR_CASE);
5009     }
5010 
5011     mSkipFrame = false;
5012 
5013     if ((*outNumTypes == 0) && (*outNumRequests == 0))
5014         return HWC2_ERROR_NONE;
5015 
5016     if (usePowerHintSession()) {
5017         mValidationDuration = systemTime(SYSTEM_TIME_MONOTONIC) - *mValidateStartTime;
5018     }
5019 
5020     return HWC2_ERROR_HAS_CHANGES;
5021 }
5022 
startPostProcessing()5023 int32_t ExynosDisplay::startPostProcessing()
5024 {
5025     ATRACE_CALL();
5026     int ret = NO_ERROR;
5027     String8 errString;
5028 
5029     float assignedCapacity = mResourceManager->getAssignedCapacity(MPP_G2D);
5030 
5031     if (assignedCapacity > (mResourceManager->getM2MCapa(MPP_G2D) * MPP_CAPA_OVER_THRESHOLD)) {
5032         errString.appendFormat("Assigned capacity for exynos composition is over restriction (%f)",
5033                 assignedCapacity);
5034         goto err;
5035     }
5036 
5037     if ((ret = doExynosComposition()) != NO_ERROR) {
5038         errString.appendFormat("exynosComposition fail (%d)\n", ret);
5039         goto err;
5040     }
5041 
5042     // loop for all layer
5043     for (size_t i=0; i < mLayers.size(); i++) {
5044         if((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
5045            (mLayers[i]->mM2mMPP != NULL)) {
5046             /* mAcquireFence is updated, Update image info */
5047             struct exynos_image srcImg, dstImg, midImg;
5048             mLayers[i]->setSrcExynosImage(&srcImg);
5049             mLayers[i]->setDstExynosImage(&dstImg);
5050             mLayers[i]->setExynosImage(srcImg, dstImg);
5051             ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
5052             midImg = mLayers[i]->mMidImg;
5053             m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
5054             if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
5055                 DISPLAY_LOGE("%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
5056                         __func__, i, ret);
5057                 errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
5058                         __func__, i, ret);
5059                 goto err;
5060             } else {
5061                 /* This should be closed by lib for each resource */
5062                 mLayers[i]->mAcquireFence = -1;
5063             }
5064         }
5065     }
5066     return ret;
5067 err:
5068     printDebugInfos(errString);
5069     closeFences();
5070     mDisplayInterface->setForcePanic();
5071     return -EINVAL;
5072 }
5073 
setCursorPositionAsync(uint32_t x_pos,uint32_t y_pos)5074 int32_t ExynosDisplay::setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos) {
5075     mDisplayInterface->setCursorPositionAsync(x_pos, y_pos);
5076     return HWC2_ERROR_NONE;
5077 }
5078 
5079 // clang-format off
dumpConfig(const exynos_win_config_data & c)5080 void ExynosDisplay::dumpConfig(const exynos_win_config_data &c)
5081 {
5082     DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\tstate = %u", c.state);
5083     if (c.state == c.WIN_STATE_COLOR) {
5084         DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer,
5085                 "\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5086                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5087     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5088         DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5089                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5090                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5091                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5092                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5093                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)",
5094                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5095                 c.acq_fence, c.rel_fence,
5096                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5097                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5098                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable,
5099                 c.blending, c.protection, getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5100                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5101                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5102                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5103     }
5104 }
5105 
dump(String8 & result)5106 void ExynosDisplay::dump(String8& result) {
5107     Mutex::Autolock lock(mDisplayMutex);
5108     dumpLocked(result);
5109 }
5110 
dumpLocked(String8 & result)5111 void ExynosDisplay::dumpLocked(String8& result) {
5112     result.appendFormat("[%s] display information size: %d x %d, vsyncState: %d, colorMode: %d, "
5113                         "colorTransformHint: %d, orientation %d\n",
5114                         mDisplayName.c_str(), mXres, mYres, mVsyncState, mColorMode,
5115                         mColorTransformHint, mMountOrientation);
5116     mClientCompositionInfo.dump(result);
5117     mExynosCompositionInfo.dump(result);
5118 
5119     result.appendFormat("PanelGammaSource (%d)\n\n", GetCurrentPanelGammaSource());
5120 
5121     {
5122         Mutex::Autolock lock(mDRMutex);
5123         if (mLayers.size()) {
5124             result.appendFormat("============================== dump layers ===========================================\n");
5125             for (uint32_t i = 0; i < mLayers.size(); i++) {
5126                 ExynosLayer *layer = mLayers[i];
5127                 layer->dump(result);
5128             }
5129         }
5130         if (mIgnoreLayers.size()) {
5131             result.appendFormat("\n============================== dump ignore layers ===========================================\n");
5132             for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
5133                 ExynosLayer *layer = mIgnoreLayers[i];
5134                 layer->dump(result);
5135             }
5136         }
5137     }
5138     result.appendFormat("\n");
5139     if (mBrightnessController) {
5140         mBrightnessController->dump(result);
5141     }
5142     if (mHistogramController) {
5143         mHistogramController->dump(result);
5144     }
5145     if (mDisplayTe2Manager) {
5146         mDisplayTe2Manager->dump(result);
5147     }
5148 }
5149 
dumpConfig(String8 & result,const exynos_win_config_data & c)5150 void ExynosDisplay::dumpConfig(String8 &result, const exynos_win_config_data &c)
5151 {
5152     result.appendFormat("\tstate = %u\n", c.state);
5153     if (c.state == c.WIN_STATE_COLOR) {
5154         result.appendFormat("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5155                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5156     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5157         result.appendFormat("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5158                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5159                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5160                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5161                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5162                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)\n",
5163                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5164                 c.acq_fence, c.rel_fence,
5165                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5166                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5167                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
5168                 getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5169                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5170                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5171                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5172     }
5173 }
5174 
printConfig(exynos_win_config_data & c)5175 void ExynosDisplay::printConfig(exynos_win_config_data &c)
5176 {
5177     ALOGD("\tstate = %u", c.state);
5178     if (c.state == c.WIN_STATE_COLOR) {
5179         ALOGD("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5180                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5181     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5182         ALOGD("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5183                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5184                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5185                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5186                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5187                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)",
5188                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5189                 c.acq_fence, c.rel_fence,
5190                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5191                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5192                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
5193                 getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5194                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5195                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5196                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5197     }
5198 }
5199 // clang-format on
5200 
setCompositionTargetExynosImage(uint32_t targetType,exynos_image * src_img,exynos_image * dst_img)5201 int32_t ExynosDisplay::setCompositionTargetExynosImage(uint32_t targetType, exynos_image *src_img, exynos_image *dst_img)
5202 {
5203     if (targetType != COMPOSITION_CLIENT && targetType != COMPOSITION_EXYNOS) {
5204         return -EINVAL;
5205     }
5206     const ExynosCompositionInfo& compositionInfo =
5207             (targetType == COMPOSITION_CLIENT) ? mClientCompositionInfo : mExynosCompositionInfo;
5208 
5209     src_img->fullWidth = mXres;
5210     src_img->fullHeight = mYres;
5211     /* To do */
5212     /* Fb crop should be set hear */
5213     src_img->x = 0;
5214     src_img->y = 0;
5215     src_img->w = mXres;
5216     src_img->h = mYres;
5217 
5218     if (compositionInfo.mTargetBuffer != NULL) {
5219         src_img->bufferHandle = compositionInfo.mTargetBuffer;
5220 
5221         VendorGraphicBufferMeta gmeta(compositionInfo.mTargetBuffer);
5222         src_img->format = gmeta.format;
5223         src_img->usageFlags = gmeta.producer_usage;
5224     } else {
5225         src_img->bufferHandle = NULL;
5226         src_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
5227         src_img->usageFlags = 0;
5228     }
5229     src_img->layerFlags = 0x0;
5230     src_img->acquireFenceFd = compositionInfo.mAcquireFence;
5231     src_img->releaseFenceFd = -1;
5232     src_img->dataSpace = compositionInfo.mDataSpace;
5233     src_img->blending = HWC2_BLEND_MODE_PREMULTIPLIED;
5234     src_img->transform = 0;
5235     src_img->compressionInfo = compositionInfo.mCompressionInfo;
5236     src_img->planeAlpha = 1;
5237     src_img->zOrder = 0;
5238     if ((targetType == COMPOSITION_CLIENT) && (mType == HWC_DISPLAY_VIRTUAL)) {
5239         if (compositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)
5240             src_img->zOrder = 0;
5241         else
5242             src_img->zOrder = 1000;
5243     }
5244     src_img->needPreblending = compositionInfo.mNeedPreblending;
5245 
5246     dst_img->fullWidth = mXres;
5247     dst_img->fullHeight = mYres;
5248     /* To do */
5249     /* Fb crop should be set hear */
5250     dst_img->x = 0;
5251     dst_img->y = 0;
5252     dst_img->w = mXres;
5253     dst_img->h = mYres;
5254 
5255     dst_img->bufferHandle = NULL;
5256     dst_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
5257     dst_img->usageFlags = 0;
5258 
5259     dst_img->layerFlags = 0x0;
5260     dst_img->acquireFenceFd = -1;
5261     dst_img->releaseFenceFd = -1;
5262     dst_img->dataSpace = src_img->dataSpace;
5263     if (mColorMode != HAL_COLOR_MODE_NATIVE)
5264         dst_img->dataSpace = colorModeToDataspace(mColorMode);
5265     dst_img->blending = HWC2_BLEND_MODE_NONE;
5266     dst_img->transform = 0;
5267     dst_img->compressionInfo = compositionInfo.mCompressionInfo;
5268     dst_img->planeAlpha = 1;
5269     dst_img->zOrder = src_img->zOrder;
5270 
5271     return NO_ERROR;
5272 }
5273 
initializeValidateInfos()5274 int32_t ExynosDisplay::initializeValidateInfos()
5275 {
5276     mCursorIndex = -1;
5277     for (uint32_t i = 0; i < mLayers.size(); i++) {
5278         ExynosLayer *layer = mLayers[i];
5279         layer->mValidateCompositionType = HWC2_COMPOSITION_INVALID;
5280         layer->mOverlayInfo = 0;
5281         if ((mDisplayControl.cursorSupport == true) &&
5282             (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CURSOR))
5283             mCursorIndex = i;
5284     }
5285 
5286     exynos_image src_img;
5287     exynos_image dst_img;
5288 
5289     mClientCompositionInfo.initializeInfos(this);
5290     setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
5291     mClientCompositionInfo.setExynosImage(src_img, dst_img);
5292 
5293     mExynosCompositionInfo.initializeInfos(this);
5294     setCompositionTargetExynosImage(COMPOSITION_EXYNOS, &src_img, &dst_img);
5295     mExynosCompositionInfo.setExynosImage(src_img, dst_img);
5296 
5297     return NO_ERROR;
5298 }
5299 
addClientCompositionLayer(uint32_t layerIndex)5300 int32_t ExynosDisplay::addClientCompositionLayer(uint32_t layerIndex)
5301 {
5302     bool exynosCompositionChanged = false;
5303     int32_t ret = NO_ERROR;
5304 
5305     DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to client composition", layerIndex);
5306 
5307     if (mClientCompositionInfo.mHasCompositionLayer == false) {
5308         mClientCompositionInfo.mFirstIndex = layerIndex;
5309         mClientCompositionInfo.mLastIndex = layerIndex;
5310         mClientCompositionInfo.mHasCompositionLayer = true;
5311         return EXYNOS_ERROR_CHANGED;
5312     } else {
5313         mClientCompositionInfo.mFirstIndex = min(mClientCompositionInfo.mFirstIndex, (int32_t)layerIndex);
5314         mClientCompositionInfo.mLastIndex = max(mClientCompositionInfo.mLastIndex, (int32_t)layerIndex);
5315     }
5316     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5317             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5318 
5319     if ((mClientCompositionInfo.mFirstIndex < 0) || (mClientCompositionInfo.mLastIndex < 0))
5320     {
5321         HWC_LOGE(this, "%s:: mClientCompositionInfo.mHasCompositionLayer is true "
5322                 "but index is not valid (firstIndex: %d, lastIndex: %d)",
5323                 __func__, mClientCompositionInfo.mFirstIndex,
5324                 mClientCompositionInfo.mLastIndex);
5325         return -EINVAL;
5326     }
5327 
5328     /* handle sandwiched layers */
5329     for (uint32_t i = (uint32_t)mClientCompositionInfo.mFirstIndex + 1; i < (uint32_t)mClientCompositionInfo.mLastIndex; i++) {
5330         ExynosLayer *layer = mLayers[i];
5331         if (layer->needClearClientTarget()) {
5332             DISPLAY_LOGD(eDebugResourceManager,
5333                          "\t[%d] layer is opaque and has high or max priority (%d)", i,
5334                          layer->mOverlayPriority);
5335             continue;
5336         }
5337         if (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT)
5338         {
5339             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
5340             if (layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS)
5341                 exynosCompositionChanged = true;
5342             else {
5343                 if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
5344             }
5345             layer->resetAssignedResource();
5346             layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5347             layer->mOverlayInfo |= eSandwitchedBetweenGLES;
5348         }
5349     }
5350 
5351     /* Check Exynos Composition info is changed */
5352     if (exynosCompositionChanged) {
5353         DISPLAY_LOGD(eDebugResourceManager, "exynos composition [%d] - [%d] is changed",
5354                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5355         uint32_t newFirstIndex = ~0;
5356         int32_t newLastIndex = -1;
5357 
5358         if ((mExynosCompositionInfo.mFirstIndex < 0) || (mExynosCompositionInfo.mLastIndex < 0))
5359         {
5360             HWC_LOGE(this, "%s:: mExynosCompositionInfo.mHasCompositionLayer should be true(%d) "
5361                     "but index is not valid (firstIndex: %d, lastIndex: %d)",
5362                     __func__, mExynosCompositionInfo.mHasCompositionLayer,
5363                     mExynosCompositionInfo.mFirstIndex,
5364                     mExynosCompositionInfo.mLastIndex);
5365             return -EINVAL;
5366         }
5367 
5368         for (uint32_t i = 0; i < mLayers.size(); i++)
5369         {
5370             ExynosLayer *exynosLayer = mLayers[i];
5371             if (exynosLayer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) {
5372                 newFirstIndex = min(newFirstIndex, i);
5373                 newLastIndex = max(newLastIndex, (int32_t)i);
5374             }
5375         }
5376 
5377         DISPLAY_LOGD(eDebugResourceManager, "changed exynos composition [%d] - [%d]",
5378                 newFirstIndex, newLastIndex);
5379 
5380         /* There is no exynos composition layer */
5381         if (newFirstIndex == (uint32_t)~0)
5382         {
5383             mExynosCompositionInfo.initializeInfos(this);
5384             ret = EXYNOS_ERROR_CHANGED;
5385         } else {
5386             mExynosCompositionInfo.mFirstIndex = newFirstIndex;
5387             mExynosCompositionInfo.mLastIndex = newLastIndex;
5388         }
5389     }
5390 
5391     DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", ret);
5392     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
5393             mClientCompositionInfo.mHasCompositionLayer,
5394             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5395     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition(%d) range [%d] - [%d]",
5396             mExynosCompositionInfo.mHasCompositionLayer,
5397             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5398 
5399     return ret;
5400 }
removeClientCompositionLayer(uint32_t layerIndex)5401 int32_t ExynosDisplay::removeClientCompositionLayer(uint32_t layerIndex)
5402 {
5403     int32_t ret = NO_ERROR;
5404 
5405     DISPLAY_LOGD(eDebugResourceManager, "[%d] - [%d] [%d] layer is removed from client composition",
5406             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
5407             layerIndex);
5408 
5409     /* Only first layer or last layer can be removed */
5410     if ((mClientCompositionInfo.mHasCompositionLayer == false) ||
5411         ((mClientCompositionInfo.mFirstIndex != (int32_t)layerIndex) &&
5412          (mClientCompositionInfo.mLastIndex != (int32_t)layerIndex))) {
5413         DISPLAY_LOGE("removeClientCompositionLayer() error, [%d] - [%d], layer[%d]",
5414                 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
5415                 layerIndex);
5416         return -EINVAL;
5417     }
5418 
5419     if (mClientCompositionInfo.mFirstIndex == mClientCompositionInfo.mLastIndex) {
5420         ExynosMPP *otfMPP = mClientCompositionInfo.mOtfMPP;
5421         if (otfMPP != NULL)
5422             otfMPP->resetAssignedState();
5423         else {
5424             DISPLAY_LOGE("mClientCompositionInfo.mOtfMPP is NULL");
5425             return -EINVAL;
5426         }
5427         mClientCompositionInfo.initializeInfos(this);
5428         mWindowNumUsed--;
5429     } else if ((int32_t)layerIndex == mClientCompositionInfo.mFirstIndex)
5430         mClientCompositionInfo.mFirstIndex++;
5431     else
5432         mClientCompositionInfo.mLastIndex--;
5433 
5434     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
5435             mClientCompositionInfo.mHasCompositionLayer,
5436             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5437 
5438     return ret;
5439 }
5440 
hasClientComposition()5441 bool ExynosDisplay::hasClientComposition() {
5442     return mClientCompositionInfo.mHasCompositionLayer;
5443 }
5444 
addExynosCompositionLayer(uint32_t layerIndex,float totalUsedCapa)5445 int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex, float totalUsedCapa) {
5446     bool invalidFlag = false;
5447     int32_t changeFlag = NO_ERROR;
5448     int ret = 0;
5449     int32_t startIndex;
5450     int32_t endIndex;
5451 
5452     DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to exynos composition", layerIndex);
5453 
5454     if (mExynosCompositionInfo.mHasCompositionLayer == false) {
5455         mExynosCompositionInfo.mFirstIndex = layerIndex;
5456         mExynosCompositionInfo.mLastIndex = layerIndex;
5457         mExynosCompositionInfo.mHasCompositionLayer = true;
5458         return EXYNOS_ERROR_CHANGED;
5459     } else {
5460         mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)layerIndex);
5461         mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)layerIndex);
5462     }
5463 
5464     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
5465             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5466 
5467     ExynosMPP *m2mMPP = mExynosCompositionInfo.mM2mMPP;
5468 
5469     if (m2mMPP == NULL) {
5470         DISPLAY_LOGE("exynosComposition m2mMPP is NULL");
5471         return -EINVAL;
5472     }
5473 
5474     startIndex = mExynosCompositionInfo.mFirstIndex;
5475     endIndex = mExynosCompositionInfo.mLastIndex;
5476 
5477     if ((startIndex < 0) || (endIndex < 0) ||
5478         (startIndex >= (int32_t)mLayers.size()) || (endIndex >= (int32_t)mLayers.size())) {
5479         DISPLAY_LOGE("exynosComposition invalid index (%d), (%d)", startIndex, endIndex);
5480         return -EINVAL;
5481     }
5482 
5483     int32_t maxPriorityIndex = -1;
5484 
5485     uint32_t highPriorityIndex = 0;
5486     uint32_t highPriorityNum = 0;
5487     int32_t highPriorityCheck = 0;
5488     std::vector<int32_t> highPriority;
5489     highPriority.assign(mLayers.size(), -1);
5490     /* handle sandwiched layers */
5491     for (int32_t i = startIndex; i <= endIndex; i++) {
5492         ExynosLayer *layer = mLayers[i];
5493         if (layer == NULL) {
5494             DISPLAY_LOGE("layer[%d] layer is null", i);
5495             continue;
5496         }
5497 
5498         if (layer->mOverlayPriority == ePriorityMax &&
5499                 m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO) {
5500             DISPLAY_LOGD(eDebugResourceManager, "\tG2D will be assgined for only [%d] layer", i);
5501             invalidFlag = true;
5502             maxPriorityIndex = i;
5503             continue;
5504         }
5505 
5506         if (layer->mOverlayPriority >= ePriorityHigh)
5507         {
5508             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high priority", i);
5509             highPriority[highPriorityIndex++] = i;
5510             highPriorityNum++;
5511             continue;
5512         }
5513 
5514         if (layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS)
5515             continue;
5516 
5517         exynos_image src_img;
5518         exynos_image dst_img;
5519         layer->setSrcExynosImage(&src_img);
5520         layer->setDstExynosImage(&dst_img);
5521         layer->setExynosMidImage(dst_img);
5522         bool isAssignable = false;
5523         if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
5524             isAssignable = m2mMPP->isAssignable(this, src_img, dst_img, totalUsedCapa);
5525 
5526         if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
5527         {
5528             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is client composition", i);
5529             invalidFlag = true;
5530         } else if (((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) == 0) ||
5531                    (isAssignable == false))
5532         {
5533             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is not supported by G2D", i);
5534             invalidFlag = true;
5535             layer->resetAssignedResource();
5536             layer->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5537             if ((ret = addClientCompositionLayer(i)) < 0)
5538                 return ret;
5539             changeFlag |= ret;
5540         } else if ((layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) ||
5541                    (layer->mValidateCompositionType == HWC2_COMPOSITION_INVALID)) {
5542             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
5543             layer->mOverlayInfo |= eSandwitchedBetweenEXYNOS;
5544             layer->resetAssignedResource();
5545             if ((ret = m2mMPP->assignMPP(this, layer)) != NO_ERROR)
5546             {
5547                 HWC_LOGE(this, "%s:: %s MPP assignMPP() error (%d)",
5548                         __func__, m2mMPP->mName.c_str(), ret);
5549                 return ret;
5550             }
5551             if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
5552             layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
5553             mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)i);
5554             mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)i);
5555         } else {
5556             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has known type (%d)", i,
5557                          layer->mValidateCompositionType);
5558         }
5559     }
5560 
5561     if (invalidFlag) {
5562         DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5563                 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5564         DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d], highPriorityNum[%d]",
5565                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, highPriorityNum);
5566 
5567         if (m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO && maxPriorityIndex >= 0) {
5568             startIndex = mExynosCompositionInfo.mFirstIndex;
5569             endIndex = mExynosCompositionInfo.mLastIndex;
5570 
5571             for (int32_t i = startIndex; i <= endIndex; i++) {
5572                 if (mLayers[i]->mOverlayPriority == ePriorityMax ||
5573                         mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
5574                     continue;
5575                 mLayers[i]->resetAssignedResource();
5576                 mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5577                 if ((ret = addClientCompositionLayer(i)) < 0)
5578                     return ret;
5579                 changeFlag |= ret;
5580             }
5581 
5582             if (mLayers[maxPriorityIndex]->mValidateCompositionType
5583                     != HWC2_COMPOSITION_EXYNOS) {
5584                 mLayers[maxPriorityIndex]->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
5585                 mLayers[maxPriorityIndex]->resetAssignedResource();
5586                 if ((ret = m2mMPP->assignMPP(this, mLayers[maxPriorityIndex])) != NO_ERROR)
5587                 {
5588                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
5589                             __func__, m2mMPP->mName.c_str(), ret);
5590                     return ret;
5591                 }
5592             }
5593 
5594             mExynosCompositionInfo.mFirstIndex = maxPriorityIndex;
5595             mExynosCompositionInfo.mLastIndex = maxPriorityIndex;
5596         }
5597 
5598         /* Check if exynos comosition nests GLES composition */
5599         if ((mClientCompositionInfo.mHasCompositionLayer) &&
5600             (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mFirstIndex) &&
5601             (mClientCompositionInfo.mFirstIndex < mExynosCompositionInfo.mLastIndex) &&
5602             (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mLastIndex) &&
5603             (mClientCompositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)) {
5604 
5605             if ((mClientCompositionInfo.mFirstIndex - mExynosCompositionInfo.mFirstIndex) <
5606                 (mExynosCompositionInfo.mLastIndex - mClientCompositionInfo.mLastIndex)) {
5607                 mLayers[mExynosCompositionInfo.mFirstIndex]->resetAssignedResource();
5608                 mLayers[mExynosCompositionInfo.mFirstIndex]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5609                 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mFirstIndex)) < 0)
5610                     return ret;
5611                 mExynosCompositionInfo.mFirstIndex = mClientCompositionInfo.mLastIndex + 1;
5612                 changeFlag |= ret;
5613             } else {
5614                 mLayers[mExynosCompositionInfo.mLastIndex]->resetAssignedResource();
5615                 mLayers[mExynosCompositionInfo.mLastIndex]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5616                 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mLastIndex)) < 0)
5617                     return ret;
5618                 mExynosCompositionInfo.mLastIndex = (mClientCompositionInfo.mFirstIndex - 1);
5619                 changeFlag |= ret;
5620             }
5621         }
5622     }
5623 
5624     if (highPriorityNum > 0 && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
5625         for (uint32_t i = 0; i < highPriorityNum; i++) {
5626             if ((int32_t)highPriority[i] == mExynosCompositionInfo.mFirstIndex)
5627                 mExynosCompositionInfo.mFirstIndex++;
5628             else if ((int32_t)highPriority[i] == mExynosCompositionInfo.mLastIndex)
5629                 mExynosCompositionInfo.mLastIndex--;
5630         }
5631     }
5632 
5633     if ((mExynosCompositionInfo.mFirstIndex < 0) ||
5634         (mExynosCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
5635         (mExynosCompositionInfo.mLastIndex < 0) ||
5636         (mExynosCompositionInfo.mLastIndex >= (int)mLayers.size()) ||
5637         (mExynosCompositionInfo.mFirstIndex > mExynosCompositionInfo.mLastIndex))
5638     {
5639         DISPLAY_LOGD(eDebugResourceManager, "\texynos composition is disabled, because of invalid index (%d, %d), size(%zu)",
5640                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, mLayers.size());
5641         mExynosCompositionInfo.initializeInfos(this);
5642         changeFlag = EXYNOS_ERROR_CHANGED;
5643     }
5644 
5645     for (uint32_t i = 0; i < highPriorityNum; i++) {
5646         if ((mExynosCompositionInfo.mFirstIndex < (int32_t)highPriority[i]) &&
5647             ((int32_t)highPriority[i] < mExynosCompositionInfo.mLastIndex)) {
5648             highPriorityCheck = 1;
5649             break;
5650         }
5651     }
5652 
5653 
5654     if (highPriorityCheck && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
5655         startIndex = mExynosCompositionInfo.mFirstIndex;
5656         endIndex = mExynosCompositionInfo.mLastIndex;
5657         DISPLAY_LOGD(eDebugResourceManager, "\texynos composition is disabled because of sandwitched max priority layer (%d, %d)",
5658                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5659         for (int32_t i = startIndex; i <= endIndex; i++) {
5660             int32_t checkPri = 0;
5661             for (uint32_t j = 0; j < highPriorityNum; j++) {
5662                 if (i == (int32_t)highPriority[j]) {
5663                     checkPri = 1;
5664                     break;
5665                 }
5666             }
5667 
5668             if (checkPri)
5669                 continue;
5670 
5671             mLayers[i]->resetAssignedResource();
5672             mLayers[i]->mValidateCompositionType = HWC2_COMPOSITION_CLIENT;
5673             if ((ret = addClientCompositionLayer(i)) < 0)
5674                 HWC_LOGE(this, "%d layer: addClientCompositionLayer() fail", i);
5675         }
5676         mExynosCompositionInfo.initializeInfos(this);
5677         changeFlag = EXYNOS_ERROR_CHANGED;
5678     }
5679 
5680     DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", changeFlag);
5681     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5682             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5683     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
5684             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5685 
5686     return changeFlag;
5687 }
5688 
isPowerModeOff() const5689 bool ExynosDisplay::isPowerModeOff() const {
5690     ATRACE_CALL();
5691     Mutex::Autolock lock(mDisplayMutex);
5692     return mPowerModeState.has_value() && mPowerModeState.value() == HWC2_POWER_MODE_OFF;
5693 }
5694 
isSecureContentPresenting() const5695 bool ExynosDisplay::isSecureContentPresenting() const {
5696     ATRACE_CALL();
5697     Mutex::Autolock lock(mDRMutex);
5698     for (uint32_t i = 0; i < mLayers.size(); i++) {
5699         ExynosLayer *layer = mLayers[i];
5700         if (layer != NULL && layer->isDrm()) { /* there is some DRM layer */
5701             return true;
5702         }
5703     }
5704     return false;
5705 }
5706 
windowUpdateExceptions()5707 bool ExynosDisplay::windowUpdateExceptions()
5708 {
5709 
5710     if (mExynosCompositionInfo.mHasCompositionLayer) {
5711         DISPLAY_LOGD(eDebugWindowUpdate, "has exynos composition");
5712         return true;
5713     }
5714     if (mClientCompositionInfo.mHasCompositionLayer) {
5715         DISPLAY_LOGD(eDebugWindowUpdate, "has client composition");
5716         return true;
5717     }
5718 
5719     for (size_t i = 0; i < mLayers.size(); i++) {
5720         if (mLayers[i]->mM2mMPP != NULL) return true;
5721         if (mLayers[i]->mLayerBuffer == NULL) return true;
5722         if (mLayers[i]->mTransform != 0) return true;
5723     }
5724 
5725     for (size_t i = 0; i < mDpuData.configs.size(); i++) {
5726         exynos_win_config_data &config = mDpuData.configs[i];
5727         if (config.state == config.WIN_STATE_BUFFER) {
5728             if (config.src.w/config.dst.w != 1 || config.src.h/config.dst.h != 1) {
5729                 DISPLAY_LOGD(eDebugWindowUpdate, "Skip reason : scaled");
5730                 return true;
5731             }
5732         }
5733     }
5734 
5735     return false;
5736 }
5737 
handleWindowUpdate()5738 int ExynosDisplay::handleWindowUpdate()
5739 {
5740     int ret = NO_ERROR;
5741     // TODO will be implemented
5742     unsigned int excp;
5743 
5744     mDpuData.enable_win_update = false;
5745     /* Init with full size */
5746     mDpuData.win_update_region.x = 0;
5747     mDpuData.win_update_region.w = mXres;
5748     mDpuData.win_update_region.y = 0;
5749     mDpuData.win_update_region.h = mYres;
5750 
5751     if (exynosHWCControl.windowUpdate != 1) return 0;
5752 
5753     if (mGeometryChanged != 0) {
5754         DISPLAY_LOGD(eDebugWindowUpdate, "GEOMETRY chnaged 0x%"  PRIx64 "",
5755                 mGeometryChanged);
5756         return 0;
5757     }
5758 
5759     if ((mCursorIndex >= 0) && (mCursorIndex < (int32_t)mLayers.size())) {
5760         ExynosLayer *layer = mLayers[mCursorIndex];
5761         /* Cursor layer is enabled */
5762         if (layer->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) {
5763             return 0;
5764         }
5765     }
5766 
5767     /* exceptions */
5768     if (windowUpdateExceptions())
5769         return 0;
5770 
5771     hwc_rect mergedRect = {(int)mXres, (int)mYres, 0, 0};
5772     hwc_rect damageRect = {(int)mXres, (int)mYres, 0, 0};
5773 
5774     for (size_t i = 0; i < mLayers.size(); i++) {
5775         if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION) {
5776             continue;
5777         }
5778         excp = getLayerRegion(mLayers[i], &damageRect, eDamageRegionByDamage);
5779         if (excp == eDamageRegionPartial) {
5780             DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) partial : %d, %d, %d, %d", i,
5781                     damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
5782             mergedRect = expand(mergedRect, damageRect);
5783         }
5784         else if (excp == eDamageRegionSkip) {
5785             int32_t windowIndex = mLayers[i]->mWindowIndex;
5786             if ((ret = checkConfigDstChanged(mDpuData, mLastDpuData, windowIndex)) < 0) {
5787                 return 0;
5788             } else if (ret > 0) {
5789                 damageRect.left = mLayers[i]->mDisplayFrame.left;
5790                 damageRect.right = mLayers[i]->mDisplayFrame.right;
5791                 damageRect.top = mLayers[i]->mDisplayFrame.top;
5792                 damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
5793                 DISPLAY_LOGD(eDebugWindowUpdate, "Skip layer (origin) : %d, %d, %d, %d",
5794                         damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
5795                 mergedRect = expand(mergedRect, damageRect);
5796                 hwc_rect prevDst = {mLastDpuData.configs[i].dst.x, mLastDpuData.configs[i].dst.y,
5797                     mLastDpuData.configs[i].dst.x + (int)mLastDpuData.configs[i].dst.w,
5798                     mLastDpuData.configs[i].dst.y + (int)mLastDpuData.configs[i].dst.h};
5799                 mergedRect = expand(mergedRect, prevDst);
5800             } else {
5801                 DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) skip", i);
5802                 continue;
5803             }
5804         }
5805         else if (excp == eDamageRegionFull) {
5806             damageRect.left = mLayers[i]->mDisplayFrame.left;
5807             damageRect.top = mLayers[i]->mDisplayFrame.top;
5808             damageRect.right = mLayers[i]->mDisplayFrame.right;
5809             damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
5810             DISPLAY_LOGD(eDebugWindowUpdate, "Full layer update : %d, %d, %d, %d", mLayers[i]->mDisplayFrame.left,
5811                     mLayers[i]->mDisplayFrame.top, mLayers[i]->mDisplayFrame.right, mLayers[i]->mDisplayFrame.bottom);
5812             mergedRect = expand(mergedRect, damageRect);
5813         }
5814         else {
5815             DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, Skip reason (layer %zu) : %d", i, excp);
5816             return 0;
5817         }
5818     }
5819 
5820     if (mergedRect.left == (int32_t)mXres && mergedRect.right == 0 &&
5821         mergedRect.top == (int32_t)mYres && mergedRect.bottom == 0) {
5822         DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, All layer skiped" );
5823         return 0;
5824     }
5825 
5826     DISPLAY_LOGD(eDebugWindowUpdate, "Partial(origin) : %d, %d, %d, %d",
5827             mergedRect.left, mergedRect.top, mergedRect.right, mergedRect.bottom);
5828 
5829     if (mergedRect.left < 0) mergedRect.left = 0;
5830     if (mergedRect.right > (int32_t)mXres) mergedRect.right = mXres;
5831     if (mergedRect.top < 0) mergedRect.top = 0;
5832     if (mergedRect.bottom > (int32_t)mYres) mergedRect.bottom = mYres;
5833 
5834     if (mergedRect.left == 0 && mergedRect.right == (int32_t)mXres &&
5835         mergedRect.top == 0 && mergedRect.bottom == (int32_t)mYres) {
5836         DISPLAY_LOGD(eDebugWindowUpdate, "Partial : Full size");
5837         mDpuData.enable_win_update = true;
5838         mDpuData.win_update_region.x = 0;
5839         mDpuData.win_update_region.w = mXres;
5840         mDpuData.win_update_region.y = 0;
5841         mDpuData.win_update_region.h = mYres;
5842         DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
5843         return 0;
5844     }
5845 
5846     mDpuData.enable_win_update = true;
5847     mDpuData.win_update_region.x = mergedRect.left;
5848     mDpuData.win_update_region.w = WIDTH(mergedRect);
5849     mDpuData.win_update_region.y = mergedRect.top;
5850     mDpuData.win_update_region.h = HEIGHT(mergedRect);
5851 
5852     DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
5853     return 0;
5854 }
5855 
getLayerRegion(ExynosLayer * layer,hwc_rect * rect_area,uint32_t regionType)5856 unsigned int ExynosDisplay::getLayerRegion(ExynosLayer *layer, hwc_rect *rect_area, uint32_t regionType) {
5857 
5858     android::Vector <hwc_rect_t> hwcRects;
5859     size_t numRects = 0;
5860 
5861     rect_area->left = INT_MAX;
5862     rect_area->top = INT_MAX;
5863     rect_area->right = rect_area->bottom = 0;
5864 
5865     hwcRects = layer->mDamageRects;
5866     numRects = layer->mDamageNum;
5867 
5868     if ((numRects == 0) || (hwcRects.size() == 0))
5869         return eDamageRegionFull;
5870 
5871     if ((numRects == 1) && (hwcRects[0].left == 0) && (hwcRects[0].top == 0) &&
5872             (hwcRects[0].right == 0) && (hwcRects[0].bottom == 0))
5873         return eDamageRegionSkip;
5874 
5875     switch (regionType) {
5876     case eDamageRegionByDamage:
5877         for (size_t j = 0; j < hwcRects.size(); j++) {
5878             hwc_rect_t rect;
5879 
5880             if ((hwcRects[j].left < 0) || (hwcRects[j].top < 0) ||
5881                     (hwcRects[j].right < 0) || (hwcRects[j].bottom < 0) ||
5882                     (hwcRects[j].left >= hwcRects[j].right) || (hwcRects[j].top >= hwcRects[j].bottom) ||
5883                     (hwcRects[j].right - hwcRects[j].left > WIDTH(layer->mSourceCrop)) ||
5884                     (hwcRects[j].bottom - hwcRects[j].top > HEIGHT(layer->mSourceCrop))) {
5885                 rect_area->left = INT_MAX;
5886                 rect_area->top = INT_MAX;
5887                 rect_area->right = rect_area->bottom = 0;
5888                 return eDamageRegionFull;
5889             }
5890 
5891             rect.left = layer->mDisplayFrame.left + hwcRects[j].left - layer->mSourceCrop.left;
5892             rect.top = layer->mDisplayFrame.top + hwcRects[j].top - layer->mSourceCrop.top;
5893             rect.right = layer->mDisplayFrame.left + hwcRects[j].right - layer->mSourceCrop.left;
5894             rect.bottom = layer->mDisplayFrame.top + hwcRects[j].bottom - layer->mSourceCrop.top;
5895             DISPLAY_LOGD(eDebugWindowUpdate, "Display frame : %d, %d, %d, %d", layer->mDisplayFrame.left,
5896                     layer->mDisplayFrame.top, layer->mDisplayFrame.right, layer->mDisplayFrame.bottom);
5897             DISPLAY_LOGD(eDebugWindowUpdate, "hwcRects : %d, %d, %d, %d", hwcRects[j].left,
5898                     hwcRects[j].top, hwcRects[j].right, hwcRects[j].bottom);
5899             adjustRect(rect, INT_MAX, INT_MAX);
5900             /* Get sums of rects */
5901             *rect_area = expand(*rect_area, rect);
5902         }
5903         return eDamageRegionPartial;
5904         break;
5905     case eDamageRegionByLayer:
5906         if (layer->mLastLayerBuffer != layer->mLayerBuffer)
5907             return eDamageRegionFull;
5908         else
5909             return eDamageRegionSkip;
5910         break;
5911     default:
5912         HWC_LOGE(this, "%s:: Invalid regionType (%d)", __func__, regionType);
5913         return eDamageRegionError;
5914         break;
5915     }
5916 
5917     return eDamageRegionFull;
5918 }
5919 
getRestrictionIndex(int halFormat)5920 uint32_t ExynosDisplay::getRestrictionIndex(int halFormat)
5921 {
5922     if (isFormatRgb(halFormat))
5923         return RESTRICTION_RGB;
5924     else
5925         return RESTRICTION_YUV;
5926 }
5927 
closeFencesForSkipFrame(rendering_state renderingState)5928 void ExynosDisplay::closeFencesForSkipFrame(rendering_state renderingState)
5929 {
5930     for (size_t i=0; i < mLayers.size(); i++) {
5931         if (mLayers[i]->mAcquireFence != -1) {
5932             mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
5933                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
5934         }
5935     }
5936 
5937     if (mDpuData.readback_info.rel_fence >= 0) {
5938         mDpuData.readback_info.rel_fence =
5939             fence_close(mDpuData.readback_info.rel_fence, this,
5940                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5941     }
5942     if (mDpuData.readback_info.acq_fence >= 0) {
5943         mDpuData.readback_info.acq_fence =
5944             fence_close(mDpuData.readback_info.acq_fence, this,
5945                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
5946     }
5947 
5948     if (renderingState >= RENDERING_STATE_VALIDATED) {
5949         if (mDisplayControl.earlyStartMPP == true) {
5950             if (mExynosCompositionInfo.mHasCompositionLayer) {
5951                 /*
5952                  * m2mMPP's release fence for dst buffer was set to
5953                  * mExynosCompositionInfo.mAcquireFence by startPostProcessing()
5954                  * in validate time.
5955                  * This fence should be passed to display driver
5956                  * but it wont't because this frame will not be presented.
5957                  * So fence should be closed.
5958                  */
5959                 mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence,
5960                         this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5961             }
5962 
5963             for (size_t i = 0; i < mLayers.size(); i++) {
5964                 exynos_image outImage;
5965                 ExynosMPP* m2mMPP = mLayers[i]->mM2mMPP;
5966                 if ((mLayers[i]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) &&
5967                     (m2mMPP != NULL) &&
5968                     (m2mMPP->mAssignedDisplay == this) &&
5969                     (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
5970                     if (m2mMPP->mPhysicalType == MPP_MSC) {
5971                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
5972                     } else if (m2mMPP->mPhysicalType == MPP_G2D) {
5973                         ALOGD("close(%d)", outImage.releaseFenceFd);
5974                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5975                     } else {
5976                         DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
5977                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
5978                     }
5979                     m2mMPP->resetDstReleaseFence();
5980                     ALOGD("reset buf[%d], %d", m2mMPP->mCurrentDstBuf,
5981                             m2mMPP->mDstImgs[m2mMPP->mCurrentDstBuf].acrylicReleaseFenceFd);
5982                 }
5983             }
5984         }
5985     }
5986 
5987     if (renderingState >= RENDERING_STATE_PRESENTED) {
5988         /* mAcquireFence is set after validate */
5989         mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
5990                 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
5991     }
5992 }
closeFences()5993 void ExynosDisplay::closeFences()
5994 {
5995     for (auto &config : mDpuData.configs) {
5996         if (config.acq_fence != -1)
5997             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
5998         config.acq_fence = -1;
5999         if (config.rel_fence >= 0)
6000             fence_close(config.rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP);
6001         config.rel_fence = -1;
6002     }
6003     for (auto &config : mDpuData.rcdConfigs) {
6004         if (config.acq_fence != -1)
6005             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
6006         config.acq_fence = -1;
6007         if (config.rel_fence >= 0)
6008             fence_close(config.rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP);
6009         config.rel_fence = -1;
6010     }
6011     for (size_t i = 0; i < mLayers.size(); i++) {
6012         if (mLayers[i]->mReleaseFence > 0) {
6013             fence_close(mLayers[i]->mReleaseFence, this,
6014                     FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
6015             mLayers[i]->mReleaseFence = -1;
6016         }
6017         if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
6018             (mLayers[i]->mM2mMPP != NULL)) {
6019             mLayers[i]->mM2mMPP->closeFences();
6020         }
6021     }
6022     if (mExynosCompositionInfo.mHasCompositionLayer) {
6023         if (mExynosCompositionInfo.mM2mMPP == NULL)
6024         {
6025             DISPLAY_LOGE("There is exynos composition, but m2mMPP is NULL");
6026             return;
6027         }
6028         mExynosCompositionInfo.mM2mMPP->closeFences();
6029     }
6030 
6031     for (size_t i=0; i < mLayers.size(); i++) {
6032         if (mLayers[i]->mAcquireFence != -1) {
6033             mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
6034                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
6035         }
6036     }
6037 
6038     mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence, this,
6039             FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
6040     mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
6041             FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
6042 
6043     if (mDpuData.retire_fence > 0)
6044         fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
6045     mDpuData.retire_fence = -1;
6046 
6047     mLastRetireFence = fence_close(mLastRetireFence, this,  FENCE_TYPE_RETIRE, FENCE_IP_DPP);
6048 
6049     if (mDpuData.readback_info.rel_fence >= 0) {
6050         mDpuData.readback_info.rel_fence =
6051             fence_close(mDpuData.readback_info.rel_fence, this,
6052                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6053     }
6054     if (mDpuData.readback_info.acq_fence >= 0) {
6055         mDpuData.readback_info.acq_fence =
6056             fence_close(mDpuData.readback_info.acq_fence, this,
6057                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
6058     }
6059 }
6060 
setHWCControl(uint32_t ctrl,int32_t val)6061 void ExynosDisplay::setHWCControl(uint32_t ctrl, int32_t val)
6062 {
6063     switch (ctrl) {
6064         case HWC_CTL_ENABLE_COMPOSITION_CROP:
6065             mDisplayControl.enableCompositionCrop = (unsigned int)val;
6066             break;
6067         case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
6068             mDisplayControl.enableExynosCompositionOptimization = (unsigned int)val;
6069             break;
6070         case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
6071             mDisplayControl.enableClientCompositionOptimization = (unsigned int)val;
6072             break;
6073         case HWC_CTL_USE_MAX_G2D_SRC:
6074             mDisplayControl.useMaxG2DSrc = (unsigned int)val;
6075             break;
6076         case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
6077             mDisplayControl.handleLowFpsLayers = (unsigned int)val;
6078             break;
6079         case HWC_CTL_ENABLE_EARLY_START_MPP:
6080             mDisplayControl.earlyStartMPP = (unsigned int)val;
6081             break;
6082         default:
6083             ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
6084             break;
6085     }
6086 }
6087 
getHdrCapabilities(uint32_t * outNumTypes,int32_t * outTypes,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)6088 int32_t ExynosDisplay::getHdrCapabilities(uint32_t* outNumTypes,
6089         int32_t* outTypes, float* outMaxLuminance,
6090         float* outMaxAverageLuminance, float* outMinLuminance)
6091 {
6092     DISPLAY_LOGD(eDebugHWC, "HWC2: %s, %d", __func__, __LINE__);
6093 
6094     if (outNumTypes == NULL || outMaxLuminance == NULL ||
6095             outMaxAverageLuminance == NULL || outMinLuminance == NULL) {
6096         return HWC2_ERROR_BAD_PARAMETER;
6097     }
6098 
6099     if (outTypes == NULL) {
6100         /*
6101          * This function is always called twice.
6102          * outTypes is NULL in the first call and
6103          * outType is valid pointer in the second call.
6104          * Get information only in the first call.
6105          * Use saved information in the second call.
6106          */
6107         if (mDisplayInterface->updateHdrCapabilities() != NO_ERROR)
6108             return HWC2_ERROR_BAD_CONFIG;
6109     }
6110 
6111     *outMaxLuminance = mMaxLuminance;
6112     *outMaxAverageLuminance = mMaxAverageLuminance;
6113     *outMinLuminance = mMinLuminance;
6114 
6115     if (outTypes == NULL) {
6116         *outNumTypes = mHdrTypes.size();
6117     } else {
6118         if (*outNumTypes != mHdrTypes.size()) {
6119             ALOGE("%s:: Invalid parameter (outNumTypes: %d, mHdrTypes size: %zu",
6120                     __func__, *outNumTypes, mHdrTypes.size());
6121             return HWC2_ERROR_BAD_PARAMETER;
6122         }
6123         for(uint32_t i = 0; i < *outNumTypes; i++) {
6124             outTypes[i] = mHdrTypes[i];
6125         }
6126     }
6127     return HWC2_ERROR_NONE;
6128 }
6129 
getMountOrientation(HwcMountOrientation * orientation)6130 int32_t ExynosDisplay::getMountOrientation(HwcMountOrientation *orientation)
6131 {
6132     if (!orientation)
6133         return HWC2_ERROR_BAD_PARAMETER;
6134 
6135     *orientation = mMountOrientation;
6136     return HWC2_ERROR_NONE;
6137 }
6138 
getVrrConfigs(hwc2_config_t config)6139 std::optional<VrrConfig_t> ExynosDisplay::getVrrConfigs(hwc2_config_t config) {
6140     if (isBadConfig(config)) {
6141         return std::nullopt;
6142     }
6143     return mDisplayConfigs[config].vrrConfig;
6144 }
6145 
6146 // Support DDI scalser
setDDIScalerEnable(int __unused width,int __unused height)6147 void ExynosDisplay::setDDIScalerEnable(int __unused width, int __unused height) {
6148 }
6149 
getDDIScalerMode(int __unused width,int __unused height)6150 int ExynosDisplay::getDDIScalerMode(int __unused width, int __unused height) {
6151     return 1; // WQHD
6152 }
6153 
increaseMPPDstBufIndex()6154 void ExynosDisplay::increaseMPPDstBufIndex() {
6155     for (size_t i=0; i < mLayers.size(); i++) {
6156         if((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
6157            (mLayers[i]->mM2mMPP != NULL)) {
6158             mLayers[i]->mM2mMPP->increaseDstBuffIndex();
6159         }
6160     }
6161 
6162     if ((mExynosCompositionInfo.mHasCompositionLayer) &&
6163         (mExynosCompositionInfo.mM2mMPP != NULL)) {
6164         mExynosCompositionInfo.mM2mMPP->increaseDstBuffIndex();
6165     }
6166 }
6167 
getReadbackBufferAttributes(int32_t * outFormat,int32_t * outDataspace)6168 int32_t ExynosDisplay::getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
6169         int32_t* /*android_dataspace_t*/ outDataspace)
6170 {
6171     int32_t ret = mDisplayInterface->getReadbackBufferAttributes(outFormat, outDataspace);
6172     if (ret == NO_ERROR) {
6173         /* Interface didn't specific set dataspace */
6174         if (*outDataspace == HAL_DATASPACE_UNKNOWN)
6175             *outDataspace = colorModeToDataspace(mColorMode);
6176         /* Set default value */
6177         if (*outDataspace == HAL_DATASPACE_UNKNOWN)
6178             *outDataspace = HAL_DATASPACE_V0_SRGB;
6179 
6180         mDisplayControl.readbackSupport = true;
6181         ALOGI("readback info: format(0x%8x), dataspace(0x%8x)", *outFormat, *outDataspace);
6182     } else {
6183         mDisplayControl.readbackSupport = false;
6184         ALOGI("readback is not supported, ret(%d)", ret);
6185         ret = HWC2_ERROR_UNSUPPORTED;
6186     }
6187     return ret;
6188 }
6189 
setReadbackBuffer(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)6190 int32_t ExynosDisplay::setReadbackBuffer(buffer_handle_t buffer,
6191         int32_t releaseFence, bool requestedService)
6192 {
6193     Mutex::Autolock lock(mDisplayMutex);
6194     int32_t ret = NO_ERROR;
6195 
6196     if (buffer == nullptr)
6197         return HWC2_ERROR_BAD_PARAMETER;
6198 
6199     if (mDisplayControl.readbackSupport) {
6200         mDpuData.enable_readback = true;
6201     } else {
6202         DISPLAY_LOGE("readback is not supported but setReadbackBuffer is called, buffer(%p), releaseFence(%d)",
6203                 buffer, releaseFence);
6204         if (releaseFence >= 0)
6205             releaseFence = fence_close(releaseFence, this,
6206                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6207         mDpuData.enable_readback = false;
6208         ret = HWC2_ERROR_UNSUPPORTED;
6209     }
6210     setReadbackBufferInternal(buffer, releaseFence, requestedService);
6211     return ret;
6212 }
6213 
setReadbackBufferInternal(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)6214 void ExynosDisplay::setReadbackBufferInternal(buffer_handle_t buffer,
6215         int32_t releaseFence, bool requestedService)
6216 {
6217     if (mDpuData.readback_info.rel_fence >= 0) {
6218         mDpuData.readback_info.rel_fence =
6219             fence_close(mDpuData.readback_info.rel_fence, this,
6220                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6221         DISPLAY_LOGE("previous readback release fence is not delivered to display device");
6222     }
6223     if (releaseFence >= 0) {
6224         setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB,
6225                      HwcFenceDirection::FROM);
6226     }
6227     mDpuData.readback_info.rel_fence = releaseFence;
6228 
6229     if (buffer != NULL)
6230         mDpuData.readback_info.handle = buffer;
6231 
6232     mDpuData.readback_info.requested_from_service = requestedService;
6233 }
6234 
getReadbackBufferFence(int32_t * outFence)6235 int32_t ExynosDisplay::getReadbackBufferFence(int32_t* outFence)
6236 {
6237     /*
6238      * acq_fence was not set or
6239      * it was already closed by error or frame skip
6240      */
6241     if (mDpuData.readback_info.acq_fence < 0) {
6242         *outFence = -1;
6243         return HWC2_ERROR_UNSUPPORTED;
6244     }
6245 
6246     *outFence = mDpuData.readback_info.acq_fence;
6247     /* Fence will be closed by caller of this function */
6248     mDpuData.readback_info.acq_fence = -1;
6249     return NO_ERROR;
6250 }
6251 
setReadbackBufferAcqFence(int32_t acqFence)6252 int32_t ExynosDisplay::setReadbackBufferAcqFence(int32_t acqFence) {
6253     if (mDpuData.readback_info.acq_fence >= 0) {
6254         mDpuData.readback_info.acq_fence =
6255             fence_close(mDpuData.readback_info.acq_fence, this,
6256                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
6257         DISPLAY_LOGE("previous readback out fence is not delivered to framework");
6258     }
6259     mDpuData.readback_info.acq_fence = acqFence;
6260     if (acqFence >= 0) {
6261         /*
6262          * Requtester of readback will get acqFence after presentDisplay
6263          * so validateFences should not check this fence
6264          * in presentDisplay so this function sets pendingAllowed parameter.
6265          */
6266         setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP,
6267                      HwcFenceDirection::FROM, true);
6268     }
6269 
6270     return NO_ERROR;
6271 }
6272 
initDisplayInterface(uint32_t __unused interfaceType)6273 void ExynosDisplay::initDisplayInterface(uint32_t __unused interfaceType)
6274 {
6275     mDisplayInterface = std::make_unique<ExynosDisplayInterface>();
6276     mDisplayInterface->init(this);
6277 }
6278 
uncacheLayerBuffers(ExynosLayer * layer,const std::vector<buffer_handle_t> & buffers,std::vector<buffer_handle_t> & outClearableBuffers)6279 int32_t ExynosDisplay::uncacheLayerBuffers(ExynosLayer* layer,
6280                                            const std::vector<buffer_handle_t>& buffers,
6281                                            std::vector<buffer_handle_t>& outClearableBuffers) {
6282     if (mPowerModeState.has_value() && mPowerModeState.value() == HWC2_POWER_MODE_OFF) {
6283         for (auto buffer : buffers) {
6284             if (layer->mLayerBuffer == buffer) {
6285                 layer->mLayerBuffer = nullptr;
6286             }
6287             if (layer->mLastLayerBuffer == buffer) {
6288                 layer->mLastLayerBuffer = nullptr;
6289             }
6290         }
6291         outClearableBuffers = buffers;
6292         return mDisplayInterface->uncacheLayerBuffers(layer, outClearableBuffers);
6293     }
6294     return NO_ERROR;
6295 }
6296 
traceLayerTypes()6297 void ExynosDisplay::traceLayerTypes() {
6298     size_t g2d_count = 0;
6299     size_t dpu_count = 0;
6300     size_t gpu_count = 0;
6301     size_t skip_count = 0;
6302     size_t rcd_count = 0;
6303     for(auto const& layer: mLayers) {
6304         switch (layer->mExynosCompositionType) {
6305             case HWC2_COMPOSITION_EXYNOS:
6306                 g2d_count++;
6307                 break;
6308             case HWC2_COMPOSITION_CLIENT:
6309                 if (layer->mCompositionType == HWC2_COMPOSITION_DEVICE) {
6310                     skip_count++;
6311                 } else {
6312                     gpu_count++;
6313                 }
6314                 break;
6315             case HWC2_COMPOSITION_DEVICE:
6316                 dpu_count++;
6317                 break;
6318             case HWC2_COMPOSITION_DISPLAY_DECORATION:
6319                 ++rcd_count;
6320                 break;
6321             default:
6322                 ALOGW("%s: Unknown layer composition type: %d", __func__,
6323                       layer->mExynosCompositionType);
6324                 break;
6325         }
6326     }
6327     DISPLAY_ATRACE_INT("HWComposer: DPU Layer", dpu_count);
6328     DISPLAY_ATRACE_INT("HWComposer: G2D Layer", g2d_count);
6329     DISPLAY_ATRACE_INT("HWComposer: GPU Layer", gpu_count);
6330     DISPLAY_ATRACE_INT("HWComposer: RCD Layer", rcd_count);
6331     DISPLAY_ATRACE_INT("HWComposer: DPU Cached Layer", skip_count);
6332     DISPLAY_ATRACE_INT("HWComposer: SF Cached Layer", mIgnoreLayers.size());
6333     DISPLAY_ATRACE_INT("HWComposer: Total Layer", mLayers.size() + mIgnoreLayers.size());
6334 }
6335 
updateBrightnessState()6336 void ExynosDisplay::updateBrightnessState() {
6337     static constexpr float kMaxCll = 10000.0;
6338     bool clientRgbHdr = false;
6339     bool instantHbm = false;
6340     bool sdrDim = false;
6341     BrightnessController::HdrLayerState hdrState = BrightnessController::HdrLayerState::kHdrNone;
6342 
6343     for (size_t i = 0; i < mLayers.size(); i++) {
6344         if (mLayers[i]->mIsHdrLayer) {
6345             // TODO(longling): Below code block for RGB HDR is obsolete also
6346             // need some fix (mExynosCompositionType is invalid at this time)
6347             if (mLayers[i]->isLayerFormatRgb()) {
6348                 auto meta = mLayers[i]->getMetaParcel();
6349                 if ((meta != nullptr) && (meta->eType & VIDEO_INFO_TYPE_HDR_STATIC) &&
6350                     meta->sHdrStaticInfo.sType1.mMaxContentLightLevel >= kMaxCll) {
6351                     // if there are one or more such layers and any one of them
6352                     // is composed by GPU, we won't dim sdr layers
6353                     if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
6354                         clientRgbHdr = true;
6355                     } else {
6356                         instantHbm = true;
6357                     }
6358                 }
6359             }
6360 
6361             // If any HDR layer is large, keep the state as kHdrLarge
6362             if (hdrState != BrightnessController::HdrLayerState::kHdrLarge
6363                 && mLayers[i]->getDisplayFrameArea() >= mHdrFullScrenAreaThreshold) {
6364                 hdrState = BrightnessController::HdrLayerState::kHdrLarge;
6365             } else if (hdrState == BrightnessController::HdrLayerState::kHdrNone) {
6366                 hdrState = BrightnessController::HdrLayerState::kHdrSmall;
6367             } // else keep the state (kHdrLarge or kHdrSmall) unchanged.
6368         }
6369         // SDR layers could be kept dimmed for a while after HDR is gone (DM
6370         // will animate the display brightness from HDR brightess to SDR brightness).
6371         if (mLayers[i]->mBrightness < 1.0) {
6372             sdrDim = true;
6373         }
6374     }
6375 
6376     if (mBrightnessController) {
6377         mBrightnessController->updateFrameStates(hdrState, sdrDim);
6378         mBrightnessController->processInstantHbm(instantHbm && !clientRgbHdr);
6379         mBrightnessController->updateCabcMode();
6380     }
6381 }
6382 
cleanupAfterClientDeath()6383 void ExynosDisplay::cleanupAfterClientDeath() {
6384     // Invalidate the client target buffer because it will be freed when the client dies
6385     mClientCompositionInfo.mTargetBuffer = NULL;
6386     // Invalidate the skip static flag so that we have to get a new target buffer first
6387     // before we can skip the static layers
6388     mClientCompositionInfo.mSkipStaticInitFlag = false;
6389     mClientCompositionInfo.mSkipFlag = false;
6390 }
6391 
flushDisplayBrightnessChange()6392 int32_t ExynosDisplay::flushDisplayBrightnessChange() {
6393     if (mBrightnessController) {
6394         setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
6395         if (mOperationRateManager) {
6396             mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
6397             handleTargetOperationRate();
6398         }
6399         return mBrightnessController->applyPendingChangeViaSysfs(mVsyncPeriod);
6400     }
6401     return NO_ERROR;
6402 }
6403 
6404 // we can cache the value once it is known to avoid the lock after boot
6405 // we also only actually check once per frame to keep the value internally consistent
usePowerHintSession()6406 bool ExynosDisplay::usePowerHintSession() {
6407     if (!mUsePowerHintSession.has_value() && mPowerHalHint.checkPowerHintSessionReady()) {
6408         mUsePowerHintSession = mPowerHalHint.usePowerHintSession();
6409     }
6410     return mUsePowerHintSession.value_or(false);
6411 }
6412 
getExpectedPresentTime(nsecs_t startTime)6413 nsecs_t ExynosDisplay::getExpectedPresentTime(nsecs_t startTime) {
6414     ExynosDisplay *primaryDisplay = mDevice->getDisplay(HWC_DISPLAY_PRIMARY);
6415     if (primaryDisplay) {
6416         nsecs_t out = primaryDisplay->getPendingExpectedPresentTime();
6417         if (out != 0) {
6418             return out;
6419         }
6420     }
6421     return getPredictedPresentTime(startTime);
6422 }
6423 
getPredictedPresentTime(nsecs_t startTime)6424 nsecs_t ExynosDisplay::getPredictedPresentTime(nsecs_t startTime) {
6425     auto lastRetireFenceSignalTime = getSignalTime(mLastRetireFence);
6426     auto expectedPresentTime = startTime - 1;
6427     if (lastRetireFenceSignalTime != SIGNAL_TIME_INVALID &&
6428         lastRetireFenceSignalTime != SIGNAL_TIME_PENDING) {
6429         expectedPresentTime = lastRetireFenceSignalTime + mVsyncPeriod;
6430         mRetireFencePreviousSignalTime = lastRetireFenceSignalTime;
6431     } else if (sync_wait(mLastRetireFence, 0) < 0) {
6432         // if last retire fence was not signaled, then try previous signal time
6433         if (mRetireFencePreviousSignalTime.has_value()) {
6434             expectedPresentTime = *mRetireFencePreviousSignalTime + 2 * mVsyncPeriod;
6435         }
6436         // the last retire fence acquire time can be useful where the previous fence signal time may
6437         // not be recorded yet, but it's only accurate when there is fence wait time
6438         if (mRetireFenceAcquireTime.has_value()) {
6439             expectedPresentTime =
6440                     max(expectedPresentTime, *mRetireFenceAcquireTime + 2 * mVsyncPeriod);
6441         }
6442     }
6443     if (expectedPresentTime < startTime) {
6444         ALOGV("Could not predict expected present time, fall back on target of one vsync");
6445         expectedPresentTime = startTime + mVsyncPeriod;
6446     }
6447     return expectedPresentTime;
6448 }
6449 
getSignalTime(int32_t fd) const6450 nsecs_t ExynosDisplay::getSignalTime(int32_t fd) const {
6451     if (fd == -1) {
6452         return SIGNAL_TIME_INVALID;
6453     }
6454 
6455     struct sync_file_info *finfo = sync_file_info(fd);
6456     if (finfo == nullptr) {
6457         return SIGNAL_TIME_INVALID;
6458     }
6459 
6460     if (finfo->status != 1) {
6461         const auto status = finfo->status;
6462         sync_file_info_free(finfo);
6463         return status < 0 ? SIGNAL_TIME_INVALID : SIGNAL_TIME_PENDING;
6464     }
6465 
6466     uint64_t timestamp = 0;
6467     struct sync_fence_info *pinfo = sync_get_fence_info(finfo);
6468     for (size_t i = 0; i < finfo->num_fences; i++) {
6469         if (pinfo[i].timestamp_ns > timestamp) {
6470             timestamp = pinfo[i].timestamp_ns;
6471         }
6472     }
6473 
6474     sync_file_info_free(finfo);
6475     return nsecs_t(timestamp);
6476 }
6477 
getPredictedDuration(bool duringValidation)6478 std::optional<nsecs_t> ExynosDisplay::getPredictedDuration(bool duringValidation) {
6479     AveragesKey beforeFenceKey(mLayers.size(), duringValidation, true);
6480     AveragesKey afterFenceKey(mLayers.size(), duringValidation, false);
6481     if (mRollingAverages.count(beforeFenceKey) == 0 || mRollingAverages.count(afterFenceKey) == 0) {
6482         return std::nullopt;
6483     }
6484     nsecs_t beforeReleaseFence = mRollingAverages[beforeFenceKey].average;
6485     nsecs_t afterReleaseFence = mRollingAverages[afterFenceKey].average;
6486     return std::make_optional(afterReleaseFence + beforeReleaseFence);
6487 }
6488 
updateAverages(nsecs_t endTime)6489 void ExynosDisplay::updateAverages(nsecs_t endTime) {
6490     if (!mRetireFenceWaitTime.has_value() || !mRetireFenceAcquireTime.has_value()) {
6491         return;
6492     }
6493     nsecs_t beforeFenceTime =
6494             mValidationDuration.value_or(0) + (*mRetireFenceWaitTime - mPresentStartTime);
6495     nsecs_t afterFenceTime = endTime - *mRetireFenceAcquireTime;
6496     mRollingAverages[AveragesKey(mLayers.size(), mValidationDuration.has_value(), true)].insert(
6497             beforeFenceTime);
6498     mRollingAverages[AveragesKey(mLayers.size(), mValidationDuration.has_value(), false)].insert(
6499             afterFenceTime);
6500 }
6501 
getRCDLayerSupport(bool & outSupport) const6502 int32_t ExynosDisplay::getRCDLayerSupport(bool &outSupport) const {
6503     outSupport = mDebugRCDLayerEnabled && mDpuData.rcdConfigs.size() > 0;
6504     return NO_ERROR;
6505 }
6506 
setDebugRCDLayerEnabled(bool enable)6507 int32_t ExynosDisplay::setDebugRCDLayerEnabled(bool enable) {
6508     mDebugRCDLayerEnabled = enable;
6509     return NO_ERROR;
6510 }
6511 
getDisplayIdleTimerSupport(bool & outSupport)6512 int32_t ExynosDisplay::getDisplayIdleTimerSupport(bool &outSupport) {
6513     return mDisplayInterface->getDisplayIdleTimerSupport(outSupport);
6514 }
6515 
getDisplayMultiThreadedPresentSupport(bool & outSupport)6516 int32_t ExynosDisplay::getDisplayMultiThreadedPresentSupport(bool &outSupport) {
6517     outSupport = mDisplayControl.multiThreadedPresent;
6518     return NO_ERROR;
6519 }
6520 
isMixedComposition()6521 bool ExynosDisplay::isMixedComposition() {
6522     for (size_t i = 0; i < mLayers.size(); i++) {
6523         if (mLayers[i]->mBrightness < 1.0) {
6524             return true;
6525         }
6526     }
6527     return false;
6528 }
6529 
lookupDisplayConfigs(const int32_t & width,const int32_t & height,const int32_t & fps,const int32_t & vsyncRate,int32_t * outConfig)6530 int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
6531                                         const int32_t &height,
6532                                         const int32_t &fps,
6533                                         const int32_t &vsyncRate,
6534                                         int32_t *outConfig) {
6535     if (!fps || !vsyncRate)
6536         return HWC2_ERROR_BAD_CONFIG;
6537 
6538     constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
6539     const auto vsyncPeriod = nsecsPerSec / vsyncRate;
6540 
6541     for (auto const& [config, mode] : mDisplayConfigs) {
6542         long delta = abs(vsyncPeriod - mode.vsyncPeriod);
6543         if ((width == 0 || width == mode.width) && (height == 0 || height == mode.height) &&
6544             (delta < nsecsPerMs) && (fps == mode.refreshRate)) {
6545             ALOGD("%s: found display config for mode: %dx%d@%d:%d config=%d",
6546                  __func__, width, height, fps, vsyncRate, config);
6547             *outConfig = config;
6548             return HWC2_ERROR_NONE;
6549         }
6550     }
6551 
6552     return HWC2_ERROR_BAD_CONFIG;
6553 }
6554 
lookupDisplayConfigsRelaxed(const int32_t & width,const int32_t & height,const int32_t & fps,int32_t * outConfig)6555 int ExynosDisplay::lookupDisplayConfigsRelaxed(const int32_t &width,
6556                                                const int32_t &height,
6557                                                const int32_t &fps,
6558                                                int32_t *outConfig) {
6559     if (fps <= 1)
6560         return HWC2_ERROR_BAD_CONFIG;
6561 
6562     const auto vsyncPeriod = nsecsPerSec / fps;
6563     const auto vsyncPeriodMin = nsecsPerSec / (fps + 1);
6564     const auto vsyncPeriodMax = nsecsPerSec / (fps - 1);
6565 
6566     // Search for exact match in resolution and vsync
6567     for (auto const& [config, mode] : mDisplayConfigs) {
6568         if (mode.width == width && mode.height == height && mode.vsyncPeriod == vsyncPeriod) {
6569             ALOGD("%s: found exact match for mode %dx%d@%d -> config=%d",
6570                  __func__, width, height, fps, config);
6571             *outConfig = config;
6572             return HWC2_ERROR_NONE;
6573         }
6574     }
6575 
6576     // Search for exact match in resolution, allow small variance in vsync
6577     for (auto const& [config, mode] : mDisplayConfigs) {
6578         if (mode.width == width && mode.height == height &&
6579             mode.vsyncPeriod >= vsyncPeriodMin && mode.vsyncPeriod <= vsyncPeriodMax) {
6580             ALOGD("%s: found close match for mode %dx%d@%d -> config=%d",
6581                  __func__, width, height, fps, config);
6582             *outConfig = config;
6583             return HWC2_ERROR_NONE;
6584         }
6585     }
6586 
6587     // Search for smaller resolution, allow small variance in vsync
6588     // mDisplayConfigs is sorted, so this will give the largest available option
6589     for (auto const& [config, mode] : mDisplayConfigs) {
6590         if (mode.width <= width && mode.height <= height &&
6591             mode.vsyncPeriod >= vsyncPeriodMin && mode.vsyncPeriod <= vsyncPeriodMax) {
6592             ALOGD("%s: found relaxed match for mode %dx%d@%d -> config=%d",
6593                  __func__, width, height, fps, config);
6594             *outConfig = config;
6595             return HWC2_ERROR_NONE;
6596         }
6597     }
6598 
6599     return HWC2_ERROR_BAD_CONFIG;
6600 }
6601 
openLogFile(const std::string & filename,const std::string & mode)6602 FILE *ExynosDisplay::RotatingLogFileWriter::openLogFile(const std::string &filename,
6603                                                         const std::string &mode) {
6604     FILE *file = nullptr;
6605     auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
6606     file = fopen(fullpath.c_str(), mode.c_str());
6607     if (file != nullptr) {
6608         return file;
6609     }
6610     ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
6611     fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
6612     file = fopen(fullpath.c_str(), mode.c_str());
6613     if (file == nullptr) {
6614         ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
6615     }
6616     return file;
6617 }
6618 
getLastModifiedTimestamp(const std::string & filename)6619 std::optional<nsecs_t> ExynosDisplay::RotatingLogFileWriter::getLastModifiedTimestamp(
6620         const std::string &filename) {
6621     struct stat fileStat;
6622     auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
6623     if (stat(fullpath.c_str(), &fileStat) == 0) {
6624         return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
6625     }
6626     fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
6627     if (stat(fullpath.c_str(), &fileStat) == 0) {
6628         return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
6629     }
6630     return std::nullopt;
6631 }
6632 
chooseOpenedFile()6633 bool ExynosDisplay::RotatingLogFileWriter::chooseOpenedFile() {
6634     if (mLastFileIndex < 0) {
6635         // HWC could be restarted, so choose to open new file or continue the last modified file
6636         int chosenIndex = 0;
6637         nsecs_t lastModifTimestamp = 0;
6638         for (int i = 0; i < mMaxFileCount; ++i) {
6639             auto timestamp = getLastModifiedTimestamp(mPrefixName + std::to_string(i) + mExtension);
6640             if (!timestamp.has_value()) {
6641                 chosenIndex = i;
6642                 break;
6643             }
6644             if (i == 0 || lastModifTimestamp < *timestamp) {
6645                 chosenIndex = i;
6646                 lastModifTimestamp = *timestamp;
6647             }
6648         }
6649         auto filename = mPrefixName + std::to_string(chosenIndex) + mExtension;
6650         mFile = openLogFile(filename, "ab");
6651         if (mFile == nullptr) {
6652             ALOGE("Unable to open log file for %s", filename.c_str());
6653             return false;
6654         }
6655         mLastFileIndex = chosenIndex;
6656     }
6657 
6658     // Choose to use the same last file or move on to the next file
6659     for (int i = 0; i < 2; ++i) {
6660         if (mFile == nullptr) {
6661             mFile = openLogFile(mPrefixName + std::to_string(mLastFileIndex) + mExtension,
6662                                 (i == 0) ? "ab" : "wb");
6663         }
6664         if (mFile != nullptr) {
6665             auto fileSize = ftell(mFile);
6666             if (fileSize < mThresholdSizePerFile) return true;
6667             fclose(mFile);
6668             mFile = nullptr;
6669         }
6670         mLastFileIndex = (mLastFileIndex + 1) % mMaxFileCount;
6671     }
6672     return false;
6673 }
6674 
invalidate()6675 void ExynosDisplay::invalidate() {
6676     mDevice->onRefresh(mDisplayId);
6677 }
6678 
checkHotplugEventUpdated(bool & hpdStatus)6679 bool ExynosDisplay::checkHotplugEventUpdated(bool &hpdStatus) {
6680     if (mDisplayInterface == nullptr) {
6681         ALOGW("%s: mDisplayInterface == nullptr", __func__);
6682         return false;
6683     }
6684 
6685     hpdStatus = mDisplayInterface->readHotplugStatus();
6686 
6687     int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
6688 
6689     DISPLAY_LOGI("[%s] mDisplayId(%d), mIndex(%d), HPD Status(previous :%d, current : %d), "
6690                  "hotplugErrorCode=%d",
6691                  __func__, mDisplayId, mIndex, mHpdStatus, hpdStatus, hotplugErrorCode);
6692 
6693     return (mHpdStatus != hpdStatus) || (hotplugErrorCode != 0);
6694 }
6695 
handleHotplugEvent(bool hpdStatus)6696 void ExynosDisplay::handleHotplugEvent(bool hpdStatus) {
6697     mHpdStatus = hpdStatus;
6698 }
6699 
hotplug()6700 void ExynosDisplay::hotplug() {
6701     int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
6702     mDisplayInterface->resetHotplugErrorCode();
6703     mDevice->onHotPlug(mDisplayId, mHpdStatus, hotplugErrorCode);
6704     ALOGI("HPD callback(%s, mDisplayId %d, hotplugErrorCode=%d) was called",
6705           mHpdStatus ? "connection" : "disconnection", mDisplayId, hotplugErrorCode);
6706 }
6707 
contentProtectionUpdated(HdcpLevels hdcpLevels)6708 void ExynosDisplay::contentProtectionUpdated(HdcpLevels hdcpLevels) {
6709     mDevice->onContentProtectionUpdated(mDisplayId, hdcpLevels);
6710 }
6711 
SysfsBasedRRIHandler(ExynosDisplay * display)6712 ExynosDisplay::SysfsBasedRRIHandler::SysfsBasedRRIHandler(ExynosDisplay* display)
6713       : mDisplay(display),
6714         mLastRefreshRate(0),
6715         mLastCallbackTime(0),
6716         mIgnoringLastUpdate(false),
6717         mCanIgnoreIncreaseUpdate(false) {}
6718 
init()6719 int32_t ExynosDisplay::SysfsBasedRRIHandler::init() {
6720     auto path = String8::format(kRefreshRateStatePathFormat, mDisplay->mIndex);
6721     mFd.Set(open(path.c_str(), O_RDONLY));
6722     if (mFd.get() < 0) {
6723         ALOGE("Failed to open sysfs(%s) for refresh rate debug event: %s", path.c_str(),
6724               strerror(errno));
6725         return -errno;
6726     }
6727     auto ret = mDisplay->mDevice->mDeviceInterface->registerSysfsEventHandler(shared_from_this());
6728     if (ret != NO_ERROR) {
6729         ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret);
6730         return ret;
6731     }
6732     setAllowWakeup(true);
6733     // Call the callback immediately
6734     handleSysfsEvent();
6735     return NO_ERROR;
6736 }
6737 
disable()6738 int32_t ExynosDisplay::SysfsBasedRRIHandler::disable() {
6739     setAllowWakeup(false);
6740     return mDisplay->mDevice->mDeviceInterface->unregisterSysfsEventHandler(getFd());
6741 }
6742 
updateRefreshRateLocked(int refreshRate)6743 void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRateLocked(int refreshRate) {
6744     ATRACE_CALL();
6745     ATRACE_INT("Refresh rate indicator event", refreshRate);
6746     // Ignore refresh rate increase that is caused by refresh rate indicator update but there's
6747     // no update for the other layers
6748     if (mCanIgnoreIncreaseUpdate && refreshRate > mLastRefreshRate && mLastRefreshRate > 0 &&
6749         mDisplay->getLastLayerUpdateTime() < mLastCallbackTime) {
6750         mIgnoringLastUpdate = true;
6751         mCanIgnoreIncreaseUpdate = false;
6752         return;
6753     }
6754     mIgnoringLastUpdate = false;
6755     if (refreshRate == mLastRefreshRate) {
6756         return;
6757     }
6758     mLastRefreshRate = refreshRate;
6759     mLastCallbackTime = systemTime(CLOCK_MONOTONIC);
6760     mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / mLastRefreshRate);
6761     mCanIgnoreIncreaseUpdate = true;
6762 }
6763 
handleSysfsEvent()6764 void ExynosDisplay::SysfsBasedRRIHandler::handleSysfsEvent() {
6765     ATRACE_CALL();
6766     std::scoped_lock lock(mMutex);
6767 
6768     char buffer[1024];
6769     lseek(mFd.get(), 0, SEEK_SET);
6770     int ret = read(mFd.get(), &buffer, sizeof(buffer));
6771     if (ret < 0) {
6772         ALOGE("%s: Failed to read refresh rate from fd %d: %s", __func__, mFd.get(),
6773               strerror(errno));
6774         return;
6775     }
6776     std::string_view bufferView(buffer);
6777     auto pos = bufferView.find('@');
6778     if (pos == std::string::npos) {
6779         ALOGE("%s: Failed to parse refresh rate event (invalid format)", __func__);
6780         return;
6781     }
6782     int refreshRate = 0;
6783     std::from_chars(bufferView.data() + pos + 1, bufferView.data() + bufferView.size() - 1,
6784                     refreshRate);
6785     updateRefreshRateLocked(refreshRate);
6786 }
6787 
updateRefreshRate(int refreshRate)6788 void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRate(int refreshRate) {
6789     std::scoped_lock lock(mMutex);
6790     updateRefreshRateLocked(refreshRate);
6791 }
6792 
setAllowWakeup(const bool enabled)6793 void ExynosDisplay::SysfsBasedRRIHandler::setAllowWakeup(const bool enabled) {
6794     auto path = String8::format(kRefreshRateAllowWakeupStateChangePathFormat, mDisplay->mIndex);
6795     std::ofstream ofs(path);
6796     if (ofs.is_open()) {
6797         ofs << enabled;
6798         if (ofs.fail()) {
6799             ALOGW("%s: Failed to write %d to allow wakeup node: %d", __func__, enabled, errno);
6800         }
6801     } else {
6802         ALOGW("%s: Failed to open allow wakeup node: %d", __func__, errno);
6803     }
6804 }
6805 
setRefreshRateChangedCallbackDebugEnabled(bool enabled)6806 int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
6807     if ((!!mRefreshRateIndicatorHandler) == enabled) {
6808         ALOGW("%s: RefreshRateChangedCallbackDebug is already %s", __func__,
6809               enabled ? "enabled" : "disabled");
6810         return NO_ERROR;
6811     }
6812     int32_t ret = NO_ERROR;
6813     if (enabled) {
6814         if (mType == HWC_DISPLAY_PRIMARY) {
6815             mRefreshRateIndicatorHandler = std::make_shared<SysfsBasedRRIHandler>(this);
6816         } else {
6817             mRefreshRateIndicatorHandler = std::make_shared<ActiveConfigBasedRRIHandler>(this);
6818         }
6819         if (!mRefreshRateIndicatorHandler) {
6820             ALOGE("%s: Failed to create refresh rate debug handler", __func__);
6821             return -ENOMEM;
6822         }
6823         ret = mRefreshRateIndicatorHandler->init();
6824         if (ret != NO_ERROR) {
6825             ALOGE("%s: Failed to initialize refresh rate debug handler: %d", __func__, ret);
6826             mRefreshRateIndicatorHandler.reset();
6827             return ret;
6828         }
6829     } else {
6830         ret = mRefreshRateIndicatorHandler->disable();
6831         mRefreshRateIndicatorHandler.reset();
6832     }
6833     return ret;
6834 }
6835 
getLastLayerUpdateTime()6836 nsecs_t ExynosDisplay::getLastLayerUpdateTime() {
6837     Mutex::Autolock lock(mDRMutex);
6838     nsecs_t time = 0;
6839     for (size_t i = 0; i < mLayers.size(); ++i) {
6840         // The update from refresh rate indicator layer should be ignored
6841         if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
6842             continue;
6843         time = max(time, mLayers[i]->mLastUpdateTime);
6844     }
6845     return time;
6846 }
6847 
checkOnPresentDisplay()6848 void ExynosDisplay::SysfsBasedRRIHandler::checkOnPresentDisplay() {
6849     // Update refresh rate indicator if the last update event is ignored to make sure that
6850     // the refresh rate caused by the current frame update will be applied immediately since
6851     // we may not receive the sysfs event if the refresh rate is the same as the last ignored one.
6852     if (!mIgnoringLastUpdate) {
6853         return;
6854     }
6855     handleSysfsEvent();
6856 }
6857 
ActiveConfigBasedRRIHandler(ExynosDisplay * display)6858 ExynosDisplay::ActiveConfigBasedRRIHandler::ActiveConfigBasedRRIHandler(ExynosDisplay* display)
6859       : mDisplay(display), mLastRefreshRate(0) {}
6860 
init()6861 int32_t ExynosDisplay::ActiveConfigBasedRRIHandler::init() {
6862     updateRefreshRate(mDisplay->mRefreshRate);
6863     return NO_ERROR;
6864 }
6865 
updateRefreshRate(int refreshRate)6866 void ExynosDisplay::ActiveConfigBasedRRIHandler::updateRefreshRate(int refreshRate) {
6867     if (mLastRefreshRate == refreshRate) {
6868         return;
6869     }
6870     mLastRefreshRate = refreshRate;
6871     mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / refreshRate);
6872 }
6873 
checkOnSetActiveConfig(int refreshRate)6874 void ExynosDisplay::ActiveConfigBasedRRIHandler::checkOnSetActiveConfig(int refreshRate) {
6875     updateRefreshRate(refreshRate);
6876 }
6877 
checkUpdateRRIndicatorOnly()6878 bool ExynosDisplay::checkUpdateRRIndicatorOnly() {
6879     mUpdateRRIndicatorOnly = false;
6880     // mGeometryChanged & mBufferUpdates have already excluded any changes from RR Indicator layer.
6881     // GEOMETRY_LAYER_TYPE_CHANGED still needs to be excluded since SF sometimes could retry to use
6882     // DEVICE composition type again if it falls back to CLIENT at previous frame.
6883     if ((mGeometryChanged & ~GEOMETRY_LAYER_TYPE_CHANGED) > 0 || mBufferUpdates > 0) {
6884         return false;
6885     }
6886     Mutex::Autolock lock(mDRMutex);
6887     for (size_t i = 0; i < mLayers.size(); ++i) {
6888         const auto& layer = mLayers[i];
6889         if (layer->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) {
6890             // Sometimes, HWC could call onRefresh() so that SF would call another present without
6891             // any changes on geometry or buffers. Thus, this function should return true if only
6892             // there's any update on geometry or buffer of RR Indicator layer.
6893             mUpdateRRIndicatorOnly =
6894                     ((layer->mGeometryChanged) & ~GEOMETRY_LAYER_TYPE_CHANGED) > 0 ||
6895                     (layer->mLastLayerBuffer != layer->mLayerBuffer);
6896             return mUpdateRRIndicatorOnly;
6897         }
6898     }
6899     return false;
6900 }
6901 
isUpdateRRIndicatorOnly()6902 bool ExynosDisplay::isUpdateRRIndicatorOnly() {
6903     return mUpdateRRIndicatorOnly;
6904 }
6905 
getPeakRefreshRate()6906 uint32_t ExynosDisplay::getPeakRefreshRate() {
6907     uint32_t opRate = mBrightnessController->getOperationRate();
6908     return opRate ?: mPeakRefreshRate;
6909 }
6910 
getVsyncPeriod(const int32_t config)6911 VsyncPeriodNanos ExynosDisplay::getVsyncPeriod(const int32_t config) {
6912     const auto& it = mDisplayConfigs.find(config);
6913     if (it == mDisplayConfigs.end()) return 0;
6914     return it->second.vsyncPeriod;
6915 }
6916 
getRefreshRate(const int32_t config)6917 uint32_t ExynosDisplay::getRefreshRate(const int32_t config) {
6918     const auto& it = mDisplayConfigs.find(config);
6919     if (it == mDisplayConfigs.end()) return 0;
6920     return it->second.refreshRate;
6921 }
6922 
getConfigId(const int32_t refreshRate,const int32_t width,const int32_t height)6923 uint32_t ExynosDisplay::getConfigId(const int32_t refreshRate, const int32_t width,
6924                                     const int32_t height) {
6925     for (auto entry : mDisplayConfigs) {
6926         auto config = entry.first;
6927         auto displayCfg = entry.second;
6928         if (getRefreshRate(config) == refreshRate && displayCfg.width == width &&
6929             displayCfg.height == height) {
6930             return config;
6931         }
6932     }
6933     return UINT_MAX;
6934 }
6935 
resetColorMappingInfoForClientComp()6936 void ExynosDisplay::resetColorMappingInfoForClientComp() {
6937     if (mType != HWC_DISPLAY_PRIMARY) return;
6938 
6939     int32_t ret = NO_ERROR;
6940     for (uint32_t i = 0; i < mLayers.size(); i++) {
6941         ExynosLayer *layer = mLayers[i];
6942         if (layer->mPrevValidateCompositionType != HWC2_COMPOSITION_CLIENT &&
6943             layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT) {
6944             if ((ret = resetColorMappingInfo(layer)) != NO_ERROR) {
6945                 DISPLAY_LOGE("%s:: resetColorMappingInfo() idx=%d error(%d)", __func__, i, ret);
6946             }
6947         }
6948     }
6949 
6950     // when no GPU composition, resets the mapping info of client composition info
6951     if (mClientCompositionInfo.mPrevHasCompositionLayer &&
6952         !mClientCompositionInfo.mHasCompositionLayer) {
6953         if ((ret = resetColorMappingInfo(&mClientCompositionInfo)) != NO_ERROR) {
6954             DISPLAY_LOGE("%s:: resetColorMappingInfo() for client target error(%d)", __func__, ret);
6955         }
6956     }
6957 }
6958 
storePrevValidateCompositionType()6959 void ExynosDisplay::storePrevValidateCompositionType() {
6960     for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
6961         ExynosLayer *layer = mIgnoreLayers[i];
6962         layer->mPrevValidateCompositionType = layer->mValidateCompositionType;
6963     }
6964 
6965     for (uint32_t i = 0; i < mLayers.size(); i++) {
6966         ExynosLayer *layer = mLayers[i];
6967         layer->mPrevValidateCompositionType = layer->mValidateCompositionType;
6968     }
6969     mClientCompositionInfo.mPrevHasCompositionLayer = mClientCompositionInfo.mHasCompositionLayer;
6970 }
6971 
getDcDisplayType() const6972 displaycolor::DisplayType ExynosDisplay::getDcDisplayType() const {
6973     switch (mType) {
6974         case HWC_DISPLAY_PRIMARY:
6975             return mIndex == 0 ? displaycolor::DisplayType::DISPLAY_PRIMARY
6976                                : displaycolor::DisplayType::DISPLAY_SECONDARY;
6977         case HWC_DISPLAY_EXTERNAL:
6978             return displaycolor::DisplayType::DISPLAY_EXTERNAL;
6979         case HWC_DISPLAY_VIRTUAL:
6980         default:
6981             DISPLAY_LOGE("%s: Unsupported display type(%d)", __func__, mType);
6982             assert(false);
6983             return displaycolor::DisplayType::DISPLAY_PRIMARY;
6984     }
6985 }
6986