1 | // Copyright (C) 2020 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | // |
5 | // W A R N I N G |
6 | // ------------- |
7 | // |
8 | // This file is not part of the Qt API. It exists purely as an |
9 | // implementation detail. This header file may change from version to |
10 | // version without notice, or even be removed. |
11 | // |
12 | // We mean it. |
13 | // |
14 | |
15 | #ifndef QQSBCOLLECTION_H |
16 | #define QQSBCOLLECTION_H |
17 | |
18 | #include <QtQuick3DUtils/private/qtquick3dutilsglobal_p.h> |
19 | |
20 | #include <QtCore/qfile.h> |
21 | #include <QtCore/qset.h> |
22 | #include <QtCore/qmap.h> |
23 | |
24 | #include <rhi/qshader.h> |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | class QRhiShaderStage; |
29 | |
30 | class Q_QUICK3DUTILS_EXPORT QQsbCollection |
31 | { |
32 | public: |
33 | virtual ~QQsbCollection(); |
34 | |
35 | struct Q_QUICK3DUTILS_EXPORT Entry |
36 | { |
37 | // 'value' is optional. hashing and comparison are based solely on 'key'. |
38 | Entry() = default; |
39 | explicit Entry(const QByteArray &key) : key(key) |
40 | { |
41 | hashKey = qHash(key); |
42 | } |
43 | Entry(const QByteArray &key, qint64 value) : key(key), value(value) |
44 | { |
45 | hashKey = qHash(key); |
46 | } |
47 | bool isValid() const { return !key.isEmpty(); } |
48 | QByteArray key; |
49 | qint64 value = -1; |
50 | size_t hashKey; |
51 | }; |
52 | |
53 | using FeatureSet = QMap<QByteArray, bool>; // QMap so it is ordered by key |
54 | |
55 | template<typename T> |
56 | static FeatureSet toFeatureSet(const T &ssgFeatureSet) |
57 | { |
58 | FeatureSet ret; |
59 | for (quint32 i = 0, end = T::Count; i != end; ++i) { |
60 | auto def = T::fromIndex(i); |
61 | if (ssgFeatureSet.isSet(def)) |
62 | ret.insert(T::asDefineString(def), true); |
63 | } |
64 | return ret; |
65 | } |
66 | |
67 | struct Q_QUICK3DUTILS_EXPORT EntryDesc { |
68 | QByteArray materialKey; |
69 | FeatureSet featureSet; |
70 | QShader vertShader; |
71 | QShader fragShader; |
72 | QByteArray generateSha() const; |
73 | static QByteArray generateSha(const QByteArray &materialKey, const FeatureSet &featureSet); |
74 | }; |
75 | |
76 | using EntryMap = QSet<Entry>; |
77 | virtual EntryMap availableEntries() const = 0; |
78 | virtual Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) = 0; |
79 | virtual bool (Entry entry, EntryDesc &entryDesc) = 0; |
80 | |
81 | protected: |
82 | enum Version : quint8 |
83 | { |
84 | Unknown, |
85 | One = 0x10, |
86 | Two = 0x20 |
87 | }; |
88 | bool (QDataStream &ds, qint64 *startPos, quint8 *version); |
89 | void (QDataStream &ds, qint64 startPos, quint8 version, quint64 magic); |
90 | bool (QIODevice *device, EntryMap *entries, quint8 *version); |
91 | void (QIODevice *device, const EntryMap &entries); |
92 | }; |
93 | |
94 | Q_DECLARE_TYPEINFO(QQsbCollection::Entry, Q_PRIMITIVE_TYPE); |
95 | |
96 | Q_QUICK3DUTILS_EXPORT QDataStream &operator<<(QDataStream &stream, const QQsbCollection::Entry &entry); |
97 | Q_QUICK3DUTILS_EXPORT QDataStream &operator>>(QDataStream &stream, QQsbCollection::Entry &entry); |
98 | Q_QUICK3DUTILS_EXPORT QDataStream &operator<<(QDataStream &stream, const QQsbCollection::EntryDesc &entryDesc); |
99 | Q_QUICK3DUTILS_EXPORT QDataStream &operator>>(QDataStream &stream, QQsbCollection::EntryDesc &entryDesc); |
100 | |
101 | Q_QUICK3DUTILS_EXPORT size_t qHash(const QQsbCollection::Entry &entry, size_t); |
102 | Q_QUICK3DUTILS_EXPORT bool operator==(const QQsbCollection::Entry &l, const QQsbCollection::Entry &r); |
103 | |
104 | // Simple implementation backed by a hash table. Save and load are explicit and |
105 | // all data is read and written. The file format is compatible with other |
106 | // implementations. |
107 | class Q_QUICK3DUTILS_EXPORT QQsbInMemoryCollection : public QQsbCollection |
108 | { |
109 | public: |
110 | QQsbInMemoryCollection() = default; |
111 | |
112 | EntryMap availableEntries() const override; |
113 | Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override; |
114 | bool (Entry entry, EntryDesc &entryDesc) override; |
115 | |
116 | void clear(); |
117 | |
118 | bool load(const QString &filename); |
119 | bool save(const QString &filename); |
120 | |
121 | private: |
122 | Q_DISABLE_COPY(QQsbInMemoryCollection); |
123 | |
124 | QHash<Entry, EntryDesc> entries; |
125 | }; |
126 | |
127 | // Serial, direct-to/from-QIODevice implementation. |
128 | class Q_QUICK3DUTILS_EXPORT QQsbIODeviceCollection : public QQsbCollection |
129 | { |
130 | public: |
131 | enum MapMode |
132 | { |
133 | Read = QIODevice::ReadOnly, |
134 | Write = (QIODevice::WriteOnly | QIODevice::Truncate) |
135 | }; |
136 | |
137 | explicit QQsbIODeviceCollection(const QString &filePath); |
138 | explicit QQsbIODeviceCollection(QIODevice &dev); |
139 | ~QQsbIODeviceCollection(); |
140 | |
141 | bool map(MapMode mode); |
142 | void unmap(); |
143 | |
144 | EntryMap availableEntries() const override; |
145 | Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override; |
146 | bool (Entry entry, EntryDesc &entryDesc) override; |
147 | |
148 | void dumpInfo(); |
149 | static void dumpInfo(const QString &device); |
150 | static void dumpInfo(QIODevice &device); |
151 | |
152 | private: |
153 | Q_DISABLE_COPY(QQsbIODeviceCollection); |
154 | |
155 | enum class DeviceOwner : quint8 |
156 | { |
157 | Self, |
158 | Extern |
159 | }; |
160 | QFile file; |
161 | QIODevice &device; |
162 | DeviceOwner devOwner = DeviceOwner::Self; |
163 | quint8 version = Version::Unknown; |
164 | EntryMap entries; |
165 | }; |
166 | |
167 | QT_END_NAMESPACE |
168 | |
169 | #endif // QQSBCOLLECTION_H |
170 | |