diff options
-rw-r--r-- | src/gui/util/qktxhandler.cpp | 189 | ||||
-rw-r--r-- | src/gui/util/qktxhandler_p.h | 78 | ||||
-rw-r--r-- | src/gui/util/qpkmhandler.cpp | 126 | ||||
-rw-r--r-- | src/gui/util/qpkmhandler_p.h | 70 | ||||
-rw-r--r-- | src/gui/util/qtexturefiledata.cpp | 279 | ||||
-rw-r--r-- | src/gui/util/qtexturefiledata_p.h | 115 | ||||
-rw-r--r-- | src/gui/util/qtexturefilehandler_p.h | 79 | ||||
-rw-r--r-- | src/gui/util/qtexturefilereader.cpp | 102 | ||||
-rw-r--r-- | src/gui/util/qtexturefilereader_p.h | 88 | ||||
-rw-r--r-- | src/gui/util/util.pri | 13 | ||||
-rw-r--r-- | tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro | 5 | ||||
-rw-r--r-- | tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc | 6 | ||||
-rw-r--r-- | tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx | bin | 0 -> 11908 bytes | |||
-rw-r--r-- | tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm | bin | 0 -> 2064 bytes | |||
-rw-r--r-- | tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp | 97 | ||||
-rw-r--r-- | tests/auto/gui/util/util.pro | 2 |
16 files changed, 1246 insertions, 3 deletions
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp new file mode 100644 index 0000000000..c7831f8143 --- /dev/null +++ b/src/gui/util/qktxhandler.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qktxhandler_p.h" +#include "qtexturefiledata_p.h" +#include <QtEndian> +#include <QSize> + +//#define KTX_DEBUG + +QT_BEGIN_NAMESPACE + +#define KTX_IDENTIFIER_LENGTH 12 +static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' }; +static const quint32 platformEndianIdentifier = 0x04030201; +static const quint32 inversePlatformEndianIdentifier = 0x01020304; + +struct KTXHeader { + quint8 identifier[KTX_IDENTIFIER_LENGTH]; // Must match ktxIdentifier + quint32 endianness; // Either platformEndianIdentifier or inversePlatformEndianIdentifier, other values not allowed. + quint32 glType; + quint32 glTypeSize; + quint32 glFormat; + quint32 glInternalFormat; + quint32 glBaseInternalFormat; + quint32 pixelWidth; + quint32 pixelHeight; + quint32 pixelDepth; + quint32 numberOfArrayElements; + quint32 numberOfFaces; + quint32 numberOfMipmapLevels; + quint32 bytesOfKeyValueData; +}; + +static const int headerSize = sizeof(KTXHeader); + +// Currently unused, declared for future reference +struct KTXKeyValuePairItem { + quint32 keyAndValueByteSize; + /* + quint8 keyAndValue[keyAndValueByteSize]; + quint8 valuePadding[3 - ((keyAndValueByteSize + 3) % 4)]; + */ +}; + +struct KTXMipmapLevel { + quint32 imageSize; + /* + for each array_element in numberOfArrayElements* + for each face in numberOfFaces + for each z_slice in pixelDepth* + for each row or row_of_blocks in pixelHeight* + for each pixel or block_of_pixels in pixelWidth + Byte data[format-specific-number-of-bytes]** + end + end + end + Byte cubePadding[0-3] + end + end + quint8 mipPadding[3 - ((imageSize + 3) % 4)] + */ +}; + +bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block) +{ + Q_UNUSED(suffix) + + return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0); +} + +QTextureFileData QKtxHandler::read() +{ + if (!device()) + return QTextureFileData(); + + QByteArray buf = device()->readAll(); + if (buf.size() < headerSize || !canRead(QByteArray(), buf)) { + qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData()); + return QTextureFileData(); + } + + const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData()); + if (!checkHeader(*header)) { + qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData()); + return QTextureFileData(); + } + + QTextureFileData texData; + texData.setData(buf); + + texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight))); + texData.setGLFormat(decode(header->glFormat)); + texData.setGLInternalFormat(decode(header->glInternalFormat)); + texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat)); + + //### For now, ignore any additional mipmap levels + texData.setNumLevels(1); + int preambleSize = headerSize + decode(header->bytesOfKeyValueData); + if (buf.size() >= preambleSize + int(sizeof(KTXMipmapLevel))) { + texData.setDataOffset(preambleSize + sizeof(quint32)); // for the imageSize + const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel *>(buf.constData() + preambleSize); + texData.setDataLength(decode(level->imageSize)); + } + + if (!texData.isValid()) { + qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData()); + return QTextureFileData(); + } + + texData.setLogName(logName()); + +#ifdef KTX_DEBUG + qDebug() << "KTX file handler read" << texData.data(); +#endif + + return texData; +} + +bool QKtxHandler::checkHeader(const KTXHeader &header) +{ + if (header.endianness != platformEndianIdentifier && header.endianness != inversePlatformEndianIdentifier) + return false; + inverseEndian = (header.endianness == inversePlatformEndianIdentifier); +#ifdef KTX_DEBUG + QMetaEnum tfme = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>(); + QMetaEnum ptme = QMetaEnum::fromType<QOpenGLTexture::PixelType>(); + qDebug("Header of %s:", logName().constData()); + qDebug(" glType: 0x%x (%s)", decode(header.glType), ptme.valueToKey(decode(header.glType))); + qDebug(" glTypeSize: %u", decode(header.glTypeSize)); + qDebug(" glFormat: 0x%x (%s)", decode(header.glFormat), tfme.valueToKey(decode(header.glFormat))); + qDebug(" glInternalFormat: 0x%x (%s)", decode(header.glInternalFormat), tfme.valueToKey(decode(header.glInternalFormat))); + qDebug(" glBaseInternalFormat: 0x%x (%s)", decode(header.glBaseInternalFormat), tfme.valueToKey(decode(header.glBaseInternalFormat))); + qDebug(" pixelWidth: %u", decode(header.pixelWidth)); + qDebug(" pixelHeight: %u", decode(header.pixelHeight)); + qDebug(" pixelDepth: %u", decode(header.pixelDepth)); + qDebug(" numberOfArrayElements: %u", decode(header.numberOfArrayElements)); + qDebug(" numberOfFaces: %u", decode(header.numberOfFaces)); + qDebug(" numberOfMipmapLevels: %u", decode(header.numberOfMipmapLevels)); + qDebug(" bytesOfKeyValueData: %u", decode(header.bytesOfKeyValueData)); +#endif + return ((decode(header.glType) == 0) && + (decode(header.glFormat) == 0) && + (decode(header.pixelDepth) == 0) && + (decode(header.numberOfFaces) == 1)); +} + +quint32 QKtxHandler::decode(quint32 val) +{ + return inverseEndian ? qbswap<quint32>(val) : val; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h new file mode 100644 index 0000000000..19f7b0e79a --- /dev/null +++ b/src/gui/util/qktxhandler_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKTXHANDLER_H +#define QKTXHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtexturefilehandler_p.h" + +QT_BEGIN_NAMESPACE + +struct KTXHeader; + +class QKtxHandler : public QTextureFileHandler +{ +public: + using QTextureFileHandler::QTextureFileHandler; + + static bool canRead(const QByteArray &suffix, const QByteArray &block); + + QTextureFileData read() override; + +private: + bool checkHeader(const KTXHeader &header); + quint32 decode(quint32 val); + + bool inverseEndian = false; +}; + +QT_END_NAMESPACE + +#endif // QKTXHANDLER_H diff --git a/src/gui/util/qpkmhandler.cpp b/src/gui/util/qpkmhandler.cpp new file mode 100644 index 0000000000..4481deaa8e --- /dev/null +++ b/src/gui/util/qpkmhandler.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpkmhandler_p.h" +#include "qtexturefiledata_p.h" + +#include <QFile> +#include <QDebug> +#include <QSize> +#include <qendian.h> + +//#define ETC_DEBUG + +QT_BEGIN_NAMESPACE + +static const int headerSize = 16; + +struct PkmType +{ + quint32 glFormat; + quint32 bytesPerBlock; +}; + +static PkmType typeMap[5] = { + { 0x8D64, 8 }, // GL_ETC1_RGB8_OES + { 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2 + { 0, 0 }, // unused (obsolete) + { 0x9278, 16}, // GL_COMPRESSED_RGBA8_ETC2_EAC + { 0x9276, 8 } // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 +}; + +bool QPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block) +{ + Q_UNUSED(suffix) + + return block.startsWith("PKM "); +} + +QTextureFileData QPkmHandler::read() +{ + QTextureFileData texData; + + if (!device()) + return texData; + + QByteArray fileData = device()->readAll(); + if (fileData.size() < headerSize || !canRead(QByteArray(), fileData)) { + qCDebug(lcQtGuiTextureIO, "Invalid PKM file %s", logName().constData()); + return QTextureFileData(); + } + texData.setData(fileData); + + const char *rawData = fileData.constData(); + + // ignore version (rawData + 4 & 5) + + // texture type + quint16 type = qFromBigEndian<quint16>(rawData + 6); + if (type > sizeof(typeMap)/sizeof(typeMap[0])) { + qCDebug(lcQtGuiTextureIO, "Unknown compression format in PKM file %s", logName().constData()); + return QTextureFileData(); + } + texData.setGLFormat(0); // 0 for compressed textures + texData.setGLInternalFormat(typeMap[type].glFormat); + //### setBaseInternalFormat + + // texture size + texData.setNumLevels(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); + QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14)); + texData.setSize(texSize); + + texData.setDataOffset(headerSize); + + if (!texData.isValid()) { + qCDebug(lcQtGuiTextureIO, "Invalid values in header of PKM file %s", logName().constData()); + return QTextureFileData(); + } + + texData.setLogName(logName()); + +#ifdef ETC_DEBUG + qDebug() << "PKM file handler read" << texData; +#endif + return texData; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qpkmhandler_p.h b/src/gui/util/qpkmhandler_p.h new file mode 100644 index 0000000000..2f7618bc53 --- /dev/null +++ b/src/gui/util/qpkmhandler_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPKMHANDLER_H +#define QPKMHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtexturefilehandler_p.h" + +QT_BEGIN_NAMESPACE + +class QPkmHandler : public QTextureFileHandler +{ +public: + using QTextureFileHandler::QTextureFileHandler; + + static bool canRead(const QByteArray &suffix, const QByteArray &block); + + QTextureFileData read() override; +}; + +QT_END_NAMESPACE + +#endif // QPKMHANDLER_H diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp new file mode 100644 index 0000000000..f9129e86c2 --- /dev/null +++ b/src/gui/util/qtexturefiledata.cpp @@ -0,0 +1,279 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtexturefiledata_p.h" +#include <QMetaEnum> +#if QT_CONFIG(opengl) +#include <QOpenGLTexture> +#endif + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQtGuiTextureIO, "qt.gui.textureio"); + +class QTextureFileDataPrivate : public QSharedData +{ +public: + QTextureFileDataPrivate() + { + } + + QTextureFileDataPrivate(const QTextureFileDataPrivate &other) + : QSharedData(other), + logName(other.logName), + data(other.data), + offsets(other.offsets), + lengths(other.lengths), + size(other.size), + format(other.format) + { + } + + ~QTextureFileDataPrivate() + { + } + + void ensureLevels(int num, bool force = false) + { + const int newSize = force ? num : qMax(offsets.size(), num); + offsets.resize(newSize); + lengths.resize(newSize); + } + + QByteArray logName; + QByteArray data; + QVector<int> offsets; + QVector<int> lengths; + QSize size; + quint32 format = 0; + quint32 internalFormat = 0; + quint32 baseInternalFormat = 0; +}; + + + +QTextureFileData::QTextureFileData() +{ +} + +QTextureFileData::QTextureFileData(const QTextureFileData &other) + : d(other.d) +{ +} + +QTextureFileData &QTextureFileData::operator=(const QTextureFileData &other) +{ + d = other.d; + return *this; +} + +QTextureFileData::~QTextureFileData() +{ +} + +bool QTextureFileData::isNull() const +{ + return !d; +} + +bool QTextureFileData::isValid() const +{ + if (!d) + return false; + + 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 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)) + return false; + } + return true; +} + +void QTextureFileData::clear() +{ + d = nullptr; +} + +QByteArray QTextureFileData::data() const +{ + return d ? d->data : QByteArray(); +} + +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; + + d->data = data; +} + +int QTextureFileData::dataOffset(int level) const +{ + return (d && d->offsets.size() > level) ? d->offsets.at(level) : 0; +} + +void QTextureFileData::setDataOffset(int offset, int level) +{ + if (d.constData() && level >= 0) { + d->ensureLevels(level + 1); + d->offsets[level] = offset; + } +} + +int QTextureFileData::dataLength(int level) const +{ + return (d && d->lengths.size() > level) ? d->lengths.at(level) : 0; +} + +void QTextureFileData::setDataLength(int length, int level) +{ + if (d.constData() && level >= 0) { + d->ensureLevels(level + 1); + d->lengths[level] = length; + } +} + +int QTextureFileData::numLevels() const +{ + return d ? d->offsets.size() : 0; +} + +void QTextureFileData::setNumLevels(int num) +{ + if (d && num >= 0) + d->ensureLevels(num, true); +} + +QSize QTextureFileData::size() const +{ + return d ? d->size : QSize(); +} + +void QTextureFileData::setSize(const QSize &size) +{ + if (d.constData()) + d->size = size; +} + +quint32 QTextureFileData::glFormat() const +{ + return d ? d->format : 0; +} + +void QTextureFileData::setGLFormat(quint32 format) +{ + if (d.constData()) + d->format = format; +} + +quint32 QTextureFileData::glInternalFormat() const +{ + return d ? d->internalFormat : 0; +} + +void QTextureFileData::setGLInternalFormat(quint32 format) +{ + if (d.constData()) + d->internalFormat = format; +} + +quint32 QTextureFileData::glBaseInternalFormat() const +{ + return d ? d->baseInternalFormat : 0; +} + +void QTextureFileData::setGLBaseInternalFormat(quint32 format) +{ + if (d.constData()) + d->baseInternalFormat = format; +} + +QByteArray QTextureFileData::logName() const +{ + return d ? d->logName : QByteArray(); +} + +void QTextureFileData::setLogName(const QByteArray &name) +{ + if (d.constData()) + d->logName = name; +} + +QByteArray glFormatName(quint32 fmt) +{ + const char *id = 0; +#if QT_CONFIG(opengl) + id = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>().valueToKey(fmt); +#endif + QByteArray res(id ? id : "(?)"); + res += " [0x" + QByteArray::number(fmt, 16).rightJustified(4, '0') + ']'; + return res; +} + +QDebug operator<<(QDebug dbg, const QTextureFileData &d) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "QTextureFileData("; + if (!d.isNull()) { + dbg.space() << d.logName() << d.size(); + dbg << "glFormat:" << glFormatName(d.glFormat()); + dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat()); + dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat()); + dbg.nospace() << "Levels: " << d.numLevels(); + if (!d.isValid()) + dbg << " {Invalid}"; + dbg << ")"; + } else { + dbg << "null)"; + } + + return dbg; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h new file mode 100644 index 0000000000..2df23de33c --- /dev/null +++ b/src/gui/util/qtexturefiledata_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTUREFILEDATA_P_H +#define QTEXTUREFILEDATA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qtguiglobal.h> +#include <QSharedDataPointer> +#include <QLoggingCategory> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQtGuiTextureIO) + +class QTextureFileDataPrivate; + +class Q_GUI_EXPORT QTextureFileData +{ +public: + QTextureFileData(); + QTextureFileData(const QTextureFileData &other); + QTextureFileData &operator=(const QTextureFileData &other); + ~QTextureFileData(); + + bool isNull() const; + bool isValid() const; + + void clear(); + + QByteArray data() const; + void setData(const QByteArray &data); + + int dataOffset(int level = 0) const; + void setDataOffset(int offset, int level = 0); + + int dataLength(int level = 0) const; + void setDataLength(int length, int level = 0); + + int numLevels() const; + void setNumLevels(int num); + + QSize size() const; + void setSize(const QSize &size); + + quint32 glFormat() const; + void setGLFormat(quint32 format); + + quint32 glInternalFormat() const; + void setGLInternalFormat(quint32 format); + + quint32 glBaseInternalFormat() const; + void setGLBaseInternalFormat(quint32 format); + + QByteArray logName() const; + void setLogName(const QByteArray &name); + +private: + QSharedDataPointer<QTextureFileDataPrivate> d; +}; + +Q_DECLARE_TYPEINFO(QTextureFileData, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d); + +QT_END_NAMESPACE + +#endif // QABSTRACTLAYOUTSTYLEINFO_P_H diff --git a/src/gui/util/qtexturefilehandler_p.h b/src/gui/util/qtexturefilehandler_p.h new file mode 100644 index 0000000000..b808d3e7db --- /dev/null +++ b/src/gui/util/qtexturefilehandler_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTUREFILEHANDLER_P_H +#define QTEXTUREFILEHANDLER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtexturefiledata_p.h" + +QT_BEGIN_NAMESPACE + +class QTextureFileHandler +{ +public: + QTextureFileHandler(QIODevice *device, const QByteArray &logName = QByteArray()) + : m_device(device) + { + m_logName = !logName.isEmpty() ? logName : QByteArrayLiteral("(unknown)"); + } + virtual ~QTextureFileHandler() {} + + virtual QTextureFileData read() = 0; + QIODevice *device() const { return m_device; } + QByteArray logName() const { return m_logName; } + +private: + QIODevice *m_device = nullptr; + QByteArray m_logName; +}; + +QT_END_NAMESPACE + +#endif // QTEXTUREFILEHANDLER_P_H diff --git a/src/gui/util/qtexturefilereader.cpp b/src/gui/util/qtexturefilereader.cpp new file mode 100644 index 0000000000..5d4bd600e0 --- /dev/null +++ b/src/gui/util/qtexturefilereader.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtexturefilereader_p.h" + +#include "qpkmhandler_p.h" +#include "qktxhandler_p.h" + +#include <QFileInfo> + +QT_BEGIN_NAMESPACE + +QTextureFileReader::QTextureFileReader(QIODevice *device, const QString &fileName) + : m_device(device), m_fileName(fileName) +{ +} + +QTextureFileReader::~QTextureFileReader() +{ + delete m_handler; +} + +QTextureFileData QTextureFileReader::read() +{ + if (!canRead()) + return QTextureFileData(); + return m_handler->read(); +} + +bool QTextureFileReader::canRead() +{ + if (!checked) { + checked = true; + if (!init()) + return false; + + QByteArray headerBlock = m_device->peek(64); + QFileInfo fi(m_fileName); + QByteArray suffix = fi.suffix().toLower().toLatin1(); + QByteArray logName = fi.fileName().toUtf8(); + + // Currently the handlers are hardcoded; later maybe a list of plugins + if (QPkmHandler::canRead(suffix, headerBlock)) { + m_handler = new QPkmHandler(m_device, logName); + } else if (QKtxHandler::canRead(suffix, headerBlock)) { + m_handler = new QKtxHandler(m_device, logName); + } + // else if OtherHandler::canRead() ...etc. + } + return (m_handler != nullptr); +} + +QList<QByteArray> QTextureFileReader::supportedFileFormats() +{ + // Hardcoded for now + return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")}; +} + +bool QTextureFileReader::init() +{ + if (!m_device) + return false; + return m_device->isReadable(); +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qtexturefilereader_p.h b/src/gui/util/qtexturefilereader_p.h new file mode 100644 index 0000000000..2ec0b0cc49 --- /dev/null +++ b/src/gui/util/qtexturefilereader_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTUREFILEREADER_H +#define QTEXTUREFILEREADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtexturefiledata_p.h" +#include <QString> +#include <QFileInfo> + +QT_BEGIN_NAMESPACE + +class QIODevice; +class QTextureFileHandler; + +class Q_GUI_EXPORT QTextureFileReader +{ +public: + QTextureFileReader(QIODevice *device, const QString &fileName = QString()); //### drop this logname thing? + ~QTextureFileReader(); + + bool canRead(); + QTextureFileData read(); + + // TBD access function to params + // TBD ask for identified fmt + + static QList<QByteArray> supportedFileFormats(); + +private: + bool init(); + QIODevice *m_device = nullptr; + QString m_fileName; + QTextureFileHandler *m_handler = nullptr; + bool checked = false; +}; + +QT_END_NAMESPACE + + +#endif // QTEXTUREFILEREADER_H diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index cf3cbee48e..6324642505 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -14,7 +14,12 @@ HEADERS += \ util/qshaderlanguage_p.h \ util/qshadernode_p.h \ util/qshadernodeport_p.h \ - util/qshadernodesloader_p.h + util/qshadernodesloader_p.h \ + util/qtexturefiledata_p.h \ + util/qtexturefilereader_p.h \ + util/qtexturefilehandler_p.h \ + util/qpkmhandler_p.h \ + util/qktxhandler_p.h SOURCES += \ util/qdesktopservices.cpp \ @@ -29,4 +34,8 @@ SOURCES += \ util/qshaderlanguage.cpp \ util/qshadernode.cpp \ util/qshadernodeport.cpp \ - util/qshadernodesloader.cpp + util/qshadernodesloader.cpp \ + util/qtexturefiledata.cpp \ + util/qtexturefilereader.cpp \ + util/qpkmhandler.cpp \ + util/qktxhandler.cpp diff --git a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro new file mode 100644 index 0000000000..43951fe722 --- /dev/null +++ b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +QT += testlib gui-private +SOURCES += tst_qtexturefilereader.cpp +TARGET = tst_qtexturefilereader +RESOURCES += qtexturefilereader.qrc diff --git a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc new file mode 100644 index 0000000000..74f33d57ad --- /dev/null +++ b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>texturefiles/car.ktx</file> + <file>texturefiles/pattern.pkm</file> + </qresource> +</RCC> diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx b/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx Binary files differnew file mode 100644 index 0000000000..2aefdd306b --- /dev/null +++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm b/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm Binary files differnew file mode 100644 index 0000000000..d986e89b2d --- /dev/null +++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm diff --git a/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp new file mode 100644 index 0000000000..f480184067 --- /dev/null +++ b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qtexturefilereader_p.h> +#include <QtTest> + +class tst_qtexturefilereader : public QObject +{ + Q_OBJECT + +private slots: + void checkHandlers_data(); + void checkHandlers(); +}; + +void tst_qtexturefilereader::checkHandlers_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QSize>("size"); + QTest::addColumn<quint32>("glFormat"); + QTest::addColumn<quint32>("glInternalFormat"); + // todo: glBaseInternalFormat + QTest::addColumn<int>("levels"); + QTest::addColumn<int>("dataOffset"); + QTest::addColumn<int>("dataLength"); + + QTest::addRow("pattern.pkm") << QStringLiteral(":/texturefiles/pattern.pkm") + << QSize(64, 64) + << quint32(0x0) + << quint32(0x8d64) + << 1 + << 16 + << 2048; + + QTest::addRow("car.ktx") << QStringLiteral(":/texturefiles/car.ktx") + << QSize(146, 80) + << quint32(0x0) + << quint32(0x9278) + << 1 + << 68 + << 11840; +} + +void tst_qtexturefilereader::checkHandlers() +{ + QFETCH(QString, fileName); + QFETCH(QSize, size); + QFETCH(quint32, glFormat); + QFETCH(quint32, glInternalFormat); + QFETCH(int, levels); + QFETCH(int, dataOffset); + QFETCH(int, dataLength); + + QFile f(fileName); + QVERIFY(f.open(QIODevice::ReadOnly)); + QTextureFileReader r(&f, fileName); + QVERIFY(r.canRead()); + + QTextureFileData tex = r.read(); + QVERIFY(!tex.isNull()); + QVERIFY(tex.isValid()); + QCOMPARE(tex.size(), size); + QCOMPARE(tex.glFormat(), glFormat); + QCOMPARE(tex.glInternalFormat(), glInternalFormat); + QCOMPARE(tex.numLevels(), levels); + QCOMPARE(tex.dataOffset(), dataOffset); + QCOMPARE(tex.dataLength(), dataLength); +} + +QTEST_MAIN(tst_qtexturefilereader) + +#include "tst_qtexturefilereader.moc" diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro index 940e892e5f..2789ffb55d 100644 --- a/tests/auto/gui/util/util.pro +++ b/tests/auto/gui/util/util.pro @@ -10,4 +10,4 @@ SUBDIRS= \ qshadergraphloader \ qshadernodes \ qshadernodesloader \ - + qtexturefilereader |