• 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 "hdi_backend.h"
17 
18 #include <scoped_bytrace.h>
19 #include "surface_buffer.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 
GetInstance()24 HdiBackend* HdiBackend::GetInstance()
25 {
26     static HdiBackend instance;
27 
28     return &instance;
29 }
30 
RegScreenHotplug(OnScreenHotplugFunc func,void * data)31 RosenError HdiBackend::RegScreenHotplug(OnScreenHotplugFunc func, void* data)
32 {
33     if (func == nullptr) {
34         HLOGE("OnScreenHotplugFunc is null");
35         return ROSEN_ERROR_INVALID_ARGUMENTS;
36     }
37 
38     onScreenHotplugCb_ = func;
39     onHotPlugCbData_ = data;
40 
41     return InitDevice();
42 }
43 
RegPrepareComplete(OnPrepareCompleteFunc func,void * data)44 RosenError HdiBackend::RegPrepareComplete(OnPrepareCompleteFunc func, void* data)
45 {
46     if (func == nullptr) {
47         HLOGE("OnPrepareCompleteFunc is null");
48         return ROSEN_ERROR_INVALID_ARGUMENTS;
49     }
50 
51     onPrepareCompleteCb_ = func;
52     onPrepareCompleteCbData_ = data;
53 
54     return ROSEN_ERROR_OK;
55 }
56 
PreProcessLayersComp(const OutputPtr & output,const std::unordered_map<uint32_t,LayerPtr> & layersMap,bool & needFlush)57 int32_t HdiBackend::PreProcessLayersComp(const OutputPtr &output,
58                                          const std::unordered_map<uint32_t, LayerPtr> &layersMap, bool &needFlush)
59 {
60     if (device_ == nullptr) {
61         HLOGE("device has not been initialized");
62         return DISPLAY_FAILURE;
63     }
64 
65     uint32_t layersNum = layersMap.size();
66     uint32_t layerCompCapacity = output->GetLayerCompCapacity();
67     uint32_t screenId = output->GetScreenId();
68 
69     // If doClientCompositionDirectly is true then layer->SetHdiLayerInfo and UpdateLayerCompType is no need to run.
70     bool doClientCompositionDirectly = ((layerCompCapacity != LAYER_COMPOSITION_CAPACITY_INVALID) &&
71                                         (layersNum > layerCompCapacity));
72     bool isDirectClientCompositionEnabled = output->GetDirectClientCompEnableStatus();
73     if (!isDirectClientCompositionEnabled) {
74         doClientCompositionDirectly = false;
75     }
76     int32_t ret;
77     for (auto iter = layersMap.begin(); iter != layersMap.end(); ++iter) {
78         const LayerPtr &layer = iter->second;
79         if (doClientCompositionDirectly) {
80             HLOGD("Direct client composition is enabled.");
81             layer->UpdateCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT);
82             continue;
83         }
84         ret = layer->SetHdiLayerInfo();
85         if (ret != DISPLAY_SUCCESS) {
86             HLOGE("Set hdi layer[id:%{public}d] info failed, ret %{public}d.", layer->GetLayerId(), ret);
87         }
88     }
89 
90     ret = device_->PrepareScreenLayers(screenId, needFlush);
91     if (ret != DISPLAY_SUCCESS) {
92         HLOGE("PrepareScreenLayers failed, ret is %{public}d", ret);
93         return DISPLAY_FAILURE;
94     }
95 
96     if (doClientCompositionDirectly) {
97         ScopedBytrace doClientCompositionDirectlyTag("DoClientCompositionDirectly");
98         return DISPLAY_SUCCESS;
99     }
100 
101     return UpdateLayerCompType(screenId, layersMap);
102 }
103 
Repaint(std::vector<OutputPtr> & outputs)104 void HdiBackend::Repaint(std::vector<OutputPtr> &outputs)
105 {
106     ScopedBytrace bytrace(__func__);
107     HLOGD("%{public}s: start", __func__);
108 
109     if (device_ == nullptr) {
110         HLOGE("device has not been initialized");
111         return;
112     }
113 
114     if (sampler_ == nullptr) {
115         sampler_ = CreateVSyncSampler();
116     }
117 
118     int32_t ret = DISPLAY_SUCCESS;
119     for (auto &output : outputs) {
120         if (output == nullptr) {
121             continue;
122         }
123         const std::unordered_map<uint32_t, LayerPtr> &layersMap = output->GetLayers();
124         if (layersMap.empty()) {
125             HLOGI("layer map is empty, drop this frame");
126             continue;
127         }
128         bool needFlush = false;
129         ret = PreProcessLayersComp(output, layersMap, needFlush);
130         if (ret != DISPLAY_SUCCESS) {
131             HLOGE("Pre process layers composition failed, ret = %{public}d.", ret);
132             return;
133         }
134 
135         uint32_t screenId = output->GetScreenId();
136         std::vector<LayerPtr> compClientLayers;
137         std::vector<LayerInfoPtr> newLayerInfos;
138         for (auto iter = layersMap.begin(); iter != layersMap.end(); ++iter) {
139             const LayerPtr &layer = iter->second;
140             newLayerInfos.emplace_back(layer->GetLayerInfo());
141             if (layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT) {
142                 compClientLayers.emplace_back(layer);
143             }
144         }
145 
146         if (compClientLayers.size() > 0) {
147             needFlush = true;
148             HLOGD("Need flush framebuffer, client composition layer num is %{public}zu", compClientLayers.size());
149         }
150 
151         OnPrepareComplete(needFlush, output, newLayerInfos);
152         sptr<SurfaceBuffer> frameBuffer = nullptr;
153         if (needFlush) {
154             if (FlushScreen(output, compClientLayers, frameBuffer) != DISPLAY_SUCCESS) {
155                 // return
156             }
157         }
158 
159         sptr<SyncFence> fbFence = SyncFence::INVALID_FENCE;
160         ret = device_->Commit(screenId, fbFence);
161         if (ret != DISPLAY_SUCCESS) {
162             HLOGE("commit failed, ret is %{public}d", ret);
163             // return
164         }
165 
166         output->UpdatePrevLayerInfo();
167         int64_t timestamp = lastPresentFence_->SyncFileReadTimestamp();
168         bool startSample = false;
169         if (timestamp != SyncFence::FENCE_PENDING_TIMESTAMP) {
170             startSample = sampler_->AddPresentFenceTime(timestamp);
171             output->RecordCompositionTime(timestamp);
172             for (auto iter = layersMap.begin(); iter != layersMap.end(); ++iter) {
173                 const LayerPtr &layer = iter->second;
174                 layer->RecordPresentTime(timestamp);
175             }
176         }
177         if (startSample) {
178             HLOGD("Enable Screen Vsync");
179             device_->SetScreenVsyncEnabled(screenId, true);
180             sampler_->BeginSample();
181         }
182 
183         ReleaseFramebuffer(output, fbFence, frameBuffer);
184         lastPresentFence_ = fbFence;
185         HLOGD("%{public}s: end", __func__);
186     }
187 }
188 
UpdateLayerCompType(uint32_t screenId,const std::unordered_map<uint32_t,LayerPtr> & layersMap)189 int32_t HdiBackend::UpdateLayerCompType(uint32_t screenId, const std::unordered_map<uint32_t, LayerPtr> &layersMap)
190 {
191     std::vector<uint32_t> layersId;
192     std::vector<int32_t> types;
193     int32_t ret = device_->GetScreenCompChange(screenId, layersId, types);
194     if (ret != DISPLAY_SUCCESS || layersId.size() != types.size()) {
195         HLOGE("GetScreenCompChange failed, ret is %{public}d", ret);
196         return ret;
197     }
198 
199     size_t layerNum = layersId.size();
200     for (size_t i = 0; i < layerNum; i++) {
201         auto iter = layersMap.find(layersId[i]);
202         if (iter == layersMap.end()) {
203             HLOGE("Invalid hdi layer id[%{public}u]", layersId[i]);
204             continue;
205         }
206 
207         const LayerPtr &layer = iter->second;
208         layer->UpdateCompositionType(static_cast<GraphicCompositionType>(types[i]));
209     }
210 
211     return ret;
212 }
213 
OnPrepareComplete(bool needFlush,OutputPtr & output,std::vector<LayerInfoPtr> & newLayerInfos)214 void HdiBackend::OnPrepareComplete(bool needFlush, OutputPtr &output, std::vector<LayerInfoPtr> &newLayerInfos)
215 {
216     if (needFlush) {
217         ReorderLayerInfo(newLayerInfos);
218     }
219 
220     struct PrepareCompleteParam param = {
221         .needFlushFramebuffer = needFlush,
222         .layers = newLayerInfos,
223     };
224 
225     auto fbSurface = output->GetFrameBufferSurface();
226     if (onPrepareCompleteCb_ != nullptr) {
227         onPrepareCompleteCb_(fbSurface, param, onPrepareCompleteCbData_);
228     }
229 }
230 
Cmp(const LayerInfoPtr & layer1,const LayerInfoPtr & layer2)231 static inline bool Cmp(const LayerInfoPtr &layer1, const LayerInfoPtr &layer2)
232 {
233     return layer1->GetZorder() < layer2->GetZorder();
234 }
235 
ReorderLayerInfo(std::vector<LayerInfoPtr> & newLayerInfos)236 void HdiBackend::ReorderLayerInfo(std::vector<LayerInfoPtr> &newLayerInfos)
237 {
238     std::sort(newLayerInfos.begin(), newLayerInfos.end(), Cmp);
239 }
240 
FlushScreen(const OutputPtr & output,std::vector<LayerPtr> & compClientLayers,sptr<SurfaceBuffer> & buffer)241 int32_t HdiBackend::FlushScreen(
242     const OutputPtr &output, std::vector<LayerPtr> &compClientLayers, sptr<SurfaceBuffer> &buffer)
243 {
244     auto fbEntry = output->GetFramebuffer();
245     if (fbEntry == nullptr) {
246         HLOGE("HdiBackend::FlushScreen: GetFramebuffer failed!");
247         return -1;
248     }
249 
250     const auto& fbAcquireFence = fbEntry->acquireFence;
251     for (auto &layer : compClientLayers) {
252         layer->MergeWithFramebufferFence(fbAcquireFence);
253     }
254 
255     buffer = fbEntry->buffer;
256     return SetScreenClientInfo(*fbEntry, output);
257 }
258 
ReleaseFramebuffer(const OutputPtr & output,sptr<SyncFence> & presentFence,const sptr<SurfaceBuffer> & buffer)259 void HdiBackend::ReleaseFramebuffer(
260     const OutputPtr &output, sptr<SyncFence> &presentFence, const sptr<SurfaceBuffer> &buffer)
261 {
262     if (buffer == nullptr) {
263         return;
264     }
265     if (lastFrameBuffers_.find(output->GetScreenId()) != lastFrameBuffers_.end()) {
266         // wrong check
267         (void)output->ReleaseFramebuffer(lastFrameBuffers_[output->GetScreenId()], presentFence);
268     }
269     lastFrameBuffers_[output->GetScreenId()] = buffer;
270 }
271 
SetScreenClientInfo(const FrameBufferEntry & fbEntry,const OutputPtr & output)272 int32_t HdiBackend::SetScreenClientInfo(const FrameBufferEntry &fbEntry, const OutputPtr &output)
273 {
274     if (fbEntry.buffer == nullptr) {
275         HLOGE("SetScreenClientBuffer failed: frame buffer is null");
276         return -1;
277     }
278 
279     int ret = device_->SetScreenClientBuffer(output->GetScreenId(),
280         fbEntry.buffer->GetBufferHandle(), fbEntry.acquireFence);
281     if (ret != DISPLAY_SUCCESS) {
282         HLOGE("SetScreenClientBuffer failed, ret is %{public}d", ret);
283         return ret;
284     }
285 
286     ret = device_->SetScreenClientDamage(output->GetScreenId(), output->GetOutputDamageNum(),
287                                          output->GetOutputDamage());
288     if (ret != DISPLAY_SUCCESS) {
289         HLOGD("SetScreenClientDamage failed, ret is %{public}d", ret);
290         return ret;
291     }
292 
293     return DISPLAY_SUCCESS;
294 }
295 
GetLayersReleaseFence(const OutputPtr & output)296 std::map<LayerInfoPtr, sptr<SyncFence>> HdiBackend::GetLayersReleaseFence(const OutputPtr& output)
297 {
298     if (output == nullptr) {
299         return {};
300     }
301     uint32_t screenId = output->GetScreenId();
302     std::vector<uint32_t> layersId;
303     std::vector<sptr<SyncFence>> fences;
304     int32_t ret = device_->GetScreenReleaseFence(screenId, layersId, fences);
305     if (ret != DISPLAY_SUCCESS || layersId.size() != fences.size()) {
306         HLOGE("GetScreenReleaseFence failed, ret is %{public}d, layerId size[%{public}d], fence size[%{public}d]",
307                ret, (int)layersId.size(), (int)fences.size());
308         return {};
309     }
310 
311     std::map<LayerInfoPtr, sptr<SyncFence>> res;
312     auto layersMap = output->GetLayers();
313     size_t layerNum = layersId.size();
314     for (size_t i = 0; i < layerNum; i++) {
315         auto iter = layersMap.find(layersId[i]);
316         if (iter == layersMap.end()) {
317             HLOGE("Invalid hdi layer id [%{public}u]", layersId[i]);
318             continue;
319         }
320 
321         const LayerPtr &layer = iter->second;
322         layer->MergeWithLayerFence(fences[i]);
323         res[layer->GetLayerInfo()] = layer->GetReleaseFence();
324     }
325     return res;
326 }
327 
OnHdiBackendHotPlugEvent(uint32_t screenId,bool connected,void * data)328 void HdiBackend::OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data)
329 {
330     HLOGI("HotPlugEvent, screenId is %{public}u, connected is %{public}u", screenId, connected);
331     HdiBackend *hdiBackend = nullptr;
332     if (data != nullptr) {
333         hdiBackend = static_cast<HdiBackend *>(data);
334     } else {
335         hdiBackend = HdiBackend::GetInstance();
336     }
337 
338     hdiBackend->OnHdiBackendConnected(screenId, connected);
339 }
340 
OnHdiBackendConnected(uint32_t screenId,bool connected)341 void HdiBackend::OnHdiBackendConnected(uint32_t screenId, bool connected)
342 {
343     if (connected) {
344         CreateHdiOutput(screenId);
345     }
346 
347     OnScreenHotplug(screenId, connected);
348 }
349 
CreateHdiOutput(uint32_t screenId)350 void HdiBackend::CreateHdiOutput(uint32_t screenId)
351 {
352     OutputPtr newOutput = HdiOutput::CreateHdiOutput(screenId);
353     newOutput->Init();
354     outputs_.emplace(screenId, newOutput);
355 }
356 
OnScreenHotplug(uint32_t screenId,bool connected)357 void HdiBackend::OnScreenHotplug(uint32_t screenId, bool connected)
358 {
359     auto iter = outputs_.find(screenId);
360     if (iter == outputs_.end()) {
361         HLOGE("invalid hotplug screen id[%{public}u]", screenId);
362         return;
363     }
364 
365     if (onScreenHotplugCb_ != nullptr) {
366         onScreenHotplugCb_(iter->second, connected, onHotPlugCbData_);
367     }
368 
369     if (!connected) {
370         outputs_.erase(iter);
371     }
372 }
373 
InitDevice()374 RosenError HdiBackend::InitDevice()
375 {
376     if (device_ != nullptr) {
377         return ROSEN_ERROR_OK;
378     }
379 
380     device_ = HdiDevice::GetInstance();
381     if (device_ == nullptr) {
382         HLOGE("Get HdiDevice failed");
383         return ROSEN_ERROR_NOT_INIT;
384     }
385 
386     int32_t ret = device_->RegHotPlugCallback(HdiBackend::OnHdiBackendHotPlugEvent, this);
387     if (ret != DISPLAY_SUCCESS) {
388         HLOGE("RegHotPlugCallback failed, ret is %{public}d", ret);
389         return ROSEN_ERROR_API_FAILED;
390     }
391 
392     HLOGI("Init device succeed");
393 
394     return ROSEN_ERROR_OK;
395 }
396 
SetHdiBackendDevice(Base::HdiDevice * device)397 void HdiBackend::SetHdiBackendDevice(Base::HdiDevice* device)
398 {
399     if (device == nullptr) {
400         HLOGE("Input HdiDevice is null");
401         return;
402     }
403 
404     if (device_ != nullptr) {
405         HLOGW("HdiDevice has been changed");
406         return;
407     }
408     device_ = device;
409 }
410 
411 } // namespace Rosen
412 } // namespace OHOS
413