• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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