• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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