blob: bbaa9b3f02cc71ae656c8d24c7d90889934d53bb
1 | /* |
2 | * Copyright (c) 2017 Amlogic, Inc. All rights reserved. |
3 | * |
4 | * This source code is subject to the terms and conditions defined in the |
5 | * file 'LICENSE' which is part of this source code package. |
6 | * |
7 | * Description: |
8 | */ |
9 | #include <hardware/hwcomposer2.h> |
10 | #include <inttypes.h> |
11 | |
12 | #include "Hwc2Display.h" |
13 | #include "Hwc2Base.h" |
14 | |
15 | #include <DrmTypes.h> |
16 | #include <HwcConfig.h> |
17 | #include <MesonLog.h> |
18 | #include <DebugHelper.h> |
19 | #include <Composition.h> |
20 | #include <IComposer.h> |
21 | #include <ComposerFactory.h> |
22 | #include <CompositionStrategyFactory.h> |
23 | #include <EventThread.h> |
24 | #include <systemcontrol.h> |
25 | |
26 | Hwc2Display::Hwc2Display(std::shared_ptr<Hwc2DisplayObserver> observer) { |
27 | mObserver = observer; |
28 | mForceClientComposer = false; |
29 | mPowerMode = std::make_shared<HwcPowerMode>(); |
30 | mSignalHpd = false; |
31 | mValidateDisplay = false; |
32 | mVsyncState = false; |
33 | memset(&mHdrCaps, 0, sizeof(mHdrCaps)); |
34 | memset(mColorMatrix, 0, sizeof(float) * 16); |
35 | memset(&mCalibrateCoordinates, 0, sizeof(int) * 4); |
36 | } |
37 | |
38 | Hwc2Display::~Hwc2Display() { |
39 | mLayers.clear(); |
40 | mPlanes.clear(); |
41 | mComposers.clear(); |
42 | |
43 | mCrtc.reset(); |
44 | mConnector.reset(); |
45 | mObserver.reset(); |
46 | mCompositionStrategy.reset(); |
47 | mPresentCompositionStg.reset(); |
48 | |
49 | mVsync.reset(); |
50 | mModeMgr.reset(); |
51 | |
52 | if (mPostProcessor != NULL) |
53 | mPostProcessor->stop(); |
54 | mPostProcessor.reset(); |
55 | } |
56 | |
57 | int32_t Hwc2Display::setModeMgr(std::shared_ptr<HwcModeMgr> & mgr) { |
58 | MESON_LOG_FUN_ENTER(); |
59 | std::lock_guard<std::mutex> lock(mMutex); |
60 | mModeMgr = mgr; |
61 | |
62 | if (mModeMgr->getDisplayMode(mDisplayMode) == 0) { |
63 | mPowerMode->setConnectorStatus(true); |
64 | } |
65 | MESON_LOG_FUN_LEAVE(); |
66 | return 0; |
67 | } |
68 | |
69 | int32_t Hwc2Display::initialize() { |
70 | MESON_LOG_FUN_ENTER(); |
71 | std::lock_guard<std::mutex> lock(mMutex); |
72 | |
73 | /*add valid composers*/ |
74 | std::shared_ptr<IComposer> composer; |
75 | ComposerFactory::create(MESON_CLIENT_COMPOSER, composer); |
76 | mComposers.emplace(MESON_CLIENT_COMPOSER, std::move(composer)); |
77 | ComposerFactory::create(MESON_DUMMY_COMPOSER, composer); |
78 | mComposers.emplace(MESON_DUMMY_COMPOSER, std::move(composer)); |
79 | #if defined(HWC_ENABLE_GE2D_COMPOSITION) |
80 | //TODO: havenot finish ge2d composer. |
81 | ComposerFactory::create(MESON_GE2D_COMPOSER, composer); |
82 | mComposers.emplace(MESON_GE2D_COMPOSER, std::move(composer)); |
83 | #endif |
84 | ComposerFactory::create(MESON_DI_COMPOSER, composer); |
85 | mComposers.emplace(MESON_DI_COMPOSER, std::move(composer)); |
86 | |
87 | initLayerIdGenerator(); |
88 | |
89 | MESON_LOG_FUN_LEAVE(); |
90 | return 0; |
91 | } |
92 | |
93 | int32_t Hwc2Display::setDisplayResource( |
94 | std::shared_ptr<HwDisplayCrtc> & crtc, |
95 | std::shared_ptr<HwDisplayConnector> & connector, |
96 | std::vector<std::shared_ptr<HwDisplayPlane>> & planes) { |
97 | MESON_LOG_FUN_ENTER(); |
98 | std::lock_guard<std::mutex> lock(mMutex); |
99 | |
100 | mCrtc = crtc; |
101 | mPlanes = planes; |
102 | mConnector = connector; |
103 | |
104 | /*update composition strategy.*/ |
105 | uint32_t strategyFlags = 0; |
106 | int osdPlanes = 0; |
107 | for (auto it = mPlanes.begin(); it != mPlanes.end(); ++ it) { |
108 | if ((*it)->getPlaneType() == OSD_PLANE) { |
109 | osdPlanes ++; |
110 | if (osdPlanes > 1) { |
111 | strategyFlags |= MULTI_PLANES_WITH_DI; |
112 | break; |
113 | } |
114 | } |
115 | } |
116 | auto newCompositionStrategy = |
117 | CompositionStrategyFactory::create(SIMPLE_STRATEGY, strategyFlags); |
118 | if (newCompositionStrategy != mCompositionStrategy) { |
119 | MESON_LOGD("Update composition %s -> %s", |
120 | mCompositionStrategy != NULL ? mCompositionStrategy->getName() : "NULL", |
121 | newCompositionStrategy->getName()); |
122 | mCompositionStrategy = newCompositionStrategy; |
123 | } |
124 | |
125 | mConnector->getHdrCapabilities(&mHdrCaps); |
126 | #ifdef HWC_HDR_METADATA_SUPPORT |
127 | mCrtc->getHdrMetadataKeys(mHdrKeys); |
128 | #endif |
129 | |
130 | MESON_LOG_FUN_LEAVE(); |
131 | return 0; |
132 | } |
133 | |
134 | int32_t Hwc2Display::setPostProcessor( |
135 | std::shared_ptr<HwcPostProcessor> processor) { |
136 | std::lock_guard<std::mutex> lock(mMutex); |
137 | mPostProcessor = processor; |
138 | mProcessorFlags = 0; |
139 | return 0; |
140 | } |
141 | |
142 | int32_t Hwc2Display::setVsync(std::shared_ptr<HwcVsync> vsync) { |
143 | std::lock_guard<std::mutex> lock(mMutex); |
144 | if (mVsync != vsync) { |
145 | if (mVsync.get()) { |
146 | mVsync->setEnabled(false); |
147 | mVsync->setObserver(NULL); |
148 | } else { |
149 | mVsync = vsync; |
150 | mVsync->setObserver(this); |
151 | mVsync->setEnabled(mVsyncState); |
152 | } |
153 | } |
154 | |
155 | return 0; |
156 | } |
157 | |
158 | /* |
159 | * Make sure all display planes are blank (since there is no layer) |
160 | * |
161 | * If composer service died, surfaceflinger will restart and frameBufferSurface will |
162 | * be recreated. But one framebuffer will be hold by the osd driver. If cma ion memory |
163 | * only configed to triple size of FrameBuffer, there will be one non continuous FrameBuffer |
164 | * and lead to messed display. |
165 | */ |
166 | int32_t Hwc2Display::blankDisplay() { |
167 | MESON_LOGD("blank all display planes"); |
168 | std::lock_guard<std::mutex> lock(mMutex); |
169 | |
170 | for (auto it = mPlanes.begin(); it != mPlanes.end(); ++ it) { |
171 | (*it)->setPlane(NULL, HWC_PLANE_FAKE_ZORDER, BLANK_FOR_NO_CONTENT); |
172 | } |
173 | |
174 | int32_t fence = -1; |
175 | if (mCrtc && mCrtc->pageFlip(fence) == 0) { |
176 | std::shared_ptr<DrmFence> outfence = |
177 | std::make_shared<DrmFence>(fence); |
178 | outfence->wait(3000); |
179 | } |
180 | |
181 | return 0; |
182 | } |
183 | |
184 | const char * Hwc2Display::getName() { |
185 | return mConnector->getName(); |
186 | } |
187 | |
188 | const drm_hdr_capabilities_t * Hwc2Display::getHdrCapabilities() { |
189 | mConnector->getHdrCapabilities(&mHdrCaps); |
190 | return &mHdrCaps; |
191 | } |
192 | |
193 | void Hwc2Display::getDispMode(drm_mode_info_t & dispMode){ |
194 | dispMode = mDisplayMode; |
195 | } |
196 | |
197 | #ifdef HWC_HDR_METADATA_SUPPORT |
198 | hwc2_error_t Hwc2Display::getFrameMetadataKeys( |
199 | uint32_t* outNumKeys, int32_t* outKeys) { |
200 | *outNumKeys = mHdrKeys.size(); |
201 | if (NULL != outKeys) { |
202 | for (uint32_t i = 0; i < *outNumKeys; i++) |
203 | outKeys[i] = mHdrKeys[i]; |
204 | } |
205 | |
206 | return HWC2_ERROR_NONE; |
207 | } |
208 | #endif |
209 | |
210 | hwc2_error_t Hwc2Display::setVsyncEnable(hwc2_vsync_t enabled) { |
211 | std::lock_guard<std::mutex> lock(mMutex); |
212 | bool state; |
213 | switch (enabled) { |
214 | case HWC2_VSYNC_ENABLE: |
215 | state = true; |
216 | break; |
217 | case HWC2_VSYNC_DISABLE: |
218 | state = false; |
219 | break; |
220 | default: |
221 | MESON_LOGE("[%s]: set vsync state invalid %d.", __func__, enabled); |
222 | return HWC2_ERROR_BAD_PARAMETER; |
223 | } |
224 | MESON_LOGD("setVsyncEnable: %s", state ? "true" : "false"); |
225 | mVsyncState = state; |
226 | if (mVsync.get()) |
227 | mVsync->setEnabled(mVsyncState); |
228 | return HWC2_ERROR_NONE; |
229 | } |
230 | |
231 | // HWC uses SystemControl for HDMI query / control purpose. Bacuase both parties |
232 | // respond to the same hot plug uevent additional means of synchronization |
233 | // are required before former can talk to the latter. To accomplish that HWC |
234 | // shall wait for SystemControl before it can update its state and notify FWK |
235 | // accordingly. |
236 | void Hwc2Display::onHotplug(bool connected) { |
237 | bool bSendPlugOut = false; |
238 | MESON_LOGD("On hot plug: [%s]", connected == true ? "Plug in" : "Plug out"); |
239 | |
240 | { |
241 | std::lock_guard<std::mutex> lock(mMutex); |
242 | if (connected) { |
243 | mSignalHpd = true; |
244 | return; |
245 | } |
246 | mPowerMode->setConnectorStatus(false); |
247 | if (mObserver != NULL ) { |
248 | bSendPlugOut = true; |
249 | } |
250 | } |
251 | |
252 | /*call hotplug out of lock, SF may call some hwc function to cause deadlock.*/ |
253 | if (bSendPlugOut) { |
254 | mObserver->onHotplug(false); |
255 | } |
256 | |
257 | /* switch to software vsync when hdmi plug out and no cvbs mode */ |
258 | if (mConnector && mConnector->getType() == DRM_MODE_CONNECTOR_HDMI) { |
259 | mVsync->setSoftwareMode(); |
260 | } |
261 | } |
262 | |
263 | void Hwc2Display::onUpdate(bool bHdcp) { |
264 | std::lock_guard<std::mutex> lock(mMutex); |
265 | MESON_LOGD("On update: [%s]", bHdcp == true ? "HDCP verify success" : "HDCP verify fail"); |
266 | |
267 | if (bHdcp) { |
268 | if (mObserver != NULL) { |
269 | mObserver->refresh(); |
270 | } else { |
271 | MESON_LOGE("No display oberserve register to display (%s)", getName()); |
272 | } |
273 | } |
274 | } |
275 | |
276 | void Hwc2Display::onVsync(int64_t timestamp) { |
277 | if (mObserver != NULL) { |
278 | mObserver->onVsync(timestamp); |
279 | } else { |
280 | MESON_LOGE("Hwc2Display (%p) observer is NULL", this); |
281 | } |
282 | } |
283 | |
284 | void Hwc2Display::onModeChanged(int stage) { |
285 | bool bSendPlugIn = false; |
286 | { |
287 | std::lock_guard<std::mutex> lock(mMutex); |
288 | MESON_LOGD("On mode change state: [%s]", stage == 1 ? "Complete" : "Begin to change"); |
289 | if (stage == 1) { |
290 | if (mObserver != NULL) { |
291 | /*plug in and set displaymode ok, update inforamtion.*/ |
292 | if (mSignalHpd) { |
293 | mConnector->getHdrCapabilities(&mHdrCaps); |
294 | #ifdef HWC_HDR_METADATA_SUPPORT |
295 | mCrtc->getHdrMetadataKeys(mHdrKeys); |
296 | #endif |
297 | } |
298 | |
299 | /*update mode success.*/ |
300 | if (mModeMgr->getDisplayMode(mDisplayMode) == 0) { |
301 | MESON_LOGD("Hwc2Display::onModeChanged getDisplayMode [%s]", mDisplayMode.name); |
302 | mPowerMode->setConnectorStatus(true); |
303 | if (mSignalHpd) { |
304 | bSendPlugIn = true; |
305 | mSignalHpd = false; |
306 | } else { |
307 | /*Workaround: needed for NTS test.*/ |
308 | if (HwcConfig::primaryHotplugEnabled() |
309 | && (mModeMgr->getPolicyType() == FIXED_SIZE_POLICY || |
310 | mModeMgr->getPolicyType() == REAL_MODE_POLICY)) { |
311 | bSendPlugIn = true; |
312 | } else if (mModeMgr->getPolicyType() == ACTIVE_MODE_POLICY) { |
313 | bSendPlugIn = true; |
314 | } else if (mModeMgr->getPolicyType() == REAL_MODE_POLICY) { |
315 | bSendPlugIn = true; |
316 | } |
317 | } |
318 | } |
319 | } else { |
320 | MESON_LOGE("No display oberserve register to display (%s)", getName()); |
321 | } |
322 | } |
323 | } |
324 | /*call hotplug out of lock, SF may call some hwc function to cause deadlock.*/ |
325 | if (bSendPlugIn && mModeMgr->needCallHotPlug()) { |
326 | MESON_LOGD("onModeChanged mObserver->onHotplug(true)"); |
327 | mObserver->onHotplug(true); |
328 | } else { |
329 | MESON_LOGD("mModeMgr->resetTags"); |
330 | mModeMgr->resetTags(); |
331 | } |
332 | /*last call refresh*/ |
333 | mObserver->refresh(); |
334 | } |
335 | |
336 | /* |
337 | LayerId is 16bits. |
338 | Higher 8 Bits: now is 256 layer slot, the higher 8 bits is the slot index. |
339 | Lower 8 Bits: a sequence no, used to distinguish layers have same slot index ( |
340 | which may happended a layer destoryed and at the same time a new layer created.) |
341 | */ |
342 | #define MAX_HWC_LAYERS (256) |
343 | #define LAYER_SLOT_BITS (8) |
344 | |
345 | void Hwc2Display::initLayerIdGenerator() { |
346 | mLayersBitmap = std::make_shared<BitsMap>(MAX_HWC_LAYERS); |
347 | mLayerSeq = 0; |
348 | } |
349 | |
350 | hwc2_layer_t Hwc2Display::createLayerId() { |
351 | hwc2_layer_t layerId = 0; |
352 | int idx = mLayersBitmap->getZeroBit(); |
353 | mLayersBitmap->setBit(idx); |
354 | |
355 | mLayerSeq++; |
356 | mLayerSeq %= MAX_HWC_LAYERS; |
357 | |
358 | layerId = ((idx & (MAX_HWC_LAYERS - 1)) << LAYER_SLOT_BITS) |mLayerSeq; |
359 | return layerId; |
360 | } |
361 | |
362 | void Hwc2Display::destroyLayerId(hwc2_layer_t id) { |
363 | int slotIdx = id >> LAYER_SLOT_BITS; |
364 | mLayersBitmap->clearBit(slotIdx); |
365 | } |
366 | |
367 | hwc2_error_t Hwc2Display::createLayer(hwc2_layer_t * outLayer) { |
368 | std::lock_guard<std::mutex> lock(mMutex); |
369 | |
370 | std::shared_ptr<Hwc2Layer> layer = std::make_shared<Hwc2Layer>(); |
371 | uint32_t idx = createLayerId(); |
372 | *outLayer = idx; |
373 | layer->setUniqueId(*outLayer); |
374 | mLayers.emplace(*outLayer, layer); |
375 | |
376 | return HWC2_ERROR_NONE; |
377 | } |
378 | |
379 | hwc2_error_t Hwc2Display::destroyLayer(hwc2_layer_t inLayer) { |
380 | std::lock_guard<std::mutex> lock(mMutex); |
381 | auto layerit = mLayers.find(inLayer); |
382 | if (layerit == mLayers.end()) |
383 | return HWC2_ERROR_BAD_LAYER; |
384 | |
385 | DebugHelper::getInstance().removeDebugLayer((int)inLayer); |
386 | mLayers.erase(inLayer); |
387 | destroyLayerId(inLayer); |
388 | return HWC2_ERROR_NONE; |
389 | } |
390 | |
391 | hwc2_error_t Hwc2Display::setCursorPosition(hwc2_layer_t layer __unused, |
392 | int32_t x __unused, int32_t y __unused) { |
393 | MESON_LOG_EMPTY_FUN(); |
394 | return HWC2_ERROR_NONE; |
395 | } |
396 | |
397 | hwc2_error_t Hwc2Display::setColorTransform(const float* matrix, |
398 | android_color_transform_t hint) { |
399 | if (hint == HAL_COLOR_TRANSFORM_IDENTITY) { |
400 | mForceClientComposer = false; |
401 | memset(mColorMatrix, 0, sizeof(float) * 16); |
402 | } else { |
403 | mForceClientComposer = true; |
404 | memcpy(mColorMatrix, matrix, sizeof(float) * 16); |
405 | } |
406 | return HWC2_ERROR_NONE; |
407 | } |
408 | |
409 | hwc2_error_t Hwc2Display::setPowerMode(hwc2_power_mode_t mode) { |
410 | switch(mode) { |
411 | case HWC2_POWER_MODE_ON: |
412 | case HWC2_POWER_MODE_OFF: |
413 | MESON_LOG_EMPTY_FUN(); |
414 | return HWC2_ERROR_NONE; |
415 | case HWC2_POWER_MODE_DOZE: |
416 | case HWC2_POWER_MODE_DOZE_SUSPEND: |
417 | return HWC2_ERROR_UNSUPPORTED; |
418 | default: |
419 | return HWC2_ERROR_BAD_PARAMETER; |
420 | }; |
421 | } |
422 | |
423 | std::shared_ptr<Hwc2Layer> Hwc2Display::getLayerById(hwc2_layer_t id) { |
424 | std::unordered_map<hwc2_layer_t, std::shared_ptr<Hwc2Layer>>::iterator it = |
425 | mLayers.find(id); |
426 | |
427 | if (it != mLayers.end()) |
428 | return it->second; |
429 | |
430 | return NULL; |
431 | } |
432 | |
433 | hwc2_error_t Hwc2Display::collectLayersForPresent() { |
434 | /* |
435 | * 1) add reference to Layers to keep it alive during display. |
436 | * 2) for special layer, update its composition type. |
437 | * 3) sort Layers by zorder for composition. |
438 | */ |
439 | mPresentLayers.reserve(10); |
440 | |
441 | /*Check if layer list is changed or not*/ |
442 | bool bUpdateLayerList = false; |
443 | for (auto it = mLayers.begin(); it != mLayers.end(); it++) { |
444 | std::shared_ptr<Hwc2Layer> layer = it->second; |
445 | if (layer->isUpdateZorder() == true) { |
446 | bUpdateLayerList = true; |
447 | break; |
448 | } |
449 | } |
450 | |
451 | for (auto it = mLayers.begin(); it != mLayers.end(); it++) { |
452 | std::shared_ptr<Hwc2Layer> layer = it->second; |
453 | std::shared_ptr<DrmFramebuffer> buffer = layer; |
454 | if (bUpdateLayerList == true && layer->isUpdateZorder() == false) { |
455 | continue; |
456 | } |
457 | mPresentLayers.push_back(buffer); |
458 | |
459 | if (isLayerHideForDebug(it->first)) { |
460 | layer->mCompositionType = MESON_COMPOSITION_DUMMY; |
461 | continue; |
462 | } |
463 | |
464 | if (HwcConfig::isHeadlessMode()) { |
465 | layer->mCompositionType = MESON_COMPOSITION_DUMMY; |
466 | } else { |
467 | if (layer->mHwcCompositionType == HWC2_COMPOSITION_CLIENT) { |
468 | layer->mCompositionType = MESON_COMPOSITION_CLIENT; |
469 | } else { |
470 | /* |
471 | * Other layers need further handle: |
472 | * 1) HWC2_COMPOSITION_DEVICE |
473 | * 2) HWC2_COMPOSITION_SOLID_COLOR |
474 | * 3) HWC2_COMPOSITION_CURSOR |
475 | * 4) HWC2_COMPOSITION_SIDEBAND |
476 | */ |
477 | /*composition type unknown, set to none first.*/ |
478 | layer->mCompositionType = MESON_COMPOSITION_UNDETERMINED; |
479 | } |
480 | } |
481 | } |
482 | |
483 | if (mPresentLayers.size() > 1) { |
484 | /* Sort mComposeLayers by zorder. */ |
485 | struct { |
486 | bool operator() (std::shared_ptr<DrmFramebuffer> a, |
487 | std::shared_ptr<DrmFramebuffer> b) { |
488 | return a->mZorder > b->mZorder; |
489 | } |
490 | } zorderCompare; |
491 | std::sort(mPresentLayers.begin(), mPresentLayers.end(), zorderCompare); |
492 | } |
493 | |
494 | return HWC2_ERROR_NONE; |
495 | } |
496 | |
497 | hwc2_error_t Hwc2Display::collectPlanesForPresent() { |
498 | mPresentPlanes = mPlanes; |
499 | |
500 | if (DebugHelper::getInstance().debugPlanes()) { |
501 | std::map<int, int> planeFlags; |
502 | DebugHelper::getInstance().getPlaneDebugFlags(planeFlags); |
503 | |
504 | for (auto it = mPresentPlanes.begin(); it != mPresentPlanes.end(); it++) { |
505 | std::shared_ptr<HwDisplayPlane> plane = *it; |
506 | |
507 | auto dbgIt = planeFlags.find(plane->getPlaneId()); |
508 | if (dbgIt != planeFlags.end()) { |
509 | plane->setDebugFlag(dbgIt->second); |
510 | } else { |
511 | plane->setDebugFlag(0); |
512 | } |
513 | } |
514 | } |
515 | |
516 | return HWC2_ERROR_NONE; |
517 | } |
518 | |
519 | hwc2_error_t Hwc2Display::collectComposersForPresent() { |
520 | for (auto it = mComposers.begin(); it != mComposers.end(); it++) { |
521 | mPresentComposers.push_back(it->second); |
522 | } |
523 | |
524 | return HWC2_ERROR_NONE; |
525 | } |
526 | |
527 | hwc2_error_t Hwc2Display::collectCompositionStgForPresent() { |
528 | mPresentCompositionStg = mCompositionStrategy; |
529 | return HWC2_ERROR_NONE; |
530 | } |
531 | |
532 | hwc2_error_t Hwc2Display::setCalibrateInfo(int32_t caliX,int32_t caliY,int32_t caliW,int32_t caliH){ |
533 | |
534 | mCalibrateCoordinates[0] = caliX; |
535 | mCalibrateCoordinates[1] = caliY; |
536 | mCalibrateCoordinates[2] = caliW; |
537 | mCalibrateCoordinates[3] = caliH; |
538 | |
539 | return HWC2_ERROR_NONE; |
540 | } |
541 | |
542 | |
543 | int32_t Hwc2Display::getDisplayIdentificationData(uint32_t &outPort, |
544 | std::vector<uint8_t> &outData) { |
545 | int32_t ret = mConnector->getIdentificationData(outData); |
546 | if (0 == ret) { |
547 | outPort = mConnector->getId(); |
548 | } |
549 | return ret; |
550 | } |
551 | |
552 | int32_t Hwc2Display::loadCalibrateInfo() { |
553 | hwc2_config_t config; |
554 | int32_t configWidth; |
555 | int32_t configHeight; |
556 | if (mModeMgr->getActiveConfig(&config) != HWC2_ERROR_NONE) { |
557 | MESON_ASSERT(0, "[%s]: getHwcDisplayHeight failed!", __func__); |
558 | return -ENOENT; |
559 | } |
560 | if (mModeMgr->getDisplayAttribute(config, |
561 | HWC2_ATTRIBUTE_WIDTH, &configWidth) != HWC2_ERROR_NONE) { |
562 | MESON_ASSERT(0, "[%s]: getHwcDisplayHeight failed!", __func__); |
563 | return -ENOENT; |
564 | } |
565 | if (mModeMgr->getDisplayAttribute(config, |
566 | HWC2_ATTRIBUTE_HEIGHT, &configHeight) != HWC2_ERROR_NONE) { |
567 | MESON_ASSERT(0, "[%s]: getHwcDisplayHeight failed!", __func__); |
568 | return -ENOENT; |
569 | } |
570 | |
571 | if (mDisplayMode.pixelW == 0 || mDisplayMode.pixelH == 0) { |
572 | MESON_ASSERT(0, "[%s]: Displaymode is invalid(%s, %dx%d)!", |
573 | __func__, mDisplayMode.name, mDisplayMode.pixelW, mDisplayMode.pixelH); |
574 | return -ENOENT; |
575 | } |
576 | /* MESON_LOGD("(%s): loadCalibrateInfo:(%s) pixelW (%d) pixelH (%d) ", __func__, |
577 | mDisplayMode.name , mDisplayMode.pixelW, mDisplayMode.pixelH);*/ |
578 | /*default info*/ |
579 | mCalibrateInfo.framebuffer_w = configWidth; |
580 | mCalibrateInfo.framebuffer_h = configHeight; |
581 | mCalibrateInfo.crtc_display_x = mCalibrateCoordinates[0]; |
582 | mCalibrateInfo.crtc_display_y = mCalibrateCoordinates[1]; |
583 | mCalibrateInfo.crtc_display_w = mCalibrateCoordinates[2]; |
584 | mCalibrateInfo.crtc_display_h = mCalibrateCoordinates[3]; |
585 | |
586 | return 0; |
587 | } |
588 | |
589 | // Scaled display frame to the framebuffer config if necessary |
590 | // (i.e. not at the default resolution of 1080p) |
591 | int32_t Hwc2Display::adjustDisplayFrame() { |
592 | bool bNoScale = false; |
593 | if (mCalibrateInfo.framebuffer_w == mCalibrateInfo.crtc_display_w && |
594 | mCalibrateInfo.framebuffer_h == mCalibrateInfo.crtc_display_h) { |
595 | bNoScale = true; |
596 | } |
597 | |
598 | Hwc2Layer * layer; |
599 | for (auto it = mPresentLayers.begin() ; it != mPresentLayers.end(); it++) { |
600 | layer = (Hwc2Layer*)(it->get()); |
601 | if (bNoScale) { |
602 | layer->mDisplayFrame = layer->mBackupDisplayFrame; |
603 | } else { |
604 | layer->mDisplayFrame.left = (int32_t)ceilf(layer->mBackupDisplayFrame.left * |
605 | mCalibrateInfo.crtc_display_w / mCalibrateInfo.framebuffer_w) + |
606 | mCalibrateInfo.crtc_display_x; |
607 | layer->mDisplayFrame.top = (int32_t)ceilf(layer->mBackupDisplayFrame.top * |
608 | mCalibrateInfo.crtc_display_h / mCalibrateInfo.framebuffer_h) + |
609 | mCalibrateInfo.crtc_display_y; |
610 | layer->mDisplayFrame.right = (int32_t)ceilf(layer->mBackupDisplayFrame.right * |
611 | mCalibrateInfo.crtc_display_w / mCalibrateInfo.framebuffer_w) + |
612 | mCalibrateInfo.crtc_display_x; |
613 | layer->mDisplayFrame.bottom = (int32_t)ceilf(layer->mBackupDisplayFrame.bottom * |
614 | mCalibrateInfo.crtc_display_h / mCalibrateInfo.framebuffer_h) + |
615 | mCalibrateInfo.crtc_display_y; |
616 | } |
617 | } |
618 | |
619 | return 0; |
620 | } |
621 | |
622 | hwc2_error_t Hwc2Display::validateDisplay(uint32_t* outNumTypes, |
623 | uint32_t* outNumRequests) { |
624 | std::lock_guard<std::mutex> lock(mMutex); |
625 | /*clear data used in composition.*/ |
626 | mPresentLayers.clear(); |
627 | mPresentComposers.clear(); |
628 | mPresentPlanes.clear(); |
629 | mPresentCompositionStg.reset(); |
630 | mChangedLayers.clear(); |
631 | mOverlayLayers.clear(); |
632 | mFailedDeviceComp = false; |
633 | mSkipComposition = false; |
634 | |
635 | hwc2_error_t ret = collectLayersForPresent(); |
636 | if (ret != HWC2_ERROR_NONE) { |
637 | return ret; |
638 | } |
639 | ret = collectComposersForPresent(); |
640 | if (ret != HWC2_ERROR_NONE) { |
641 | return ret; |
642 | } |
643 | ret = collectPlanesForPresent(); |
644 | if (ret != HWC2_ERROR_NONE) { |
645 | return ret; |
646 | } |
647 | ret = collectCompositionStgForPresent(); |
648 | if (ret != HWC2_ERROR_NONE) { |
649 | return ret; |
650 | } |
651 | |
652 | /*collect composition flag*/ |
653 | uint32_t compositionFlags = 0; |
654 | if (mForceClientComposer || |
655 | DebugHelper::getInstance().disableUiHwc() || |
656 | HwcConfig::forceClientEnabled()) { |
657 | compositionFlags |= COMPOSE_FORCE_CLIENT; |
658 | } |
659 | |
660 | if (HwcConfig::secureLayerProcessEnabled()) { |
661 | if (!mConnector->isSecure()) { |
662 | compositionFlags |= COMPOSE_HIDE_SECURE_FB; |
663 | } |
664 | } |
665 | |
666 | /*check power mode*/ |
667 | if (mPowerMode->needBlankScreen(mPresentLayers.size())) { |
668 | if (!mPowerMode->getScreenStatus()) { |
669 | MESON_LOGD("Need to blank screen."); |
670 | mPresentLayers.clear(); |
671 | } else { |
672 | mSkipComposition = true; |
673 | } |
674 | } |
675 | /*do composition*/ |
676 | if (!mSkipComposition) { |
677 | mPowerMode->setScreenStatus(mPresentLayers.size() > 0 ? false : true); |
678 | /*update calibrate info.*/ |
679 | loadCalibrateInfo(); |
680 | /*update displayframe before do composition.*/ |
681 | if (mPresentLayers.size() > 0) |
682 | adjustDisplayFrame(); |
683 | /*setup composition strategy.*/ |
684 | mPresentCompositionStg->setup(mPresentLayers, |
685 | mPresentComposers, mPresentPlanes, mCrtc, compositionFlags); |
686 | if (mPresentCompositionStg->decideComposition() < 0) { |
687 | return HWC2_ERROR_NO_RESOURCES; |
688 | } |
689 | |
690 | /*collect changed dispplay, layer, compostiion.*/ |
691 | ret = collectCompositionRequest(outNumTypes, outNumRequests); |
692 | } else { |
693 | /* skip Composition */ |
694 | std::shared_ptr<IComposer> clientComposer = |
695 | mComposers.find(MESON_CLIENT_COMPOSER)->second; |
696 | clientComposer->prepare(); |
697 | } |
698 | |
699 | if (mPowerMode->getScreenStatus()) { |
700 | mProcessorFlags |= PRESENT_BLANK; |
701 | } |
702 | |
703 | /* If mValidateDisplay = false, hwc will not handle presentDisplay. */ |
704 | mValidateDisplay = true; |
705 | |
706 | /*dump at end of validate, for we need check by some composition info.*/ |
707 | bool dumpLayers = false; |
708 | if (DebugHelper::getInstance().logCompositionDetail()) { |
709 | MESON_LOGE("***CompositionFlow (%s):\n", __func__); |
710 | dumpLayers = true; |
711 | } else if (mFailedDeviceComp) { |
712 | MESON_LOGE("***MonitorFailedDeviceComposition: \n"); |
713 | dumpLayers = true; |
714 | } |
715 | if (dumpLayers) { |
716 | String8 layersDump; |
717 | dumpPresentLayers(layersDump); |
718 | MESON_LOGE("%s", layersDump.string()); |
719 | } |
720 | return ret; |
721 | } |
722 | |
723 | hwc2_error_t Hwc2Display::collectCompositionRequest( |
724 | uint32_t* outNumTypes, uint32_t* outNumRequests) { |
725 | Hwc2Layer *layer; |
726 | /*collect display requested, and changed composition type.*/ |
727 | for (auto it = mPresentLayers.begin() ; it != mPresentLayers.end(); it++) { |
728 | layer = (Hwc2Layer*)(it->get()); |
729 | /*record composition changed layer.*/ |
730 | hwc2_composition_t expectedHwcComposition = |
731 | mesonComp2Hwc2Comp(layer); |
732 | if (expectedHwcComposition != layer->mHwcCompositionType) { |
733 | mChangedLayers.push_back(layer->getUniqueId()); |
734 | /*For debug.*/ |
735 | if (DebugHelper::getInstance().monitorDeviceComposition() && |
736 | (mPresentLayers.size() <= DebugHelper::getInstance().deviceCompositionThreshold()) && |
737 | (expectedHwcComposition == HWC2_COMPOSITION_CLIENT)) { |
738 | mFailedDeviceComp = true; |
739 | } |
740 | } |
741 | if (expectedHwcComposition == HWC2_COMPOSITION_SIDEBAND || layer->mCompositionType == MESON_COMPOSITION_PLANE_AMVIDEO) |
742 | mProcessorFlags |= PRESENT_SIDEBAND; |
743 | } |
744 | |
745 | /*collcet client clear layer.*/ |
746 | std::shared_ptr<IComposer> clientComposer = |
747 | mComposers.find(MESON_CLIENT_COMPOSER)->second; |
748 | std::vector<std::shared_ptr<DrmFramebuffer>> overlayLayers; |
749 | if (0 == clientComposer->getOverlyFbs(overlayLayers) ) { |
750 | auto it = overlayLayers.begin(); |
751 | for (; it != overlayLayers.end(); ++it) { |
752 | layer = (Hwc2Layer*)(it->get()); |
753 | mOverlayLayers.push_back(layer->getUniqueId()); |
754 | } |
755 | } |
756 | |
757 | *outNumRequests = mOverlayLayers.size(); |
758 | *outNumTypes = mChangedLayers.size(); |
759 | |
760 | return ((*outNumTypes) > 0) ? HWC2_ERROR_HAS_CHANGES : HWC2_ERROR_NONE; |
761 | } |
762 | |
763 | hwc2_error_t Hwc2Display::getDisplayRequests( |
764 | int32_t* outDisplayRequests, uint32_t* outNumElements, |
765 | hwc2_layer_t* outLayers,int32_t* outLayerRequests) { |
766 | *outDisplayRequests = 0; |
767 | |
768 | /*check if need HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET*/ |
769 | *outNumElements = mOverlayLayers.size(); |
770 | if (outLayers && outLayerRequests) { |
771 | for (uint32_t i = 0; i < mOverlayLayers.size(); i++) { |
772 | outLayers[i] = mOverlayLayers[i]; |
773 | outLayerRequests[i] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET; |
774 | } |
775 | } |
776 | |
777 | return HWC2_ERROR_NONE; |
778 | } |
779 | |
780 | hwc2_error_t Hwc2Display::getChangedCompositionTypes( |
781 | uint32_t * outNumElements, hwc2_layer_t * outLayers, |
782 | int32_t * outTypes) { |
783 | *outNumElements = mChangedLayers.size(); |
784 | if (outLayers && outTypes) { |
785 | for (uint32_t i = 0; i < mChangedLayers.size(); i++) { |
786 | std::shared_ptr<Hwc2Layer> layer = mLayers.find(mChangedLayers[i])->second; |
787 | outTypes[i] = mesonComp2Hwc2Comp(layer.get()); |
788 | outLayers[i] = mChangedLayers[i]; |
789 | } |
790 | } |
791 | |
792 | return HWC2_ERROR_NONE; |
793 | } |
794 | |
795 | hwc2_error_t Hwc2Display::acceptDisplayChanges() { |
796 | /* commit composition type */ |
797 | for (auto it = mPresentLayers.begin(); it != mPresentLayers.end(); it++) { |
798 | Hwc2Layer * layer = (Hwc2Layer*)(it->get()); |
799 | layer->commitCompType(mesonComp2Hwc2Comp(layer)); |
800 | } |
801 | |
802 | /* set updateZorder flag to false */ |
803 | for (auto it = mLayers.begin(); it != mLayers.end(); it++) { |
804 | std::shared_ptr<Hwc2Layer> layer = it->second; |
805 | layer->updateZorder(false); |
806 | } |
807 | |
808 | return HWC2_ERROR_NONE; |
809 | } |
810 | |
811 | hwc2_error_t Hwc2Display::presentDisplay(int32_t* outPresentFence) { |
812 | std::lock_guard<std::mutex> lock(mMutex); |
813 | |
814 | if (mSkipComposition) { |
815 | *outPresentFence = -1; |
816 | } else { |
817 | if (mValidateDisplay == false) { |
818 | MESON_LOGD("presentDisplay without validateDisplay"); |
819 | return HWC2_ERROR_NONE; |
820 | } |
821 | mValidateDisplay = false; |
822 | int32_t outFence = -1; |
823 | /*Start to compose, set up plane info.*/ |
824 | if (mPresentCompositionStg->commit() != 0) { |
825 | return HWC2_ERROR_NOT_VALIDATED; |
826 | } |
827 | |
828 | #ifdef HWC_HDR_METADATA_SUPPORT |
829 | /*set hdr metadata info.*/ |
830 | for (auto it = mPresentLayers.begin() ; it != mPresentLayers.end(); it++) { |
831 | if ((*it)->mHdrMetaData.empty() == false) { |
832 | mCrtc->setHdrMetadata((*it)->mHdrMetaData); |
833 | break; |
834 | } |
835 | } |
836 | #endif |
837 | |
838 | /* Page flip */ |
839 | if (mCrtc->pageFlip(outFence) < 0) { |
840 | return HWC2_ERROR_UNSUPPORTED; |
841 | } |
842 | if (mPostProcessor != NULL) { |
843 | int32_t displayFence = ::dup(outFence); |
844 | mPostProcessor->present(mProcessorFlags, displayFence); |
845 | mProcessorFlags = 0; |
846 | } |
847 | |
848 | *outPresentFence = outFence; |
849 | } |
850 | |
851 | /*dump debug informations.*/ |
852 | bool dumpComposition = false; |
853 | if (DebugHelper::getInstance().logCompositionDetail()) { |
854 | MESON_LOGE("***CompositionFlow (%s):\n", __func__); |
855 | dumpComposition = true; |
856 | } else if (mFailedDeviceComp) { |
857 | MESON_LOGE("***MonitorFailedDeviceComposition: \n"); |
858 | dumpComposition = true; |
859 | } |
860 | if (dumpComposition) { |
861 | String8 compDump; |
862 | mPresentCompositionStg->dump(compDump); |
863 | MESON_LOGE("%s", compDump.string()); |
864 | } |
865 | return HWC2_ERROR_NONE; |
866 | } |
867 | |
868 | hwc2_error_t Hwc2Display::getReleaseFences(uint32_t* outNumElements, |
869 | hwc2_layer_t* outLayers, int32_t* outFences) { |
870 | uint32_t num = 0; |
871 | bool needInfo = false; |
872 | if (outLayers && outFences) |
873 | needInfo = true; |
874 | |
875 | /* |
876 | * Return release fence for all layers, not only DEVICE composition Layers, |
877 | * for we donot know if it is DEVICE compositin in last composition. |
878 | */ |
879 | for (auto it = mPresentLayers.begin(); it != mPresentLayers.end(); it++) { |
880 | Hwc2Layer *layer = (Hwc2Layer*)(it->get()); |
881 | num++; |
882 | if (needInfo) { |
883 | int32_t releaseFence = layer->getReleaseFence(); |
884 | *outLayers = layer->getUniqueId(); |
885 | *outFences = releaseFence; |
886 | outLayers++; |
887 | outFences++; |
888 | layer->clearReleaseFence(); |
889 | } |
890 | } |
891 | |
892 | *outNumElements = num; |
893 | return HWC2_ERROR_NONE; |
894 | } |
895 | |
896 | hwc2_error_t Hwc2Display::setClientTarget(buffer_handle_t target, |
897 | int32_t acquireFence, int32_t dataspace, hwc_region_t damage) { |
898 | std::lock_guard<std::mutex> lock(mMutex); |
899 | /*create DrmFramebuffer for client target.*/ |
900 | std::shared_ptr<DrmFramebuffer> clientFb = std::make_shared<DrmFramebuffer>( |
901 | target, acquireFence); |
902 | clientFb->mFbType = DRM_FB_SCANOUT; |
903 | clientFb->mBlendMode = DRM_BLEND_MODE_PREMULTIPLIED; |
904 | clientFb->mPlaneAlpha = 1.0f; |
905 | clientFb->mTransform = 0; |
906 | clientFb->mDataspace = dataspace; |
907 | |
908 | /* real mode set real source crop */ |
909 | if (HwcConfig::getModePolicy(0) == REAL_MODE_POLICY) { |
910 | drm_mode_info_t mode; |
911 | mModeMgr->getDisplayMode(mode); |
912 | clientFb->mSourceCrop.right = ((int32_t)mode.pixelW < clientFb->mSourceCrop.right) |
913 | ? mode.pixelW : clientFb->mSourceCrop.right; |
914 | clientFb->mSourceCrop.bottom = ((int32_t)mode.pixelH < clientFb->mSourceCrop.bottom) |
915 | ? mode.pixelH : clientFb->mSourceCrop.bottom; |
916 | } |
917 | |
918 | /*client target is always full screen, just post to crtc display axis.*/ |
919 | clientFb->mDisplayFrame.left = mCalibrateInfo.crtc_display_x; |
920 | clientFb->mDisplayFrame.top = mCalibrateInfo.crtc_display_y; |
921 | clientFb->mDisplayFrame.right = mCalibrateInfo.crtc_display_x + |
922 | mCalibrateInfo.crtc_display_w; |
923 | clientFb->mDisplayFrame.bottom = mCalibrateInfo.crtc_display_y + |
924 | mCalibrateInfo.crtc_display_h; |
925 | |
926 | /*set framebuffer to client composer.*/ |
927 | std::shared_ptr<IComposer> clientComposer = |
928 | mComposers.find(MESON_CLIENT_COMPOSER)->second; |
929 | if (clientComposer.get() && |
930 | clientComposer->setOutput(clientFb, damage) == 0) { |
931 | return HWC2_ERROR_NONE; |
932 | } |
933 | |
934 | return HWC2_ERROR_BAD_PARAMETER; |
935 | } |
936 | |
937 | hwc2_error_t Hwc2Display::getDisplayConfigs( |
938 | uint32_t* outNumConfigs, |
939 | hwc2_config_t* outConfigs) { |
940 | if (mModeMgr != NULL) { |
941 | return (hwc2_error_t)mModeMgr->getDisplayConfigs(outNumConfigs, outConfigs); |
942 | } else { |
943 | MESON_LOGE("Hwc2Display getDisplayConfigs (%s) miss valid DisplayConfigure.", |
944 | getName()); |
945 | return HWC2_ERROR_BAD_DISPLAY; |
946 | } |
947 | } |
948 | |
949 | hwc2_error_t Hwc2Display::getDisplayAttribute( |
950 | hwc2_config_t config, |
951 | int32_t attribute, |
952 | int32_t* outValue) { |
953 | if (mModeMgr != NULL) { |
954 | return (hwc2_error_t)mModeMgr->getDisplayAttribute( |
955 | config, attribute, outValue, CALL_FROM_SF); |
956 | } else { |
957 | MESON_LOGE("Hwc2Display (%s) getDisplayAttribute miss valid DisplayConfigure.", |
958 | getName()); |
959 | return HWC2_ERROR_BAD_DISPLAY; |
960 | } |
961 | } |
962 | |
963 | hwc2_error_t Hwc2Display::getActiveConfig( |
964 | hwc2_config_t* outConfig) { |
965 | if (mModeMgr != NULL) { |
966 | return (hwc2_error_t)mModeMgr->getActiveConfig(outConfig, CALL_FROM_SF); |
967 | } else { |
968 | MESON_LOGE("Hwc2Display (%s) getActiveConfig miss valid DisplayConfigure.", |
969 | getName()); |
970 | return HWC2_ERROR_BAD_DISPLAY; |
971 | } |
972 | } |
973 | |
974 | hwc2_error_t Hwc2Display::setActiveConfig( |
975 | hwc2_config_t config) { |
976 | if (mModeMgr != NULL) { |
977 | return (hwc2_error_t)mModeMgr->setActiveConfig(config); |
978 | } else { |
979 | MESON_LOGE("Display (%s) setActiveConfig miss valid DisplayConfigure.", |
980 | getName()); |
981 | return HWC2_ERROR_BAD_DISPLAY; |
982 | } |
983 | } |
984 | |
985 | bool Hwc2Display::isLayerHideForDebug(hwc2_layer_t id) { |
986 | std::vector<int> hideLayers; |
987 | DebugHelper::getInstance().getHideLayers(hideLayers); |
988 | if (hideLayers.empty()) |
989 | return false; |
990 | |
991 | for (auto it = hideLayers.begin(); it < hideLayers.end(); it++) { |
992 | if (*it == (int)id) |
993 | return true; |
994 | } |
995 | |
996 | return false; |
997 | } |
998 | |
999 | hwc2_error_t Hwc2Display::getDisplayCapabilities( |
1000 | uint32_t* outNumCapabilities, uint32_t* outCapabilities) { |
1001 | if (outCapabilities == nullptr) { |
1002 | if (mConnector->isConnected() == false) |
1003 | *outNumCapabilities = 1; |
1004 | else |
1005 | *outNumCapabilities = 0; |
1006 | } else { |
1007 | if (mConnector->isConnected() == false && *outNumCapabilities == 1) { |
1008 | outCapabilities[0] = HWC2_DISPLAY_CAPABILITY_INVALID; |
1009 | } |
1010 | } |
1011 | return HWC2_ERROR_NONE; |
1012 | } |
1013 | |
1014 | void Hwc2Display::dumpPresentLayers(String8 & dumpstr) { |
1015 | dumpstr.append("----------------------------------------------------------" |
1016 | "-----------------------------------\n"); |
1017 | dumpstr.append("| id | z | type |blend| alpha |t|" |
1018 | " AFBC | Source Crop | Display Frame |\n"); |
1019 | for (auto it = mPresentLayers.begin(); it != mPresentLayers.end(); it++) { |
1020 | Hwc2Layer *layer = (Hwc2Layer*)(it->get()); |
1021 | dumpstr.append("+------+-----+------------+-----+--------+-+--------+" |
1022 | "-------------------+-------------------+\n"); |
1023 | dumpstr.appendFormat("|%6llu|%5d|%12s|%5d|%8f|%1d|%8x|%4d %4d %4d %4d" |
1024 | "|%4d %4d %4d %4d|\n", |
1025 | layer->getUniqueId(), |
1026 | layer->mZorder, |
1027 | drmFbTypeToString(layer->mFbType), |
1028 | layer->mBlendMode, |
1029 | layer->mPlaneAlpha, |
1030 | layer->mTransform, |
1031 | am_gralloc_get_vpu_afbc_mask(layer->mBufferHandle), |
1032 | layer->mSourceCrop.left, |
1033 | layer->mSourceCrop.top, |
1034 | layer->mSourceCrop.right, |
1035 | layer->mSourceCrop.bottom, |
1036 | layer->mDisplayFrame.left, |
1037 | layer->mDisplayFrame.top, |
1038 | layer->mDisplayFrame.right, |
1039 | layer->mDisplayFrame.bottom |
1040 | ); |
1041 | } |
1042 | dumpstr.append("----------------------------------------------------------" |
1043 | "-----------------------------------\n"); |
1044 | } |
1045 | |
1046 | void Hwc2Display::dumpHwDisplayPlane(String8 &dumpstr) { |
1047 | if (DebugHelper::getInstance().dumpDetailInfo()) { |
1048 | dumpstr.append("HwDisplayPlane Info:\n"); |
1049 | dumpstr.append("------------------------------------------------------------" |
1050 | "-----------------------------------------------------------------\n"); |
1051 | dumpstr.append("| ID |Zorder| type | source crop | dis Frame" |
1052 | " | fd | fm | b_st | p_st | blend | alpha | op | afbc fm |\n"); |
1053 | dumpstr.append("+-------+------+------+---------------------+-----------------" |
1054 | "----+----+----+------+------+-------+-------+------+----------+\n"); |
1055 | |
1056 | /* dump osd plane */ |
1057 | for (auto it = mPresentPlanes.begin(); it != mPresentPlanes.end(); it++) { |
1058 | std::shared_ptr<HwDisplayPlane> plane = *it; |
1059 | if (!strncmp("OSD", plane->getName(), 3)) { |
1060 | plane->dump(dumpstr); |
1061 | } |
1062 | } |
1063 | dumpstr.append("------------------------------------------------------------" |
1064 | "-----------------------------------------------------------------\n"); |
1065 | dumpstr.append("\n"); |
1066 | } |
1067 | } |
1068 | |
1069 | void Hwc2Display::dump(String8 & dumpstr) { |
1070 | /*update for debug*/ |
1071 | if (DebugHelper::getInstance().debugHideLayers() || |
1072 | DebugHelper::getInstance().debugPlanes()) { |
1073 | //ask for auto refresh for debug layers update. |
1074 | if (mObserver != NULL) { |
1075 | mObserver->refresh(); |
1076 | } |
1077 | } |
1078 | |
1079 | /*dump*/ |
1080 | dumpstr.append("---------------------------------------------------------" |
1081 | "-----------------------------\n"); |
1082 | dumpstr.appendFormat("Display (%s, %s) \n", |
1083 | getName(), mForceClientComposer ? "Client-Comp" : "HW-Comp"); |
1084 | dumpstr.appendFormat("Power: (%d-%d) \n", |
1085 | mPowerMode->getMode(), mPowerMode->getScreenStatus()); |
1086 | /*calibration info*/ |
1087 | dumpstr.appendFormat("Calibration: (%dx%d)->(%dx%d,%dx%d)\n", |
1088 | mCalibrateInfo.framebuffer_w, mCalibrateInfo.framebuffer_h, |
1089 | mCalibrateInfo.crtc_display_x, mCalibrateInfo.crtc_display_y, |
1090 | mCalibrateInfo.crtc_display_w, mCalibrateInfo.crtc_display_h); |
1091 | |
1092 | /* HDR info */ |
1093 | dumpstr.append("HDR Capabilities:\n"); |
1094 | dumpstr.appendFormat(" DolbyVision1=%d\n", |
1095 | mHdrCaps.DolbyVisionSupported ? 1 : 0); |
1096 | dumpstr.appendFormat(" HLG=%d\n", |
1097 | mHdrCaps.HLGSupported ? 1 : 0); |
1098 | dumpstr.appendFormat(" HDR10=%d, HDR10+=%d, " |
1099 | "maxLuminance=%d, avgLuminance=%d, minLuminance=%d\n", |
1100 | mHdrCaps.HDR10Supported ? 1 : 0, |
1101 | mHdrCaps.HDR10PlusSupported ? 1 : 0, |
1102 | mHdrCaps.maxLuminance, |
1103 | mHdrCaps.avgLuminance, |
1104 | mHdrCaps.minLuminance); |
1105 | |
1106 | dumpstr.append("\n"); |
1107 | |
1108 | /* dump display configs*/ |
1109 | mModeMgr->dump(dumpstr); |
1110 | dumpstr.append("\n"); |
1111 | mVsync->dump(dumpstr); |
1112 | dumpstr.append("\n"); |
1113 | |
1114 | /*dump detail debug info*/ |
1115 | if (DebugHelper::getInstance().dumpDetailInfo()) { |
1116 | /* dump composers*/ |
1117 | dumpstr.append("Valid composers:\n"); |
1118 | for (auto it = mPresentComposers.begin(); it != mPresentComposers.end(); it++) { |
1119 | dumpstr.appendFormat("%s-Composer (%p)\n", it->get()->getName(), it->get()); |
1120 | } |
1121 | dumpstr.append("\n"); |
1122 | |
1123 | /* dump present layers info*/ |
1124 | dumpstr.append("Present layers:\n"); |
1125 | dumpPresentLayers(dumpstr); |
1126 | dumpstr.append("\n"); |
1127 | |
1128 | /* dump composition stragegy.*/ |
1129 | if (mPresentCompositionStg) { |
1130 | mPresentCompositionStg->dump(dumpstr); |
1131 | dumpstr.append("\n"); |
1132 | } |
1133 | } |
1134 | |
1135 | dumpstr.append("\n"); |
1136 | dumpHwDisplayPlane(dumpstr); |
1137 | } |
1138 | |
1139 |