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