• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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_LOGD();
29 }
30 
Init()31 int32_t HdiDrmComposition::Init()
32 {
33     DISPLAY_LOGD();
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_LOGD();
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_LOGD("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_LOGD("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_LOGD("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_LOGD("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_LOGD("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_LOGD("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_LOGD("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_LOGD("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_LOGD();
131     if (propId != 0) {
132         DISPLAY_LOGD("set the fence in prop");
133         if (fenceFd >= 0) {
134             ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd);
135             DISPLAY_LOGD("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_LOGD("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_LOGD("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_LOGD("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)169 int32_t HdiDrmComposition::UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock)
170 {
171     // set the mode
172     DISPLAY_LOGD();
173     if (mCrtc->NeedModeSet()) {
174         int drmFd = mDrmDevice->GetDrmFd();
175         drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
176         modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId());
177         if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) {
178             // set to active
179             DISPLAY_LOGD("set crtc to active");
180             int ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1);
181             DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
182                 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno));
183 
184             // set the mode id
185             DISPLAY_LOGD("set the mode");
186             ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
187             DISPLAY_LOGD("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d",
188                 mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
189             DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
190                 DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno));
191             ret = drmModeAtomicAddProperty(pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
192             DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d",
193                 mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
194             DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
195                 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno));
196 
197             uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
198             ret = drmModeAtomicCommit(drmFd, pset, flags, nullptr);
199             DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE,
200                 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno));
201             mCrtc->ClearModeSet();
202         }
203     }
204     return DISPLAY_SUCCESS;
205 }
206 
RemoveUnusePlane(drmModeAtomicReqPtr pset)207 int32_t HdiDrmComposition::RemoveUnusePlane(drmModeAtomicReqPtr pset)
208 {
209     int ret = 0;
210     /* Remove useless planes from the drm */
211     for (uint32_t j = 0; j < mPlanes.size(); j++) {
212         auto &drmPlane = mPlanes[j];
213         if ((static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask()) &&  drmPlane->GetPipe() == 0) {
214             DISPLAY_LOGD("no used plane %{public}s id %{public}d", drmPlane->GetName().c_str(), drmPlane->GetId());
215             ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0);
216             ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0);
217             drmPlane->UnBindPipe();
218         }
219     }
220     return DISPLAY_SUCCESS;
221 }
222 
FindPlaneAndApply(drmModeAtomicReqPtr pset)223 int32_t HdiDrmComposition::FindPlaneAndApply(drmModeAtomicReqPtr pset)
224 {
225     int32_t ret = 0;
226     for (uint32_t i = 0; i < mCompLayers.size(); i++) {
227         HdiDrmLayer *layer = static_cast<HdiDrmLayer *>(mCompLayers[i]);
228         HdiLayer *hlayer = mCompLayers[i];
229         for (uint32_t j = 0; j < mPlanes.size(); j++) {
230             auto &drmPlane = mPlanes[j];
231             if (drmPlane->GetPipe() != 0 && drmPlane->GetPipe() != (1 << mCrtc->GetPipe())) {
232                 DISPLAY_LOGD("plane %{public}d used pipe %{public}d crtc pipe %{public}d", drmPlane->GetId(),
233                     drmPlane->GetPipe(), mCrtc->GetPipe());
234                 continue;
235             }
236             /* Check whether the plane belond to the crtc */
237             if (!(static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask())) {
238                 continue;
239             }
240             DISPLAY_LOGD("use plane %{public}d WinType %{public}x crtc %{public}d PlaneMask %{public}x",
241                 drmPlane->GetId(), drmPlane->GetWinType(), mCrtc->GetId(), mCrtc->GetPlaneMask());
242 
243             if (drmPlane->GetCrtcId() == mCrtc->GetId() || drmPlane->GetCrtcId() == 0) {
244                 ret = ApplyPlane(*layer, *hlayer, *drmPlane, pset);
245                 if (ret != DISPLAY_SUCCESS) {
246                     DISPLAY_LOGE("apply plane failed");
247                     break;
248                 }
249                 /* mark the plane is used by crtc */
250                 drmPlane->BindToPipe(1 << mCrtc->GetPipe());
251                 break;
252             }
253         }
254     }
255     return DISPLAY_SUCCESS;
256 }
257 
Apply(bool modeSet)258 int32_t HdiDrmComposition::Apply(bool modeSet)
259 {
260     uint64_t crtcOutFence = -1;
261     int ret = 0;
262     std::unique_ptr<DrmModeBlock> modeBlock;
263     int drmFd = mDrmDevice->GetDrmFd();
264 
265     ret = UpdateMode(modeBlock);
266     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed"));
267 
268     DISPLAY_LOGD("mPlane size: %{public}zd mCompLayers size: %{public}zd", mPlanes.size(), mCompLayers.size());
269     DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough"));
270     drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
271     DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR,
272         DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno));
273     AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset);
274 
275     // set the outFence property
276     ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(),
277         (uint64_t)&crtcOutFence);
278 
279     DISPLAY_LOGD("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(),
280         mCrtc->GetOutFencePropId());
281     DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed "));
282 
283     // set the plane info.
284     DISPLAY_LOGD("mCompLayers size %{public}zd", mCompLayers.size());
285     DISPLAY_LOGD("crtc id %{public}d connect id %{public}d encoder id %{public}d", mCrtc->GetId(),
286         mConnector->GetId(), mConnector->GetEncoderId());
287 
288     /*  Bind the plane not used by other crtcs to the crtc. */
289     FindPlaneAndApply(atomicReqPtr.Get());
290     /* Remove useless planes from the drm */
291     RemoveUnusePlane(atomicReqPtr.Get());
292 
293     ret = drmModeAtomicAddProperty(pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
294     DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", mConnector->GetId(),
295         mConnector->GetPropCrtcId(), mCrtc->GetId());
296     DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
297         DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno));
298 
299     // set to active
300     DISPLAY_LOGD("set crtc to active");
301     ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1);
302     DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
303         DISPLAY_LOGE("can not add the active prop errno %{public}d", errno));
304 
305     uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
306 
307     ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr);
308     DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE,
309         DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno));
310     // set the release fence
311     for (auto layer : mCompLayers) {
312         layer->SetReleaseFence(static_cast<int>(crtcOutFence));
313     }
314 
315     return DISPLAY_SUCCESS;
316 }
317 } // OHOS
318 } // HDI
319 } // DISPLAY
320