• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #include "ExynosDevice.h"
20 
21 #include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
22 #include <sync/sync.h>
23 #include <sys/mman.h>
24 #include <unistd.h>
25 
26 #include "BrightnessController.h"
27 #include "ExynosDeviceDrmInterface.h"
28 #include "ExynosDisplay.h"
29 #include "ExynosExternalDisplayModule.h"
30 #include "ExynosHWCDebug.h"
31 #include "ExynosHWCHelper.h"
32 #include "ExynosLayer.h"
33 #include "ExynosPrimaryDisplayModule.h"
34 #include "ExynosResourceManagerModule.h"
35 #include "ExynosVirtualDisplayModule.h"
36 #include "VendorGraphicBuffer.h"
37 
38 using namespace vendor::graphics;
39 using namespace SOC_VERSION;
40 using aidl::android::hardware::graphics::composer3::IComposerCallback;
41 
42 /**
43  * ExynosDevice implementation
44  */
45 
46 class ExynosDevice;
47 
48 extern uint32_t mFenceLogSize;
49 extern void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str);
50 
51 static const std::map<const uint32_t, const std::string_view> pixelDisplayIntfName =
52         {{getDisplayId(HWC_DISPLAY_PRIMARY, 0), "default"},
53 #ifdef USES_IDISPLAY_INTF_SEC
54          {getDisplayId(HWC_DISPLAY_PRIMARY, 1), "secondary"}
55 #endif
56 };
57 
58 int hwcDebug;
59 int hwcFenceDebug[FENCE_IP_ALL];
60 struct exynos_hwc_control exynosHWCControl;
61 struct update_time_info updateTimeInfo;
62 char fence_names[FENCE_MAX][32];
63 
getDeviceInterfaceType()64 uint32_t getDeviceInterfaceType()
65 {
66     if (access(DRM_DEVICE_PATH, F_OK) == NO_ERROR)
67         return INTERFACE_TYPE_DRM;
68     else
69         return INTERFACE_TYPE_FB;
70 }
71 
ExynosDevice()72 ExynosDevice::ExynosDevice()
73     : mGeometryChanged(0),
74     mVsyncFd(-1),
75     mExtVsyncFd(-1),
76     mVsyncDisplayId(getDisplayId(HWC_DISPLAY_PRIMARY, 0)),
77     mTimestamp(0),
78     mDisplayMode(0),
79     mInterfaceType(INTERFACE_TYPE_FB),
80     mIsInTUI(false)
81 {
82     exynosHWCControl.forceGpu = false;
83     exynosHWCControl.windowUpdate = true;
84     exynosHWCControl.forcePanic = false;
85     exynosHWCControl.skipStaticLayers = true;
86     exynosHWCControl.skipM2mProcessing = true;
87     exynosHWCControl.skipResourceAssign = true;
88     exynosHWCControl.multiResolution = true;
89     exynosHWCControl.dumpMidBuf = false;
90     exynosHWCControl.displayMode = DISPLAY_MODE_NUM;
91     exynosHWCControl.setDDIScaler = false;
92     exynosHWCControl.skipWinConfig = false;
93     exynosHWCControl.skipValidate = true;
94     exynosHWCControl.doFenceFileDump = false;
95     exynosHWCControl.fenceTracer = 0;
96     exynosHWCControl.sysFenceLogging = false;
97     exynosHWCControl.useDynamicRecomp = false;
98 
99     mInterfaceType = getDeviceInterfaceType();
100 
101     ALOGD("HWC2 : %s : interface type(%d)", __func__, mInterfaceType);
102     mResourceManager = new ExynosResourceManagerModule(this);
103 
104     for (size_t i = 0; i < AVAILABLE_DISPLAY_UNITS.size(); i++) {
105         exynos_display_t display_t = AVAILABLE_DISPLAY_UNITS[i];
106         ExynosDisplay *exynos_display = NULL;
107         ALOGD("Create display[%zu] type: %d, index: %d", i, display_t.type, display_t.index);
108         switch(display_t.type) {
109             case HWC_DISPLAY_PRIMARY:
110                 exynos_display = (ExynosDisplay *)(new ExynosPrimaryDisplayModule(display_t.index, this));
111                 if(display_t.index == 0) {
112                     exynos_display->mPlugState = true;
113                     ExynosMPP::mainDisplayWidth = exynos_display->mXres;
114                     if (ExynosMPP::mainDisplayWidth <= 0) {
115                         ExynosMPP::mainDisplayWidth = 1440;
116                     }
117                     ExynosMPP::mainDisplayHeight = exynos_display->mYres;
118                     if (ExynosMPP::mainDisplayHeight <= 0) {
119                         ExynosMPP::mainDisplayHeight = 2560;
120                     }
121                 }
122                 break;
123             case HWC_DISPLAY_EXTERNAL:
124                 exynos_display = (ExynosDisplay *)(new ExynosExternalDisplayModule(display_t.index, this));
125                 break;
126             case HWC_DISPLAY_VIRTUAL:
127                 exynos_display = (ExynosDisplay *)(new ExynosVirtualDisplayModule(display_t.index, this));
128                 mNumVirtualDisplay = 0;
129                 break;
130             default:
131                 ALOGE("Unsupported display type(%d)", display_t.type);
132                 break;
133         }
134         exynos_display->mDeconNodeName.appendFormat("%s", display_t.decon_node_name.c_str());
135         exynos_display->mDisplayName.appendFormat("%s", display_t.display_name.c_str());
136         mDisplays.add(exynos_display);
137 
138 #ifndef FORCE_DISABLE_DR
139         if (exynos_display->mDREnable)
140             exynosHWCControl.useDynamicRecomp = true;
141 #endif
142     }
143 
144     memset(mCallbackInfos, 0, sizeof(mCallbackInfos));
145 
146     dynamicRecompositionThreadCreate();
147 
148     hwcDebug = 0;
149     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
150         hwcFenceDebug[i] = 0;
151 
152     for (uint32_t i = 0; i < FENCE_MAX; i++) {
153         memset(fence_names[i], 0, sizeof(fence_names[0]));
154         sprintf(fence_names[i], "_%2dh", i);
155     }
156 
157     String8 saveString;
158     saveString.appendFormat("ExynosDevice is initialized");
159     uint32_t errFileSize = saveErrorLog(saveString);
160     ALOGI("Initial errlog size: %d bytes\n", errFileSize);
161 
162     /*
163      * This order should not be changed
164      * new ExynosResourceManager ->
165      * create displays and add them to the list ->
166      * initDeviceInterface() ->
167      * ExynosResourceManager::updateRestrictions()
168      */
169     initDeviceInterface(mInterfaceType);
170     mResourceManager->updateRestrictions();
171 
172     if (mInterfaceType == INTERFACE_TYPE_DRM) {
173         /* disable vblank immediately after updates */
174         setVBlankOffDelay(-1);
175     }
176 
177     char value[PROPERTY_VALUE_MAX];
178     property_get("vendor.display.lbe.supported", value, "0");
179     const bool lbe_supported = atoi(value) ? true : false;
180 
181     for (size_t i = 0; i < mDisplays.size(); i++) {
182         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY) {
183             auto iter = pixelDisplayIntfName.find(getDisplayId(HWC_DISPLAY_PRIMARY, i));
184             if (iter != pixelDisplayIntfName.end()) {
185                 PixelDisplayInit(mDisplays[i], iter->second);
186                 if (lbe_supported) {
187                     mDisplays[i]->initLbe();
188                 }
189             }
190         }
191     }
192 
193     mDisplayOffAsync = property_get_bool("vendor.display.async_off.supported", false);
194 }
195 
initDeviceInterface(uint32_t interfaceType)196 void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
197 {
198     if (interfaceType == INTERFACE_TYPE_DRM) {
199         mDeviceInterface = std::make_unique<ExynosDeviceDrmInterface>(this);
200     } else {
201         LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
202                 __func__, interfaceType);
203     }
204 
205     mDeviceInterface->init(this);
206 
207     /* Remove display when display interface is not valid */
208     for (uint32_t i = 0; i < mDisplays.size();) {
209         ExynosDisplay* display = mDisplays[i];
210         display->initDisplayInterface(interfaceType);
211         if (mDeviceInterface->initDisplayInterface(
212                     display->mDisplayInterface) != NO_ERROR) {
213             ALOGD("Remove display[%d], Failed to initialize display interface", i);
214             mDisplays.removeAt(i);
215             delete display;
216         } else {
217             i++;
218         }
219     }
220 }
221 
~ExynosDevice()222 ExynosDevice::~ExynosDevice() {
223     mDRLoopStatus = false;
224     mDRThread.join();
225     for(auto& display : mDisplays) {
226         delete display;
227     }
228     mDisplays.clear();
229 }
230 
isFirstValidate()231 bool ExynosDevice::isFirstValidate()
232 {
233     for (uint32_t i = 0; i < mDisplays.size(); i++) {
234         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
235             (!mDisplays[i]->mPowerModeState.has_value() ||
236              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
237             continue;
238         if ((mDisplays[i]->mPlugState == true) &&
239             ((mDisplays[i]->mRenderingState != RENDERING_STATE_NONE) &&
240              (mDisplays[i]->mRenderingState != RENDERING_STATE_PRESENTED)))
241             return false;
242     }
243 
244     return true;
245 }
246 
isLastValidate(ExynosDisplay * display)247 bool ExynosDevice::isLastValidate(ExynosDisplay *display)
248 {
249     for (uint32_t i = 0; i < mDisplays.size(); i++) {
250         if (mDisplays[i] == display)
251             continue;
252         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
253             (!mDisplays[i]->mPowerModeState.has_value() ||
254              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
255             continue;
256         if ((mDisplays[i]->mPlugState == true) &&
257             (mDisplays[i]->mRenderingState != RENDERING_STATE_VALIDATED) &&
258             (mDisplays[i]->mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE))
259             return false;
260     }
261     return true;
262 }
263 
isDynamicRecompositionThreadAlive()264 bool ExynosDevice::isDynamicRecompositionThreadAlive()
265 {
266     android_atomic_acquire_load(&mDRThreadStatus);
267     return (mDRThreadStatus > 0);
268 }
269 
checkDynamicRecompositionThread()270 void ExynosDevice::checkDynamicRecompositionThread()
271 {
272     ATRACE_CALL();
273     // If thread was destroyed, create thread and run. (resume status)
274     if (isDynamicRecompositionThreadAlive() == false) {
275         for (uint32_t i = 0; i < mDisplays.size(); i++) {
276             if (mDisplays[i]->mDREnable) {
277                 dynamicRecompositionThreadCreate();
278                 return;
279             }
280         }
281     } else {
282     // If thread is running and all displays turnned off DR, destroy the thread.
283         for (uint32_t i = 0; i < mDisplays.size(); i++) {
284             if (mDisplays[i]->mDREnable)
285                 return;
286         }
287         mDRLoopStatus = false;
288         mDRWakeUpCondition.notify_one();
289         mDRThread.join();
290     }
291 }
292 
dynamicRecompositionThreadCreate()293 void ExynosDevice::dynamicRecompositionThreadCreate()
294 {
295     if (exynosHWCControl.useDynamicRecomp == true) {
296         mDRLoopStatus = true;
297         mDRThread = std::thread(&dynamicRecompositionThreadLoop, this);
298     }
299 }
300 
dynamicRecompositionThreadLoop(void * data)301 void *ExynosDevice::dynamicRecompositionThreadLoop(void *data)
302 {
303     ExynosDevice *dev = (ExynosDevice *)data;
304     ExynosDisplay *display[dev->mDisplays.size()];
305     uint64_t event_cnt[dev->mDisplays.size()];
306 
307     for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
308         display[i] = dev->mDisplays[i];
309         event_cnt[i] = 0;
310     }
311     android_atomic_inc(&(dev->mDRThreadStatus));
312 
313     while (dev->mDRLoopStatus) {
314         for (uint32_t i = 0; i < dev->mDisplays.size(); i++)
315             event_cnt[i] = display[i]->mUpdateEventCnt;
316 
317         /*
318          * If there is no update for more than 5s, favor the client composition mode.
319          * If all other conditions are met, mode will be switched to client composition.
320          */
321         {
322             std::unique_lock<std::mutex> lock(dev->mDRWakeUpMutex);
323             dev->mDRWakeUpCondition.wait_for(lock, std::chrono::seconds(5));
324             if (!dev->mDRLoopStatus) {
325                 break;
326             }
327         }
328         for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
329             if (display[i]->mDREnable &&
330                 display[i]->mPlugState == true &&
331                 event_cnt[i] == display[i]->mUpdateEventCnt) {
332                 if (display[i]->checkDynamicReCompMode() == DEVICE_2_CLIENT) {
333                     display[i]->mUpdateEventCnt = 0;
334                     display[i]->setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
335                     dev->onRefresh(display[i]->mDisplayId);
336                 }
337             }
338         }
339     }
340 
341     android_atomic_dec(&(dev->mDRThreadStatus));
342 
343     return NULL;
344 }
345 /**
346  * @param display
347  * @return ExynosDisplay
348  */
getDisplay(uint32_t display)349 ExynosDisplay* ExynosDevice::getDisplay(uint32_t display) {
350     if (mDisplays.isEmpty()) {
351         ALOGE("mDisplays.size(%zu), requested display(%d)",
352                 mDisplays.size(), display);
353         return NULL;
354     }
355 
356     for (size_t i = 0;i < mDisplays.size(); i++) {
357         if (mDisplays[i]->mDisplayId == display)
358             return (ExynosDisplay*)mDisplays[i];
359     }
360 
361     return NULL;
362 }
363 
364 /**
365  * Device Functions for HWC 2.0
366  */
367 
createVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,ExynosDisplay * display)368 int32_t ExynosDevice::createVirtualDisplay(
369         uint32_t width, uint32_t height, int32_t* /*android_pixel_format_t*/ format, ExynosDisplay* display) {
370     ((ExynosVirtualDisplay*)display)->createVirtualDisplay(width, height, format);
371     return 0;
372 }
373 
374 /**
375  * @param *display
376  * @return int32_t
377  */
destroyVirtualDisplay(ExynosDisplay * display)378 int32_t ExynosDevice::destroyVirtualDisplay(ExynosDisplay* display) {
379     ((ExynosVirtualDisplay *)display)->destroyVirtualDisplay();
380     return 0;
381 }
382 
dump(uint32_t * outSize,char * outBuffer)383 void ExynosDevice::dump(uint32_t *outSize, char *outBuffer) {
384     if (outSize == NULL) {
385         ALOGE("%s:: outSize is null", __func__);
386         return;
387     }
388 
389     String8 result;
390     dump(result);
391 
392     if (outBuffer == NULL) {
393         *outSize = static_cast<uint32_t>(result.length());
394     } else {
395         if (*outSize == 0) {
396             ALOGE("%s:: outSize is 0", __func__);
397             return;
398         }
399         size_t copySize = min(static_cast<size_t>(*outSize), result.size());
400         ALOGI("HWC dump:: resultSize(%zu), outSize(%d), copySize(%zu)", result.size(), *outSize,
401               copySize);
402         strlcpy(outBuffer, result.string(), copySize);
403     }
404 }
405 
dump(String8 & result)406 void ExynosDevice::dump(String8 &result) {
407     result.append("\n\n");
408 
409     struct tm* localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastUeventTime.tv_sec);
410     result.appendFormat("lastUeventTime(%02d:%02d:%02d.%03lu) lastTimestamp(%" PRIu64 ")\n",
411             localTime->tm_hour, localTime->tm_min,
412             localTime->tm_sec, updateTimeInfo.lastUeventTime.tv_usec/1000, mTimestamp);
413 
414     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastEnableVsyncTime.tv_sec);
415     result.appendFormat("lastEnableVsyncTime(%02d:%02d:%02d.%03lu)\n",
416             localTime->tm_hour, localTime->tm_min,
417             localTime->tm_sec, updateTimeInfo.lastEnableVsyncTime.tv_usec/1000);
418 
419     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastDisableVsyncTime.tv_sec);
420     result.appendFormat("lastDisableVsyncTime(%02d:%02d:%02d.%03lu)\n",
421             localTime->tm_hour, localTime->tm_min,
422             localTime->tm_sec, updateTimeInfo.lastDisableVsyncTime.tv_usec/1000);
423 
424     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastValidateTime.tv_sec);
425     result.appendFormat("lastValidateTime(%02d:%02d:%02d.%03lu)\n",
426             localTime->tm_hour, localTime->tm_min,
427             localTime->tm_sec, updateTimeInfo.lastValidateTime.tv_usec/1000);
428 
429     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastPresentTime.tv_sec);
430     result.appendFormat("lastPresentTime(%02d:%02d:%02d.%03lu)\n",
431             localTime->tm_hour, localTime->tm_min,
432             localTime->tm_sec, updateTimeInfo.lastPresentTime.tv_usec/1000);
433 
434     result.appendFormat("\n");
435     mResourceManager->dump(result);
436 
437     result.appendFormat("special plane num: %d:\n", getSpecialPlaneNum());
438     for (uint32_t index = 0; index < getSpecialPlaneNum(); index++) {
439         result.appendFormat("\tindex: %d attribute 0x%" PRIx64 "\n", getSpecialPlaneId(index),
440                             getSpecialPlaneAttr(index));
441     }
442     result.append("\n");
443 
444     for (size_t i = 0;i < mDisplays.size(); i++) {
445         ExynosDisplay *display = mDisplays[i];
446         if (display->mPlugState == true)
447             display->dump(result);
448     }
449 }
450 
getMaxVirtualDisplayCount()451 uint32_t ExynosDevice::getMaxVirtualDisplayCount() {
452 #ifdef USES_VIRTUAL_DISPLAY
453     return 1;
454 #else
455     return 0;
456 #endif
457 }
458 
registerCallback(int32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)459 int32_t ExynosDevice::registerCallback (
460         int32_t descriptor, hwc2_callback_data_t callbackData,
461         hwc2_function_pointer_t point) {
462     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE)
463         return HWC2_ERROR_BAD_PARAMETER;
464 
465     Mutex::Autolock lock(mDeviceCallbackMutex);
466     mCallbackInfos[descriptor].callbackData = callbackData;
467     mCallbackInfos[descriptor].funcPointer = point;
468 
469     /* Call hotplug callback for primary display*/
470     if (descriptor == HWC2_CALLBACK_HOTPLUG) {
471         HWC2_PFN_HOTPLUG callbackFunc =
472                 reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[descriptor].funcPointer);
473         if (callbackFunc != nullptr) {
474             for (auto it : mDisplays) {
475                 if (it->mPlugState)
476                     callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex),
477                             HWC2_CONNECTION_CONNECTED);
478             }
479         } else {
480             // unregistering callback can be used as a sign of ComposerClient's death
481             for (auto it : mDisplays) {
482                 it->cleanupAfterClientDeath();
483             }
484         }
485     }
486     /* TODO(b/265244856): called by register callback vsync. it's only hwc2. */
487     if (descriptor == HWC2_CALLBACK_VSYNC)
488         mResourceManager->doPreProcessing();
489 
490     return HWC2_ERROR_NONE;
491 }
492 
isCallbackRegisteredLocked(int32_t descriptor)493 bool ExynosDevice::isCallbackRegisteredLocked(int32_t descriptor) {
494     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE) {
495         ALOGE("%s:: %d callback is unknown", __func__, descriptor);
496         return false;
497     }
498 
499     if (mCallbackInfos[descriptor].callbackData == nullptr ||
500         mCallbackInfos[descriptor].funcPointer == nullptr) {
501         ALOGE("%s:: %d callback is not registered", __func__, descriptor);
502         return false;
503     }
504 
505     return true;
506 }
507 
isCallbackAvailable(int32_t descriptor)508 bool ExynosDevice::isCallbackAvailable(int32_t descriptor) {
509     Mutex::Autolock lock(mDeviceCallbackMutex);
510     return isCallbackRegisteredLocked(descriptor);
511 }
512 
onHotPlug(uint32_t displayId,bool status)513 void ExynosDevice::onHotPlug(uint32_t displayId, bool status) {
514     Mutex::Autolock lock(mDeviceCallbackMutex);
515 
516     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_HOTPLUG)) return;
517 
518     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData;
519     HWC2_PFN_HOTPLUG callbackFunc =
520             reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer);
521     callbackFunc(callbackData, displayId,
522                  status ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED);
523 }
onRefreshDisplays()524 void ExynosDevice::onRefreshDisplays() {
525     for (auto& display : mDisplays) {
526          onRefresh(display->mDisplayId);
527     }
528 }
529 
onRefresh(uint32_t displayId)530 void ExynosDevice::onRefresh(uint32_t displayId) {
531     Mutex::Autolock lock(mDeviceCallbackMutex);
532 
533     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_REFRESH)) return;
534 
535     if (!checkDisplayConnection(displayId)) return;
536 
537     ExynosDisplay *display = (ExynosDisplay *)getDisplay(displayId);
538 
539     if (!display->mPowerModeState.has_value() ||
540              (display->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
541         return;
542 
543     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData;
544     HWC2_PFN_REFRESH callbackFunc =
545             reinterpret_cast<HWC2_PFN_REFRESH>(mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer);
546     callbackFunc(callbackData, displayId);
547 }
548 
onVsync(uint32_t displayId,int64_t timestamp)549 void ExynosDevice::onVsync(uint32_t displayId, int64_t timestamp) {
550     Mutex::Autolock lock(mDeviceCallbackMutex);
551 
552     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC)) return;
553 
554     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC].callbackData;
555     HWC2_PFN_VSYNC callbackFunc =
556             reinterpret_cast<HWC2_PFN_VSYNC>(mCallbackInfos[HWC2_CALLBACK_VSYNC].funcPointer);
557     callbackFunc(callbackData, displayId, timestamp);
558 }
559 
onVsync_2_4(uint32_t displayId,int64_t timestamp,uint32_t vsyncPeriod)560 bool ExynosDevice::onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod) {
561     Mutex::Autolock lock(mDeviceCallbackMutex);
562 
563     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) return false;
564 
565     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
566     HWC2_PFN_VSYNC_2_4 callbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
567             mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
568     callbackFunc(callbackData, displayId, timestamp, vsyncPeriod);
569 
570     return true;
571 }
572 
onVsyncPeriodTimingChanged(uint32_t displayId,hwc_vsync_period_change_timeline_t * timeline)573 void ExynosDevice::onVsyncPeriodTimingChanged(uint32_t displayId,
574                                               hwc_vsync_period_change_timeline_t *timeline) {
575     Mutex::Autolock lock(mDeviceCallbackMutex);
576 
577     if (!timeline) {
578         ALOGE("vsync period change timeline is null");
579         return;
580     }
581 
582     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED)) return;
583 
584     hwc2_callback_data_t callbackData =
585             mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData;
586     HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED callbackFunc =
587             reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>(
588                     mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer);
589     callbackFunc(callbackData, displayId, timeline);
590 }
591 
setHWCDebug(unsigned int debug)592 void ExynosDevice::setHWCDebug(unsigned int debug)
593 {
594     hwcDebug = debug;
595 }
596 
getHWCDebug()597 uint32_t ExynosDevice::getHWCDebug()
598 {
599     return hwcDebug;
600 }
601 
setHWCFenceDebug(uint32_t typeNum,uint32_t ipNum,uint32_t mode)602 void ExynosDevice::setHWCFenceDebug(uint32_t typeNum, uint32_t ipNum, uint32_t mode)
603 {
604     if (typeNum > FENCE_TYPE_ALL || typeNum < 0 || ipNum > FENCE_IP_ALL || ipNum < 0
605             || mode > 1 || mode < 0) {
606         ALOGE("%s:: input is not valid type(%u), IP(%u), mode(%d)", __func__, typeNum, ipNum, mode);
607         return;
608     }
609 
610     uint32_t value = 0;
611 
612     if (typeNum == FENCE_TYPE_ALL)
613         value = (1 << FENCE_TYPE_ALL) - 1;
614     else
615         value = 1 << typeNum;
616 
617     if (ipNum == FENCE_IP_ALL) {
618         for (uint32_t i = 0; i < FENCE_IP_ALL; i++) {
619             if (mode)
620                 hwcFenceDebug[i] |= value;
621             else
622                 hwcFenceDebug[i] &= (~value);
623         }
624     } else {
625         if (mode)
626             hwcFenceDebug[ipNum] |= value;
627         else
628             hwcFenceDebug[ipNum] &= (~value);
629     }
630 
631 }
632 
getHWCFenceDebug()633 void ExynosDevice::getHWCFenceDebug()
634 {
635     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
636         ALOGE("[HWCFenceDebug] IP_Number(%d) : Debug(%x)", i, hwcFenceDebug[i]);
637 }
638 
setHWCControl(uint32_t displayId,uint32_t ctrl,int32_t val)639 void ExynosDevice::setHWCControl(uint32_t displayId, uint32_t ctrl, int32_t val) {
640     ExynosDisplay *exynosDisplay = NULL;
641     switch (ctrl) {
642         case HWC_CTL_FORCE_GPU:
643             ALOGI("%s::HWC_CTL_FORCE_GPU on/off=%d", __func__, val);
644             exynosHWCControl.forceGpu = (unsigned int)val;
645             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
646             onRefresh(displayId);
647             break;
648         case HWC_CTL_WINDOW_UPDATE:
649             ALOGI("%s::HWC_CTL_WINDOW_UPDATE on/off=%d", __func__, val);
650             exynosHWCControl.windowUpdate = (unsigned int)val;
651             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
652             onRefresh(displayId);
653             break;
654         case HWC_CTL_FORCE_PANIC:
655             ALOGI("%s::HWC_CTL_FORCE_PANIC on/off=%d", __func__, val);
656             exynosHWCControl.forcePanic = (unsigned int)val;
657             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
658             break;
659         case HWC_CTL_SKIP_STATIC:
660             ALOGI("%s::HWC_CTL_SKIP_STATIC on/off=%d", __func__, val);
661             exynosHWCControl.skipStaticLayers = (unsigned int)val;
662             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
663             break;
664         case HWC_CTL_SKIP_M2M_PROCESSING:
665             ALOGI("%s::HWC_CTL_SKIP_M2M_PROCESSING on/off=%d", __func__, val);
666             exynosHWCControl.skipM2mProcessing = (unsigned int)val;
667             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
668             break;
669         case HWC_CTL_SKIP_RESOURCE_ASSIGN:
670             ALOGI("%s::HWC_CTL_SKIP_RESOURCE_ASSIGN on/off=%d", __func__, val);
671             exynosHWCControl.skipResourceAssign = (unsigned int)val;
672             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
673             onRefreshDisplays();
674             break;
675         case HWC_CTL_SKIP_VALIDATE:
676             ALOGI("%s::HWC_CTL_SKIP_VALIDATE on/off=%d", __func__, val);
677             exynosHWCControl.skipValidate = (unsigned int)val;
678             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
679             onRefreshDisplays();
680             break;
681         case HWC_CTL_DUMP_MID_BUF:
682             ALOGI("%s::HWC_CTL_DUMP_MID_BUF on/off=%d", __func__, val);
683             exynosHWCControl.dumpMidBuf = (unsigned int)val;
684             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
685             onRefreshDisplays();
686             break;
687         case HWC_CTL_CAPTURE_READBACK:
688             captureScreenWithReadback(displayId);
689             break;
690         case HWC_CTL_DISPLAY_MODE:
691             ALOGI("%s::HWC_CTL_DISPLAY_MODE mode=%d", __func__, val);
692             setDisplayMode((uint32_t)val);
693             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
694             onRefreshDisplays();
695             break;
696         // Support DDI scalser {
697         case HWC_CTL_DDI_RESOLUTION_CHANGE:
698             ALOGI("%s::HWC_CTL_DDI_RESOLUTION_CHANGE mode=%d", __func__, val);
699             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
700             uint32_t width, height;
701 
702             /* TODO: Add branch here for each resolution/index */
703             switch(val) {
704             case 1:
705             case 2:
706             case 3:
707             default:
708                 width = 1440; height = 2960;
709                 break;
710             }
711 
712             if (exynosDisplay == NULL) {
713                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
714                     mDisplays[i]->setDDIScalerEnable(width, height);
715                 }
716             } else {
717                 exynosDisplay->setDDIScalerEnable(width, height);
718             }
719             setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
720             onRefreshDisplays();
721             break;
722         // } Support DDI scaler
723         case HWC_CTL_ENABLE_COMPOSITION_CROP:
724         case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
725         case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
726         case HWC_CTL_USE_MAX_G2D_SRC:
727         case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
728         case HWC_CTL_ENABLE_EARLY_START_MPP:
729             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
730             if (exynosDisplay == NULL) {
731                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
732                     mDisplays[i]->setHWCControl(ctrl, val);
733                 }
734             } else {
735                 exynosDisplay->setHWCControl(ctrl, val);
736             }
737             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
738             onRefreshDisplays();
739             break;
740         case HWC_CTL_DYNAMIC_RECOMP:
741             ALOGI("%s::HWC_CTL_DYNAMIC_RECOMP on/off = %d", __func__, val);
742             setDynamicRecomposition(displayId, (unsigned int)val);
743             break;
744         case HWC_CTL_ENABLE_FENCE_TRACER:
745             ALOGI("%s::HWC_CTL_ENABLE_FENCE_TRACER on/off=%d", __func__, val);
746             exynosHWCControl.fenceTracer = (unsigned int)val;
747             break;
748         case HWC_CTL_SYS_FENCE_LOGGING:
749             ALOGI("%s::HWC_CTL_SYS_FENCE_LOGGING on/off=%d", __func__, val);
750             exynosHWCControl.sysFenceLogging = (unsigned int)val;
751             break;
752         case HWC_CTL_DO_FENCE_FILE_DUMP:
753             ALOGI("%s::HWC_CTL_DO_FENCE_FILE_DUMP on/off=%d", __func__, val);
754             exynosHWCControl.doFenceFileDump = (unsigned int)val;
755             break;
756         default:
757             ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
758             break;
759     }
760 }
761 
setDisplayMode(uint32_t displayMode)762 void ExynosDevice::setDisplayMode(uint32_t displayMode)
763 {
764     exynosHWCControl.displayMode = displayMode;
765 }
766 
setDynamicRecomposition(uint32_t displayId,unsigned int on)767 void ExynosDevice::setDynamicRecomposition(uint32_t displayId, unsigned int on) {
768     exynosHWCControl.useDynamicRecomp = on;
769     ExynosDisplay *display = getDisplay(displayId);
770     if (display) {
771         display->mDRDefault = on;
772         display->mDREnable = on;
773         onRefresh(displayId);
774     }
775 }
776 
checkDisplayConnection(uint32_t displayId)777 bool ExynosDevice::checkDisplayConnection(uint32_t displayId)
778 {
779 	ExynosDisplay *display = getDisplay(displayId);
780 
781     if (!display)
782         return false;
783     else
784         return display->mPlugState;
785 }
786 
checkNonInternalConnection()787 bool ExynosDevice::checkNonInternalConnection()
788 {
789     for (uint32_t i = 0; i < mDisplays.size(); i++) {
790         switch(mDisplays[i]->mType) {
791             case HWC_DISPLAY_PRIMARY:
792                 break;
793             case HWC_DISPLAY_EXTERNAL:
794             case HWC_DISPLAY_VIRTUAL:
795                 if (mDisplays[i]->mPlugState)
796                     return true;
797                 break;
798             default:
799                 break;
800         }
801     }
802     return false;
803 }
804 
getCapabilities(uint32_t * outCount,int32_t * outCapabilities)805 void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t* outCapabilities)
806 {
807     uint32_t capabilityNum = 0;
808 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
809     capabilityNum++;
810 #endif
811 #ifdef HWC_SKIP_VALIDATE
812     capabilityNum++;
813 #endif
814     if (outCapabilities == NULL) {
815         *outCount = capabilityNum;
816         return;
817     }
818     if (capabilityNum != *outCount) {
819         ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
820         return;
821     }
822 #if defined(HWC_SUPPORT_COLOR_TRANSFORM) || defined(HWC_SKIP_VALIDATE)
823     uint32_t index = 0;
824 #endif
825 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
826     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
827 #endif
828 #ifdef HWC_SKIP_VALIDATE
829     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_VALIDATE;
830 #endif
831     return;
832 }
833 
clearGeometryChanged()834 void ExynosDevice::clearGeometryChanged()
835 {
836     mGeometryChanged = 0;
837 }
838 
canSkipValidate()839 bool ExynosDevice::canSkipValidate()
840 {
841     /*
842      * This should be called by presentDisplay()
843      * when presentDisplay() is called without validateDisplay() call
844      */
845 
846     int ret = 0;
847     if (exynosHWCControl.skipValidate == false)
848         return false;
849 
850     for (uint32_t i = 0; i < mDisplays.size(); i++) {
851         /*
852          * Check all displays.
853          * Resource assignment can have problem if validateDisplay is skipped
854          * on only some displays.
855          * All display's validateDisplay should be skipped or all display's validateDisplay
856          * should not be skipped.
857          */
858         if (mDisplays[i]->mPlugState) {
859             /*
860              * presentDisplay is called without validateDisplay.
861              * Call functions that should be called in validateDiplay
862              */
863             mDisplays[i]->doPreProcessing();
864             mDisplays[i]->checkLayerFps();
865 
866             if ((ret = mDisplays[i]->canSkipValidate()) != NO_ERROR) {
867                 HDEBUGLOGD(eDebugSkipValidate, "Display[%d] can't skip validate (%d), renderingState(%d), geometryChanged(0x%" PRIx64 ")",
868                         mDisplays[i]->mDisplayId, ret,
869                         mDisplays[i]->mRenderingState, mGeometryChanged);
870                 return false;
871             } else {
872                 HDEBUGLOGD(eDebugSkipValidate, "Display[%d] can skip validate (%d), renderingState(%d), geometryChanged(0x%" PRIx64 ")",
873                         mDisplays[i]->mDisplayId, ret,
874                         mDisplays[i]->mRenderingState, mGeometryChanged);
875             }
876         }
877     }
878     return true;
879 }
880 
validateFences(ExynosDisplay * display)881 bool ExynosDevice::validateFences(ExynosDisplay *display) {
882     std::scoped_lock lock(display->mDevice->mFenceMutex);
883 
884     if (!validateFencePerFrame(display)) {
885         ALOGE("You should doubt fence leak!");
886         saveFenceTrace(display);
887         return false;
888     }
889 
890     if (fenceWarn(display, MAX_FENCE_THRESHOLD)) {
891         printLeakFds(display);
892         saveFenceTrace(display);
893         return false;
894     }
895 
896     if (exynosHWCControl.doFenceFileDump) {
897         ALOGD("Fence file dump !");
898         if (mFenceLogSize != 0) ALOGD("Fence file not empty!");
899         saveFenceTrace(display);
900         exynosHWCControl.doFenceFileDump = false;
901     }
902 
903     return true;
904 }
905 
compareVsyncPeriod()906 void ExynosDevice::compareVsyncPeriod() {
907     /* TODO(b/265244856): to clarify what purpose of the function */
908     ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
909     ExynosDisplay *external_display = getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
910 
911     mVsyncDisplayId = getDisplayId(HWC_DISPLAY_PRIMARY, 0);
912 
913     if ((external_display == nullptr) ||
914         (!external_display->mPowerModeState.has_value() ||
915          (external_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF))) {
916         return;
917     } else if (!primary_display->mPowerModeState.has_value() ||
918                (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF)) {
919         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
920         return;
921     } else if (primary_display->mPowerModeState.has_value() &&
922                ((primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE) ||
923                 (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE_SUSPEND)) &&
924                (external_display->mVsyncPeriod >= DOZE_VSYNC_PERIOD)) { /*30fps*/
925         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
926         return;
927     } else if (primary_display->mVsyncPeriod <= external_display->mVsyncPeriod) {
928         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
929         return;
930     }
931 
932     return;
933 }
934 
captureReadbackClass(ExynosDevice * device)935 ExynosDevice::captureReadbackClass::captureReadbackClass(
936         ExynosDevice *device) :
937     mDevice(device)
938 {
939     if (device == nullptr)
940         return;
941 }
942 
~captureReadbackClass()943 ExynosDevice::captureReadbackClass::~captureReadbackClass()
944 {
945     VendorGraphicBufferMapper& gMapper(VendorGraphicBufferMapper::get());
946     if (mBuffer != nullptr)
947         gMapper.freeBuffer(mBuffer);
948 
949     if (mDevice != nullptr)
950         mDevice->clearWaitingReadbackReqDone();
951 }
952 
953 
allocBuffer(uint32_t format,uint32_t w,uint32_t h)954 int32_t ExynosDevice::captureReadbackClass::allocBuffer(
955         uint32_t format, uint32_t w, uint32_t h)
956 {
957     VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
958 
959     uint32_t dstStride = 0;
960     uint64_t usage = static_cast<uint64_t>(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER |
961             GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN);
962 
963     status_t error = NO_ERROR;
964     error = gAllocator.allocate(w, h, format, 1, usage, &mBuffer, &dstStride, "HWC");
965     if ((error != NO_ERROR) || (mBuffer == nullptr)) {
966         ALOGE("failed to allocate destination buffer(%dx%d): %d",
967                 w, h, error);
968         return static_cast<int32_t>(error);
969     }
970     return NO_ERROR;
971 }
972 
saveToFile(const String8 & fileName)973 void  ExynosDevice::captureReadbackClass::saveToFile(const String8 &fileName)
974 {
975     if (mBuffer == nullptr) {
976         ALOGE("%s:: buffer is null", __func__);
977         return;
978     }
979 
980     char filePath[MAX_DEV_NAME] = {0};
981     VendorGraphicBufferMeta gmeta(mBuffer);
982 
983     snprintf(filePath, MAX_DEV_NAME,
984             "%s/%s", WRITEBACK_CAPTURE_PATH, fileName.string());
985     FILE *fp = fopen(filePath, "w");
986     if (fp) {
987         uint32_t writeSize =
988             gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format)/8;
989         void *writebackData = mmap(0, writeSize,
990                 PROT_READ|PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
991         if (writebackData != MAP_FAILED && writebackData != NULL) {
992             size_t result = fwrite(writebackData, writeSize, 1, fp);
993             munmap(writebackData, writeSize);
994             ALOGD("Success to write %zu data, size(%d)", result, writeSize);
995         } else {
996             ALOGE("Fail to mmap");
997         }
998         fclose(fp);
999     } else {
1000         ALOGE("Fail to open %s", filePath);
1001     }
1002 }
1003 
signalReadbackDone()1004 void ExynosDevice::signalReadbackDone()
1005 {
1006     if (mIsWaitingReadbackReqDone) {
1007         Mutex::Autolock lock(mCaptureMutex);
1008         mCaptureCondition.signal();
1009     }
1010 }
1011 
captureScreenWithReadback(uint32_t displayId)1012 void ExynosDevice::captureScreenWithReadback(uint32_t displayId) {
1013     ExynosDisplay *display = getDisplay(displayId);
1014     if (display == nullptr) {
1015         ALOGE("There is no display(%d)", displayId);
1016         return;
1017     }
1018 
1019     int32_t outFormat;
1020     int32_t outDataspace;
1021     int32_t ret = 0;
1022     if ((ret = display->getReadbackBufferAttributes(
1023                 &outFormat, &outDataspace)) != HWC2_ERROR_NONE) {
1024         ALOGE("getReadbackBufferAttributes fail, ret(%d)", ret);
1025         return;
1026     }
1027 
1028     captureReadbackClass captureClass(this);
1029     if ((ret = captureClass.allocBuffer(outFormat, display->mXres, display->mYres))
1030             != NO_ERROR) {
1031         return;
1032     }
1033 
1034     mIsWaitingReadbackReqDone = true;
1035 
1036     if (display->setReadbackBuffer(captureClass.getBuffer(), -1, true) != HWC2_ERROR_NONE) {
1037         ALOGE("setReadbackBuffer fail");
1038         return;
1039     }
1040 
1041     /* Update screen */
1042     onRefresh(displayId);
1043 
1044     /* Wait for handling readback */
1045     uint32_t waitPeriod = display->mVsyncPeriod * 3;
1046     {
1047         Mutex::Autolock lock(mCaptureMutex);
1048         status_t err = mCaptureCondition.waitRelative(
1049                 mCaptureMutex, us2ns(waitPeriod));
1050         if (err == TIMED_OUT) {
1051             ALOGE("timeout, readback is not requested");
1052             return;
1053         } else if (err != NO_ERROR) {
1054             ALOGE("error waiting for readback request: %s (%d)", strerror(-err), err);
1055             return;
1056         } else {
1057             ALOGD("readback request is done");
1058         }
1059     }
1060 
1061     int32_t fence = -1;
1062     if (display->getReadbackBufferFence(&fence) != HWC2_ERROR_NONE) {
1063         ALOGE("getReadbackBufferFence fail");
1064         return;
1065     }
1066     if (sync_wait(fence, 1000) < 0) {
1067         ALOGE("sync wait error, fence(%d)", fence);
1068     }
1069     hwcFdClose(fence);
1070 
1071     String8 fileName;
1072     time_t curTime = time(NULL);
1073     struct tm *tm = localtime(&curTime);
1074     fileName.appendFormat("capture_format%d_%dx%d_%04d-%02d-%02d_%02d_%02d_%02d.raw",
1075             outFormat, display->mXres, display->mYres,
1076             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1077             tm->tm_hour, tm->tm_min, tm->tm_sec);
1078     captureClass.saveToFile(fileName);
1079 }
1080 
setDisplayDeviceMode(int32_t display_id,int32_t mode)1081 int32_t ExynosDevice::setDisplayDeviceMode(int32_t display_id, int32_t mode)
1082 {
1083     int32_t ret = HWC2_ERROR_NONE;
1084 
1085     for (size_t i = 0; i < mDisplays.size(); i++) {
1086         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY && mDisplays[i]->mDisplayId == display_id) {
1087             if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE) ||
1088                 mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
1089                 ret = mDisplays[i]->setPowerMode(mode);
1090                 if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) &&
1091                     ret == HWC2_ERROR_NONE) {
1092                     onRefresh(display_id);
1093                 }
1094                 return ret;
1095             } else {
1096                 return HWC2_ERROR_UNSUPPORTED;
1097             }
1098         }
1099     }
1100     return HWC2_ERROR_UNSUPPORTED;
1101 }
1102 
setPanelGammaTableSource(int32_t display_id,int32_t type,int32_t source)1103 int32_t ExynosDevice::setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) {
1104     if (display_id < HWC_DISPLAY_PRIMARY || display_id >= HWC_NUM_DISPLAY_TYPES) {
1105         ALOGE("invalid display %d", display_id);
1106         return HWC2_ERROR_BAD_DISPLAY;
1107     }
1108 
1109     if (type < static_cast<int32_t>(DisplayType::DISPLAY_PRIMARY) ||
1110         type >= static_cast<int32_t>(DisplayType::DISPLAY_MAX)) {
1111         ALOGE("invalid display type %d", type);
1112         return HWC2_ERROR_BAD_PARAMETER;
1113     }
1114 
1115     if (source < static_cast<int32_t>(PanelGammaSource::GAMMA_DEFAULT) ||
1116         source >= static_cast<int32_t>(PanelGammaSource::GAMMA_TYPES)) {
1117         ALOGE("invalid gamma source %d", source);
1118         return HWC2_ERROR_BAD_PARAMETER;
1119     }
1120 
1121     return mDisplays[display_id]->SetCurrentPanelGammaSource(static_cast<DisplayType>(type),
1122                                                              static_cast<PanelGammaSource>(source));
1123 }
1124 
getLayerGenericMetadataKey(uint32_t __unused keyIndex,uint32_t * outKeyLength,char * __unused outKey,bool * __unused outMandatory)1125 void ExynosDevice::getLayerGenericMetadataKey(uint32_t __unused keyIndex,
1126         uint32_t* outKeyLength, char* __unused outKey, bool* __unused outMandatory)
1127 {
1128     *outKeyLength = 0;
1129     return;
1130 }
1131 
setVBlankOffDelay(int vblankOffDelay)1132 void ExynosDevice::setVBlankOffDelay(int vblankOffDelay) {
1133     static constexpr const char *kVblankOffDelayPath = "/sys/module/drm/parameters/vblankoffdelay";
1134 
1135     writeIntToFile(kVblankOffDelayPath, vblankOffDelay);
1136 }
1137 
getWindowPlaneNum()1138 uint32_t ExynosDevice::getWindowPlaneNum()
1139 {
1140     /*
1141      * ExynosDevice supports DPU Window Composition.
1142      * The number of windows can be composited is depends on the number of DPP planes.
1143      */
1144     return mDeviceInterface->getNumDPPChs();
1145 }
1146 
getSpecialPlaneNum()1147 uint32_t ExynosDevice::getSpecialPlaneNum()
1148 {
1149     /*
1150      * ExynosDevice might support something special purpose planes.
1151      * These planes are different with DPP planes.
1152      */
1153     return mDeviceInterface->getNumSPPChs();
1154 }
1155 
getSpecialPlaneNum(uint32_t)1156 uint32_t ExynosDevice::getSpecialPlaneNum(uint32_t /*displayId*/) {
1157     /*
1158      * TODO: create the query function for each display
1159      */
1160     return mDeviceInterface->getNumSPPChs();
1161 }
1162 
getSpecialPlaneId(uint32_t index)1163 uint32_t ExynosDevice::getSpecialPlaneId(uint32_t index)
1164 {
1165     return mDeviceInterface->getSPPChId(index);
1166 }
1167 
getSpecialPlaneAttr(uint32_t index)1168 uint64_t ExynosDevice::getSpecialPlaneAttr(uint32_t index)
1169 {
1170     return mDeviceInterface->getSPPChAttr(index);
1171 }
1172 
registerHwc3Callback(uint32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)1173 int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData,
1174                                            hwc2_function_pointer_t point) {
1175     Mutex::Autolock lock(mDeviceCallbackMutex);
1176     mHwc3CallbackInfos[descriptor].callbackData = callbackData;
1177     mHwc3CallbackInfos[descriptor].funcPointer = point;
1178 
1179     return HWC2_ERROR_NONE;
1180 }
1181 
onVsyncIdle(hwc2_display_t displayId)1182 void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) {
1183     Mutex::Autolock lock(mDeviceCallbackMutex);
1184     const auto &idleCallback = mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onVsyncIdle);
1185 
1186     if (idleCallback == mHwc3CallbackInfos.end()) return;
1187 
1188     const auto &callbackInfo = idleCallback->second;
1189     if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
1190 
1191     auto callbackFunc =
1192             reinterpret_cast<void (*)(hwc2_callback_data_t callbackData,
1193                                       hwc2_display_t hwcDisplay)>(callbackInfo.funcPointer);
1194     callbackFunc(callbackInfo.callbackData, displayId);
1195 }
1196