aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp')
-rw-r--r--src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp171
1 files changed, 40 insertions, 131 deletions
diff --git a/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp b/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp
index 62066a136a..daec23d478 100644
--- a/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp
+++ b/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp
@@ -38,173 +38,82 @@
****************************************************************************/
#include "qsgpkmhandler_p.h"
+#include "qsgcompressedtexture_p.h"
#include <QFile>
#include <QDebug>
#include <qendian.h>
#include <qopenglfunctions.h>
#include <qqmlfile.h>
+#include <QOpenGLTexture>
//#define ETC_DEBUG
-#ifndef GL_ETC1_RGB8_OES
- #define GL_ETC1_RGB8_OES 0x8d64
-#endif
-
-#ifndef GL_COMPRESSED_RGB8_ETC2
- #define GL_COMPRESSED_RGB8_ETC2 0x9274
-#endif
-
-#ifndef GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
- #define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
-#endif
-
-#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
- #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
-#endif
-
QT_BEGIN_NAMESPACE
static const int headerSize = 16;
static unsigned int typeMap[5] = {
- GL_ETC1_RGB8_OES,
- GL_COMPRESSED_RGB8_ETC2,
- 0, // unused
- GL_COMPRESSED_RGBA8_ETC2_EAC,
- GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ QOpenGLTexture::RGB8_ETC1, // GL_ETC1_RGB8_OES,
+ QOpenGLTexture::RGB8_ETC2, // GL_COMPRESSED_RGB8_ETC2,
+ 0, // unused (obsolete)
+ QOpenGLTexture::RGBA8_ETC2_EAC, // GL_COMPRESSED_RGBA8_ETC2_EAC,
+ QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2 // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
};
-QEtcTexture::QEtcTexture()
- : m_texture_id(0), m_uploaded(false)
-{
- initializeOpenGLFunctions();
-}
-
-QEtcTexture::~QEtcTexture()
-{
- if (m_texture_id)
- glDeleteTextures(1, &m_texture_id);
-}
-
-int QEtcTexture::textureId() const
-{
- if (m_texture_id == 0) {
- QEtcTexture *texture = const_cast<QEtcTexture*>(this);
- texture->glGenTextures(1, &texture->m_texture_id);
- }
- return m_texture_id;
-}
-
-bool QEtcTexture::hasAlphaChannel() const
-{
- return m_type == GL_COMPRESSED_RGBA8_ETC2_EAC ||
- m_type == GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
-}
-
-
-void QEtcTexture::bind()
+bool QSGPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
- if (m_uploaded && m_texture_id) {
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
- return;
- }
-
- if (m_texture_id == 0)
- glGenTextures(1, &m_texture_id);
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
-
-#ifdef ETC_DEBUG
- qDebug() << "glCompressedTexImage2D, width: " << m_size.width() << "height" << m_size.height() <<
- "paddedWidth: " << m_paddedSize.width() << "paddedHeight: " << m_paddedSize.height();
-#endif
+ Q_UNUSED(suffix)
-#ifndef QT_NO_DEBUG
- while (glGetError() != GL_NO_ERROR) { }
-#endif
-
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- Q_ASSERT(ctx != 0);
- const int compFactor = m_type == GL_COMPRESSED_RGBA8_ETC2_EAC ? 1 : 2;
- ctx->functions()->glCompressedTexImage2D(GL_TEXTURE_2D, 0, m_type,
- m_size.width(), m_size.height(), 0,
- (m_paddedSize.width() * m_paddedSize.height()) / compFactor,
- m_data.data() + headerSize);
-
-#ifndef QT_NO_DEBUG
- // Gracefully fail in case of an error...
- GLuint error = glGetError();
- if (error != GL_NO_ERROR) {
- qDebug () << "glCompressedTexImage2D for compressed texture failed, error: " << error;
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &m_texture_id);
- m_texture_id = 0;
- return;
- }
-#endif
-
- m_uploaded = true;
- updateBindOptions(true);
+ return block.startsWith("PKM ");
}
-class QEtcTextureFactory : public QQuickTextureFactory
-{
-public:
- QByteArray m_data;
- QSize m_size;
- QSize m_paddedSize;
- unsigned int m_type;
-
- QSize textureSize() const { return m_size; }
- int textureByteCount() const { return m_data.size(); }
-
- QSGTexture *createTexture(QQuickWindow *) const {
- QEtcTexture *texture = new QEtcTexture;
- texture->m_data = m_data;
- texture->m_size = m_size;
- texture->m_paddedSize = m_paddedSize;
- texture->m_type = m_type;
- return texture;
- }
-};
-
-QQuickTextureFactory *QSGPkmHandler::read(QIODevice *device)
+QQuickTextureFactory *QSGPkmHandler::read()
{
- QScopedPointer<QEtcTextureFactory> ret(new QEtcTextureFactory);
- ret->m_data = device->readAll();
- if (ret->m_data.isEmpty() || ret->m_data.size() < headerSize)
+ if (!device())
return nullptr;
- const char *rawData = ret->m_data.constData();
+ QSGCompressedTexture::DataPtr texData(QSGCompressedTexture::DataPtr::create());
- // magic number
- if (qstrncmp(rawData, "PKM ", 4) != 0)
+ texData->data = device()->readAll();
+ if (texData->data.size() < headerSize || !canRead(QByteArray(), texData->data)) {
+ qCDebug(QSG_LOG_TEXTUREIO, "Invalid PKM file %s", logName().constData());
return nullptr;
+ }
+
+ const char *rawData = texData->data.constData();
- // currently ignore version (rawData + 4)
+ // ignore version (rawData + 4 & 5)
// texture type
quint16 type = qFromBigEndian<quint16>(rawData + 6);
- static int typeCount = sizeof(typeMap)/sizeof(typeMap[0]);
- if (type >= typeCount)
+ if (type > sizeof(typeMap)/sizeof(typeMap[0])) {
+ qCDebug(QSG_LOG_TEXTUREIO, "Unknown compression format in PKM file %s", logName().constData());
return nullptr;
- ret->m_type = typeMap[type];
+ }
+ texData->format = typeMap[type];
+ texData->hasAlpha = !QSGCompressedTexture::formatIsOpaque(texData->format);
// texture size
- ret->m_paddedSize.setWidth(qFromBigEndian<quint16>(rawData + 8));
- ret->m_paddedSize.setHeight(qFromBigEndian<quint16>(rawData + 10));
- if ((ret->m_paddedSize.width() * ret->m_paddedSize.height()) / 2 > ret->m_data.size() - headerSize)
- return nullptr;
- ret->m_size.setWidth(qFromBigEndian<quint16>(rawData + 12));
- ret->m_size.setHeight(qFromBigEndian<quint16>(rawData + 14));
- if (ret->m_size.isEmpty())
+ /* Actual data length depends on format; for now just use 0, i.e. rest-of-file
+ QSize paddedSize(qFromBigEndian<quint16>(rawData + 8), qFromBigEndian<quint16>(rawData + 10));
+ texData->dataLength = (paddedSize.width() / 4) * (paddedSize.height() / 4) * 8;
+ */
+ QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14));
+ texData->size = texSize;
+
+ texData->dataOffset = headerSize;
+
+ if (!texData->isValid()) {
+ qCDebug(QSG_LOG_TEXTUREIO, "Invalid values in header of PKM file %s", logName().constData());
return nullptr;
+ }
+ texData->logName = logName();
#ifdef ETC_DEBUG
- qDebug() << "requestTexture returning: " << ret->m_data.length() << "bytes; width: " << ret->m_size.width() << ", height: " << ret->m_size.height();
+ qDebug() << "PKM file handler read" << texData.data();
#endif
-
- return ret.take();
+ return new QSGCompressedTextureFactory(texData);
}
QT_END_NAMESPACE