summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorJonas Karlsson <jonas.karlsson@qt.io>2021-01-19 15:24:29 +0100
committerJonas Karlsson <jonas.karlsson@qt.io>2021-01-21 18:33:59 +0100
commit509196b1d9c1ec9c483d3b7c84168494ef804f95 (patch)
tree09076b439069d085cad39f53f58cab0e7d7c0054 /src/gui
parentd95a1a8bd4734df3c2b6b55e5eb7a86108b682d3 (diff)
Add face support to texture file
Task-Id: QTBUG-76970 Change-Id: I3bbd43357c7fcce8949522b089a4572b948f08f4 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/util/qastchandler.cpp1
-rw-r--r--src/gui/util/qktxhandler.cpp1
-rw-r--r--src/gui/util/qpkmhandler.cpp1
-rw-r--r--src/gui/util/qtexturefiledata.cpp108
-rw-r--r--src/gui/util/qtexturefiledata_p.h13
5 files changed, 85 insertions, 39 deletions
diff --git a/src/gui/util/qastchandler.cpp b/src/gui/util/qastchandler.cpp
index e91ae3e0f5..94cb42e29b 100644
--- a/src/gui/util/qastchandler.cpp
+++ b/src/gui/util/qastchandler.cpp
@@ -150,6 +150,7 @@ QTextureFileData QAstcHandler::read()
res.setDataOffset(sizeof(AstcHeader));
res.setNumLevels(1);
+ res.setNumFaces(1);
res.setDataLength(byteCount);
if (oob || !res.isValid()) {
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp
index f65eed7290..31c572db54 100644
--- a/src/gui/util/qktxhandler.cpp
+++ b/src/gui/util/qktxhandler.cpp
@@ -138,6 +138,7 @@ QTextureFileData QKtxHandler::read()
texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
texData.setNumLevels(decode(header->numberOfMipmapLevels));
+ texData.setNumFaces(1);
quint32 offset = headerSize + decode(header->bytesOfKeyValueData);
const int maxLevels = qMin(texData.numLevels(), 32); // Cap iterations in case of corrupt file.
for (int i = 0; i < maxLevels; i++) {
diff --git a/src/gui/util/qpkmhandler.cpp b/src/gui/util/qpkmhandler.cpp
index 1c073cf94e..0ad0a54a79 100644
--- a/src/gui/util/qpkmhandler.cpp
+++ b/src/gui/util/qpkmhandler.cpp
@@ -102,6 +102,7 @@ QTextureFileData QPkmHandler::read()
// texture size
texData.setNumLevels(1);
+ texData.setNumFaces(1);
const int bpb = typeMap[type].bytesPerBlock;
QSize paddedSize(qFromBigEndian<quint16>(rawData + 8), qFromBigEndian<quint16>(rawData + 10));
texData.setDataLength((paddedSize.width() / 4) * (paddedSize.height() / 4) * bpb);
diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp
index 29c6acaeca..0a3958aaf2 100644
--- a/src/gui/util/qtexturefiledata.cpp
+++ b/src/gui/util/qtexturefiledata.cpp
@@ -44,6 +44,8 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQtGuiTextureIO, "qt.gui.textureio");
+constexpr size_t MAX_FACES = 6;
+
class QTextureFileDataPrivate : public QSharedData
{
public:
@@ -58,7 +60,9 @@ public:
offsets(other.offsets),
lengths(other.lengths),
size(other.size),
- format(other.format)
+ format(other.format),
+ numFaces(other.numFaces),
+ numLevels(other.numLevels)
{
}
@@ -66,25 +70,38 @@ public:
{
}
- void ensureLevels(int num, bool force = false)
+ void ensureSize(int levels, int faces, bool force = false)
{
- const int newSize = force ? num : qMax(offsets.size(), num);
- offsets.resize(newSize);
- lengths.resize(newSize);
+ numLevels = force ? levels : qMax(numLevels, levels);
+ numFaces = force ? faces : qMax(numFaces, faces);
+
+ offsets.resize(numFaces);
+ lengths.resize(numFaces);
+
+ for (auto faceList : { &offsets, &lengths })
+ for (auto &levelList : *faceList)
+ levelList.resize(numLevels);
}
+ bool isValid(int level, int face) const { return level < numLevels && face < numFaces; }
+
+ int getOffset(int level, int face) const { return offsets[face][level]; }
+ void setOffset(int value, int level, int face) { offsets[face][level] = value; }
+ int getLength(int level, int face) const { return lengths[face][level]; }
+ void setLength(int value, int level, int face) { lengths[face][level] = value; }
+
QByteArray logName;
QByteArray data;
- QList<int> offsets;
- QList<int> lengths;
+ QVarLengthArray<QList<int>, MAX_FACES> offsets; // [Face][Level] = offset
+ QVarLengthArray<QList<int>, MAX_FACES> lengths; // [Face][Level] = length
QSize size;
quint32 format = 0;
quint32 internalFormat = 0;
quint32 baseInternalFormat = 0;
+ int numFaces = 0;
+ int numLevels = 0;
};
-
-
QTextureFileData::QTextureFileData()
{
}
@@ -117,16 +134,28 @@ bool QTextureFileData::isValid() const
if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat))
return false;
- const int numChunks = d->offsets.size();
- if (numChunks == 0 || (d->lengths.size() != numChunks))
- return false;
+ const int numFacesOffset = d->offsets.length();
+ const int numFacesLength = d->lengths.length();
+ if (numFacesOffset == 0 || numFacesLength == 0 || d->numFaces != numFacesOffset
+ || d->numFaces != numFacesLength)
+ return false;
+
+ const qint64 dataSize = d->data.size();
- const qint64 sz = d->data.size();
- for (int i = 0; i < numChunks; i++) {
- qint64 offi = d->offsets.at(i);
- qint64 leni = d->lengths.at(i);
- if (offi < 0 || offi >= sz || leni <= 0 || (offi + leni > sz))
+ // Go through all faces and levels and check that the range is inside the data size.
+ for (int face = 0; face < d->numFaces; face++) {
+ const int numLevelsOffset = d->offsets.at(face).size();
+ const int numLevelsLength = d->lengths.at(face).size();
+ if (numLevelsOffset == 0 || numLevelsLength == 0 || d->numLevels != numLevelsOffset
+ || d->numLevels != numLevelsLength)
return false;
+
+ for (int level = 0; level < d->numLevels; level++) {
+ const qint64 offset = d->getOffset(level, face);
+ const qint64 length = d->getLength(level, face);
+ if (offset < 0 || offset >= dataSize || length <= 0 || (offset + length > dataSize))
+ return false;
+ }
}
return true;
}
@@ -149,28 +178,28 @@ void QTextureFileData::setData(const QByteArray &data)
d->data = data;
}
-int QTextureFileData::dataOffset(int level) const
+int QTextureFileData::dataOffset(int level, int face) const
{
- return (d && d->offsets.size() > level) ? d->offsets.at(level) : 0;
+ return (d && d->isValid(level, face)) ? d->getOffset(level, face) : 0;
}
-void QTextureFileData::setDataOffset(int offset, int level)
+void QTextureFileData::setDataOffset(int offset, int level, int face)
{
if (d.constData() && level >= 0) {
- d->ensureLevels(level + 1);
- d->offsets[level] = offset;
+ d->ensureSize(level + 1, face + 1);
+ d->setOffset(offset, level, face);
}
}
-int QTextureFileData::dataLength(int level) const
+int QTextureFileData::dataLength(int level, int face) const
{
- return (d && d->lengths.size() > level) ? d->lengths.at(level) : 0;
+ return (d && d->isValid(level, face)) ? d->getLength(level, face) : 0;
}
-QByteArrayView QTextureFileData::getDataView(int level) const
+QByteArrayView QTextureFileData::getDataView(int level, int face) const
{
- const int dataLength = this->dataLength(level);
- const int dataOffset = this->dataOffset(level);
+ const int dataLength = this->dataLength(level, face);
+ const int dataOffset = this->dataOffset(level, face);
if (d == nullptr || dataLength == 0)
return QByteArrayView();
@@ -178,23 +207,34 @@ QByteArrayView QTextureFileData::getDataView(int level) const
return QByteArrayView(d->data.constData() + dataOffset, dataLength);
}
-void QTextureFileData::setDataLength(int length, int level)
+void QTextureFileData::setDataLength(int length, int level, int face)
{
if (d.constData() && level >= 0) {
- d->ensureLevels(level + 1);
- d->lengths[level] = length;
+ d->ensureSize(level + 1, face + 1);
+ d->setLength(length, level, face);
}
}
int QTextureFileData::numLevels() const
{
- return d ? d->offsets.size() : 0;
+ return d ? d->numLevels : 0;
+}
+
+void QTextureFileData::setNumLevels(int numLevels)
+{
+ if (d && numLevels >= 0)
+ d->ensureSize(numLevels, d->numFaces, true);
+}
+
+int QTextureFileData::numFaces() const
+{
+ return d ? d->numFaces : 0;
}
-void QTextureFileData::setNumLevels(int num)
+void QTextureFileData::setNumFaces(int numFaces)
{
- if (d && num >= 0)
- d->ensureLevels(num, true);
+ if (d && numFaces >= 0)
+ d->ensureSize(d->numLevels, numFaces, true);
}
QSize QTextureFileData::size() const
diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h
index 3d75d46c94..f6a03c0550 100644
--- a/src/gui/util/qtexturefiledata_p.h
+++ b/src/gui/util/qtexturefiledata_p.h
@@ -78,17 +78,20 @@ public:
QByteArray data() const;
void setData(const QByteArray &data);
- int dataOffset(int level = 0) const;
- void setDataOffset(int offset, int level = 0);
+ int dataOffset(int level = 0, int face = 0) const;
+ void setDataOffset(int offset, int level = 0, int face = 0);
- int dataLength(int level = 0) const;
- void setDataLength(int length, int level = 0);
+ int dataLength(int level = 0, int face = 0) const;
+ void setDataLength(int length, int level = 0, int face = 0);
- QByteArrayView getDataView(int level = 0) const;
+ QByteArrayView getDataView(int level = 0, int face = 0) const;
int numLevels() const;
void setNumLevels(int num);
+ int numFaces() const;
+ void setNumFaces(int num);
+
QSize size() const;
void setSize(const QSize &size);