summaryrefslogtreecommitdiff
path: root/hwc2/Hwc2Display.cpp (plain)
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
26Hwc2Display::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
38Hwc2Display::~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
57int32_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
69int32_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
93int32_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
134int32_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
142int32_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 */
166int32_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
184const char * Hwc2Display::getName() {
185 return mConnector->getName();
186}
187
188const drm_hdr_capabilities_t * Hwc2Display::getHdrCapabilities() {
189 mConnector->getHdrCapabilities(&mHdrCaps);
190 return &mHdrCaps;
191}
192
193void Hwc2Display::getDispMode(drm_mode_info_t & dispMode){
194 dispMode = mDisplayMode;
195}
196
197#ifdef HWC_HDR_METADATA_SUPPORT
198hwc2_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
210hwc2_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.
236void 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
263void 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
276void 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
284void 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/*
337LayerId is 16bits.
338Higher 8 Bits: now is 256 layer slot, the higher 8 bits is the slot index.
339Lower 8 Bits: a sequence no, used to distinguish layers have same slot index (
340which 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
345void Hwc2Display::initLayerIdGenerator() {
346 mLayersBitmap = std::make_shared<BitsMap>(MAX_HWC_LAYERS);
347 mLayerSeq = 0;
348}
349
350hwc2_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
362void Hwc2Display::destroyLayerId(hwc2_layer_t id) {
363 int slotIdx = id >> LAYER_SLOT_BITS;
364 mLayersBitmap->clearBit(slotIdx);
365}
366
367hwc2_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
379hwc2_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
391hwc2_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
397hwc2_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
409hwc2_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
423std::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
433hwc2_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
497hwc2_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
519hwc2_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
527hwc2_error_t Hwc2Display::collectCompositionStgForPresent() {
528 mPresentCompositionStg = mCompositionStrategy;
529 return HWC2_ERROR_NONE;
530}
531
532hwc2_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
543int32_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
552int32_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)
591int32_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
622hwc2_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
723hwc2_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
763hwc2_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
780hwc2_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
795hwc2_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
811hwc2_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
868hwc2_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
896hwc2_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
937hwc2_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
949hwc2_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
963hwc2_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
974hwc2_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
985bool 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
999hwc2_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
1014void 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
1046void 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
1069void 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