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