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