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