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