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