1 /*
2 * Copyright (c) 2021-2022 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_drm_composition.h"
17 #include <cerrno>
18 #include "hdi_drm_layer.h"
19
20 namespace OHOS {
21 namespace HDI {
22 namespace DISPLAY {
HdiDrmComposition(const std::shared_ptr<DrmConnector> & connector,const std::shared_ptr<DrmCrtc> & crtc,const std::shared_ptr<DrmDevice> & drmDevice)23 HdiDrmComposition::HdiDrmComposition(const std::shared_ptr<DrmConnector> &connector,
24 const std::shared_ptr<DrmCrtc> &crtc,
25 const std::shared_ptr<DrmDevice> &drmDevice)
26 : mDrmDevice(drmDevice), mConnector(connector), mCrtc(crtc)
27 {
28 DISPLAY_DEBUGLOG();
29 }
30
Init()31 int32_t HdiDrmComposition::Init()
32 {
33 DISPLAY_DEBUGLOG();
34 mPrimPlanes.clear();
35 mOverlayPlanes.clear();
36 mPlanes.clear();
37 DISPLAY_CHK_RETURN((mCrtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null"));
38 DISPLAY_CHK_RETURN((mConnector == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("connector is null"));
39 DISPLAY_CHK_RETURN((mDrmDevice == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("drmDevice is null"));
40 mPrimPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_PRIMARY);
41 mOverlayPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_OVERLAY);
42 mPlanes.insert(mPlanes.end(), mPrimPlanes.begin(), mPrimPlanes.end());
43 mPlanes.insert(mPlanes.end(), mOverlayPlanes.begin(), mOverlayPlanes.end());
44 return DISPLAY_SUCCESS;
45 }
46
SetLayers(std::vector<HdiLayer * > & layers,HdiLayer & clientLayer)47 int32_t HdiDrmComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
48 {
49 // now we do not surpport present direct
50 DISPLAY_DEBUGLOG();
51 mCompLayers.clear();
52 mCompLayers.push_back(&clientLayer);
53 return DISPLAY_SUCCESS;
54 }
55
SetCrtcProperty(DrmPlane & drmPlane,drmModeAtomicReqPtr pset,int32_t bufferW,int32_t bufferH)56 int32_t HdiDrmComposition::SetCrtcProperty(DrmPlane &drmPlane,
57 drmModeAtomicReqPtr pset,
58 int32_t bufferW,
59 int32_t bufferH)
60 {
61 int ret;
62
63 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_xId(), 0);
64 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_xId %{public}d, crop.x %{public}d", drmPlane.GetId(),
65 drmPlane.GetPropCrtc_xId(), 0);
66 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
67
68 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_yId(), 0);
69 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_yId %{public}d, crop.y %{public}d", drmPlane.GetId(),
70 drmPlane.GetPropCrtc_yId(), 0);
71 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
72
73 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_wId(), bufferW);
74 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_wId %{public}d, crop.w %{public}d", drmPlane.GetId(),
75 drmPlane.GetPropCrtc_wId(), bufferW);
76 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
77
78 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_hId(), bufferH);
79 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_hId %{public}d, crop.h %{public}d", drmPlane.GetId(),
80 drmPlane.GetPropCrtc_xId(), bufferH);
81 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
82
83 return DISPLAY_SUCCESS;
84 }
85
SetSrcProperty(DrmPlane & drmPlane,drmModeAtomicReqPtr pset,int32_t bufferW,int32_t bufferH)86 int32_t HdiDrmComposition::SetSrcProperty(DrmPlane &drmPlane,
87 drmModeAtomicReqPtr pset,
88 int32_t bufferW,
89 int32_t bufferH)
90 {
91 int ret;
92
93 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 0<<16); // 16:shift left 16 bits
94 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_xId %{public}d, displayRect.x %{public}d",
95 drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 0);
96 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
97
98 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 0<<16); // 16:shift left 16 bits
99 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_yId %{public}d, displayRect.y %{public}d",
100 drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 0);
101 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
102
103 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_wId(),
104 bufferW<<16); // 16:shift left 16 bits
105 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_wId %{public}d, displayRect.w %{public}d",
106 drmPlane.GetId(), drmPlane.GetPropSrc_wId(), bufferW);
107 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
108
109 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_hId(),
110 bufferH<<16); // 16:shift left 16 bits
111 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_hId %{public}d, displayRect.h %{public}d",
112 drmPlane.GetId(), drmPlane.GetPropSrc_hId(), bufferH);
113 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno));
114
115 return DISPLAY_SUCCESS;
116 }
117
ApplyPlane(HdiDrmLayer & layer,HdiLayer & hlayer,DrmPlane & drmPlane,drmModeAtomicReqPtr pset)118 int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer,
119 HdiLayer &hlayer,
120 DrmPlane &drmPlane,
121 drmModeAtomicReqPtr pset)
122 {
123 int ret;
124 int fenceFd = layer.GetAcquireFenceFd();
125 int propId = drmPlane.GetPropFenceInId();
126 HdiLayerBuffer *layerBuffer = hlayer.GetCurrentBuffer();
127 int32_t bufferW = layerBuffer->GetWight();
128 int32_t bufferH = layerBuffer->GetHeight();
129
130 DISPLAY_DEBUGLOG();
131 if (propId != 0) {
132 DISPLAY_DEBUGLOG("set the fence in prop");
133 if (fenceFd >= 0) {
134 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd);
135 DISPLAY_DEBUGLOG("set the IfenceProp plane id %{public}d, propId %{public}d, fenceFd %{public}d",
136 drmPlane.GetId(), propId, fenceFd);
137 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set IN_FENCE_FD failed"));
138 }
139 }
140
141 ret = SetCrtcProperty(drmPlane, pset, bufferW, bufferH);
142 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set Crtc fialed errno : %{public}d", errno));
143
144 ret = SetSrcProperty(drmPlane, pset, bufferW, bufferH);
145 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set Src fialed errno : %{public}d", errno));
146
147 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder());
148 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropZposId %{public}d, zpos %{public}d",
149 drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder());
150 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the zpos fialed errno : %{public}d", errno));
151
152 // set fb id
153 DrmGemBuffer *gemBuffer = layer.GetGemBuffer();
154 DISPLAY_CHK_RETURN((gemBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("current gemBuffer is nullptr"));
155 DISPLAY_CHK_RETURN((!gemBuffer->IsValid()), DISPLAY_FAILURE, DISPLAY_LOGE("the DrmGemBuffer is invalid"));
156 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId());
157 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, propId %{public}d, fbId %{public}d",
158 drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId());
159 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set fb id fialed errno : %{public}d", errno));
160
161 // set crtc id
162 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId());
163 DISPLAY_DEBUGLOG("set the crtc planeId %{public}d, propId %{public}d, crtcId %{public}d",
164 drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId());
165 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set crtc id fialed errno : %{public}d", errno));
166 return DISPLAY_SUCCESS;
167 }
168
UpdateMode(std::unique_ptr<DrmModeBlock> & modeBlock,drmModeAtomicReq & pset)169 int32_t HdiDrmComposition::UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock, drmModeAtomicReq &pset)
170 {
171 // set the mode
172 DISPLAY_DEBUGLOG();
173 if (mCrtc->NeedModeSet()) {
174 modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId());
175 if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) {
176 // set to active
177 DISPLAY_DEBUGLOG("set crtc to active");
178 int ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1);
179 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
180 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno));
181
182 // set the mode id
183 DISPLAY_DEBUGLOG("set the mode");
184 ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
185 DISPLAY_DEBUGLOG("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d",
186 mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
187 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
188 DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno));
189 ret = drmModeAtomicAddProperty(&pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
190 DISPLAY_DEBUGLOG("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d",
191 mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
192 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
193 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno));
194 }
195 }
196 return DISPLAY_SUCCESS;
197 }
198
RemoveUnusePlane(drmModeAtomicReqPtr pset)199 int32_t HdiDrmComposition::RemoveUnusePlane(drmModeAtomicReqPtr pset)
200 {
201 int ret = 0;
202 /* Remove useless planes from the drm */
203 for (uint32_t j = 0; j < mPlanes.size(); j++) {
204 auto &drmPlane = mPlanes[j];
205 if ((static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask()) && drmPlane->GetPipe() == 0) {
206 DISPLAY_DEBUGLOG("no used plane %{public}s id %{public}d", drmPlane->GetName().c_str(), drmPlane->GetId());
207 ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0);
208 ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0);
209 drmPlane->UnBindPipe();
210 }
211 }
212 return DISPLAY_SUCCESS;
213 }
214
FindPlaneAndApply(drmModeAtomicReqPtr pset)215 int32_t HdiDrmComposition::FindPlaneAndApply(drmModeAtomicReqPtr pset)
216 {
217 int32_t ret = 0;
218 for (uint32_t i = 0; i < mCompLayers.size(); i++) {
219 HdiDrmLayer *layer = static_cast<HdiDrmLayer *>(mCompLayers[i]);
220 HdiLayer *hlayer = mCompLayers[i];
221 for (uint32_t j = 0; j < mPlanes.size(); j++) {
222 auto &drmPlane = mPlanes[j];
223 if (drmPlane->GetPipe() != 0 && drmPlane->GetPipe() != (1 << mCrtc->GetPipe())) {
224 DISPLAY_DEBUGLOG("plane %{public}d used pipe %{public}d crtc pipe %{public}d", drmPlane->GetId(),
225 drmPlane->GetPipe(), mCrtc->GetPipe());
226 continue;
227 }
228 /* Check whether the plane belond to the crtc */
229 if (!(static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask())) {
230 continue;
231 }
232 DISPLAY_DEBUGLOG("use plane %{public}d WinType %{public}x crtc %{public}d PlaneMask %{public}x",
233 drmPlane->GetId(), drmPlane->GetWinType(), mCrtc->GetId(), mCrtc->GetPlaneMask());
234
235 if (drmPlane->GetCrtcId() == mCrtc->GetId() || drmPlane->GetCrtcId() == 0) {
236 ret = ApplyPlane(*layer, *hlayer, *drmPlane, pset);
237 if (ret != DISPLAY_SUCCESS) {
238 DISPLAY_LOGE("apply plane failed");
239 break;
240 }
241 /* mark the plane is used by crtc */
242 drmPlane->BindToPipe(1 << mCrtc->GetPipe());
243 break;
244 }
245 }
246 }
247 return DISPLAY_SUCCESS;
248 }
249
Apply(bool modeSet)250 int32_t HdiDrmComposition::Apply(bool modeSet)
251 {
252 uint64_t crtcOutFence = -1;
253 int ret = 0;
254 std::unique_ptr<DrmModeBlock> modeBlock;
255 int drmFd = mDrmDevice->GetDrmFd();
256
257 DISPLAY_DEBUGLOG("mPlane size: %{public}zd mCompLayers size: %{public}zd", mPlanes.size(), mCompLayers.size());
258 DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough"));
259 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
260 DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR,
261 DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno));
262 AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset);
263
264 // set the outFence property
265 ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(),
266 (uint64_t)&crtcOutFence);
267
268 DISPLAY_DEBUGLOG("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(),
269 mCrtc->GetOutFencePropId());
270 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed "));
271
272 // set the plane info.
273 DISPLAY_DEBUGLOG("mCompLayers size %{public}zd", mCompLayers.size());
274 DISPLAY_DEBUGLOG("crtc id %{public}d connect id %{public}d encoder id %{public}d", mCrtc->GetId(),
275 mConnector->GetId(), mConnector->GetEncoderId());
276
277 /* Bind the plane not used by other crtcs to the crtc. */
278 FindPlaneAndApply(atomicReqPtr.Get());
279 /* Remove useless planes from the drm */
280 RemoveUnusePlane(atomicReqPtr.Get());
281
282 ret = UpdateMode(modeBlock, *(atomicReqPtr.Get()));
283 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed"));
284 uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
285
286 ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr);
287 DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE,
288 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno));
289 // set the release fence
290 for (auto layer : mCompLayers) {
291 layer->SetReleaseFence(static_cast<int>(crtcOutFence));
292 }
293
294 return DISPLAY_SUCCESS;
295 }
296 } // OHOS
297 } // HDI
298 } // DISPLAY
299