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]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) &&
1159                 (m2mMPP != NULL) && (m2mMPP->mAssignedDisplay == this) &&
1160                 (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
1161                 if (m2mMPP->mPhysicalType == MPP_MSC) {
1162                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
1163                 } else if (m2mMPP->mPhysicalType == MPP_G2D) {
1164                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
1165                 } else {
1166                     DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
1167                     fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
1168                 }
1169                 m2mMPP->resetDstReleaseFence();
1170             }
1171         }
1172     }
1173 }
1174 
1175 /**
1176  * @param outLayer
1177  * @return int32_t
1178  */
destroyLayer(hwc2_layer_t outLayer)1179 int32_t ExynosDisplay::destroyLayer(hwc2_layer_t outLayer) {
1180 
1181     Mutex::Autolock lock(mDRMutex);
1182     ExynosLayer *layer = (ExynosLayer *)outLayer;
1183 
1184     if (layer == nullptr) {
1185         return HWC2_ERROR_BAD_LAYER;
1186     }
1187 
1188     if (mLayers.remove(layer) < 0) {
1189         auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), layer);
1190         if (it == mIgnoreLayers.end()) {
1191             ALOGE("%s:: There is no layer", __func__);
1192         } else {
1193             mIgnoreLayers.erase(it);
1194         }
1195     } else {
1196         setGeometryChanged(GEOMETRY_DISPLAY_LAYER_REMOVED);
1197     }
1198 
1199     mDisplayInterface->destroyLayer(layer);
1200     layer->resetAssignedResource();
1201 
1202     delete layer;
1203 
1204     if (mPlugState == false) {
1205         DISPLAY_LOGI("%s : destroyLayer is done. But display is already disconnected",
1206                 __func__);
1207         return HWC2_ERROR_BAD_DISPLAY;
1208     }
1209 
1210     return HWC2_ERROR_NONE;
1211 }
1212 
1213 /**
1214  * @return void
1215  */
destroyLayers()1216 void ExynosDisplay::destroyLayers() {
1217     Mutex::Autolock lock(mDRMutex);
1218     for (uint32_t index = 0; index < mLayers.size();) {
1219         ExynosLayer *layer = mLayers[index];
1220         mLayers.removeAt(index);
1221         delete layer;
1222     }
1223 
1224     for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
1225         ExynosLayer *layer = *it;
1226         it = mIgnoreLayers.erase(it);
1227         delete layer;
1228     }
1229 }
1230 
checkLayer(hwc2_layer_t addr)1231 ExynosLayer *ExynosDisplay::checkLayer(hwc2_layer_t addr) {
1232     ExynosLayer *temp = (ExynosLayer *)addr;
1233     if (!mLayers.isEmpty()) {
1234         for (size_t i = 0; i < mLayers.size(); i++) {
1235             if (mLayers[i] == temp)
1236                 return mLayers[i];
1237         }
1238     }
1239 
1240     if (mIgnoreLayers.size()) {
1241         auto it = std::find(mIgnoreLayers.begin(), mIgnoreLayers.end(), temp);
1242         return (it == mIgnoreLayers.end()) ? NULL : *it;
1243     }
1244 
1245     ALOGE("HWC2 : %s : %d, wrong layer request!", __func__, __LINE__);
1246     return NULL;
1247 }
1248 
checkIgnoreLayers()1249 void ExynosDisplay::checkIgnoreLayers() {
1250     Mutex::Autolock lock(mDRMutex);
1251     for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
1252         ExynosLayer *layer = *it;
1253         if ((layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) == 0) {
1254             mLayers.push_back(layer);
1255             it = mIgnoreLayers.erase(it);
1256             layer->mOverlayInfo &= ~eIgnoreLayer;
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->updateValidateCompositionType(HWC2_COMPOSITION_DEVICE, eIgnoreLayer);
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->getValidateCompositionType() == 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", i,
1705                                  layer->getValidateCompositionType());
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             mLayers[i]->mReleaseFence = -1;
2817         }
2818         config.rel_fence = fence_close(config.rel_fence, this,
2819                    FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB);
2820     }
2821 
2822     // DPU doesn't close acq_fence, HWC should close it.
2823     for (auto &config : mDpuData.configs) {
2824         if (config.acq_fence != -1)
2825             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
2826         config.acq_fence = -1;
2827     }
2828     for (auto &config : mDpuData.rcdConfigs) {
2829         if (config.acq_fence != -1)
2830             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
2831         config.acq_fence = -1;
2832     }
2833     // DPU doesn't close rel_fence of readback buffer, HWC should close it
2834     if (mDpuData.readback_info.rel_fence >= 0) {
2835         mDpuData.readback_info.rel_fence =
2836             fence_close(mDpuData.readback_info.rel_fence, this,
2837                 FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
2838     }
2839 
2840     for (size_t i = 0; i < mLayers.size(); i++) {
2841         if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) ||
2842             (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) ||
2843             (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION))
2844             continue;
2845         if ((mLayers[i]->mWindowIndex < 0) ||
2846             (mLayers[i]->mWindowIndex >= mDpuData.configs.size())) {
2847             errString.appendFormat("%s:: layer[%zu] has invalid window index(%d)\n",
2848                     __func__, i, mLayers[i]->mWindowIndex);
2849             goto err;
2850         }
2851         exynos_win_config_data &config = mDpuData.configs[mLayers[i]->mWindowIndex];
2852         if (mLayers[i]->mOtfMPP != NULL) {
2853             mLayers[i]->mOtfMPP->setHWStateFence(-1);
2854         }
2855         if (mLayers[i]->mM2mMPP != NULL) {
2856             if (mLayers[i]->mM2mMPP->mUseM2MSrcFence)
2857                 mLayers[i]->mReleaseFence = mLayers[i]->mM2mMPP->getSrcReleaseFence(0);
2858             else {
2859                 mLayers[i]->mReleaseFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP,
2860                     hwc_dup(config.rel_fence, this,
2861                         FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER));
2862             }
2863 
2864             mLayers[i]->mM2mMPP->resetSrcReleaseFence();
2865 #ifdef DISABLE_FENCE
2866             mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2867 #else
2868             DISPLAY_LOGD(eDebugFence, "m2m : win_index(%d), releaseFencefd(%d)",
2869                     mLayers[i]->mWindowIndex, config.rel_fence);
2870             if (config.rel_fence > 0) {
2871                 release_fd = config.rel_fence;
2872                 if (release_fd >= 0) {
2873                     setFenceInfo(release_fd, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP,
2874                                  HwcFenceDirection::UPDATE, true);
2875                     mLayers[i]->mM2mMPP->setDstAcquireFence(release_fd);
2876                 } else {
2877                     DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2878                     mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2879                 }
2880             } else {
2881                 mLayers[i]->mM2mMPP->setDstAcquireFence(-1);
2882             }
2883             DISPLAY_LOGD(eDebugFence, "mM2mMPP is used, layer[%zu].releaseFencefd(%d)",
2884                     i, mLayers[i]->mReleaseFence);
2885 #endif
2886         } else {
2887 #ifdef DISABLE_FENCE
2888             mLayers[i]->mReleaseFence = -1;
2889 #else
2890             DISPLAY_LOGD(eDebugFence, "other : win_index(%d), releaseFencefd(%d)",
2891                     mLayers[i]->mWindowIndex, config.rel_fence);
2892             if (config.rel_fence > 0) {
2893                 release_fd = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, config.rel_fence);
2894                 if (release_fd >= 0)
2895                     mLayers[i]->mReleaseFence = release_fd;
2896                 else {
2897                     DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno));
2898                     mLayers[i]->mReleaseFence = -1;
2899                 }
2900             } else {
2901                 mLayers[i]->mReleaseFence = -1;
2902             }
2903             DISPLAY_LOGD(eDebugFence, "Direct overlay layer[%zu].releaseFencefd(%d)",
2904                 i, mLayers[i]->mReleaseFence);
2905 #endif
2906         }
2907     }
2908 
2909     if (mExynosCompositionInfo.mHasCompositionLayer) {
2910         if (mExynosCompositionInfo.mM2mMPP == NULL)
2911         {
2912             errString.appendFormat("There is exynos composition, but m2mMPP is NULL\n");
2913             goto err;
2914         }
2915         if (mUseDpu &&
2916             ((mExynosCompositionInfo.mWindowIndex < 0) ||
2917              (mExynosCompositionInfo.mWindowIndex >= (int32_t)mDpuData.configs.size()))) {
2918             errString.appendFormat("%s:: exynosComposition has invalid window index(%d)\n",
2919                     __func__, mExynosCompositionInfo.mWindowIndex);
2920             goto err;
2921         }
2922         exynos_win_config_data &config = mDpuData.configs[mExynosCompositionInfo.mWindowIndex];
2923         for (int i = mExynosCompositionInfo.mFirstIndex; i <= mExynosCompositionInfo.mLastIndex; i++) {
2924             /* break when only framebuffer target is assigned on ExynosCompositor */
2925             if (i == -1)
2926                 break;
2927 
2928             if (mLayers[i]->mExynosCompositionType != HWC2_COMPOSITION_EXYNOS) {
2929                 errString.appendFormat("%d layer compositionType is not exynos(%d)\n", i, mLayers[i]->mExynosCompositionType);
2930                 goto err;
2931             }
2932 
2933             if (mExynosCompositionInfo.mM2mMPP->mUseM2MSrcFence)
2934                 mLayers[i]->mReleaseFence =
2935                     mExynosCompositionInfo.mM2mMPP->getSrcReleaseFence(i-mExynosCompositionInfo.mFirstIndex);
2936             else {
2937                 mLayers[i]->mReleaseFence =
2938                     hwc_dup(config.rel_fence,
2939                             this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
2940             }
2941 
2942             DISPLAY_LOGD(eDebugFence, "exynos composition layer[%d].releaseFencefd(%d)",
2943                     i, mLayers[i]->mReleaseFence);
2944         }
2945         mExynosCompositionInfo.mM2mMPP->resetSrcReleaseFence();
2946         if(mUseDpu) {
2947 #ifdef DISABLE_FENCE
2948             mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2949 #else
2950             if (config.rel_fence > 0) {
2951                 setFenceInfo(config.rel_fence, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP,
2952                              HwcFenceDirection::UPDATE, true);
2953                 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(config.rel_fence);
2954             } else {
2955                 mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1);
2956             }
2957 #endif
2958         }
2959     }
2960     return 0;
2961 
2962 err:
2963     printDebugInfos(errString);
2964     closeFences();
2965     mDisplayInterface->setForcePanic();
2966     return -EINVAL;
2967 }
2968 
2969 /**
2970  * If display uses outbuf and outbuf is invalid, this function return false.
2971  * Otherwise, this function return true.
2972  * If outbuf is invalid, display should handle fence of layers.
2973  */
checkFrameValidation()2974 bool ExynosDisplay::checkFrameValidation() {
2975     return true;
2976 }
2977 
acceptDisplayChanges()2978 int32_t ExynosDisplay::acceptDisplayChanges() {
2979     int32_t type = 0;
2980     if (mDropFrameDuringResSwitch) {
2981         return HWC2_ERROR_NONE;
2982     }
2983     if (mRenderingState != RENDERING_STATE_VALIDATED) {
2984         DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
2985         return HWC2_ERROR_NOT_VALIDATED;
2986     }
2987 
2988     for (size_t i = 0; i < mLayers.size(); i++) {
2989         if (mLayers[i] != NULL) {
2990             HDEBUGLOGD(eDebugDefault, "%s, Layer %zu : %d, %d", __func__, i,
2991                        mLayers[i]->mExynosCompositionType,
2992                        mLayers[i]->getValidateCompositionType());
2993             type = getLayerCompositionTypeForValidationType(i);
2994 
2995             /* update compositionType
2996              * SF updates their state and doesn't call back into HWC HAL
2997              */
2998             mLayers[i]->mCompositionType = type;
2999             mLayers[i]->mExynosCompositionType = mLayers[i]->getValidateCompositionType();
3000         }
3001         else {
3002             HWC_LOGE(this, "Layer %zu is NULL", i);
3003         }
3004     }
3005     mRenderingState = RENDERING_STATE_ACCEPTED_CHANGE;
3006 
3007     return HWC2_ERROR_NONE;
3008 }
3009 
createLayer(hwc2_layer_t * outLayer)3010 int32_t ExynosDisplay::createLayer(hwc2_layer_t* outLayer) {
3011 
3012     Mutex::Autolock lock(mDRMutex);
3013     if (mPlugState == false) {
3014         DISPLAY_LOGI("%s : skip createLayer. Display is already disconnected", __func__);
3015         return HWC2_ERROR_BAD_DISPLAY;
3016     }
3017 
3018     /* TODO : Implementation here */
3019     ExynosLayer *layer = new ExynosLayer(this);
3020 
3021     /* TODO : Sort sequence should be added to somewhere */
3022     mLayers.add((ExynosLayer*)layer);
3023 
3024     /* TODO : Set z-order to max, check outLayer address? */
3025     layer->setLayerZOrder(1000);
3026 
3027     *outLayer = (hwc2_layer_t)layer;
3028     setGeometryChanged(GEOMETRY_DISPLAY_LAYER_ADDED);
3029 
3030     return HWC2_ERROR_NONE;
3031 }
3032 
getActiveConfig(hwc2_config_t * outConfig)3033 int32_t ExynosDisplay::getActiveConfig(hwc2_config_t* outConfig)
3034 {
3035     Mutex::Autolock lock(mDisplayMutex);
3036     return getActiveConfigInternal(outConfig);
3037 }
3038 
getActiveConfigInternal(hwc2_config_t * outConfig)3039 int32_t ExynosDisplay::getActiveConfigInternal(hwc2_config_t* outConfig)
3040 {
3041     *outConfig = mActiveConfig;
3042 
3043     return HWC2_ERROR_NONE;
3044 }
3045 
getLayerCompositionTypeForValidationType(uint32_t layerIndex)3046 int32_t ExynosDisplay::getLayerCompositionTypeForValidationType(uint32_t layerIndex)
3047 {
3048     int32_t type = -1;
3049 
3050     if (layerIndex >= mLayers.size())
3051     {
3052         DISPLAY_LOGE("invalid layer index (%d)", layerIndex);
3053         return type;
3054     }
3055     if ((mLayers[layerIndex]->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT) &&
3056         (mClientCompositionInfo.mSkipFlag) &&
3057         (mClientCompositionInfo.mFirstIndex <= (int32_t)layerIndex) &&
3058         ((int32_t)layerIndex <= mClientCompositionInfo.mLastIndex)) {
3059         type = HWC2_COMPOSITION_DEVICE;
3060     } else if (mLayers[layerIndex]->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS) {
3061         type = HWC2_COMPOSITION_DEVICE;
3062     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_CURSOR) &&
3063                (mLayers[layerIndex]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)) {
3064         if (mDisplayControl.cursorSupport == true)
3065             type = HWC2_COMPOSITION_CURSOR;
3066         else
3067             type = HWC2_COMPOSITION_DEVICE;
3068     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_SOLID_COLOR) &&
3069                (mLayers[layerIndex]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)) {
3070         type = HWC2_COMPOSITION_SOLID_COLOR;
3071     } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) &&
3072                (mLayers[layerIndex]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)) {
3073         type = HWC2_COMPOSITION_REFRESH_RATE_INDICATOR;
3074     } else {
3075         type = mLayers[layerIndex]->getValidateCompositionType();
3076     }
3077 
3078     return type;
3079 }
3080 
getChangedCompositionTypes(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outTypes)3081 int32_t ExynosDisplay::getChangedCompositionTypes(
3082         uint32_t* outNumElements, hwc2_layer_t* outLayers,
3083         int32_t* /*hwc2_composition_t*/ outTypes) {
3084     if (mDropFrameDuringResSwitch) {
3085         if ((outLayers == NULL) || (outTypes == NULL)) {
3086             *outNumElements = 0;
3087         }
3088         return HWC2_ERROR_NONE;
3089     }
3090 
3091     if (mRenderingState != RENDERING_STATE_VALIDATED) {
3092         DISPLAY_LOGE("%s:: display is not validated : %d", __func__, mRenderingState);
3093         return HWC2_ERROR_NOT_VALIDATED;
3094     }
3095 
3096     uint32_t count = 0;
3097 
3098     auto set_out_param = [](ExynosLayer *layer, int32_t type, uint32_t &count, uint32_t num,
3099                             hwc2_layer_t *out_layers, int32_t *out_types) -> int32_t {
3100         if (type == layer->mCompositionType) {
3101             return 0;
3102         }
3103         if (out_layers == NULL || out_types == NULL) {
3104             count++;
3105         } else {
3106             if (count < num) {
3107                 out_layers[count] = (hwc2_layer_t)layer;
3108                 out_types[count] = type;
3109                 count++;
3110             } else {
3111                 return -1;
3112             }
3113         }
3114         return 0;
3115     };
3116 
3117     int32_t ret = 0;
3118     for (size_t i = 0; i < mLayers.size(); i++) {
3119         DISPLAY_LOGD(eDebugHWC,
3120                      "[%zu] layer: mCompositionType(%d), mValidateCompositionType(%d), "
3121                      "mExynosCompositionType(%d), skipFlag(%d)",
3122                      i, mLayers[i]->mCompositionType, mLayers[i]->getValidateCompositionType(),
3123                      mLayers[i]->mExynosCompositionType, mClientCompositionInfo.mSkipFlag);
3124         if ((ret = set_out_param(mLayers[i], getLayerCompositionTypeForValidationType(i), count,
3125                                  *outNumElements, outLayers, outTypes)) < 0) {
3126             break;
3127         }
3128     }
3129     if (ret == 0) {
3130         for (size_t i = 0; i < mIgnoreLayers.size(); i++) {
3131             DISPLAY_LOGD(eDebugHWC,
3132                          "[%zu] ignore layer: mCompositionType(%d), mValidateCompositionType(%d)",
3133                          i, mIgnoreLayers[i]->mCompositionType,
3134                          mIgnoreLayers[i]->getValidateCompositionType());
3135             if ((ret = set_out_param(mIgnoreLayers[i],
3136                                      mIgnoreLayers[i]->getValidateCompositionType(), count,
3137                                      *outNumElements, outLayers, outTypes)) < 0) {
3138                 break;
3139             }
3140         }
3141     }
3142     if (ret < 0) {
3143         DISPLAY_LOGE("array size is not valid (%d, %d)", count, *outNumElements);
3144         String8 errString;
3145         errString.appendFormat("array size is not valid (%d, %d)", count, *outNumElements);
3146         printDebugInfos(errString);
3147         return ret;
3148     }
3149 
3150     if ((outLayers == NULL) || (outTypes == NULL))
3151         *outNumElements = count;
3152 
3153     return HWC2_ERROR_NONE;
3154 }
3155 
getClientTargetSupport(uint32_t width,uint32_t height,int32_t format,int32_t dataspace)3156 int32_t ExynosDisplay::getClientTargetSupport(uint32_t width, uint32_t height,
3157                                               int32_t /*android_pixel_format_t*/ format,
3158                                               int32_t /*android_dataspace_t*/ dataspace)
3159 {
3160     if (width != mXres)
3161         return HWC2_ERROR_UNSUPPORTED;
3162     if (height != mYres)
3163         return HWC2_ERROR_UNSUPPORTED;
3164     if (format != HAL_PIXEL_FORMAT_RGBA_8888)
3165         return HWC2_ERROR_UNSUPPORTED;
3166     if ((dataspace != HAL_DATASPACE_UNKNOWN) &&
3167         (!mDisplayInterface->supportDataspace(dataspace)))
3168         return HWC2_ERROR_UNSUPPORTED;
3169 
3170     return HWC2_ERROR_NONE;
3171 }
3172 
getColorModes(uint32_t * outNumModes,int32_t * outModes)3173 int32_t ExynosDisplay::getColorModes(uint32_t *outNumModes, int32_t * /*android_color_mode_t*/ outModes)
3174 {
3175     return mDisplayInterface->getColorModes(outNumModes, outModes);
3176 }
3177 
getDisplayAttribute(hwc2_config_t config,int32_t attribute,int32_t * outValue)3178 int32_t ExynosDisplay::getDisplayAttribute(
3179         hwc2_config_t config,
3180         int32_t /*hwc2_attribute_t*/ attribute, int32_t* outValue) {
3181 
3182     switch (attribute) {
3183     case HWC2_ATTRIBUTE_VSYNC_PERIOD:
3184         *outValue = mDisplayConfigs[config].vsyncPeriod;
3185         break;
3186 
3187     case HWC2_ATTRIBUTE_WIDTH:
3188         *outValue = mDisplayConfigs[config].width;
3189         break;
3190 
3191     case HWC2_ATTRIBUTE_HEIGHT:
3192         *outValue = mDisplayConfigs[config].height;
3193         break;
3194 
3195     case HWC2_ATTRIBUTE_DPI_X:
3196         *outValue = mDisplayConfigs[config].Xdpi;
3197         break;
3198 
3199     case HWC2_ATTRIBUTE_DPI_Y:
3200         *outValue = mDisplayConfigs[config].Ydpi;
3201         break;
3202 
3203     case HWC2_ATTRIBUTE_CONFIG_GROUP:
3204         *outValue = mDisplayConfigs[config].groupId;
3205         break;
3206 
3207     default:
3208         ALOGE("unknown display attribute %u", attribute);
3209         return HWC2_ERROR_BAD_CONFIG;
3210     }
3211 
3212     return HWC2_ERROR_NONE;
3213 }
3214 
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)3215 int32_t ExynosDisplay::getDisplayConfigs(
3216         uint32_t* outNumConfigs,
3217         hwc2_config_t* outConfigs) {
3218     return mDisplayInterface->getDisplayConfigs(outNumConfigs, outConfigs);
3219 }
3220 
getDisplayName(uint32_t * outSize,char * outName)3221 int32_t ExynosDisplay::getDisplayName(uint32_t* outSize, char* outName)
3222 {
3223     if (outName == NULL) {
3224         *outSize = mDisplayName.size();
3225         return HWC2_ERROR_NONE;
3226     }
3227 
3228     uint32_t strSize = mDisplayName.size();
3229     if (*outSize < strSize) {
3230         DISPLAY_LOGE("Invalide outSize(%d), mDisplayName.size(%d)",
3231                 *outSize, strSize);
3232         strSize = *outSize;
3233     }
3234     std::strncpy(outName, mDisplayName.c_str(), strSize);
3235     *outSize = strSize;
3236 
3237     return HWC2_ERROR_NONE;
3238 }
3239 
getDisplayRequests(int32_t * outDisplayRequests,uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outLayerRequests)3240 int32_t ExynosDisplay::getDisplayRequests(
3241         int32_t* /*hwc2_display_request_t*/ outDisplayRequests,
3242         uint32_t* outNumElements, hwc2_layer_t* outLayers,
3243         int32_t* /*hwc2_layer_request_t*/ outLayerRequests) {
3244     /*
3245      * This function doesn't check mRenderingState
3246      * This can be called in the below rendering state
3247      * RENDERING_STATE_PRESENTED: when it is called by canSkipValidate()
3248      * RENDERING_STATE_ACCEPTED_CHANGE: when it is called by SF
3249      * RENDERING_STATE_VALIDATED:  when it is called by validateDisplay()
3250      */
3251 
3252     String8 errString;
3253     *outDisplayRequests = 0;
3254 
3255     if (mDropFrameDuringResSwitch) {
3256         if ((outLayers == NULL) || (outLayerRequests == NULL)) {
3257             *outNumElements = 0;
3258         }
3259         return HWC2_ERROR_NONE;
3260     }
3261 
3262     uint32_t requestNum = 0;
3263     if (mClientCompositionInfo.mHasCompositionLayer == true) {
3264         if ((mClientCompositionInfo.mFirstIndex < 0) ||
3265             (mClientCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
3266             (mClientCompositionInfo.mLastIndex < 0) ||
3267             (mClientCompositionInfo.mLastIndex >= (int)mLayers.size())) {
3268             errString.appendFormat("%s:: mClientCompositionInfo.mHasCompositionLayer is true "
3269                     "but index is not valid (firstIndex: %d, lastIndex: %d)\n",
3270                     __func__, mClientCompositionInfo.mFirstIndex,
3271                     mClientCompositionInfo.mLastIndex);
3272             goto err;
3273         }
3274 
3275         for (int32_t i = mClientCompositionInfo.mFirstIndex; i < mClientCompositionInfo.mLastIndex; i++) {
3276             ExynosLayer *layer = mLayers[i];
3277             if (layer->needClearClientTarget()) {
3278                 if ((outLayers != NULL) && (outLayerRequests != NULL)) {
3279                     if (requestNum >= *outNumElements)
3280                         return -1;
3281                     outLayers[requestNum] = (hwc2_layer_t)layer;
3282                     outLayerRequests[requestNum] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET;
3283                 }
3284                 requestNum++;
3285             }
3286         }
3287     }
3288     if ((outLayers == NULL) || (outLayerRequests == NULL))
3289         *outNumElements = requestNum;
3290 
3291     return HWC2_ERROR_NONE;
3292 
3293 err:
3294     printDebugInfos(errString);
3295     *outNumElements = 0;
3296     mDisplayInterface->setForcePanic();
3297     return -EINVAL;
3298 }
3299 
getDisplayType(int32_t * outType)3300 int32_t ExynosDisplay::getDisplayType(
3301         int32_t* /*hwc2_display_type_t*/ outType) {
3302     switch (mType) {
3303     case HWC_DISPLAY_PRIMARY:
3304     case HWC_DISPLAY_EXTERNAL:
3305         *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
3306         return HWC2_ERROR_NONE;
3307     case HWC_DISPLAY_VIRTUAL:
3308         *outType = HWC2_DISPLAY_TYPE_VIRTUAL;
3309         return HWC2_ERROR_NONE;
3310     default:
3311         DISPLAY_LOGE("Invalid display type(%d)", mType);
3312         *outType = HWC2_DISPLAY_TYPE_INVALID;
3313         return HWC2_ERROR_NONE;
3314     }
3315 }
3316 
getDozeSupport(int32_t * outSupport)3317 int32_t ExynosDisplay::getDozeSupport(
3318         int32_t* outSupport) {
3319     if (mDisplayInterface->isDozeModeAvailable()) {
3320         *outSupport = 1;
3321     } else {
3322         *outSupport = 0;
3323     }
3324 
3325     return 0;
3326 }
3327 
getReleaseFences(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outFences)3328 int32_t ExynosDisplay::getReleaseFences(
3329         uint32_t* outNumElements,
3330         hwc2_layer_t* outLayers, int32_t* outFences) {
3331 
3332     if (outNumElements == NULL) {
3333         return HWC2_ERROR_BAD_PARAMETER;
3334     }
3335 
3336     Mutex::Autolock lock(mDisplayMutex);
3337     uint32_t deviceLayerNum = 0;
3338     if (outLayers != NULL && outFences != NULL) {
3339         // second pass call
3340         for (size_t i = 0; i < mLayers.size(); i++) {
3341             if (mLayers[i]->mReleaseFence >= 0) {
3342                 if (deviceLayerNum < *outNumElements) {
3343                     // transfer fence ownership to the caller
3344                     setFenceName(mLayers[i]->mReleaseFence, FENCE_LAYER_RELEASE_DPP);
3345                     outLayers[deviceLayerNum] = (hwc2_layer_t)mLayers[i];
3346                     outFences[deviceLayerNum] = mLayers[i]->mReleaseFence;
3347                     mLayers[i]->mReleaseFence = -1;
3348 
3349                     DISPLAY_LOGD(eDebugHWC, "[%zu] layer deviceLayerNum(%d), release fence: %d", i,
3350                                  deviceLayerNum, outFences[deviceLayerNum]);
3351                 } else {
3352                     // *outNumElements is not from the first pass call.
3353                     DISPLAY_LOGE("%s: outNumElements %d too small", __func__, *outNumElements);
3354                     return HWC2_ERROR_BAD_PARAMETER;
3355                 }
3356                 deviceLayerNum++;
3357             }
3358         }
3359     } else {
3360         // first pass call
3361         for (size_t i = 0; i < mLayers.size(); i++) {
3362             if (mLayers[i]->mReleaseFence >= 0) {
3363                 deviceLayerNum++;
3364             }
3365         }
3366     }
3367     *outNumElements = deviceLayerNum;
3368 
3369     return 0;
3370 }
3371 
canSkipValidate()3372 int32_t ExynosDisplay::canSkipValidate() {
3373     if (exynosHWCControl.skipResourceAssign == 0)
3374         return SKIP_ERR_CONFIG_DISABLED;
3375 
3376     /* This is first frame. validateDisplay can't be skipped */
3377     if (mRenderingState == RENDERING_STATE_NONE)
3378         return SKIP_ERR_FIRST_FRAME;
3379 
3380     if (mDevice->mGeometryChanged != 0) {
3381         /* validateDisplay() should be called */
3382         return SKIP_ERR_GEOMETRY_CHAGNED;
3383     } else {
3384         for (uint32_t i = 0; i < mLayers.size(); i++) {
3385             if (getLayerCompositionTypeForValidationType(i) ==
3386                     HWC2_COMPOSITION_CLIENT) {
3387                 return SKIP_ERR_HAS_CLIENT_COMP;
3388             }
3389         }
3390 
3391         if ((mClientCompositionInfo.mSkipStaticInitFlag == true) &&
3392             (mClientCompositionInfo.mSkipFlag == true)) {
3393             if (skipStaticLayerChanged(mClientCompositionInfo) == true)
3394                 return SKIP_ERR_SKIP_STATIC_CHANGED;
3395         }
3396 
3397         if (mClientCompositionInfo.mHasCompositionLayer &&
3398             mClientCompositionInfo.mTargetBuffer == NULL) {
3399             return SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER;
3400         }
3401 
3402         /*
3403          * If there is hwc2_layer_request_t
3404          * validateDisplay() can't be skipped
3405          */
3406         int32_t displayRequests = 0;
3407         uint32_t outNumRequests = 0;
3408         if ((getDisplayRequests(&displayRequests, &outNumRequests, NULL, NULL) != NO_ERROR) ||
3409             (outNumRequests != 0))
3410             return SKIP_ERR_HAS_REQUEST;
3411     }
3412     return NO_ERROR;
3413 }
3414 
isFullScreenComposition()3415 bool ExynosDisplay::isFullScreenComposition() {
3416     hwc_rect_t dispRect = { INT_MAX, INT_MAX, 0, 0 };
3417     for (auto layer : mLayers) {
3418         auto &r = layer->mDisplayFrame;
3419 
3420         if (r.top < dispRect.top)
3421             dispRect.top = r.top;
3422         if (r.left < dispRect.left)
3423             dispRect.left = r.left;
3424         if (r.bottom > dispRect.bottom)
3425             dispRect.bottom = r.bottom;
3426         if (r.right > dispRect.right)
3427             dispRect.right = r.right;
3428     }
3429 
3430     if ((dispRect.right != mXres) || (dispRect.bottom != mYres)) {
3431         ALOGD("invalid displayFrame disp=[%d %d %d %d] expected=%dx%d",
3432                 dispRect.left, dispRect.top, dispRect.right, dispRect.bottom,
3433                 mXres, mYres);
3434         return false;
3435     }
3436 
3437     return true;
3438 }
3439 
dumpBuffer(const String8 & prefix,const exynos_image & image,std::ofstream & configFile)3440 void dumpBuffer(const String8& prefix, const exynos_image& image, std::ofstream& configFile) {
3441     ATRACE_NAME(prefix.c_str());
3442     if (image.bufferHandle == nullptr) {
3443         ALOGE("%s: Buffer handle for %s is NULL", __func__, prefix.c_str());
3444         return;
3445     }
3446     ALOGI("%s: dumping buffer for %s", __func__, prefix.c_str());
3447 
3448     bool failFenceSync = false;
3449     String8 infoDump;
3450     if (image.acquireFenceFd > 0 && sync_wait(image.acquireFenceFd, 1000) < 0) {
3451         infoDump.appendFormat("Failed to sync acquire fence\n");
3452         ALOGE("%s: Failed to wait acquire fence %d, errno=(%d, %s)", __func__, image.acquireFenceFd,
3453               errno, strerror(errno));
3454         failFenceSync = true;
3455     }
3456     if (image.releaseFenceFd > 0 && sync_wait(image.releaseFenceFd, 1000) < 0) {
3457         infoDump.appendFormat("Failed to sync release fence\n");
3458 
3459         ALOGE("%s: Failed to wait release fence %d, errno=(%d, %s)", __func__, image.releaseFenceFd,
3460               errno, strerror(errno));
3461         failFenceSync = true;
3462     }
3463 
3464     VendorGraphicBufferMeta gmeta(image.bufferHandle);
3465     String8 infoPath = String8::format("%s/%s-info.txt", kBufferDumpPath, prefix.c_str());
3466     std::ofstream infoFile(infoPath.c_str());
3467     if (!infoFile) {
3468         ALOGE("%s: failed to open file %s", __func__, infoPath.c_str());
3469         return;
3470     }
3471 
3472     // TODO(b/261232489): Fix fence sync errors
3473     // We currently ignore the fence errors and just dump the buffers
3474 
3475     // dump buffer info
3476     dumpExynosImage(infoDump, image);
3477     infoDump.appendFormat("\nfd[%d, %d, %d] size[%d, %d, %d]\n", gmeta.fd, gmeta.fd1, gmeta.fd2,
3478                           gmeta.size, gmeta.size1, gmeta.size2);
3479     infoDump.appendFormat(" offset[%d, %d, %d] format:%d framework_format:%d\n", gmeta.offset,
3480                           gmeta.offset1, gmeta.offset2, gmeta.format, gmeta.frameworkFormat);
3481     infoDump.appendFormat(" width:%d height:%d stride:%d vstride:%d\n", gmeta.width, gmeta.height,
3482                           gmeta.stride, gmeta.vstride);
3483     infoDump.appendFormat(" producer: 0x%" PRIx64 " consumer: 0x%" PRIx64 " flags: 0x%" PRIx32 "\n",
3484                           gmeta.producer_usage, gmeta.consumer_usage, gmeta.flags);
3485     infoFile << infoDump << std::endl;
3486 
3487     String8 bufferPath =
3488             String8::format("%s/%s-%s.raw", kBufferDumpPath, prefix.c_str(),
3489                             getFormatStr(image.format, image.compressionInfo.type).c_str());
3490     std::ofstream bufferFile(bufferPath.c_str(), std::ios::binary);
3491     if (!bufferFile) {
3492         ALOGE("%s: failed to open file %s", __func__, bufferPath.c_str());
3493         return;
3494     }
3495 
3496     // dump info that can be loaded by hwc-tester
3497     configFile << "buffers {\n";
3498     configFile << "    key: \"" << prefix << "\"\n";
3499     configFile << "    format: " << getFormatStr(image.format, image.compressionInfo.type) << "\n";
3500     configFile << "    width: " << gmeta.width << "\n";
3501     configFile << "    height: " << gmeta.height << "\n";
3502     auto usage = gmeta.producer_usage | gmeta.consumer_usage;
3503     configFile << "    usage: 0x" << std::hex << usage << std::dec << "\n";
3504     configFile << "    filepath: \"" << bufferPath << "\"\n";
3505     configFile << "}\n" << std::endl;
3506 
3507     int bufferNumber = getBufferNumOfFormat(image.format, image.compressionInfo.type);
3508     for (int i = 0; i < bufferNumber; ++i) {
3509         if (gmeta.fds[i] <= 0) {
3510             ALOGE("%s: gmeta.fds[%d]=%d is invalid", __func__, i, gmeta.fds[i]);
3511             continue;
3512         }
3513         if (gmeta.sizes[i] <= 0) {
3514             ALOGE("%s: gmeta.sizes[%d]=%d is invalid", __func__, i, gmeta.sizes[i]);
3515             continue;
3516         }
3517         auto addr = mmap(0, gmeta.sizes[i], PROT_READ | PROT_WRITE, MAP_SHARED, gmeta.fds[i], 0);
3518         if (addr != MAP_FAILED && addr != NULL) {
3519             bufferFile.write(static_cast<char*>(addr), gmeta.sizes[i]);
3520             munmap(addr, gmeta.sizes[i]);
3521         } else {
3522             ALOGE("%s: failed to mmap fds[%d]:%d", __func__, i, gmeta.fds[i]);
3523         }
3524     }
3525 }
3526 
dumpAllBuffers()3527 void ExynosDisplay::dumpAllBuffers() {
3528     ATRACE_CALL();
3529     // dump layers info
3530     String8 infoPath = String8::format("%s/%03d-display-info.txt", kBufferDumpPath, mBufferDumpNum);
3531     std::ofstream infoFile(infoPath.c_str());
3532     if (!infoFile) {
3533         DISPLAY_LOGE("%s: failed to open file %s", __func__, infoPath.c_str());
3534         ++mBufferDumpNum;
3535         return;
3536     }
3537     String8 displayDump;
3538     dumpLocked(displayDump);
3539     infoFile << displayDump << std::endl;
3540 
3541     // dump buffer contents & infos
3542     std::vector<String8> allLayerKeys;
3543     String8 testerConfigPath =
3544             String8::format("%s/%03d-hwc-tester-config.textproto", kBufferDumpPath, mBufferDumpNum);
3545     std::ofstream configFile(testerConfigPath.c_str());
3546     configFile << std::string(15, '#')
3547                << " You can load this config file using hwc-tester to reproduce this frame "
3548                << std::string(15, '#') << std::endl;
3549     {
3550         std::scoped_lock lock(mDRMutex);
3551         for (int i = 0; i < mLayers.size(); ++i) {
3552             String8 prefix = String8::format("%03d-%d-src", mBufferDumpNum, i);
3553             dumpBuffer(prefix, mLayers[i]->mSrcImg, configFile);
3554             if (mLayers[i]->mM2mMPP != nullptr) {
3555                 String8 midPrefix = String8::format("%03d-%d-mid", mBufferDumpNum, i);
3556                 exynos_image image = mLayers[i]->mMidImg;
3557                 mLayers[i]->mM2mMPP->getDstImageInfo(&image);
3558                 dumpBuffer(midPrefix, image, configFile);
3559             }
3560             configFile << "layers {\n";
3561             configFile << "    key: \"" << prefix << "\"\n";
3562             configFile << "    composition: "
3563                        << AidlComposer3::toString(static_cast<AidlComposer3::Composition>(
3564                                   mLayers[i]->mRequestedCompositionType))
3565                        << "\n";
3566             configFile << "    source_crop: {\n";
3567             configFile << "        left: " << mLayers[i]->mPreprocessedInfo.sourceCrop.left << "\n";
3568             configFile << "        top: " << mLayers[i]->mPreprocessedInfo.sourceCrop.top << "\n";
3569             configFile << "        right: " << mLayers[i]->mPreprocessedInfo.sourceCrop.right
3570                        << "\n";
3571             configFile << "        bottom: " << mLayers[i]->mPreprocessedInfo.sourceCrop.bottom
3572                        << "\n";
3573             configFile << "    }\n";
3574             configFile << "    display_frame: {\n";
3575             configFile << "        left: " << mLayers[i]->mPreprocessedInfo.displayFrame.left
3576                        << "\n";
3577             configFile << "        top: " << mLayers[i]->mPreprocessedInfo.displayFrame.top << "\n";
3578             configFile << "        right: " << mLayers[i]->mPreprocessedInfo.displayFrame.right
3579                        << "\n";
3580             configFile << "        bottom: " << mLayers[i]->mPreprocessedInfo.displayFrame.bottom
3581                        << "\n";
3582             configFile << "    }\n";
3583             configFile << "    dataspace: "
3584                        << AidlCommon::toString(
3585                                   static_cast<AidlCommon::Dataspace>(mLayers[i]->mDataSpace))
3586                        << "\n";
3587             configFile << "    blend: "
3588                        << AidlCommon::toString(
3589                                   static_cast<AidlCommon::BlendMode>(mLayers[i]->mBlending))
3590                        << "\n";
3591             configFile << "    transform: "
3592                        << AidlCommon::toString(
3593                                   static_cast<AidlCommon::Transform>(mLayers[i]->mTransform))
3594                        << "\n";
3595             configFile << "    plane_alpha: " << mLayers[i]->mPlaneAlpha << "\n";
3596             configFile << "    z_order: " << mLayers[i]->mZOrder << "\n";
3597             if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_SOLID_COLOR) {
3598                 configFile << "    color: {\n";
3599                 configFile << "        r: " << mLayers[i]->mColor.r << "\n";
3600                 configFile << "        g: " << mLayers[i]->mColor.g << "\n";
3601                 configFile << "        b: " << mLayers[i]->mColor.b << "\n";
3602                 configFile << "        a: " << mLayers[i]->mColor.a << "\n";
3603                 configFile << "    }\n";
3604             } else if (mLayers[i]->mSrcImg.bufferHandle != nullptr) {
3605                 configFile << "    buffer_key: \"" << prefix << "\"\n";
3606             }
3607             configFile << "}\n" << std::endl;
3608             allLayerKeys.push_back(prefix);
3609         }
3610     }
3611 
3612     if (mClientCompositionInfo.mHasCompositionLayer) {
3613         String8 prefix = String8::format("%03d-client-target", mBufferDumpNum);
3614         exynos_image src, dst;
3615         setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src, &dst);
3616         dumpBuffer(prefix, src, configFile);
3617     }
3618 
3619     configFile << "timelines {\n";
3620     configFile << "    display_id: " << mDisplayId << "\n";
3621     configFile << "    width: " << mXres << "\n";
3622     configFile << "    height: " << mYres << "\n";
3623     configFile << "    color_mode: "
3624                << AidlComposer3::toString(static_cast<AidlComposer3::ColorMode>(mColorMode))
3625                << "\n";
3626     configFile << std::endl;
3627     for (auto& layerKey : allLayerKeys) {
3628         configFile << "    layers: {\n";
3629         configFile << "        layer_key: \"" << layerKey << "\"\n";
3630         configFile << "    }\n";
3631     }
3632     configFile << "}" << std::endl;
3633 
3634     ++mBufferDumpNum;
3635 }
3636 
presentDisplay(int32_t * outRetireFence)3637 int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
3638     DISPLAY_ATRACE_CALL();
3639     gettimeofday(&updateTimeInfo.lastPresentTime, NULL);
3640 
3641     const bool mixedComposition = isMixedComposition();
3642     // store this once here for the whole frame so it's consistent
3643     mUsePowerHints = usePowerHintSession();
3644     if (mUsePowerHints) {
3645         // adds + removes the tid for adpf tracking
3646         mPowerHalHint.trackThisThread();
3647         mPresentStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
3648         if (!mValidateStartTime.has_value()) {
3649             mValidationDuration = std::nullopt;
3650             // load target time here if validation was skipped
3651             mExpectedPresentTime = getExpectedPresentTime(mPresentStartTime);
3652             auto target = min(mExpectedPresentTime - mPresentStartTime,
3653                               static_cast<nsecs_t>(mVsyncPeriod));
3654             mPowerHalHint.signalTargetWorkDuration(target);
3655             // if we did not validate (have not sent hint yet) and have data for this case
3656             std::optional<nsecs_t> predictedDuration = getPredictedDuration(false);
3657             if (predictedDuration.has_value()) {
3658                 mPowerHalHint.signalActualWorkDuration(*predictedDuration);
3659             }
3660         }
3661         mRetireFenceWaitTime = std::nullopt;
3662         mValidateStartTime = std::nullopt;
3663     }
3664 
3665     int ret = HWC2_ERROR_NONE;
3666     String8 errString;
3667     thread_local bool setTaskProfileDone = false;
3668 
3669     if (setTaskProfileDone == false) {
3670         if (!SetTaskProfiles(gettid(), {"SFMainPolicy"})) {
3671             ALOGW("Failed to add `%d` into SFMainPolicy", gettid());
3672         }
3673         setTaskProfileDone = true;
3674     }
3675 
3676     Mutex::Autolock lock(mDisplayMutex);
3677 
3678     if (!mHpdStatus) {
3679         ALOGD("presentDisplay: drop frame: mHpdStatus == false");
3680     }
3681 
3682     mDropFrameDuringResSwitch =
3683             (mGeometryChanged & GEOMETRY_DISPLAY_RESOLUTION_CHANGED) && !isFullScreenComposition();
3684     if (mDropFrameDuringResSwitch) {
3685         ALOGD("presentDisplay: drop invalid frame during resolution switch");
3686     }
3687 
3688     if (!mHpdStatus || mDropFrameDuringResSwitch || mPauseDisplay || mDevice->isInTUI()) {
3689         closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3690         *outRetireFence = -1;
3691         mRenderingState = RENDERING_STATE_PRESENTED;
3692         applyExpectedPresentTime();
3693         return ret;
3694     }
3695 
3696     /*
3697      * buffer handle, dataspace were set by setClientTarget() after validateDisplay
3698      * ExynosImage should be set again according to changed handle and dataspace
3699      */
3700     exynos_image src_img;
3701     exynos_image dst_img;
3702     setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
3703     mClientCompositionInfo.setExynosImage(src_img, dst_img);
3704     mClientCompositionInfo.setExynosMidImage(dst_img);
3705 
3706     funcReturnCallback presentRetCallback([&]() {
3707         if (ret != HWC2_ERROR_NOT_VALIDATED)
3708             presentPostProcessing();
3709     });
3710 
3711     if (mSkipFrame) {
3712         ALOGI("[%d] presentDisplay is skipped by mSkipFrame", mDisplayId);
3713         closeFencesForSkipFrame(RENDERING_STATE_PRESENTED);
3714         setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE);
3715         *outRetireFence = -1;
3716         for (size_t i=0; i < mLayers.size(); i++) {
3717             mLayers[i]->mReleaseFence = -1;
3718         }
3719         if (mRenderingState == RENDERING_STATE_NONE) {
3720             ALOGD("\tThis is the first frame after power on");
3721             ret = HWC2_ERROR_NONE;
3722         } else {
3723             ALOGD("\tThis is the second frame after power on");
3724             ret = HWC2_ERROR_NOT_VALIDATED;
3725         }
3726         mRenderingState = RENDERING_STATE_PRESENTED;
3727         mDevice->onRefresh(mDisplayId);
3728         return ret;
3729     }
3730 
3731     tryUpdateBtsFromOperationRate(true);
3732 
3733     if (mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE) {
3734         /*
3735          * presentDisplay() can be called before validateDisplay()
3736          * when HWC2_CAPABILITY_SKIP_VALIDATE is supported
3737          */
3738 #ifdef HWC_NO_SUPPORT_SKIP_VALIDATE
3739         DISPLAY_LOGE("%s:: Skip validate is not supported. Invalid rendering state : %d", __func__, mRenderingState);
3740         goto err;
3741 #endif
3742         if ((mRenderingState != RENDERING_STATE_NONE) &&
3743             (mRenderingState != RENDERING_STATE_PRESENTED)) {
3744             DISPLAY_LOGE("%s:: invalid rendering state : %d", __func__, mRenderingState);
3745             goto err;
3746         }
3747 
3748         if (mDevice->canSkipValidate() == false)
3749             goto not_validated;
3750         else {
3751             for (size_t i=0; i < mLayers.size(); i++) {
3752                 // Layer's acquire fence from SF
3753                 mLayers[i]->setSrcAcquireFence();
3754             }
3755             DISPLAY_LOGD(eDebugSkipValidate, "validate is skipped");
3756         }
3757 
3758         if (updateColorConversionInfo() != NO_ERROR) {
3759             ALOGE("%s:: updateColorConversionInfo() fail, ret(%d)",
3760                     __func__, ret);
3761         }
3762         if (mDisplayControl.earlyStartMPP == true) {
3763             /*
3764              * HWC should update performanceInfo when validate is skipped
3765              * HWC excludes the layer from performance calculation
3766              * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
3767              * Therefore performanceInfo should be calculated again if the buffer is updated.
3768              */
3769             if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
3770                 DISPLAY_LOGE("deliverPerformanceInfo() error (%d) in validateSkip case", ret);
3771             }
3772             startPostProcessing();
3773         }
3774     }
3775     mRetireFenceAcquireTime = std::nullopt;
3776     mDpuData.reset();
3777 
3778     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
3779         if ((ret = doDisplayConfigPostProcess(mDevice)) != NO_ERROR) {
3780             DISPLAY_LOGE("doDisplayConfigPostProcess error (%d)", ret);
3781         }
3782     }
3783 
3784     if (updatePresentColorConversionInfo() != NO_ERROR) {
3785         ALOGE("%s:: updatePresentColorConversionInfo() fail, ret(%d)",
3786                 __func__, ret);
3787     }
3788 
3789     if ((mLayers.size() == 0) &&
3790         (mType != HWC_DISPLAY_VIRTUAL)) {
3791         ALOGI("%s:: layer size is 0", __func__);
3792         clearDisplay();
3793         *outRetireFence = -1;
3794         mLastRetireFence = fence_close(mLastRetireFence, this,
3795                 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3796         mRenderingState = RENDERING_STATE_PRESENTED;
3797         ret = 0;
3798         return ret;
3799     }
3800 
3801     if (!checkFrameValidation()) {
3802         ALOGW("%s: checkFrameValidation fail", __func__);
3803         clearDisplay();
3804         *outRetireFence = -1;
3805         mLastRetireFence = fence_close(mLastRetireFence, this,
3806                 FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3807         mRenderingState = RENDERING_STATE_PRESENTED;
3808         return ret;
3809     }
3810 
3811     if ((mDisplayControl.earlyStartMPP == false) &&
3812         ((ret = doExynosComposition()) != NO_ERROR)) {
3813         errString.appendFormat("exynosComposition fail (%d)\n", ret);
3814         goto err;
3815     }
3816 
3817     // loop for all layer
3818     for (size_t i=0; i < mLayers.size(); i++) {
3819         /* mAcquireFence is updated, Update image info */
3820         struct exynos_image srcImg, dstImg, midImg;
3821         mLayers[i]->setSrcExynosImage(&srcImg);
3822         mLayers[i]->setDstExynosImage(&dstImg);
3823         mLayers[i]->setExynosImage(srcImg, dstImg);
3824 
3825         if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
3826             mLayers[i]->mReleaseFence = -1;
3827             mLayers[i]->mAcquireFence =
3828                 fence_close(mLayers[i]->mAcquireFence, this,
3829                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3830         } else if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_EXYNOS) {
3831             continue;
3832         } else {
3833             if (mLayers[i]->mOtfMPP != NULL) {
3834                 mLayers[i]->mOtfMPP->requestHWStateChange(MPP_HW_STATE_RUNNING);
3835             }
3836 
3837             if ((mDisplayControl.earlyStartMPP == false) &&
3838                 (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
3839                 (mLayers[i]->mM2mMPP != NULL)) {
3840                 ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
3841                 midImg = mLayers[i]->mMidImg;
3842                 m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
3843                 if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
3844                     HWC_LOGE(this, "%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
3845                             __func__, i, ret);
3846                     errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
3847                             __func__, i, ret);
3848                     goto err;
3849                 } else {
3850                     /* This should be closed by lib for each resource */
3851                     mLayers[i]->mAcquireFence = -1;
3852                 }
3853             }
3854         }
3855     }
3856 
3857     if ((ret = setWinConfigData()) != NO_ERROR) {
3858         errString.appendFormat("setWinConfigData fail (%d)\n", ret);
3859         goto err;
3860     }
3861 
3862     if ((ret = handleStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
3863         mClientCompositionInfo.mSkipStaticInitFlag = false;
3864         errString.appendFormat("handleStaticLayers error\n");
3865         goto err;
3866     }
3867 
3868     if (shouldSignalNonIdle()) {
3869         mPowerHalHint.signalNonIdle();
3870     }
3871 
3872     if (!checkUpdateRRIndicatorOnly()) {
3873         if (mRefreshRateIndicatorHandler) {
3874             mRefreshRateIndicatorHandler->checkOnPresentDisplay();
3875         }
3876     }
3877 
3878     handleWindowUpdate();
3879 
3880     setDisplayWinConfigData();
3881 
3882     if ((ret = deliverWinConfigData()) != NO_ERROR) {
3883         HWC_LOGE(this, "%s:: fail to deliver win_config (%d)", __func__, ret);
3884         if (mDpuData.retire_fence > 0)
3885             fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3886         mDpuData.retire_fence = -1;
3887     }
3888 
3889     setReleaseFences();
3890 
3891     if (mBufferDumpNum < mBufferDumpCount) {
3892         dumpAllBuffers();
3893     }
3894 
3895     if (mDpuData.retire_fence != -1) {
3896 #ifdef DISABLE_FENCE
3897         if (mDpuData.retire_fence >= 0)
3898             fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3899         *outRetireFence = -1;
3900 #else
3901         *outRetireFence =
3902             hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, mDpuData.retire_fence);
3903 #endif
3904         setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_LAYER,
3905                      HwcFenceDirection::TO);
3906     } else
3907         *outRetireFence = -1;
3908 
3909     /* Update last retire fence */
3910     mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
3911     mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, true);
3912     setFenceName(mLastRetireFence, FENCE_RETIRE);
3913 
3914     increaseMPPDstBufIndex();
3915 
3916     /* Check all of acquireFence are closed */
3917     for (size_t i=0; i < mLayers.size(); i++) {
3918         if (mLayers[i]->mAcquireFence != -1) {
3919             DISPLAY_LOGE("layer[%zu] fence(%d) type(%d, %d, %d) is not closed", i,
3920                          mLayers[i]->mAcquireFence, mLayers[i]->mCompositionType,
3921                          mLayers[i]->mExynosCompositionType,
3922                          mLayers[i]->getValidateCompositionType());
3923             if (mLayers[i]->mM2mMPP != NULL)
3924                 DISPLAY_LOGE("\t%s is assigned", mLayers[i]->mM2mMPP->mName.c_str());
3925             if (mLayers[i]->mAcquireFence > 0)
3926                 fence_close(mLayers[i]->mAcquireFence, this,
3927                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
3928             mLayers[i]->mAcquireFence = -1;
3929         }
3930     }
3931     if (mExynosCompositionInfo.mAcquireFence >= 0) {
3932         DISPLAY_LOGE("mExynosCompositionInfo mAcquireFence(%d) is not initialized", mExynosCompositionInfo.mAcquireFence);
3933         fence_close(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
3934         mExynosCompositionInfo.mAcquireFence = -1;
3935     }
3936     if (mClientCompositionInfo.mAcquireFence >= 0) {
3937         DISPLAY_LOGE("mClientCompositionInfo mAcquireFence(%d) is not initialized", mClientCompositionInfo.mAcquireFence);
3938         fence_close(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
3939         mClientCompositionInfo.mAcquireFence = -1;
3940     }
3941 
3942     /* All of release fences are tranferred */
3943     for (size_t i=0; i < mLayers.size(); i++) {
3944         setFenceInfo(mLayers[i]->mReleaseFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER,
3945                      HwcFenceDirection::TO);
3946     }
3947 
3948     doPostProcessing();
3949 
3950     if (!mDevice->validateFences(this)) {
3951         ALOGE("%s:: validate fence failed.", __func__);
3952     }
3953 
3954     mDpuData.reset();
3955 
3956     mRenderingState = RENDERING_STATE_PRESENTED;
3957 
3958     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
3959         /* Do not update mVsyncPeriod */
3960         updateInternalDisplayConfigVariables(mDesiredConfig, false);
3961     }
3962 
3963     if (mUsePowerHints) {
3964         // update the "last present" now that we know for sure when this frame is due
3965         mLastExpectedPresentTime = mExpectedPresentTime;
3966 
3967         // we add an offset here to keep the flinger and HWC error terms roughly the same
3968         static const constexpr std::chrono::nanoseconds kFlingerOffset = 300us;
3969         nsecs_t now = systemTime() + kFlingerOffset.count();
3970 
3971         updateAverages(now);
3972         nsecs_t duration = now - mPresentStartTime;
3973         if (mRetireFenceWaitTime.has_value() && mRetireFenceAcquireTime.has_value()) {
3974             duration = now - *mRetireFenceAcquireTime + *mRetireFenceWaitTime - mPresentStartTime;
3975         }
3976         mPowerHalHint.signalActualWorkDuration(duration + mValidationDuration.value_or(0));
3977     }
3978 
3979     mPriorFrameMixedComposition = mixedComposition;
3980 
3981     tryUpdateBtsFromOperationRate(false);
3982 
3983     return ret;
3984 err:
3985     printDebugInfos(errString);
3986     closeFences();
3987     *outRetireFence = -1;
3988     mLastRetireFence = -1;
3989     mRenderingState = RENDERING_STATE_PRESENTED;
3990     setGeometryChanged(GEOMETRY_ERROR_CASE);
3991 
3992     mLastDpuData.reset();
3993 
3994     mClientCompositionInfo.mSkipStaticInitFlag = false;
3995     mExynosCompositionInfo.mSkipStaticInitFlag = false;
3996 
3997     mDpuData.reset();
3998 
3999     if (!mDevice->validateFences(this)) {
4000         ALOGE("%s:: validate fence failed.", __func__);
4001     }
4002     mDisplayInterface->setForcePanic();
4003 
4004     ret = -EINVAL;
4005     return ret;
4006 
4007 not_validated:
4008     DISPLAY_LOGD(eDebugSkipValidate, "display need validate");
4009     mRenderingState = RENDERING_STATE_NONE;
4010     ret = HWC2_ERROR_NOT_VALIDATED;
4011     return ret;
4012 }
4013 
presentPostProcessing()4014 int32_t ExynosDisplay::presentPostProcessing()
4015 {
4016     setReadbackBufferInternal(NULL, -1, false);
4017     if (mDpuData.enable_readback)
4018         mDevice->signalReadbackDone();
4019     mDpuData.enable_readback = false;
4020 
4021     for (auto it : mIgnoreLayers) {
4022         /*
4023          * Directly close without counting down
4024          * because it was not counted by validate
4025          */
4026         if (it->mAcquireFence > 0) {
4027             close(it->mAcquireFence);
4028         }
4029         it->mAcquireFence = -1;
4030     }
4031     return NO_ERROR;
4032 }
4033 
setActiveConfig(hwc2_config_t config)4034 int32_t ExynosDisplay::setActiveConfig(hwc2_config_t config)
4035 {
4036     Mutex::Autolock lock(mDisplayMutex);
4037     DISPLAY_LOGD(eDebugDisplayConfig, "%s:: config(%d)", __func__, config);
4038     return setActiveConfigInternal(config, false);
4039 }
4040 
setActiveConfigInternal(hwc2_config_t config,bool force)4041 int32_t ExynosDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
4042     if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
4043 
4044     if (!force && needNotChangeConfig(config)) {
4045         ALOGI("skip same config %d (force %d)", config, force);
4046         return HWC2_ERROR_NONE;
4047     }
4048 
4049     DISPLAY_LOGD(eDebugDisplayConfig, "(current %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", mActiveConfig,
4050             mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
4051     DISPLAY_LOGD(eDebugDisplayConfig, "(requested %d) : %dx%d, %dms, %d Xdpi, %d Ydpi", config,
4052             mDisplayConfigs[config].width, mDisplayConfigs[config].height, mDisplayConfigs[config].vsyncPeriod,
4053             mDisplayConfigs[config].Xdpi, mDisplayConfigs[config].Ydpi);
4054 
4055     if (mDisplayInterface->setActiveConfig(config) < 0) {
4056         ALOGE("%s bad config request", __func__);
4057         return HWC2_ERROR_BAD_CONFIG;
4058     }
4059 
4060     if ((mXres != mDisplayConfigs[config].width) ||
4061         (mYres != mDisplayConfigs[config].height)) {
4062         mRenderingState = RENDERING_STATE_NONE;
4063         setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
4064     }
4065 
4066     updateInternalDisplayConfigVariables(config);
4067     return HWC2_ERROR_NONE;
4068 }
4069 
setClientTarget(buffer_handle_t target,int32_t acquireFence,int32_t dataspace)4070 int32_t ExynosDisplay::setClientTarget(
4071         buffer_handle_t target,
4072         int32_t acquireFence, int32_t /*android_dataspace_t*/ dataspace) {
4073     buffer_handle_t handle = NULL;
4074     if (target != NULL)
4075         handle = target;
4076 
4077 #ifdef DISABLE_FENCE
4078     if (acquireFence >= 0)
4079         fence_close(acquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
4080     acquireFence = -1;
4081 #endif
4082     acquireFence = hwcCheckFenceDebug(this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, acquireFence);
4083     if (handle == NULL) {
4084         DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget is NULL, skipStaic (%d)",
4085                 mClientCompositionInfo.mSkipFlag);
4086         if (mClientCompositionInfo.mSkipFlag == false) {
4087             DISPLAY_LOGE("ClientTarget is NULL");
4088             DISPLAY_LOGE("\t%s:: mRenderingState(%d)",__func__, mRenderingState);
4089         }
4090     } else {
4091         VendorGraphicBufferMeta gmeta(handle);
4092 
4093         DISPLAY_LOGD(eDebugOverlaySupported, "ClientTarget handle: %p [fd: %d, %d, %d]",
4094                 handle, gmeta.fd, gmeta.fd1, gmeta.fd2);
4095         if ((mClientCompositionInfo.mSkipFlag == true) &&
4096                 ((mClientCompositionInfo.mLastWinConfigData.fd_idma[0] != gmeta.fd) ||
4097                  (mClientCompositionInfo.mLastWinConfigData.fd_idma[1] != gmeta.fd1) ||
4098                  (mClientCompositionInfo.mLastWinConfigData.fd_idma[2] != gmeta.fd2))) {
4099             String8 errString;
4100             DISPLAY_LOGE("skip flag is enabled but buffer is updated lastConfig[%d, %d, %d], handle[%d, %d, %d]\n",
4101                     mClientCompositionInfo.mLastWinConfigData.fd_idma[0],
4102                     mClientCompositionInfo.mLastWinConfigData.fd_idma[1],
4103                     mClientCompositionInfo.mLastWinConfigData.fd_idma[2],
4104                     gmeta.fd, gmeta.fd1, gmeta.fd2);
4105             DISPLAY_LOGE("last win config");
4106             for (size_t i = 0; i < mLastDpuData.configs.size(); i++) {
4107                 errString.appendFormat("config[%zu]\n", i);
4108                 dumpConfig(errString, mLastDpuData.configs[i]);
4109                 DISPLAY_LOGE("\t%s", errString.c_str());
4110                 errString.clear();
4111             }
4112             errString.appendFormat("%s:: skip flag is enabled but buffer is updated\n",
4113                     __func__);
4114             printDebugInfos(errString);
4115         }
4116     }
4117     mClientCompositionInfo.setTargetBuffer(this, handle, acquireFence, (android_dataspace)dataspace);
4118     setFenceInfo(acquireFence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, HwcFenceDirection::FROM);
4119 
4120     if (handle) {
4121         mClientCompositionInfo.mCompressionInfo = getCompressionInfo(handle);
4122         mExynosCompositionInfo.mCompressionInfo = getCompressionInfo(handle);
4123     }
4124 
4125     return 0;
4126 }
4127 
setColorTransform(const float * matrix,int32_t hint)4128 int32_t ExynosDisplay::setColorTransform(
4129         const float* matrix,
4130         int32_t /*android_color_transform_t*/ hint) {
4131     if ((hint < HAL_COLOR_TRANSFORM_IDENTITY) ||
4132         (hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA))
4133         return HWC2_ERROR_BAD_PARAMETER;
4134     ALOGI("%s:: %d, %d", __func__, mColorTransformHint, hint);
4135     if (mColorTransformHint != hint)
4136         setGeometryChanged(GEOMETRY_DISPLAY_COLOR_TRANSFORM_CHANGED);
4137     mColorTransformHint = hint;
4138 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4139     int ret = mDisplayInterface->setColorTransform(matrix, hint);
4140     if (ret < 0)
4141         mColorTransformHint = ret;
4142     return ret;
4143 #else
4144     return HWC2_ERROR_NONE;
4145 #endif
4146 }
4147 
setColorMode(int32_t mode)4148 int32_t ExynosDisplay::setColorMode(int32_t /*android_color_mode_t*/ mode)
4149 {
4150     if (mDisplayInterface->setColorMode(mode) < 0) {
4151         if (mode == HAL_COLOR_MODE_NATIVE)
4152             return HWC2_ERROR_NONE;
4153 
4154         ALOGE("%s:: is not supported", __func__);
4155         return HWC2_ERROR_UNSUPPORTED;
4156     }
4157 
4158     ALOGI("%s:: %d, %d", __func__, mColorMode, mode);
4159     if (mColorMode != mode)
4160         setGeometryChanged(GEOMETRY_DISPLAY_COLOR_MODE_CHANGED);
4161     mColorMode = (android_color_mode_t)mode;
4162     return HWC2_ERROR_NONE;
4163 }
4164 
getRenderIntents(int32_t mode,uint32_t * outNumIntents,int32_t * outIntents)4165 int32_t ExynosDisplay::getRenderIntents(int32_t mode, uint32_t* outNumIntents,
4166         int32_t* /*android_render_intent_v1_1_t*/ outIntents)
4167 {
4168     ALOGI("%s:: mode(%d), outNum(%d), outIntents(%p)",
4169             __func__, mode, *outNumIntents, outIntents);
4170 
4171     return mDisplayInterface->getRenderIntents(mode, outNumIntents, outIntents);
4172 }
4173 
setColorModeWithRenderIntent(int32_t mode,int32_t intent)4174 int32_t ExynosDisplay::setColorModeWithRenderIntent(int32_t /*android_color_mode_t*/ mode,
4175         int32_t /*android_render_intent_v1_1_t */ intent)
4176 {
4177     ALOGI("%s:: mode(%d), intent(%d)", __func__, mode, intent);
4178 
4179     return mDisplayInterface->setColorModeWithRenderIntent(mode, intent);
4180 }
4181 
getDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)4182 int32_t ExynosDisplay::getDisplayIdentificationData(uint8_t* outPort,
4183         uint32_t* outDataSize, uint8_t* outData)
4184 {
4185     return mDisplayInterface->getDisplayIdentificationData(outPort, outDataSize, outData);
4186 }
4187 
getDisplayCapabilities(uint32_t * outNumCapabilities,uint32_t * outCapabilities)4188 int32_t ExynosDisplay::getDisplayCapabilities(uint32_t* outNumCapabilities,
4189         uint32_t* outCapabilities)
4190 {
4191     /* If each display has their own capabilities,
4192      * this should be described in display module codes */
4193 
4194     uint32_t capabilityNum = 0;
4195     bool isBrightnessSupported = false;
4196     int32_t isDozeSupported = 0;
4197 
4198     auto ret = getDisplayBrightnessSupport(&isBrightnessSupported);
4199     if (ret != HWC2_ERROR_NONE) {
4200         ALOGE("%s: failed to getDisplayBrightnessSupport: %d", __func__, ret);
4201         return ret;
4202     }
4203     if (isBrightnessSupported) {
4204         capabilityNum++;
4205     }
4206 
4207     ret = getDozeSupport(&isDozeSupported);
4208     if (ret != HWC2_ERROR_NONE) {
4209         ALOGE("%s: failed to getDozeSupport: %d", __func__, ret);
4210         return ret;
4211     }
4212     if (isDozeSupported) {
4213         capabilityNum++;
4214     }
4215 
4216 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4217     capabilityNum++;
4218 #endif
4219 
4220     if (outCapabilities == NULL) {
4221         *outNumCapabilities = capabilityNum;
4222         return HWC2_ERROR_NONE;
4223     }
4224     if (capabilityNum != *outNumCapabilities) {
4225         ALOGE("%s:: invalid outNumCapabilities(%d), should be(%d)", __func__, *outNumCapabilities, capabilityNum);
4226         return HWC2_ERROR_BAD_PARAMETER;
4227     }
4228 
4229     uint32_t index = 0;
4230     if (isBrightnessSupported) {
4231         outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
4232     }
4233 
4234     if (isDozeSupported) {
4235         outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
4236     }
4237 
4238 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
4239     outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
4240 #endif
4241 
4242     return HWC2_ERROR_NONE;
4243 }
4244 
getDisplayBrightnessSupport(bool * outSupport)4245 int32_t ExynosDisplay::getDisplayBrightnessSupport(bool* outSupport)
4246 {
4247     if (!mBrightnessController || !mBrightnessController->isSupported()) {
4248         *outSupport = false;
4249     } else {
4250         *outSupport = true;
4251     }
4252 
4253     return HWC2_ERROR_NONE;
4254 }
4255 
handleTargetOperationRate()4256 void ExynosDisplay::handleTargetOperationRate() {
4257     int32_t targetOpRate = mOperationRateManager->getTargetOperationRate();
4258     if (targetOpRate == mBrightnessController->getOperationRate()) return;
4259 
4260     mDevice->onRefresh(mDisplayId);
4261     mBrightnessController->processOperationRate(targetOpRate);
4262 }
4263 
setDisplayBrightness(float brightness,bool waitPresent)4264 int32_t ExynosDisplay::setDisplayBrightness(float brightness, bool waitPresent)
4265 {
4266     if (mBrightnessController) {
4267         int32_t ret;
4268 
4269         ret = mBrightnessController->processDisplayBrightness(brightness, mVsyncPeriod,
4270                                                               waitPresent);
4271         if (ret == NO_ERROR) {
4272             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4273             if (mOperationRateManager) {
4274                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4275                 handleTargetOperationRate();
4276             }
4277         }
4278         return ret;
4279     }
4280 
4281     return HWC2_ERROR_UNSUPPORTED;
4282 }
4283 
ignoreBrightnessUpdateRequests(bool ignore)4284 int32_t ExynosDisplay::ignoreBrightnessUpdateRequests(bool ignore) {
4285     if (mBrightnessController)
4286         return mBrightnessController->ignoreBrightnessUpdateRequests(ignore);
4287 
4288     return HWC2_ERROR_UNSUPPORTED;
4289 }
4290 
setBrightnessNits(const float nits)4291 int32_t ExynosDisplay::setBrightnessNits(const float nits)
4292 {
4293     if (mBrightnessController) {
4294         int32_t ret = mBrightnessController->setBrightnessNits(nits, mVsyncPeriod);
4295 
4296         if (ret == NO_ERROR) {
4297             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4298             if (mOperationRateManager)
4299                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4300         }
4301 
4302         return ret;
4303     }
4304 
4305     return HWC2_ERROR_UNSUPPORTED;
4306 }
4307 
setBrightnessDbv(const uint32_t dbv)4308 int32_t ExynosDisplay::setBrightnessDbv(const uint32_t dbv) {
4309     if (mBrightnessController) {
4310         int32_t ret = mBrightnessController->setBrightnessDbv(dbv, mVsyncPeriod);
4311 
4312         if (ret == NO_ERROR) {
4313             setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
4314             if (mOperationRateManager) {
4315                 mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
4316             }
4317         }
4318 
4319         return ret;
4320     }
4321 
4322     return HWC2_ERROR_UNSUPPORTED;
4323 }
4324 
getDisplayConnectionType(uint32_t * outType)4325 int32_t ExynosDisplay::getDisplayConnectionType(uint32_t* outType)
4326 {
4327     if (mType == HWC_DISPLAY_PRIMARY)
4328         *outType = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL;
4329     else if (mType == HWC_DISPLAY_EXTERNAL)
4330         *outType = HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL;
4331     else
4332         return HWC2_ERROR_BAD_DISPLAY;
4333 
4334     return HWC2_ERROR_NONE;
4335 }
4336 
getDisplayVsyncPeriod(hwc2_vsync_period_t * __unused outVsyncPeriod)4337 int32_t ExynosDisplay::getDisplayVsyncPeriod(hwc2_vsync_period_t* __unused outVsyncPeriod)
4338 {
4339     Mutex::Autolock lock(mDisplayMutex);
4340     return getDisplayVsyncPeriodInternal(outVsyncPeriod);
4341 }
4342 
getConfigAppliedTime(const uint64_t desiredTime,const uint64_t actualChangeTime,int64_t & appliedTime,int64_t & refreshTime)4343 int32_t ExynosDisplay::getConfigAppliedTime(const uint64_t desiredTime,
4344         const uint64_t actualChangeTime,
4345         int64_t &appliedTime, int64_t &refreshTime)
4346 {
4347     uint32_t transientDuration = mDisplayInterface->getConfigChangeDuration();
4348     appliedTime = actualChangeTime;
4349 
4350     if (desiredTime > appliedTime) {
4351         const int64_t originalAppliedTime = appliedTime;
4352         const int64_t diff = desiredTime - appliedTime;
4353         appliedTime += (diff + mVsyncPeriod - 1) / mVsyncPeriod * mVsyncPeriod;
4354         DISPLAY_LOGD(eDebugDisplayConfig,
4355                      "desired time(%" PRId64 "), applied time(%" PRId64 "->%" PRId64 ")",
4356                      desiredTime, originalAppliedTime, appliedTime);
4357     } else {
4358         DISPLAY_LOGD(eDebugDisplayConfig, "desired time(%" PRId64 "), applied time(%" PRId64 ")",
4359                      desiredTime, appliedTime);
4360     }
4361 
4362     refreshTime = appliedTime - (transientDuration * mVsyncPeriod);
4363 
4364     return NO_ERROR;
4365 }
4366 
calculateTimelineLocked(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)4367 void ExynosDisplay::calculateTimelineLocked(
4368         hwc2_config_t config, hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
4369         hwc_vsync_period_change_timeline_t* outTimeline) {
4370     int64_t actualChangeTime = 0;
4371     /* actualChangeTime includes transient duration */
4372     mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
4373 
4374     outTimeline->refreshRequired = true;
4375     getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
4376                          outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
4377 
4378     DISPLAY_LOGD(eDebugDisplayConfig,
4379                  "requested config : %d(%d)->%d(%d), "
4380                  "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
4381                  mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
4382                  mDisplayConfigs[config].vsyncPeriod,
4383                  mVsyncPeriodChangeConstraints.desiredTimeNanos,
4384                  outTimeline->newVsyncAppliedTimeNanos);
4385 }
4386 
setActiveConfigWithConstraints(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)4387 int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
4388         hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
4389         hwc_vsync_period_change_timeline_t* outTimeline)
4390 {
4391     DISPLAY_ATRACE_CALL();
4392     Mutex::Autolock lock(mDisplayMutex);
4393     const nsecs_t current = systemTime(SYSTEM_TIME_MONOTONIC);
4394     const nsecs_t diffMs = ns2ms(vsyncPeriodChangeConstraints->desiredTimeNanos - current);
4395     DISPLAY_LOGD(eDebugDisplayConfig, "config(%d->%d), seamless(%d), diff(%" PRId64 ")",
4396                  mActiveConfig, config, vsyncPeriodChangeConstraints->seamlessRequired, diffMs);
4397 
4398     if (CC_UNLIKELY(ATRACE_ENABLED())) ATRACE_NAME(("diff:" + std::to_string(diffMs)).c_str());
4399 
4400     if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
4401 
4402     if (!isConfigSettingEnabled()) {
4403         mPendingConfig = config;
4404         DISPLAY_LOGI("%s: config setting disabled, set pending config=%d", __func__, config);
4405         return HWC2_ERROR_NONE;
4406     }
4407 
4408     if (mDisplayConfigs[mActiveConfig].groupId != mDisplayConfigs[config].groupId) {
4409         if (vsyncPeriodChangeConstraints->seamlessRequired) {
4410             DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not allowed");
4411             return HWC2_ERROR_SEAMLESS_NOT_ALLOWED;
4412         }
4413 
4414         outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
4415         outTimeline->refreshRequired = true;
4416     }
4417 
4418     if (needNotChangeConfig(config)) {
4419         outTimeline->refreshRequired = false;
4420         outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
4421         return HWC2_ERROR_NONE;
4422     }
4423 
4424     if ((mXres != mDisplayConfigs[config].width) || (mYres != mDisplayConfigs[config].height)) {
4425         if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
4426             ALOGW("Mode change not possible");
4427             return HWC2_ERROR_BAD_CONFIG;
4428         }
4429         mRenderingState = RENDERING_STATE_NONE;
4430         setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
4431         updateInternalDisplayConfigVariables(config, false);
4432     } else if (vsyncPeriodChangeConstraints->seamlessRequired) {
4433         if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
4434             DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not possible");
4435             return HWC2_ERROR_SEAMLESS_NOT_POSSIBLE;
4436         }
4437     }
4438 
4439     DISPLAY_LOGD(eDebugDisplayConfig, "%s : %dx%d, %dms, %d Xdpi, %d Ydpi", __func__,
4440             mXres, mYres, mVsyncPeriod, mXdpi, mYdpi);
4441 
4442     if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4443         DISPLAY_LOGI("%s, previous request config is processing (desird %d, new request %d)",
4444                      __func__, mDesiredConfig, config);
4445     }
4446     /* Config would be requested on present time */
4447     mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING;
4448     mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
4449     mDesiredConfig = config;
4450     DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
4451 
4452     calculateTimelineLocked(config, vsyncPeriodChangeConstraints, outTimeline);
4453 
4454     /* mActiveConfig should be changed immediately for internal status */
4455     mActiveConfig = config;
4456     mVsyncAppliedTimeLine = *outTimeline;
4457     updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config));
4458 
4459     bool earlyWakeupNeeded = checkRrCompensationEnabled();
4460     if (earlyWakeupNeeded) {
4461         setEarlyWakeupDisplay();
4462     }
4463     if (mRefreshRateIndicatorHandler) {
4464         mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
4465     }
4466 
4467     return HWC2_ERROR_NONE;
4468 }
4469 
setBootDisplayConfig(int32_t config)4470 int32_t ExynosDisplay::setBootDisplayConfig(int32_t config) {
4471     return HWC2_ERROR_UNSUPPORTED;
4472 }
4473 
clearBootDisplayConfig()4474 int32_t ExynosDisplay::clearBootDisplayConfig() {
4475     return HWC2_ERROR_UNSUPPORTED;
4476 }
4477 
getPreferredBootDisplayConfig(int32_t * outConfig)4478 int32_t ExynosDisplay::getPreferredBootDisplayConfig(int32_t *outConfig) {
4479     return getPreferredDisplayConfigInternal(outConfig);
4480 }
4481 
getPreferredDisplayConfigInternal(int32_t * outConfig)4482 int32_t ExynosDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
4483     return HWC2_ERROR_UNSUPPORTED;
4484 }
4485 
setAutoLowLatencyMode(bool __unused on)4486 int32_t ExynosDisplay::setAutoLowLatencyMode(bool __unused on)
4487 {
4488     return HWC2_ERROR_UNSUPPORTED;
4489 }
4490 
getSupportedContentTypes(uint32_t * __unused outNumSupportedContentTypes,uint32_t * __unused outSupportedContentTypes)4491 int32_t ExynosDisplay::getSupportedContentTypes(uint32_t* __unused outNumSupportedContentTypes,
4492         uint32_t* __unused outSupportedContentTypes)
4493 {
4494     if (outSupportedContentTypes == NULL)
4495         outNumSupportedContentTypes = 0;
4496     return HWC2_ERROR_NONE;
4497 }
4498 
setContentType(int32_t contentType)4499 int32_t ExynosDisplay::setContentType(int32_t /* hwc2_content_type_t */ contentType)
4500 {
4501     if (contentType == HWC2_CONTENT_TYPE_NONE)
4502         return HWC2_ERROR_NONE;
4503 
4504     return HWC2_ERROR_UNSUPPORTED;
4505 }
4506 
getClientTargetProperty(hwc_client_target_property_t * outClientTargetProperty,HwcDimmingStage * outDimmingStage)4507 int32_t ExynosDisplay::getClientTargetProperty(
4508                         hwc_client_target_property_t *outClientTargetProperty,
4509                         HwcDimmingStage *outDimmingStage) {
4510     outClientTargetProperty->pixelFormat = HAL_PIXEL_FORMAT_RGBA_8888;
4511     outClientTargetProperty->dataspace = HAL_DATASPACE_UNKNOWN;
4512     if (outDimmingStage != nullptr)
4513         *outDimmingStage = HwcDimmingStage::DIMMING_NONE;
4514 
4515     return HWC2_ERROR_NONE;
4516 }
4517 
isBadConfig(hwc2_config_t config)4518 bool ExynosDisplay::isBadConfig(hwc2_config_t config)
4519 {
4520     /* Check invalid config */
4521     const auto its = mDisplayConfigs.find(config);
4522     if (its == mDisplayConfigs.end()) {
4523         DISPLAY_LOGE("%s, invalid config : %d", __func__, config);
4524         return true;
4525     }
4526 
4527     return false;
4528 }
4529 
needNotChangeConfig(hwc2_config_t config)4530 bool ExynosDisplay::needNotChangeConfig(hwc2_config_t config)
4531 {
4532     /* getting current config and compare */
4533     /* If same value, return */
4534     if (mActiveConfig == config) {
4535         DISPLAY_LOGI("%s, Same config change requested : %d", __func__, config);
4536         return true;
4537     }
4538 
4539     return false;
4540 }
4541 
updateInternalDisplayConfigVariables(hwc2_config_t config,bool updateVsync)4542 int32_t ExynosDisplay::updateInternalDisplayConfigVariables(
4543         hwc2_config_t config, bool updateVsync)
4544 {
4545     mActiveConfig = config;
4546 
4547     /* Update internal variables */
4548     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_WIDTH, (int32_t*)&mXres);
4549     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_HEIGHT, (int32_t*)&mYres);
4550     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_X, (int32_t*)&mXdpi);
4551     getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_Y, (int32_t*)&mYdpi);
4552     mHdrFullScrenAreaThreshold = mXres * mYres * kHdrFullScreen;
4553     if (updateVsync) {
4554         resetConfigRequestStateLocked(config);
4555     }
4556     if (mRefreshRateIndicatorHandler) {
4557         mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
4558     }
4559 
4560     return NO_ERROR;
4561 }
4562 
updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod,bool configApplied)4563 void ExynosDisplay::updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod, bool configApplied) {
4564     if (mBtsFrameScanoutPeriod == frameScanoutPeriod) {
4565         return;
4566     }
4567 
4568     if (configApplied || frameScanoutPeriod < mBtsFrameScanoutPeriod) {
4569         checkBtsReassignResource(frameScanoutPeriod, mBtsFrameScanoutPeriod);
4570         mBtsFrameScanoutPeriod = frameScanoutPeriod;
4571         ATRACE_INT("btsFrameScanoutPeriod", mBtsFrameScanoutPeriod);
4572     }
4573 }
4574 
tryUpdateBtsFromOperationRate(bool beforeValidateDisplay)4575 void ExynosDisplay::tryUpdateBtsFromOperationRate(bool beforeValidateDisplay) {
4576     if (mOperationRateManager == nullptr || mBrightnessController == nullptr ||
4577         mActiveConfig == UINT_MAX) {
4578         return;
4579     }
4580 
4581     if (!mDisplayConfigs[mActiveConfig].isOperationRateToBts) {
4582         return;
4583     }
4584 
4585     if (beforeValidateDisplay && mBrightnessController->isOperationRatePending()) {
4586         uint32_t opRate = mBrightnessController->getOperationRate();
4587         if (opRate) {
4588             int32_t operationRatePeriod = nsecsPerSec / opRate;
4589             if (operationRatePeriod < mBtsFrameScanoutPeriod) {
4590                 updateBtsFrameScanoutPeriod(opRate);
4591                 mBtsPendingOperationRatePeriod = 0;
4592             } else if (operationRatePeriod != mBtsFrameScanoutPeriod) {
4593                 mBtsPendingOperationRatePeriod = operationRatePeriod;
4594             }
4595         }
4596     }
4597 
4598     if (!beforeValidateDisplay && mBtsPendingOperationRatePeriod &&
4599         !mBrightnessController->isOperationRatePending()) {
4600         /* Do not update during rr transition, it will be updated after setting config done */
4601         if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4602             updateBtsFrameScanoutPeriod(mBtsPendingOperationRatePeriod, true);
4603         }
4604         mBtsPendingOperationRatePeriod = 0;
4605     }
4606 }
4607 
getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config)4608 inline int32_t ExynosDisplay::getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config) {
4609     int32_t frameScanoutPeriodNs;
4610     auto vrrConfig = getVrrConfigs(config);
4611     if (vrrConfig.has_value() && vrrConfig->isFullySupported) {
4612         frameScanoutPeriodNs = vrrConfig->minFrameIntervalNs;
4613     } else {
4614         getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &frameScanoutPeriodNs);
4615         if (mOperationRateManager && mBrightnessController &&
4616             mDisplayConfigs[config].isOperationRateToBts) {
4617             uint32_t opRate = mBrightnessController->getOperationRate();
4618             if (opRate) {
4619                 uint32_t opPeriodNs = nsecsPerSec / opRate;
4620                 frameScanoutPeriodNs =
4621                         (frameScanoutPeriodNs <= opPeriodNs) ? frameScanoutPeriodNs : opPeriodNs;
4622             }
4623         } else if (mDisplayConfigs[config].isBoost2xBts) {
4624             frameScanoutPeriodNs = frameScanoutPeriodNs / 2;
4625         }
4626     }
4627 
4628     assert(frameScanoutPeriodNs > 0);
4629     return frameScanoutPeriodNs;
4630 }
4631 
getBtsRefreshRate() const4632 uint32_t ExynosDisplay::getBtsRefreshRate() const {
4633     return static_cast<uint32_t>(round(nsecsPerSec / mBtsFrameScanoutPeriod * 0.1f) * 10);
4634 }
4635 
updateRefreshRateHint()4636 void ExynosDisplay::updateRefreshRateHint() {
4637     if (mRefreshRate) {
4638         mPowerHalHint.signalRefreshRate(mPowerModeState.value_or(HWC2_POWER_MODE_OFF),
4639                                         mRefreshRate);
4640     }
4641 }
4642 
4643 /* This function must be called within a mDisplayMutex protection */
resetConfigRequestStateLocked(hwc2_config_t config)4644 int32_t ExynosDisplay::resetConfigRequestStateLocked(hwc2_config_t config) {
4645     ATRACE_CALL();
4646 
4647     assert(isBadConfig(config) == false);
4648 
4649     mRefreshRate = mDisplayConfigs[config].refreshRate;
4650     mVsyncPeriod = getDisplayVsyncPeriodFromConfig(config);
4651     updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config), true);
4652     DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by config(%d)", mVsyncPeriod, config);
4653 
4654     updateRefreshRateHint();
4655 
4656     if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4657         DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
4658                      mConfigRequestState);
4659     } else {
4660         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to DONE",
4661                      __func__, mConfigRequestState);
4662         mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
4663         updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
4664     }
4665     return NO_ERROR;
4666 }
4667 
updateConfigRequestAppliedTime()4668 int32_t ExynosDisplay::updateConfigRequestAppliedTime()
4669 {
4670     if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4671         DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
4672                      mConfigRequestState);
4673         return NO_ERROR;
4674     }
4675 
4676     /*
4677      * config change was requested but
4678      * it is not applied until newVsyncAppliedTimeNanos
4679      * Update time information
4680      */
4681     int64_t actualChangeTime = 0;
4682     mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
4683     return updateVsyncAppliedTimeLine(actualChangeTime);
4684 }
4685 
updateVsyncAppliedTimeLine(int64_t actualChangeTime)4686 int32_t ExynosDisplay::updateVsyncAppliedTimeLine(int64_t actualChangeTime)
4687 {
4688     ExynosDevice *dev = mDevice;
4689 
4690     DISPLAY_LOGD(eDebugDisplayConfig,"Vsync applied time is changed (%" PRId64 "-> %" PRId64 ")",
4691             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
4692             actualChangeTime);
4693     getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos,
4694             actualChangeTime,
4695             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos,
4696             mVsyncAppliedTimeLine.refreshTimeNanos);
4697     if (mConfigRequestState ==
4698             hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
4699         mVsyncAppliedTimeLine.refreshRequired = false;
4700     } else {
4701         mVsyncAppliedTimeLine.refreshRequired = true;
4702     }
4703 
4704     DISPLAY_LOGD(eDebugDisplayConfig,"refresh required(%d), newVsyncAppliedTimeNanos (%" PRId64 ")",
4705             mVsyncAppliedTimeLine.refreshRequired,
4706             mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos);
4707 
4708     dev->onVsyncPeriodTimingChanged(getId(), &mVsyncAppliedTimeLine);
4709 
4710     return NO_ERROR;
4711 }
4712 
getDisplayVsyncPeriodInternal(hwc2_vsync_period_t * outVsyncPeriod)4713 int32_t ExynosDisplay::getDisplayVsyncPeriodInternal(hwc2_vsync_period_t* outVsyncPeriod)
4714 {
4715     /* Getting actual config from DPU */
4716     if (mDisplayInterface->getDisplayVsyncPeriod(outVsyncPeriod) == HWC2_ERROR_NONE) {
4717         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period : %ld",
4718                 (long)*outVsyncPeriod);
4719     } else {
4720         *outVsyncPeriod = mVsyncPeriod;
4721         DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "period is mVsyncPeriod: %d",
4722                 mVsyncPeriod);
4723     }
4724     return HWC2_ERROR_NONE;
4725 }
4726 
doDisplayConfigInternal(hwc2_config_t config)4727 int32_t ExynosDisplay::doDisplayConfigInternal(hwc2_config_t config) {
4728     return mDisplayInterface->setActiveConfigWithConstraints(config);
4729 }
4730 
doDisplayConfigPostProcess(ExynosDevice * dev)4731 int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
4732 {
4733     ATRACE_CALL();
4734     uint64_t current = systemTime(SYSTEM_TIME_MONOTONIC);
4735 
4736     int64_t actualChangeTime = 0;
4737     mDisplayInterface->getVsyncAppliedTime(mDesiredConfig, &actualChangeTime);
4738     bool needSetActiveConfig = false;
4739 
4740     DISPLAY_LOGD(eDebugDisplayConfig,
4741             "Check time for setActiveConfig (curr: %" PRId64
4742             ", actualChangeTime: %" PRId64 ", desiredTime: %" PRId64 "",
4743             current, actualChangeTime,
4744             mVsyncPeriodChangeConstraints.desiredTimeNanos);
4745     if (actualChangeTime >= mVsyncPeriodChangeConstraints.desiredTimeNanos) {
4746         DISPLAY_LOGD(eDebugDisplayConfig, "Request setActiveConfig %d", mDesiredConfig);
4747         needSetActiveConfig = true;
4748         DISPLAY_ATRACE_INT("Pending ActiveConfig", 0);
4749         DISPLAY_ATRACE_INT64("TimeToApplyConfig", 0);
4750     } else {
4751         DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending (mDesiredConfig %d)",
4752                      mDesiredConfig);
4753         DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
4754         DISPLAY_ATRACE_INT64("TimeToApplyConfig",
4755                              ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - current));
4756     }
4757 
4758     if (needSetActiveConfig) {
4759         int32_t ret = NO_ERROR;
4760         if ((ret = doDisplayConfigInternal(mDesiredConfig)) != NO_ERROR) {
4761             return ret;
4762         }
4763 
4764         mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_REQUESTED;
4765     }
4766 
4767     return updateVsyncAppliedTimeLine(actualChangeTime);
4768 }
4769 
setOutputBuffer(buffer_handle_t __unused buffer,int32_t __unused releaseFence)4770 int32_t ExynosDisplay::setOutputBuffer( buffer_handle_t __unused buffer, int32_t __unused releaseFence)
4771 {
4772     return HWC2_ERROR_NONE;
4773 }
4774 
clearDisplay(bool needModeClear)4775 int ExynosDisplay::clearDisplay(bool needModeClear) {
4776 
4777     const int ret = mDisplayInterface->clearDisplay(needModeClear);
4778     if (ret)
4779         DISPLAY_LOGE("fail to clear display");
4780 
4781     mClientCompositionInfo.mSkipStaticInitFlag = false;
4782     mClientCompositionInfo.mSkipFlag = false;
4783 
4784     mLastDpuData.reset();
4785 
4786     /* Update last retire fence */
4787     mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
4788 
4789     if (mBrightnessController) {
4790         mBrightnessController->onClearDisplay(needModeClear);
4791     }
4792     return ret;
4793 }
4794 
setPowerMode(int32_t mode)4795 int32_t ExynosDisplay::setPowerMode(
4796         int32_t /*hwc2_power_mode_t*/ mode) {
4797     Mutex::Autolock lock(mDisplayMutex);
4798 
4799     if (!mDisplayInterface->isDozeModeAvailable() &&
4800         (mode == HWC2_POWER_MODE_DOZE || mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
4801         return HWC2_ERROR_UNSUPPORTED;
4802     }
4803 
4804     if (mode == HWC_POWER_MODE_OFF) {
4805         mDevice->mPrimaryBlank = true;
4806         clearDisplay(true);
4807         ALOGV("HWC2: Clear display (power off)");
4808     } else {
4809         mDevice->mPrimaryBlank = false;
4810     }
4811 
4812     if (mode == HWC_POWER_MODE_OFF)
4813         mDREnable = false;
4814     else
4815         mDREnable = mDRDefault;
4816 
4817     // check the dynamic recomposition thread by following display power status;
4818     mDevice->checkDynamicRecompositionThread();
4819 
4820 
4821     /* TODO: Call display interface */
4822     mDisplayInterface->setPowerMode(mode);
4823 
4824     ALOGD("%s:: mode(%d))", __func__, mode);
4825 
4826     mPowerModeState = (hwc2_power_mode_t)mode;
4827 
4828     if (mode == HWC_POWER_MODE_OFF) {
4829         /* It should be called from validate() when the screen is on */
4830         mSkipFrame = true;
4831         setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
4832         if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
4833             (mRenderingState < RENDERING_STATE_PRESENTED))
4834             closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
4835         mRenderingState = RENDERING_STATE_NONE;
4836     } else {
4837         setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
4838     }
4839 
4840     return HWC2_ERROR_NONE;
4841 }
4842 
setVsyncEnabled(int32_t enabled)4843 int32_t ExynosDisplay::setVsyncEnabled(
4844         int32_t /*hwc2_vsync_t*/ enabled) {
4845     Mutex::Autolock lock(mDisplayMutex);
4846     return setVsyncEnabledInternal(enabled);
4847 }
4848 
setVsyncEnabledInternal(int32_t enabled)4849 int32_t ExynosDisplay::setVsyncEnabledInternal(
4850         int32_t enabled) {
4851 
4852     uint32_t val = 0;
4853 
4854     if (enabled < 0 || enabled > HWC2_VSYNC_DISABLE)
4855         return HWC2_ERROR_BAD_PARAMETER;
4856 
4857 
4858     if (enabled == HWC2_VSYNC_ENABLE) {
4859         gettimeofday(&updateTimeInfo.lastEnableVsyncTime, NULL);
4860         val = 1;
4861         if (mVsyncState != HWC2_VSYNC_ENABLE) {
4862             /* TODO: remove it once driver can handle on its own */
4863             setEarlyWakeupDisplay();
4864         }
4865     } else {
4866         gettimeofday(&updateTimeInfo.lastDisableVsyncTime, NULL);
4867     }
4868 
4869     if (mDisplayInterface->setVsyncEnabled(val) < 0) {
4870         HWC_LOGE(this, "vsync ioctl failed errno : %d", errno);
4871         return HWC2_ERROR_BAD_DISPLAY;
4872     }
4873 
4874     mVsyncState = (hwc2_vsync_t)enabled;
4875 
4876     return HWC2_ERROR_NONE;
4877 }
4878 
validateDisplay(uint32_t * outNumTypes,uint32_t * outNumRequests)4879 int32_t ExynosDisplay::validateDisplay(
4880         uint32_t* outNumTypes, uint32_t* outNumRequests) {
4881     DISPLAY_ATRACE_CALL();
4882     gettimeofday(&updateTimeInfo.lastValidateTime, NULL);
4883     Mutex::Autolock lock(mDisplayMutex);
4884 
4885     if (!mHpdStatus) {
4886         ALOGD("validateDisplay: drop frame: mHpdStatus == false");
4887         return HWC2_ERROR_NONE;
4888     }
4889 
4890     if (mPauseDisplay) return HWC2_ERROR_NONE;
4891 
4892     mDropFrameDuringResSwitch =
4893             (mGeometryChanged & GEOMETRY_DISPLAY_RESOLUTION_CHANGED) && !isFullScreenComposition();
4894     if (mDropFrameDuringResSwitch) {
4895         ALOGD("validateDisplay: drop invalid frame during resolution switch");
4896         *outNumTypes = 0;
4897         *outNumRequests = 0;
4898         return HWC2_ERROR_NONE;
4899     }
4900 
4901     int ret = NO_ERROR;
4902     bool validateError = false;
4903     mUpdateEventCnt++;
4904     mUpdateCallCnt++;
4905     mLastUpdateTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
4906 
4907     if (usePowerHintSession()) {
4908         mValidateStartTime = mLastUpdateTimeStamp;
4909         mExpectedPresentTime = getExpectedPresentTime(*mValidateStartTime);
4910         auto target =
4911                 min(mExpectedPresentTime - *mValidateStartTime, static_cast<nsecs_t>(mVsyncPeriod));
4912         mPowerHalHint.signalTargetWorkDuration(target);
4913         std::optional<nsecs_t> predictedDuration = getPredictedDuration(true);
4914         if (predictedDuration.has_value()) {
4915             mPowerHalHint.signalActualWorkDuration(*predictedDuration);
4916         }
4917     }
4918 
4919     checkIgnoreLayers();
4920     if (mLayers.size() == 0)
4921         DISPLAY_LOGI("%s:: validateDisplay layer size is 0", __func__);
4922     else
4923         mLayers.vector_sort();
4924 
4925     for (size_t i = 0; i < mLayers.size(); i++) mLayers[i]->setSrcAcquireFence();
4926 
4927     tryUpdateBtsFromOperationRate(true);
4928     doPreProcessing();
4929     checkLayerFps();
4930     if (exynosHWCControl.useDynamicRecomp == true && mDREnable) {
4931         checkDynamicReCompMode();
4932         if (mDevice->isDynamicRecompositionThreadAlive() == false &&
4933             mDevice->mDRLoopStatus == false)
4934             mDevice->dynamicRecompositionThreadCreate();
4935     }
4936 
4937     if ((ret = mResourceManager->assignResource(this)) != NO_ERROR) {
4938         validateError = true;
4939         HWC_LOGE(this, "%s:: assignResource() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4940         String8 errString;
4941         errString.appendFormat("%s:: assignResource() fail, display(%d), ret(%d)\n",
4942                 __func__, mDisplayId, ret);
4943         printDebugInfos(errString);
4944         mDisplayInterface->setForcePanic();
4945     }
4946 
4947     if ((ret = skipStaticLayers(mClientCompositionInfo)) != NO_ERROR) {
4948         validateError = true;
4949         HWC_LOGE(this, "%s:: skipStaticLayers() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
4950     } else {
4951         if ((mClientCompositionInfo.mHasCompositionLayer) &&
4952             (mClientCompositionInfo.mSkipFlag == false)) {
4953             /* Initialize compositionType */
4954             for (size_t i = (size_t)mClientCompositionInfo.mFirstIndex; i <= (size_t)mClientCompositionInfo.mLastIndex; i++) {
4955                 if (mLayers[i]->mOverlayPriority >= ePriorityHigh)
4956                     continue;
4957                 mLayers[i]->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT);
4958             }
4959         }
4960     }
4961 
4962     mRenderingState = RENDERING_STATE_VALIDATED;
4963 
4964     /*
4965      * HWC should update performanceInfo even if assignResource is skipped
4966      * HWC excludes the layer from performance calculation
4967      * if there is no buffer update. (using ExynosMPP::canSkipProcessing())
4968      * Therefore performanceInfo should be calculated again if only the buffer is updated.
4969      */
4970     if ((ret = mDevice->mResourceManager->deliverPerformanceInfo()) != NO_ERROR) {
4971         HWC_LOGE(NULL,"%s:: deliverPerformanceInfo() error (%d)",
4972                 __func__, ret);
4973     }
4974 
4975     if ((validateError == false) && (mDisplayControl.earlyStartMPP == true)) {
4976         if ((ret = startPostProcessing()) != NO_ERROR)
4977             validateError = true;
4978     }
4979 
4980     if (validateError) {
4981         setGeometryChanged(GEOMETRY_ERROR_CASE);
4982         mClientCompositionInfo.mSkipStaticInitFlag = false;
4983         mExynosCompositionInfo.mSkipStaticInitFlag = false;
4984         mResourceManager->resetAssignedResources(this, true);
4985         mClientCompositionInfo.initializeInfos(this);
4986         mExynosCompositionInfo.initializeInfos(this);
4987         for (uint32_t i = 0; i < mLayers.size(); i++) {
4988             ExynosLayer *layer = mLayers[i];
4989             layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, eResourceAssignFail);
4990             addClientCompositionLayer(i);
4991         }
4992         mResourceManager->assignCompositionTarget(this, COMPOSITION_CLIENT);
4993         mResourceManager->assignWindow(this);
4994     }
4995 
4996     resetColorMappingInfoForClientComp();
4997     storePrevValidateCompositionType();
4998 
4999     int32_t displayRequests = 0;
5000     if ((ret = getChangedCompositionTypes(outNumTypes, NULL, NULL)) != NO_ERROR) {
5001         HWC_LOGE(this, "%s:: getChangedCompositionTypes() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
5002         setGeometryChanged(GEOMETRY_ERROR_CASE);
5003     }
5004     if ((ret = getDisplayRequests(&displayRequests, outNumRequests, NULL, NULL)) != NO_ERROR) {
5005         HWC_LOGE(this, "%s:: getDisplayRequests() fail, display(%d), ret(%d)", __func__, mDisplayId, ret);
5006         setGeometryChanged(GEOMETRY_ERROR_CASE);
5007     }
5008 
5009     mSkipFrame = false;
5010 
5011     if ((*outNumTypes == 0) && (*outNumRequests == 0))
5012         return HWC2_ERROR_NONE;
5013 
5014     if (usePowerHintSession()) {
5015         mValidationDuration = systemTime(SYSTEM_TIME_MONOTONIC) - *mValidateStartTime;
5016     }
5017 
5018     return HWC2_ERROR_HAS_CHANGES;
5019 }
5020 
startPostProcessing()5021 int32_t ExynosDisplay::startPostProcessing()
5022 {
5023     ATRACE_CALL();
5024     int ret = NO_ERROR;
5025     String8 errString;
5026 
5027     float assignedCapacity = mResourceManager->getAssignedCapacity(MPP_G2D);
5028 
5029     if (assignedCapacity > (mResourceManager->getM2MCapa(MPP_G2D) * MPP_CAPA_OVER_THRESHOLD)) {
5030         errString.appendFormat("Assigned capacity for exynos composition is over restriction (%f)",
5031                 assignedCapacity);
5032         goto err;
5033     }
5034 
5035     if ((ret = doExynosComposition()) != NO_ERROR) {
5036         errString.appendFormat("exynosComposition fail (%d)\n", ret);
5037         goto err;
5038     }
5039 
5040     // loop for all layer
5041     for (size_t i=0; i < mLayers.size(); i++) {
5042         if ((mLayers[i]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) &&
5043             (mLayers[i]->mM2mMPP != NULL)) {
5044             /* mAcquireFence is updated, Update image info */
5045             struct exynos_image srcImg, dstImg, midImg;
5046             mLayers[i]->setSrcExynosImage(&srcImg);
5047             mLayers[i]->setDstExynosImage(&dstImg);
5048             mLayers[i]->setExynosImage(srcImg, dstImg);
5049             ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
5050             midImg = mLayers[i]->mMidImg;
5051             m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
5052             if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
5053                 DISPLAY_LOGE("%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
5054                         __func__, i, ret);
5055                 errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
5056                         __func__, i, ret);
5057                 goto err;
5058             } else {
5059                 /* This should be closed by lib for each resource */
5060                 mLayers[i]->mAcquireFence = -1;
5061             }
5062         }
5063     }
5064     return ret;
5065 err:
5066     printDebugInfos(errString);
5067     closeFences();
5068     mDisplayInterface->setForcePanic();
5069     return -EINVAL;
5070 }
5071 
setCursorPositionAsync(uint32_t x_pos,uint32_t y_pos)5072 int32_t ExynosDisplay::setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos) {
5073     mDisplayInterface->setCursorPositionAsync(x_pos, y_pos);
5074     return HWC2_ERROR_NONE;
5075 }
5076 
5077 // clang-format off
dumpConfig(const exynos_win_config_data & c)5078 void ExynosDisplay::dumpConfig(const exynos_win_config_data &c)
5079 {
5080     DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\tstate = %u", c.state);
5081     if (c.state == c.WIN_STATE_COLOR) {
5082         DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer,
5083                 "\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5084                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5085     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5086         DISPLAY_LOGD(eDebugWinConfig|eDebugSkipStaicLayer, "\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5087                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5088                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5089                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5090                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5091                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)",
5092                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5093                 c.acq_fence, c.rel_fence,
5094                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5095                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5096                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable,
5097                 c.blending, c.protection, getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5098                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5099                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5100                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5101     }
5102 }
5103 
miniDump(String8 & result)5104 void ExynosDisplay::miniDump(String8& result)
5105 {
5106     Mutex::Autolock lock(mDRMutex);
5107     result.appendFormat("=======================  Mini dump  ================================\n");
5108     TableBuilder tb;
5109     ExynosSortedLayer allLayers = mLayers;
5110     for (auto layer : mIgnoreLayers)
5111         allLayers.push_back(layer);
5112     allLayers.vector_sort();
5113 
5114     for (auto layer : allLayers)
5115         layer->miniDump(tb);
5116 
5117     result.appendFormat("%s", tb.buildForMiniDump().c_str());
5118 }
5119 
dump(String8 & result,const std::vector<std::string> & args)5120 void ExynosDisplay::dump(String8 &result, const std::vector<std::string>& args) {
5121     Mutex::Autolock lock(mDisplayMutex);
5122     dumpLocked(result);
5123 }
5124 
dumpLocked(String8 & result)5125 void ExynosDisplay::dumpLocked(String8& result) {
5126     result.appendFormat("[%s] display information size: %d x %d, vsyncState: %d, colorMode: %d, "
5127                         "colorTransformHint: %d, orientation %d\n",
5128                         mDisplayName.c_str(), mXres, mYres, mVsyncState, mColorMode,
5129                         mColorTransformHint, mMountOrientation);
5130     mClientCompositionInfo.dump(result);
5131     mExynosCompositionInfo.dump(result);
5132 
5133     result.appendFormat("PanelGammaSource (%d)\n\n", GetCurrentPanelGammaSource());
5134 
5135     {
5136         Mutex::Autolock lock(mDRMutex);
5137         if (mLayers.size()) {
5138             result.appendFormat("============================== dump layers ===========================================\n");
5139             for (uint32_t i = 0; i < mLayers.size(); i++) {
5140                 ExynosLayer *layer = mLayers[i];
5141                 layer->dump(result);
5142             }
5143         }
5144         if (mIgnoreLayers.size()) {
5145             result.appendFormat("\n============================== dump ignore layers ===========================================\n");
5146             for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
5147                 ExynosLayer *layer = mIgnoreLayers[i];
5148                 layer->dump(result);
5149             }
5150         }
5151     }
5152     result.appendFormat("\n");
5153     if (mBrightnessController) {
5154         mBrightnessController->dump(result);
5155     }
5156     if (mHistogramController) {
5157         mHistogramController->dump(result);
5158     }
5159     if (mDisplayTe2Manager) {
5160         mDisplayTe2Manager->dump(result);
5161     }
5162 }
5163 
dumpConfig(String8 & result,const exynos_win_config_data & c)5164 void ExynosDisplay::dumpConfig(String8 &result, const exynos_win_config_data &c)
5165 {
5166     result.appendFormat("\tstate = %u\n", c.state);
5167     if (c.state == c.WIN_STATE_COLOR) {
5168         result.appendFormat("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5169                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5170     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5171         result.appendFormat("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5172                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5173                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5174                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5175                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5176                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)\n",
5177                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5178                 c.acq_fence, c.rel_fence,
5179                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5180                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5181                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
5182                 getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5183                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5184                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5185                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5186     }
5187 }
5188 
printConfig(exynos_win_config_data & c)5189 void ExynosDisplay::printConfig(exynos_win_config_data &c)
5190 {
5191     ALOGD("\tstate = %u", c.state);
5192     if (c.state == c.WIN_STATE_COLOR) {
5193         ALOGD("\t\tx = %d, y = %d, width = %d, height = %d, color = %u, alpha = %f\n",
5194                 c.dst.x, c.dst.y, c.dst.w, c.dst.h, c.color, c.plane_alpha);
5195     } else/* if (c.state != c.WIN_STATE_DISABLED) */{
5196         ALOGD("\t\tfd = (%d, %d, %d), acq_fence = %d, rel_fence = %d "
5197                 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
5198                 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
5199                 "format = %u, pa = %f, transform = %d, dataspace = 0x%8x, hdr_enable = %d, blending = %u, "
5200                 "protection = %u, compression = %s, compression_src = %d, transparent(x:%d, y:%d, w:%u, h:%u), "
5201                 "block(x:%d, y:%d, w:%u, h:%u), opaque(x:%d, y:%d, w:%u, h:%u)",
5202                 c.fd_idma[0], c.fd_idma[1], c.fd_idma[2],
5203                 c.acq_fence, c.rel_fence,
5204                 c.src.f_w, c.src.f_h, c.src.x, c.src.y, c.src.w, c.src.h,
5205                 c.dst.f_w, c.dst.f_h, c.dst.x, c.dst.y, c.dst.w, c.dst.h,
5206                 c.format, c.plane_alpha, c.transform, c.dataspace, c.hdr_enable, c.blending, c.protection,
5207                 getCompressionStr(c.compressionInfo).c_str(), c.comp_src,
5208                 c.transparent_area.x, c.transparent_area.y, c.transparent_area.w, c.transparent_area.h,
5209                 c.block_area.x, c.block_area.y, c.block_area.w, c.block_area.h,
5210                 c.opaque_area.x, c.opaque_area.y, c.opaque_area.w, c.opaque_area.h);
5211     }
5212 }
5213 // clang-format on
5214 
setCompositionTargetExynosImage(uint32_t targetType,exynos_image * src_img,exynos_image * dst_img)5215 int32_t ExynosDisplay::setCompositionTargetExynosImage(uint32_t targetType, exynos_image *src_img, exynos_image *dst_img)
5216 {
5217     if (targetType != COMPOSITION_CLIENT && targetType != COMPOSITION_EXYNOS) {
5218         return -EINVAL;
5219     }
5220     const ExynosCompositionInfo& compositionInfo =
5221             (targetType == COMPOSITION_CLIENT) ? mClientCompositionInfo : mExynosCompositionInfo;
5222 
5223     src_img->fullWidth = mXres;
5224     src_img->fullHeight = mYres;
5225     /* To do */
5226     /* Fb crop should be set hear */
5227     src_img->x = 0;
5228     src_img->y = 0;
5229     src_img->w = mXres;
5230     src_img->h = mYres;
5231 
5232     if (compositionInfo.mTargetBuffer != NULL) {
5233         src_img->bufferHandle = compositionInfo.mTargetBuffer;
5234 
5235         VendorGraphicBufferMeta gmeta(compositionInfo.mTargetBuffer);
5236         src_img->format = gmeta.format;
5237         src_img->usageFlags = gmeta.producer_usage;
5238     } else {
5239         src_img->bufferHandle = NULL;
5240         src_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
5241         src_img->usageFlags = 0;
5242     }
5243     src_img->layerFlags = 0x0;
5244     src_img->acquireFenceFd = compositionInfo.mAcquireFence;
5245     src_img->releaseFenceFd = -1;
5246     src_img->dataSpace = compositionInfo.mDataSpace;
5247     src_img->blending = HWC2_BLEND_MODE_PREMULTIPLIED;
5248     src_img->transform = 0;
5249     src_img->compressionInfo = compositionInfo.mCompressionInfo;
5250     src_img->planeAlpha = 1;
5251     src_img->zOrder = 0;
5252     if ((targetType == COMPOSITION_CLIENT) && (mType == HWC_DISPLAY_VIRTUAL)) {
5253         if (compositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)
5254             src_img->zOrder = 0;
5255         else
5256             src_img->zOrder = 1000;
5257     }
5258     src_img->needPreblending = compositionInfo.mNeedPreblending;
5259 
5260     dst_img->fullWidth = mXres;
5261     dst_img->fullHeight = mYres;
5262     /* To do */
5263     /* Fb crop should be set hear */
5264     dst_img->x = 0;
5265     dst_img->y = 0;
5266     dst_img->w = mXres;
5267     dst_img->h = mYres;
5268 
5269     dst_img->bufferHandle = NULL;
5270     dst_img->format = HAL_PIXEL_FORMAT_RGBA_8888;
5271     dst_img->usageFlags = 0;
5272 
5273     dst_img->layerFlags = 0x0;
5274     dst_img->acquireFenceFd = -1;
5275     dst_img->releaseFenceFd = -1;
5276     dst_img->dataSpace = src_img->dataSpace;
5277     if (mColorMode != HAL_COLOR_MODE_NATIVE)
5278         dst_img->dataSpace = colorModeToDataspace(mColorMode);
5279     dst_img->blending = HWC2_BLEND_MODE_NONE;
5280     dst_img->transform = 0;
5281     dst_img->compressionInfo = compositionInfo.mCompressionInfo;
5282     dst_img->planeAlpha = 1;
5283     dst_img->zOrder = src_img->zOrder;
5284 
5285     return NO_ERROR;
5286 }
5287 
initializeValidateInfos()5288 int32_t ExynosDisplay::initializeValidateInfos()
5289 {
5290     mCursorIndex = -1;
5291     for (uint32_t i = 0; i < mLayers.size(); i++) {
5292         ExynosLayer *layer = mLayers[i];
5293         layer->updateValidateCompositionType(HWC2_COMPOSITION_INVALID);
5294         layer->mOverlayInfo = 0;
5295         if ((mDisplayControl.cursorSupport == true) &&
5296             (mLayers[i]->mCompositionType == HWC2_COMPOSITION_CURSOR))
5297             mCursorIndex = i;
5298     }
5299 
5300     exynos_image src_img;
5301     exynos_image dst_img;
5302 
5303     mClientCompositionInfo.initializeInfos(this);
5304     setCompositionTargetExynosImage(COMPOSITION_CLIENT, &src_img, &dst_img);
5305     mClientCompositionInfo.setExynosImage(src_img, dst_img);
5306 
5307     mExynosCompositionInfo.initializeInfos(this);
5308     setCompositionTargetExynosImage(COMPOSITION_EXYNOS, &src_img, &dst_img);
5309     mExynosCompositionInfo.setExynosImage(src_img, dst_img);
5310 
5311     return NO_ERROR;
5312 }
5313 
addClientCompositionLayer(uint32_t layerIndex)5314 int32_t ExynosDisplay::addClientCompositionLayer(uint32_t layerIndex)
5315 {
5316     bool exynosCompositionChanged = false;
5317     int32_t ret = NO_ERROR;
5318 
5319     DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to client composition", layerIndex);
5320 
5321     if (mClientCompositionInfo.mHasCompositionLayer == false) {
5322         mClientCompositionInfo.mFirstIndex = layerIndex;
5323         mClientCompositionInfo.mLastIndex = layerIndex;
5324         mClientCompositionInfo.mHasCompositionLayer = true;
5325         return EXYNOS_ERROR_CHANGED;
5326     } else {
5327         mClientCompositionInfo.mFirstIndex = min(mClientCompositionInfo.mFirstIndex, (int32_t)layerIndex);
5328         mClientCompositionInfo.mLastIndex = max(mClientCompositionInfo.mLastIndex, (int32_t)layerIndex);
5329     }
5330     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5331             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5332 
5333     if ((mClientCompositionInfo.mFirstIndex < 0) || (mClientCompositionInfo.mLastIndex < 0))
5334     {
5335         HWC_LOGE(this, "%s:: mClientCompositionInfo.mHasCompositionLayer is true "
5336                 "but index is not valid (firstIndex: %d, lastIndex: %d)",
5337                 __func__, mClientCompositionInfo.mFirstIndex,
5338                 mClientCompositionInfo.mLastIndex);
5339         return -EINVAL;
5340     }
5341 
5342     /* handle sandwiched layers */
5343     for (uint32_t i = (uint32_t)mClientCompositionInfo.mFirstIndex + 1; i < (uint32_t)mClientCompositionInfo.mLastIndex; i++) {
5344         ExynosLayer *layer = mLayers[i];
5345         if (layer->needClearClientTarget()) {
5346             DISPLAY_LOGD(eDebugResourceManager,
5347                          "\t[%d] layer is opaque and has high or max priority (%d)", i,
5348                          layer->mOverlayPriority);
5349             continue;
5350         }
5351         if (layer->getValidateCompositionType() != HWC2_COMPOSITION_CLIENT) {
5352             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
5353             if (layer->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS)
5354                 exynosCompositionChanged = true;
5355             else {
5356                 if (layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE)
5357                     mWindowNumUsed--;
5358             }
5359             layer->resetAssignedResource();
5360             layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT, eSandwichedBetweenGLES);
5361         }
5362     }
5363 
5364     /* Check Exynos Composition info is changed */
5365     if (exynosCompositionChanged) {
5366         DISPLAY_LOGD(eDebugResourceManager, "exynos composition [%d] - [%d] is changed",
5367                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5368         uint32_t newFirstIndex = ~0;
5369         int32_t newLastIndex = -1;
5370 
5371         if ((mExynosCompositionInfo.mFirstIndex < 0) || (mExynosCompositionInfo.mLastIndex < 0))
5372         {
5373             HWC_LOGE(this, "%s:: mExynosCompositionInfo.mHasCompositionLayer should be true(%d) "
5374                     "but index is not valid (firstIndex: %d, lastIndex: %d)",
5375                     __func__, mExynosCompositionInfo.mHasCompositionLayer,
5376                     mExynosCompositionInfo.mFirstIndex,
5377                     mExynosCompositionInfo.mLastIndex);
5378             return -EINVAL;
5379         }
5380 
5381         for (uint32_t i = 0; i < mLayers.size(); i++)
5382         {
5383             ExynosLayer *exynosLayer = mLayers[i];
5384             if (exynosLayer->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS) {
5385                 newFirstIndex = min(newFirstIndex, i);
5386                 newLastIndex = max(newLastIndex, (int32_t)i);
5387             }
5388         }
5389 
5390         DISPLAY_LOGD(eDebugResourceManager, "changed exynos composition [%d] - [%d]",
5391                 newFirstIndex, newLastIndex);
5392 
5393         /* There is no exynos composition layer */
5394         if (newFirstIndex == (uint32_t)~0)
5395         {
5396             mExynosCompositionInfo.initializeInfos(this);
5397             ret = EXYNOS_ERROR_CHANGED;
5398         } else {
5399             mExynosCompositionInfo.mFirstIndex = newFirstIndex;
5400             mExynosCompositionInfo.mLastIndex = newLastIndex;
5401         }
5402     }
5403 
5404     DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", ret);
5405     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
5406             mClientCompositionInfo.mHasCompositionLayer,
5407             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5408     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition(%d) range [%d] - [%d]",
5409             mExynosCompositionInfo.mHasCompositionLayer,
5410             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5411 
5412     return ret;
5413 }
removeClientCompositionLayer(uint32_t layerIndex)5414 int32_t ExynosDisplay::removeClientCompositionLayer(uint32_t layerIndex)
5415 {
5416     int32_t ret = NO_ERROR;
5417 
5418     DISPLAY_LOGD(eDebugResourceManager, "[%d] - [%d] [%d] layer is removed from client composition",
5419             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
5420             layerIndex);
5421 
5422     /* Only first layer or last layer can be removed */
5423     if ((mClientCompositionInfo.mHasCompositionLayer == false) ||
5424         ((mClientCompositionInfo.mFirstIndex != (int32_t)layerIndex) &&
5425          (mClientCompositionInfo.mLastIndex != (int32_t)layerIndex))) {
5426         DISPLAY_LOGE("removeClientCompositionLayer() error, [%d] - [%d], layer[%d]",
5427                 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex,
5428                 layerIndex);
5429         return -EINVAL;
5430     }
5431 
5432     if (mClientCompositionInfo.mFirstIndex == mClientCompositionInfo.mLastIndex) {
5433         ExynosMPP *otfMPP = mClientCompositionInfo.mOtfMPP;
5434         if (otfMPP != NULL)
5435             otfMPP->resetAssignedState();
5436         else {
5437             DISPLAY_LOGE("mClientCompositionInfo.mOtfMPP is NULL");
5438             return -EINVAL;
5439         }
5440         mClientCompositionInfo.initializeInfos(this);
5441         mWindowNumUsed--;
5442     } else if ((int32_t)layerIndex == mClientCompositionInfo.mFirstIndex)
5443         mClientCompositionInfo.mFirstIndex++;
5444     else
5445         mClientCompositionInfo.mLastIndex--;
5446 
5447     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition(%d) range [%d] - [%d]",
5448             mClientCompositionInfo.mHasCompositionLayer,
5449             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5450 
5451     return ret;
5452 }
5453 
hasClientComposition()5454 bool ExynosDisplay::hasClientComposition() {
5455     return mClientCompositionInfo.mHasCompositionLayer;
5456 }
5457 
addExynosCompositionLayer(uint32_t layerIndex,float totalUsedCapa)5458 int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex, float totalUsedCapa) {
5459     bool invalidFlag = false;
5460     int32_t changeFlag = NO_ERROR;
5461     int ret = 0;
5462     int32_t startIndex;
5463     int32_t endIndex;
5464 
5465     DISPLAY_LOGD(eDebugResourceManager, "[%d] layer is added to exynos composition", layerIndex);
5466 
5467     if (mExynosCompositionInfo.mHasCompositionLayer == false) {
5468         mExynosCompositionInfo.mFirstIndex = layerIndex;
5469         mExynosCompositionInfo.mLastIndex = layerIndex;
5470         mExynosCompositionInfo.mHasCompositionLayer = true;
5471         return EXYNOS_ERROR_CHANGED;
5472     } else {
5473         mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)layerIndex);
5474         mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)layerIndex);
5475     }
5476 
5477     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
5478             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5479 
5480     ExynosMPP *m2mMPP = mExynosCompositionInfo.mM2mMPP;
5481 
5482     if (m2mMPP == NULL) {
5483         DISPLAY_LOGE("exynosComposition m2mMPP is NULL");
5484         return -EINVAL;
5485     }
5486 
5487     startIndex = mExynosCompositionInfo.mFirstIndex;
5488     endIndex = mExynosCompositionInfo.mLastIndex;
5489 
5490     if ((startIndex < 0) || (endIndex < 0) ||
5491         (startIndex >= (int32_t)mLayers.size()) || (endIndex >= (int32_t)mLayers.size())) {
5492         DISPLAY_LOGE("exynosComposition invalid index (%d), (%d)", startIndex, endIndex);
5493         return -EINVAL;
5494     }
5495 
5496     int32_t maxPriorityIndex = -1;
5497 
5498     uint32_t highPriorityIndex = 0;
5499     uint32_t highPriorityNum = 0;
5500     int32_t highPriorityCheck = 0;
5501     std::vector<int32_t> highPriority;
5502     highPriority.assign(mLayers.size(), -1);
5503     /* handle sandwiched layers */
5504     for (int32_t i = startIndex; i <= endIndex; i++) {
5505         ExynosLayer *layer = mLayers[i];
5506         if (layer == NULL) {
5507             DISPLAY_LOGE("layer[%d] layer is null", i);
5508             continue;
5509         }
5510 
5511         if (layer->mOverlayPriority == ePriorityMax &&
5512                 m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO) {
5513             DISPLAY_LOGD(eDebugResourceManager, "\tG2D will be assgined for only [%d] layer", i);
5514             invalidFlag = true;
5515             maxPriorityIndex = i;
5516             continue;
5517         }
5518 
5519         if (layer->mOverlayPriority >= ePriorityHigh)
5520         {
5521             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high priority", i);
5522             highPriority[highPriorityIndex++] = i;
5523             highPriorityNum++;
5524             continue;
5525         }
5526 
5527         if (layer->getValidateCompositionType() == HWC2_COMPOSITION_EXYNOS) continue;
5528 
5529         exynos_image src_img;
5530         exynos_image dst_img;
5531         layer->setSrcExynosImage(&src_img);
5532         layer->setDstExynosImage(&dst_img);
5533         layer->setExynosMidImage(dst_img);
5534         bool isAssignable = false;
5535         if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
5536             isAssignable = m2mMPP->isAssignable(this, src_img, dst_img, totalUsedCapa);
5537 
5538         if (layer->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT) {
5539             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is client composition", i);
5540             invalidFlag = true;
5541         } else if (((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) == 0) ||
5542                    (isAssignable == false)) {
5543             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer is not supported by G2D", i);
5544             invalidFlag = true;
5545             layer->resetAssignedResource();
5546             layer->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT);
5547             if ((ret = addClientCompositionLayer(i)) < 0)
5548                 return ret;
5549             changeFlag |= ret;
5550         } else if ((layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) ||
5551                    (layer->getValidateCompositionType() == HWC2_COMPOSITION_INVALID)) {
5552             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer changed", i);
5553             layer->mOverlayInfo |= eSandwichedBetweenEXYNOS;
5554             layer->resetAssignedResource();
5555             if ((ret = m2mMPP->assignMPP(this, layer)) != NO_ERROR)
5556             {
5557                 HWC_LOGE(this, "%s:: %s MPP assignMPP() error (%d)",
5558                         __func__, m2mMPP->mName.c_str(), ret);
5559                 return ret;
5560             }
5561             if (layer->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
5562             layer->updateValidateCompositionType(HWC2_COMPOSITION_EXYNOS);
5563             mExynosCompositionInfo.mFirstIndex = min(mExynosCompositionInfo.mFirstIndex, (int32_t)i);
5564             mExynosCompositionInfo.mLastIndex = max(mExynosCompositionInfo.mLastIndex, (int32_t)i);
5565         } else {
5566             DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has known type (%d)", i,
5567                          layer->getValidateCompositionType());
5568         }
5569     }
5570 
5571     if (invalidFlag) {
5572         DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5573                 mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5574         DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d], highPriorityNum[%d]",
5575                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, highPriorityNum);
5576 
5577         if (m2mMPP->mLogicalType == MPP_LOGICAL_G2D_COMBO && maxPriorityIndex >= 0) {
5578             startIndex = mExynosCompositionInfo.mFirstIndex;
5579             endIndex = mExynosCompositionInfo.mLastIndex;
5580 
5581             for (int32_t i = startIndex; i <= endIndex; i++) {
5582                 if (mLayers[i]->mOverlayPriority == ePriorityMax ||
5583                     mLayers[i]->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT)
5584                     continue;
5585                 mLayers[i]->resetAssignedResource();
5586                 mLayers[i]->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT);
5587                 if ((ret = addClientCompositionLayer(i)) < 0)
5588                     return ret;
5589                 changeFlag |= ret;
5590             }
5591 
5592             if (mLayers[maxPriorityIndex]->getValidateCompositionType() !=
5593                 HWC2_COMPOSITION_EXYNOS) {
5594                 mLayers[maxPriorityIndex]->updateValidateCompositionType(HWC2_COMPOSITION_EXYNOS);
5595                 mLayers[maxPriorityIndex]->resetAssignedResource();
5596                 if ((ret = m2mMPP->assignMPP(this, mLayers[maxPriorityIndex])) != NO_ERROR)
5597                 {
5598                     ALOGE("%s:: %s MPP assignMPP() error (%d)",
5599                             __func__, m2mMPP->mName.c_str(), ret);
5600                     return ret;
5601                 }
5602             }
5603 
5604             mExynosCompositionInfo.mFirstIndex = maxPriorityIndex;
5605             mExynosCompositionInfo.mLastIndex = maxPriorityIndex;
5606         }
5607 
5608         /* Check if exynos comosition nests GLES composition */
5609         if ((mClientCompositionInfo.mHasCompositionLayer) &&
5610             (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mFirstIndex) &&
5611             (mClientCompositionInfo.mFirstIndex < mExynosCompositionInfo.mLastIndex) &&
5612             (mExynosCompositionInfo.mFirstIndex < mClientCompositionInfo.mLastIndex) &&
5613             (mClientCompositionInfo.mLastIndex < mExynosCompositionInfo.mLastIndex)) {
5614 
5615             if ((mClientCompositionInfo.mFirstIndex - mExynosCompositionInfo.mFirstIndex) <
5616                 (mExynosCompositionInfo.mLastIndex - mClientCompositionInfo.mLastIndex)) {
5617                 mLayers[mExynosCompositionInfo.mFirstIndex]->resetAssignedResource();
5618                 mLayers[mExynosCompositionInfo.mFirstIndex]->updateValidateCompositionType(
5619                         HWC2_COMPOSITION_CLIENT);
5620                 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mFirstIndex)) < 0)
5621                     return ret;
5622                 mExynosCompositionInfo.mFirstIndex = mClientCompositionInfo.mLastIndex + 1;
5623                 changeFlag |= ret;
5624             } else {
5625                 mLayers[mExynosCompositionInfo.mLastIndex]->resetAssignedResource();
5626                 mLayers[mExynosCompositionInfo.mLastIndex]->updateValidateCompositionType(
5627                         HWC2_COMPOSITION_CLIENT);
5628                 if ((ret = addClientCompositionLayer(mExynosCompositionInfo.mLastIndex)) < 0)
5629                     return ret;
5630                 mExynosCompositionInfo.mLastIndex = (mClientCompositionInfo.mFirstIndex - 1);
5631                 changeFlag |= ret;
5632             }
5633         }
5634     }
5635 
5636     if (highPriorityNum > 0 && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
5637         for (uint32_t i = 0; i < highPriorityNum; i++) {
5638             if ((int32_t)highPriority[i] == mExynosCompositionInfo.mFirstIndex)
5639                 mExynosCompositionInfo.mFirstIndex++;
5640             else if ((int32_t)highPriority[i] == mExynosCompositionInfo.mLastIndex)
5641                 mExynosCompositionInfo.mLastIndex--;
5642         }
5643     }
5644 
5645     if ((mExynosCompositionInfo.mFirstIndex < 0) ||
5646         (mExynosCompositionInfo.mFirstIndex >= (int)mLayers.size()) ||
5647         (mExynosCompositionInfo.mLastIndex < 0) ||
5648         (mExynosCompositionInfo.mLastIndex >= (int)mLayers.size()) ||
5649         (mExynosCompositionInfo.mFirstIndex > mExynosCompositionInfo.mLastIndex))
5650     {
5651         DISPLAY_LOGD(eDebugResourceManager, "\texynos composition is disabled, because of invalid index (%d, %d), size(%zu)",
5652                 mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex, mLayers.size());
5653         mExynosCompositionInfo.initializeInfos(this);
5654         changeFlag = EXYNOS_ERROR_CHANGED;
5655     }
5656 
5657     for (uint32_t i = 0; i < highPriorityNum; i++) {
5658         if ((mExynosCompositionInfo.mFirstIndex < (int32_t)highPriority[i]) &&
5659             ((int32_t)highPriority[i] < mExynosCompositionInfo.mLastIndex)) {
5660             highPriorityCheck = 1;
5661             break;
5662         }
5663     }
5664 
5665 
5666     if (highPriorityCheck && (m2mMPP->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
5667         startIndex = mExynosCompositionInfo.mFirstIndex;
5668         endIndex = mExynosCompositionInfo.mLastIndex;
5669         DISPLAY_LOGD(eDebugResourceManager,
5670                      "\texynos composition is disabled because of sandwiched max priority layer "
5671                      "(%d, %d)",
5672                      mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5673         for (int32_t i = startIndex; i <= endIndex; i++) {
5674             int32_t checkPri = 0;
5675             for (uint32_t j = 0; j < highPriorityNum; j++) {
5676                 if (i == (int32_t)highPriority[j]) {
5677                     checkPri = 1;
5678                     break;
5679                 }
5680             }
5681 
5682             if (checkPri)
5683                 continue;
5684 
5685             mLayers[i]->resetAssignedResource();
5686             mLayers[i]->updateValidateCompositionType(HWC2_COMPOSITION_CLIENT);
5687             if ((ret = addClientCompositionLayer(i)) < 0)
5688                 HWC_LOGE(this, "%d layer: addClientCompositionLayer() fail", i);
5689         }
5690         mExynosCompositionInfo.initializeInfos(this);
5691         changeFlag = EXYNOS_ERROR_CHANGED;
5692     }
5693 
5694     DISPLAY_LOGD(eDebugResourceManager, "\tresult changeFlag(0x%8x)", changeFlag);
5695     DISPLAY_LOGD(eDebugResourceManager, "\tClient composition range [%d] - [%d]",
5696             mClientCompositionInfo.mFirstIndex, mClientCompositionInfo.mLastIndex);
5697     DISPLAY_LOGD(eDebugResourceManager, "\tExynos composition range [%d] - [%d]",
5698             mExynosCompositionInfo.mFirstIndex, mExynosCompositionInfo.mLastIndex);
5699 
5700     return changeFlag;
5701 }
5702 
isPowerModeOff() const5703 bool ExynosDisplay::isPowerModeOff() const {
5704     ATRACE_CALL();
5705     Mutex::Autolock lock(mDisplayMutex);
5706     return mPowerModeState.has_value() && mPowerModeState.value() == HWC2_POWER_MODE_OFF;
5707 }
5708 
isSecureContentPresenting() const5709 bool ExynosDisplay::isSecureContentPresenting() const {
5710     ATRACE_CALL();
5711     Mutex::Autolock lock(mDRMutex);
5712     for (uint32_t i = 0; i < mLayers.size(); i++) {
5713         ExynosLayer *layer = mLayers[i];
5714         if (layer != NULL && layer->isDrm()) { /* there is some DRM layer */
5715             return true;
5716         }
5717     }
5718     return false;
5719 }
5720 
windowUpdateExceptions()5721 bool ExynosDisplay::windowUpdateExceptions()
5722 {
5723 
5724     if (mExynosCompositionInfo.mHasCompositionLayer) {
5725         DISPLAY_LOGD(eDebugWindowUpdate, "has exynos composition");
5726         return true;
5727     }
5728     if (mClientCompositionInfo.mHasCompositionLayer) {
5729         DISPLAY_LOGD(eDebugWindowUpdate, "has client composition");
5730         return true;
5731     }
5732 
5733     for (size_t i = 0; i < mLayers.size(); i++) {
5734         if (mLayers[i]->mM2mMPP != NULL) return true;
5735         if (mLayers[i]->mLayerBuffer == NULL) return true;
5736         if (mLayers[i]->mTransform != 0) return true;
5737     }
5738 
5739     for (size_t i = 0; i < mDpuData.configs.size(); i++) {
5740         exynos_win_config_data &config = mDpuData.configs[i];
5741         if (config.state == config.WIN_STATE_BUFFER) {
5742             if (config.src.w/config.dst.w != 1 || config.src.h/config.dst.h != 1) {
5743                 DISPLAY_LOGD(eDebugWindowUpdate, "Skip reason : scaled");
5744                 return true;
5745             }
5746         }
5747     }
5748 
5749     return false;
5750 }
5751 
handleWindowUpdate()5752 int ExynosDisplay::handleWindowUpdate()
5753 {
5754     int ret = NO_ERROR;
5755     // TODO will be implemented
5756     unsigned int excp;
5757 
5758     mDpuData.enable_win_update = false;
5759     /* Init with full size */
5760     mDpuData.win_update_region.x = 0;
5761     mDpuData.win_update_region.w = mXres;
5762     mDpuData.win_update_region.y = 0;
5763     mDpuData.win_update_region.h = mYres;
5764 
5765     if (exynosHWCControl.windowUpdate != 1) return 0;
5766 
5767     if (mGeometryChanged != 0) {
5768         DISPLAY_LOGD(eDebugWindowUpdate, "GEOMETRY chnaged 0x%"  PRIx64 "",
5769                 mGeometryChanged);
5770         return 0;
5771     }
5772 
5773     if ((mCursorIndex >= 0) && (mCursorIndex < (int32_t)mLayers.size())) {
5774         ExynosLayer *layer = mLayers[mCursorIndex];
5775         /* Cursor layer is enabled */
5776         if (layer->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) {
5777             return 0;
5778         }
5779     }
5780 
5781     /* exceptions */
5782     if (windowUpdateExceptions())
5783         return 0;
5784 
5785     hwc_rect mergedRect = {(int)mXres, (int)mYres, 0, 0};
5786     hwc_rect damageRect = {(int)mXres, (int)mYres, 0, 0};
5787 
5788     for (size_t i = 0; i < mLayers.size(); i++) {
5789         if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION) {
5790             continue;
5791         }
5792         excp = getLayerRegion(mLayers[i], &damageRect, eDamageRegionByDamage);
5793         if (excp == eDamageRegionPartial) {
5794             DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) partial : %d, %d, %d, %d", i,
5795                     damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
5796             mergedRect = expand(mergedRect, damageRect);
5797         }
5798         else if (excp == eDamageRegionSkip) {
5799             int32_t windowIndex = mLayers[i]->mWindowIndex;
5800             if ((ret = checkConfigDstChanged(mDpuData, mLastDpuData, windowIndex)) < 0) {
5801                 return 0;
5802             } else if (ret > 0) {
5803                 damageRect.left = mLayers[i]->mDisplayFrame.left;
5804                 damageRect.right = mLayers[i]->mDisplayFrame.right;
5805                 damageRect.top = mLayers[i]->mDisplayFrame.top;
5806                 damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
5807                 DISPLAY_LOGD(eDebugWindowUpdate, "Skip layer (origin) : %d, %d, %d, %d",
5808                         damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
5809                 mergedRect = expand(mergedRect, damageRect);
5810                 hwc_rect prevDst = {mLastDpuData.configs[i].dst.x, mLastDpuData.configs[i].dst.y,
5811                     mLastDpuData.configs[i].dst.x + (int)mLastDpuData.configs[i].dst.w,
5812                     mLastDpuData.configs[i].dst.y + (int)mLastDpuData.configs[i].dst.h};
5813                 mergedRect = expand(mergedRect, prevDst);
5814             } else {
5815                 DISPLAY_LOGD(eDebugWindowUpdate, "layer(%zu) skip", i);
5816                 continue;
5817             }
5818         }
5819         else if (excp == eDamageRegionFull) {
5820             damageRect.left = mLayers[i]->mDisplayFrame.left;
5821             damageRect.top = mLayers[i]->mDisplayFrame.top;
5822             damageRect.right = mLayers[i]->mDisplayFrame.right;
5823             damageRect.bottom = mLayers[i]->mDisplayFrame.bottom;
5824             DISPLAY_LOGD(eDebugWindowUpdate, "Full layer update : %d, %d, %d, %d", mLayers[i]->mDisplayFrame.left,
5825                     mLayers[i]->mDisplayFrame.top, mLayers[i]->mDisplayFrame.right, mLayers[i]->mDisplayFrame.bottom);
5826             mergedRect = expand(mergedRect, damageRect);
5827         }
5828         else {
5829             DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, Skip reason (layer %zu) : %d", i, excp);
5830             return 0;
5831         }
5832     }
5833 
5834     if (mergedRect.left == (int32_t)mXres && mergedRect.right == 0 &&
5835         mergedRect.top == (int32_t)mYres && mergedRect.bottom == 0) {
5836         DISPLAY_LOGD(eDebugWindowUpdate, "Partial canceled, All layer skiped" );
5837         return 0;
5838     }
5839 
5840     DISPLAY_LOGD(eDebugWindowUpdate, "Partial(origin) : %d, %d, %d, %d",
5841             mergedRect.left, mergedRect.top, mergedRect.right, mergedRect.bottom);
5842 
5843     if (mergedRect.left < 0) mergedRect.left = 0;
5844     if (mergedRect.right > (int32_t)mXres) mergedRect.right = mXres;
5845     if (mergedRect.top < 0) mergedRect.top = 0;
5846     if (mergedRect.bottom > (int32_t)mYres) mergedRect.bottom = mYres;
5847 
5848     if (mergedRect.left == 0 && mergedRect.right == (int32_t)mXres &&
5849         mergedRect.top == 0 && mergedRect.bottom == (int32_t)mYres) {
5850         DISPLAY_LOGD(eDebugWindowUpdate, "Partial : Full size");
5851         mDpuData.enable_win_update = true;
5852         mDpuData.win_update_region.x = 0;
5853         mDpuData.win_update_region.w = mXres;
5854         mDpuData.win_update_region.y = 0;
5855         mDpuData.win_update_region.h = mYres;
5856         DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
5857         return 0;
5858     }
5859 
5860     mDpuData.enable_win_update = true;
5861     mDpuData.win_update_region.x = mergedRect.left;
5862     mDpuData.win_update_region.w = WIDTH(mergedRect);
5863     mDpuData.win_update_region.y = mergedRect.top;
5864     mDpuData.win_update_region.h = HEIGHT(mergedRect);
5865 
5866     DISPLAY_LOGD(eDebugWindowUpdate, "window update end ------------------");
5867     return 0;
5868 }
5869 
getLayerRegion(ExynosLayer * layer,hwc_rect * rect_area,uint32_t regionType)5870 unsigned int ExynosDisplay::getLayerRegion(ExynosLayer *layer, hwc_rect *rect_area, uint32_t regionType) {
5871 
5872     android::Vector <hwc_rect_t> hwcRects;
5873     size_t numRects = 0;
5874 
5875     rect_area->left = INT_MAX;
5876     rect_area->top = INT_MAX;
5877     rect_area->right = rect_area->bottom = 0;
5878 
5879     hwcRects = layer->mDamageRects;
5880     numRects = layer->mDamageNum;
5881 
5882     if ((numRects == 0) || (hwcRects.size() == 0))
5883         return eDamageRegionFull;
5884 
5885     if ((numRects == 1) && (hwcRects[0].left == 0) && (hwcRects[0].top == 0) &&
5886             (hwcRects[0].right == 0) && (hwcRects[0].bottom == 0))
5887         return eDamageRegionSkip;
5888 
5889     switch (regionType) {
5890     case eDamageRegionByDamage:
5891         for (size_t j = 0; j < hwcRects.size(); j++) {
5892             hwc_rect_t rect;
5893 
5894             if ((hwcRects[j].left < 0) || (hwcRects[j].top < 0) ||
5895                     (hwcRects[j].right < 0) || (hwcRects[j].bottom < 0) ||
5896                     (hwcRects[j].left >= hwcRects[j].right) || (hwcRects[j].top >= hwcRects[j].bottom) ||
5897                     (hwcRects[j].right - hwcRects[j].left > WIDTH(layer->mSourceCrop)) ||
5898                     (hwcRects[j].bottom - hwcRects[j].top > HEIGHT(layer->mSourceCrop))) {
5899                 rect_area->left = INT_MAX;
5900                 rect_area->top = INT_MAX;
5901                 rect_area->right = rect_area->bottom = 0;
5902                 return eDamageRegionFull;
5903             }
5904 
5905             rect.left = layer->mDisplayFrame.left + hwcRects[j].left - layer->mSourceCrop.left;
5906             rect.top = layer->mDisplayFrame.top + hwcRects[j].top - layer->mSourceCrop.top;
5907             rect.right = layer->mDisplayFrame.left + hwcRects[j].right - layer->mSourceCrop.left;
5908             rect.bottom = layer->mDisplayFrame.top + hwcRects[j].bottom - layer->mSourceCrop.top;
5909             DISPLAY_LOGD(eDebugWindowUpdate, "Display frame : %d, %d, %d, %d", layer->mDisplayFrame.left,
5910                     layer->mDisplayFrame.top, layer->mDisplayFrame.right, layer->mDisplayFrame.bottom);
5911             DISPLAY_LOGD(eDebugWindowUpdate, "hwcRects : %d, %d, %d, %d", hwcRects[j].left,
5912                     hwcRects[j].top, hwcRects[j].right, hwcRects[j].bottom);
5913             adjustRect(rect, INT_MAX, INT_MAX);
5914             /* Get sums of rects */
5915             *rect_area = expand(*rect_area, rect);
5916         }
5917         return eDamageRegionPartial;
5918         break;
5919     case eDamageRegionByLayer:
5920         if (layer->mLastLayerBuffer != layer->mLayerBuffer)
5921             return eDamageRegionFull;
5922         else
5923             return eDamageRegionSkip;
5924         break;
5925     default:
5926         HWC_LOGE(this, "%s:: Invalid regionType (%d)", __func__, regionType);
5927         return eDamageRegionError;
5928         break;
5929     }
5930 
5931     return eDamageRegionFull;
5932 }
5933 
getRestrictionIndex(int halFormat)5934 uint32_t ExynosDisplay::getRestrictionIndex(int halFormat)
5935 {
5936     if (isFormatRgb(halFormat))
5937         return RESTRICTION_RGB;
5938     else
5939         return RESTRICTION_YUV;
5940 }
5941 
closeFencesForSkipFrame(rendering_state renderingState)5942 void ExynosDisplay::closeFencesForSkipFrame(rendering_state renderingState)
5943 {
5944     for (size_t i=0; i < mLayers.size(); i++) {
5945         if (mLayers[i]->mAcquireFence != -1) {
5946             mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
5947                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
5948         }
5949     }
5950 
5951     if (mDpuData.readback_info.rel_fence >= 0) {
5952         mDpuData.readback_info.rel_fence =
5953             fence_close(mDpuData.readback_info.rel_fence, this,
5954                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
5955     }
5956     if (mDpuData.readback_info.acq_fence >= 0) {
5957         mDpuData.readback_info.acq_fence =
5958             fence_close(mDpuData.readback_info.acq_fence, this,
5959                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
5960     }
5961 
5962     if (renderingState >= RENDERING_STATE_VALIDATED) {
5963         if (mDisplayControl.earlyStartMPP == true) {
5964             if (mExynosCompositionInfo.mHasCompositionLayer) {
5965                 /*
5966                  * m2mMPP's release fence for dst buffer was set to
5967                  * mExynosCompositionInfo.mAcquireFence by startPostProcessing()
5968                  * in validate time.
5969                  * This fence should be passed to display driver
5970                  * but it wont't because this frame will not be presented.
5971                  * So fence should be closed.
5972                  */
5973                 mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence,
5974                         this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5975             }
5976 
5977             for (size_t i = 0; i < mLayers.size(); i++) {
5978                 exynos_image outImage;
5979                 ExynosMPP* m2mMPP = mLayers[i]->mM2mMPP;
5980                 if ((mLayers[i]->getValidateCompositionType() == HWC2_COMPOSITION_DEVICE) &&
5981                     (m2mMPP != NULL) && (m2mMPP->mAssignedDisplay == this) &&
5982                     (m2mMPP->getDstImageInfo(&outImage) == NO_ERROR)) {
5983                     if (m2mMPP->mPhysicalType == MPP_MSC) {
5984                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC);
5985                     } else if (m2mMPP->mPhysicalType == MPP_G2D) {
5986                         ALOGD("close(%d)", outImage.releaseFenceFd);
5987                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
5988                     } else {
5989                         DISPLAY_LOGE("[%zu] layer has invalid mppType(%d)", i, m2mMPP->mPhysicalType);
5990                         fence_close(outImage.releaseFenceFd, this, FENCE_TYPE_DST_RELEASE, FENCE_IP_ALL);
5991                     }
5992                     m2mMPP->resetDstReleaseFence();
5993                     ALOGD("reset buf[%d], %d", m2mMPP->mCurrentDstBuf,
5994                             m2mMPP->mDstImgs[m2mMPP->mCurrentDstBuf].acrylicReleaseFenceFd);
5995                 }
5996             }
5997         }
5998     }
5999 
6000     if (renderingState >= RENDERING_STATE_PRESENTED) {
6001         /* mAcquireFence is set after validate */
6002         mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
6003                 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
6004     }
6005 }
closeFences()6006 void ExynosDisplay::closeFences()
6007 {
6008     for (auto &config : mDpuData.configs) {
6009         if (config.acq_fence != -1)
6010             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
6011         config.acq_fence = -1;
6012         if (config.rel_fence >= 0)
6013             fence_close(config.rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP);
6014         config.rel_fence = -1;
6015     }
6016     for (auto &config : mDpuData.rcdConfigs) {
6017         if (config.acq_fence != -1)
6018             fence_close(config.acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP);
6019         config.acq_fence = -1;
6020         if (config.rel_fence >= 0)
6021             fence_close(config.rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP);
6022         config.rel_fence = -1;
6023     }
6024     for (size_t i = 0; i < mLayers.size(); i++) {
6025         if (mLayers[i]->mReleaseFence > 0) {
6026             fence_close(mLayers[i]->mReleaseFence, this,
6027                     FENCE_TYPE_SRC_RELEASE, FENCE_IP_LAYER);
6028             mLayers[i]->mReleaseFence = -1;
6029         }
6030         if ((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
6031             (mLayers[i]->mM2mMPP != NULL)) {
6032             mLayers[i]->mM2mMPP->closeFences();
6033         }
6034     }
6035     if (mExynosCompositionInfo.mHasCompositionLayer) {
6036         if (mExynosCompositionInfo.mM2mMPP == NULL)
6037         {
6038             DISPLAY_LOGE("There is exynos composition, but m2mMPP is NULL");
6039             return;
6040         }
6041         mExynosCompositionInfo.mM2mMPP->closeFences();
6042     }
6043 
6044     for (size_t i=0; i < mLayers.size(); i++) {
6045         if (mLayers[i]->mAcquireFence != -1) {
6046             mLayers[i]->mAcquireFence = fence_close(mLayers[i]->mAcquireFence, this,
6047                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
6048         }
6049     }
6050 
6051     mExynosCompositionInfo.mAcquireFence = fence_close(mExynosCompositionInfo.mAcquireFence, this,
6052             FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
6053     mClientCompositionInfo.mAcquireFence = fence_close(mClientCompositionInfo.mAcquireFence, this,
6054             FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB);
6055 
6056     if (mDpuData.retire_fence > 0)
6057         fence_close(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
6058     mDpuData.retire_fence = -1;
6059 
6060     mLastRetireFence = fence_close(mLastRetireFence, this,  FENCE_TYPE_RETIRE, FENCE_IP_DPP);
6061 
6062     if (mDpuData.readback_info.rel_fence >= 0) {
6063         mDpuData.readback_info.rel_fence =
6064             fence_close(mDpuData.readback_info.rel_fence, this,
6065                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6066     }
6067     if (mDpuData.readback_info.acq_fence >= 0) {
6068         mDpuData.readback_info.acq_fence =
6069             fence_close(mDpuData.readback_info.acq_fence, this,
6070                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
6071     }
6072 }
6073 
setHWCControl(uint32_t ctrl,int32_t val)6074 void ExynosDisplay::setHWCControl(uint32_t ctrl, int32_t val)
6075 {
6076     switch (ctrl) {
6077         case HWC_CTL_ENABLE_COMPOSITION_CROP:
6078             mDisplayControl.enableCompositionCrop = (unsigned int)val;
6079             break;
6080         case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
6081             mDisplayControl.enableExynosCompositionOptimization = (unsigned int)val;
6082             break;
6083         case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
6084             mDisplayControl.enableClientCompositionOptimization = (unsigned int)val;
6085             break;
6086         case HWC_CTL_USE_MAX_G2D_SRC:
6087             mDisplayControl.useMaxG2DSrc = (unsigned int)val;
6088             break;
6089         case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
6090             mDisplayControl.handleLowFpsLayers = (unsigned int)val;
6091             break;
6092         case HWC_CTL_ENABLE_EARLY_START_MPP:
6093             mDisplayControl.earlyStartMPP = (unsigned int)val;
6094             break;
6095         default:
6096             ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
6097             break;
6098     }
6099 }
6100 
getHdrCapabilities(uint32_t * outNumTypes,int32_t * outTypes,float * outMaxLuminance,float * outMaxAverageLuminance,float * outMinLuminance)6101 int32_t ExynosDisplay::getHdrCapabilities(uint32_t* outNumTypes,
6102         int32_t* outTypes, float* outMaxLuminance,
6103         float* outMaxAverageLuminance, float* outMinLuminance)
6104 {
6105     DISPLAY_LOGD(eDebugHWC, "HWC2: %s, %d", __func__, __LINE__);
6106 
6107     if (outNumTypes == NULL || outMaxLuminance == NULL ||
6108             outMaxAverageLuminance == NULL || outMinLuminance == NULL) {
6109         return HWC2_ERROR_BAD_PARAMETER;
6110     }
6111 
6112     if (outTypes == NULL) {
6113         /*
6114          * This function is always called twice.
6115          * outTypes is NULL in the first call and
6116          * outType is valid pointer in the second call.
6117          * Get information only in the first call.
6118          * Use saved information in the second call.
6119          */
6120         if (mDisplayInterface->updateHdrCapabilities() != NO_ERROR)
6121             return HWC2_ERROR_BAD_CONFIG;
6122     }
6123 
6124     *outMaxLuminance = mMaxLuminance;
6125     *outMaxAverageLuminance = mMaxAverageLuminance;
6126     *outMinLuminance = mMinLuminance;
6127 
6128     if (outTypes == NULL) {
6129         *outNumTypes = mHdrTypes.size();
6130     } else {
6131         if (*outNumTypes != mHdrTypes.size()) {
6132             ALOGE("%s:: Invalid parameter (outNumTypes: %d, mHdrTypes size: %zu",
6133                     __func__, *outNumTypes, mHdrTypes.size());
6134             return HWC2_ERROR_BAD_PARAMETER;
6135         }
6136         for(uint32_t i = 0; i < *outNumTypes; i++) {
6137             outTypes[i] = mHdrTypes[i];
6138         }
6139     }
6140     return HWC2_ERROR_NONE;
6141 }
6142 
getMountOrientation(HwcMountOrientation * orientation)6143 int32_t ExynosDisplay::getMountOrientation(HwcMountOrientation *orientation)
6144 {
6145     if (!orientation)
6146         return HWC2_ERROR_BAD_PARAMETER;
6147 
6148     *orientation = mMountOrientation;
6149     return HWC2_ERROR_NONE;
6150 }
6151 
getVrrConfigs(hwc2_config_t config)6152 std::optional<VrrConfig_t> ExynosDisplay::getVrrConfigs(hwc2_config_t config) {
6153     if (isBadConfig(config)) {
6154         return std::nullopt;
6155     }
6156     return mDisplayConfigs[config].vrrConfig;
6157 }
6158 
6159 // Support DDI scalser
setDDIScalerEnable(int __unused width,int __unused height)6160 void ExynosDisplay::setDDIScalerEnable(int __unused width, int __unused height) {
6161 }
6162 
getDDIScalerMode(int __unused width,int __unused height)6163 int ExynosDisplay::getDDIScalerMode(int __unused width, int __unused height) {
6164     return 1; // WQHD
6165 }
6166 
increaseMPPDstBufIndex()6167 void ExynosDisplay::increaseMPPDstBufIndex() {
6168     for (size_t i=0; i < mLayers.size(); i++) {
6169         if((mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
6170            (mLayers[i]->mM2mMPP != NULL)) {
6171             mLayers[i]->mM2mMPP->increaseDstBuffIndex();
6172         }
6173     }
6174 
6175     if ((mExynosCompositionInfo.mHasCompositionLayer) &&
6176         (mExynosCompositionInfo.mM2mMPP != NULL)) {
6177         mExynosCompositionInfo.mM2mMPP->increaseDstBuffIndex();
6178     }
6179 }
6180 
getReadbackBufferAttributes(int32_t * outFormat,int32_t * outDataspace)6181 int32_t ExynosDisplay::getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
6182         int32_t* /*android_dataspace_t*/ outDataspace)
6183 {
6184     int32_t ret = mDisplayInterface->getReadbackBufferAttributes(outFormat, outDataspace);
6185     if (ret == NO_ERROR) {
6186         /* Interface didn't specific set dataspace */
6187         if (*outDataspace == HAL_DATASPACE_UNKNOWN)
6188             *outDataspace = colorModeToDataspace(mColorMode);
6189         /* Set default value */
6190         if (*outDataspace == HAL_DATASPACE_UNKNOWN)
6191             *outDataspace = HAL_DATASPACE_V0_SRGB;
6192 
6193         mDisplayControl.readbackSupport = true;
6194         ALOGI("readback info: format(0x%8x), dataspace(0x%8x)", *outFormat, *outDataspace);
6195     } else {
6196         mDisplayControl.readbackSupport = false;
6197         ALOGI("readback is not supported, ret(%d)", ret);
6198         ret = HWC2_ERROR_UNSUPPORTED;
6199     }
6200     return ret;
6201 }
6202 
setReadbackBuffer(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)6203 int32_t ExynosDisplay::setReadbackBuffer(buffer_handle_t buffer,
6204         int32_t releaseFence, bool requestedService)
6205 {
6206     Mutex::Autolock lock(mDisplayMutex);
6207     int32_t ret = NO_ERROR;
6208 
6209     if (buffer == nullptr)
6210         return HWC2_ERROR_BAD_PARAMETER;
6211 
6212     if (mDisplayControl.readbackSupport) {
6213         mDpuData.enable_readback = true;
6214     } else {
6215         DISPLAY_LOGE("readback is not supported but setReadbackBuffer is called, buffer(%p), releaseFence(%d)",
6216                 buffer, releaseFence);
6217         if (releaseFence >= 0)
6218             releaseFence = fence_close(releaseFence, this,
6219                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6220         mDpuData.enable_readback = false;
6221         ret = HWC2_ERROR_UNSUPPORTED;
6222     }
6223     setReadbackBufferInternal(buffer, releaseFence, requestedService);
6224     return ret;
6225 }
6226 
setReadbackBufferInternal(buffer_handle_t buffer,int32_t releaseFence,bool requestedService)6227 void ExynosDisplay::setReadbackBufferInternal(buffer_handle_t buffer,
6228         int32_t releaseFence, bool requestedService)
6229 {
6230     if (mDpuData.readback_info.rel_fence >= 0) {
6231         mDpuData.readback_info.rel_fence =
6232             fence_close(mDpuData.readback_info.rel_fence, this,
6233                     FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB);
6234         DISPLAY_LOGE("previous readback release fence is not delivered to display device");
6235     }
6236     if (releaseFence >= 0) {
6237         setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB,
6238                      HwcFenceDirection::FROM);
6239     }
6240     mDpuData.readback_info.rel_fence = releaseFence;
6241 
6242     if (buffer != NULL)
6243         mDpuData.readback_info.handle = buffer;
6244 
6245     mDpuData.readback_info.requested_from_service = requestedService;
6246 }
6247 
getReadbackBufferFence(int32_t * outFence)6248 int32_t ExynosDisplay::getReadbackBufferFence(int32_t* outFence)
6249 {
6250     /*
6251      * acq_fence was not set or
6252      * it was already closed by error or frame skip
6253      */
6254     if (mDpuData.readback_info.acq_fence < 0) {
6255         *outFence = -1;
6256         return HWC2_ERROR_UNSUPPORTED;
6257     }
6258 
6259     *outFence = mDpuData.readback_info.acq_fence;
6260     /* Fence will be closed by caller of this function */
6261     mDpuData.readback_info.acq_fence = -1;
6262     return NO_ERROR;
6263 }
6264 
setReadbackBufferAcqFence(int32_t acqFence)6265 int32_t ExynosDisplay::setReadbackBufferAcqFence(int32_t acqFence) {
6266     if (mDpuData.readback_info.acq_fence >= 0) {
6267         mDpuData.readback_info.acq_fence =
6268             fence_close(mDpuData.readback_info.acq_fence, this,
6269                     FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP);
6270         DISPLAY_LOGE("previous readback out fence is not delivered to framework");
6271     }
6272     mDpuData.readback_info.acq_fence = acqFence;
6273     if (acqFence >= 0) {
6274         /*
6275          * Requtester of readback will get acqFence after presentDisplay
6276          * so validateFences should not check this fence
6277          * in presentDisplay so this function sets pendingAllowed parameter.
6278          */
6279         setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP,
6280                      HwcFenceDirection::FROM, true);
6281     }
6282 
6283     return NO_ERROR;
6284 }
6285 
initDisplayInterface(uint32_t __unused interfaceType)6286 void ExynosDisplay::initDisplayInterface(uint32_t __unused interfaceType)
6287 {
6288     mDisplayInterface = std::make_unique<ExynosDisplayInterface>();
6289     mDisplayInterface->init(this);
6290 }
6291 
uncacheLayerBuffers(ExynosLayer * layer,const std::vector<buffer_handle_t> & buffers,std::vector<buffer_handle_t> & outClearableBuffers)6292 int32_t ExynosDisplay::uncacheLayerBuffers(ExynosLayer* layer,
6293                                            const std::vector<buffer_handle_t>& buffers,
6294                                            std::vector<buffer_handle_t>& outClearableBuffers) {
6295     if (mPowerModeState.has_value() && mPowerModeState.value() == HWC2_POWER_MODE_OFF) {
6296         for (auto buffer : buffers) {
6297             if (layer->mLayerBuffer == buffer) {
6298                 layer->mLayerBuffer = nullptr;
6299             }
6300             if (layer->mLastLayerBuffer == buffer) {
6301                 layer->mLastLayerBuffer = nullptr;
6302             }
6303         }
6304         outClearableBuffers = buffers;
6305         return mDisplayInterface->uncacheLayerBuffers(layer, outClearableBuffers);
6306     }
6307     return NO_ERROR;
6308 }
6309 
traceLayerTypes()6310 void ExynosDisplay::traceLayerTypes() {
6311     size_t g2d_count = 0;
6312     size_t dpu_count = 0;
6313     size_t gpu_count = 0;
6314     size_t skip_count = 0;
6315     size_t rcd_count = 0;
6316     for(auto const& layer: mLayers) {
6317         switch (layer->mExynosCompositionType) {
6318             case HWC2_COMPOSITION_EXYNOS:
6319                 g2d_count++;
6320                 break;
6321             case HWC2_COMPOSITION_CLIENT:
6322                 if (layer->mCompositionType == HWC2_COMPOSITION_DEVICE) {
6323                     skip_count++;
6324                 } else {
6325                     gpu_count++;
6326                 }
6327                 break;
6328             case HWC2_COMPOSITION_DEVICE:
6329                 dpu_count++;
6330                 break;
6331             case HWC2_COMPOSITION_DISPLAY_DECORATION:
6332                 ++rcd_count;
6333                 break;
6334             default:
6335                 ALOGW("%s: Unknown layer composition type: %d", __func__,
6336                       layer->mExynosCompositionType);
6337                 break;
6338         }
6339     }
6340     DISPLAY_ATRACE_INT("HWComposer: DPU Layer", dpu_count);
6341     DISPLAY_ATRACE_INT("HWComposer: G2D Layer", g2d_count);
6342     DISPLAY_ATRACE_INT("HWComposer: GPU Layer", gpu_count);
6343     DISPLAY_ATRACE_INT("HWComposer: RCD Layer", rcd_count);
6344     DISPLAY_ATRACE_INT("HWComposer: DPU Cached Layer", skip_count);
6345     DISPLAY_ATRACE_INT("HWComposer: SF Cached Layer", mIgnoreLayers.size());
6346     DISPLAY_ATRACE_INT("HWComposer: Total Layer", mLayers.size() + mIgnoreLayers.size());
6347 }
6348 
updateBrightnessState()6349 void ExynosDisplay::updateBrightnessState() {
6350     static constexpr float kMaxCll = 10000.0;
6351     bool clientRgbHdr = false;
6352     bool instantHbm = false;
6353     bool sdrDim = false;
6354     BrightnessController::HdrLayerState hdrState = BrightnessController::HdrLayerState::kHdrNone;
6355 
6356     for (size_t i = 0; i < mLayers.size(); i++) {
6357         if (mLayers[i]->mIsHdrLayer) {
6358             // TODO(longling): Below code block for RGB HDR is obsolete also
6359             // need some fix (mExynosCompositionType is invalid at this time)
6360             if (mLayers[i]->isLayerFormatRgb()) {
6361                 auto meta = mLayers[i]->getMetaParcel();
6362                 if ((meta != nullptr) && (meta->eType & VIDEO_INFO_TYPE_HDR_STATIC) &&
6363                     meta->sHdrStaticInfo.sType1.mMaxContentLightLevel >= kMaxCll) {
6364                     // if there are one or more such layers and any one of them
6365                     // is composed by GPU, we won't dim sdr layers
6366                     if (mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_CLIENT) {
6367                         clientRgbHdr = true;
6368                     } else {
6369                         instantHbm = true;
6370                     }
6371                 }
6372             }
6373 
6374             // If any HDR layer is large, keep the state as kHdrLarge
6375             if (hdrState != BrightnessController::HdrLayerState::kHdrLarge
6376                 && mLayers[i]->getDisplayFrameArea() >= mHdrFullScrenAreaThreshold) {
6377                 hdrState = BrightnessController::HdrLayerState::kHdrLarge;
6378             } else if (hdrState == BrightnessController::HdrLayerState::kHdrNone) {
6379                 hdrState = BrightnessController::HdrLayerState::kHdrSmall;
6380             } // else keep the state (kHdrLarge or kHdrSmall) unchanged.
6381         }
6382         // SDR layers could be kept dimmed for a while after HDR is gone (DM
6383         // will animate the display brightness from HDR brightess to SDR brightness).
6384         if (mLayers[i]->mBrightness < 1.0) {
6385             sdrDim = true;
6386         }
6387     }
6388 
6389     if (mBrightnessController) {
6390         mBrightnessController->updateFrameStates(hdrState, sdrDim);
6391         mBrightnessController->processInstantHbm(instantHbm && !clientRgbHdr);
6392         mBrightnessController->updateCabcMode();
6393     }
6394 }
6395 
cleanupAfterClientDeath()6396 void ExynosDisplay::cleanupAfterClientDeath() {
6397     // Invalidate the client target buffer because it will be freed when the client dies
6398     mClientCompositionInfo.mTargetBuffer = NULL;
6399     // Invalidate the skip static flag so that we have to get a new target buffer first
6400     // before we can skip the static layers
6401     mClientCompositionInfo.mSkipStaticInitFlag = false;
6402     mClientCompositionInfo.mSkipFlag = false;
6403 }
6404 
flushDisplayBrightnessChange()6405 int32_t ExynosDisplay::flushDisplayBrightnessChange() {
6406     if (mBrightnessController) {
6407         setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
6408         if (mOperationRateManager) {
6409             mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
6410             handleTargetOperationRate();
6411         }
6412         return mBrightnessController->applyPendingChangeViaSysfs(mVsyncPeriod);
6413     }
6414     return NO_ERROR;
6415 }
6416 
6417 // we can cache the value once it is known to avoid the lock after boot
6418 // we also only actually check once per frame to keep the value internally consistent
usePowerHintSession()6419 bool ExynosDisplay::usePowerHintSession() {
6420     if (!mUsePowerHintSession.has_value() && mPowerHalHint.checkPowerHintSessionReady()) {
6421         mUsePowerHintSession = mPowerHalHint.usePowerHintSession();
6422     }
6423     return mUsePowerHintSession.value_or(false);
6424 }
6425 
getExpectedPresentTime(nsecs_t startTime)6426 nsecs_t ExynosDisplay::getExpectedPresentTime(nsecs_t startTime) {
6427     ExynosDisplay *primaryDisplay = mDevice->getDisplay(HWC_DISPLAY_PRIMARY);
6428     if (primaryDisplay) {
6429         nsecs_t out = primaryDisplay->getPendingExpectedPresentTime();
6430         if (out != 0) {
6431             return out;
6432         }
6433     }
6434     return getPredictedPresentTime(startTime);
6435 }
6436 
getPredictedPresentTime(nsecs_t startTime)6437 nsecs_t ExynosDisplay::getPredictedPresentTime(nsecs_t startTime) {
6438     auto lastRetireFenceSignalTime = getSignalTime(mLastRetireFence);
6439     auto expectedPresentTime = startTime - 1;
6440     if (lastRetireFenceSignalTime != SIGNAL_TIME_INVALID &&
6441         lastRetireFenceSignalTime != SIGNAL_TIME_PENDING) {
6442         expectedPresentTime = lastRetireFenceSignalTime + mVsyncPeriod;
6443         mRetireFencePreviousSignalTime = lastRetireFenceSignalTime;
6444     } else if (sync_wait(mLastRetireFence, 0) < 0) {
6445         // if last retire fence was not signaled, then try previous signal time
6446         if (mRetireFencePreviousSignalTime.has_value()) {
6447             expectedPresentTime = *mRetireFencePreviousSignalTime + 2 * mVsyncPeriod;
6448         }
6449         // the last retire fence acquire time can be useful where the previous fence signal time may
6450         // not be recorded yet, but it's only accurate when there is fence wait time
6451         if (mRetireFenceAcquireTime.has_value()) {
6452             expectedPresentTime =
6453                     max(expectedPresentTime, *mRetireFenceAcquireTime + 2 * mVsyncPeriod);
6454         }
6455     }
6456     if (expectedPresentTime < startTime) {
6457         ALOGV("Could not predict expected present time, fall back on target of one vsync");
6458         expectedPresentTime = startTime + mVsyncPeriod;
6459     }
6460     return expectedPresentTime;
6461 }
6462 
getPredictedDuration(bool duringValidation)6463 std::optional<nsecs_t> ExynosDisplay::getPredictedDuration(bool duringValidation) {
6464     AveragesKey beforeFenceKey(mLayers.size(), duringValidation, true);
6465     AveragesKey afterFenceKey(mLayers.size(), duringValidation, false);
6466     if (mRollingAverages.count(beforeFenceKey) == 0 || mRollingAverages.count(afterFenceKey) == 0) {
6467         return std::nullopt;
6468     }
6469     nsecs_t beforeReleaseFence = mRollingAverages[beforeFenceKey].average;
6470     nsecs_t afterReleaseFence = mRollingAverages[afterFenceKey].average;
6471     return std::make_optional(afterReleaseFence + beforeReleaseFence);
6472 }
6473 
updateAverages(nsecs_t endTime)6474 void ExynosDisplay::updateAverages(nsecs_t endTime) {
6475     if (!mRetireFenceWaitTime.has_value() || !mRetireFenceAcquireTime.has_value()) {
6476         return;
6477     }
6478     nsecs_t beforeFenceTime =
6479             mValidationDuration.value_or(0) + (*mRetireFenceWaitTime - mPresentStartTime);
6480     nsecs_t afterFenceTime = endTime - *mRetireFenceAcquireTime;
6481     mRollingAverages[AveragesKey(mLayers.size(), mValidationDuration.has_value(), true)].insert(
6482             beforeFenceTime);
6483     mRollingAverages[AveragesKey(mLayers.size(), mValidationDuration.has_value(), false)].insert(
6484             afterFenceTime);
6485 }
6486 
getRCDLayerSupport(bool & outSupport) const6487 int32_t ExynosDisplay::getRCDLayerSupport(bool &outSupport) const {
6488     outSupport = mDebugRCDLayerEnabled && mDpuData.rcdConfigs.size() > 0;
6489     return NO_ERROR;
6490 }
6491 
setDebugRCDLayerEnabled(bool enable)6492 int32_t ExynosDisplay::setDebugRCDLayerEnabled(bool enable) {
6493     mDebugRCDLayerEnabled = enable;
6494     return NO_ERROR;
6495 }
6496 
getDisplayIdleTimerSupport(bool & outSupport)6497 int32_t ExynosDisplay::getDisplayIdleTimerSupport(bool &outSupport) {
6498     return mDisplayInterface->getDisplayIdleTimerSupport(outSupport);
6499 }
6500 
getDisplayMultiThreadedPresentSupport(bool & outSupport)6501 int32_t ExynosDisplay::getDisplayMultiThreadedPresentSupport(bool &outSupport) {
6502     outSupport = mDisplayControl.multiThreadedPresent;
6503     return NO_ERROR;
6504 }
6505 
isMixedComposition()6506 bool ExynosDisplay::isMixedComposition() {
6507     for (size_t i = 0; i < mLayers.size(); i++) {
6508         if (mLayers[i]->mBrightness < 1.0) {
6509             return true;
6510         }
6511     }
6512     return false;
6513 }
6514 
lookupDisplayConfigs(const int32_t & width,const int32_t & height,const int32_t & fps,const int32_t & vsyncRate,int32_t * outConfig)6515 int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
6516                                         const int32_t &height,
6517                                         const int32_t &fps,
6518                                         const int32_t &vsyncRate,
6519                                         int32_t *outConfig) {
6520     if (!fps || !vsyncRate)
6521         return HWC2_ERROR_BAD_CONFIG;
6522 
6523     constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
6524     const auto vsyncPeriod = nsecsPerSec / vsyncRate;
6525 
6526     for (auto const& [config, mode] : mDisplayConfigs) {
6527         long delta = abs(vsyncPeriod - mode.vsyncPeriod);
6528         if ((width == 0 || width == mode.width) && (height == 0 || height == mode.height) &&
6529             (delta < nsecsPerMs) && (fps == mode.refreshRate)) {
6530             ALOGD("%s: found display config for mode: %dx%d@%d:%d config=%d",
6531                  __func__, width, height, fps, vsyncRate, config);
6532             *outConfig = config;
6533             return HWC2_ERROR_NONE;
6534         }
6535     }
6536 
6537     return HWC2_ERROR_BAD_CONFIG;
6538 }
6539 
lookupDisplayConfigsRelaxed(const int32_t & width,const int32_t & height,const int32_t & fps,int32_t * outConfig)6540 int ExynosDisplay::lookupDisplayConfigsRelaxed(const int32_t &width,
6541                                                const int32_t &height,
6542                                                const int32_t &fps,
6543                                                int32_t *outConfig) {
6544     if (fps <= 1)
6545         return HWC2_ERROR_BAD_CONFIG;
6546 
6547     const auto vsyncPeriod = nsecsPerSec / fps;
6548     const auto vsyncPeriodMin = nsecsPerSec / (fps + 1);
6549     const auto vsyncPeriodMax = nsecsPerSec / (fps - 1);
6550 
6551     // Search for exact match in resolution and vsync
6552     for (auto const& [config, mode] : mDisplayConfigs) {
6553         if (mode.width == width && mode.height == height && mode.vsyncPeriod == vsyncPeriod) {
6554             ALOGD("%s: found exact match for mode %dx%d@%d -> config=%d",
6555                  __func__, width, height, fps, config);
6556             *outConfig = config;
6557             return HWC2_ERROR_NONE;
6558         }
6559     }
6560 
6561     // Search for exact match in resolution, allow small variance in vsync
6562     for (auto const& [config, mode] : mDisplayConfigs) {
6563         if (mode.width == width && mode.height == height &&
6564             mode.vsyncPeriod >= vsyncPeriodMin && mode.vsyncPeriod <= vsyncPeriodMax) {
6565             ALOGD("%s: found close match for mode %dx%d@%d -> config=%d",
6566                  __func__, width, height, fps, config);
6567             *outConfig = config;
6568             return HWC2_ERROR_NONE;
6569         }
6570     }
6571 
6572     // Search for smaller resolution, allow small variance in vsync
6573     // mDisplayConfigs is sorted, so this will give the largest available option
6574     for (auto const& [config, mode] : mDisplayConfigs) {
6575         if (mode.width <= width && mode.height <= height &&
6576             mode.vsyncPeriod >= vsyncPeriodMin && mode.vsyncPeriod <= vsyncPeriodMax) {
6577             ALOGD("%s: found relaxed match for mode %dx%d@%d -> config=%d",
6578                  __func__, width, height, fps, config);
6579             *outConfig = config;
6580             return HWC2_ERROR_NONE;
6581         }
6582     }
6583 
6584     return HWC2_ERROR_BAD_CONFIG;
6585 }
6586 
openLogFile(const std::string & filename,const std::string & mode)6587 FILE *ExynosDisplay::RotatingLogFileWriter::openLogFile(const std::string &filename,
6588                                                         const std::string &mode) {
6589     FILE *file = nullptr;
6590     auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
6591     file = fopen(fullpath.c_str(), mode.c_str());
6592     if (file != nullptr) {
6593         return file;
6594     }
6595     ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
6596     fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
6597     file = fopen(fullpath.c_str(), mode.c_str());
6598     if (file == nullptr) {
6599         ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
6600     }
6601     return file;
6602 }
6603 
getLastModifiedTimestamp(const std::string & filename)6604 std::optional<nsecs_t> ExynosDisplay::RotatingLogFileWriter::getLastModifiedTimestamp(
6605         const std::string &filename) {
6606     struct stat fileStat;
6607     auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
6608     if (stat(fullpath.c_str(), &fileStat) == 0) {
6609         return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
6610     }
6611     fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
6612     if (stat(fullpath.c_str(), &fileStat) == 0) {
6613         return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
6614     }
6615     return std::nullopt;
6616 }
6617 
chooseOpenedFile()6618 bool ExynosDisplay::RotatingLogFileWriter::chooseOpenedFile() {
6619     if (mLastFileIndex < 0) {
6620         // HWC could be restarted, so choose to open new file or continue the last modified file
6621         int chosenIndex = 0;
6622         nsecs_t lastModifTimestamp = 0;
6623         for (int i = 0; i < mMaxFileCount; ++i) {
6624             auto timestamp = getLastModifiedTimestamp(mPrefixName + std::to_string(i) + mExtension);
6625             if (!timestamp.has_value()) {
6626                 chosenIndex = i;
6627                 break;
6628             }
6629             if (i == 0 || lastModifTimestamp < *timestamp) {
6630                 chosenIndex = i;
6631                 lastModifTimestamp = *timestamp;
6632             }
6633         }
6634         auto filename = mPrefixName + std::to_string(chosenIndex) + mExtension;
6635         mFile = openLogFile(filename, "ab");
6636         if (mFile == nullptr) {
6637             ALOGE("Unable to open log file for %s", filename.c_str());
6638             return false;
6639         }
6640         mLastFileIndex = chosenIndex;
6641     }
6642 
6643     // Choose to use the same last file or move on to the next file
6644     for (int i = 0; i < 2; ++i) {
6645         if (mFile == nullptr) {
6646             mFile = openLogFile(mPrefixName + std::to_string(mLastFileIndex) + mExtension,
6647                                 (i == 0) ? "ab" : "wb");
6648         }
6649         if (mFile != nullptr) {
6650             auto fileSize = ftell(mFile);
6651             if (fileSize < mThresholdSizePerFile) return true;
6652             fclose(mFile);
6653             mFile = nullptr;
6654         }
6655         mLastFileIndex = (mLastFileIndex + 1) % mMaxFileCount;
6656     }
6657     return false;
6658 }
6659 
invalidate()6660 void ExynosDisplay::invalidate() {
6661     mDevice->onRefresh(mDisplayId);
6662 }
6663 
checkHotplugEventUpdated(bool & hpdStatus)6664 bool ExynosDisplay::checkHotplugEventUpdated(bool &hpdStatus) {
6665     if (mDisplayInterface == nullptr) {
6666         ALOGW("%s: mDisplayInterface == nullptr", __func__);
6667         return false;
6668     }
6669 
6670     hpdStatus = mDisplayInterface->readHotplugStatus();
6671 
6672     int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
6673 
6674     DISPLAY_LOGI("[%s] mDisplayId(%d), mIndex(%d), HPD Status(previous :%d, current : %d), "
6675                  "hotplugErrorCode=%d",
6676                  __func__, mDisplayId, mIndex, mHpdStatus, hpdStatus, hotplugErrorCode);
6677 
6678     return (mHpdStatus != hpdStatus) || (hotplugErrorCode != 0);
6679 }
6680 
handleHotplugEvent(bool hpdStatus)6681 void ExynosDisplay::handleHotplugEvent(bool hpdStatus) {
6682     mHpdStatus = hpdStatus;
6683 }
6684 
hotplug()6685 void ExynosDisplay::hotplug() {
6686     int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
6687     mDisplayInterface->resetHotplugErrorCode();
6688     mDevice->onHotPlug(mDisplayId, mHpdStatus, hotplugErrorCode);
6689     ALOGI("HPD callback(%s, mDisplayId %d, hotplugErrorCode=%d) was called",
6690           mHpdStatus ? "connection" : "disconnection", mDisplayId, hotplugErrorCode);
6691 }
6692 
contentProtectionUpdated(HdcpLevels hdcpLevels)6693 void ExynosDisplay::contentProtectionUpdated(HdcpLevels hdcpLevels) {
6694     mDevice->onContentProtectionUpdated(mDisplayId, hdcpLevels);
6695 }
6696 
SysfsBasedRRIHandler(ExynosDisplay * display)6697 ExynosDisplay::SysfsBasedRRIHandler::SysfsBasedRRIHandler(ExynosDisplay* display)
6698       : mDisplay(display),
6699         mLastRefreshRate(0),
6700         mLastCallbackTime(0),
6701         mIgnoringLastUpdate(false),
6702         mCanIgnoreIncreaseUpdate(false) {}
6703 
init()6704 int32_t ExynosDisplay::SysfsBasedRRIHandler::init() {
6705     auto path = String8::format(kRefreshRateStatePathFormat, mDisplay->mIndex);
6706     mFd.Set(open(path.c_str(), O_RDONLY));
6707     if (mFd.get() < 0) {
6708         ALOGE("Failed to open sysfs(%s) for refresh rate debug event: %s", path.c_str(),
6709               strerror(errno));
6710         return -errno;
6711     }
6712     auto ret = mDisplay->mDevice->mDeviceInterface->registerSysfsEventHandler(shared_from_this());
6713     if (ret != NO_ERROR) {
6714         ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret);
6715         return ret;
6716     }
6717     setAllowWakeup(true);
6718     // Call the callback immediately
6719     handleSysfsEvent();
6720     return NO_ERROR;
6721 }
6722 
disable()6723 int32_t ExynosDisplay::SysfsBasedRRIHandler::disable() {
6724     setAllowWakeup(false);
6725     return mDisplay->mDevice->mDeviceInterface->unregisterSysfsEventHandler(getFd());
6726 }
6727 
updateRefreshRateLocked(int refreshRate)6728 void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRateLocked(int refreshRate) {
6729     ATRACE_CALL();
6730     ATRACE_INT("Refresh rate indicator event", refreshRate);
6731     // Ignore refresh rate increase that is caused by refresh rate indicator update but there's
6732     // no update for the other layers
6733     if (mCanIgnoreIncreaseUpdate && refreshRate > mLastRefreshRate && mLastRefreshRate > 0 &&
6734         mDisplay->getLastLayerUpdateTime() < mLastCallbackTime) {
6735         mIgnoringLastUpdate = true;
6736         mCanIgnoreIncreaseUpdate = false;
6737         return;
6738     }
6739     mIgnoringLastUpdate = false;
6740     if (refreshRate == mLastRefreshRate) {
6741         return;
6742     }
6743     mLastRefreshRate = refreshRate;
6744     mLastCallbackTime = systemTime(CLOCK_MONOTONIC);
6745     mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / mLastRefreshRate);
6746     mCanIgnoreIncreaseUpdate = true;
6747 }
6748 
handleSysfsEvent()6749 void ExynosDisplay::SysfsBasedRRIHandler::handleSysfsEvent() {
6750     ATRACE_CALL();
6751     std::scoped_lock lock(mMutex);
6752 
6753     char buffer[1024];
6754     lseek(mFd.get(), 0, SEEK_SET);
6755     int ret = read(mFd.get(), &buffer, sizeof(buffer));
6756     if (ret < 0) {
6757         ALOGE("%s: Failed to read refresh rate from fd %d: %s", __func__, mFd.get(),
6758               strerror(errno));
6759         return;
6760     }
6761     std::string_view bufferView(buffer);
6762     auto pos = bufferView.find('@');
6763     if (pos == std::string::npos) {
6764         ALOGE("%s: Failed to parse refresh rate event (invalid format)", __func__);
6765         return;
6766     }
6767     int refreshRate = 0;
6768     std::from_chars(bufferView.data() + pos + 1, bufferView.data() + bufferView.size() - 1,
6769                     refreshRate);
6770     updateRefreshRateLocked(refreshRate);
6771 }
6772 
updateRefreshRate(int refreshRate)6773 void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRate(int refreshRate) {
6774     std::scoped_lock lock(mMutex);
6775     updateRefreshRateLocked(refreshRate);
6776 }
6777 
setAllowWakeup(const bool enabled)6778 void ExynosDisplay::SysfsBasedRRIHandler::setAllowWakeup(const bool enabled) {
6779     auto path = String8::format(kRefreshRateAllowWakeupStateChangePathFormat, mDisplay->mIndex);
6780     std::ofstream ofs(path);
6781     if (ofs.is_open()) {
6782         ofs << enabled;
6783         if (ofs.fail()) {
6784             ALOGW("%s: Failed to write %d to allow wakeup node: %d", __func__, enabled, errno);
6785         }
6786     } else {
6787         ALOGW("%s: Failed to open allow wakeup node: %d", __func__, errno);
6788     }
6789 }
6790 
setRefreshRateChangedCallbackDebugEnabled(bool enabled)6791 int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
6792     if ((!!mRefreshRateIndicatorHandler) == enabled) {
6793         ALOGW("%s: RefreshRateChangedCallbackDebug is already %s", __func__,
6794               enabled ? "enabled" : "disabled");
6795         return NO_ERROR;
6796     }
6797     int32_t ret = NO_ERROR;
6798     if (enabled) {
6799         if (mType == HWC_DISPLAY_PRIMARY) {
6800             mRefreshRateIndicatorHandler = std::make_shared<SysfsBasedRRIHandler>(this);
6801         } else {
6802             mRefreshRateIndicatorHandler = std::make_shared<ActiveConfigBasedRRIHandler>(this);
6803         }
6804         if (!mRefreshRateIndicatorHandler) {
6805             ALOGE("%s: Failed to create refresh rate debug handler", __func__);
6806             return -ENOMEM;
6807         }
6808         ret = mRefreshRateIndicatorHandler->init();
6809         if (ret != NO_ERROR) {
6810             ALOGE("%s: Failed to initialize refresh rate debug handler: %d", __func__, ret);
6811             mRefreshRateIndicatorHandler.reset();
6812             return ret;
6813         }
6814     } else {
6815         ret = mRefreshRateIndicatorHandler->disable();
6816         mRefreshRateIndicatorHandler.reset();
6817     }
6818     return ret;
6819 }
6820 
getLastLayerUpdateTime()6821 nsecs_t ExynosDisplay::getLastLayerUpdateTime() {
6822     Mutex::Autolock lock(mDRMutex);
6823     nsecs_t time = 0;
6824     for (size_t i = 0; i < mLayers.size(); ++i) {
6825         // The update from refresh rate indicator layer should be ignored
6826         if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
6827             continue;
6828         time = max(time, mLayers[i]->mLastUpdateTime);
6829     }
6830     return time;
6831 }
6832 
checkOnPresentDisplay()6833 void ExynosDisplay::SysfsBasedRRIHandler::checkOnPresentDisplay() {
6834     // Update refresh rate indicator if the last update event is ignored to make sure that
6835     // the refresh rate caused by the current frame update will be applied immediately since
6836     // we may not receive the sysfs event if the refresh rate is the same as the last ignored one.
6837     if (!mIgnoringLastUpdate) {
6838         return;
6839     }
6840     handleSysfsEvent();
6841 }
6842 
ActiveConfigBasedRRIHandler(ExynosDisplay * display)6843 ExynosDisplay::ActiveConfigBasedRRIHandler::ActiveConfigBasedRRIHandler(ExynosDisplay* display)
6844       : mDisplay(display), mLastRefreshRate(0) {}
6845 
init()6846 int32_t ExynosDisplay::ActiveConfigBasedRRIHandler::init() {
6847     updateRefreshRate(mDisplay->mRefreshRate);
6848     return NO_ERROR;
6849 }
6850 
updateRefreshRate(int refreshRate)6851 void ExynosDisplay::ActiveConfigBasedRRIHandler::updateRefreshRate(int refreshRate) {
6852     if (mLastRefreshRate == refreshRate) {
6853         return;
6854     }
6855     mLastRefreshRate = refreshRate;
6856     mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / refreshRate);
6857 }
6858 
checkOnSetActiveConfig(int refreshRate)6859 void ExynosDisplay::ActiveConfigBasedRRIHandler::checkOnSetActiveConfig(int refreshRate) {
6860     updateRefreshRate(refreshRate);
6861 }
6862 
checkUpdateRRIndicatorOnly()6863 bool ExynosDisplay::checkUpdateRRIndicatorOnly() {
6864     mUpdateRRIndicatorOnly = false;
6865     // mGeometryChanged & mBufferUpdates have already excluded any changes from RR Indicator layer.
6866     // GEOMETRY_LAYER_TYPE_CHANGED still needs to be excluded since SF sometimes could retry to use
6867     // DEVICE composition type again if it falls back to CLIENT at previous frame.
6868     if ((mGeometryChanged & ~GEOMETRY_LAYER_TYPE_CHANGED) > 0 || mBufferUpdates > 0) {
6869         return false;
6870     }
6871     Mutex::Autolock lock(mDRMutex);
6872     for (size_t i = 0; i < mLayers.size(); ++i) {
6873         const auto& layer = mLayers[i];
6874         if (layer->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) {
6875             // Sometimes, HWC could call onRefresh() so that SF would call another present without
6876             // any changes on geometry or buffers. Thus, this function should return true if only
6877             // there's any update on geometry or buffer of RR Indicator layer.
6878             mUpdateRRIndicatorOnly =
6879                     ((layer->mGeometryChanged) & ~GEOMETRY_LAYER_TYPE_CHANGED) > 0 ||
6880                     (layer->mLastLayerBuffer != layer->mLayerBuffer);
6881             return mUpdateRRIndicatorOnly;
6882         }
6883     }
6884     return false;
6885 }
6886 
isUpdateRRIndicatorOnly()6887 bool ExynosDisplay::isUpdateRRIndicatorOnly() {
6888     return mUpdateRRIndicatorOnly;
6889 }
6890 
getPeakRefreshRate()6891 uint32_t ExynosDisplay::getPeakRefreshRate() {
6892     uint32_t opRate = mBrightnessController->getOperationRate();
6893     return opRate ?: mPeakRefreshRate;
6894 }
6895 
getVsyncPeriod(const int32_t config)6896 VsyncPeriodNanos ExynosDisplay::getVsyncPeriod(const int32_t config) {
6897     const auto& it = mDisplayConfigs.find(config);
6898     if (it == mDisplayConfigs.end()) return 0;
6899     return it->second.vsyncPeriod;
6900 }
6901 
getRefreshRate(const int32_t config)6902 uint32_t ExynosDisplay::getRefreshRate(const int32_t config) {
6903     const auto& it = mDisplayConfigs.find(config);
6904     if (it == mDisplayConfigs.end()) return 0;
6905     return it->second.refreshRate;
6906 }
6907 
getConfigId(const int32_t refreshRate,const int32_t width,const int32_t height)6908 uint32_t ExynosDisplay::getConfigId(const int32_t refreshRate, const int32_t width,
6909                                     const int32_t height) {
6910     for (auto entry : mDisplayConfigs) {
6911         auto config = entry.first;
6912         auto displayCfg = entry.second;
6913         if (getRefreshRate(config) == refreshRate && displayCfg.width == width &&
6914             displayCfg.height == height) {
6915             return config;
6916         }
6917     }
6918     return UINT_MAX;
6919 }
6920 
resetColorMappingInfoForClientComp()6921 void ExynosDisplay::resetColorMappingInfoForClientComp() {
6922     if (mType != HWC_DISPLAY_PRIMARY) return;
6923 
6924     int32_t ret = NO_ERROR;
6925     for (uint32_t i = 0; i < mLayers.size(); i++) {
6926         ExynosLayer *layer = mLayers[i];
6927         if (layer->mPrevValidateCompositionType != HWC2_COMPOSITION_CLIENT &&
6928             layer->getValidateCompositionType() == HWC2_COMPOSITION_CLIENT) {
6929             if ((ret = resetColorMappingInfo(layer)) != NO_ERROR) {
6930                 DISPLAY_LOGE("%s:: resetColorMappingInfo() idx=%d error(%d)", __func__, i, ret);
6931             }
6932         }
6933     }
6934 
6935     // when no GPU composition, resets the mapping info of client composition info
6936     if (mClientCompositionInfo.mPrevHasCompositionLayer &&
6937         !mClientCompositionInfo.mHasCompositionLayer) {
6938         if ((ret = resetColorMappingInfo(&mClientCompositionInfo)) != NO_ERROR) {
6939             DISPLAY_LOGE("%s:: resetColorMappingInfo() for client target error(%d)", __func__, ret);
6940         }
6941     }
6942 }
6943 
storePrevValidateCompositionType()6944 void ExynosDisplay::storePrevValidateCompositionType() {
6945     for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
6946         ExynosLayer *layer = mIgnoreLayers[i];
6947         layer->mPrevValidateCompositionType = layer->getValidateCompositionType();
6948     }
6949 
6950     for (uint32_t i = 0; i < mLayers.size(); i++) {
6951         ExynosLayer *layer = mLayers[i];
6952         layer->mPrevValidateCompositionType = layer->getValidateCompositionType();
6953     }
6954     mClientCompositionInfo.mPrevHasCompositionLayer = mClientCompositionInfo.mHasCompositionLayer;
6955 }
6956 
getDcDisplayType() const6957 displaycolor::DisplayType ExynosDisplay::getDcDisplayType() const {
6958     switch (mType) {
6959         case HWC_DISPLAY_PRIMARY:
6960             return mIndex == 0 ? displaycolor::DisplayType::DISPLAY_PRIMARY
6961                                : displaycolor::DisplayType::DISPLAY_SECONDARY;
6962         case HWC_DISPLAY_EXTERNAL:
6963             return displaycolor::DisplayType::DISPLAY_EXTERNAL;
6964         case HWC_DISPLAY_VIRTUAL:
6965         default:
6966             DISPLAY_LOGE("%s: Unsupported display type(%d)", __func__, mType);
6967             assert(false);
6968             return displaycolor::DisplayType::DISPLAY_PRIMARY;
6969     }
6970 }
6971