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
26QT_BEGIN_NAMESPACE
27
28class QRhiShaderStage;
29
30class Q_QUICK3DUTILS_EXPORT QQsbCollection
31{
32public:
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 extractEntry(Entry entry, EntryDesc &entryDesc) = 0;
80
81protected:
82 enum Version : quint8
83 {
84 Unknown,
85 One = 0x10,
86 Two = 0x20
87 };
88 bool readEndHeader(QDataStream &ds, qint64 *startPos, quint8 *version);
89 void writeEndHeader(QDataStream &ds, qint64 startPos, quint8 version, quint64 magic);
90 bool readEndHeader(QIODevice *device, EntryMap *entries, quint8 *version);
91 void writeEndHeader(QIODevice *device, const EntryMap &entries);
92};
93
94Q_DECLARE_TYPEINFO(QQsbCollection::Entry, Q_PRIMITIVE_TYPE);
95
96Q_QUICK3DUTILS_EXPORT QDataStream &operator<<(QDataStream &stream, const QQsbCollection::Entry &entry);
97Q_QUICK3DUTILS_EXPORT QDataStream &operator>>(QDataStream &stream, QQsbCollection::Entry &entry);
98Q_QUICK3DUTILS_EXPORT QDataStream &operator<<(QDataStream &stream, const QQsbCollection::EntryDesc &entryDesc);
99Q_QUICK3DUTILS_EXPORT QDataStream &operator>>(QDataStream &stream, QQsbCollection::EntryDesc &entryDesc);
100
101Q_QUICK3DUTILS_EXPORT size_t qHash(const QQsbCollection::Entry &entry, size_t);
102Q_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.
107class Q_QUICK3DUTILS_EXPORT QQsbInMemoryCollection : public QQsbCollection
108{
109public:
110 QQsbInMemoryCollection() = default;
111
112 EntryMap availableEntries() const override;
113 Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override;
114 bool extractEntry(Entry entry, EntryDesc &entryDesc) override;
115
116 void clear();
117
118 bool load(const QString &filename);
119 bool save(const QString &filename);
120
121private:
122 Q_DISABLE_COPY(QQsbInMemoryCollection);
123
124 QHash<Entry, EntryDesc> entries;
125};
126
127// Serial, direct-to/from-QIODevice implementation.
128class Q_QUICK3DUTILS_EXPORT QQsbIODeviceCollection : public QQsbCollection
129{
130public:
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 extractEntry(Entry entry, EntryDesc &entryDesc) override;
147
148 void dumpInfo();
149 static void dumpInfo(const QString &device);
150 static void dumpInfo(QIODevice &device);
151
152private:
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
167QT_END_NAMESPACE
168
169#endif // QQSBCOLLECTION_H
170

source code of qtquick3d/src/utils/qqsbcollection_p.h