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