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 
133         if (commitInfo.skipRet != HDF_SUCCESS) {
134             ReplyNotSkipInfo(devId, commitInfo);
135         } else {
136             // Write layers vector
137             vectSize = static_cast<uint32_t>(commitInfo.layers.size());
138             DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
139                 HDF_LOGE("%{public}s, write layers.size error", __func__));
140 
141             for (uint32_t i = 0; i < vectSize; i++) {
142                 DISPLAY_CHECK(replyPacker_.WriteUint32(commitInfo.layers[i]) == false,
143                     HDF_LOGE("%{public}s, write layers error", __func__));
144             }
145 
146             // Write fences vector
147             vectSize = static_cast<uint32_t>(commitInfo.fences.size());
148             DISPLAY_CHECK(replyPacker_.WriteUint32(vectSize) == false,
149                 HDF_LOGE("%{public}s, write fences.size error", __func__));
150 
151             for (uint32_t i = 0; i < vectSize; i++) {
152                 ret = CmdUtils::FileDescriptorPack(commitInfo.fences[i], replyPacker_, outFds, false);
153                 DISPLAY_CHECK(ret != HDF_SUCCESS, HDF_LOGE("%{public}s, write fences error", __func__));
154             }
155         }
156 
157         DISPLAY_CHK_CONDITION(ret, HDF_SUCCESS, CmdUtils::EndSection(replyPacker_),
158             HDF_LOGE("%{public}s, EndSection error", __func__));
159 
160         replyCommandCnt_++;
161 
162 #ifndef DISPLAY_COMMUNITY
163         fdParcel.Move();
164 #endif // DISPLAY_COMMUNITY
165 
166         if (ret != HDF_SUCCESS) {
167             errMaps_.emplace(REQUEST_CMD_COMMIT_AND_GET_RELEASE_FENCE, ret);
168         }
169     }
170 
CommitInfoDump(void)171     void CommitInfoDump(void)
172     {
173 #ifdef DISPLAY_COMSPOER_DEBUG_DUMP
174         const std::string SWITCH_ON = "on";
175         const uint32_t DUMP_CACHE_SWITCH_LEN = 4;
176         char dumpSwitch[DUMP_CACHE_SWITCH_LEN] = {0};
177         GetParameter("hdi.composer.dumpcache", "off", dumpSwitch, DUMP_CACHE_SWITCH_LEN);
178 
179         if (SWITCH_ON.compare(dumpSwitch) == 0) {
180             cacheMgr_->Dump();
181         }
182 #endif
183     }
184 
OnCommitAndGetReleaseFence(CommandDataUnpacker & unpacker,std::vector<HdifdInfo> & outFds)185     void OnCommitAndGetReleaseFence(CommandDataUnpacker& unpacker, std::vector<HdifdInfo>& outFds)
186     {
187         DISPLAY_TRACE;
188         uint32_t devId = 0;
189         bool isSupportSkipValidate = false;
190         bool isValidated = false;
191         int32_t ret = HDF_SUCCESS;
192         CommitInfo commitInfo;
193         commitInfo.fence = -1;
194         commitInfo.skipRet = HDF_FAILURE;
195         commitInfo.needFlush = false;
196 
197         CommitInfoDump();
198         if (!unpacker.ReadUint32(devId)) {
199             HDF_LOGE("%{public}s, read devId error", __func__);
200             goto REPLY;
201         }
202         if (!unpacker.ReadBool(isSupportSkipValidate)) {
203             HDF_LOGE("%{public}s, read isSupportSkipValidate error", __func__);
204             goto REPLY;
205         }
206 
207         if (!unpacker.ReadBool(isValidated)) {
208             HDF_LOGE("%{public}s, read isValidated error", __func__);
209             goto REPLY;
210         }
211         if (isSupportSkipValidate || isValidated) {
212             HdfTrace traceVdi("Commit", "HDI:DISP:HARDWARE");
213             commitInfo.skipRet = impl_->Commit(devId, commitInfo.fence);
214         }
215 
216         if (commitInfo.skipRet != HDF_SUCCESS && isValidated == false) {
217             {
218                 HdfTrace traceVdi("PrepareDisplayLayers", "HDI:DISP:HARDWARE");
219                 ret = impl_->PrepareDisplayLayers(devId, commitInfo.needFlush);
220             }
221             if (ret == HDF_SUCCESS) {
222                 HdfTrace traceVdi("GetDisplayCompChange", "HDI:DISP:HARDWARE");
223                 ret = impl_->GetDisplayCompChange(devId, commitInfo.compLayers, commitInfo.compTypes);
224             }
225         } else {
226             HdfTrace traceVdi("GetDisplayReleaseFence", "HDI:DISP:HARDWARE");
227             if (impl_->GetDisplayReleaseFence(devId, commitInfo.layers, commitInfo.fences) != HDF_SUCCESS) {
228                 HDF_LOGE("%{public}s, GetDisplayReleaseFence failed with ret = %{public}d", __func__, ret);
229             }
230         }
231         HDF_LOGD("skipRet:%{public}d,fence:%{public}d,needFlush:%{public}d, ssv:%{public}d, iv:%{public}d",
232             commitInfo.skipRet, commitInfo.fence, commitInfo.needFlush, isSupportSkipValidate, isValidated);
233 REPLY:
234         ReplyCommitAndGetReleaseFence(outFds, devId, commitInfo);
235     }
236 
CmdRequest(uint32_t inEleCnt,const std::vector<HdifdInfo> & inFds,uint32_t & outEleCnt,std::vector<HdifdInfo> & outFds)237     int32_t CmdRequest(uint32_t inEleCnt, const std::vector<HdifdInfo>& inFds, uint32_t& outEleCnt,
238         std::vector<HdifdInfo>& outFds)
239     {
240         std::shared_ptr<char> requestData(new char[inEleCnt * CmdUtils::ELEMENT_SIZE], std::default_delete<char[]>());
241         int32_t ret = HDF_SUCCESS;
242         {
243             std::lock_guard<std::mutex> lock(requestMutex_);
244             ret = request_->Read(reinterpret_cast<int32_t *>(requestData.get()), inEleCnt,
245                 CmdUtils::TRANSFER_WAIT_TIME);
246         }
247         CommandDataUnpacker unpacker;
248         unpacker.Init(requestData.get(), inEleCnt << CmdUtils::MOVE_SIZE);
249 #ifdef DEBUG_DISPLAY_CMD_RAW_DATA
250         unpacker.Dump();
251 #endif // DEBUG_DISPLAY_CMD_RAW_DATA
252 
253         int32_t unpackCmd = -1;
254         bool retBool = unpacker.PackBegin(unpackCmd);
255         DISPLAY_CHK_RETURN(retBool == false, HDF_FAILURE,
256             HDF_LOGE("%{public}s: error: Check RequestBegin failed", __func__));
257         DISPLAY_CHK_RETURN(unpackCmd != CONTROL_CMD_REQUEST_BEGIN, HDF_FAILURE,
258             HDF_LOGI("error: unpacker PackBegin cmd not match, cmd(%{public}d)=%{public}s.", unpackCmd,
259             CmdUtils::CommandToString(unpackCmd)));
260 
261         DISPLAY_CHK_RETURN(PeriodDataReset() == HDF_FAILURE, HDF_FAILURE,
262                            HDF_LOGE("%{public}s: error: PeriodDataReset failed", __func__));
263         while (ret == HDF_SUCCESS && unpacker.NextSection()) {
264             if (!unpacker.BeginSection(unpackCmd)) {
265                 HDF_LOGE("error: PackSection failed, unpackCmd=%{public}s.",
266                     CmdUtils::CommandToString(unpackCmd));
267                 return HDF_FAILURE;
268             }
269             ret = ProcessRequestCmd(unpacker, unpackCmd, inFds, outFds);
270         }
271 
272         DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, ret,
273             HDF_LOGE("%{public}s: ProcessRequestCmd failed", __func__));
274         /* pack request end commands */
275         replyPacker_.PackEnd(CONTROL_CMD_REPLY_END);
276 
277 #ifdef DEBUG_DISPLAY_CMD_RAW_DATA
278         /* just for debug */
279         replyPacker_.Dump();
280         HDF_LOGI("CmdReply command cnt=%{public}d", replyCommandCnt_);
281 #endif // DEBUG_DISPLAY_CMD_RAW_DATA
282 
283         /*  Write reply pack */
284         outEleCnt = replyPacker_.ValidSize() >> CmdUtils::MOVE_SIZE;
285         {
286             std::lock_guard<std::mutex> lock(replyMutex_);
287             ret = reply_->Write(reinterpret_cast<int32_t *>(replyPacker_.GetDataPtr()), outEleCnt,
288                 CmdUtils::TRANSFER_WAIT_TIME);
289         }
290         if (ret != HDF_SUCCESS) {
291             HDF_LOGE("Reply write failure, ret=%{public}d", ret);
292             outEleCnt = 0;
293         }
294         return ret;
295     }
296 
OnSetDisplayConstraint(CommandDataUnpacker & unpacker)297     int32_t OnSetDisplayConstraint(CommandDataUnpacker& unpacker)
298     {
299         DISPLAY_TRACE;
300         uint32_t devId = 0;
301         uint64_t frameID = 0;
302         uint64_t ns = 0;
303         uint32_t type = 0;
304 
305         int32_t ret = unpacker.ReadUint32(devId) ? HDF_SUCCESS : HDF_FAILURE;
306         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
307 
308         ret = unpacker.ReadUint64(frameID) ? HDF_SUCCESS : HDF_FAILURE;
309         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
310 
311         ret = unpacker.ReadUint64(ns) ? HDF_SUCCESS : HDF_FAILURE;
312         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
313 
314         ret = unpacker.ReadUint32(type) ? HDF_SUCCESS : HDF_FAILURE;
315         DISPLAY_CHECK(ret != HDF_SUCCESS, goto EXIT);
316 
317         if (vdiImpl1_1_ != nullptr) {
318             ret = vdiImpl1_1_->SetDisplayConstraint(devId, frameID, ns, type);
319         }
320         DISPLAY_CHECK(ret != HDF_SUCCESS && ret != DISPLAY_NOT_SUPPORT && ret != HDF_ERR_NOT_SUPPORT, goto EXIT);
321 EXIT:
322         if (ret != HDF_SUCCESS) {
323             errMaps_.emplace(REQUEST_CMD_SET_DISPLAY_CONSTRAINT, ret);
324         }
325         return ret;
326     }
327 
328 private:
329     using BaseType1_1 = V1_1::DisplayCmdResponser<Transfer, VdiImpl>;
330     using BaseType1_1::replyPacker_;
331     using BaseType1_1::cacheMgr_;
332     using BaseType1_1::impl_;
333     using BaseType1_1::replyCommandCnt_;
334     using BaseType1_1::errMaps_;
335     using BaseType1_1::request_;
336     using BaseType1_1::reply_;
337     using BaseType1_1::PeriodDataReset;
338     using BaseType1_1::OnPrepareDisplayLayers;
339     using BaseType1_1::OnSetDisplayClientBuffer;
340     using BaseType1_1::OnSetDisplayClientDamage;
341     using BaseType1_1::OnCommit;
342     using BaseType1_1::OnSetLayerAlpha;
343     using BaseType1_1::OnSetLayerRegion;
344     using BaseType1_1::OnSetLayerCrop;
345     using BaseType1_1::OnSetLayerZorder;
346     using BaseType1_1::OnSetLayerPreMulti;
347     using BaseType1_1::OnSetLayerTransformMode;
348     using BaseType1_1::OnSetLayerDirtyRegion;
349     using BaseType1_1::OnSetLayerVisibleRegion;
350     using BaseType1_1::OnSetLayerBuffer;
351     using BaseType1_1::OnSetLayerCompositionType;
352     using BaseType1_1::OnSetLayerBlendType;
353     using BaseType1_1::OnSetLayerMaskInfo;
354     using BaseType1_1::OnRequestEnd;
355     using BaseType1_1::OnSetLayerColor;
356     VdiImpl1_1* vdiImpl1_1_ = nullptr;
357     using BaseType1_1::requestMutex_;
358     using BaseType1_1::replyMutex_;
359 };
360 
361 using HdiDisplayCmdResponser =
362     DisplayCmdResponser<SharedMemQueue<int32_t>, IDisplayComposerVdi, IDisplayComposerVdiV1_1>;
363 using HdiDisplayCmdResponser_1_1 =
364     DisplayCmdResponser<SharedMemQueue<int32_t>, IDisplayComposerVdi, IDisplayComposerVdiV1_1>;
365 } // namespace V1_2
366 } // namespace Composer
367 } // namespace Display
368 } // namespace HDI
369 } // namespace OHOS
370 #endif // OHOS_HDI_DISPLAY_V1_2_DISPLAY_CMD_REQUESTER_H