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