• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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