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_1/display_command/display_cmd_requester.h"
20 #include "v1_2/display_command/display_cmd_utils.h"
21 #include "v1_2/display_composer_type.h"
22 #include "v1_2/idisplay_composer.h"
23 
24 namespace OHOS {
25 namespace HDI {
26 namespace Display {
27 namespace Composer {
28 namespace V1_2 {
29 using namespace OHOS::HDI::Base;
30 
31 template <typename Transfer, typename CompHdi>
32 class DisplayCmdRequester : public V1_1::DisplayCmdRequester<Transfer, CompHdi> {
33 public:
DisplayCmdRequester(sptr<CompHdi> hdi)34     DisplayCmdRequester(sptr<CompHdi> hdi) : BaseType1_1(hdi), hdi_1_2_(hdi) {}
35 
Create(sptr<CompHdi> hdi)36     static std::unique_ptr<DisplayCmdRequester> Create(sptr<CompHdi> hdi)
37     {
38         DISPLAY_CHK_RETURN(hdi == nullptr, nullptr, HDF_LOGE("%{public}s: hdi is nullptr", __func__));
39         auto requester = std::make_unique<DisplayCmdRequester>(hdi);
40         DISPLAY_CHK_RETURN(requester == nullptr, nullptr,
41             HDF_LOGE("%{public}s: CmdRequester is nullptr", __func__));
42         auto ret = requester->Init(CmdUtils::INIT_ELEMENT_COUNT);
43         if (ret != HDF_SUCCESS) {
44             HDF_LOGE("DisplayCmdRequester init failed");
45             return nullptr;
46         }
47         return requester;
48     }
49 
CommitAndGetReleaseFence(uint32_t devId,int32_t & fence,bool isSupportSkipValidate,int32_t & skipState,bool & needFlush,std::vector<uint32_t> & layers,std::vector<int32_t> & fences,bool isValidated)50     int32_t CommitAndGetReleaseFence(uint32_t devId, int32_t& fence, bool isSupportSkipValidate, int32_t& skipState,
51         bool& needFlush, std::vector<uint32_t>& layers, std::vector<int32_t>& fences, bool isValidated)
52     {
53         uint32_t replyEleCnt = 0;
54         std::vector<HdifdInfo> outFds;
55         std::shared_ptr<char> replyData;
56 
57         int32_t ret = CmdUtils::StartSection(REQUEST_CMD_COMMIT_AND_GET_RELEASE_FENCE, requestPacker_);
58         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
59 
60         ret = requestPacker_.WriteUint32(devId) ? HDF_SUCCESS : HDF_FAILURE;
61         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
62 
63         ret = requestPacker_.WriteBool(isSupportSkipValidate) ? HDF_SUCCESS : HDF_FAILURE;
64         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
65 
66         ret = requestPacker_.WriteBool(isValidated) ? HDF_SUCCESS : HDF_FAILURE;
67         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
68 
69         ret = CmdUtils::EndSection(requestPacker_);
70         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
71 
72         ret = CmdUtils::EndPack(requestPacker_);
73         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
74 
75         ret = DoRequest(replyEleCnt, outFds, replyData);
76         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
77 
78         ret = DoReplyResults(replyEleCnt, outFds, replyData, [&](void *data) -> int32_t {
79             FenceData *fenceData = reinterpret_cast<struct FenceData *>(data);
80             if (fenceData == nullptr) {
81                 fence = -1;
82                 skipState = -1;
83                 needFlush = false;
84                 layers.clear();
85                 fences.clear();
86                 return HDF_FAILURE;
87             }
88             fence = fenceData->fence_;
89             skipState = fenceData->skipValidateState_;
90             needFlush = fenceData->needFlush_;
91             layers = fenceData->layers;
92             fences = fenceData->fences;
93             return HDF_SUCCESS;
94         });
95         if (ret != HDF_SUCCESS) {
96             HDF_LOGE("DoReplyResults failure, ret=%{public}d", ret);
97         }
98 
99 EXIT:
100         return PeriodDataReset() == HDF_SUCCESS ? ret : HDF_FAILURE;
101     }
102 
OnReplySkipStateFailed(CommandDataUnpacker & replyUnpacker,bool & needFlush)103     int32_t OnReplySkipStateFailed(CommandDataUnpacker& replyUnpacker, bool &needFlush)
104     {
105         uint32_t devId = 0;
106         int32_t retBool = replyUnpacker.ReadUint32(devId);
107         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE, HDF_LOGE("%{public}s: read devId failed", __func__));
108 
109         retBool = replyUnpacker.ReadBool(needFlush);
110         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE, HDF_LOGE("%{public}s: read needFlush failed", __func__));
111 
112         // unpack layers vector
113         uint32_t vectSize = 0;
114         retBool = replyUnpacker.ReadUint32(vectSize);
115         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
116             HDF_LOGE("%{public}s: HDI 1.2 read vect size failed", __func__));
117 
118         compChangeLayers_[devId].resize(vectSize);
119         for (uint32_t i = 0; i < vectSize; i++) {
120             DISPLAY_CHK_RETURN(replyUnpacker.ReadUint32(compChangeLayers_[devId][i]) == false, HDF_FAILURE,
121                 HDF_LOGE("%{public}s: HDI 1.2 read layer vector failed", __func__));
122         }
123         // unpack types vector
124         vectSize = 0;
125         retBool = replyUnpacker.ReadUint32(vectSize);
126         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
127             HDF_LOGE("%{public}s: HDI 1.2 read vect size failed", __func__));
128 
129         compChangeTypes_[devId].resize(vectSize);
130         for (uint32_t i = 0; i < vectSize; i++) {
131             DISPLAY_CHK_RETURN(replyUnpacker.ReadInt32(compChangeTypes_[devId][i]) == false, HDF_FAILURE,
132                 HDF_LOGE("%{public}s: HDI 1.2 read composition type vector failed", __func__));
133         }
134         return HDF_SUCCESS;
135     }
136 
OnReplyCommitAndGetReleaseFence(CommandDataUnpacker & replyUnpacker,std::vector<HdifdInfo> & replyFds,int32_t & fenceFd,int32_t & skipState,bool & needFlush,std::vector<uint32_t> & layers,std::vector<int32_t> & fences)137     int32_t OnReplyCommitAndGetReleaseFence(CommandDataUnpacker& replyUnpacker,
138         std::vector<HdifdInfo>& replyFds, int32_t& fenceFd, int32_t& skipState,
139         bool& needFlush, std::vector<uint32_t>& layers, std::vector<int32_t>& fences)
140     {
141         int32_t ret = CmdUtils::FileDescriptorUnpack(replyUnpacker, replyFds, fenceFd);
142         DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
143             HDF_LOGE("%{public}s: FileDescriptorUnpack failed", __func__));
144 
145         int32_t retBool = replyUnpacker.ReadInt32(skipState);
146         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
147             HDF_LOGE("%{public}s: read skipValidateState failed", __func__));
148 
149         if (skipState != HDF_SUCCESS) {
150             return OnReplySkipStateFailed(replyUnpacker, needFlush);
151         } else {
152             // unpack layers vector
153             uint32_t vectSize = 0;
154             DISPLAY_CHK_RETURN(true != replyUnpacker.ReadUint32(vectSize), HDF_FAILURE,
155                 HDF_LOGE("%{public}s: HDI 1.2 read vect size failed", __func__));
156 
157             layers.resize(vectSize);
158             for (uint32_t i = 0; i < vectSize; i++) {
159                 DISPLAY_CHK_RETURN(replyUnpacker.ReadUint32(layers[i]) == false, HDF_FAILURE,
160                     HDF_LOGE("%{public}s: HDI 1.2 read layer vector failed", __func__));
161             }
162 
163             // unpack fences vector
164             vectSize = 0;
165             DISPLAY_CHK_RETURN(true != replyUnpacker.ReadUint32(vectSize), HDF_FAILURE,
166                 HDF_LOGE("%{public}s: HDI 1.2 read vect size failed", __func__));
167 
168             fences.resize(vectSize);
169             for (uint32_t i = 0; i < vectSize; i++) {
170                 ret = CmdUtils::FileDescriptorUnpack(replyUnpacker, replyFds, fences[i]);
171                 DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
172                     HDF_LOGE("%{public}s: HDI 1.2 FileDescriptorUnpack failed", __func__));
173             }
174         }
175 
176         return HDF_SUCCESS;
177     }
178 
ProcessUnpackCmd(CommandDataUnpacker & replyUnpacker,int32_t unpackCmd,std::vector<HdifdInfo> & replyFds,std::function<int32_t (void *)> fn)179     int32_t ProcessUnpackCmd(CommandDataUnpacker& replyUnpacker, int32_t unpackCmd,
180         std::vector<HdifdInfo>& replyFds, std::function<int32_t(void *)> fn)
181     {
182         int32_t ret = HDF_SUCCESS;
183         while (replyUnpacker.NextSection()) {
184             bool retBool = replyUnpacker.BeginSection(unpackCmd);
185             DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
186                 HDF_LOGE("%{public}s: BeginSection failed", __func__));
187 
188             FenceData fenceData;
189 
190             std::unordered_map<int32_t, int32_t> errMaps;
191             switch (unpackCmd) {
192                 case REPLY_CMD_COMMIT_AND_GET_RELEASE_FENCE:
193                     ret = OnReplyCommitAndGetReleaseFence(replyUnpacker, replyFds, fenceData.fence_,
194                         fenceData.skipValidateState_, fenceData.needFlush_, fenceData.layers, fenceData.fences);
195                     DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
196                         HDF_LOGE("%{public}s: OnReplyCommit failed unpackCmd=%{public}s",
197                         __func__, CmdUtils::CommandToString(unpackCmd)));
198 
199                     ret = fn(&fenceData);
200                     DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
201                         HDF_LOGE("%{public}s: return fence fd error, unpackCmd=%{public}s",
202                         __func__, CmdUtils::CommandToString(unpackCmd)));
203                     break;
204                 default:
205                     HDF_LOGE("Unpack command failure");
206                     return HDF_FAILURE;
207             }
208         }
209         return HDF_SUCCESS;
210     }
211 
DoReplyResults(uint32_t replyEleCnt,std::vector<HdifdInfo> & replyFds,std::shared_ptr<char> replyData,std::function<int32_t (void *)> fn)212     int32_t DoReplyResults(uint32_t replyEleCnt, std::vector<HdifdInfo>& replyFds, std::shared_ptr<char> replyData,
213         std::function<int32_t(void *)> fn)
214     {
215         CommandDataUnpacker replyUnpacker;
216         replyUnpacker.Init(replyData.get(), replyEleCnt << CmdUtils::MOVE_SIZE);
217 #ifdef DEBUG_DISPLAY_CMD_RAW_DATA
218         replyUnpacker.Dump();
219 #endif // DEBUG_DISPLAY_CMD_RAW_DATA
220         int32_t unpackCmd = -1;
221         bool retBool = replyUnpacker.PackBegin(unpackCmd);
222         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
223             HDF_LOGE("%{public}s: PackBegin failed", __func__));
224         DISPLAY_CHK_RETURN(unpackCmd != CONTROL_CMD_REPLY_BEGIN, HDF_FAILURE,
225             HDF_LOGE("%{public}s: PackBegin cmd not match, unpackCmd=%{public}d", __func__, unpackCmd));
226         if (ProcessUnpackCmd(replyUnpacker, unpackCmd, replyFds, fn) != HDF_SUCCESS) {
227             return HDF_FAILURE;
228         }
229 
230         retBool = replyUnpacker.PackEnd(unpackCmd);
231         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
232             HDF_LOGE("%{public}s: PackEnd failed", __func__));
233 
234         DISPLAY_CHK_RETURN(unpackCmd != CONTROL_CMD_REPLY_END, HDF_FAILURE,
235             HDF_LOGE("%{public}s: PackEnd failed, endCmd = %{public}s",
236             __func__, CmdUtils::CommandToString(unpackCmd)));
237 
238         return HDF_SUCCESS;
239     }
240 
241     // LTPO新增接口
SetDisplayConstraint(uint32_t devId,uint64_t frameID,uint64_t ns,uint32_t type)242     int32_t SetDisplayConstraint(uint32_t devId, uint64_t frameID, uint64_t ns, uint32_t type)
243     {
244         int32_t ret = 0;
245         bool retBool = false;
246         int32_t writePos = requestPacker_.ValidSize();
247 
248         do {
249             ret = CmdUtils::StartSection(REQUEST_CMD_SET_DISPLAY_CONSTRAINT, requestPacker_);
250             DISPLAY_CHK_BREAK(ret != HDF_SUCCESS,
251                 HDF_LOGE("%{public}s: StartSection failed", __func__));
252 
253             retBool = requestPacker_.WriteUint32(devId);
254             DISPLAY_CHK_BREAK(retBool == false,
255                 HDF_LOGE("%{public}s: write devId failed", __func__));
256 
257             retBool = requestPacker_.WriteUint64(frameID);
258             DISPLAY_CHK_BREAK(retBool == false,
259                 HDF_LOGE("%{public}s: write frameID failed", __func__));
260 
261             retBool = requestPacker_.WriteUint64(ns);
262             DISPLAY_CHK_BREAK(retBool == false,
263                 HDF_LOGE("%{public}s: write ns failed", __func__));
264 
265             retBool = requestPacker_.WriteUint32(type);
266             DISPLAY_CHK_BREAK(retBool == false,
267                 HDF_LOGE("%{public}s: write type failed", __func__));
268 
269             ret = CmdUtils::EndSection(requestPacker_);
270             DISPLAY_CHK_BREAK(ret != HDF_SUCCESS,
271                 HDF_LOGE("%{public}s: EndSection failed", __func__));
272         } while (0);
273 
274         if (retBool == false || ret != HDF_SUCCESS) {
275             requestPacker_.RollBack(writePos);
276             HDF_LOGE("%{public}s: writePos_ rollback", __func__);
277             return HDF_FAILURE;
278         }
279         return HDF_SUCCESS;
280     }
281 
282 protected:
283     sptr<CompHdi> hdi_1_2_;
284 private:
285     using BaseType1_1 = V1_1::DisplayCmdRequester<Transfer, CompHdi>;
286     using BaseType1_1::requestPacker_;
287     using BaseType1_1::DoRequest;
288     using BaseType1_1::PeriodDataReset;
289     using BaseType1_1::DoReplyResults;
290 
291     // Composition layers/types changed
292     using BaseType1_1::compChangeLayers_;
293     using BaseType1_1::compChangeTypes_;
294     // CommitAndGetReleaseFence
295     struct FenceData {
296         int32_t fence_ = -1;
297         int32_t skipValidateState_ = -1;
298         bool needFlush_ = false;
299         std::vector<uint32_t> layers;
300         std::vector<int32_t> fences;
301     };
302 };
303 using HdiDisplayCmdRequester = V1_2::DisplayCmdRequester<SharedMemQueue<int32_t>, V1_2::IDisplayComposer>;
304 } // namespace V1_2
305 } // namespace Composer
306 } // namespace Display
307 } // namespace HDI
308 } // namespace OHOS
309 #endif // OHOS_HDI_DISPLAY_V1_2_DISPLAY_CMD_REQUESTER_H
310