summaryrefslogtreecommitdiffstats
path: root/src/gui/util
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2022-05-25 08:59:13 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2022-05-27 20:54:44 +0200
commit9614f4d434474fe7dcca752b3f72a56f2d382230 (patch)
treef4d6550149c396c89e76d02491f0b9907a4f38b1 /src/gui/util
parent5431b40ee87ade502825258d67304882a33f9294 (diff)
Make it possible to create QTextureFileData from images
Currently it is only possible to create a cube map texture from a single compressed texture file. In many cases, the cubemap asset is available as a set of individual image files. Making it possible to use these images directly will make the development process more efficient, and will reduce the size of the assets needed to be shipped with demos and examples. Task-number: QTBUG-103191 Change-Id: Icd12548e2dab55ec2123804cb28353cbf29926ce Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/util')
-rw-r--r--src/gui/util/qtexturefiledata.cpp66
-rw-r--r--src/gui/util/qtexturefiledata_p.h6
2 files changed, 55 insertions, 17 deletions
diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp
index 4b9bcb0a33..ddd99b0ffc 100644
--- a/src/gui/util/qtexturefiledata.cpp
+++ b/src/gui/util/qtexturefiledata.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "QtGui/qimage.h"
#include "qtexturefiledata_p.h"
#include <QtCore/qsize.h>
#include <QtCore/qvarlengtharray.h>
@@ -21,14 +22,17 @@ public:
QTextureFileDataPrivate(const QTextureFileDataPrivate &other)
: QSharedData(other),
+ mode(other.mode),
logName(other.logName),
data(other.data),
offsets(other.offsets),
lengths(other.lengths),
+ images(other.images),
size(other.size),
format(other.format),
numFaces(other.numFaces),
- numLevels(other.numLevels)
+ numLevels(other.numLevels),
+ keyValues(other.keyValues)
{
}
@@ -40,13 +44,18 @@ public:
{
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)
+ if (mode == QTextureFileData::ByteArrayMode) {
+ offsets.resize(numFaces);
+ lengths.resize(numFaces);
+
+ for (auto faceList : { &offsets, &lengths })
+ for (auto &levelList : *faceList)
+ levelList.resize(numLevels);
+ } else {
+ images.resize(numFaces);
+ for (auto &levelList : images)
levelList.resize(numLevels);
+ }
}
bool isValid(int level, int face) const { return level < numLevels && face < numFaces; }
@@ -56,10 +65,12 @@ public:
int getLength(int level, int face) const { return lengths[face][level]; }
void setLength(int value, int level, int face) { lengths[face][level] = value; }
+ QTextureFileData::Mode mode = QTextureFileData::ByteArrayMode;
QByteArray logName;
QByteArray data;
QVarLengthArray<QList<int>, MAX_FACES> offsets; // [Face][Level] = offset
QVarLengthArray<QList<int>, MAX_FACES> lengths; // [Face][Level] = length
+ QVarLengthArray<QList<QImage>, MAX_FACES> images; // [Face][Level] = length
QSize size;
quint32 format = 0;
quint32 internalFormat = 0;
@@ -69,8 +80,10 @@ public:
QMap<QByteArray, QByteArray> keyValues;
};
-QTextureFileData::QTextureFileData()
+QTextureFileData::QTextureFileData(Mode mode)
{
+ d = new QTextureFileDataPrivate;
+ d->mode = mode;
}
QTextureFileData::QTextureFileData(const QTextureFileData &other)
@@ -98,6 +111,9 @@ bool QTextureFileData::isValid() const
if (!d)
return false;
+ if (d->mode == ImageMode)
+ return true; // Manually populated: the caller needs to do verification at that time.
+
if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat))
return false;
@@ -139,19 +155,26 @@ QByteArray QTextureFileData::data() const
void QTextureFileData::setData(const QByteArray &data)
{
- if (!d.constData()) //### uh think about this design, this is the only way to create; should be constructor instead at least
- d = new QTextureFileDataPrivate;
-
+ Q_ASSERT(d->mode == ByteArrayMode);
d->data = data;
}
+void QTextureFileData::setData(const QImage &image, int level, int face)
+{
+ Q_ASSERT(d->mode == ImageMode);
+ d->ensureSize(level + 1, face + 1);
+ d->images[face][level] = image;
+}
+
int QTextureFileData::dataOffset(int level, int face) const
{
+ Q_ASSERT(d->mode == ByteArrayMode);
return (d && d->isValid(level, face)) ? d->getOffset(level, face) : 0;
}
void QTextureFileData::setDataOffset(int offset, int level, int face)
{
+ Q_ASSERT(d->mode == ByteArrayMode);
if (d.constData() && level >= 0) {
d->ensureSize(level + 1, face + 1);
d->setOffset(offset, level, face);
@@ -160,22 +183,31 @@ void QTextureFileData::setDataOffset(int offset, int level, int face)
int QTextureFileData::dataLength(int level, int face) const
{
+ Q_ASSERT(d->mode == ByteArrayMode);
return (d && d->isValid(level, face)) ? d->getLength(level, face) : 0;
}
QByteArrayView QTextureFileData::getDataView(int level, int face) const
{
- const int dataLength = this->dataLength(level, face);
- const int dataOffset = this->dataOffset(level, face);
+ if (d->mode == ByteArrayMode) {
+ const int dataLength = this->dataLength(level, face);
+ const int dataOffset = this->dataOffset(level, face);
- if (d == nullptr || dataLength == 0)
- return QByteArrayView();
+ if (d == nullptr || dataLength == 0)
+ return QByteArrayView();
- return QByteArrayView(d->data.constData() + dataOffset, dataLength);
+ return QByteArrayView(d->data.constData() + dataOffset, dataLength);
+ } else {
+ if (!d->isValid(level, face))
+ return QByteArrayView();
+ const QImage &img = d->images[face][level];
+ return img.isNull() ? QByteArrayView() : QByteArrayView(img.constBits(), img.sizeInBytes());
+ }
}
void QTextureFileData::setDataLength(int length, int level, int face)
{
+ Q_ASSERT(d->mode == ByteArrayMode);
if (d.constData() && level >= 0) {
d->ensureSize(level + 1, face + 1);
d->setLength(length, level, face);
@@ -286,9 +318,11 @@ QDebug operator<<(QDebug dbg, const QTextureFileData &d)
dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat());
dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat());
dbg.nospace() << "Levels: " << d.numLevels();
+ dbg.nospace() << "Faces: " << d.numFaces();
if (!d.isValid())
dbg << " {Invalid}";
dbg << ")";
+ dbg << (d.d->mode ? "[bytearray-based]" : "[image-based]");
} else {
dbg << "null)";
}
diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h
index 189a590979..cd0dbe171c 100644
--- a/src/gui/util/qtexturefiledata_p.h
+++ b/src/gui/util/qtexturefiledata_p.h
@@ -30,7 +30,9 @@ class QTextureFileDataPrivate;
class Q_GUI_EXPORT QTextureFileData
{
public:
- QTextureFileData();
+ enum Mode { ByteArrayMode, ImageMode };
+
+ QTextureFileData(Mode mode = ByteArrayMode);
QTextureFileData(const QTextureFileData &other);
QTextureFileData &operator=(const QTextureFileData &other);
~QTextureFileData();
@@ -42,6 +44,7 @@ public:
QByteArray data() const;
void setData(const QByteArray &data);
+ void setData(const QImage &image, int level = 0, int face = 0);
int dataOffset(int level = 0, int face = 0) const;
void setDataOffset(int offset, int level = 0, int face = 0);
@@ -77,6 +80,7 @@ public:
private:
QSharedDataPointer<QTextureFileDataPrivate> d;
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d);
};
Q_DECLARE_TYPEINFO(QTextureFileData, Q_RELOCATABLE_TYPE);