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