Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqsbcollection.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qqsbcollection_p.h"
5#include <QtCore/QLockFile>
6#include <QtCore/QSaveFile>
7#include <QtCore/QCryptographicHash>
8#include <rhi/qrhi.h>
9
11
15
17{
18 return (stream << entry.key << entry.value);
19}
20
29
30size_t qHash(const QQsbCollection::Entry &entry, size_t)
31{
32 return entry.hashKey;
33}
34
36{
37 return (l.key == r.key);
38}
39
41{
42 return (stream << entryDesc.materialKey
43 << entryDesc.featureSet
44 << entryDesc.vertShader.serialized()
45 << entryDesc.fragShader.serialized());
46}
47
49{
50 QByteArray desc;
52 QByteArray vertData;
53 QByteArray fragData;
54 stream >> desc >> fs >> vertData >> fragData;
55 entryDesc.materialKey = desc;
56 entryDesc.featureSet = fs;
57 entryDesc.vertShader = QShader::fromSerialized(vertData);
58 entryDesc.fragShader = QShader::fromSerialized(fragData);
59 return stream;
60}
61
62static constexpr quint64 MagicaDS = 0x3933333335346337;
63static constexpr qint64 HeaderSize = sizeof(qint64 /*startOffs*/) + sizeof(quint8 /*version*/) + sizeof(quint32 /*qtVersion*/) + sizeof(MagicaDS);
64static constexpr quint32 QtVersion = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
65
67{
68 quint64 fileId = 0;
69 quint32 qtver = 0;
70 ds >> *startPos >> *version >> qtver >> fileId;
71 if (fileId != MagicaDS) {
72 qWarning("Corrupt qsbc file");
73 return false;
74 }
75 if (*version != Version::Two) {
76 qWarning("qsbc file has an unsupported version");
77 return false;
78 }
79 if (qtver != QtVersion) {
80 qWarning("qsbc file is for a different Qt version");
81 return false;
82 }
83 return true;
84}
85
87{
88 bool result = false;
89 const qint64 size = device->size();
90 if (device->seek(size - HeaderSize)) {
92 ds.setVersion(QDataStream::Qt_6_0);
93 qint64 startPos = 0;
94 if (readEndHeader(ds, &startPos, version)) {
95 if (startPos >= 0 && startPos < size && device->seek(startPos)) {
96 ds >> *entries;
97 result = true;
98 }
99 }
100 }
101 return result;
102}
103
105{
106 ds << startPos << version << QtVersion << magic;
107}
108
110{
111 if (!device->atEnd()) {
112 device->seek(device->size() - 1);
113 Q_ASSERT(device->atEnd());
114 }
116 ds.setVersion(QDataStream::Qt_6_0);
117 const qint64 startPos = device->pos();
118 ds << entries;
120}
121
123{
125 h.addData(materialKey);
126 for (auto it = featureSet.cbegin(), end = featureSet.cend(); it != end; ++it) {
127 if (it.value())
128 h.addData(it.key());
129 }
130 return h.result().toHex();
131}
132
134{
135 return generateSha(materialKey, featureSet);
136}
137
139{
140 return EntryMap(entries.keyBegin(), entries.keyEnd());
141}
142
144{
145 Entry e(key);
146 if (!entries.contains(e)) {
147 entries.insert(e, entryDesc);
148 return e;
149 }
150 return {}; // can only add with a given key once
151}
152
154{
155 auto it = entries.constFind(entry);
156 if (it != entries.constEnd()) {
157 entryDesc = *it;
158 return true;
159 }
160 return false;
161}
162
164{
165 entries.clear();
166}
167
168static inline QString lockFileName(const QString &name)
169{
170 return name + QLatin1String(".lck");
171}
172
174{
175 QLockFile lock(lockFileName(filename));
176 if (!lock.lock()) {
177 qWarning("Could not create shader cache lock file '%s'",
178 qPrintable(lock.fileName()));
179 return false;
180 }
181
182 QFile f(filename);
183 if (!f.open(QIODevice::ReadOnly)) {
184 qWarning("Failed to open qsbc file %s", qPrintable(filename));
185 return false;
186 }
187
188 EntryMap entryMap;
189 quint8 version = 0;
190 if (!readEndHeader(&f, &entryMap, &version)) {
191 qWarning("Ignoring qsbc file %s", qPrintable(filename));
192 return false;
193 }
194
195 f.seek(0);
196 const qint64 size = f.size();
197
198 clear();
199
200 for (const Entry &e : entryMap) {
201 const qint64 offset = e.value;
202 if (e.isValid() && offset >= 0 && size > offset && f.seek(offset)) {
203 QDataStream ds(&f);
204 ds.setVersion(QDataStream::Qt_6_0);
205 EntryDesc entryDesc;
206 ds >> entryDesc;
207 entries.insert(Entry(e.key), entryDesc);
208 }
209 }
210
211 return true;
212}
213
215{
216 QLockFile lock(lockFileName(filename));
217 if (!lock.lock()) {
218 qWarning("Could not create shader cache lock file '%s'",
219 qPrintable(lock.fileName()));
220 return false;
221 }
222
223#if QT_CONFIG(temporaryfile)
224 QSaveFile f(filename);
225#else
226 QFile f(filename);
227#endif
229 qWarning("Failed to write qsbc file %s", qPrintable(filename));
230 return false;
231 }
232
233 QDataStream ds(&f);
234 ds.setVersion(QDataStream::Qt_6_0);
235
236 EntryMap entryMap;
237 for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
238 const qint64 offset = f.pos();
239 ds << it.value();
240 entryMap.insert(Entry(it.key().key, offset));
241 }
242
243 writeEndHeader(&f, entryMap);
244
245#if QT_CONFIG(temporaryfile)
246 return f.commit();
247#else
248 return true;
249#endif
250}
251
253 : file(filePath)
254 , device(file)
255{
256}
257
259 : device(dev)
260 , devOwner(DeviceOwner::Extern)
261{
262
263}
264
266{
267 if (!entries.isEmpty() || device.isOpen())
268 unmap();
269}
270
272{
273 if (device.isOpen()) {
274 // Make sure Truncate is set if we're writing.
275 if ((device.openMode() & QIODevice::WriteOnly) != 0) {
276 if ((device.openMode() & QIODevice::Truncate) == 0) {
277 qWarning("Open mode needs to have Truncate set for writing!");
278 return false;
279 }
280 if ((device.openMode() & QIODevice::Text) != 0) {
281 qWarning("Open mode can't have Text mode set!");
282 return false;
283 }
284 }
285 } else if (!device.open(QIODevice::OpenMode(mode))) {
286 qWarning("Unable to open device!");
287 return false;
288 }
289
290 if (mode == Write)
291 return true;
292
293 Q_ASSERT(mode == Read);
294
295 const bool ret = readEndHeader(&device, &entries, &version);
296
297 if (!ret)
298 unmap();
299
300 return ret;
301}
302
304{
305 if (device.isOpen() && ((device.openMode() & Write) == Write)) {
306 if (!entries.isEmpty()) {
307 writeEndHeader(&device, entries);
308 } else {
309 if (devOwner == DeviceOwner::Self)
310 file.remove();
311 }
312 }
313 device.close();
314 entries.clear();
315}
316
321
323{
324 if (entries.contains(Entry(key)) || !map(MapMode::Write))
325 return {};
326
327 QDataStream ds(&device);
328 ds.setVersion(QDataStream::Qt_6_0);
329 const auto offset = device.pos();
330 ds << entryDesc;
331 Entry e(key, offset);
332 entries.insert(e);
333 return e;
334}
335
337{
338 if (device.isOpen() && device.isReadable()) {
339 const qint64 offset = entry.value;
340 if (entry.isValid() && offset >= 0) {
341 const qint64 size = device.size();
342 if (size > offset && device.seek(offset)) {
343 QDataStream ds(&device);
344 ds.setVersion(QDataStream::Qt_6_0);
345 ds >> entryDesc;
346 return true;
347 }
348 } else {
349 qWarning("Entry not found id(%s), offset(%lld)", entry.key.constData(), entry.value);
350 }
351 } else {
352 qWarning("Unable to open file for reading");
353 }
354
355 return false;
356}
357
358static const char *borderText() { return "--------------------------------------------------------------------------------"; }
359
361{
363 qDebug("Number of entries in collection: %zu\n", size_t(entries.size()));
364 int i = 0;
365 qDebug("Qsbc version: %u", version);
366 for (const auto &e : std::as_const(entries)) {
367 qDebug("%s\n"
368 "Entry %d\n%s\n"
369 "Key: %s\n"
370 "Offset: %llu", borderText(), i++, borderText(), e.key.constData(), e.value);
371
373 if (extractEntry(e, ed)) {
374 qDebug() << ed.materialKey << Qt::endl
375 << ed.featureSet << Qt::endl
376 << ed.vertShader << Qt::endl
377 << ed.fragShader;
378 } else {
379 qWarning("Extracting Qsb entry failed!");
380 }
381 }
382 }
383 unmap();
384}
385
387{
389 qsbc.dumpInfo();
390}
391
393{
394 QQsbIODeviceCollection qsbc(device);
395 qsbc.dumpInfo();
396}
397
IOBluetoothDevice * device
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:46
void setVersion(int)
Sets the version number of the data serialization format to v, a value of the \l Version enum.
\inmodule QtCore
Definition qfile.h:93
bool remove()
Removes the file specified by fileName().
Definition qfile.cpp:419
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
QIODeviceBase::OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
\inmodule QtCore
Definition qlockfile.h:17
const_iterator cend() const
Definition qmap.h:605
const_iterator cbegin() const
Definition qmap.h:601
void writeEndHeader(QDataStream &ds, qint64 startPos, quint8 version, quint64 magic)
virtual ~QQsbCollection()
QSet< Entry > EntryMap
bool readEndHeader(QDataStream &ds, qint64 *startPos, quint8 *version)
Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override
bool map(MapMode mode)
bool extractEntry(Entry entry, EntryDesc &entryDesc) override
QQsbIODeviceCollection(const QString &filePath)
EntryMap availableEntries() const override
Entry addEntry(const QByteArray &key, const EntryDesc &entryDesc) override
bool load(const QString &filename)
bool save(const QString &filename)
EntryMap availableEntries() const override
bool extractEntry(Entry entry, EntryDesc &entryDesc) override
qsizetype size() const
Definition qset.h:50
bool isEmpty() const
Definition qset.h:52
const_iterator constEnd() const noexcept
Definition qset.h:143
void clear()
Definition qset.h:61
const_iterator constFind(const T &value) const
Definition qset.h:161
bool contains(const T &value) const
Definition qset.h:71
const_iterator cbegin() const noexcept
Definition qset.h:138
iterator insert(const T &value)
Definition qset.h:155
static QShader fromSerialized(const QByteArray &data)
Creates a new QShader instance from the given data.
Definition qshader.cpp:540
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
Definition lalr.h:268
QMap< QString, QString > map
[6]
b clear()
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QTextStream & endl(QTextStream &stream)
Writes '\n' to the stream and flushes the stream.
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QByteArray fileId(HANDLE handle)
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
return ret
GLenum mode
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLfloat GLfloat f
GLenum GLuint GLintptr offset
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLuint entry
GLuint64EXT * result
[6]
static const char * borderText()
static constexpr quint32 QtVersion
bool operator==(const QQsbCollection::Entry &l, const QQsbCollection::Entry &r)
static constexpr quint64 MagicaDS
static QString lockFileName(const QString &name)
QDataStream & operator>>(QDataStream &stream, QQsbCollection::Entry &entry)
QDataStream & operator<<(QDataStream &stream, const QQsbCollection::Entry &entry)
static constexpr qint64 HeaderSize
size_t qHash(const QQsbCollection::Entry &entry, size_t)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
static const uchar magic[MagicLength]
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
long long qint64
Definition qtypes.h:60
unsigned char quint8
Definition qtypes.h:46
QFile file
[0]
QReadWriteLock lock
[0]
QByteArray generateSha() const