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
RegPrepareComplete(OnPrepareCompleteFunc func,void * data)82 RosenError HdiBackend::RegPrepareComplete(OnPrepareCompleteFunc func, void* data)
83 {
84 if (func == nullptr) {
85 HLOGE("OnPrepareCompleteFunc is null");
86 return ROSEN_ERROR_INVALID_ARGUMENTS;
87 }
88
89 onPrepareCompleteCb_ = func;
90 onPrepareCompleteCbData_ = data;
91
92 return ROSEN_ERROR_OK;
93 }
94
OnHdiBackendRefreshEvent(uint32_t deviceId,void * data)95 void HdiBackend::OnHdiBackendRefreshEvent(uint32_t deviceId, void *data)
96 {
97 HdiBackend *hdiBackend = nullptr;
98 if (data != nullptr) {
99 hdiBackend = static_cast<HdiBackend *>(data);
100 } else {
101 hdiBackend = HdiBackend::GetInstance();
102 }
103
104 hdiBackend->OnScreenRefresh(deviceId);
105 }
106
OnScreenRefresh(uint32_t deviceId)107 void HdiBackend::OnScreenRefresh(uint32_t deviceId)
108 {
109 if (onScreenRefreshCb_ != nullptr) {
110 onScreenRefreshCb_(deviceId, onRefreshCbData_);
111 }
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 output->SetActiveRectSwitchStatus(false);
198 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
199 HLOGE("PreProcessLayersComp failed, ret is %{public}d", ret);
200 return;
201 }
202
203 sptr<SyncFence> fbFence = SyncFence::InvalidFence();
204 ret = output->CommitAndGetReleaseFence(fbFence, skipState, needFlush, false);
205 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
206 HLOGE("first commit failed, ret is %{public}d, skipState is %{public}d", ret, skipState);
207 }
208
209 if (skipState != GRAPHIC_DISPLAY_SUCCESS) {
210 ret = output->UpdateLayerCompType();
211 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
212 return;
213 }
214 ret = PrepareCompleteIfNeed(output, needFlush);
215 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
216 return;
217 }
218 skipState = INT32_MAX;
219 ret = output->CommitAndGetReleaseFence(fbFence, skipState, needFlush, true);
220 HLOGD("%{public}s: ValidateDisplay", __func__);
221 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
222 HLOGE("second commit failed, ret is %{public}d", ret);
223 }
224 }
225
226 if (IsTagEnabled(HITRACE_TAG_GRAPHIC_AGP)) {
227 static SyncFenceTracker presentFenceThread("Present Fence");
228 presentFenceThread.TrackFence(fbFence);
229 }
230
231 ret = output->UpdateInfosAfterCommit(fbFence);
232 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
233 return;
234 }
235
236 ret = output->ReleaseFramebuffer(fbFence);
237 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
238 return;
239 }
240 HLOGD("%{public}s: end", __func__);
241 }
242
StartSample(const OutputPtr & output)243 void HdiBackend::StartSample(const OutputPtr &output)
244 {
245 if (output == nullptr) {
246 HLOGE("output is nullptr.");
247 return;
248 }
249 output->StartVSyncSampler(true); // force resample
250 }
251
SetVsyncSamplerEnabled(const OutputPtr & output,bool enabled)252 void HdiBackend::SetVsyncSamplerEnabled(const OutputPtr &output, bool enabled)
253 {
254 if (output == nullptr) {
255 HLOGE("output is nullptr.");
256 return;
257 }
258 output->SetVsyncSamplerEnabled(enabled);
259 }
260
GetVsyncSamplerEnabled(const OutputPtr & output)261 bool HdiBackend::GetVsyncSamplerEnabled(const OutputPtr &output)
262 {
263 if (output == nullptr) {
264 HLOGE("output is nullptr.");
265 return false;
266 }
267 return output->GetVsyncSamplerEnabled();
268 }
269
ResetDevice()270 void HdiBackend::ResetDevice()
271 {
272 if (device_) {
273 device_->Destroy();
274 device_ = nullptr;
275 }
276 for (auto [id, output] : outputs_) {
277 output->ResetDevice();
278 }
279 outputs_.clear();
280 }
281
OnPrepareComplete(bool needFlush,const OutputPtr & output,std::vector<LayerInfoPtr> & newLayerInfos)282 void HdiBackend::OnPrepareComplete(bool needFlush, const OutputPtr &output, std::vector<LayerInfoPtr> &newLayerInfos)
283 {
284 if (needFlush) {
285 ReorderLayerInfo(newLayerInfos);
286 }
287
288 struct PrepareCompleteParam param = {
289 .needFlushFramebuffer = needFlush,
290 .layers = newLayerInfos,
291 .screenId = output->GetScreenId(),
292 };
293
294 auto fbSurface = output->GetFrameBufferSurface();
295 if (onPrepareCompleteCb_ != nullptr) {
296 onPrepareCompleteCb_(fbSurface, param, onPrepareCompleteCbData_);
297 }
298 }
299
Cmp(const LayerInfoPtr & layer1,const LayerInfoPtr & layer2)300 static inline bool Cmp(const LayerInfoPtr &layer1, const LayerInfoPtr &layer2)
301 {
302 if (layer1 == nullptr || layer2 == nullptr) {
303 return false;
304 }
305 return layer1->GetZorder() < layer2->GetZorder();
306 }
307
ReorderLayerInfo(std::vector<LayerInfoPtr> & newLayerInfos)308 void HdiBackend::ReorderLayerInfo(std::vector<LayerInfoPtr> &newLayerInfos)
309 {
310 std::sort(newLayerInfos.begin(), newLayerInfos.end(), Cmp);
311 }
312
OnHdiBackendHotPlugEvent(uint32_t screenId,bool connected,void * data)313 void HdiBackend::OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data)
314 {
315 HLOGI("HotPlugEvent, screenId is %{public}u, connected is %{public}u", screenId, connected);
316 HdiBackend *hdiBackend = nullptr;
317 if (data != nullptr) {
318 hdiBackend = static_cast<HdiBackend *>(data);
319 } else {
320 hdiBackend = HdiBackend::GetInstance();
321 }
322
323 hdiBackend->OnHdiBackendConnected(screenId, connected);
324 }
325
OnHdiBackendConnected(uint32_t screenId,bool connected)326 void HdiBackend::OnHdiBackendConnected(uint32_t screenId, bool connected)
327 {
328 if (connected) {
329 CreateHdiOutput(screenId);
330 }
331
332 OnScreenHotplug(screenId, connected);
333 }
334
CreateHdiOutput(uint32_t screenId)335 void HdiBackend::CreateHdiOutput(uint32_t screenId)
336 {
337 OutputPtr newOutput = HdiOutput::CreateHdiOutput(screenId);
338 newOutput->Init();
339 outputs_.emplace(screenId, newOutput);
340 }
341
OnScreenHotplug(uint32_t screenId,bool connected)342 void HdiBackend::OnScreenHotplug(uint32_t screenId, bool connected)
343 {
344 auto iter = outputs_.find(screenId);
345 if (iter == outputs_.end()) {
346 HLOGE("invalid hotplug screen id[%{public}u]", screenId);
347 return;
348 }
349
350 if (onScreenHotplugCb_ != nullptr) {
351 onScreenHotplugCb_(iter->second, connected, onHotPlugCbData_);
352 }
353
354 if (!connected) {
355 outputs_.erase(iter);
356 }
357 }
358
InitDevice()359 RosenError HdiBackend::InitDevice()
360 {
361 if (device_ != nullptr) {
362 return ROSEN_ERROR_OK;
363 }
364
365 device_ = HdiDevice::GetInstance();
366 if (device_ == nullptr) {
367 HLOGE("Get HdiDevice failed");
368 return ROSEN_ERROR_NOT_INIT;
369 }
370
371 HLOGI("Init device succeed");
372 return ROSEN_ERROR_OK;
373 }
374
SetHdiBackendDevice(HdiDevice * device)375 RosenError HdiBackend::SetHdiBackendDevice(HdiDevice* device)
376 {
377 if (device == nullptr) {
378 HLOGE("Input HdiDevice is null");
379 return ROSEN_ERROR_INVALID_ARGUMENTS;
380 }
381
382 if (device_ != nullptr) {
383 HLOGW("HdiDevice has been changed");
384 return ROSEN_ERROR_OK;
385 }
386 device_ = device;
387 return ROSEN_ERROR_OK;
388 }
389
390
RegHwcEventCallback(RSHwcEventCallback func,void * data)391 RosenError HdiBackend::RegHwcEventCallback(RSHwcEventCallback func, void* data)
392 {
393 if (func == nullptr) {
394 HLOGE("HwcEventCallback is null.");
395 return ROSEN_ERROR_INVALID_ARGUMENTS;
396 }
397
398 RosenError retCode = InitDevice();
399 if (retCode != ROSEN_ERROR_OK) {
400 return retCode;
401 }
402
403 int32_t ret = device_->RegHwcEventCallback(func, data);
404 if (ret != GRAPHIC_DISPLAY_SUCCESS) {
405 HLOGE("RegHwcEventCallback failed, ret is %{public}d", ret);
406 return ROSEN_ERROR_API_FAILED;
407 }
408 return ROSEN_ERROR_OK;
409 }
410 } // namespace Rosen
411 } // namespace OHOS
412