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 ROSEN_INSTANTIATE_COMMAND_TEMPLATE 37 #define ADD_COMMAND(ALIAS, TYPE) \ 38 using ALIAS = RSCommandTemplate<TYPE>; \ 39 template class RSCommandTemplate<TYPE>; 40 #else 41 #define ADD_COMMAND(ALIAS, TYPE) using ALIAS = RSCommandTemplate<TYPE>; 42 #endif 43 44 template<RSCommandPermissionType permissionType, uint16_t commandType, uint16_t commandSubType, auto processFunc, 45 typename... Params> 46 class RSCommandTemplate : public RSCommand { 47 public: RSCommandTemplate(const Params &...params)48 RSCommandTemplate(const Params&... params) : params_(params...) {} RSCommandTemplate(std::tuple<Params...> && params)49 RSCommandTemplate(std::tuple<Params...>&& params) : params_(std::move(params)) {} 50 ~RSCommandTemplate() override = default; 51 GetAccessPermission()52 RSCommandPermissionType GetAccessPermission() const override 53 { 54 return permissionType; 55 } 56 GetType()57 uint16_t GetType() const override 58 { 59 return commandType; 60 } GetSubType()61 uint16_t GetSubType() const override 62 { 63 return commandSubType; 64 } 65 GetDrawCmdList()66 std::shared_ptr<Drawing::DrawCmdList> GetDrawCmdList() const override 67 { 68 if constexpr (std::tuple_size<decltype(params_)>::value > 1) { 69 using ptrType = typename std::tuple_element<1, decltype(params_)>::type; 70 if constexpr (std::is_same<std::shared_ptr<Drawing::DrawCmdList>, ptrType>::value) { 71 return std::get<1>(params_); 72 } else if constexpr (std::is_same<std::shared_ptr<RSRenderModifier>, ptrType>::value) { 73 auto& modifier = std::get<1>(params_); 74 if (modifier) { 75 return modifier->GetPropertyDrawCmdList(); 76 } 77 } 78 } 79 return nullptr; 80 } 81 GetNodeId()82 NodeId GetNodeId() const override 83 { 84 using idType = typename std::tuple_element<0, decltype(params_)>::type; 85 if (std::is_same<NodeId, idType>::value) { 86 return std::get<0>(params_); 87 } 88 return 0; // invalidId 89 } 90 GetToken()91 uint64_t GetToken() const override 92 { 93 if constexpr (std::tuple_size<decltype(params_)>::value > 3) { // 3:For RSAnimationCallback 94 using aniIdType = typename std::tuple_element<1, decltype(params_)>::type; // 1:animationId 95 using tokenType = typename std::tuple_element<2, decltype(params_)>::type; // 2:token 96 if (std::is_same<AnimationId, aniIdType>::value && std::is_same<uint64_t, tokenType>::value) { 97 return std::get<2>(params_); // 2:return token 98 } 99 } 100 return 0; // invalidId 101 } 102 Process(RSContext & context)103 void Process(RSContext& context) override 104 { 105 // expand the tuple to function parameters 106 std::apply([&context](auto&... args) { return (*processFunc)(context, args...); }, params_); 107 } 108 Marshalling(Parcel & parcel)109 bool Marshalling(Parcel& parcel) const override 110 { 111 return RSMarshallingHelper::Marshalling(parcel, commandType) && 112 RSMarshallingHelper::Marshalling(parcel, commandSubType) && 113 std::apply([&parcel](const auto&... args) { return RSMarshallingHelper::Marshalling(parcel, args...); }, 114 params_); 115 }; 116 Unmarshalling(Parcel & parcel)117 [[nodiscard]] static RSCommand* Unmarshalling(Parcel& parcel) 118 { 119 std::tuple<Params...> params; 120 if (!std::apply( 121 [&parcel](auto&... args) { return RSMarshallingHelper::Unmarshalling(parcel, args...); }, params)) { 122 return nullptr; 123 } 124 return new RSCommandTemplate(std::move(params)); 125 } 126 127 static inline RSCommandRegister<commandType, commandSubType, Unmarshalling> registry; 128 129 private: 130 std::tuple<Params...> params_; 131 132 #ifdef RS_PROFILER_ENABLED Patch(PatchFunction function)133 void Patch(PatchFunction function) override 134 { 135 PatchParameters(function, params_, std::make_index_sequence<std::tuple_size_v<decltype(params_)>> {}); 136 } 137 138 template<typename T, std::size_t... Index> PatchParameters(PatchFunction function,T & params,std::index_sequence<Index...>)139 static void PatchParameters(PatchFunction function, T& params, std::index_sequence<Index...>) 140 { 141 (PatchParameter(function, std::get<Index>(params)), ...); 142 } 143 144 template<typename T> PatchParameter(PatchFunction function,T & value)145 static void PatchParameter(PatchFunction function, T& value) 146 { 147 if (std::is_same<NodeId, T>::value || std::is_same<AnimationId, T>::value || 148 std::is_same<PropertyId, T>::value) { 149 auto& id = reinterpret_cast<NodeId&>(value); 150 id = function(id); 151 } 152 } 153 #endif 154 }; 155 } // namespace Rosen 156 } // namespace OHOS 157 158 #endif // ROSEN_RENDER_SERVICE_BASE_COMMAND_RS_COMMAND_TEMPLATES_H 159