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 #include "hdi_log.h"
18
19 #include <scoped_bytrace.h>
20 #include "surface_buffer.h"
21 #include "hitrace_meter.h"
22 #include "sync_fence_tracker.h"
23
24 namespace OHOS {
25 namespace Rosen {
26
GetInstance()27 HdiBackend* HdiBackend::GetInstance()
28 {
29 static HdiBackend instance;
30
31 return &instance;
32 }
33
RegScreenHotplug(OnScreenHotplugFunc func, void* data)34 RosenError HdiBackend::RegScreenHotplug(OnScreenHotplugFunc func, void* data)
35 {
36 if (func == nullptr) {
37 HLOGE("OnScreenHotplugFunc is null");
38 return ROSEN_ERROR_INVALID_ARGUMENTS;
39 }
40
41 onScreenHotplugCb_ = func;
42 onHotPlugCbData_ = data;
43
44 RosenError retCode = InitDevice();
45 if (retCode != ROSEN_ERROR_OK) {
46 return retCode;
47 }
48
49 int32_t ret = device_->RegHotPlugCallback(HdiBackend::OnHdiBackendHotPlugEvent, this);
50 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
51 HLOGE("RegHotPlugCallback failed, ret is %{public}d", ret);
52 return ROSEN_ERROR_API_FAILED;
53 }
54
55 return ROSEN_ERROR_OK;
56 }
57
RegScreenRefresh(OnScreenRefreshFunc func, void* data)58 RosenError HdiBackend::RegScreenRefresh(OnScreenRefreshFunc func, void* data)
59 {
60 if (func == nullptr) {
61 HLOGE("OnScreenRefreshFunc is null");
62 return ROSEN_ERROR_INVALID_ARGUMENTS;
63 }
64
65 onScreenRefreshCb_ = func;
66 onRefreshCbData_ = data;
67
68 RosenError retCode = InitDevice();
69 if (retCode != ROSEN_ERROR_OK) {
70 return retCode;
71 }
72
73 int32_t ret = device_->RegRefreshCallback(HdiBackend::OnHdiBackendRefreshEvent, this);
74 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
75 HLOGE("RegRefreshCallback failed, ret is %{public}d", ret);
76 return ROSEN_ERROR_API_FAILED;
77 }
78
79 return ROSEN_ERROR_OK;
80 }
81
OnHdiBackendRefreshEvent(uint32_t deviceId, void *data)82 void HdiBackend::OnHdiBackendRefreshEvent(uint32_t deviceId, void *data)
83 {
84 HdiBackend *hdiBackend = nullptr;
85 if (data != nullptr) {
86 hdiBackend = static_cast<HdiBackend *>(data);
87 } else {
88 hdiBackend = HdiBackend::GetInstance();
89 }
90
91 hdiBackend->OnScreenRefresh(deviceId);
92 }
93
OnScreenRefresh(uint32_t deviceId)94 void HdiBackend::OnScreenRefresh(uint32_t deviceId)
95 {
96 if (onScreenRefreshCb_ != nullptr) {
97 onScreenRefreshCb_(deviceId, onRefreshCbData_);
98 }
99 }
100
RegPrepareComplete(OnPrepareCompleteFunc func, void* data)101 RosenError HdiBackend::RegPrepareComplete(OnPrepareCompleteFunc func, void* data)
102 {
103 if (func == nullptr) {
104 HLOGE("OnPrepareCompleteFunc is null");
105 return ROSEN_ERROR_INVALID_ARGUMENTS;
106 }
107
108 onPrepareCompleteCb_ = func;
109 onPrepareCompleteCbData_ = data;
110
111 return ROSEN_ERROR_OK;
112 }
113
RegHwcDeadListener(OnHwcDeadCallback func, void* data)114 RosenError HdiBackend::RegHwcDeadListener(OnHwcDeadCallback func, void* data)
115 {
116 if (func == nullptr) {
117 HLOGE("onHwcDeadCallbackFunc is null.");
118 return ROSEN_ERROR_INVALID_ARGUMENTS;
119 }
120
121 RosenError retCode = InitDevice();
122 if (retCode != ROSEN_ERROR_OK) {
123 return retCode;
124 }
125
126 bool ret = device_->RegHwcDeadCallback(func, data);
127 if (!ret) {
128 HLOGE("RegHwcDeadCallback failed, ret is %{public}d", ret);
129 return ROSEN_ERROR_API_FAILED;
130 }
131
132 return ROSEN_ERROR_OK;
133 }
134
RegScreenVBlankIdleCallback(OnVBlankIdleCallback func, void* data)135 RosenError HdiBackend::RegScreenVBlankIdleCallback(OnVBlankIdleCallback func, void* data)
136 {
137 if (func == nullptr) {
138 HLOGE("OnScreenVBlankIdleFunc is null.");
139 return ROSEN_ERROR_INVALID_ARGUMENTS;
140 }
141
142 RosenError retCode = InitDevice();
143 if (retCode != ROSEN_ERROR_OK) {
144 return retCode;
145 }
146
147 int32_t ret = device_->RegScreenVBlankIdleCallback(func, data);
148 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
149 HLOGE("RegScreenVBlankIdleCallback failed, ret is %{public}d", ret);
150 return ROSEN_ERROR_API_FAILED;
151 }
152
153 return ROSEN_ERROR_OK;
154 }
155
SetPendingMode(const OutputPtr &output, int64_t period, int64_t timestamp)156 void HdiBackend::SetPendingMode(const OutputPtr &output, int64_t period, int64_t timestamp)
157 {
158 if (output == nullptr) {
159 HLOGE("output is nullptr.");
160 return;
161 }
162 output->SetPendingMode(period, timestamp);
163 }
164
PrepareCompleteIfNeed(const OutputPtr &output, bool needFlush)165 int32_t HdiBackend::PrepareCompleteIfNeed(const OutputPtr &output, bool needFlush)
166 {
167 std::vector<LayerPtr> compClientLayers;
168 output->GetComposeClientLayers(compClientLayers);
169 std::vector<LayerInfoPtr> newLayerInfos;
170 output->GetLayerInfos(newLayerInfos);
171
172 if (compClientLayers.size() > 0) {
173 needFlush = true;
174 HLOGD("Need flush framebuffer, client composition layer num is %{public}zu", compClientLayers.size());
175 }
176
177 OnPrepareComplete(needFlush, output, newLayerInfos);
178 if (needFlush) {
179 return output->FlushScreen(compClientLayers);
180 }
181 return GRAPHIC_DISPLAY_SUCCESS;
182 }
183
Repaint(const OutputPtr &output)184 void HdiBackend::Repaint(const OutputPtr &output)
185 {
186 ScopedBytrace bytrace(__func__);
187 HLOGD("%{public}s: start", __func__);
188
189 if (output == nullptr) {
190 HLOGE("output is nullptr.");
191 return;
192 }
193
194 bool needFlush = false;
195 int32_t skipState = INT32_MAX;
196 int32_t ret = output->PreProcessLayersComp();
197 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
198 HLOGE("PreProcessLayersComp failed, ret is %{public}d", ret);
199 return;
200 }
201
202 sptr<SyncFence> fbFence = SyncFence::InvalidFence();
203 ret = output->CommitAndGetReleaseFence(fbFence, skipState, needFlush, false);
204 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
205 HLOGE("first commit failed, ret is %{public}d, skipState is %{public}d", ret, skipState);
206 }
207
208 if (skipState != GRAPHIC_DISPLAY_SUCCESS) {
209 ret = output->UpdateLayerCompType();
210 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
211 return;
212 }
213 ret = PrepareCompleteIfNeed(output, needFlush);
214 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
215 return;
216 }
217 skipState = INT32_MAX;
218 ret = output->CommitAndGetReleaseFence(fbFence, skipState, needFlush, true);
219 HLOGD("%{public}s: ValidateDisplay", __func__);
220 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
221 HLOGE("second commit failed, ret is %{public}d", ret);
222 }
223 }
224
225 if (IsTagEnabled(HITRACE_TAG_GRAPHIC_AGP)) {
226 static SyncFenceTracker presentFenceThread("Present Fence");
227 presentFenceThread.TrackFence(fbFence);
228 }
229
230 ret = output->UpdateInfosAfterCommit(fbFence);
231 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
232 return;
233 }
234
235 ret = output->ReleaseFramebuffer(fbFence);
236 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
237 return;
238 }
239 HLOGD("%{public}s: end", __func__);
240 }
241
StartSample(const OutputPtr &output)242 void HdiBackend::StartSample(const OutputPtr &output)
243 {
244 if (output == nullptr) {
245 HLOGE("output is nullptr.");
246 return;
247 }
248 output->StartVSyncSampler(true); // force resample
249 }
250
SetVsyncSamplerEnabled(const OutputPtr &output, bool enabled)251 void HdiBackend::SetVsyncSamplerEnabled(const OutputPtr &output, bool enabled)
252 {
253 if (output == nullptr) {
254 HLOGE("output is nullptr.");
255 return;
256 }
257 output->SetVsyncSamplerEnabled(enabled);
258 }
259
GetVsyncSamplerEnabled(const OutputPtr &output)260 bool HdiBackend::GetVsyncSamplerEnabled(const OutputPtr &output)
261 {
262 if (output == nullptr) {
263 HLOGE("output is nullptr.");
264 return false;
265 }
266 return output->GetVsyncSamplerEnabled();
267 }
268
ResetDevice()269 void HdiBackend::ResetDevice()
270 {
271 if (device_) {
272 device_->Destroy();
273 device_ = nullptr;
274 }
275 for (auto [id, output] : outputs_) {
276 output->ResetDevice();
277 }
278 outputs_.clear();
279 }
280
OnPrepareComplete(bool needFlush, const OutputPtr &output, std::vector<LayerInfoPtr> &newLayerInfos)281 void HdiBackend::OnPrepareComplete(bool needFlush, const OutputPtr &output, std::vector<LayerInfoPtr> &newLayerInfos)
282 {
283 if (needFlush) {
284 ReorderLayerInfo(newLayerInfos);
285 }
286
287 struct PrepareCompleteParam param = {
288 .needFlushFramebuffer = needFlush,
289 .layers = newLayerInfos,
290 .screenId = output->GetScreenId(),
291 };
292
293 auto fbSurface = output->GetFrameBufferSurface();
294 if (onPrepareCompleteCb_ != nullptr) {
295 onPrepareCompleteCb_(fbSurface, param, onPrepareCompleteCbData_);
296 }
297 }
298
Cmp(const LayerInfoPtr &layer1, const LayerInfoPtr &layer2)299 static inline bool Cmp(const LayerInfoPtr &layer1, const LayerInfoPtr &layer2)
300 {
301 if (layer1 == nullptr || layer2 == nullptr) {
302 return false;
303 }
304 return layer1->GetZorder() < layer2->GetZorder();
305 }
306
ReorderLayerInfo(std::vector<LayerInfoPtr> &newLayerInfos)307 void HdiBackend::ReorderLayerInfo(std::vector<LayerInfoPtr> &newLayerInfos)
308 {
309 std::sort(newLayerInfos.begin(), newLayerInfos.end(), Cmp);
310 }
311
OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data)312 void HdiBackend::OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data)
313 {
314 HLOGI("HotPlugEvent, screenId is %{public}u, connected is %{public}u", screenId, connected);
315 HdiBackend *hdiBackend = nullptr;
316 if (data != nullptr) {
317 hdiBackend = static_cast<HdiBackend *>(data);
318 } else {
319 hdiBackend = HdiBackend::GetInstance();
320 }
321
322 hdiBackend->OnHdiBackendConnected(screenId, connected);
323 }
324
OnHdiBackendConnected(uint32_t screenId, bool connected)325 void HdiBackend::OnHdiBackendConnected(uint32_t screenId, bool connected)
326 {
327 if (connected) {
328 CreateHdiOutput(screenId);
329 }
330
331 OnScreenHotplug(screenId, connected);
332 }
333
CreateHdiOutput(uint32_t screenId)334 void HdiBackend::CreateHdiOutput(uint32_t screenId)
335 {
336 OutputPtr newOutput = HdiOutput::CreateHdiOutput(screenId);
337 newOutput->Init();
338 outputs_.emplace(screenId, newOutput);
339 }
340
OnScreenHotplug(uint32_t screenId, bool connected)341 void HdiBackend::OnScreenHotplug(uint32_t screenId, bool connected)
342 {
343 auto iter = outputs_.find(screenId);
344 if (iter == outputs_.end()) {
345 HLOGE("invalid hotplug screen id[%{public}u]", screenId);
346 return;
347 }
348
349 if (onScreenHotplugCb_ != nullptr) {
350 onScreenHotplugCb_(iter->second, connected, onHotPlugCbData_);
351 }
352
353 if (!connected) {
354 outputs_.erase(iter);
355 }
356 }
357
InitDevice()358 RosenError HdiBackend::InitDevice()
359 {
360 if (device_ != nullptr) {
361 return ROSEN_ERROR_OK;
362 }
363
364 device_ = HdiDevice::GetInstance();
365 if (device_ == nullptr) {
366 HLOGE("Get HdiDevice failed");
367 return ROSEN_ERROR_NOT_INIT;
368 }
369
370 HLOGI("Init device succeed");
371 return ROSEN_ERROR_OK;
372 }
373
SetHdiBackendDevice(HdiDevice* device)374 RosenError HdiBackend::SetHdiBackendDevice(HdiDevice* device)
375 {
376 if (device == nullptr) {
377 HLOGE("Input HdiDevice is null");
378 return ROSEN_ERROR_INVALID_ARGUMENTS;
379 }
380
381 if (device_ != nullptr) {
382 HLOGW("HdiDevice has been changed");
383 return ROSEN_ERROR_OK;
384 }
385 device_ = device;
386 return ROSEN_ERROR_OK;
387 }
388
389 } // namespace Rosen
390 } // namespace OHOS
391