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