1 /* 2 * Copyright (c) 2021-2023 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 ROSEN_RENDER_SERVICE_BASE_COMMAND_RS_COMMAND_TEMPLATES_H 17 #define ROSEN_RENDER_SERVICE_BASE_COMMAND_RS_COMMAND_TEMPLATES_H 18 19 #include <cinttypes> 20 #include "command/rs_command.h" 21 #include "command/rs_command_factory.h" 22 #include "transaction/rs_marshalling_helper.h" 23 24 namespace OHOS { 25 namespace Rosen { 26 class RSUIDirector; 27 28 // avoiding C++ macros spliting parameters 29 #ifndef ARG 30 #define ARG(...) __VA_ARGS__ 31 #endif 32 33 // Add new RSCommand as alias of template class 34 // Explicit instantiating templates will register the unmarshalling function into RSCommandFactory. 35 // To avoid redundant registry, make sure templates only instantiated once. 36 #ifdef _WIN32 37 #ifdef ROSEN_INSTANTIATE_COMMAND_TEMPLATE 38 #define ADD_COMMAND(ALIAS, TYPE) \ 39 using ALIAS = RSCommandTemplate<TYPE>; \ 40 template class RSCommandTemplate<TYPE>; 41 #else 42 #define ADD_COMMAND(ALIAS, TYPE) using ALIAS = RSCommandTemplate<TYPE>; 43 #endif 44 #else 45 #ifdef ROSEN_INSTANTIATE_COMMAND_TEMPLATE 46 #define ADD_COMMAND(ALIAS, TYPE) \ 47 using ALIAS = RSCommandTemplate<TYPE>; \ 48 template class RSB_EXPORT RSCommandTemplate<TYPE>; 49 #else 50 #define ADD_COMMAND(ALIAS, TYPE) \ 51 using ALIAS = RSCommandTemplate<TYPE>; \ 52 extern template class RSB_EXPORT RSCommandTemplate<TYPE>; 53 #endif 54 #endif 55 56 template<RSCommandPermissionType permissionType, uint16_t commandType, uint16_t commandSubType, auto processFunc, 57 typename... Params> 58 class RSCommandTemplate : public RSCommand { 59 public: RSCommandTemplate(const Params &...params)60 RSCommandTemplate(const Params&... params) : params_(params...) {} RSCommandTemplate(std::tuple<Params...> && params)61 RSCommandTemplate(std::tuple<Params...>&& params) : params_(std::move(params)) {} 62 ~RSCommandTemplate() override = default; 63 GetAccessPermission()64 RSCommandPermissionType GetAccessPermission() const override 65 { 66 return permissionType; 67 } 68 GetType()69 uint16_t GetType() const override 70 { 71 return commandType; 72 } GetSubType()73 uint16_t GetSubType() const override 74 { 75 return commandSubType; 76 } 77 GetDrawCmdList()78 std::shared_ptr<Drawing::DrawCmdList> GetDrawCmdList() const override 79 { 80 if constexpr (std::tuple_size<decltype(params_)>::value > 1) { 81 using ptrType = typename std::tuple_element<1, decltype(params_)>::type; 82 if constexpr (std::is_same<std::shared_ptr<Drawing::DrawCmdList>, ptrType>::value) { 83 return std::get<1>(params_); 84 } else if constexpr (std::is_same<std::shared_ptr<ModifierNG::RSRenderModifier>, ptrType>::value) { 85 auto& modifier = std::get<1>(params_); 86 if (modifier) { 87 return modifier->GetPropertyDrawCmdList(); 88 } 89 } 90 } 91 return nullptr; 92 } 93 GetNodeId()94 NodeId GetNodeId() const override 95 { 96 using idType = typename std::tuple_element<0, decltype(params_)>::type; 97 if (std::is_same<NodeId, idType>::value) { 98 return std::get<0>(params_); 99 } 100 return 0; // invalidId 101 } 102 GetToken()103 uint64_t GetToken() const override 104 { 105 if (GetType() == RSCommandType::ANIMATION) { 106 if constexpr (std::tuple_size<decltype(params_)>::value > 3) { // 3:For RSAnimationCallback 107 using aniIdType = typename std::tuple_element<1, decltype(params_)>::type; // 1:animationId 108 using tokenType = typename std::tuple_element<2, decltype(params_)>::type; // 2:token 109 if (std::is_same<AnimationId, aniIdType>::value && std::is_same<uint64_t, tokenType>::value) { 110 return static_cast<uint64_t>(std::get<2>(params_)); // 2:return token 111 } 112 } 113 } else if (GetType() == RSCommandType::RS_NODE) { 114 if constexpr (std::tuple_size<decltype(params_)>::value > 3) { // 3:For RSDumpClientNodeTree 115 using pidType = typename std::tuple_element<1, decltype(params_)>::type; // 1:pid_t 116 using tokenType = typename std::tuple_element<2, decltype(params_)>::type; // 2:token 117 if (std::is_same<pid_t, pidType>::value && std::is_same<uint64_t, tokenType>::value) { 118 return static_cast<uint64_t>(std::get<2>(params_)); // 2:return token 119 } 120 } 121 } 122 return 0; // invalidId 123 } 124 Process(RSContext & context)125 void Process(RSContext& context) override 126 { 127 // expand the tuple to function parameters 128 std::apply([&context](auto&... args) { return (*processFunc)(context, args...); }, params_); 129 } 130 Marshalling(Parcel & parcel)131 bool Marshalling(Parcel& parcel) const override 132 { 133 return RSMarshallingHelper::Marshalling(parcel, commandType) && 134 RSMarshallingHelper::Marshalling(parcel, commandSubType) && 135 std::apply([&parcel](const auto&... args) { return RSMarshallingHelper::Marshalling(parcel, args...); }, 136 params_); 137 }; 138 Unmarshalling(Parcel & parcel)139 [[nodiscard]] static RSCommand* Unmarshalling(Parcel& parcel) 140 { 141 std::tuple<Params...> params; 142 if (!std::apply( 143 [&parcel](auto&... args) { return RSMarshallingHelper::Unmarshalling(parcel, args...); }, params)) { 144 return nullptr; 145 } 146 return new RSCommandTemplate(std::move(params)); 147 } 148 149 static inline RSCommandRegister<commandType, commandSubType, Unmarshalling> registry; 150 151 private: 152 std::tuple<Params...> params_; 153 154 #ifdef RS_PROFILER_ENABLED Patch(PatchFunction function)155 void Patch(PatchFunction function) override 156 { 157 PatchParameters(function, params_, std::make_index_sequence<std::tuple_size_v<decltype(params_)>> {}); 158 } 159 160 template<typename T, std::size_t... Index> PatchParameters(PatchFunction function,T & params,std::index_sequence<Index...>)161 static void PatchParameters(PatchFunction function, T& params, std::index_sequence<Index...>) 162 { 163 (PatchParameter(function, std::get<Index>(params)), ...); 164 } 165 166 template<typename T> PatchParameter(PatchFunction function,T & value)167 static void PatchParameter(PatchFunction function, T& value) 168 { 169 if (std::is_same<NodeId, T>::value || std::is_same<AnimationId, T>::value || 170 std::is_same<PropertyId, T>::value || std::is_same<ModifierId, T>::value) { 171 auto& id = reinterpret_cast<NodeId&>(value); 172 id = function(id); 173 } 174 } 175 #endif 176 }; 177 } // namespace Rosen 178 } // namespace OHOS 179 180 #endif // ROSEN_RENDER_SERVICE_BASE_COMMAND_RS_COMMAND_TEMPLATES_H 181