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