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, drmModeAtomicReqPtr pset, int32_t bufferW, 57 int32_t bufferH) 58 { 59 int ret; 60 61 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_xId(), 0); 62 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_xId %{public}d, crop.x %{public}d", 63 drmPlane.GetId(), drmPlane.GetPropCrtc_xId(), 0); 64 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 65 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 66 67 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_yId(), 0); 68 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_yId %{public}d, crop.y %{public}d", 69 drmPlane.GetId(), drmPlane.GetPropCrtc_yId(), 0); 70 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 71 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", 75 drmPlane.GetId(), drmPlane.GetPropCrtc_wId(), bufferW); 76 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 77 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 78 79 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_hId(), bufferH); 80 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_hId %{public}d, crop.h %{public}d", 81 drmPlane.GetId(), drmPlane.GetPropCrtc_xId(), bufferH); 82 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 83 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 84 85 return DISPLAY_SUCCESS; 86 } 87 SetSrcProperty(DrmPlane &drmPlane, drmModeAtomicReqPtr pset, int32_t bufferW, int32_t bufferH)88 int32_t HdiDrmComposition::SetSrcProperty(DrmPlane &drmPlane, drmModeAtomicReqPtr pset, int32_t bufferW, 89 int32_t bufferH) 90 { 91 int ret; 92 93 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 94 0 << 16); // 16:shift left 16 bits 95 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_xId %{public}d, displayRect.x %{public}d", 96 drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 0); 97 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 98 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 99 100 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 101 0 << 16); // 16:shift left 16 bits 102 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_yId %{public}d, displayRect.y %{public}d", 103 drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 0); 104 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 105 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 106 107 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_wId(), 108 bufferW << 16); // 16:shift left 16 bits 109 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropCrtc_wId %{public}d, displayRect.w %{public}d", 110 drmPlane.GetId(), drmPlane.GetPropSrc_wId(), bufferW); 111 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 112 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 113 114 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_hId(), 115 bufferH << 16); // 16:shift left 16 bits 116 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropSrc_hId %{public}d, displayRect.h %{public}d", 117 drmPlane.GetId(), drmPlane.GetPropSrc_hId(), bufferH); 118 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 119 DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); 120 121 return DISPLAY_SUCCESS; 122 } 123 ApplyPlane(HdiDrmLayer &layer, HdiLayer &hlayer, DrmPlane &drmPlane, drmModeAtomicReqPtr pset)124 int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer, HdiLayer &hlayer, DrmPlane &drmPlane, 125 drmModeAtomicReqPtr pset) 126 { 127 int ret; 128 int fenceFd = layer.GetAcquireFenceFd(); 129 int propId = drmPlane.GetPropFenceInId(); 130 HdiLayerBuffer *layerBuffer = hlayer.GetCurrentBuffer(); 131 int32_t bufferW = layerBuffer->GetWight(); 132 int32_t bufferH = layerBuffer->GetHeight(); 133 134 DISPLAY_DEBUGLOG(); 135 if (propId != 0) { 136 DISPLAY_DEBUGLOG("set the fence in prop"); 137 if (fenceFd >= 0) { 138 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd); 139 DISPLAY_DEBUGLOG( 140 "set the IfenceProp plane id %{public}d, propId %{public}d, fenceFd %{public}d", 141 drmPlane.GetId(), propId, fenceFd); 142 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set IN_FENCE_FD failed")); 143 } 144 } 145 146 ret = SetCrtcProperty(drmPlane, pset, bufferW, bufferH); 147 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 148 DISPLAY_LOGE("set Crtc fialed errno : %{public}d", errno)); 149 150 ret = SetSrcProperty(drmPlane, pset, bufferW, bufferH); 151 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 152 DISPLAY_LOGE("set Src fialed errno : %{public}d", errno)); 153 154 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder()); 155 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, GetPropZposId %{public}d, zpos %{public}d", 156 drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder()); 157 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 158 DISPLAY_LOGE("set the zpos fialed errno : %{public}d", errno)); 159 160 // set fb id 161 DrmGemBuffer *gemBuffer = layer.GetGemBuffer(); 162 DISPLAY_CHK_RETURN((gemBuffer == nullptr), DISPLAY_FAILURE, 163 DISPLAY_LOGE("current gemBuffer is nullptr")); 164 DISPLAY_CHK_RETURN((!gemBuffer->IsValid()), DISPLAY_FAILURE, 165 DISPLAY_LOGE("the DrmGemBuffer is invalid")); 166 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId()); 167 DISPLAY_DEBUGLOG("set the fb planeid %{public}d, propId %{public}d, fbId %{public}d", drmPlane.GetId(), 168 drmPlane.GetPropFbId(), gemBuffer->GetFbId()); 169 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 170 DISPLAY_LOGE("set fb id fialed errno : %{public}d", errno)); 171 172 // set crtc id 173 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId()); 174 DISPLAY_DEBUGLOG("set the crtc planeId %{public}d, propId %{public}d, crtcId %{public}d", 175 drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId()); 176 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 177 DISPLAY_LOGE("set crtc id fialed errno : %{public}d", errno)); 178 return DISPLAY_SUCCESS; 179 } 180 UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock)181 int32_t HdiDrmComposition::UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock) 182 { 183 // set the mode 184 DISPLAY_DEBUGLOG(); 185 if (mCrtc->NeedModeSet()) { 186 int drmFd = mDrmDevice->GetDrmFd(); 187 drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); 188 modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId()); 189 if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) { 190 // set to active 191 DISPLAY_DEBUGLOG("set crtc to active"); 192 int ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1); 193 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 194 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno)); 195 196 // set the mode id 197 DISPLAY_DEBUGLOG("set the mode"); 198 ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetModePropId(), 199 modeBlock->GetBlockId()); 200 DISPLAY_DEBUGLOG("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d", 201 mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId()); 202 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 203 DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno)); 204 ret = drmModeAtomicAddProperty(pset, mConnector->GetId(), mConnector->GetPropCrtcId(), 205 mCrtc->GetId()); 206 DISPLAY_DEBUGLOG("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", 207 mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); 208 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 209 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); 210 211 uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; 212 ret = drmModeAtomicCommit(drmFd, pset, flags, nullptr); 213 DISPLAY_CHK_RETURN( 214 (ret != 0), DISPLAY_FAILURE, 215 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno)); 216 mCrtc->ClearModeSet(); 217 } 218 } 219 return DISPLAY_SUCCESS; 220 } 221 RemoveUnusePlane(drmModeAtomicReqPtr pset)222 int32_t HdiDrmComposition::RemoveUnusePlane(drmModeAtomicReqPtr pset) 223 { 224 int ret = 0; 225 /* Remove useless planes from the drm */ 226 for (uint32_t j = 0; j < mPlanes.size(); j++) { 227 auto &drmPlane = mPlanes[j]; 228 if ((static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask()) && 229 drmPlane->GetPipe() == 0) { 230 DISPLAY_DEBUGLOG("no used plane %{public}s id %{public}d", drmPlane->GetName().c_str(), 231 drmPlane->GetId()); 232 ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0); 233 ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0); 234 drmPlane->UnBindPipe(); 235 } 236 } 237 return DISPLAY_SUCCESS; 238 } 239 FindPlaneAndApply(drmModeAtomicReqPtr pset)240 int32_t HdiDrmComposition::FindPlaneAndApply(drmModeAtomicReqPtr pset) 241 { 242 int32_t ret = 0; 243 for (uint32_t i = 0; i < mCompLayers.size(); i++) { 244 HdiDrmLayer *layer = static_cast<HdiDrmLayer *>(mCompLayers[i]); 245 HdiLayer *hlayer = mCompLayers[i]; 246 for (uint32_t j = 0; j < mPlanes.size(); j++) { 247 auto &drmPlane = mPlanes[j]; 248 if (drmPlane->GetPipe() != 0 && drmPlane->GetPipe() != (1 << mCrtc->GetPipe())) { 249 DISPLAY_DEBUGLOG("plane %{public}d used pipe %{public}d crtc pipe %{public}d", 250 drmPlane->GetId(), drmPlane->GetPipe(), mCrtc->GetPipe()); 251 continue; 252 } 253 /* Check whether the plane belond to the crtc */ 254 if (!(static_cast<int>(drmPlane->GetWinType()) & mCrtc->GetPlaneMask())) { 255 continue; 256 } 257 DISPLAY_DEBUGLOG("use plane %{public}d WinType %{public}x crtc %{public}d PlaneMask %{public}x", 258 drmPlane->GetId(), drmPlane->GetWinType(), mCrtc->GetId(), 259 mCrtc->GetPlaneMask()); 260 261 if (drmPlane->GetCrtcId() == mCrtc->GetId() || drmPlane->GetCrtcId() == 0) { 262 ret = ApplyPlane(*layer, *hlayer, *drmPlane, pset); 263 if (ret != DISPLAY_SUCCESS) { 264 DISPLAY_LOGE("apply plane failed"); 265 break; 266 } 267 /* mark the plane is used by crtc */ 268 drmPlane->BindToPipe(1 << mCrtc->GetPipe()); 269 break; 270 } 271 } 272 } 273 return DISPLAY_SUCCESS; 274 } 275 Apply(bool modeSet)276 int32_t HdiDrmComposition::Apply(bool modeSet) 277 { 278 uint64_t crtcOutFence = -1; 279 int ret = 0; 280 std::unique_ptr<DrmModeBlock> modeBlock; 281 int drmFd = mDrmDevice->GetDrmFd(); 282 283 ret = UpdateMode(modeBlock); 284 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed")); 285 286 DISPLAY_DEBUGLOG("mPlane size: %{public}zd mCompLayers size: %{public}zd", mPlanes.size(), 287 mCompLayers.size()); 288 DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, 289 DISPLAY_LOGE("plane not enough")); 290 drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); 291 DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR, 292 DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno)); 293 AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset); 294 295 // set the outFence property 296 ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(), 297 (uint64_t)&crtcOutFence); 298 299 DISPLAY_DEBUGLOG("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(), 300 mCrtc->GetOutFencePropId()); 301 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 302 DISPLAY_LOGE("set the outfence property of crtc failed ")); 303 304 // set the plane info. 305 DISPLAY_DEBUGLOG("mCompLayers size %{public}zd", mCompLayers.size()); 306 DISPLAY_DEBUGLOG("crtc id %{public}d connect id %{public}d encoder id %{public}d", mCrtc->GetId(), 307 mConnector->GetId(), mConnector->GetEncoderId()); 308 309 /* Bind the plane not used by other crtcs to the crtc. */ 310 FindPlaneAndApply(atomicReqPtr.Get()); 311 /* Remove useless planes from the drm */ 312 RemoveUnusePlane(atomicReqPtr.Get()); 313 314 ret = drmModeAtomicAddProperty(pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); 315 DISPLAY_LOGI("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", 316 mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); 317 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 318 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); 319 320 // set to active 321 DISPLAY_DEBUGLOG("set crtc to active"); 322 ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1); 323 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, 324 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno)); 325 326 uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; 327 328 ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr); 329 DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, 330 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno)); 331 // set the release fence 332 for (auto layer : mCompLayers) { 333 layer->SetReleaseFence(static_cast<int>(crtcOutFence)); 334 } 335 336 return DISPLAY_SUCCESS; 337 } 338 } // OHOS 339 } // HDI 340 } // DISPLAY 341