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_drm_composition.h"
17 #include <cerrno>
18 #include "hdi_drm_layer.h"
19
20 namespace OHOS {
21 namespace HDI {
22 namespace DISPLAY {
HdiDrmComposition(std::shared_ptr<DrmConnector> & connector,const std::shared_ptr<DrmCrtc> & crtc,std::shared_ptr<DrmDevice> & drmDevice)23 HdiDrmComposition::HdiDrmComposition(std::shared_ptr<DrmConnector> &connector, const std::shared_ptr<DrmCrtc> &crtc,
24 std::shared_ptr<DrmDevice> &drmDevice)
25 : mDrmDevice(drmDevice), mConnector(connector), mCrtc(crtc)
26 {
27 DISPLAY_LOGD();
28 }
29
Init()30 int32_t HdiDrmComposition::Init()
31 {
32 DISPLAY_LOGD();
33 mPrimPlanes.clear();
34 mOverlayPlanes.clear();
35 mPlanes.clear();
36 DISPLAY_CHK_RETURN((mCrtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null"));
37 DISPLAY_CHK_RETURN((mConnector == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("connector is null"));
38 DISPLAY_CHK_RETURN((mDrmDevice == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("drmDevice is null"));
39 mPrimPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_PRIMARY);
40 mOverlayPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_OVERLAY);
41 DISPLAY_CHK_RETURN((mPrimPlanes.size() == 0), DISPLAY_FAILURE, DISPLAY_LOGE("has no primary plane"));
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
ApplyPlane(HdiDrmLayer & layer,const DrmPlane & drmPlane,drmModeAtomicReqPtr pset)56 int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer, const DrmPlane &drmPlane, drmModeAtomicReqPtr pset)
57 {
58 // set fence in
59 int ret;
60 int fenceFd = layer.GetAcquireFenceFd();
61 int propId = drmPlane.GetPropFenceInId();
62 DISPLAY_LOGD();
63 if (propId != 0) {
64 DISPLAY_LOGD("set the fence in prop");
65 if (fenceFd >= 0) {
66 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd);
67 DISPLAY_LOGD("set the IfenceProp plane id %{public}d, propId %{public}d, fenceFd %{public}d",
68 drmPlane.GetId(), propId, fenceFd);
69 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set IN_FENCE_FD failed"));
70 }
71 }
72
73 // set fb id
74 DrmGemBuffer *gemBuffer = layer.GetGemBuffer();
75 DISPLAY_CHK_RETURN((gemBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("current gemBuffer is nullptr"));
76 DISPLAY_CHK_RETURN((!gemBuffer->IsValid()), DISPLAY_FAILURE, DISPLAY_LOGE("the DrmGemBuffer is invalid"));
77 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId());
78 DISPLAY_LOGD("set the fb planeid %{public}d, propId %{public}d, fbId %{public}d", drmPlane.GetId(),
79 drmPlane.GetPropFbId(), gemBuffer->GetFbId());
80 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set fb id fialed errno : %{public}d", errno));
81
82 // set crtc id
83 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId());
84 DISPLAY_LOGD("set the crtc planeId %{public}d, propId %{public}d, crtcId %{public}d", drmPlane.GetId(),
85 drmPlane.GetPropCrtcId(), mCrtc->GetId());
86 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set crtc id fialed errno : %{public}d", errno));
87 return DISPLAY_SUCCESS;
88 }
89
UpdateMode(std::unique_ptr<DrmModeBlock> & modeBlock,drmModeAtomicReq & pset)90 int32_t HdiDrmComposition::UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock, drmModeAtomicReq &pset)
91 {
92 // set the mode
93 DISPLAY_LOGD();
94 if (mCrtc->NeedModeSet()) {
95 modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId());
96 if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) {
97 // set to active
98 DISPLAY_LOGD("set crtc to active");
99 int ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1);
100 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
101 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno));
102
103 // set the mode id
104 DISPLAY_LOGD("set the mode");
105 ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
106 DISPLAY_LOGD("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d", mCrtc->GetId(),
107 mCrtc->GetModePropId(), modeBlock->GetBlockId());
108 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
109 DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno));
110 ret = drmModeAtomicAddProperty(&pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
111 DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", mConnector->GetId(),
112 mConnector->GetPropCrtcId(), mCrtc->GetId());
113 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
114 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno));
115 }
116 }
117 return DISPLAY_SUCCESS;
118 }
119
Apply(bool modeSet)120 int32_t HdiDrmComposition::Apply(bool modeSet)
121 {
122 (void)modeSet;
123 uint64_t crtcOutFence = -1;
124 int ret;
125 std::unique_ptr<DrmModeBlock> modeBlock;
126 int drmFd = mDrmDevice->GetDrmFd();
127 DISPLAY_LOGD();
128 DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough"));
129 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
130 DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR,
131 DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno));
132 AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset);
133
134 // set the outFence property
135 ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(),
136 (uint64_t)&crtcOutFence);
137
138 DISPLAY_LOGD("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(),
139 mCrtc->GetOutFencePropId());
140 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed "));
141
142 // set the plane info.
143 DISPLAY_LOGD("mCompLayers size %{public}zd", mCompLayers.size());
144 for (uint32_t i = 0; i < mCompLayers.size(); i++) {
145 HdiDrmLayer *layer = static_cast<HdiDrmLayer *>(mCompLayers[i]);
146 const auto &drmPlane = mPlanes[i];
147 ret = ApplyPlane(*layer, *drmPlane, atomicReqPtr.Get());
148 if (ret != DISPLAY_SUCCESS) {
149 DISPLAY_LOGE("apply plane failed");
150 break;
151 }
152 }
153 ret = UpdateMode(modeBlock, *(atomicReqPtr.Get()));
154 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed"));
155 uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
156
157 ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr);
158 DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE,
159 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno));
160 // set the release fence
161 for (auto layer : mCompLayers) {
162 layer->SetReleaseFence(dup(static_cast<int32_t>(crtcOutFence)));
163 }
164 close(static_cast<int32_t>(crtcOutFence));
165 crtcOutFence = -1;
166 return DISPLAY_SUCCESS;
167 }
168 } // OHOS
169 } // HDI
170 } // DISPLAY
171