• 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 
RegPrepareComplete(OnPrepareCompleteFunc func,void * data)58 RosenError HdiBackend::RegPrepareComplete(OnPrepareCompleteFunc func, void* data)
59 {
60     if (func == nullptr) {
61         HLOGE("OnPrepareCompleteFunc is null");
62         return ROSEN_ERROR_INVALID_ARGUMENTS;
63     }
64 
65     onPrepareCompleteCb_ = func;
66     onPrepareCompleteCbData_ = data;
67 
68     return ROSEN_ERROR_OK;
69 }
70 
RegHwcDeadListener(OnHwcDeadCallback func,void * data)71 RosenError HdiBackend::RegHwcDeadListener(OnHwcDeadCallback func, void* data)
72 {
73     if (func == nullptr) {
74         HLOGE("onHwcDeadCallbackFunc is null.");
75         return ROSEN_ERROR_INVALID_ARGUMENTS;
76     }
77 
78     RosenError retCode = InitDevice();
79     if (retCode != ROSEN_ERROR_OK) {
80         return retCode;
81     }
82 
83     int32_t ret = device_->RegHwcDeadCallback(func, data);
84     if (!ret) {
85         HLOGE("RegHwcDeadCallback failed, ret is %{public}d", ret);
86         return ROSEN_ERROR_API_FAILED;
87     }
88 
89     return ROSEN_ERROR_OK;
90 }
91 
SetPendingMode(const OutputPtr & output,int64_t period,int64_t timestamp)92 void HdiBackend::SetPendingMode(const OutputPtr &output, int64_t period, int64_t timestamp)
93 {
94     if (output == nullptr) {
95         HLOGE("output is nullptr.");
96         return;
97     }
98     output->SetPendingMode(period, timestamp);
99 }
100 
PrepareCompleteIfNeed(const OutputPtr & output,bool needFlush)101 int32_t HdiBackend::PrepareCompleteIfNeed(const OutputPtr &output, bool needFlush)
102 {
103     std::vector<LayerPtr> compClientLayers;
104     std::vector<LayerInfoPtr> newLayerInfos;
105     const std::unordered_map<uint32_t, LayerPtr> &layersMap = output->GetLayers();
106     for (auto iter = layersMap.begin(); iter != layersMap.end(); ++iter) {
107         const LayerPtr &layer = iter->second;
108         if (layer == nullptr) {
109             continue;
110         }
111         newLayerInfos.emplace_back(layer->GetLayerInfo());
112         if (layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT ||
113             layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT_CLEAR ||
114             layer->GetLayerInfo()->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_TUNNEL) {
115             compClientLayers.emplace_back(layer);
116         }
117     }
118 
119     if (compClientLayers.size() > 0) {
120         needFlush = true;
121         HLOGD("Need flush framebuffer, client composition layer num is %{public}zu", compClientLayers.size());
122     }
123 
124     OnPrepareComplete(needFlush, output, newLayerInfos);
125     if (needFlush) {
126         return output->FlushScreen(compClientLayers);
127     }
128     return GRAPHIC_DISPLAY_SUCCESS;
129 }
130 
Repaint(const OutputPtr & output)131 void HdiBackend::Repaint(const OutputPtr &output)
132 {
133     ScopedBytrace bytrace(__func__);
134     HLOGD("%{public}s: start", __func__);
135 
136     if (output == nullptr) {
137         HLOGE("output is nullptr.");
138         return;
139     }
140 
141     bool needFlush = false;
142     int32_t ret = output->PreProcessLayersComp(needFlush);
143     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
144         return;
145     }
146 
147     ret = PrepareCompleteIfNeed(output, needFlush);
148     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
149         return;
150     }
151     sptr<SyncFence> fbFence = SyncFence::INVALID_FENCE;
152     ret = output->Commit(fbFence);
153     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
154         HLOGE("commit failed, ret is %{public}d", ret);
155         // return
156     }
157 
158     if (IsTagEnabled(HITRACE_TAG_GRAPHIC_AGP)) {
159         static SyncFenceTracker presentFenceThread("Present Fence");
160         presentFenceThread.TrackFence(fbFence);
161     }
162 
163     ret = output->UpdateInfosAfterCommit(fbFence);
164     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
165         return;
166     }
167 
168     ret = output->ReleaseFramebuffer(fbFence);
169     if (ret != GRAPHIC_DISPLAY_SUCCESS) {
170         return;
171     }
172     HLOGD("%{public}s: end", __func__);
173 }
174 
StartSample(const OutputPtr & output)175 void HdiBackend::StartSample(const OutputPtr &output)
176 {
177     if (output == nullptr) {
178         HLOGE("output is nullptr.");
179         return;
180     }
181     output->StartVSyncSampler(true); // force resample
182 }
183 
ResetDevice()184 void HdiBackend::ResetDevice()
185 {
186     if (device_) {
187         device_->Destroy();
188         device_ = nullptr;
189     }
190     for (auto [id, output] : outputs_) {
191         output->ResetDevice();
192     }
193     outputs_.clear();
194 }
195 
OnPrepareComplete(bool needFlush,const OutputPtr & output,std::vector<LayerInfoPtr> & newLayerInfos)196 void HdiBackend::OnPrepareComplete(bool needFlush, const OutputPtr &output, std::vector<LayerInfoPtr> &newLayerInfos)
197 {
198     if (needFlush) {
199         ReorderLayerInfo(newLayerInfos);
200     }
201 
202     struct PrepareCompleteParam param = {
203         .needFlushFramebuffer = needFlush,
204         .layers = newLayerInfos,
205         .screenId = output->GetScreenId(),
206     };
207 
208     auto fbSurface = output->GetFrameBufferSurface();
209     if (onPrepareCompleteCb_ != nullptr) {
210         onPrepareCompleteCb_(fbSurface, param, onPrepareCompleteCbData_);
211     }
212 }
213 
Cmp(const LayerInfoPtr & layer1,const LayerInfoPtr & layer2)214 static inline bool Cmp(const LayerInfoPtr &layer1, const LayerInfoPtr &layer2)
215 {
216     return layer1->GetZorder() < layer2->GetZorder();
217 }
218 
ReorderLayerInfo(std::vector<LayerInfoPtr> & newLayerInfos)219 void HdiBackend::ReorderLayerInfo(std::vector<LayerInfoPtr> &newLayerInfos)
220 {
221     std::sort(newLayerInfos.begin(), newLayerInfos.end(), Cmp);
222 }
223 
OnHdiBackendHotPlugEvent(uint32_t screenId,bool connected,void * data)224 void HdiBackend::OnHdiBackendHotPlugEvent(uint32_t screenId, bool connected, void *data)
225 {
226     HLOGI("HotPlugEvent, screenId is %{public}u, connected is %{public}u", screenId, connected);
227     HdiBackend *hdiBackend = nullptr;
228     if (data != nullptr) {
229         hdiBackend = static_cast<HdiBackend *>(data);
230     } else {
231         hdiBackend = HdiBackend::GetInstance();
232     }
233 
234     hdiBackend->OnHdiBackendConnected(screenId, connected);
235 }
236 
OnHdiBackendConnected(uint32_t screenId,bool connected)237 void HdiBackend::OnHdiBackendConnected(uint32_t screenId, bool connected)
238 {
239     if (connected) {
240         CreateHdiOutput(screenId);
241     }
242 
243     OnScreenHotplug(screenId, connected);
244 }
245 
CreateHdiOutput(uint32_t screenId)246 void HdiBackend::CreateHdiOutput(uint32_t screenId)
247 {
248     OutputPtr newOutput = HdiOutput::CreateHdiOutput(screenId);
249     newOutput->Init();
250     outputs_.emplace(screenId, newOutput);
251 }
252 
OnScreenHotplug(uint32_t screenId,bool connected)253 void HdiBackend::OnScreenHotplug(uint32_t screenId, bool connected)
254 {
255     auto iter = outputs_.find(screenId);
256     if (iter == outputs_.end()) {
257         HLOGE("invalid hotplug screen id[%{public}u]", screenId);
258         return;
259     }
260 
261     if (onScreenHotplugCb_ != nullptr) {
262         onScreenHotplugCb_(iter->second, connected, onHotPlugCbData_);
263     }
264 
265     if (!connected) {
266         outputs_.erase(iter);
267     }
268 }
269 
InitDevice()270 RosenError HdiBackend::InitDevice()
271 {
272     if (device_ != nullptr) {
273         return ROSEN_ERROR_OK;
274     }
275 
276     device_ = HdiDevice::GetInstance();
277     if (device_ == nullptr) {
278         HLOGE("Get HdiDevice failed");
279         return ROSEN_ERROR_NOT_INIT;
280     }
281 
282     HLOGI("Init device succeed");
283     return ROSEN_ERROR_OK;
284 }
285 
SetHdiBackendDevice(HdiDevice * device)286 RosenError HdiBackend::SetHdiBackendDevice(HdiDevice* device)
287 {
288     if (device == nullptr) {
289         HLOGE("Input HdiDevice is null");
290         return ROSEN_ERROR_INVALID_ARGUMENTS;
291     }
292 
293     if (device_ != nullptr) {
294         HLOGW("HdiDevice has been changed");
295         return ROSEN_ERROR_OK;
296     }
297     device_ = device;
298     return ROSEN_ERROR_OK;
299 }
300 
301 } // namespace Rosen
302 } // namespace OHOS
303