1 /*
2 * Copyright (c) 2022 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 RENDER_UTIL_PROPERTY_UTIL_H
17 #define RENDER_UTIL_PROPERTY_UTIL_H
18
19 #include <base/containers/string.h>
20 #include <base/containers/vector.h>
21 #include <core/json/json.h>
22 #include <core/property/intf_property_api.h>
23 #include <core/property/intf_property_handle.h>
24 #include <core/property/property_handle_util.h>
25 #include <core/property/property_types.h>
26 #include <render/namespace.h>
27
RENDER_BEGIN_NAMESPACE()28 RENDER_BEGIN_NAMESPACE()
29 /*
30 * Implements a custom property blob for simple PODs e.g. shader custom shader properties which are stored in a single
31 * byte data.
32 * Supports float -> vec4 with u/i -variants
33 * - Single byte data blob
34 * - Multiple offsets customized properties for that data
35 * - Can only hold simple data within a single byte-blob
36 *
37 * NOTE: One must use Reserve(propertyCount) before adding properties
38 */
39 class CustomPropertyPodContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
40 public:
41 CustomPropertyPodContainer() = default;
42 /* Reserve a predefined byte size to hold the property data */
43 explicit CustomPropertyPodContainer(size_t reserveByteSize);
44
45 ~CustomPropertyPodContainer() override = default;
46
47 CustomPropertyPodContainer(const CustomPropertyPodContainer& other) = delete;
48 CustomPropertyPodContainer(CustomPropertyPodContainer&& other) noexcept = delete;
49 CustomPropertyPodContainer& operator=(const CustomPropertyPodContainer& other) = delete;
50 CustomPropertyPodContainer& operator=(CustomPropertyPodContainer&& other) noexcept = delete;
51
52 // IPropertyHandle
53 const CORE_NS::IPropertyApi* Owner() const override;
54 size_t Size() const override;
55 const void* RLock() const override;
56 void RUnlock() const override;
57 void* WLock() override;
58 void WUnlock() override;
59
60 // IPropertyApi
61 size_t PropertyCount() const override;
62 const CORE_NS::Property* MetaData(size_t index) const override;
63 BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
64 uint64_t Type() const override;
65 CORE_NS::IPropertyHandle* Create() const override;
66 CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
67 void Release(CORE_NS::IPropertyHandle* handle) const override;
68
69 // Reset, to remove old properties
70 void Reset();
71 // Reserve before adding any properties
72 void ReservePropertyCount(size_t propertyCount);
73
74 void AddOffsetProperty(BASE_NS::string_view propertyName, BASE_NS::string_view displayName, uintptr_t offset,
75 const CORE_NS::PropertyTypeDecl& typeDecl);
76 void AddOffsetProperty(BASE_NS::string_view propertyName, BASE_NS::string_view displayName, uintptr_t offset,
77 const CORE_NS::PropertyTypeDecl& typeDecl, BASE_NS::array_view<const uint8_t> data);
78 bool SetValue(BASE_NS::string_view propertyName, BASE_NS::array_view<uint8_t> data);
79 bool SetValue(size_t byteOffset, BASE_NS::array_view<uint8_t> data);
80 BASE_NS::array_view<const uint8_t> GetValue(BASE_NS::string_view name) const;
81 // byte size of the data container
82 size_t GetByteSize() const;
83 BASE_NS::array_view<const uint8_t> GetData() const;
84
85 // Uses property handle util
86 template<typename T>
87 bool SetValue(const BASE_NS::string_view propertyName, T&& propertyValue)
88 {
89 CORE_NS::SetPropertyValue<T>(*this, propertyName, propertyValue);
90 }
91 template<typename T>
92 T GetValue(const BASE_NS::string_view propertyName)
93 {
94 return CORE_NS::GetPropertyValue<T>(*this, propertyName);
95 }
96
97 private:
98 struct Strings {
99 BASE_NS::string name;
100 BASE_NS::string displayName;
101 };
102 BASE_NS::vector<Strings> metaStrings_;
103 BASE_NS::vector<CORE_NS::Property> metaData_;
104 BASE_NS::vector<uint8_t> data_;
105
106 size_t reservePropertyCount_ { 0 };
107 };
108
109 /*
110 * CustomPropertyDataHelper
111 */
112 class CustomPropertyPodHelper final {
113 public:
114 CustomPropertyPodHelper() = default;
115 ~CustomPropertyPodHelper() = default;
116
117 static CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(BASE_NS::string_view type);
118 static size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
119 static void SetCustomPropertyBlobValue(const CORE_NS::PropertyTypeDecl& propertyType,
120 const CORE_NS::json::value* value, CustomPropertyPodContainer& customProperties, size_t offset);
121 };
122
123 /*
124 * Simple signaller class
125 */
126 class CustomPropertyWriteSignal {
127 public:
128 CustomPropertyWriteSignal() = default;
129 virtual ~CustomPropertyWriteSignal() = default;
130
131 virtual void Signal() = 0;
132 };
133
134 /*
135 * Implements a custom binding properties.
136 *
137 * NOTE: One must use Reserve(propertyCount) before adding properties
138 */
139 class CustomPropertyBindingContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
140 public:
141 explicit CustomPropertyBindingContainer(CustomPropertyWriteSignal& writeSignal);
142 ~CustomPropertyBindingContainer() override;
143
144 CustomPropertyBindingContainer(const CustomPropertyBindingContainer& other) = delete;
145 CustomPropertyBindingContainer(CustomPropertyBindingContainer&& other) noexcept = delete;
146 CustomPropertyBindingContainer& operator=(const CustomPropertyBindingContainer& other) = delete;
147 CustomPropertyBindingContainer& operator=(CustomPropertyBindingContainer&& other) noexcept = delete;
148
149 // IPropertyHandle
150 const CORE_NS::IPropertyApi* Owner() const override;
151 size_t Size() const override;
152 const void* RLock() const override;
153 void RUnlock() const override;
154 void* WLock() override;
155 void WUnlock() override;
156
157 // IPropertyApi
158 size_t PropertyCount() const override;
159 const CORE_NS::Property* MetaData(size_t index) const override;
160 BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
161 uint64_t Type() const override;
162 CORE_NS::IPropertyHandle* Create() const override;
163 CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
164 void Release(CORE_NS::IPropertyHandle* handle) const override;
165
166 // Reserve before adding any properties
167 void ReservePropertyCount(size_t propertyCount);
168
169 void AddOffsetProperty(BASE_NS::string_view propertyName, BASE_NS::string_view displayName, uintptr_t offset,
170 const CORE_NS::PropertyTypeDecl& typeDecl);
171 // byte size of the data container
172 size_t GetByteSize() const;
173
174 // Uses property handle util
175 template<typename T>
SetValue(const BASE_NS::string_view propertyName,T && propertyValue)176 bool SetValue(const BASE_NS::string_view propertyName, T&& propertyValue)
177 {
178 CORE_NS::SetPropertyValue<T>(*this, propertyName, propertyValue);
179 }
180 template<typename T>
GetValue(const BASE_NS::string_view propertyName)181 T GetValue(const BASE_NS::string_view propertyName)
182 {
183 return CORE_NS::GetPropertyValue<T>(*this, propertyName);
184 }
185 template<typename T>
GetValue(size_t index)186 T GetValue(size_t index)
187 {
188 // the casting type needs to be known
189 if ((index < metaData_.size())) {
190 const auto& meta = metaData_[index];
191 CORE_ASSERT(meta.offset < data_.size_in_bytes());
192 if (void* ptr = (void*)(data_.data() + meta.offset); ptr) {
193 return *((T*)(ptr));
194 }
195 }
196 return {};
197 }
198
199 private:
200 // signal when value is written
201 CustomPropertyWriteSignal& writeSignal_;
202
203 struct Strings {
204 BASE_NS::string name;
205 BASE_NS::string displayName;
206 };
207 BASE_NS::vector<Strings> metaStrings_;
208 BASE_NS::vector<CORE_NS::Property> metaData_;
209 BASE_NS::vector<uint8_t> data_;
210 size_t reservePropertyCount_ { 0 };
211 };
212
213 /*
214 * CustomBindingPropertyHelper
215 */
216 class CustomPropertyBindingHelper final {
217 public:
218 CustomPropertyBindingHelper() = default;
219 ~CustomPropertyBindingHelper() = default;
220
221 static CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(BASE_NS::string_view type);
222 static size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
223 };
224 RENDER_END_NAMESPACE()
225
226 #endif // RENDER_UTIL_PROPERTY_UTIL_H
227