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