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