• 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(bool vrrApiSupported)71 ExynosDevice::ExynosDevice(bool vrrApiSupported)
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         mVrrApiSupported(vrrApiSupported) {
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->mDRDefault) exynosHWCControl.useDynamicRecomp = true;
154 #endif
155     }
156 
157     memset(mCallbackInfos, 0, sizeof(mCallbackInfos));
158 
159     dynamicRecompositionThreadCreate();
160 
161     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
162         hwcFenceDebug[i] = 0;
163 
164     for (uint32_t i = 0; i < FENCE_MAX; i++) {
165         memset(fence_names[i], 0, sizeof(fence_names[0]));
166         sprintf(fence_names[i], "_%2dh", i);
167     }
168 
169     for (auto it : mDisplays) {
170         std::string displayName = std::string(it->mDisplayName.c_str());
171         it->mErrLogFileWriter.setPrefixName(displayName + "_hwc_error_log");
172         it->mDebugDumpFileWriter.setPrefixName(displayName + "_hwc_debug");
173         it->mFenceFileWriter.setPrefixName(displayName + "_hwc_fence_state");
174         String8 saveString;
175         saveString.appendFormat("ExynosDisplay %s is initialized", it->mDisplayName.c_str());
176         saveErrorLog(saveString, it);
177     }
178 
179     if (mInterfaceType == INTERFACE_TYPE_DRM) {
180         setVBlankOffDelay(1);
181     }
182 
183     mDisplayOffAsync = property_get_bool("vendor.display.async_off.supported", false);
184     initDeviceInterface(mInterfaceType);
185 
186     // registerRestrictions();
187     mResourceManager->updateRestrictions();
188     mResourceManager->initDisplays(mDisplays, mDisplayMap);
189 
190     char value[PROPERTY_VALUE_MAX];
191     property_get("vendor.display.lbe.supported", value, "0");
192     const bool lbe_supported = atoi(value) ? true : false;
193 
194     mNumPrimaryDisplays = 0;
195     for (size_t i = 0; i < mDisplays.size(); i++) {
196         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY) {
197             ++mNumPrimaryDisplays;
198             auto iter = pixelDisplayIntfName.find(getDisplayId(HWC_DISPLAY_PRIMARY, i));
199             if (iter != pixelDisplayIntfName.end()) {
200                 PixelDisplayInit(mDisplays[i], iter->second);
201                 if (lbe_supported) {
202                     mDisplays[i]->initLbe();
203                 }
204             }
205         }
206     }
207 }
208 
initDeviceInterface(uint32_t interfaceType)209 void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
210 {
211     if (interfaceType == INTERFACE_TYPE_DRM) {
212         mDeviceInterface = std::make_unique<ExynosDeviceDrmInterface>(this);
213     } else {
214         LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
215                 __func__, interfaceType);
216     }
217 
218     mDeviceInterface->init(this);
219 
220     /* Remove display when display interface is not valid */
221     for (uint32_t i = 0; i < mDisplays.size();) {
222         ExynosDisplay* display = mDisplays[i];
223         display->initDisplayInterface(interfaceType);
224         if (mDeviceInterface->initDisplayInterface(display->mDisplayInterface) != NO_ERROR) {
225             ALOGD("Remove display[%d], Failed to initialize display interface", i);
226             mDisplays.removeAt(i);
227             mDisplayMap.erase(display->mDisplayId);
228             delete display;
229         } else {
230             i++;
231         }
232     }
233 
234     // Call handleHotplug() to capture the initial coldplug state of each display.
235     // This is necessary because the hotplug uevent handler created in postInit()
236     // below does not get always triggered when HWC is restarting.
237     handleHotplug();
238     mDeviceInterface->postInit();
239 }
240 
~ExynosDevice()241 ExynosDevice::~ExynosDevice() {
242     mDRLoopStatus = false;
243     mDRThread.join();
244     for(auto& display : mDisplays) {
245         delete display;
246     }
247     mDisplays.clear();
248 }
249 
isFirstValidate()250 bool ExynosDevice::isFirstValidate()
251 {
252     for (uint32_t i = 0; i < mDisplays.size(); i++) {
253         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
254             (!mDisplays[i]->mPowerModeState.has_value() ||
255              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
256             continue;
257         if ((mDisplays[i]->mPlugState == true) &&
258             ((mDisplays[i]->mRenderingState != RENDERING_STATE_NONE) &&
259              (mDisplays[i]->mRenderingState != RENDERING_STATE_PRESENTED)))
260             return false;
261     }
262 
263     return true;
264 }
265 
isLastValidate(ExynosDisplay * display)266 bool ExynosDevice::isLastValidate(ExynosDisplay *display)
267 {
268     for (uint32_t i = 0; i < mDisplays.size(); i++) {
269         if (mDisplays[i] == display)
270             continue;
271         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
272             (!mDisplays[i]->mPowerModeState.has_value() ||
273              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
274             continue;
275         if ((mDisplays[i]->mPlugState == true) &&
276             (mDisplays[i]->mRenderingState != RENDERING_STATE_VALIDATED) &&
277             (mDisplays[i]->mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE))
278             return false;
279     }
280     return true;
281 }
282 
hasOtherDisplayOn(ExynosDisplay * display)283 bool ExynosDevice::hasOtherDisplayOn(ExynosDisplay *display) {
284     for (uint32_t i = 0; i < mDisplays.size(); i++) {
285         if (mDisplays[i] == display) continue;
286         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
287             mDisplays[i]->mPowerModeState.has_value() &&
288             (mDisplays[i]->mPowerModeState.value() != (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
289             return true;
290     }
291     return false;
292 }
293 
isDynamicRecompositionThreadAlive()294 bool ExynosDevice::isDynamicRecompositionThreadAlive()
295 {
296     android_atomic_acquire_load(&mDRThreadStatus);
297     return (mDRThreadStatus > 0);
298 }
299 
checkDynamicRecompositionThread()300 void ExynosDevice::checkDynamicRecompositionThread()
301 {
302     ATRACE_CALL();
303     // If thread was destroyed, create thread and run. (resume status)
304     if (isDynamicRecompositionThreadAlive() == false) {
305         for (uint32_t i = 0; i < mDisplays.size(); i++) {
306             if (mDisplays[i]->mDREnable) {
307                 dynamicRecompositionThreadCreate();
308                 return;
309             }
310         }
311     } else {
312     // If thread is running and all displays turnned off DR, destroy the thread.
313         for (uint32_t i = 0; i < mDisplays.size(); i++) {
314             if (mDisplays[i]->mDREnable)
315                 return;
316         }
317         ALOGI("Destroying dynamic recomposition thread");
318         mDRLoopStatus = false;
319         mDRWakeUpCondition.notify_one();
320         mDRThread.join();
321     }
322 }
323 
dynamicRecompositionThreadCreate()324 void ExynosDevice::dynamicRecompositionThreadCreate()
325 {
326     if (exynosHWCControl.useDynamicRecomp == true) {
327         ALOGI("Creating dynamic recomposition thread");
328         mDRLoopStatus = true;
329         mDRThread = std::thread(&dynamicRecompositionThreadLoop, this);
330     }
331 }
332 
dynamicRecompositionThreadLoop(void * data)333 void *ExynosDevice::dynamicRecompositionThreadLoop(void *data)
334 {
335     ExynosDevice *dev = (ExynosDevice *)data;
336     ExynosDisplay *display[dev->mDisplays.size()];
337     uint64_t event_cnt[dev->mDisplays.size()];
338 
339     for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
340         display[i] = dev->mDisplays[i];
341         event_cnt[i] = 0;
342     }
343     android_atomic_inc(&(dev->mDRThreadStatus));
344 
345     while (dev->mDRLoopStatus) {
346         for (uint32_t i = 0; i < dev->mDisplays.size(); i++)
347             event_cnt[i] = display[i]->mUpdateEventCnt;
348 
349         /*
350          * If there is no update for more than 5s, favor the client composition mode.
351          * If all other conditions are met, mode will be switched to client composition.
352          */
353         {
354             std::unique_lock<std::mutex> lock(dev->mDRWakeUpMutex);
355             dev->mDRWakeUpCondition.wait_for(lock, std::chrono::seconds(5));
356             if (!dev->mDRLoopStatus) {
357                 break;
358             }
359         }
360         for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
361             if (display[i]->mDREnable &&
362                 display[i]->mPlugState == true &&
363                 event_cnt[i] == display[i]->mUpdateEventCnt) {
364                 if (display[i]->checkDynamicReCompMode() == DEVICE_2_CLIENT) {
365                     display[i]->mUpdateEventCnt = 0;
366                     display[i]->setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
367                     dev->onRefresh(display[i]->mDisplayId);
368                 }
369             }
370         }
371     }
372 
373     android_atomic_dec(&(dev->mDRThreadStatus));
374 
375     return NULL;
376 }
377 
378 /**
379  * Device Functions for HWC 2.0
380  */
381 
createVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,ExynosDisplay * display)382 int32_t ExynosDevice::createVirtualDisplay(
383         uint32_t width, uint32_t height, int32_t* /*android_pixel_format_t*/ format, ExynosDisplay* display) {
384     ((ExynosVirtualDisplay*)display)->createVirtualDisplay(width, height, format);
385     return 0;
386 }
387 
388 /**
389  * @param *display
390  * @return int32_t
391  */
destroyVirtualDisplay(ExynosDisplay * display)392 int32_t ExynosDevice::destroyVirtualDisplay(ExynosDisplay* display) {
393     ((ExynosVirtualDisplay *)display)->destroyVirtualDisplay();
394     return 0;
395 }
396 
dump(uint32_t * outSize,char * outBuffer)397 void ExynosDevice::dump(uint32_t *outSize, char *outBuffer) {
398     if (outSize == NULL) {
399         ALOGE("%s:: outSize is null", __func__);
400         return;
401     }
402 
403     String8 result;
404     dump(result);
405 
406     if (outBuffer == NULL) {
407         *outSize = static_cast<uint32_t>(result.length());
408     } else {
409         if (*outSize == 0) {
410             ALOGE("%s:: outSize is 0", __func__);
411             return;
412         }
413         size_t copySize = min(static_cast<size_t>(*outSize), result.size());
414         ALOGI("HWC dump:: resultSize(%zu), outSize(%d), copySize(%zu)", result.size(), *outSize,
415               copySize);
416         strlcpy(outBuffer, result.c_str(), copySize);
417     }
418 }
419 
dump(String8 & result)420 void ExynosDevice::dump(String8 &result) {
421     result.append("\n\n");
422 
423     struct tm* localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastUeventTime.tv_sec);
424     result.appendFormat("lastUeventTime(%02d:%02d:%02d.%03lu) lastTimestamp(%" PRIu64 ")\n",
425             localTime->tm_hour, localTime->tm_min,
426             localTime->tm_sec, updateTimeInfo.lastUeventTime.tv_usec/1000, mTimestamp);
427 
428     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastEnableVsyncTime.tv_sec);
429     result.appendFormat("lastEnableVsyncTime(%02d:%02d:%02d.%03lu)\n",
430             localTime->tm_hour, localTime->tm_min,
431             localTime->tm_sec, updateTimeInfo.lastEnableVsyncTime.tv_usec/1000);
432 
433     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastDisableVsyncTime.tv_sec);
434     result.appendFormat("lastDisableVsyncTime(%02d:%02d:%02d.%03lu)\n",
435             localTime->tm_hour, localTime->tm_min,
436             localTime->tm_sec, updateTimeInfo.lastDisableVsyncTime.tv_usec/1000);
437 
438     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastValidateTime.tv_sec);
439     result.appendFormat("lastValidateTime(%02d:%02d:%02d.%03lu)\n",
440             localTime->tm_hour, localTime->tm_min,
441             localTime->tm_sec, updateTimeInfo.lastValidateTime.tv_usec/1000);
442 
443     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastPresentTime.tv_sec);
444     result.appendFormat("lastPresentTime(%02d:%02d:%02d.%03lu)\n",
445             localTime->tm_hour, localTime->tm_min,
446             localTime->tm_sec, updateTimeInfo.lastPresentTime.tv_usec/1000);
447 
448     result.appendFormat("\n");
449     mResourceManager->dump(result);
450 
451     result.appendFormat("special plane num: %d:\n", getSpecialPlaneNum());
452     for (uint32_t index = 0; index < getSpecialPlaneNum(); index++) {
453         result.appendFormat("\tindex: %d attribute 0x%" PRIx64 "\n", getSpecialPlaneId(index),
454                             getSpecialPlaneAttr(index));
455     }
456     result.append("\n");
457 
458     for (size_t i = 0;i < mDisplays.size(); i++) {
459         ExynosDisplay *display = mDisplays[i];
460         if (display->mPlugState == true)
461             display->dump(result);
462     }
463 }
464 
getMaxVirtualDisplayCount()465 uint32_t ExynosDevice::getMaxVirtualDisplayCount() {
466 #ifdef USES_VIRTUAL_DISPLAY
467     return 1;
468 #else
469     return 0;
470 #endif
471 }
472 
registerCallback(int32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)473 int32_t ExynosDevice::registerCallback (
474         int32_t descriptor, hwc2_callback_data_t callbackData,
475         hwc2_function_pointer_t point) {
476     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE)
477         return HWC2_ERROR_BAD_PARAMETER;
478 
479     Mutex::Autolock lock(mDeviceCallbackMutex);
480     mCallbackInfos[descriptor].callbackData = callbackData;
481     mCallbackInfos[descriptor].funcPointer = point;
482 
483     /* Call hotplug callback for primary display*/
484     if (descriptor == HWC2_CALLBACK_HOTPLUG) {
485         HWC2_PFN_HOTPLUG callbackFunc =
486                 reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[descriptor].funcPointer);
487         if (callbackFunc != nullptr) {
488             for (auto it : mDisplays) {
489                 if (it->mPlugState)
490                     callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex),
491                             HWC2_CONNECTION_CONNECTED);
492             }
493         } else {
494             // unregistering callback can be used as a sign of ComposerClient's death
495             for (auto it : mDisplays) {
496                 it->cleanupAfterClientDeath();
497             }
498         }
499     }
500     /* TODO(b/265244856): called by register callback vsync. it's only hwc2. */
501     if (descriptor == HWC2_CALLBACK_VSYNC)
502         mResourceManager->doPreProcessing();
503 
504     return HWC2_ERROR_NONE;
505 }
506 
isCallbackRegisteredLocked(int32_t descriptor)507 bool ExynosDevice::isCallbackRegisteredLocked(int32_t descriptor) {
508     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE) {
509         ALOGE("%s:: %d callback is unknown", __func__, descriptor);
510         return false;
511     }
512 
513     if (mCallbackInfos[descriptor].callbackData == nullptr ||
514         mCallbackInfos[descriptor].funcPointer == nullptr) {
515         ALOGE("%s:: %d callback is not registered", __func__, descriptor);
516         return false;
517     }
518 
519     return true;
520 }
521 
isCallbackAvailable(int32_t descriptor)522 bool ExynosDevice::isCallbackAvailable(int32_t descriptor) {
523     Mutex::Autolock lock(mDeviceCallbackMutex);
524     return isCallbackRegisteredLocked(descriptor);
525 }
526 
527 using DisplayHotplugEvent = aidl::android::hardware::graphics::common::DisplayHotplugEvent;
hotplug_event_to_aidl(bool connected,int hotplugErrorCode)528 DisplayHotplugEvent hotplug_event_to_aidl(bool connected, int hotplugErrorCode) {
529     switch (hotplugErrorCode) {
530         case 0:
531             return connected ? DisplayHotplugEvent::CONNECTED : DisplayHotplugEvent::DISCONNECTED;
532         case 1:
533             return DisplayHotplugEvent::ERROR_INCOMPATIBLE_CABLE;
534         default:
535             return DisplayHotplugEvent::ERROR_UNKNOWN;
536     }
537 }
538 
findPoweredOffPrimaryDisplay(ExynosDisplay * excludeDisplay)539 ExynosDisplay* ExynosDevice::findPoweredOffPrimaryDisplay(ExynosDisplay* excludeDisplay) {
540     for (auto disp : mDisplays) {
541         if (disp != excludeDisplay && disp->mType == HWC_DISPLAY_PRIMARY &&
542             disp->mPowerModeState == HWC_POWER_MODE_OFF)
543             return disp;
544     }
545     return nullptr;
546 }
547 
onHotPlug(uint32_t displayId,bool status,int hotplugErrorCode)548 void ExynosDevice::onHotPlug(uint32_t displayId, bool status, int hotplugErrorCode) {
549     Mutex::Autolock lock(mDeviceCallbackMutex);
550 
551     // If we detect a hotplug of an external display on a foldable device, and we have a
552     // primary/built-in display in a powered off state, we need to use the powered off display's
553     // crtc/decon for the external display, to ensure color management is working properly
554     // (color management is supported only on decon0/decon1). See b/329034082.
555     ExynosDisplay* hotpluggedDisplay = getDisplay(displayId);
556     if (mNumPrimaryDisplays >= 2 && hotpluggedDisplay &&
557         hotpluggedDisplay->mType == HWC_DISPLAY_EXTERNAL) {
558         ALOGD("%s: display %s pluggedIn=%d hotplugErrorCode=%d", __func__,
559               hotpluggedDisplay->mDisplayTraceName.c_str(), status, hotplugErrorCode);
560         auto hotpluggedDisplayIntf = hotpluggedDisplay->mDisplayInterface.get();
561         ExynosDisplay* borrowedCrtcFrom = hotpluggedDisplayIntf->borrowedCrtcFrom();
562         if (status && hotplugErrorCode == 0) {
563             // The external display has been connected successfully, check if we can find an
564             // available decon for it, before we start initializing it.
565             if (borrowedCrtcFrom) {
566                 ALOGW("%s: external display is already using decon of %s", __func__,
567                       borrowedCrtcFrom->mDisplayTraceName.c_str());
568                 // Restore the original decon of the external display before proceeding.
569                 hotpluggedDisplayIntf->swapCrtcs(borrowedCrtcFrom);
570             }
571             ExynosDisplay* poweredOffPrimaryDisplay = findPoweredOffPrimaryDisplay(nullptr);
572             if (poweredOffPrimaryDisplay) {
573                 hotpluggedDisplayIntf->swapCrtcs(poweredOffPrimaryDisplay);
574             } else {
575                 // There is no powered off primary display/available decon at the moment,
576                 // this means hotplug of external display happened while the foldable device
577                 // was in dual concurrent display mode. We will try to switch decon assignment
578                 // for the external display later, when one of primary displays is turned off.
579                 ALOGD("onHotPlug: No powered off primary displays found!");
580             }
581         } else {
582             // The external display has been unplugged, or plugged in, but ran into an error.
583             // Restore the original decon assigned to it, if we previously switched decons.
584             if (borrowedCrtcFrom) {
585                 hotpluggedDisplayIntf->swapCrtcs(borrowedCrtcFrom);
586             }
587         }
588     }
589 
590     // If the new HotplugEvent API is available, use it, otherwise fall back
591     // to the old V2 API with onVsync hack, if necessary.
592     const auto& hotplugEventCallback =
593             mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onHotplugEvent);
594     if (hotplugEventCallback != mHwc3CallbackInfos.end()) {
595         const auto& callbackInfo = hotplugEventCallback->second;
596         if (callbackInfo.funcPointer != nullptr && callbackInfo.callbackData != nullptr) {
597             auto callbackFunc = reinterpret_cast<
598                     void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
599                              aidl::android::hardware::graphics::common::DisplayHotplugEvent)>(
600                     callbackInfo.funcPointer);
601             callbackFunc(callbackInfo.callbackData, displayId,
602                          hotplug_event_to_aidl(status, hotplugErrorCode));
603             return;
604         }
605     }
606 
607     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_HOTPLUG)) return;
608 
609     if (hotplugErrorCode) {
610         // We need to pass the error code to SurfaceFlinger, but we cannot modify the HWC
611         // HAL interface, so for now we'll send the hotplug error via a onVsync callback with
612         // a negative time value indicating the hotplug error.
613         if (isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) {
614             ALOGD("%s: hotplugErrorCode=%d sending to SF via onVsync_2_4", __func__,
615                   hotplugErrorCode);
616             hwc2_callback_data_t vsyncCallbackData =
617                     mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
618             HWC2_PFN_VSYNC_2_4 vsyncCallbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
619                     mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
620             vsyncCallbackFunc(vsyncCallbackData, displayId, -hotplugErrorCode, ~0);
621             return;
622         } else {
623             ALOGW("%s: onVsync_2_4 is not registered, ignoring hotplugErrorCode=%d", __func__,
624                   hotplugErrorCode);
625             return;
626         }
627     }
628 
629     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData;
630     HWC2_PFN_HOTPLUG callbackFunc =
631             reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer);
632     callbackFunc(callbackData, displayId,
633                  status ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED);
634 }
635 
onRefreshDisplays()636 void ExynosDevice::onRefreshDisplays() {
637     for (auto& display : mDisplays) {
638          onRefresh(display->mDisplayId);
639     }
640 }
641 
onRefresh(uint32_t displayId)642 void ExynosDevice::onRefresh(uint32_t displayId) {
643     Mutex::Autolock lock(mDeviceCallbackMutex);
644 
645     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_REFRESH)) return;
646 
647     if (!checkDisplayConnection(displayId)) return;
648 
649     ExynosDisplay *display = (ExynosDisplay *)getDisplay(displayId);
650 
651     if (!display->mPowerModeState.has_value() ||
652              (display->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
653         return;
654 
655     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData;
656     HWC2_PFN_REFRESH callbackFunc =
657             reinterpret_cast<HWC2_PFN_REFRESH>(mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer);
658     callbackFunc(callbackData, displayId);
659 }
660 
onVsync(uint32_t displayId,int64_t timestamp)661 void ExynosDevice::onVsync(uint32_t displayId, int64_t timestamp) {
662     Mutex::Autolock lock(mDeviceCallbackMutex);
663 
664     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC)) return;
665 
666     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC].callbackData;
667     HWC2_PFN_VSYNC callbackFunc =
668             reinterpret_cast<HWC2_PFN_VSYNC>(mCallbackInfos[HWC2_CALLBACK_VSYNC].funcPointer);
669     callbackFunc(callbackData, displayId, timestamp);
670 }
671 
onVsync_2_4(uint32_t displayId,int64_t timestamp,uint32_t vsyncPeriod)672 bool ExynosDevice::onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod) {
673     Mutex::Autolock lock(mDeviceCallbackMutex);
674 
675     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) return false;
676 
677     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
678     HWC2_PFN_VSYNC_2_4 callbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
679             mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
680     callbackFunc(callbackData, displayId, timestamp, vsyncPeriod);
681 
682     return true;
683 }
684 
onVsyncPeriodTimingChanged(uint32_t displayId,hwc_vsync_period_change_timeline_t * timeline)685 void ExynosDevice::onVsyncPeriodTimingChanged(uint32_t displayId,
686                                               hwc_vsync_period_change_timeline_t *timeline) {
687     Mutex::Autolock lock(mDeviceCallbackMutex);
688 
689     if (!timeline) {
690         ALOGE("vsync period change timeline is null");
691         return;
692     }
693 
694     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED)) return;
695 
696     hwc2_callback_data_t callbackData =
697             mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData;
698     HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED callbackFunc =
699             reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>(
700                     mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer);
701     callbackFunc(callbackData, displayId, timeline);
702 }
703 
onContentProtectionUpdated(uint32_t displayId,HdcpLevels hdcpLevels)704 void ExynosDevice::onContentProtectionUpdated(uint32_t displayId, HdcpLevels hdcpLevels) {
705     Mutex::Autolock lock(mDeviceCallbackMutex);
706 
707     // Workaround to pass content protection updates to SurfaceFlinger
708     // without changing HWC HAL interface.
709     if (isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) {
710         ALOGI("%s: displayId=%u hdcpLevels=%s sending to SF via onVsync_2_4", __func__, displayId,
711               hdcpLevels.toString().c_str());
712         hwc2_callback_data_t vsyncCallbackData =
713                 mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
714         HWC2_PFN_VSYNC_2_4 vsyncCallbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
715                 mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
716         int32_t connectedLevel = static_cast<int32_t>(hdcpLevels.connectedLevel);
717         int32_t maxLevel = static_cast<int32_t>(hdcpLevels.maxLevel);
718         int32_t timestampValue = (connectedLevel & 0xFF) | ((maxLevel & 0xFF) << 8);
719         vsyncCallbackFunc(vsyncCallbackData, displayId, -timestampValue, ~1);
720     } else
721         ALOGW("%s: onVsync_2_4 is not registered, ignoring onContentProtectionUpdated", __func__);
722 }
723 
setHWCDebug(unsigned int debug)724 void ExynosDevice::setHWCDebug(unsigned int debug)
725 {
726     hwcDebug = debug;
727 }
728 
getHWCDebug()729 uint32_t ExynosDevice::getHWCDebug()
730 {
731     return hwcDebug;
732 }
733 
setHWCFenceDebug(uint32_t typeNum,uint32_t ipNum,uint32_t mode)734 void ExynosDevice::setHWCFenceDebug(uint32_t typeNum, uint32_t ipNum, uint32_t mode)
735 {
736     if (typeNum > FENCE_TYPE_ALL || typeNum < 0 || ipNum > FENCE_IP_ALL || ipNum < 0
737             || mode > 1 || mode < 0) {
738         ALOGE("%s:: input is not valid type(%u), IP(%u), mode(%d)", __func__, typeNum, ipNum, mode);
739         return;
740     }
741 
742     uint32_t value = 0;
743 
744     if (typeNum == FENCE_TYPE_ALL)
745         value = (1 << FENCE_TYPE_ALL) - 1;
746     else
747         value = 1 << typeNum;
748 
749     if (ipNum == FENCE_IP_ALL) {
750         for (uint32_t i = 0; i < FENCE_IP_ALL; i++) {
751             if (mode)
752                 hwcFenceDebug[i] |= value;
753             else
754                 hwcFenceDebug[i] &= (~value);
755         }
756     } else {
757         if (mode)
758             hwcFenceDebug[ipNum] |= value;
759         else
760             hwcFenceDebug[ipNum] &= (~value);
761     }
762 
763 }
764 
getHWCFenceDebug()765 void ExynosDevice::getHWCFenceDebug()
766 {
767     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
768         ALOGE("[HWCFenceDebug] IP_Number(%d) : Debug(%x)", i, hwcFenceDebug[i]);
769 }
770 
setHWCControl(uint32_t displayId,uint32_t ctrl,int32_t val)771 void ExynosDevice::setHWCControl(uint32_t displayId, uint32_t ctrl, int32_t val) {
772     ExynosDisplay *exynosDisplay = NULL;
773     switch (ctrl) {
774         case HWC_CTL_FORCE_GPU:
775             ALOGI("%s::HWC_CTL_FORCE_GPU on/off=%d", __func__, val);
776             exynosHWCControl.forceGpu = (unsigned int)val;
777             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
778             onRefresh(displayId);
779             break;
780         case HWC_CTL_WINDOW_UPDATE:
781             ALOGI("%s::HWC_CTL_WINDOW_UPDATE on/off=%d", __func__, val);
782             exynosHWCControl.windowUpdate = (unsigned int)val;
783             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
784             onRefresh(displayId);
785             break;
786         case HWC_CTL_FORCE_PANIC:
787             ALOGI("%s::HWC_CTL_FORCE_PANIC on/off=%d", __func__, val);
788             exynosHWCControl.forcePanic = (unsigned int)val;
789             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
790             break;
791         case HWC_CTL_SKIP_STATIC:
792             ALOGI("%s::HWC_CTL_SKIP_STATIC on/off=%d", __func__, val);
793             exynosHWCControl.skipStaticLayers = (unsigned int)val;
794             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
795             break;
796         case HWC_CTL_SKIP_M2M_PROCESSING:
797             ALOGI("%s::HWC_CTL_SKIP_M2M_PROCESSING on/off=%d", __func__, val);
798             exynosHWCControl.skipM2mProcessing = (unsigned int)val;
799             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
800             break;
801         case HWC_CTL_SKIP_RESOURCE_ASSIGN:
802             ALOGI("%s::HWC_CTL_SKIP_RESOURCE_ASSIGN on/off=%d", __func__, val);
803             exynosHWCControl.skipResourceAssign = (unsigned int)val;
804             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
805             onRefreshDisplays();
806             break;
807         case HWC_CTL_SKIP_VALIDATE:
808             ALOGI("%s::HWC_CTL_SKIP_VALIDATE on/off=%d", __func__, val);
809             exynosHWCControl.skipValidate = (unsigned int)val;
810             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
811             onRefreshDisplays();
812             break;
813         case HWC_CTL_DUMP_MID_BUF:
814             ALOGI("%s::HWC_CTL_DUMP_MID_BUF on/off=%d", __func__, val);
815             exynosHWCControl.dumpMidBuf = (unsigned int)val;
816             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
817             onRefreshDisplays();
818             break;
819         case HWC_CTL_CAPTURE_READBACK:
820             captureScreenWithReadback(displayId);
821             break;
822         case HWC_CTL_DISPLAY_MODE:
823             ALOGI("%s::HWC_CTL_DISPLAY_MODE mode=%d", __func__, val);
824             setDisplayMode((uint32_t)val);
825             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
826             onRefreshDisplays();
827             break;
828         // Support DDI scalser {
829         case HWC_CTL_DDI_RESOLUTION_CHANGE:
830             ALOGI("%s::HWC_CTL_DDI_RESOLUTION_CHANGE mode=%d", __func__, val);
831             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
832             uint32_t width, height;
833 
834             /* TODO: Add branch here for each resolution/index */
835             switch(val) {
836             case 1:
837             case 2:
838             case 3:
839             default:
840                 width = 1440; height = 2960;
841                 break;
842             }
843 
844             if (exynosDisplay == NULL) {
845                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
846                     mDisplays[i]->setDDIScalerEnable(width, height);
847                 }
848             } else {
849                 exynosDisplay->setDDIScalerEnable(width, height);
850             }
851             setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
852             onRefreshDisplays();
853             break;
854         // } Support DDI scaler
855         case HWC_CTL_ENABLE_COMPOSITION_CROP:
856         case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
857         case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
858         case HWC_CTL_USE_MAX_G2D_SRC:
859         case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
860         case HWC_CTL_ENABLE_EARLY_START_MPP:
861             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
862             if (exynosDisplay == NULL) {
863                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
864                     mDisplays[i]->setHWCControl(ctrl, val);
865                 }
866             } else {
867                 exynosDisplay->setHWCControl(ctrl, val);
868             }
869             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
870             onRefreshDisplays();
871             break;
872         case HWC_CTL_DYNAMIC_RECOMP:
873             ALOGI("%s::HWC_CTL_DYNAMIC_RECOMP on/off = %d", __func__, val);
874             setDynamicRecomposition(displayId, (unsigned int)val);
875             break;
876         case HWC_CTL_ENABLE_FENCE_TRACER:
877             ALOGI("%s::HWC_CTL_ENABLE_FENCE_TRACER on/off=%d", __func__, val);
878             exynosHWCControl.fenceTracer = (unsigned int)val;
879             break;
880         case HWC_CTL_SYS_FENCE_LOGGING:
881             ALOGI("%s::HWC_CTL_SYS_FENCE_LOGGING on/off=%d", __func__, val);
882             exynosHWCControl.sysFenceLogging = (unsigned int)val;
883             break;
884         case HWC_CTL_DO_FENCE_FILE_DUMP:
885             ALOGI("%s::HWC_CTL_DO_FENCE_FILE_DUMP on/off=%d", __func__, val);
886             exynosHWCControl.doFenceFileDump = (unsigned int)val;
887             break;
888         default:
889             ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
890             break;
891     }
892 }
893 
setDisplayMode(uint32_t displayMode)894 void ExynosDevice::setDisplayMode(uint32_t displayMode)
895 {
896     exynosHWCControl.displayMode = displayMode;
897 }
898 
setDynamicRecomposition(uint32_t displayId,unsigned int on)899 void ExynosDevice::setDynamicRecomposition(uint32_t displayId, unsigned int on) {
900     exynosHWCControl.useDynamicRecomp = on;
901     ExynosDisplay *display = getDisplay(displayId);
902     if (display) {
903         display->mDRDefault = on;
904         display->mDREnable = on;
905         onRefresh(displayId);
906     }
907 }
908 
checkDisplayConnection(uint32_t displayId)909 bool ExynosDevice::checkDisplayConnection(uint32_t displayId)
910 {
911 	ExynosDisplay *display = getDisplay(displayId);
912 
913     if (!display)
914         return false;
915     else
916         return display->mPlugState;
917 }
918 
checkNonInternalConnection()919 bool ExynosDevice::checkNonInternalConnection()
920 {
921     for (uint32_t i = 0; i < mDisplays.size(); i++) {
922         switch(mDisplays[i]->mType) {
923             case HWC_DISPLAY_PRIMARY:
924                 break;
925             case HWC_DISPLAY_EXTERNAL:
926             case HWC_DISPLAY_VIRTUAL:
927                 if (mDisplays[i]->mPlugState)
928                     return true;
929                 break;
930             default:
931                 break;
932         }
933     }
934     return false;
935 }
936 
getCapabilitiesLegacy(uint32_t * outCount,int32_t * outCapabilities)937 void ExynosDevice::getCapabilitiesLegacy(uint32_t *outCount, int32_t *outCapabilities) {
938     uint32_t capabilityNum = 0;
939 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
940     capabilityNum++;
941 #endif
942 #ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
943     capabilityNum++;
944 #endif
945     if (outCapabilities == NULL) {
946         *outCount = capabilityNum;
947         return;
948     }
949     if (capabilityNum != *outCount) {
950         ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
951         return;
952     }
953 #if defined(HWC_SUPPORT_COLOR_TRANSFORM) || !defined(HWC_NO_SUPPORT_SKIP_VALIDATE)
954     uint32_t index = 0;
955 #endif
956 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
957     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
958 #endif
959 #ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
960     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_VALIDATE;
961 #endif
962     return;
963 }
964 
getCapabilities(uint32_t * outCount,int32_t * outCapabilities)965 void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
966     uint32_t capabilityNum = 0;
967 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
968     capabilityNum++;
969 #endif
970     if (outCapabilities == NULL) {
971         *outCount = capabilityNum;
972         return;
973     }
974     if (capabilityNum != *outCount) {
975         ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
976         return;
977     }
978 #if defined(HWC_SUPPORT_COLOR_TRANSFORM)
979     uint32_t index = 0;
980     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
981 #endif
982     return;
983 }
984 
clearGeometryChanged()985 void ExynosDevice::clearGeometryChanged()
986 {
987     mGeometryChanged = 0;
988 }
989 
canSkipValidate()990 bool ExynosDevice::canSkipValidate()
991 {
992     /*
993      * This should be called by presentDisplay()
994      * when presentDisplay() is called without validateDisplay() call
995      */
996 
997     int ret = 0;
998     if (exynosHWCControl.skipValidate == false)
999         return false;
1000 
1001     for (uint32_t i = 0; i < mDisplays.size(); i++) {
1002         /*
1003          * Check all displays.
1004          * Resource assignment can have problem if validateDisplay is skipped
1005          * on only some displays.
1006          * All display's validateDisplay should be skipped or all display's validateDisplay
1007          * should not be skipped.
1008          */
1009         if (mDisplays[i]->mPlugState && mDisplays[i]->mPowerModeState.has_value() &&
1010             mDisplays[i]->mPowerModeState.value() != HWC2_POWER_MODE_OFF) {
1011             /*
1012              * presentDisplay is called without validateDisplay.
1013              * Call functions that should be called in validateDiplay
1014              */
1015             mDisplays[i]->doPreProcessing();
1016             mDisplays[i]->checkLayerFps();
1017 
1018             if ((ret = mDisplays[i]->canSkipValidate()) != NO_ERROR) {
1019                 ALOGD_AND_ATRACE_NAME(eDebugSkipValidate,
1020                                       "Display[%d] can't skip validate (%d), renderingState(%d), "
1021                                       "geometryChanged(0x%" PRIx64 ")",
1022                                       mDisplays[i]->mDisplayId, ret, mDisplays[i]->mRenderingState,
1023                                       mGeometryChanged);
1024                 return false;
1025             } else {
1026                 HDEBUGLOGD(eDebugSkipValidate, "Display[%d] can skip validate (%d), renderingState(%d), geometryChanged(0x%" PRIx64 ")",
1027                         mDisplays[i]->mDisplayId, ret,
1028                         mDisplays[i]->mRenderingState, mGeometryChanged);
1029             }
1030         }
1031     }
1032     return true;
1033 }
1034 
validateFences(ExynosDisplay * display)1035 bool ExynosDevice::validateFences(ExynosDisplay *display) {
1036     return mFenceTracker.validateFences(display);
1037 }
1038 
compareVsyncPeriod()1039 void ExynosDevice::compareVsyncPeriod() {
1040     /* TODO(b/265244856): to clarify what purpose of the function */
1041     ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
1042     ExynosDisplay *external_display = getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
1043 
1044     mVsyncDisplayId = getDisplayId(HWC_DISPLAY_PRIMARY, 0);
1045 
1046     if ((external_display == nullptr) ||
1047         (!external_display->mPowerModeState.has_value() ||
1048          (external_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF))) {
1049         return;
1050     } else if (!primary_display->mPowerModeState.has_value() ||
1051                (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF)) {
1052         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1053         return;
1054     } else if (primary_display->mPowerModeState.has_value() &&
1055                ((primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE) ||
1056                 (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE_SUSPEND)) &&
1057                (external_display->mVsyncPeriod >= DOZE_VSYNC_PERIOD)) { /*30fps*/
1058         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1059         return;
1060     } else if (primary_display->mVsyncPeriod <= external_display->mVsyncPeriod) {
1061         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1062         return;
1063     }
1064 
1065     return;
1066 }
1067 
captureReadbackClass(ExynosDevice * device)1068 ExynosDevice::captureReadbackClass::captureReadbackClass(
1069         ExynosDevice *device) :
1070     mDevice(device)
1071 {
1072     if (device == nullptr)
1073         return;
1074 }
1075 
~captureReadbackClass()1076 ExynosDevice::captureReadbackClass::~captureReadbackClass()
1077 {
1078     VendorGraphicBufferMapper& gMapper(VendorGraphicBufferMapper::get());
1079     if (mBuffer != nullptr)
1080         gMapper.freeBuffer(mBuffer);
1081 
1082     if (mDevice != nullptr)
1083         mDevice->clearWaitingReadbackReqDone();
1084 }
1085 
1086 
allocBuffer(uint32_t format,uint32_t w,uint32_t h)1087 int32_t ExynosDevice::captureReadbackClass::allocBuffer(
1088         uint32_t format, uint32_t w, uint32_t h)
1089 {
1090     VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
1091 
1092     uint32_t dstStride = 0;
1093     uint64_t usage = static_cast<uint64_t>(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER |
1094             GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN);
1095 
1096     status_t error = NO_ERROR;
1097     error = gAllocator.allocate(w, h, format, 1, usage, &mBuffer, &dstStride, "HWC");
1098     if ((error != NO_ERROR) || (mBuffer == nullptr)) {
1099         ALOGE("failed to allocate destination buffer(%dx%d): %d",
1100                 w, h, error);
1101         return static_cast<int32_t>(error);
1102     }
1103     return NO_ERROR;
1104 }
1105 
saveToFile(const String8 & fileName)1106 void  ExynosDevice::captureReadbackClass::saveToFile(const String8 &fileName)
1107 {
1108     if (mBuffer == nullptr) {
1109         ALOGE("%s:: buffer is null", __func__);
1110         return;
1111     }
1112 
1113     char filePath[MAX_DEV_NAME] = {0};
1114     VendorGraphicBufferMeta gmeta(mBuffer);
1115 
1116     snprintf(filePath, MAX_DEV_NAME,
1117             "%s/%s", WRITEBACK_CAPTURE_PATH, fileName.c_str());
1118     FILE *fp = fopen(filePath, "w");
1119     if (fp) {
1120         uint32_t writeSize =
1121             gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format)/8;
1122         void *writebackData = mmap(0, writeSize,
1123                 PROT_READ|PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
1124         if (writebackData != MAP_FAILED && writebackData != NULL) {
1125             size_t result = fwrite(writebackData, writeSize, 1, fp);
1126             munmap(writebackData, writeSize);
1127             ALOGD("Success to write %zu data, size(%d)", result, writeSize);
1128         } else {
1129             ALOGE("Fail to mmap");
1130         }
1131         fclose(fp);
1132     } else {
1133         ALOGE("Fail to open %s", filePath);
1134     }
1135 }
1136 
signalReadbackDone()1137 void ExynosDevice::signalReadbackDone()
1138 {
1139     if (mIsWaitingReadbackReqDone) {
1140         Mutex::Autolock lock(mCaptureMutex);
1141         mCaptureCondition.signal();
1142     }
1143 }
1144 
captureScreenWithReadback(uint32_t displayId)1145 void ExynosDevice::captureScreenWithReadback(uint32_t displayId) {
1146     ExynosDisplay *display = getDisplay(displayId);
1147     if (display == nullptr) {
1148         ALOGE("There is no display(%d)", displayId);
1149         return;
1150     }
1151 
1152     int32_t outFormat;
1153     int32_t outDataspace;
1154     int32_t ret = 0;
1155     if ((ret = display->getReadbackBufferAttributes(
1156                 &outFormat, &outDataspace)) != HWC2_ERROR_NONE) {
1157         ALOGE("getReadbackBufferAttributes fail, ret(%d)", ret);
1158         return;
1159     }
1160 
1161     captureReadbackClass captureClass(this);
1162     if ((ret = captureClass.allocBuffer(outFormat, display->mXres, display->mYres))
1163             != NO_ERROR) {
1164         return;
1165     }
1166 
1167     mIsWaitingReadbackReqDone = true;
1168 
1169     if (display->setReadbackBuffer(captureClass.getBuffer(), -1, true) != HWC2_ERROR_NONE) {
1170         ALOGE("setReadbackBuffer fail");
1171         return;
1172     }
1173 
1174     /* Update screen */
1175     onRefresh(displayId);
1176 
1177     /* Wait for handling readback */
1178     uint32_t waitPeriod = display->mVsyncPeriod * 3;
1179     {
1180         Mutex::Autolock lock(mCaptureMutex);
1181         status_t err = mCaptureCondition.waitRelative(
1182                 mCaptureMutex, us2ns(waitPeriod));
1183         if (err == TIMED_OUT) {
1184             ALOGE("timeout, readback is not requested");
1185             return;
1186         } else if (err != NO_ERROR) {
1187             ALOGE("error waiting for readback request: %s (%d)", strerror(-err), err);
1188             return;
1189         } else {
1190             ALOGD("readback request is done");
1191         }
1192     }
1193 
1194     int32_t fence = -1;
1195     if (display->getReadbackBufferFence(&fence) != HWC2_ERROR_NONE) {
1196         ALOGE("getReadbackBufferFence fail");
1197         return;
1198     }
1199     if (sync_wait(fence, 1000) < 0) {
1200         ALOGE("sync wait error, fence(%d)", fence);
1201     }
1202     hwcFdClose(fence);
1203 
1204     String8 fileName;
1205     time_t curTime = time(NULL);
1206     struct tm *tm = localtime(&curTime);
1207     fileName.appendFormat("capture_format%d_%dx%d_%04d-%02d-%02d_%02d_%02d_%02d.raw",
1208             outFormat, display->mXres, display->mYres,
1209             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1210             tm->tm_hour, tm->tm_min, tm->tm_sec);
1211     captureClass.saveToFile(fileName);
1212 }
1213 
setDisplayDeviceMode(int32_t display_id,int32_t mode)1214 int32_t ExynosDevice::setDisplayDeviceMode(int32_t display_id, int32_t mode)
1215 {
1216     int32_t ret = HWC2_ERROR_NONE;
1217 
1218     for (size_t i = 0; i < mDisplays.size(); i++) {
1219         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY && mDisplays[i]->mDisplayId == display_id) {
1220             if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE) ||
1221                 mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
1222                 ret = mDisplays[i]->setPowerMode(mode);
1223                 if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) &&
1224                     ret == HWC2_ERROR_NONE) {
1225                     onRefresh(display_id);
1226                 }
1227                 return ret;
1228             } else {
1229                 return HWC2_ERROR_UNSUPPORTED;
1230             }
1231         }
1232     }
1233     return HWC2_ERROR_UNSUPPORTED;
1234 }
1235 
setPanelGammaTableSource(int32_t display_id,int32_t type,int32_t source)1236 int32_t ExynosDevice::setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) {
1237     if (display_id < HWC_DISPLAY_PRIMARY || display_id >= HWC_NUM_DISPLAY_TYPES) {
1238         ALOGE("invalid display %d", display_id);
1239         return HWC2_ERROR_BAD_DISPLAY;
1240     }
1241 
1242     if (type < static_cast<int32_t>(DisplayType::DISPLAY_PRIMARY) ||
1243         type >= static_cast<int32_t>(DisplayType::DISPLAY_MAX)) {
1244         ALOGE("invalid display type %d", type);
1245         return HWC2_ERROR_BAD_PARAMETER;
1246     }
1247 
1248     if (source < static_cast<int32_t>(PanelGammaSource::GAMMA_DEFAULT) ||
1249         source >= static_cast<int32_t>(PanelGammaSource::GAMMA_TYPES)) {
1250         ALOGE("invalid gamma source %d", source);
1251         return HWC2_ERROR_BAD_PARAMETER;
1252     }
1253 
1254     return mDisplays[display_id]->SetCurrentPanelGammaSource(static_cast<DisplayType>(type),
1255                                                              static_cast<PanelGammaSource>(source));
1256 }
1257 
getLayerGenericMetadataKey(uint32_t __unused keyIndex,uint32_t * outKeyLength,char * __unused outKey,bool * __unused outMandatory)1258 void ExynosDevice::getLayerGenericMetadataKey(uint32_t __unused keyIndex,
1259         uint32_t* outKeyLength, char* __unused outKey, bool* __unused outMandatory)
1260 {
1261     *outKeyLength = 0;
1262     return;
1263 }
1264 
setVBlankOffDelay(const int vblankOffDelay)1265 void ExynosDevice::setVBlankOffDelay(const int vblankOffDelay) {
1266     static constexpr const char *kVblankOffDelayPath = "/sys/module/drm/parameters/vblankoffdelay";
1267 
1268     writeIntToFile(kVblankOffDelayPath, vblankOffDelay);
1269 }
1270 
getWindowPlaneNum()1271 uint32_t ExynosDevice::getWindowPlaneNum()
1272 {
1273     /*
1274      * ExynosDevice supports DPU Window Composition.
1275      * The number of windows can be composited is depends on the number of DPP planes.
1276      */
1277     return mDeviceInterface->getNumDPPChs();
1278 }
1279 
getSpecialPlaneNum()1280 uint32_t ExynosDevice::getSpecialPlaneNum()
1281 {
1282     /*
1283      * ExynosDevice might support something special purpose planes.
1284      * These planes are different with DPP planes.
1285      */
1286     return mDeviceInterface->getNumSPPChs();
1287 }
1288 
getSpecialPlaneNum(uint32_t)1289 uint32_t ExynosDevice::getSpecialPlaneNum(uint32_t /*displayId*/) {
1290     /*
1291      * TODO: create the query function for each display
1292      */
1293     return mDeviceInterface->getNumSPPChs();
1294 }
1295 
getSpecialPlaneId(uint32_t index)1296 uint32_t ExynosDevice::getSpecialPlaneId(uint32_t index)
1297 {
1298     return mDeviceInterface->getSPPChId(index);
1299 }
1300 
getSpecialPlaneAttr(uint32_t index)1301 uint64_t ExynosDevice::getSpecialPlaneAttr(uint32_t index)
1302 {
1303     return mDeviceInterface->getSPPChAttr(index);
1304 }
1305 
registerHwc3Callback(uint32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)1306 int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData,
1307                                            hwc2_function_pointer_t point) {
1308     Mutex::Autolock lock(mDeviceCallbackMutex);
1309     mHwc3CallbackInfos[descriptor].callbackData = callbackData;
1310     mHwc3CallbackInfos[descriptor].funcPointer = point;
1311 
1312     return HWC2_ERROR_NONE;
1313 }
1314 
onVsyncIdle(hwc2_display_t displayId)1315 void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) {
1316     Mutex::Autolock lock(mDeviceCallbackMutex);
1317     const auto &idleCallback = mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onVsyncIdle);
1318 
1319     if (idleCallback == mHwc3CallbackInfos.end()) return;
1320 
1321     const auto &callbackInfo = idleCallback->second;
1322     if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
1323 
1324     auto callbackFunc =
1325             reinterpret_cast<void (*)(hwc2_callback_data_t callbackData,
1326                                       hwc2_display_t hwcDisplay)>(callbackInfo.funcPointer);
1327     callbackFunc(callbackInfo.callbackData, displayId);
1328 }
1329 
handleHotplug()1330 void ExynosDevice::handleHotplug() {
1331     bool hpdStatus = false;
1332 
1333     for (size_t i = 0; i < mDisplays.size(); i++) {
1334         if (mDisplays[i] == nullptr) {
1335             continue;
1336         }
1337 
1338         // Lock mDisplayMutex during hotplug processing.
1339         // Must-have for unplug handling so that in-flight calls to
1340         // validateDisplay() and presentDisplay() don't race with
1341         // the display being removed.
1342         Mutex::Autolock lock(mDisplays[i]->mDisplayMutex);
1343 
1344         if (mDisplays[i]->checkHotplugEventUpdated(hpdStatus)) {
1345             mDisplays[i]->handleHotplugEvent(hpdStatus);
1346             mDisplays[i]->hotplug();
1347             mDisplays[i]->invalidate();
1348         }
1349     }
1350 }
1351 
onRefreshRateChangedDebug(hwc2_display_t displayId,uint32_t vsyncPeriod,uint32_t refreshPeriod)1352 void ExynosDevice::onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod,
1353                                              uint32_t refreshPeriod) {
1354     Mutex::Autolock lock(mDeviceCallbackMutex);
1355     const auto &refreshRateCallback =
1356             mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug);
1357 
1358     if (refreshRateCallback == mHwc3CallbackInfos.end()) return;
1359 
1360     const auto &callbackInfo = refreshRateCallback->second;
1361     if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
1362 
1363     ATRACE_INT("Refresh rate indicator callback",
1364                static_cast<int>(std::nano::den / (refreshPeriod ?: vsyncPeriod)));
1365 
1366     auto callbackFunc =
1367             reinterpret_cast<void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
1368                                       hwc2_vsync_period_t, int32_t)>(callbackInfo.funcPointer);
1369     callbackFunc(callbackInfo.callbackData, displayId, vsyncPeriod, refreshPeriod ?: vsyncPeriod);
1370 }
1371