1 /*
2 * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3 * This file contains confidential and proprietary information of
4 * OSWare Technology Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "hdi_drm_composition.h"
20 #include <cerrno>
21 #include "hdi_drm_layer.h"
22
23 namespace OHOS {
24 namespace HDI {
25 namespace DISPLAY {
HdiDrmComposition(std::shared_ptr<DrmConnector> & connector,std::shared_ptr<DrmCrtc> & crtc,std::shared_ptr<DrmDevice> & drmDevice)26 HdiDrmComposition::HdiDrmComposition(std::shared_ptr<DrmConnector> &connector, std::shared_ptr<DrmCrtc> &crtc,
27 std::shared_ptr<DrmDevice> &drmDevice)
28 : mDrmDevice(drmDevice), mConnector(connector), mCrtc(crtc)
29 {
30 DISPLAY_LOGD();
31 }
32
Init()33 int32_t HdiDrmComposition::Init()
34 {
35 DISPLAY_LOGD();
36 mPrimPlanes.clear();
37 mOverlayPlanes.clear();
38 mPlanes.clear();
39 DISPLAY_CHK_RETURN((mCrtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null"));
40 DISPLAY_CHK_RETURN((mConnector == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("connector is null"));
41 DISPLAY_CHK_RETURN((mDrmDevice == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("drmDevice is null"));
42 mPrimPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_PRIMARY);
43 mOverlayPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_OVERLAY);
44 DISPLAY_CHK_RETURN((mPrimPlanes.size() == 0), DISPLAY_FAILURE, DISPLAY_LOGE("has no primary plane"));
45 mPlanes.insert(mPlanes.end(), mPrimPlanes.begin(), mPrimPlanes.end());
46 mPlanes.insert(mPlanes.end(), mOverlayPlanes.begin(), mOverlayPlanes.end());
47 return DISPLAY_SUCCESS;
48 }
49
SetLayers(std::vector<HdiLayer * > & layers,HdiLayer & clientLayer)50 int32_t HdiDrmComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
51 {
52 // now we do not surpport present direct
53 DISPLAY_LOGD();
54 mCompLayers.clear();
55 mCompLayers.push_back(&clientLayer);
56 return DISPLAY_SUCCESS;
57 }
58
ApplyPlane(HdiDrmLayer & layer,DrmPlane & drmPlane,drmModeAtomicReqPtr pset)59 int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer, DrmPlane &drmPlane, drmModeAtomicReqPtr pset)
60 {
61 // set fence in
62 int ret;
63 int fenceFd = layer.GetAcquireFenceFd();
64 int propId = drmPlane.GetPropFenceInId();
65 DISPLAY_LOGD();
66 if (propId != 0) {
67 DISPLAY_LOGD("set the fence in prop");
68 if (fenceFd >= 0) {
69 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd);
70 DISPLAY_LOGD("set the IfenceProp plane id %{public}d, propId %{public}d, fenceFd %{public}d",
71 drmPlane.GetId(), propId, fenceFd);
72 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set IN_FENCE_FD failed"));
73 }
74 }
75
76 // set fb id
77 DrmGemBuffer *gemBuffer = layer.GetGemBuffer();
78 DISPLAY_CHK_RETURN((gemBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("current gemBuffer is nullptr"));
79 DISPLAY_CHK_RETURN((!gemBuffer->IsValid()), DISPLAY_FAILURE, DISPLAY_LOGE("the DrmGemBuffer is invalid"));
80 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId());
81 DISPLAY_LOGD("set the fb planeid %{public}d, propId %{public}d, fbId %{public}d", drmPlane.GetId(),
82 drmPlane.GetPropFbId(), gemBuffer->GetFbId());
83 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set fb id fialed errno : %{public}d", errno));
84
85 // set crtc id
86 ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId());
87 DISPLAY_LOGD("set the crtc planeId %{public}d, propId %{public}d, crtcId %{public}d", drmPlane.GetId(),
88 drmPlane.GetPropCrtcId(), mCrtc->GetId());
89 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set crtc id fialed errno : %{public}d", errno));
90 return DISPLAY_SUCCESS;
91 }
92
UpdateMode(std::unique_ptr<DrmModeBlock> & modeBlock,drmModeAtomicReq & pset)93 int32_t HdiDrmComposition::UpdateMode(std::unique_ptr<DrmModeBlock> &modeBlock, drmModeAtomicReq &pset)
94 {
95 // set the mode
96 int ret;
97 DISPLAY_LOGD();
98 if (mCrtc->NeedModeSet()) {
99 modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId());
100 if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) {
101 // set to active
102 DISPLAY_LOGD("set crtc to active");
103 ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1);
104 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
105 DISPLAY_LOGE("can not add the active prop errno %{public}d", errno));
106
107 // set the mode id
108 DISPLAY_LOGD("set the mode");
109 ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId());
110 DISPLAY_LOGD("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d", mCrtc->GetId(),
111 mCrtc->GetModePropId(), modeBlock->GetBlockId());
112 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
113 DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno));
114 ret = drmModeAtomicAddProperty(&pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId());
115 DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", mConnector->GetId(),
116 mConnector->GetPropCrtcId(), mCrtc->GetId());
117 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE,
118 DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno));
119 }
120 }
121 return DISPLAY_SUCCESS;
122 }
123
Apply(bool modeSet)124 int32_t HdiDrmComposition::Apply(bool modeSet)
125 {
126 uint64_t crtcOutFence = -1;
127 int ret;
128 std::unique_ptr<DrmModeBlock> modeBlock;
129 int drmFd = mDrmDevice->GetDrmFd();
130 DISPLAY_LOGD();
131 DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough"));
132 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
133 DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR,
134 DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno));
135 AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset);
136
137 // set the outFence property
138 ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(),
139 (uint64_t)&crtcOutFence);
140
141 DISPLAY_LOGD("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(),
142 mCrtc->GetOutFencePropId());
143 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed "));
144
145 // set the plane info.
146 DISPLAY_LOGD("mCompLayers size %{public}zd", mCompLayers.size());
147 for (uint32_t i = 0; i < mCompLayers.size(); i++) {
148 HdiDrmLayer *layer = static_cast<HdiDrmLayer *>(mCompLayers[i]);
149 auto &drmPlane = mPlanes[i];
150 ret = ApplyPlane(*layer, *drmPlane, atomicReqPtr.Get());
151 if (ret != DISPLAY_SUCCESS) {
152 DISPLAY_LOGE("apply plane failed");
153 break;
154 }
155 }
156 ret = UpdateMode(modeBlock, *(atomicReqPtr.Get()));
157 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed"));
158 uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
159
160 ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr);
161 DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE,
162 DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno));
163 // set the release fence
164 for (auto layer : mCompLayers) {
165 layer->SetReleaseFence(dup(static_cast<int32_t>(crtcOutFence)));
166 }
167 close(static_cast<int32_t>(crtcOutFence));
168 crtcOutFence = -1;
169 return DISPLAY_SUCCESS;
170 }
171 } // OHOS
172 } // HDI
173 } // DISPLAY
174