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