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