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