18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef UTIL__PROPERTY_UTIL_H
178bf80f4bSopenharmony_ci#define UTIL__PROPERTY_UTIL_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <base/containers/string.h>
208bf80f4bSopenharmony_ci#include <base/containers/vector.h>
218bf80f4bSopenharmony_ci#include <core/json/json.h>
228bf80f4bSopenharmony_ci#include <core/property/intf_property_api.h>
238bf80f4bSopenharmony_ci#include <core/property/intf_property_handle.h>
248bf80f4bSopenharmony_ci#include <core/property/property_handle_util.h>
258bf80f4bSopenharmony_ci#include <core/property/property_types.h>
268bf80f4bSopenharmony_ci#include <render/namespace.h>
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
298bf80f4bSopenharmony_ci/*
308bf80f4bSopenharmony_ci * Implements a custom property blob for simple PODs e.g. shader custom shader properties which are stored in a single
318bf80f4bSopenharmony_ci * byte data.
328bf80f4bSopenharmony_ci * Supports float -> vec4 with u/i -variants
338bf80f4bSopenharmony_ci * - Single byte data blob
348bf80f4bSopenharmony_ci * - Multiple offsets customized properties for that data
358bf80f4bSopenharmony_ci * - Can only hold simple data within a single byte-blob
368bf80f4bSopenharmony_ci *
378bf80f4bSopenharmony_ci * NOTE: One must use Reserve(propertyCount) before adding properties
388bf80f4bSopenharmony_ci */
398bf80f4bSopenharmony_ciclass CustomPropertyPodContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
408bf80f4bSopenharmony_cipublic:
418bf80f4bSopenharmony_ci    CustomPropertyPodContainer() = default;
428bf80f4bSopenharmony_ci    /* Reserve a predefined byte size to hold the property data */
438bf80f4bSopenharmony_ci    explicit CustomPropertyPodContainer(size_t reserveByteSize);
448bf80f4bSopenharmony_ci
458bf80f4bSopenharmony_ci    ~CustomPropertyPodContainer() override = default;
468bf80f4bSopenharmony_ci
478bf80f4bSopenharmony_ci    CustomPropertyPodContainer(const CustomPropertyPodContainer& other) = delete;
488bf80f4bSopenharmony_ci    CustomPropertyPodContainer(CustomPropertyPodContainer&& other) noexcept;
498bf80f4bSopenharmony_ci    CustomPropertyPodContainer& operator=(const CustomPropertyPodContainer& other) = delete;
508bf80f4bSopenharmony_ci    CustomPropertyPodContainer& operator=(CustomPropertyPodContainer&& other) noexcept;
518bf80f4bSopenharmony_ci
528bf80f4bSopenharmony_ci    // IPropertyHandle
538bf80f4bSopenharmony_ci    const CORE_NS::IPropertyApi* Owner() const override;
548bf80f4bSopenharmony_ci    size_t Size() const override;
558bf80f4bSopenharmony_ci    const void* RLock() const override;
568bf80f4bSopenharmony_ci    void RUnlock() const override;
578bf80f4bSopenharmony_ci    void* WLock() override;
588bf80f4bSopenharmony_ci    void WUnlock() override;
598bf80f4bSopenharmony_ci
608bf80f4bSopenharmony_ci    // IPropertyApi
618bf80f4bSopenharmony_ci    size_t PropertyCount() const override;
628bf80f4bSopenharmony_ci    const CORE_NS::Property* MetaData(size_t index) const override;
638bf80f4bSopenharmony_ci    BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
648bf80f4bSopenharmony_ci    uint64_t Type() const override;
658bf80f4bSopenharmony_ci    CORE_NS::IPropertyHandle* Create() const override;
668bf80f4bSopenharmony_ci    CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
678bf80f4bSopenharmony_ci    void Release(CORE_NS::IPropertyHandle* handle) const override;
688bf80f4bSopenharmony_ci
698bf80f4bSopenharmony_ci    // Reset, to remove old properties
708bf80f4bSopenharmony_ci    void Reset();
718bf80f4bSopenharmony_ci    // Reserve before adding any properties
728bf80f4bSopenharmony_ci    void ReservePropertyCount(size_t propertyCount);
738bf80f4bSopenharmony_ci
748bf80f4bSopenharmony_ci    void AddOffsetProperty(const BASE_NS::string_view propertyName, const BASE_NS::string_view displayName,
758bf80f4bSopenharmony_ci        const uintptr_t offset, const CORE_NS::PropertyTypeDecl& typeDecl);
768bf80f4bSopenharmony_ci    void AddOffsetProperty(const BASE_NS::string_view propertyName, const BASE_NS::string_view displayName,
778bf80f4bSopenharmony_ci        const uintptr_t offset, const CORE_NS::PropertyTypeDecl& typeDecl,
788bf80f4bSopenharmony_ci        const BASE_NS::array_view<const uint8_t> data);
798bf80f4bSopenharmony_ci    bool SetValue(const BASE_NS::string_view propertyName, const BASE_NS::array_view<uint8_t> data);
808bf80f4bSopenharmony_ci    bool SetValue(const size_t byteOffset, const BASE_NS::array_view<uint8_t> data);
818bf80f4bSopenharmony_ci    BASE_NS::array_view<const uint8_t> GetValue(const BASE_NS::string_view name) const;
828bf80f4bSopenharmony_ci    // byte size of the data container
838bf80f4bSopenharmony_ci    size_t GetByteSize() const;
848bf80f4bSopenharmony_ci    BASE_NS::array_view<const uint8_t> GetData() const;
858bf80f4bSopenharmony_ci
868bf80f4bSopenharmony_ci    // Uses property handle util
878bf80f4bSopenharmony_ci    template<typename T>
888bf80f4bSopenharmony_ci    bool SetValue(const BASE_NS::string_view propertyName, T&& propertyValue)
898bf80f4bSopenharmony_ci    {
908bf80f4bSopenharmony_ci        CORE_NS::SetPropertyValue<T>(*this, propertyName, propertyValue);
918bf80f4bSopenharmony_ci    }
928bf80f4bSopenharmony_ci    template<typename T>
938bf80f4bSopenharmony_ci    T GetValue(const BASE_NS::string_view propertyName)
948bf80f4bSopenharmony_ci    {
958bf80f4bSopenharmony_ci        return CORE_NS::GetPropertyValue<T>(*this, propertyName);
968bf80f4bSopenharmony_ci    }
978bf80f4bSopenharmony_ci
988bf80f4bSopenharmony_ciprivate:
998bf80f4bSopenharmony_ci    struct Strings {
1008bf80f4bSopenharmony_ci        BASE_NS::string name;
1018bf80f4bSopenharmony_ci        BASE_NS::string displayName;
1028bf80f4bSopenharmony_ci    };
1038bf80f4bSopenharmony_ci    BASE_NS::vector<Strings> metaStrings_;
1048bf80f4bSopenharmony_ci    BASE_NS::vector<CORE_NS::Property> metaData_;
1058bf80f4bSopenharmony_ci    BASE_NS::vector<uint8_t> data_;
1068bf80f4bSopenharmony_ci
1078bf80f4bSopenharmony_ci    size_t reservePropertyCount_ { 0 };
1088bf80f4bSopenharmony_ci};
1098bf80f4bSopenharmony_ci
1108bf80f4bSopenharmony_ci/*
1118bf80f4bSopenharmony_ci * CustomPropertyDataHelper
1128bf80f4bSopenharmony_ci */
1138bf80f4bSopenharmony_ciclass CustomPropertyPodHelper final {
1148bf80f4bSopenharmony_cipublic:
1158bf80f4bSopenharmony_ci    CustomPropertyPodHelper() = default;
1168bf80f4bSopenharmony_ci    ~CustomPropertyPodHelper() = default;
1178bf80f4bSopenharmony_ci
1188bf80f4bSopenharmony_ci    static CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(const BASE_NS::string_view type);
1198bf80f4bSopenharmony_ci    static size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
1208bf80f4bSopenharmony_ci    static void SetCustomPropertyBlobValue(const CORE_NS::PropertyTypeDecl& propertyType,
1218bf80f4bSopenharmony_ci        const CORE_NS::json::value* value, CustomPropertyPodContainer& customProperties, const size_t offset);
1228bf80f4bSopenharmony_ci};
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_ci/*
1258bf80f4bSopenharmony_ci * Simple signaller class
1268bf80f4bSopenharmony_ci */
1278bf80f4bSopenharmony_ciclass CustomPropertyWriteSignal {
1288bf80f4bSopenharmony_cipublic:
1298bf80f4bSopenharmony_ci    CustomPropertyWriteSignal() = default;
1308bf80f4bSopenharmony_ci    virtual ~CustomPropertyWriteSignal() = default;
1318bf80f4bSopenharmony_ci
1328bf80f4bSopenharmony_ci    virtual void Signal() = 0;
1338bf80f4bSopenharmony_ci};
1348bf80f4bSopenharmony_ci
1358bf80f4bSopenharmony_ci/*
1368bf80f4bSopenharmony_ci * Implements a custom binding properties.
1378bf80f4bSopenharmony_ci *
1388bf80f4bSopenharmony_ci * NOTE: One must use Reserve(propertyCount) before adding properties
1398bf80f4bSopenharmony_ci */
1408bf80f4bSopenharmony_ciclass CustomPropertyBindingContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
1418bf80f4bSopenharmony_cipublic:
1428bf80f4bSopenharmony_ci    explicit CustomPropertyBindingContainer(CustomPropertyWriteSignal& writeSignal);
1438bf80f4bSopenharmony_ci    ~CustomPropertyBindingContainer() override;
1448bf80f4bSopenharmony_ci
1458bf80f4bSopenharmony_ci    CustomPropertyBindingContainer(const CustomPropertyBindingContainer& other) = delete;
1468bf80f4bSopenharmony_ci    CustomPropertyBindingContainer(CustomPropertyBindingContainer&& other) noexcept;
1478bf80f4bSopenharmony_ci    CustomPropertyBindingContainer& operator=(const CustomPropertyBindingContainer& other) = delete;
1488bf80f4bSopenharmony_ci    CustomPropertyBindingContainer& operator=(CustomPropertyBindingContainer&& other) noexcept;
1498bf80f4bSopenharmony_ci
1508bf80f4bSopenharmony_ci    // IPropertyHandle
1518bf80f4bSopenharmony_ci    const CORE_NS::IPropertyApi* Owner() const override;
1528bf80f4bSopenharmony_ci    size_t Size() const override;
1538bf80f4bSopenharmony_ci    const void* RLock() const override;
1548bf80f4bSopenharmony_ci    void RUnlock() const override;
1558bf80f4bSopenharmony_ci    void* WLock() override;
1568bf80f4bSopenharmony_ci    void WUnlock() override;
1578bf80f4bSopenharmony_ci
1588bf80f4bSopenharmony_ci    // IPropertyApi
1598bf80f4bSopenharmony_ci    size_t PropertyCount() const override;
1608bf80f4bSopenharmony_ci    const CORE_NS::Property* MetaData(size_t index) const override;
1618bf80f4bSopenharmony_ci    BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
1628bf80f4bSopenharmony_ci    uint64_t Type() const override;
1638bf80f4bSopenharmony_ci    CORE_NS::IPropertyHandle* Create() const override;
1648bf80f4bSopenharmony_ci    CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
1658bf80f4bSopenharmony_ci    void Release(CORE_NS::IPropertyHandle* handle) const override;
1668bf80f4bSopenharmony_ci
1678bf80f4bSopenharmony_ci    // Reserve before adding any properties
1688bf80f4bSopenharmony_ci    void ReservePropertyCount(size_t propertyCount);
1698bf80f4bSopenharmony_ci
1708bf80f4bSopenharmony_ci    void AddOffsetProperty(const BASE_NS::string_view propertyName, const BASE_NS::string_view displayName,
1718bf80f4bSopenharmony_ci        const uintptr_t offset, const CORE_NS::PropertyTypeDecl& typeDecl);
1728bf80f4bSopenharmony_ci    // byte size of the data container
1738bf80f4bSopenharmony_ci    size_t GetByteSize() const;
1748bf80f4bSopenharmony_ci
1758bf80f4bSopenharmony_ci    // Uses property handle util
1768bf80f4bSopenharmony_ci    template<typename T>
1778bf80f4bSopenharmony_ci    bool SetValue(const BASE_NS::string_view propertyName, T&& propertyValue)
1788bf80f4bSopenharmony_ci    {
1798bf80f4bSopenharmony_ci        CORE_NS::SetPropertyValue<T>(*this, propertyName, propertyValue);
1808bf80f4bSopenharmony_ci    }
1818bf80f4bSopenharmony_ci    template<typename T>
1828bf80f4bSopenharmony_ci    T GetValue(const BASE_NS::string_view propertyName)
1838bf80f4bSopenharmony_ci    {
1848bf80f4bSopenharmony_ci        return CORE_NS::GetPropertyValue<T>(*this, propertyName);
1858bf80f4bSopenharmony_ci    }
1868bf80f4bSopenharmony_ci    template<typename T>
1878bf80f4bSopenharmony_ci    T GetValue(size_t index)
1888bf80f4bSopenharmony_ci    {
1898bf80f4bSopenharmony_ci        // the casting type needs to be known
1908bf80f4bSopenharmony_ci        if ((index < metaData_.size())) {
1918bf80f4bSopenharmony_ci            const auto& meta = metaData_[index];
1928bf80f4bSopenharmony_ci            CORE_ASSERT(meta.offset < data_.size_in_bytes());
1938bf80f4bSopenharmony_ci            if (void* ptr = (void*)(data_.data() + meta.offset); ptr) {
1948bf80f4bSopenharmony_ci                return *((T*)(ptr));
1958bf80f4bSopenharmony_ci            }
1968bf80f4bSopenharmony_ci        }
1978bf80f4bSopenharmony_ci        return {};
1988bf80f4bSopenharmony_ci    }
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_ciprivate:
2018bf80f4bSopenharmony_ci    // signal when value is written
2028bf80f4bSopenharmony_ci    CustomPropertyWriteSignal& writeSignal_;
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ci    struct Strings {
2058bf80f4bSopenharmony_ci        BASE_NS::string name;
2068bf80f4bSopenharmony_ci        BASE_NS::string displayName;
2078bf80f4bSopenharmony_ci    };
2088bf80f4bSopenharmony_ci    BASE_NS::vector<Strings> metaStrings_;
2098bf80f4bSopenharmony_ci    BASE_NS::vector<CORE_NS::Property> metaData_;
2108bf80f4bSopenharmony_ci    BASE_NS::vector<uint8_t> data_;
2118bf80f4bSopenharmony_ci    size_t reservePropertyCount_ { 0 };
2128bf80f4bSopenharmony_ci};
2138bf80f4bSopenharmony_ci
2148bf80f4bSopenharmony_ci/*
2158bf80f4bSopenharmony_ci * CustomBindingPropertyHelper
2168bf80f4bSopenharmony_ci */
2178bf80f4bSopenharmony_ciclass CustomPropertyBindingHelper final {
2188bf80f4bSopenharmony_cipublic:
2198bf80f4bSopenharmony_ci    CustomPropertyBindingHelper() = default;
2208bf80f4bSopenharmony_ci    ~CustomPropertyBindingHelper() = default;
2218bf80f4bSopenharmony_ci
2228bf80f4bSopenharmony_ci    static CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(const BASE_NS::string_view type);
2238bf80f4bSopenharmony_ci    static size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
2248bf80f4bSopenharmony_ci};
2258bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
2268bf80f4bSopenharmony_ci
2278bf80f4bSopenharmony_ci#endif // UTIL__PROPERTY_UTIL_H