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