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