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