• 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 <scoped_bytrace.h>
17 #include "hdi_output.h"
18 
19 #define CHECK_DEVICE_NULL(device)                                   \
20     do {                                                            \
21         if ((device) == nullptr) {                                  \
22             HLOGD("[%{public}s]HdiDevice is nullptr.", __func__);   \
23             return ROSEN_ERROR_NOT_INIT;                            \
24         }                                                           \
25     } while (0)
26 
27 namespace OHOS {
28 namespace Rosen {
29 
CreateHdiOutput(uint32_t screenId)30 std::shared_ptr<HdiOutput> HdiOutput::CreateHdiOutput(uint32_t screenId)
31 {
32     return std::make_shared<HdiOutput>(screenId);
33 }
34 
HdiOutput(uint32_t screenId)35 HdiOutput::HdiOutput(uint32_t screenId) : screenId_(screenId)
36 {
37 }
38 
~HdiOutput()39 HdiOutput::~HdiOutput()
40 {
41 }
42 
Init()43 RosenError HdiOutput::Init()
44 {
45     if (fbSurface_ != nullptr) {
46         return ROSEN_ERROR_OK;
47     }
48 
49     fbSurface_ = HdiFramebufferSurface::CreateFramebufferSurface();
50     if (fbSurface_ == nullptr) {
51         HLOGE("Create framebuffer surface failed");
52         return ROSEN_ERROR_NOT_INIT;
53     }
54 
55     if (device_ != nullptr) {
56         return ROSEN_ERROR_OK;
57     }
58 
59     device_ = HdiDevice::GetInstance();
60     CHECK_DEVICE_NULL(device_);
61 
62     bufferCacheCountMax_ = fbSurface_->GetBufferQueueSize();
63     int32_t ret = device_->SetScreenClientBufferCacheCount(screenId_, bufferCacheCountMax_);
64     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
65         HLOGE("Set screen client buffer cache count failed, ret is %{public}d", ret);
66         return ROSEN_ERROR_INVALID_OPERATING;
67     }
68     bufferCache_.resize(bufferCacheCountMax_);
69 
70     return ROSEN_ERROR_OK;
71 }
72 
SetHdiOutputDevice(HdiDevice * device)73 RosenError HdiOutput::SetHdiOutputDevice(HdiDevice* device)
74 {
75     if (device == nullptr) {
76         HLOGE("Input HdiDevice is null");
77         return ROSEN_ERROR_INVALID_ARGUMENTS;
78     }
79 
80     if (device_ != nullptr) {
81         HLOGW("HdiDevice has been changed");
82         return ROSEN_ERROR_OK;
83     }
84     device_ = device;
85     return ROSEN_ERROR_OK;
86 }
87 
SetLayerInfo(const std::vector<LayerInfoPtr> & layerInfos)88 void HdiOutput::SetLayerInfo(const std::vector<LayerInfoPtr> &layerInfos)
89 {
90     for (auto &layerInfo : layerInfos) {
91         if (layerInfo == nullptr || layerInfo->GetSurface() == nullptr) {
92             HLOGE("current layerInfo or layerInfo's cSurface is null");
93             continue;
94         }
95 
96         uint64_t surfaceId = layerInfo->GetSurface()->GetUniqueId();
97         auto iter = surfaceIdMap_.find(surfaceId);
98         if (iter != surfaceIdMap_.end()) {
99             const LayerPtr &layer = iter->second;
100             layer->UpdateLayerInfo(layerInfo);
101             continue;
102         }
103 
104         int32_t ret = CreateLayer(surfaceId, layerInfo);
105         if (ret != GRAPHIC_DISPLAY_SUCCESS) {
106             return;
107         }
108     }
109 
110     DeletePrevLayers();
111     ResetLayerStatus();
112 }
113 
DeletePrevLayers()114 void HdiOutput::DeletePrevLayers()
115 {
116     auto surfaceIter = surfaceIdMap_.begin();
117     while (surfaceIter != surfaceIdMap_.end()) {
118         const LayerPtr &layer = surfaceIter->second;
119         if (!layer->GetLayerStatus()) {
120             surfaceIdMap_.erase(surfaceIter++);
121         } else {
122             ++surfaceIter;
123         }
124     }
125 
126     auto layerIter = layerIdMap_.begin();
127     while (layerIter != layerIdMap_.end()) {
128         const LayerPtr &layer = layerIter->second;
129         if (!layer->GetLayerStatus()) {
130             layerIdMap_.erase(layerIter++);
131         } else {
132             ++layerIter;
133         }
134     }
135 }
136 
ResetLayerStatus()137 void HdiOutput::ResetLayerStatus()
138 {
139     for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
140         iter->second->SetLayerStatus(false);
141     }
142 }
143 
CreateLayer(uint64_t surfaceId,const LayerInfoPtr & layerInfo)144 int32_t HdiOutput::CreateLayer(uint64_t surfaceId, const LayerInfoPtr &layerInfo)
145 {
146     LayerPtr layer = HdiLayer::CreateHdiLayer(screenId_);
147     if (!layer->Init(layerInfo)) {
148         HLOGE("Init hdiLayer failed");
149         return GRAPHIC_DISPLAY_FAILURE;
150     }
151 
152     layer->UpdateLayerInfo(layerInfo);
153     uint32_t layerId = layer->GetLayerId();
154     layerIdMap_[layerId] = layer;
155     surfaceIdMap_[surfaceId] = layer;
156 
157     return GRAPHIC_DISPLAY_SUCCESS;
158 }
159 
SetOutputDamages(const std::vector<GraphicIRect> & outputDamages)160 void HdiOutput::SetOutputDamages(const std::vector<GraphicIRect> &outputDamages)
161 {
162     outputDamages_ = outputDamages;
163 }
164 
GetOutputDamages()165 const std::vector<GraphicIRect>& HdiOutput::GetOutputDamages()
166 {
167     return outputDamages_;
168 }
169 
GetLayers()170 const std::unordered_map<uint32_t, std::shared_ptr<HdiLayer>>& HdiOutput::GetLayers()
171 {
172     return layerIdMap_;
173 }
174 
UpdatePrevLayerInfo()175 void HdiOutput::UpdatePrevLayerInfo()
176 {
177     for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); iter++) {
178         LayerPtr layer = iter->second;
179         layer->SavePrevLayerInfo();
180     }
181 }
182 
GetScreenId() const183 uint32_t HdiOutput::GetScreenId() const
184 {
185     return screenId_;
186 }
187 
SetLayerCompCapacity(uint32_t layerCompositionCapacity)188 void HdiOutput::SetLayerCompCapacity(uint32_t layerCompositionCapacity)
189 {
190     layerCompCapacity_ = layerCompositionCapacity;
191 }
192 
GetLayerCompCapacity() const193 uint32_t HdiOutput::GetLayerCompCapacity() const
194 {
195     return layerCompCapacity_;
196 }
197 
GetFrameBufferSurface()198 sptr<Surface> HdiOutput::GetFrameBufferSurface()
199 {
200     if (!CheckFbSurface()) {
201         return nullptr;
202     }
203 
204     return fbSurface_->GetSurface();
205 }
206 
GetFramebuffer()207 std::unique_ptr<FrameBufferEntry> HdiOutput::GetFramebuffer()
208 {
209     if (!CheckFbSurface()) {
210         return nullptr;
211     }
212 
213     return fbSurface_->GetFramebuffer();
214 }
215 
CheckFbSurface()216 bool HdiOutput::CheckFbSurface()
217 {
218     if (fbSurface_ == nullptr) {
219         HLOGE("fbSurface is nullptr");
220         return false;
221     }
222 
223     return true;
224 }
225 
RecordCompositionTime(int64_t timeStamp)226 void HdiOutput::RecordCompositionTime(int64_t timeStamp)
227 {
228     compositionTimeRecords_[compTimeRcdIndex_] = timeStamp;
229     compTimeRcdIndex_ = (compTimeRcdIndex_ + 1) % COMPOSITION_RECORDS_NUM;
230 }
231 
SetDirectClientCompEnableStatus(bool enableStatus)232 void HdiOutput::SetDirectClientCompEnableStatus(bool enableStatus)
233 {
234     directClientCompositionEnabled_ = enableStatus;
235 }
236 
GetDirectClientCompEnableStatus() const237 bool HdiOutput::GetDirectClientCompEnableStatus() const
238 {
239     return directClientCompositionEnabled_;
240 }
241 
PreProcessLayersComp(bool & needFlush)242 int32_t HdiOutput::PreProcessLayersComp(bool &needFlush)
243 {
244     if (layerIdMap_.empty()) {
245         HLOGI("layer map is empty, drop this frame");
246         return GRAPHIC_DISPLAY_PARAM_ERR;
247     }
248 
249     uint32_t layersNum = layerIdMap_.size();
250     // If doClientCompositionDirectly is true then layer->SetHdiLayerInfo and UpdateLayerCompType is no need to run.
251     bool doClientCompositionDirectly = ((layerCompCapacity_ != LAYER_COMPOSITION_CAPACITY_INVALID) &&
252                                         (layersNum > layerCompCapacity_));
253     if (!directClientCompositionEnabled_) {
254         doClientCompositionDirectly = false;
255     }
256 
257     int32_t ret;
258     for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
259         const LayerPtr &layer = iter->second;
260         if (doClientCompositionDirectly) {
261             layer->UpdateCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT);
262             continue;
263         }
264         ret = layer->SetHdiLayerInfo();
265         if (ret != GRAPHIC_DISPLAY_SUCCESS) {
266             HLOGE("Set hdi layer[id:%{public}d] info failed, ret %{public}d.", layer->GetLayerId(), ret);
267             return GRAPHIC_DISPLAY_FAILURE;
268         }
269     }
270 
271     CHECK_DEVICE_NULL(device_);
272     ret = device_->PrepareScreenLayers(screenId_, needFlush);
273     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
274         HLOGE("PrepareScreenLayers failed, ret is %{public}d", ret);
275         return GRAPHIC_DISPLAY_FAILURE;
276     }
277 
278     if (doClientCompositionDirectly) {
279         ScopedBytrace doClientCompositionDirectlyTag("DoClientCompositionDirectly");
280         HLOGD("Direct client composition is enabled.");
281         return GRAPHIC_DISPLAY_SUCCESS;
282     }
283 
284     return UpdateLayerCompType();
285 }
286 
UpdateLayerCompType()287 int32_t HdiOutput::UpdateLayerCompType()
288 {
289     CHECK_DEVICE_NULL(device_);
290     std::vector<uint32_t> layersId;
291     std::vector<int32_t> types;
292     int32_t ret = device_->GetScreenCompChange(screenId_, layersId, types);
293     if (ret != GRAPHIC_DISPLAY_SUCCESS || layersId.size() != types.size()) {
294         HLOGE("GetScreenCompChange failed, ret is %{public}d", ret);
295         return ret;
296     }
297 
298     size_t layerNum = layersId.size();
299     for (size_t i = 0; i < layerNum; i++) {
300         auto iter = layerIdMap_.find(layersId[i]);
301         if (iter == layerIdMap_.end()) {
302             HLOGE("Invalid hdi layer id[%{public}u]", layersId[i]);
303             continue;
304         }
305 
306         const LayerPtr &layer = iter->second;
307         layer->UpdateCompositionType(static_cast<GraphicCompositionType>(types[i]));
308     }
309 
310     return ret;
311 }
312 
CheckAndUpdateClientBufferCahce(sptr<SurfaceBuffer> buffer,uint32_t & index)313 bool HdiOutput::CheckAndUpdateClientBufferCahce(sptr<SurfaceBuffer> buffer, uint32_t& index)
314 {
315     for (uint32_t i = 0; i < bufferCacheCountMax_; i++) {
316         if (bufferCache_[i] == buffer) {
317             index = i;
318             return true;
319         }
320     }
321 
322     if (bufferCacheIndex_ >= bufferCacheCountMax_) {
323         HLOGE("HdiOutput::FlushScreen: the length of buffer cache exceeds the limit!");
324         return false;
325     }
326     bufferCache_[bufferCacheIndex_] = buffer;
327     index = bufferCacheIndex_;
328     bufferCacheIndex_++;
329     return false;
330 }
331 
FlushScreen(std::vector<LayerPtr> & compClientLayers)332 int32_t HdiOutput::FlushScreen(std::vector<LayerPtr> &compClientLayers)
333 {
334     auto fbEntry = GetFramebuffer();
335     if (fbEntry == nullptr) {
336         HLOGE("HdiBackend flush screen failed : GetFramebuffer failed!");
337         return -1;
338     }
339 
340     const auto& fbAcquireFence = fbEntry->acquireFence;
341     for (auto &layer : compClientLayers) {
342         layer->MergeWithFramebufferFence(fbAcquireFence);
343     }
344 
345     currFrameBuffer_ = fbEntry->buffer;
346     if (currFrameBuffer_ == nullptr) {
347         HLOGE("HdiBackend flush screen failed : frame buffer is null");
348         return -1;
349     }
350 
351     uint32_t index = INVALID_BUFFER_CACHE_INDEX;
352     bool bufferCached = false;
353     if (bufferCacheCountMax_ == 0) {
354         bufferCache_.clear();
355         bufferCacheIndex_ = INVALID_BUFFER_CACHE_INDEX;
356         HLOGE("The count of this client buffer cache is 0.");
357     } else {
358         bufferCached = CheckAndUpdateClientBufferCahce(currFrameBuffer_, index);
359     }
360 
361     CHECK_DEVICE_NULL(device_);
362     int32_t ret = device_->SetScreenClientDamage(screenId_, outputDamages_);
363     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
364         HLOGE("Set screen client damage failed, ret is %{public}d", ret);
365         return ret;
366     }
367 
368     CHECK_DEVICE_NULL(device_);
369     if (bufferCached && index < bufferCacheCountMax_) {
370         ret = device_->SetScreenClientBuffer(screenId_, nullptr, index, fbAcquireFence);
371     } else {
372         ret = device_->SetScreenClientBuffer(screenId_, currFrameBuffer_->GetBufferHandle(), index, fbAcquireFence);
373     }
374     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
375         HLOGE("Set screen client buffer failed, ret is %{public}d", ret);
376         return ret;
377     }
378 
379     return GRAPHIC_DISPLAY_SUCCESS;
380 }
381 
Commit(sptr<SyncFence> & fbFence)382 int32_t HdiOutput::Commit(sptr<SyncFence> &fbFence)
383 {
384     CHECK_DEVICE_NULL(device_);
385     return device_->Commit(screenId_, fbFence);
386 }
387 
UpdateInfosAfterCommit(sptr<SyncFence> fbFence)388 int32_t HdiOutput::UpdateInfosAfterCommit(sptr<SyncFence> fbFence)
389 {
390     UpdatePrevLayerInfo();
391 
392     if (sampler_ == nullptr) {
393         sampler_ = CreateVSyncSampler();
394     }
395     int64_t timestamp = lastPresentFence_->SyncFileReadTimestamp();
396     bool startSample = false;
397     if (timestamp != SyncFence::FENCE_PENDING_TIMESTAMP) {
398         startSample = sampler_->AddPresentFenceTime(timestamp);
399         RecordCompositionTime(timestamp);
400         for (auto iter = layerIdMap_.begin(); iter != layerIdMap_.end(); ++iter) {
401             const LayerPtr &layer = iter->second;
402             layer->RecordPresentTime(timestamp);
403         }
404     }
405 
406     int32_t ret = GRAPHIC_DISPLAY_SUCCESS;
407     bool alreadyStartSample = sampler_->GetHardwareVSyncStatus();
408     if (startSample && !alreadyStartSample) {
409         HLOGD("Enable Screen Vsync");
410         CHECK_DEVICE_NULL(device_);
411         ret = device_->SetScreenVsyncEnabled(screenId_, true);
412         if (ret == GRAPHIC_DISPLAY_SUCCESS) {
413             sampler_->BeginSample();
414         } else {
415             HLOGE("Enable Screen Vsync failed");
416         }
417     }
418     lastPresentFence_ = fbFence;
419     return ret;
420 }
421 
ReleaseFramebuffer(const sptr<SyncFence> & releaseFence)422 int32_t HdiOutput::ReleaseFramebuffer(const sptr<SyncFence>& releaseFence)
423 {
424     if (currFrameBuffer_ == nullptr) {
425         HLOGE("Current frame buffer is nullptr.");
426         return GRAPHIC_DISPLAY_NULL_PTR;
427     }
428 
429     int32_t ret = GRAPHIC_DISPLAY_SUCCESS;
430     if (lastFrameBuffer_ != nullptr) {
431         if (!CheckFbSurface()) { // wrong check
432             ret = GRAPHIC_DISPLAY_NULL_PTR;
433         } else {
434             ret = fbSurface_->ReleaseFramebuffer(lastFrameBuffer_, releaseFence);
435         }
436     }
437 
438     lastFrameBuffer_ = currFrameBuffer_;
439     currFrameBuffer_ = nullptr;
440     return ret;
441 }
442 
GetLayersReleaseFence()443 std::map<LayerInfoPtr, sptr<SyncFence>> HdiOutput::GetLayersReleaseFence()
444 {
445     if (device_ == nullptr) {
446         return {};
447     }
448     std::vector<uint32_t> layersId;
449     std::vector<sptr<SyncFence>> fences;
450     int32_t ret = device_->GetScreenReleaseFence(screenId_, layersId, fences);
451     if (ret != GRAPHIC_DISPLAY_SUCCESS || layersId.size() != fences.size()) {
452         HLOGE("GetScreenReleaseFence failed, ret is %{public}d, layerId size[%{public}d], fence size[%{public}d]",
453               ret, (int)layersId.size(), (int)fences.size());
454         return {};
455     }
456 
457     std::map<LayerInfoPtr, sptr<SyncFence>> res;
458     size_t layerNum = layersId.size();
459     for (size_t i = 0; i < layerNum; i++) {
460         auto iter = layerIdMap_.find(layersId[i]);
461         if (iter == layerIdMap_.end()) {
462             HLOGE("Invalid hdi layer id [%{public}u]", layersId[i]);
463             continue;
464         }
465 
466         const LayerPtr &layer = iter->second;
467         layer->MergeWithLayerFence(fences[i]);
468         res[layer->GetLayerInfo()] = layer->GetReleaseFence();
469     }
470     return res;
471 }
472 
Dump(std::string & result) const473 void HdiOutput::Dump(std::string &result) const
474 {
475     std::vector<LayerDumpInfo> dumpLayerInfos;
476     ReorderLayerInfo(dumpLayerInfos);
477 
478     result.append("\n");
479     result.append("-- LayerInfo\n");
480 
481     for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
482         const LayerPtr &layer = layerInfo.layer;
483         if (layer == nullptr || layer->GetLayerInfo() == nullptr ||
484             layer->GetLayerInfo()->GetSurface() == nullptr) {
485             continue;
486         }
487         const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
488         const LayerInfoPtr &info = layer->GetLayerInfo();
489         result += "\n surface [" + name + "] NodeId[" + std::to_string(layerInfo.surfaceId) + "]";
490         result +=  " LayerId[" + std::to_string(layer->GetLayerId()) + "]:\n";
491         info->Dump(result);
492     }
493 
494     if (fbSurface_ != nullptr) {
495         result += "\n";
496         result += "FrameBufferSurface\n";
497         fbSurface_->Dump(result);
498     }
499 }
500 
DumpFps(std::string & result,const std::string & arg) const501 void HdiOutput::DumpFps(std::string &result, const std::string &arg) const
502 {
503     std::vector<LayerDumpInfo> dumpLayerInfos;
504     ReorderLayerInfo(dumpLayerInfos);
505 
506     result.append("\n");
507     if (arg == "composer") {
508         result += "The fps of screen [Id:" + std::to_string(screenId_) + "] is:\n";
509         const int32_t offset = compTimeRcdIndex_;
510         for (uint32_t i = 0; i < COMPOSITION_RECORDS_NUM; i++) {
511             uint32_t order = (offset + i) % COMPOSITION_RECORDS_NUM;
512             result += std::to_string(compositionTimeRecords_[order]) + "\n";
513         }
514         return;
515     }
516 
517     for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
518         const LayerPtr &layer = layerInfo.layer;
519         const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
520         if (name == arg) {
521             result += "\n surface [" + name + "] Id[" + std::to_string(layerInfo.surfaceId) + "]:\n";
522             layer->Dump(result);
523         }
524     }
525 }
526 
ClearFpsDump(std::string & result,const std::string & arg)527 void HdiOutput::ClearFpsDump(std::string &result, const std::string &arg)
528 {
529     std::vector<LayerDumpInfo> dumpLayerInfos;
530     ReorderLayerInfo(dumpLayerInfos);
531 
532     result.append("\n");
533     if (arg == "composer") {
534         result += "The fps info of screen [Id:" + std::to_string(screenId_) + "] is cleared.\n";
535         compositionTimeRecords_.fill(0);
536         return;
537     }
538 
539     for (const LayerDumpInfo &layerInfo : dumpLayerInfos) {
540         const LayerPtr &layer = layerInfo.layer;
541         const std::string& name = layer->GetLayerInfo()->GetSurface()->GetName();
542         if (name == arg) {
543             result += "\n The fps info of surface [" + name + "] Id["
544                 + std::to_string(layerInfo.surfaceId) + "] is cleared.\n";
545             layer->ClearDump();
546         }
547     }
548 }
549 
Cmp(const LayerDumpInfo & layer1,const LayerDumpInfo & layer2)550 static inline bool Cmp(const LayerDumpInfo &layer1, const LayerDumpInfo &layer2)
551 {
552     return layer1.layer->GetLayerInfo()->GetZorder() < layer2.layer->GetLayerInfo()->GetZorder();
553 }
554 
ReorderLayerInfo(std::vector<LayerDumpInfo> & dumpLayerInfos) const555 void HdiOutput::ReorderLayerInfo(std::vector<LayerDumpInfo> &dumpLayerInfos) const
556 {
557     for (auto iter = surfaceIdMap_.begin(); iter != surfaceIdMap_.end(); ++iter) {
558         struct LayerDumpInfo layerInfo = {
559             .surfaceId = iter->first,
560             .layer = iter->second,
561         };
562         dumpLayerInfos.emplace_back(layerInfo);
563     }
564 
565     std::sort(dumpLayerInfos.begin(), dumpLayerInfos.end(), Cmp);
566 }
567 } // namespace Rosen
568 } // namespace OHOS
569