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