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 #include "util/property_util.h"
17
18 #include <PropertyTools/core_metadata.inl>
19 #include <cinttypes>
20
21 #include <base/math/vector.h>
22 #include <core/log.h>
23 #include <core/property/intf_property_handle.h>
24 #include <core/property/property_types.h>
25
26 #include "util/component_util_functions.h"
27 #include "util/json_util.h"
28 #include "util/string_util.h"
29
30 CORE_BEGIN_NAMESPACE()
31 static constexpr inline bool operator==(const Property& lhs, const Property& rhs) noexcept
32 {
33 return (lhs.type == rhs.type) && (lhs.hash == rhs.hash) && (lhs.name == rhs.name);
34 }
35 CORE_END_NAMESPACE()
36
37 CORE3D_BEGIN_NAMESPACE()
38 using namespace BASE_NS;
39 using namespace CORE_NS;
40
41 namespace {
GetPropertyTypeByteSize(const PropertyTypeDecl & typeDecl)42 uint32_t GetPropertyTypeByteSize(const PropertyTypeDecl& typeDecl)
43 {
44 uint32_t byteSize = 0; // zero means that un-supported property type
45 switch (typeDecl) {
46 case PropertyType::UINT32_T:
47 case PropertyType::INT32_T:
48 case PropertyType::FLOAT_T:
49 case PropertyType::BOOL_T:
50 byteSize = sizeof(uint32_t);
51 break;
52 case PropertyType::UVEC2_T:
53 case PropertyType::IVEC2_T:
54 case PropertyType::VEC2_T:
55 byteSize = sizeof(Math::UVec2);
56 break;
57 case PropertyType::UVEC3_T:
58 case PropertyType::IVEC3_T:
59 case PropertyType::VEC3_T:
60 byteSize = sizeof(Math::UVec3);
61 break;
62 case PropertyType::UVEC4_T:
63 case PropertyType::IVEC4_T:
64 case PropertyType::VEC4_T:
65 byteSize = sizeof(Math::UVec4);
66 break;
67 case PropertyType::MAT3X3_T:
68 byteSize = sizeof(Math::Mat3X3);
69 break;
70 case PropertyType::MAT4X4_T:
71 byteSize = sizeof(Math::Mat4X4);
72 break;
73 default:
74 break;
75 }
76 return byteSize;
77 }
78
GetMetaData(const PropertyTypeDecl & typeDecl)79 constexpr MetaData GetMetaData(const PropertyTypeDecl& typeDecl)
80 {
81 switch (typeDecl) {
82 case PropertyType::UINT32_T:
83 return PropertyType::MetaDataFrom<uint32_t>(nullptr);
84 case PropertyType::INT32_T:
85 return PropertyType::MetaDataFrom<int32_t>(nullptr);
86 case PropertyType::FLOAT_T:
87 return PropertyType::MetaDataFrom<float>(nullptr);
88
89 case PropertyType::BOOL_T:
90 return PropertyType::MetaDataFrom<bool>(nullptr);
91
92 case PropertyType::UVEC2_T:
93 return PropertyType::MetaDataFrom<Math::UVec2>(nullptr);
94 case PropertyType::IVEC2_T:
95 return PropertyType::MetaDataFrom<Math::IVec2>(nullptr);
96 case PropertyType::VEC2_T:
97 return PropertyType::MetaDataFrom<Math::Vec2>(nullptr);
98
99 case PropertyType::UVEC3_T:
100 return PropertyType::MetaDataFrom<Math::UVec3>(nullptr);
101 case PropertyType::IVEC3_T:
102 return PropertyType::MetaDataFrom<Math::IVec3>(nullptr);
103 case PropertyType::VEC3_T:
104 return PropertyType::MetaDataFrom<Math::Vec3>(nullptr);
105
106 case PropertyType::UVEC4_T:
107 return PropertyType::MetaDataFrom<Math::UVec4>(nullptr);
108 case PropertyType::IVEC4_T:
109 return PropertyType::MetaDataFrom<Math::IVec4>(nullptr);
110 case PropertyType::VEC4_T:
111 return PropertyType::MetaDataFrom<Math::Vec4>(nullptr);
112
113 case PropertyType::MAT3X3_T:
114 return PropertyType::MetaDataFrom<Math::Mat3X3>(nullptr);
115 case PropertyType::MAT4X4_T:
116 return PropertyType::MetaDataFrom<Math::Mat4X4>(nullptr);
117 default:
118 break;
119 }
120 return {};
121 }
122 } // namespace
123
CustomPropertyPodContainer(size_t reserveByteSize)124 CustomPropertyPodContainer::CustomPropertyPodContainer(size_t reserveByteSize)
125 {
126 data_.reserve(reserveByteSize);
127 }
128
PropertyCount() const129 size_t CustomPropertyPodContainer::PropertyCount() const
130 {
131 return metaData_.size();
132 }
133
MetaData(size_t index) const134 const Property* CustomPropertyPodContainer::MetaData(size_t index) const
135 {
136 if (index < metaData_.size()) {
137 return &metaData_[index];
138 }
139
140 return nullptr;
141 }
142
MetaData() const143 array_view<const Property> CustomPropertyPodContainer::MetaData() const
144 {
145 return { metaData_ };
146 }
147
Type() const148 uint64_t CustomPropertyPodContainer::Type() const
149 {
150 return 0;
151 }
152
Create() const153 IPropertyHandle* CustomPropertyPodContainer::Create() const
154 {
155 return nullptr;
156 }
157
Clone(const IPropertyHandle *) const158 IPropertyHandle* CustomPropertyPodContainer::Clone(const IPropertyHandle* /* src */) const
159 {
160 return nullptr;
161 }
162
Release(IPropertyHandle *) const163 void CustomPropertyPodContainer::Release(IPropertyHandle* /* handle */) const {}
164
Reset()165 void CustomPropertyPodContainer::Reset()
166 {
167 metaStrings_.clear();
168 metaData_.clear();
169 data_.clear();
170 }
171
ReservePropertyCount(size_t propertyCount)172 void CustomPropertyPodContainer::ReservePropertyCount(size_t propertyCount)
173 {
174 reservePropertyCount_ = propertyCount;
175 metaStrings_.reserve(reservePropertyCount_);
176 metaData_.reserve(reservePropertyCount_);
177 }
178
179 // CustomProperties IPropertyHandle
Owner() const180 const IPropertyApi* CustomPropertyPodContainer::Owner() const
181 {
182 return this;
183 }
184
Size() const185 size_t CustomPropertyPodContainer::Size() const
186 {
187 return data_.size();
188 }
189
RLock() const190 const void* CustomPropertyPodContainer::RLock() const
191 {
192 return data_.data();
193 }
194
RUnlock() const195 void CustomPropertyPodContainer::RUnlock() const {}
196
WLock()197 void* CustomPropertyPodContainer::WLock()
198 {
199 return data_.data();
200 }
201
WUnlock()202 void CustomPropertyPodContainer::WUnlock() {}
203
204 //
205
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl)206 void CustomPropertyPodContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
207 const uintptr_t offset, const PropertyTypeDecl& typeDecl)
208 {
209 const size_t byteSize = GetPropertyTypeByteSize(typeDecl);
210 const bool reserved = (metaStrings_.size() < reservePropertyCount_);
211 if ((byteSize > 0) && reserved) {
212 metaStrings_.push_back({ string { propertyName }, string { displayName } });
213 const auto& strings = metaStrings_.back();
214 const Property meta {
215 strings.name, // name
216 FNV1aHash(strings.name.data(), strings.name.size()), // hash
217 typeDecl, // type
218 1U, // count
219 byteSize, // size
220 offset, // offset
221 strings.displayName, // displayName
222 0U, // flags
223 GetMetaData(typeDecl), // metaData
224 };
225 metaData_.push_back(meta);
226 data_.resize(Math::max(data_.size(), meta.offset + meta.size));
227 } else {
228 CORE_LOG_W("unsupported property addition for custom property POD container");
229 }
230 }
231
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl,const array_view<const uint8_t> data)232 void CustomPropertyPodContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
233 const uintptr_t offset, const PropertyTypeDecl& typeDecl, const array_view<const uint8_t> data)
234 {
235 const size_t byteSize = GetPropertyTypeByteSize(typeDecl);
236 const bool reserved = (metaStrings_.size() < reservePropertyCount_);
237 if ((byteSize > 0) && reserved) {
238 metaStrings_.push_back({ string { propertyName }, string { displayName } });
239 const auto& strings = metaStrings_.back();
240 const Property meta {
241 strings.name, // name
242 FNV1aHash(strings.name.data(), strings.name.size()), // hash
243 typeDecl, // type
244 1U, // count
245 byteSize, // size
246 offset, // offset
247 strings.displayName, // displayName
248 0U, // flags
249 GetMetaData(typeDecl), // metaData
250 };
251 metaData_.push_back(meta);
252 data_.resize(Math::max(data_.size(), meta.offset + meta.size));
253 if (data.size_bytes() == byteSize) {
254 CloneData(data_.data() + offset, data_.size_in_bytes() - offset, data.data(), data.size_bytes());
255 }
256 } else {
257 CORE_LOG_W("unsupported property addition for custom property POD container");
258 }
259 }
260
SetValue(const string_view propertyName,const array_view<const uint8_t> data)261 bool CustomPropertyPodContainer::SetValue(const string_view propertyName, const array_view<const uint8_t> data)
262 {
263 for (const auto& metaRef : metaData_) {
264 if ((metaRef.name == propertyName) && (metaRef.size == data.size_bytes())) {
265 return SetValue(metaRef.offset, data);
266 }
267 }
268 return false;
269 }
270
SetValue(const size_t byteOffset,const array_view<const uint8_t> data)271 bool CustomPropertyPodContainer::SetValue(const size_t byteOffset, const array_view<const uint8_t> data)
272 {
273 return CloneData(data_.data() + byteOffset,
274 (byteOffset < data_.size_in_bytes()) ? (data_.size_in_bytes() - byteOffset) : 0U, data.data(),
275 data.size_bytes());
276 }
277
GetValue(const string_view propertyName) const278 array_view<const uint8_t> CustomPropertyPodContainer::GetValue(const string_view propertyName) const
279 {
280 for (const auto& metaRef : metaData_) {
281 if (metaRef.name == propertyName) {
282 const size_t endData = metaRef.offset + metaRef.size;
283 if (endData <= data_.size_in_bytes()) {
284 return { data_.data() + metaRef.offset, metaRef.size };
285 }
286 }
287 }
288 return {};
289 }
290
GetByteSize() const291 size_t CustomPropertyPodContainer::GetByteSize() const
292 {
293 return data_.size_in_bytes();
294 }
295
CopyValues(const CustomPropertyPodContainer & other)296 void CustomPropertyPodContainer::CopyValues(const CustomPropertyPodContainer& other)
297 {
298 // copy values with matching type and name
299 for (const auto& otherProperty : other.MetaData()) {
300 if (auto pos = std::find(metaData_.cbegin(), metaData_.cend(), otherProperty); pos != metaData_.cend()) {
301 SetValue(pos->offset, other.GetValue(otherProperty.name));
302 }
303 }
304 }
305
306 //
307
GetPropertyTypeDeclaration(const string_view type)308 PropertyTypeDecl CustomPropertyPodHelper::GetPropertyTypeDeclaration(const string_view type)
309 {
310 if (type == "vec4") {
311 return PropertyType::VEC4_T;
312 } else if (type == "uvec4") {
313 return PropertyType::UVEC4_T;
314 } else if (type == "ivec4") {
315 return PropertyType::IVEC4_T;
316 } else if (type == "vec3") {
317 return PropertyType::VEC3_T;
318 } else if (type == "uvec3") {
319 return PropertyType::UVEC3_T;
320 } else if (type == "ivec3") {
321 return PropertyType::IVEC3_T;
322 } else if (type == "vec2") {
323 return PropertyType::VEC2_T;
324 } else if (type == "uvec2") {
325 return PropertyType::UVEC2_T;
326 } else if (type == "ivec2") {
327 return PropertyType::IVEC2_T;
328 } else if (type == "float") {
329 return PropertyType::FLOAT_T;
330 } else if (type == "uint") {
331 return PropertyType::UINT32_T;
332 } else if (type == "int") {
333 return PropertyType::INT32_T;
334 } else if (type == "bool") {
335 return PropertyType::BOOL_T;
336 } else if (type == "mat3x3") {
337 return PropertyType::MAT3X3_T;
338 } else if (type == "mat4x4") {
339 return PropertyType::MAT4X4_T;
340 } else {
341 CORE_LOG_W("CORE3D_VALIDATION: Invalid property type only int, uint, float, bool, and XvecX variants, and "
342 "mat3x3 and mat4x4 are supported");
343 }
344 // NOTE: does not handle invalid types
345 return PropertyType::INVALID;
346 }
347
GetPropertyTypeAlignment(const PropertyTypeDecl & propertyType)348 size_t CustomPropertyPodHelper::GetPropertyTypeAlignment(const PropertyTypeDecl& propertyType)
349 {
350 size_t align = 1U;
351 static_assert(sizeof(float) == sizeof(uint32_t) && sizeof(float) == sizeof(int32_t));
352 switch (propertyType) {
353 case PropertyType::FLOAT_T:
354 [[fallthrough]];
355 case PropertyType::UINT32_T:
356 [[fallthrough]];
357 case PropertyType::INT32_T:
358 [[fallthrough]];
359 case PropertyType::BOOL_T:
360 align = sizeof(float);
361 break;
362 case PropertyType::VEC2_T:
363 [[fallthrough]];
364 case PropertyType::UVEC2_T:
365 [[fallthrough]];
366 case PropertyType::IVEC2_T:
367 align = sizeof(float) * 2U;
368 break;
369 case PropertyType::VEC3_T:
370 [[fallthrough]];
371 case PropertyType::UVEC3_T:
372 [[fallthrough]];
373 case PropertyType::IVEC3_T:
374 [[fallthrough]];
375 case PropertyType::VEC4_T:
376 [[fallthrough]];
377 case PropertyType::UVEC4_T:
378 [[fallthrough]];
379 case PropertyType::IVEC4_T:
380 align = sizeof(float) * 4U;
381 break;
382 case PropertyType::MAT3X3_T:
383 align = sizeof(float) * 4U * 3U;
384 break;
385 case PropertyType::MAT4X4_T:
386 align = sizeof(float) * 4U * 4U;
387 break;
388 }
389 return align;
390 }
391
SetCustomPropertyBlobValue(const PropertyTypeDecl & propertyType,const json::value * value,CustomPropertyPodContainer & customProperties,const size_t offset)392 void CustomPropertyPodHelper::SetCustomPropertyBlobValue(const PropertyTypeDecl& propertyType, const json::value* value,
393 CustomPropertyPodContainer& customProperties, const size_t offset)
394 {
395 if (propertyType == PropertyType::VEC4_T) {
396 Math::Vec4 val;
397 FromJson(*value, val);
398 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
399 } else if (propertyType == PropertyType::UVEC4_T) {
400 Math::UVec4 val;
401 FromJson(*value, val);
402 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
403 } else if (propertyType == PropertyType::IVEC4_T) {
404 Math::IVec4 val;
405 FromJson(*value, val);
406 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
407 } else if (propertyType == PropertyType::VEC3_T) {
408 Math::Vec3 val;
409 FromJson(*value, val);
410 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
411 } else if (propertyType == PropertyType::UVEC3_T) {
412 Math::UVec3 val;
413 FromJson(*value, val);
414 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
415 } else if (propertyType == PropertyType::IVEC3_T) {
416 Math::IVec3 val;
417 FromJson(*value, val);
418 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
419 } else if (propertyType == PropertyType::VEC2_T) {
420 Math::Vec2 val;
421 FromJson(*value, val);
422 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
423 } else if (propertyType == PropertyType::UVEC2_T) {
424 Math::UVec2 val;
425 FromJson(*value, val);
426 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
427 } else if (propertyType == PropertyType::IVEC2_T) {
428 Math::IVec2 val;
429 FromJson(*value, val);
430 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
431 } else if (propertyType == PropertyType::FLOAT_T) {
432 float val;
433 FromJson(*value, val);
434 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
435 } else if (propertyType == PropertyType::UINT32_T) {
436 uint32_t val;
437 FromJson(*value, val);
438 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
439 } else if (propertyType == PropertyType::INT32_T) {
440 int32_t val;
441 FromJson(*value, val);
442 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
443 } else if (propertyType == PropertyType::BOOL_T) {
444 bool tmpVal;
445 FromJson(*value, tmpVal);
446 uint32_t val = tmpVal;
447 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
448 } else if (propertyType == PropertyType::MAT3X3_T) {
449 Math::Mat3X3 val;
450 FromJson(*value, val);
451 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat3X3) });
452 } else if (propertyType == PropertyType::MAT4X4_T) {
453 Math::Mat4X4 val;
454 FromJson(*value, val);
455 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat4X4) });
456 } else {
457 CORE_LOG_W("CORE3D_VALIDATION: Invalid property type only int, uint, float, and XvecX variants supported");
458 }
459 // NOTE: does not handle invalid types
460 }
461
462 CORE3D_END_NAMESPACE()
463