1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdint>
17 #include <scoped_bytrace.h>
18 #include <unordered_set>
19 #include "rs_trace.h"
20 #include "hdi_output.h"
21 #include "string_utils.h"
22 #include "metadata_helper.h"
23 #include "vsync_generator.h"
24 #include "vsync_sampler.h"
25 // DISPLAYENGINE
26 #include "syspara/parameters.h"
27
28 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
29
30 #define CHECK_DEVICE_NULL(device) \
31 do { \
32 if ((device) == nullptr) { \
33 HLOGD("[%{public}s]HdiDevice is nullptr.", __func__); \
34 return ROSEN_ERROR_NOT_INIT; \
35 } \
36 } while (0)
37
38 namespace OHOS {
39 namespace Rosen {
40 static constexpr uint32_t NUMBER_OF_HISTORICAL_FRAMES = 2;
41 static const std::string GENERIC_METADATA_KEY_ARSR_PRE_NEEDED = "ArsrDoEnhance";
42
CreateHdiOutput(uint32_t screenId)43 std::shared_ptr<HdiOutput> HdiOutput::CreateHdiOutput(uint32_t screenId)
44 {
45 return std::make_shared<HdiOutput>(screenId);
46 }
47
HdiOutput(uint32_t screenId)48 HdiOutput::HdiOutput(uint32_t screenId) : screenId_(screenId)
49 {
50 // DISPLAYENGINE ARSR_PRE FLAG
51 arsrPreEnabled_ = system::GetBoolParameter("const.display.enable_arsr_pre", true);
52 arsrPreEnabledForVm_ = system::GetBoolParameter("const.display.enable_arsr_pre_for_vm", false);
53 vmArsrWhiteList_ = system::GetParameter("const.display.vmlayer.whitelist", "unknown");
54 }
55
~HdiOutput()56 HdiOutput::~HdiOutput()
57 {
58 ClearBufferCache();
59 }
60
ClearFrameBuffer()61 GSError HdiOutput::ClearFrameBuffer()
62 {
63 GSError ret = GSERROR_OK;
64 if (!CheckFbSurface()) {
65 return ret;
66 }
67 currFrameBuffer_ = nullptr;
68 lastFrameBuffer_ = nullptr;
69 ClearBufferCache();
70 fbSurface_->ClearFrameBuffer();
71 sptr<Surface> pFrameSurface = GetFrameBufferSurface();
72 if (pFrameSurface != nullptr) {
73 ret = pFrameSurface->CleanCache();
74 }
75 return ret;
76 }
77
Init()78 RosenError HdiOutput::Init()
79 {
80 if (fbSurface_ != nullptr) {
81 return ROSEN_ERROR_OK;
82 }
83
84 fbSurface_ = HdiFramebufferSurface::CreateFramebufferSurface();
85 if (fbSurface_ == nullptr) {
86 HLOGE("Create framebuffer surface failed");
87 return ROSEN_ERROR_NOT_INIT;
88 }
89
90 if (device_ != nullptr) {
91 return ROSEN_ERROR_OK;
92 }
93
94 device_ = HdiDevice::GetInstance();
95 CHECK_DEVICE_NULL(device_);
96
97 bufferCacheCountMax_ = fbSurface_->GetBufferQueueSize();
98 int32_t ret = device_->SetScreenClientBufferCacheCount(screenId_, bufferCacheCountMax_);
99 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
100 HLOGE("Set screen client buffer cache count failed, ret is %{public}d", ret);
101 return ROSEN_ERROR_INVALID_OPERATING;
102 }
103 ClearBufferCache();
104 bufferCache_.reserve(bufferCacheCountMax_);
105 historicalPresentfences_.clear();
106
107 return ROSEN_ERROR_OK;
108 }
109
SetHdiOutputDevice(HdiDevice* device)110 RosenError HdiOutput::SetHdiOutputDevice(HdiDevice* device)
111 {
112 if (device == nullptr) {
113 HLOGE("Input HdiDevice is null");
114 return ROSEN_ERROR_INVALID_ARGUMENTS;
115 }
116
117 if (device_ != nullptr) {
118 HLOGW("HdiDevice has been changed");
119 return ROSEN_ERROR_OK;
120 }
121 device_ = device;
122 return ROSEN_ERROR_OK;
123 }
124
SetLayerInfo(const std::vector<LayerInfoPtr> &layerInfos)125 void HdiOutput::SetLayerInfo(const std::vector<LayerInfoPtr> &layerInfos)
126 {
127 std::unique_lock<std::mutex> lock(mutex_);
128 for (auto &layerInfo : layerInfos) {
129 if (layerInfo == nullptr || layerInfo->GetSurface() == nullptr) {
130 HLOGE("current layerInfo or layerInfo's cSurface is null");
131 continue;
132 }
133
134 uint64_t surfaceId = layerInfo->GetSurface()->GetUniqueId();
135 auto iter = surfaceIdMap_.find(surfaceId);
136 if (iter != surfaceIdMap_.end()) {
137 const LayerPtr &layer = iter->second;
138 layer->UpdateLayerInfo(layerInfo);
139 continue;
140 }
141
142 int32_t ret = CreateLayerLocked(surfaceId, layerInfo);
143 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
144 return;
145 }
146 }
147
148 DeletePrevLayersLocked();
149 ResetLayerStatusLocked();
150 }
151
DeletePrevLayersLocked()152 void HdiOutput::DeletePrevLayersLocked()
153 {
154 auto surfaceIter = surfaceIdMap_.begin();
155 while (surfaceIter != surfaceIdMap_.end()) {
156 const LayerPtr &layer = surfaceIter->second;
157 if (!layer->GetLayerStatus()) {
158 surfaceIdMap_.erase(surfaceIter++);
159 } else {
160 ++surfaceIter;
161 }
162 }
163
164 auto layerIter = layerIdMap_.begin();
165 while (layerIter != layerIdMap_.end()) {
166 const LayerPtr &layer = layerIter->second;
167 if (!layer->GetLayerStatus()) {
168 layerIdMap_.erase(layerIter++);
169 } else {
170 ++layerIter;
171 }
172 }
173 }
174
ResetLayerStatusLocked()175 void HdiOutput::ResetLayerStatusLocked()
176 {
177 for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
178 iter->second->SetLayerStatus(false);
179 }
180 }
181
CheckSupportArsrPreMetadata()182 bool HdiOutput::CheckSupportArsrPreMetadata()
183 {
184 const auto& validKeys = device_->GetSupportedLayerPerFrameParameterKey();
185 if (std::find(validKeys.begin(), validKeys.end(), GENERIC_METADATA_KEY_ARSR_PRE_NEEDED) != validKeys.end()) {
186 return true;
187 }
188 return false;
189 }
190
CreateLayerLocked(uint64_t surfaceId, const LayerInfoPtr &layerInfo)191 int32_t HdiOutput::CreateLayerLocked(uint64_t surfaceId, const LayerInfoPtr &layerInfo)
192 {
193 LayerPtr layer = HdiLayer::CreateHdiLayer(screenId_);
194 if (layer == nullptr || !layer->Init(layerInfo)) {
195 HLOGE("Init hdiLayer failed");
196 return GRAPHIC_DISPLAY_FAILURE;
197 }
198
199 layer->UpdateLayerInfo(layerInfo);
200 uint32_t layerId = layer->GetLayerId();
201
202 layerIdMap_[layerId] = layer;
203 surfaceIdMap_[surfaceId] = layer;
204
205 if (device_ == nullptr) {
206 HLOGE("[%{public}s]HdiDevice is nullptr.", __func__);
207 return GRAPHIC_DISPLAY_SUCCESS;
208 }
209
210 if ((arsrPreEnabledForVm_ && CheckSupportArsrPreMetadata() && CheckIfDoArsrPreForVm(layerInfo)) ||
211 (arsrPreEnabled_ && CheckSupportArsrPreMetadata() && CheckIfDoArsrPre(layerInfo))) {
212 const std::vector<int8_t> valueBlob{static_cast<int8_t>(1)};
213 if (device_->SetLayerPerFrameParameter(screenId_,
214 layerId, GENERIC_METADATA_KEY_ARSR_PRE_NEEDED, valueBlob) != 0) {
215 HLOGE("SetLayerPerFrameParameter Fail!");
216 }
217 }
218
219 return GRAPHIC_DISPLAY_SUCCESS;
220 }
221
SetOutputDamages(const std::vector<GraphicIRect> &outputDamages)222 void HdiOutput::SetOutputDamages(const std::vector<GraphicIRect> &outputDamages)
223 {
224 outputDamages_ = outputDamages;
225 }
226
GetOutputDamages()227 const std::vector<GraphicIRect>& HdiOutput::GetOutputDamages()
228 {
229 return outputDamages_;
230 }
231
GetComposeClientLayers(std::vector<LayerPtr>& clientLayers)232 void HdiOutput::GetComposeClientLayers(std::vector<LayerPtr>& clientLayers)
233 {
234 std::unique_lock<std::mutex> lock(mutex_);
235 for (const auto &[first, layer] : layerIdMap_) {
236 if (layer == nullptr) {
237 continue;
238 }
239 if (layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT ||
240 layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT_CLEAR ||
241 layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_TUNNEL) {
242 clientLayers.emplace_back(layer);
243 }
244 }
245 }
246
GetLayerInfos(std::vector<LayerInfoPtr>& layerInfos)247 void HdiOutput::GetLayerInfos(std::vector<LayerInfoPtr>& layerInfos)
248 {
249 std::unique_lock<std::mutex> lock(mutex_);
250 for (const auto &it : layerIdMap_) {
251 if (it.second != nullptr) {
252 layerInfos.emplace_back(it.second->GetLayerInfo());
253 }
254 }
255 }
256
UpdatePrevLayerInfoLocked()257 void HdiOutput::UpdatePrevLayerInfoLocked()
258 {
259 for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); iter++) {
260 LayerPtr layer = iter->second;
261 layer->SavePrevLayerInfo();
262 }
263 }
264
GetScreenId() const265 uint32_t HdiOutput::GetScreenId() const
266 {
267 return screenId_;
268 }
269
SetLayerCompCapacity(uint32_t layerCompositionCapacity)270 void HdiOutput::SetLayerCompCapacity(uint32_t layerCompositionCapacity)
271 {
272 std::unique_lock<std::mutex> lock(mutex_);
273 layerCompCapacity_ = layerCompositionCapacity;
274 }
275
GetLayerCompCapacity() const276 uint32_t HdiOutput::GetLayerCompCapacity() const
277 {
278 std::unique_lock<std::mutex> lock(mutex_);
279 return layerCompCapacity_;
280 }
281
GetFrameBufferSurface()282 sptr<Surface> HdiOutput::GetFrameBufferSurface()
283 {
284 if (!CheckFbSurface()) {
285 return nullptr;
286 }
287
288 return fbSurface_->GetSurface();
289 }
290
GetFramebuffer()291 std::unique_ptr<FrameBufferEntry> HdiOutput::GetFramebuffer()
292 {
293 if (!CheckFbSurface()) {
294 return nullptr;
295 }
296
297 return fbSurface_->GetFramebuffer();
298 }
299
CheckFbSurface()300 bool HdiOutput::CheckFbSurface()
301 {
302 if (fbSurface_ == nullptr) {
303 HLOGE("fbSurface is nullptr");
304 return false;
305 }
306
307 return true;
308 }
309
RecordCompositionTime(int64_t timeStamp)310 void HdiOutput::RecordCompositionTime(int64_t timeStamp)
311 {
312 compositionTimeRecords_[compTimeRcdIndex_] = timeStamp;
313 compTimeRcdIndex_ = (compTimeRcdIndex_ + 1) % COMPOSITION_RECORDS_NUM;
314 }
315
SetDirectClientCompEnableStatus(bool enableStatus)316 void HdiOutput::SetDirectClientCompEnableStatus(bool enableStatus)
317 {
318 std::unique_lock<std::mutex> lock(mutex_);
319 directClientCompositionEnabled_ = enableStatus;
320 }
321
GetDirectClientCompEnableStatus() const322 bool HdiOutput::GetDirectClientCompEnableStatus() const
323 {
324 std::unique_lock<std::mutex> lock(mutex_);
325 return directClientCompositionEnabled_;
326 }
327
PreProcessLayersComp()328 int32_t HdiOutput::PreProcessLayersComp()
329 {
330 int32_t ret = GRAPHIC_DISPLAY_SUCCESS;
331 bool doClientCompositionDirectly;
332 {
333 std::unique_lock<std::mutex> lock(mutex_);
334 if (layerIdMap_.empty()) {
335 HLOGI("layer map is empty, drop this frame");
336 return GRAPHIC_DISPLAY_PARAM_ERR;
337 }
338
339 uint32_t layersNum = layerIdMap_.size();
340 // If doClientCompositionDirectly is true then layer->SetHdiLayerInfo and UpdateLayerCompType is no need to run.
341 doClientCompositionDirectly = directClientCompositionEnabled_ &&
342 ((layerCompCapacity_ != LAYER_COMPOSITION_CAPACITY_INVALID) && (layersNum > layerCompCapacity_));
343
344 for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
345 const LayerPtr &layer = iter->second;
346 if (doClientCompositionDirectly) {
347 layer->UpdateCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT);
348 continue;
349 }
350 ret = layer->SetHdiLayerInfo();
351 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
352 HLOGE("Set hdi layer[id:%{public}d] info failed, ret %{public}d.", layer->GetLayerId(), ret);
353 return GRAPHIC_DISPLAY_FAILURE;
354 }
355 }
356 }
357
358 if (doClientCompositionDirectly) {
359 ScopedBytrace doClientCompositionDirectlyTag("DoClientCompositionDirectly");
360 HLOGD("Direct client composition is enabled.");
361 return GRAPHIC_DISPLAY_SUCCESS;
362 }
363
364 return ret;
365 }
366
UpdateLayerCompType()367 int32_t HdiOutput::UpdateLayerCompType()
368 {
369 CHECK_DEVICE_NULL(device_);
370 std::vector<uint32_t> layersId;
371 std::vector<int32_t> types;
372 int32_t ret = device_->GetScreenCompChange(screenId_, layersId, types);
373 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
374 HLOGE("GetScreenCompChange failed, ret is %{public}d", ret);
375 return ret;
376 }
377 if (layersId.size() != types.size()) {
378 HLOGE("HdiOutput::UpdateLayerCompType layersId size is not types size");
379 return GRAPHIC_DISPLAY_FAILURE;
380 }
381
382 std::unique_lock<std::mutex> lock(mutex_);
383 size_t layerNum = layersId.size();
384 for (size_t i = 0; i < layerNum; i++) {
385 auto iter = layerIdMap_.find(layersId[i]);
386 if (iter == layerIdMap_.end()) {
387 HLOGE("Invalid hdi layer id[%{public}u]", layersId[i]);
388 continue;
389 }
390
391 const LayerPtr &layer = iter->second;
392 layer->UpdateCompositionType(static_cast<GraphicCompositionType>(types[i]));
393 }
394
395 return ret;
396 }
397
CheckAndUpdateClientBufferCahce(sptr<SurfaceBuffer> buffer, uint32_t& index)398 bool HdiOutput::CheckAndUpdateClientBufferCahce(sptr<SurfaceBuffer> buffer, uint32_t& index)
399 {
400 uint32_t bufferCahceSize = (uint32_t)bufferCache_.size();
401 for (uint32_t i = 0; i < bufferCahceSize; i++) {
402 if (bufferCache_[i] == buffer) {
403 index = i;
404 return true;
405 }
406 }
407
408 if (bufferCahceSize >= bufferCacheCountMax_) {
409 HLOGI("the length of buffer cache exceeds the limit, and not find the aim buffer!");
410 ClearBufferCache();
411 }
412
413 index = (uint32_t)bufferCache_.size();
414 bufferCache_.push_back(buffer);
415 return false;
416 }
417
418 // DISPLAY ENGINE
CheckIfDoArsrPre(const LayerInfoPtr &layerInfo)419 bool HdiOutput::CheckIfDoArsrPre(const LayerInfoPtr &layerInfo)
420 {
421 static const std::unordered_set<GraphicPixelFormat> yuvFormats {
422 GRAPHIC_PIXEL_FMT_YUV_422_I,
423 GRAPHIC_PIXEL_FMT_YCBCR_422_SP,
424 GRAPHIC_PIXEL_FMT_YCRCB_422_SP,
425 GRAPHIC_PIXEL_FMT_YCBCR_420_SP,
426 GRAPHIC_PIXEL_FMT_YCRCB_420_SP,
427 GRAPHIC_PIXEL_FMT_YCBCR_422_P,
428 GRAPHIC_PIXEL_FMT_YCRCB_422_P,
429 GRAPHIC_PIXEL_FMT_YCBCR_420_P,
430 GRAPHIC_PIXEL_FMT_YCRCB_420_P,
431 GRAPHIC_PIXEL_FMT_YUYV_422_PKG,
432 GRAPHIC_PIXEL_FMT_UYVY_422_PKG,
433 GRAPHIC_PIXEL_FMT_YVYU_422_PKG,
434 GRAPHIC_PIXEL_FMT_VYUY_422_PKG,
435 GRAPHIC_PIXEL_FMT_YCBCR_P010,
436 GRAPHIC_PIXEL_FMT_YCRCB_P010,
437 };
438
439 static const std::unordered_set<std::string> videoLayers {
440 "xcomponentIdSurface",
441 "componentIdSurface",
442 "SceneViewer Model totemweather0",
443 };
444
445 if (layerInfo == nullptr || layerInfo->GetSurface() == nullptr || layerInfo->GetBuffer() == nullptr) {
446 return false;
447 }
448
449 if (((yuvFormats.count(static_cast<GraphicPixelFormat>(layerInfo->GetBuffer()->GetFormat())) > 0) ||
450 (videoLayers.count(layerInfo->GetSurface()->GetName()) > 0)) && layerInfo->GetLayerArsr()) {
451 return true;
452 }
453
454 return false;
455 }
456
CheckIfDoArsrPreForVm(const LayerInfoPtr &layerInfo)457 bool HdiOutput::CheckIfDoArsrPreForVm(const LayerInfoPtr &layerInfo)
458 {
459 char sep = ';';
460 std::unordered_set<std::string> vmLayers;
461 SplitString(vmArsrWhiteList_, vmLayers, sep);
462 if (vmLayers.count(layerInfo->GetSurface()->GetName()) > 0) {
463 return true;
464 }
465 return false;
466 }
467
FlushScreen(std::vector<LayerPtr> &compClientLayers)468 int32_t HdiOutput::FlushScreen(std::vector<LayerPtr> &compClientLayers)
469 {
470 auto fbEntry = GetFramebuffer();
471 if (fbEntry == nullptr) {
472 HLOGE("HdiBackend flush screen failed : GetFramebuffer failed!");
473 return -1;
474 }
475
476 const auto& fbAcquireFence = fbEntry->acquireFence;
477 for (auto &layer : compClientLayers) {
478 if (layer != nullptr) {
479 layer->MergeWithFramebufferFence(fbAcquireFence);
480 }
481 }
482
483 currFrameBuffer_ = fbEntry->buffer;
484 if (currFrameBuffer_ == nullptr) {
485 HLOGE("HdiBackend flush screen failed : frame buffer is null");
486 return -1;
487 }
488
489 uint32_t index = INVALID_BUFFER_CACHE_INDEX;
490 bool bufferCached = false;
491 if (bufferCacheCountMax_ == 0) {
492 ClearBufferCache();
493 HLOGE("The count of this client buffer cache is 0.");
494 } else {
495 bufferCached = CheckAndUpdateClientBufferCahce(currFrameBuffer_, index);
496 }
497
498 CHECK_DEVICE_NULL(device_);
499 int32_t ret = device_->SetScreenClientDamage(screenId_, outputDamages_);
500 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
501 HLOGE("Set screen client damage failed, ret is %{public}d", ret);
502 return ret;
503 }
504
505 if (bufferCached && index < bufferCacheCountMax_) {
506 ret = device_->SetScreenClientBuffer(screenId_, nullptr, index, fbAcquireFence);
507 } else {
508 ret = device_->SetScreenClientBuffer(screenId_, currFrameBuffer_->GetBufferHandle(), index, fbAcquireFence);
509 }
510 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
511 HLOGE("Set screen client buffer failed, ret is %{public}d", ret);
512 return ret;
513 }
514
515 return GRAPHIC_DISPLAY_SUCCESS;
516 }
517
Commit(sptr<SyncFence> &fbFence)518 int32_t HdiOutput::Commit(sptr<SyncFence> &fbFence)
519 {
520 CHECK_DEVICE_NULL(device_);
521 return device_->Commit(screenId_, fbFence);
522 }
523
CommitAndGetReleaseFence( sptr<SyncFence> &fbFence, int32_t &skipState, bool &needFlush, bool isValidated)524 int32_t HdiOutput::CommitAndGetReleaseFence(
525 sptr<SyncFence> &fbFence, int32_t &skipState, bool &needFlush, bool isValidated)
526 {
527 CHECK_DEVICE_NULL(device_);
528 layersId_.clear();
529 fences_.clear();
530 return device_->CommitAndGetReleaseFence(
531 screenId_, fbFence, skipState, needFlush, layersId_, fences_, isValidated);
532 }
533
UpdateInfosAfterCommit(sptr<SyncFence> fbFence)534 int32_t HdiOutput::UpdateInfosAfterCommit(sptr<SyncFence> fbFence)
535 {
536 std::unique_lock<std::mutex> lock(mutex_);
537 if (thirdFrameAheadPresentFence_ == nullptr) {
538 return GRAPHIC_DISPLAY_NULL_PTR;
539 }
540 UpdatePrevLayerInfoLocked();
541
542 if (sampler_ == nullptr) {
543 sampler_ = CreateVSyncSampler();
544 }
545 int64_t timestamp = thirdFrameAheadPresentFence_->SyncFileReadTimestamp();
546 bool startSample = false;
547 if (timestamp != SyncFence::FENCE_PENDING_TIMESTAMP) {
548 startSample = enableVsyncSample_.load() && sampler_->AddPresentFenceTime(timestamp);
549 RecordCompositionTime(timestamp);
550 bool presentTimeUpdated = false;
551 LayerPtr uniRenderLayer = nullptr;
552 for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
553 const LayerPtr &layer = iter->second;
554 if (layer->RecordPresentTime(timestamp)) {
555 presentTimeUpdated = true;
556 }
557 if (layer->GetLayerInfo() && layer->GetLayerInfo()->GetUniRenderFlag()) {
558 uniRenderLayer = layer;
559 }
560 }
561 if (presentTimeUpdated && uniRenderLayer) {
562 uniRenderLayer->RecordMergedPresentTime(timestamp);
563 }
564 }
565
566 int32_t ret = GRAPHIC_DISPLAY_SUCCESS;
567 if (startSample) {
568 ret = StartVSyncSampler();
569 }
570 if (historicalPresentfences_.size() == NUMBER_OF_HISTORICAL_FRAMES) {
571 thirdFrameAheadPresentFence_ = historicalPresentfences_[presentFenceIndex_];
572 historicalPresentfences_[presentFenceIndex_] = fbFence;
573 presentFenceIndex_ = (presentFenceIndex_ + 1) % NUMBER_OF_HISTORICAL_FRAMES;
574 } else {
575 historicalPresentfences_.push_back(fbFence);
576 }
577 return ret;
578 }
579
SetVsyncSamplerEnabled(bool enabled)580 void HdiOutput::SetVsyncSamplerEnabled(bool enabled)
581 {
582 RS_TRACE_NAME_FMT("HdiOutput::SetVsyncSamplerEnabled, enableVsyncSample_:%d", enabled);
583 HLOGI("Change enableVsyncSample_, value is %{public}d", enabled);
584 enableVsyncSample_.store(enabled);
585 }
586
GetVsyncSamplerEnabled()587 bool HdiOutput::GetVsyncSamplerEnabled()
588 {
589 return enableVsyncSample_.load();
590 }
591
ReleaseFramebuffer(const sptr<SyncFence>& releaseFence)592 int32_t HdiOutput::ReleaseFramebuffer(const sptr<SyncFence>& releaseFence)
593 {
594 if (currFrameBuffer_ == nullptr) {
595 return GRAPHIC_DISPLAY_NULL_PTR;
596 }
597
598 int32_t ret = GRAPHIC_DISPLAY_SUCCESS;
599 if (lastFrameBuffer_ != nullptr) {
600 if (!CheckFbSurface()) { // wrong check
601 ret = GRAPHIC_DISPLAY_NULL_PTR;
602 } else {
603 ret = fbSurface_->ReleaseFramebuffer(lastFrameBuffer_, releaseFence);
604 }
605 }
606
607 lastFrameBuffer_ = currFrameBuffer_;
608 currFrameBuffer_ = nullptr;
609 return ret;
610 }
611
ReleaseSurfaceBuffer(sptr<SyncFence>& releaseFence)612 void HdiOutput::ReleaseSurfaceBuffer(sptr<SyncFence>& releaseFence)
613 {
614 auto releaseBuffer = [](sptr<SurfaceBuffer> buffer, sptr<SyncFence> releaseFence,
615 sptr<IConsumerSurface> cSurface) -> void {
616 if (cSurface == nullptr) {
617 HLOGE("HdiOutput:: ReleaseBuffer failed, no consumer!");
618 return;
619 }
620 if (buffer == nullptr) {
621 return;
622 }
623 RS_TRACE_NAME("HdiOutput::ReleaseBuffer");
624 auto ret = cSurface->ReleaseBuffer(buffer, releaseFence);
625 if (ret == OHOS::SURFACE_ERROR_OK) {
626 // reset prevBuffer if we release it successfully,
627 // to avoid releasing the same buffer next frame in some situations.
628 buffer = nullptr;
629 releaseFence = SyncFence::InvalidFence();
630 }
631 };
632 const auto layersReleaseFence = GetLayersReleaseFenceLocked();
633 if (layersReleaseFence.size() == 0) {
634 // When release fence's size is 0, the output may invalid, release all buffer
635 // This situation may happen when killing composer_host
636 for (const auto& [id, layer] : layerIdMap_) {
637 if (layer == nullptr || layer->GetLayerInfo()->GetSurface() == nullptr) {
638 HLOGW("HdiOutput::ReleaseLayers: layer or layer's cSurface is nullptr");
639 continue;
640 }
641 auto preBuffer = layer->GetLayerInfo()->GetPreBuffer();
642 auto consumer = layer->GetLayerInfo()->GetSurface();
643 releaseBuffer(preBuffer, SyncFence::InvalidFence(), consumer);
644 }
645 HLOGD("HdiOutput::ReleaseLayers: no layer needs to release");
646 }
647 for (const auto& [layer, fence] : layersReleaseFence) {
648 if (layer != nullptr) {
649 auto preBuffer = layer->GetPreBuffer();
650 auto consumer = layer->GetSurface();
651 releaseBuffer(preBuffer, fence, consumer);
652 if (layer->GetUniRenderFlag()) {
653 releaseFence = fence;
654 }
655 }
656 }
657 }
658
ReleaseLayers(sptr<SyncFence>& releaseFence)659 void HdiOutput::ReleaseLayers(sptr<SyncFence>& releaseFence)
660 {
661 auto layerPresentTimestamp = [](const LayerInfoPtr& layer, const sptr<IConsumerSurface>& cSurface) -> void {
662 if (!layer->IsSupportedPresentTimestamp()) {
663 return;
664 }
665 const auto& buffer = layer->GetBuffer();
666 if (buffer == nullptr) {
667 return;
668 }
669 if (cSurface->SetPresentTimestamp(buffer->GetSeqNum(), layer->GetPresentTimestamp()) != GSERROR_OK) {
670 HLOGD("LayerPresentTimestamp: SetPresentTimestamp failed");
671 }
672 };
673
674 // get present timestamp from and set present timestamp to cSurface
675 std::unique_lock<std::mutex> lock(mutex_);
676 for (const auto& [id, layer] : layerIdMap_) {
677 if (layer == nullptr || layer->GetLayerInfo()->GetSurface() == nullptr) {
678 HLOGW("HdiOutput::ReleaseLayers: layer or layer's cSurface is nullptr");
679 continue;
680 }
681 layerPresentTimestamp(layer->GetLayerInfo(), layer->GetLayerInfo()->GetSurface());
682 }
683 ReleaseSurfaceBuffer(releaseFence);
684 }
685
GetLayersReleaseFence()686 std::map<LayerInfoPtr, sptr<SyncFence>> HdiOutput::GetLayersReleaseFence()
687 {
688 std::unique_lock<std::mutex> lock(mutex_);
689 return GetLayersReleaseFenceLocked();
690 }
691
GetLayersReleaseFenceLocked()692 std::map<LayerInfoPtr, sptr<SyncFence>> HdiOutput::GetLayersReleaseFenceLocked()
693 {
694 std::map<LayerInfoPtr, sptr<SyncFence>> res;
695 size_t layerNum = layersId_.size();
696 for (size_t i = 0; i < layerNum; i++) {
697 auto iter = layerIdMap_.find(layersId_[i]);
698 if (iter == layerIdMap_.end()) {
699 HLOGE("Invalid hdi layer id [%{public}u]", layersId_[i]);
700 continue;
701 }
702
703 const LayerPtr &layer = iter->second;
704 if (layer == nullptr || layer->GetLayerInfo() == nullptr) {
705 continue;
706 }
707 if (layer->GetLayerInfo()->GetUniRenderFlag()) {
708 layer->SetReleaseFence(fences_[i]);
709 res[layer->GetLayerInfo()] = fences_[i];
710 } else {
711 layer->MergeWithLayerFence(fences_[i]);
712 res[layer->GetLayerInfo()] = layer->GetReleaseFence();
713 }
714 }
715 return res;
716 }
717
StartVSyncSampler(bool forceReSample)718 int32_t HdiOutput::StartVSyncSampler(bool forceReSample)
719 {
720 ScopedBytrace func("HdiOutput::StartVSyncSampler, forceReSample:" + std::to_string(forceReSample));
721 if (!enableVsyncSample_.load()) {
722 ScopedBytrace func("disabled vsyncSample");
723 return GRAPHIC_DISPLAY_FAILURE;
724 }
725 if (sampler_ == nullptr) {
726 sampler_ = CreateVSyncSampler();
727 }
728 bool alreadyStartSample = sampler_->GetHardwareVSyncStatus();
729 if (!forceReSample && alreadyStartSample) {
730 HLOGD("Already Start Sample.");
731 return GRAPHIC_DISPLAY_SUCCESS;
732 }
733 HLOGD("Enable Screen Vsync");
734 sampler_->SetScreenVsyncEnabledInRSMainThread(true);
735 sampler_->BeginSample();
736 return GRAPHIC_DISPLAY_SUCCESS;
737 }
738
SetPendingMode(int64_t period, int64_t timestamp)739 void HdiOutput::SetPendingMode(int64_t period, int64_t timestamp)
740 {
741 ScopedBytrace func("VSyncSampler::SetPendingMode period:" + std::to_string(period) +
742 ", timestamp:" + std::to_string(timestamp));
743 if (sampler_ == nullptr) {
744 sampler_ = CreateVSyncSampler();
745 }
746 sampler_->SetPendingPeriod(period);
747 CreateVSyncGenerator()->SetPendingMode(period, timestamp);
748 }
749
Dump(std::string &result) const750 void HdiOutput::Dump(std::string &result) const
751 {
752 std::vector<LayerDumpInfo> dumpLayerInfos;
753 std::unique_lock<std::mutex> lock(mutex_);
754 ReorderLayerInfoLocked(dumpLayerInfos);
755
756 result.append("\n");
757 result.append("-- LayerInfo\n");
758
759 for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
760 const LayerPtr &layer = layerInfo.layer;
761 if (layer == nullptr || layer->GetLayerInfo() == nullptr ||
762 layer->GetLayerInfo()->GetSurface() == nullptr) {
763 continue;
764 }
765 const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
766 auto info = layer->GetLayerInfo();
767 result += "\n surface [" + name + "] NodeId[" + std::to_string(layerInfo.nodeId) + "]";
768 result += " LayerId[" + std::to_string(layer->GetLayerId()) + "]:\n";
769 info->Dump(result);
770 }
771
772 if (fbSurface_ != nullptr) {
773 result += "\n";
774 result += "FrameBufferSurface\n";
775 fbSurface_->Dump(result);
776 }
777 CreateVSyncGenerator()->Dump(result);
778 CreateVSyncSampler()->Dump(result);
779 }
780
DumpFps(std::string &result, const std::string &arg) const781 void HdiOutput::DumpFps(std::string &result, const std::string &arg) const
782 {
783 std::vector<LayerDumpInfo> dumpLayerInfos;
784 std::unique_lock<std::mutex> lock(mutex_);
785 ReorderLayerInfoLocked(dumpLayerInfos);
786 result.append("\n");
787 if (arg == "composer") {
788 result += "The fps of screen [Id:" + std::to_string(screenId_) + "] is:\n";
789 const int32_t offset = compTimeRcdIndex_;
790 for (uint32_t i = 0; i < COMPOSITION_RECORDS_NUM; i++) {
791 uint32_t order = (offset + i) % COMPOSITION_RECORDS_NUM;
792 result += std::to_string(compositionTimeRecords_[order]) + "\n";
793 }
794 return;
795 }
796
797 for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
798 const LayerPtr &layer = layerInfo.layer;
799 if (arg == "UniRender") {
800 if (layer->GetLayerInfo()->GetUniRenderFlag()) {
801 result += "\n surface [" + arg + "] Id[" + std::to_string(layerInfo.surfaceId) + "]:\n";
802 layer->DumpMergedResult(result);
803 break;
804 }
805 continue;
806 }
807 if (layer->GetLayerInfo()->GetSurface() == nullptr) {
808 continue;
809 }
810 const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
811 if (name == arg) {
812 result += "\n surface [" + name + "] Id[" + std::to_string(layerInfo.surfaceId) + "]:\n";
813 layer->Dump(result);
814 }
815 if (layer->GetLayerInfo()->GetUniRenderFlag()) {
816 auto windowsName = layer->GetLayerInfo()->GetWindowsName();
817 auto iter = std::find(windowsName.begin(), windowsName.end(), arg);
818 if (iter != windowsName.end()) {
819 result += "\n window [" + arg + "] Id[" + std::to_string(layerInfo.surfaceId) + "]:\n";
820 layer->DumpByName(arg, result);
821 }
822 }
823 }
824 }
825
DumpHitchs(std::string &result, const std::string &arg) const826 void HdiOutput::DumpHitchs(std::string &result, const std::string &arg) const
827 {
828 std::vector<LayerDumpInfo> dumpLayerInfos;
829 std::unique_lock<std::mutex> lock(mutex_);
830 ReorderLayerInfoLocked(dumpLayerInfos);
831 result.append("\n");
832 for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
833 const LayerPtr &layer = layerInfo.layer;
834 if (layer->GetLayerInfo()->GetUniRenderFlag()) {
835 result += "\n window [" + arg + "] Id[" + std::to_string(layerInfo.surfaceId) + "]:\n";
836 layer->SelectHitchsInfo(arg, result);
837 }
838 }
839 }
840
ClearFpsDump(std::string &result, const std::string &arg)841 void HdiOutput::ClearFpsDump(std::string &result, const std::string &arg)
842 {
843 std::vector<LayerDumpInfo> dumpLayerInfos;
844 std::unique_lock<std::mutex> lock(mutex_);
845 ReorderLayerInfoLocked(dumpLayerInfos);
846
847 result.append("\n");
848 if (arg == "composer") {
849 result += "The fps info of screen [Id:" + std::to_string(screenId_) + "] is cleared.\n";
850 compositionTimeRecords_.fill(0);
851 return;
852 }
853
854 for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
855 const LayerPtr &layer = layerInfo.layer;
856 if (layer == nullptr || layer->GetLayerInfo() == nullptr ||
857 layer->GetLayerInfo()->GetSurface() == nullptr) {
858 result += "layer is null.\n";
859 return;
860 }
861 const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
862 if (name == arg) {
863 result += "\n The fps info of surface [" + name + "] Id["
864 + std::to_string(layerInfo.surfaceId) + "] is cleared.\n";
865 layer->ClearDump();
866 }
867 }
868 }
869
Cmp(const LayerDumpInfo &layer1, const LayerDumpInfo &layer2)870 static inline bool Cmp(const LayerDumpInfo &layer1, const LayerDumpInfo &layer2)
871 {
872 return layer1.layer->GetLayerInfo()->GetZorder() < layer2.layer->GetLayerInfo()->GetZorder();
873 }
874
ReorderLayerInfoLocked(std::vector<LayerDumpInfo> &dumpLayerInfos) const875 void HdiOutput::ReorderLayerInfoLocked(std::vector<LayerDumpInfo> &dumpLayerInfos) const
876 {
877 for (auto iter = surfaceIdMap_.begin(); iter != surfaceIdMap_.end(); ++iter) {
878 if (iter->second == nullptr || iter->second->GetLayerInfo() == nullptr) {
879 continue;
880 }
881 struct LayerDumpInfo layerInfo = {
882 .nodeId = iter->second->GetLayerInfo()->GetNodeId(),
883 .surfaceId = iter->first,
884 .layer = iter->second,
885 };
886 dumpLayerInfos.emplace_back(layerInfo);
887 }
888
889 std::sort(dumpLayerInfos.begin(), dumpLayerInfos.end(), Cmp);
890 }
891
GetBufferCacheSize()892 int HdiOutput::GetBufferCacheSize()
893 {
894 return bufferCache_.size();
895 }
896
ClearBufferCache()897 void HdiOutput::ClearBufferCache()
898 {
899 if (bufferCache_.empty()) {
900 return;
901 }
902 int32_t ret = device_->ClearClientBuffer(screenId_);
903 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
904 HLOGD("Call hdi ClearClientBuffer failed, ret is %{public}d", ret);
905 }
906 bufferCache_.clear();
907 }
908 } // namespace Rosen
909 } // namespace OHOS
910