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