• 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 
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