1 /*
2  * Copyright (c) 2024 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 #ifndef OHOS_HDI_DISPLAY_V1_2_DISPLAY_CMD_REQUESTER_H
17 #define OHOS_HDI_DISPLAY_V1_2_DISPLAY_CMD_REQUESTER_H
18 
19 #include "v1_0/display_command/display_cmd_responser.h"
20 #include "v1_1/display_command/display_cmd_responser.h"
21 #include "v1_2/display_composer_type.h"
22 #include "v1_2/display_command/display_cmd_utils.h"
23 
24 #define DISPLAY_TRACE HdfTrace trace(__func__, "HDI:DISP:")
25 
26 namespace OHOS {
27 namespace HDI {
28 namespace Display {
29 namespace Composer {
30 namespace V1_2 {
31 using namespace OHOS::HDI::Base;
32 
33 typedef struct CommitInfo {
34     int32_t fence;
35     int32_t skipRet;
36     bool needFlush;
37     std::vector<uint32_t> compLayers;
38     std::vector<int32_t> compTypes;
39     std::vector<uint32_t> layers;
40     std::vector<int32_t> fences;
41 } CommitInfo;
42 
43 template <typename Transfer, typename VdiImpl, typename VdiImpl1_1>
44 class DisplayCmdResponser : public V1_1::DisplayCmdResponser<Transfer, VdiImpl> {
45 public:
Create(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)46     static std::unique_ptr<DisplayCmdResponser> Create(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)
47     {
48         DISPLAY_CHK_RETURN(impl == nullptr, nullptr,
49             HDF_LOGE("%{public}s: error, VdiImpl is nullptr", __func__));
50         DISPLAY_CHK_RETURN(cacheMgr == nullptr, nullptr,
51             HDF_LOGE("%{public}s: error, VdiImpl is nullptr", __func__));
52         return std::make_unique<DisplayCmdResponser>(impl, cacheMgr);
53     }
54 
CreateV1_1( VdiImpl1_1* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)55     static std::unique_ptr<DisplayCmdResponser> CreateV1_1(
56         VdiImpl1_1* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)
57     {
58         DISPLAY_CHK_RETURN(impl == nullptr, nullptr,
59             HDF_LOGE("%{public}s: error, VdiImpl is nullptr", __func__));
60         DISPLAY_CHK_RETURN(cacheMgr == nullptr, nullptr,
61             HDF_LOGE("%{public}s: error, VdiImpl is nullptr", __func__));
62         return std::make_unique<DisplayCmdResponser>(cacheMgr, impl);
63     }
64 
DisplayCmdResponser(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr)65     DisplayCmdResponser(VdiImpl* impl, std::shared_ptr<DeviceCacheManager> cacheMgr) : BaseType1_1(impl, cacheMgr) {}
66 
DisplayCmdResponser(std::shared_ptr<DeviceCacheManager> cacheMgr, VdiImpl1_1* impl)67     DisplayCmdResponser(std::shared_ptr<DeviceCacheManager> cacheMgr, VdiImpl1_1* impl)
68         : BaseType1_1(impl, cacheMgr),
69           vdiImpl1_1_(impl)
70         {}
71 
~DisplayCmdResponser()72     virtual ~DisplayCmdResponser() {}
73 
ProcessRequestCmd(CommandDataUnpacker& unpacker, int32_t cmd, const std::vector<HdifdInfo>& inFds, std::vector<HdifdInfo>& outFds)74     int32_t ProcessRequestCmd(CommandDataUnpacker& unpacker, int32_t cmd,
75         const std::vector<HdifdInfo>& inFds, std::vector<HdifdInfo>& outFds)
76     {
77         HDF_LOGD("%{public}s: HDI 1.2 PackSection, cmd-[%{public}d] = %{public}s",
78             __func__, cmd, CmdUtils::CommandToString(cmd));
79         if (cmd == REQUEST_CMD_COMMIT_AND_GET_RELEASE_FENCE) {
80             OnCommitAndGetReleaseFence(unpacker, outFds);
81         } else if (cmd == REQUEST_CMD_SET_DISPLAY_CONSTRAINT) {
82             OnSetDisplayConstraint(unpacker);
83         } else {
84             return V1_0::DisplayCmdResponser<Transfer, VdiImpl>::ProcessRequestCmd(unpacker, cmd, inFds, outFds);
85         }
86         return HDF_SUCCESS;
87     }
88 
ReplyNotSkipInfo(uint32_t& devId, CommitInfo& commitInfo)89     void ReplyNotSkipInfo(uint32_t& devId, CommitInfo& commitInfo)
90     {
91         DISPLAY_CHECK(replyPacker_.WriteUint32(devId) == false,
92             HDF_LOGE("%{public}s, write devId error", __func__));
93 
94         DISPLAY_CHECK(replyPacker_.WriteBool(commitInfo.needFlush) == false,
95             HDF_LOGE("%{public}s, write needFlush error", __func__));
96 
97         // Write compLayers vector
98         uint32_t vectSize = static_cast<uint32_t>(commitInfo.compLayers.size());
99         DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
100             HDF_LOGE("%{public}s, write compLayers.size error", __func__));
101 
102         for (uint32_t i = 0; i < vectSize; i++) {
103             DISPLAY_CHECK(replyPacker_.WriteUint32(commitInfo.compLayers[i]) == false,
104                 HDF_LOGE("%{public}s, write compLayers error", __func__));
105         }
106         // Write compTypes vector
107         vectSize = static_cast<uint32_t>(commitInfo.compTypes.size());
108         DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
109             HDF_LOGE("%{public}s, write compTypes.size error", __func__));
110 
111         for (uint32_t i = 0; i < vectSize; i++) {
112             DISPLAY_CHECK(replyPacker_.WriteUint32(commitInfo.compTypes[i]) == false,
113                 HDF_LOGE("%{public}s, write compTypes error", __func__));
114         }
115     }
116 
ReplyCommitAndGetReleaseFence(std::vector<HdifdInfo>& outFds, uint32_t& devId, CommitInfo& commitInfo)117     void ReplyCommitAndGetReleaseFence(std::vector<HdifdInfo>& outFds, uint32_t& devId, CommitInfo& commitInfo)
118     {
119         int32_t ret = HDF_SUCCESS;
120         uint32_t vectSize = 0;
121 
122         HdifdParcelable fdParcel(commitInfo.fence);
123         DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS,
124             CmdUtils::StartSection(REPLY_CMD_COMMIT_AND_GET_RELEASE_FENCE, replyPacker_),
125             HDF_LOGE("%{public}s, StartSection error", __func__));
126 
127         DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::FileDescriptorPack(fdParcel.GetFd(), replyPacker_, outFds),
128             HDF_LOGE("%{public}s, FileDescriptorPack error", __func__));
129 
130         DISPLAY_CHECK(replyPacker_.WriteInt32(commitInfo.skipRet) == false,
131             HDF_LOGE("%{public}s, write skip validate return value error", __func__));
132         if (commitInfo.skipRet != HDF_SUCCESS) {
133             ReplyNotSkipInfo(devId, commitInfo);
134         } else {
135             // Write layers vector
136             vectSize = static_cast<uint32_t>(commitInfo.layers.size());
137             DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
138                 HDF_LOGE("%{public}s, write layers.size error", __func__));
139 
140             for (uint32_t i = 0; i < vectSize; i++) {
141                 DISPLAY_CHECK(replyPacker_.WriteUint32(commitInfo.layers[i]) == false,
142                     HDF_LOGE("%{public}s, write layers error", __func__));
143             }
144 
145             // Write fences vector
146             vectSize = static_cast<uint32_t>(commitInfo.fences.size());
147             DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
148                 HDF_LOGE("%{public}s, write fences.size error", __func__));
149 
150             for (uint32_t i = 0; i < vectSize; i++) {
151                 ret = CmdUtils::FileDescriptorPack(commitInfo.fences[i], replyPacker_, outFds, false);
152                 DISPLAY_CHECK(ret != HDF_SUCCESS, HDF_LOGE("%{public}s, write fences error", __func__));
153             }
154         }
155 
156         DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::EndSection(replyPacker_),
157             HDF_LOGE("%{public}s, EndSection error", __func__));
158 
159         replyCommandCnt_++;
160 
161 #ifndef DISPLAY_COMMUNITY
162         fdParcel.Move();
163 #endif // DISPLAY_COMMUNITY
164 
165         if (ret != HDF_SUCCESS) {
166             errMaps_.emplace(REQUEST_CMD_COMMIT_AND_GET_RELEASE_FENCE, ret);
167         }
168     }
169 
CommitInfoDump(void)170     void CommitInfoDump(void)
171     {
172 #ifdef DISPLAY_COMSPOER_DEBUG_DUMP
173         const std::string SWITCH_ON = "on";
174         const uint32_t DUMP_CACHE_SWITCH_LEN = 4;
175         char dumpSwitch[DUMP_CACHE_SWITCH_LEN] = {0};
176         GetParameter("hdi.composer.dumpcache", "off", dumpSwitch, DUMP_CACHE_SWITCH_LEN);
177 
178         if (SWITCH_ON.compare(dumpSwitch) == 0) {
179             cacheMgr_->Dump();
180         }
181 #endif
182     }
183 
OnCommitAndGetReleaseFence(CommandDataUnpacker& unpacker, std::vector<HdifdInfo>& outFds)184     void OnCommitAndGetReleaseFence(CommandDataUnpacker& unpacker, std::vector<HdifdInfo>& outFds)
185     {
186         DISPLAY_TRACE;
187         uint32_t devId = 0;
188         bool isSupportSkipValidate = false;
189         bool isValidated = false;
190         int32_t ret = HDF_SUCCESS;
191         CommitInfo commitInfo;
192         commitInfo.fence = -1;
193         commitInfo.skipRet = HDF_FAILURE;
194         commitInfo.needFlush = false;
195 
196         CommitInfoDump();
197         if (!unpacker.ReadUint32(devId)) {
198             HDF_LOGE("%{public}s, read devId error", __func__);
199             goto REPLY;
200         }
201         if (!unpacker.ReadBool(isSupportSkipValidate)) {
202             HDF_LOGE("%{public}s, read isSupportSkipValidate error", __func__);
203             goto REPLY;
204         }
205 
206         if (!unpacker.ReadBool(isValidated)) {
207             HDF_LOGE("%{public}s, read isValidated error", __func__);
208             goto REPLY;
209         }
210         if (isSupportSkipValidate || isValidated) {
211             HdfTrace traceVdi("Commit", "HDI:DISP:HARDWARE");
212             commitInfo.skipRet = impl_->Commit(devId, commitInfo.fence);
213         }
214 
215         if (commitInfo.skipRet != HDF_SUCCESS && isValidated == false) {
216             {
217                 HdfTrace traceVdi("PrepareDisplayLayers", "HDI:DISP:HARDWARE");
218                 ret = impl_->PrepareDisplayLayers(devId, commitInfo.needFlush);
219             }
220             if (ret == HDF_SUCCESS) {
221                 HdfTrace traceVdi("GetDisplayCompChange", "HDI:DISP:HARDWARE");
222                 ret = impl_->GetDisplayCompChange(devId, commitInfo.compLayers, commitInfo.compTypes);
223             }
224         } else {
225             HdfTrace traceVdi("GetDisplayReleaseFence", "HDI:DISP:HARDWARE");
226             if (impl_->GetDisplayReleaseFence(devId, commitInfo.layers, commitInfo.fences) != HDF_SUCCESS) {
227                 HDF_LOGE("%{public}s, GetDisplayReleaseFence failed with ret = %{public}d", __func__, ret);
228             }
229         }
230         HDF_LOGD("skipRet:%{public}d,fence:%{public}d,needFlush:%{public}d, ssv:%{public}d, iv:%{public}d",
231             commitInfo.skipRet, commitInfo.fence, commitInfo.needFlush, isSupportSkipValidate, isValidated);
232 REPLY:
233         ReplyCommitAndGetReleaseFence(outFds, devId, commitInfo);
234     }
235 
CmdRequest(uint32_t inEleCnt, const std::vector<HdifdInfo>& inFds, uint32_t& outEleCnt, std::vector<HdifdInfo>& outFds)236     int32_t CmdRequest(uint32_t inEleCnt, const std::vector<HdifdInfo>& inFds, uint32_t& outEleCnt,
237         std::vector<HdifdInfo>& outFds)
238     {
239         std::shared_ptr<char> requestData(new char[inEleCnt * CmdUtils::ELEMENT_SIZE], std::default_delete<char[]>());
240         int32_t ret = CmdRequestDataRead(requestData, inEleCnt);
241 
242         CommandDataUnpacker unpacker;
243         unpacker.Init(requestData.get(), inEleCnt << CmdUtils::MOVE_SIZE);
244 #ifdef DEBUG_DISPLAY_CMD_RAW_DATA
245         unpacker.Dump();
246 #endif // DEBUG_DISPLAY_CMD_RAW_DATA
247 
248         int32_t unpackCmd = -1;
249         bool retBool = unpacker.PackBegin(unpackCmd);
250         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
251             HDF_LOGE("%{public}s: error: Check RequestBegin failed", __func__));
252         DISPLAY_CHK_RETURN(unpackCmd != CONTROL_CMD_REQUEST_BEGIN, HDF_FAILURE,
253             HDF_LOGI("error: unpacker PackBegin cmd not match, cmd(%{public}d)=%{public}s.", unpackCmd,
254             CmdUtils::CommandToString(unpackCmd)));
255 
256         while (ret == HDF_SUCCESS && unpacker.NextSection()) {
257             if (!unpacker.BeginSection(unpackCmd)) {
258                 HDF_LOGE("error: PackSection failed, unpackCmd=%{public}s.",
259                     CmdUtils::CommandToString(unpackCmd));
260                 ret = HDF_FAILURE;
261             }
262             ret = ProcessRequestCmd(unpacker, unpackCmd, inFds, outFds);
263         }
264 
265         DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
266             HDF_LOGE("%{public}s: ProcessRequestCmd failed", __func__));
267         /* pack request end commands */
268         replyPacker_.PackEnd(CONTROL_CMD_REPLY_END);
269 
270 #ifdef DEBUG_DISPLAY_CMD_RAW_DATA
271         /* just for debug */
272         replyPacker_.Dump();
273         HDF_LOGI("CmdReply command cnt=%{public}d", replyCommandCnt_);
274 #endif // DEBUG_DISPLAY_CMD_RAW_DATA
275 
276         /*  Write reply pack */
277         outEleCnt = replyPacker_.ValidSize() >> CmdUtils::MOVE_SIZE;
278         ret = CmdRequestDataWrite(outEleCnt);
279         if (ret != HDF_SUCCESS) {
280             HDF_LOGE("Reply write failure, ret=%{public}d", ret);
281             outEleCnt = 0;
282         }
283         int32_t ec = PeriodDataReset();
284         return (ret == HDF_SUCCESS ? ec : ret);
285     }
286 
OnSetDisplayConstraint(CommandDataUnpacker& unpacker)287     int32_t OnSetDisplayConstraint(CommandDataUnpacker& unpacker)
288     {
289         DISPLAY_TRACE;
290         uint32_t devId = 0;
291         uint64_t frameID = 0;
292         uint64_t ns = 0;
293         uint32_t type = 0;
294 
295         int32_t ret = unpacker.ReadUint32(devId) ? HDF_SUCCESS : HDF_FAILURE;
296         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
297 
298         ret = unpacker.ReadUint64(frameID) ? HDF_SUCCESS : HDF_FAILURE;
299         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
300 
301         ret = unpacker.ReadUint64(ns) ? HDF_SUCCESS : HDF_FAILURE;
302         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
303 
304         ret = unpacker.ReadUint32(type) ? HDF_SUCCESS : HDF_FAILURE;
305         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
306         if (vdiImpl1_1_ != nullptr) {
307             ret = vdiImpl1_1_->SetDisplayConstraint(devId, frameID, ns, type);
308         }
309         DISPLAY_CHECK(ret != HDF_SUCCESS && ret != DISPLAY_NOT_SUPPORT && ret != HDF_ERR_NOT_SUPPORT, goto EXIT);
310 EXIT:
311         if (ret != HDF_SUCCESS) {
312             errMaps_.emplace(REQUEST_CMD_SET_DISPLAY_CONSTRAINT, ret);
313         }
314         return ret;
315     }
316 
317 private:
318     using BaseType1_1 = V1_1::DisplayCmdResponser<Transfer, VdiImpl>;
319     using BaseType1_1::replyPacker_;
320     using BaseType1_1::cacheMgr_;
321     using BaseType1_1::impl_;
322     using BaseType1_1::replyCommandCnt_;
323     using BaseType1_1::errMaps_;
324     using BaseType1_1::request_;
325     using BaseType1_1::reply_;
326     using BaseType1_1::PeriodDataReset;
327     using BaseType1_1::OnPrepareDisplayLayers;
328     using BaseType1_1::OnSetDisplayClientBuffer;
329     using BaseType1_1::OnSetDisplayClientDamage;
330     using BaseType1_1::OnCommit;
331     using BaseType1_1::OnSetLayerAlpha;
332     using BaseType1_1::OnSetLayerRegion;
333     using BaseType1_1::OnSetLayerCrop;
334     using BaseType1_1::OnSetLayerZorder;
335     using BaseType1_1::OnSetLayerPreMulti;
336     using BaseType1_1::OnSetLayerTransformMode;
337     using BaseType1_1::OnSetLayerDirtyRegion;
338     using BaseType1_1::OnSetLayerVisibleRegion;
339     using BaseType1_1::OnSetLayerBuffer;
340     using BaseType1_1::OnSetLayerCompositionType;
341     using BaseType1_1::OnSetLayerBlendType;
342     using BaseType1_1::OnSetLayerMaskInfo;
343     using BaseType1_1::OnRequestEnd;
344     using BaseType1_1::OnSetLayerColor;
345     using BaseType1_1::CmdRequestDataRead;
346     using BaseType1_1::CmdRequestDataWrite;
347     VdiImpl1_1* vdiImpl1_1_ = nullptr;
348     using BaseType1_1::requestMutex_;
349     using BaseType1_1::replyMutex_;
350 };
351 
352 using HdiDisplayCmdResponser =
353     DisplayCmdResponser<SharedMemQueue<int32_t>, IDisplayComposerVdi, IDisplayComposerVdiV1_1>;
354 
355 using HdiDisplayCmdResponser_1_1 =
356     DisplayCmdResponser<SharedMemQueue<int32_t>, IDisplayComposerVdi, IDisplayComposerVdiV1_1>;
357 
358 } // namespace V1_2
359 } // namespace Composer
360 } // namespace Display
361 } // namespace HDI
362 } // namespace OHOS
363 #endif // OHOS_HDI_DISPLAY_V1_2_DISPLAY_CMD_REQUESTER_H