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