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