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