diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-03-08 18:35:03 +0100 |
---|---|---|
committer | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-03-08 18:35:03 +0100 |
commit | d9ea4917ca97aeee050a86151fbfa069771b498d (patch) | |
tree | 21fd6960d8a866bf6f5a5a8f9db9be801f8065c1 /src/quick/scenegraph/util | |
parent | f9beafddd256cd0b79bf2478a812053ef61241fc (diff) | |
parent | c6a26c248e8abc421b87c3dd6b2466d490ea902e (diff) |
Merge remote-tracking branch 'gerrit/5.11' into wip/webassembly
Change-Id: I729af792166fd2f6c5843ba564e63adf8ae09a97
Diffstat (limited to 'src/quick/scenegraph/util')
25 files changed, 407 insertions, 239 deletions
diff --git a/src/quick/scenegraph/util/qsgareaallocator.cpp b/src/quick/scenegraph/util/qsgareaallocator.cpp index 67a9fa285a..cd270a1d63 100644 --- a/src/quick/scenegraph/util/qsgareaallocator.cpp +++ b/src/quick/scenegraph/util/qsgareaallocator.cpp @@ -72,8 +72,8 @@ struct QSGAreaAllocatorNode QSGAreaAllocatorNode::QSGAreaAllocatorNode(QSGAreaAllocatorNode *parent) : parent(parent) - , left(0) - , right(0) + , left(nullptr) + , right(nullptr) , isOccupied(false) { } @@ -86,14 +86,14 @@ QSGAreaAllocatorNode::~QSGAreaAllocatorNode() bool QSGAreaAllocatorNode::isLeaf() { - Q_ASSERT((left != 0) == (right != 0)); + Q_ASSERT((left != nullptr) == (right != nullptr)); return !left; } QSGAreaAllocator::QSGAreaAllocator(const QSize &size) : m_size(size) { - m_root = new QSGAreaAllocatorNode(0); + m_root = new QSGAreaAllocatorNode(nullptr); } QSGAreaAllocator::~QSGAreaAllocator() @@ -179,13 +179,13 @@ bool QSGAreaAllocator::deallocateInNode(const QPoint &pos, QSGAreaAllocatorNode void QSGAreaAllocator::mergeNodeWithNeighbors(QSGAreaAllocatorNode *node) { bool done = false; - QSGAreaAllocatorNode *parent = 0; - QSGAreaAllocatorNode *current = 0; + QSGAreaAllocatorNode *parent = nullptr; + QSGAreaAllocatorNode *current = nullptr; QSGAreaAllocatorNode *sibling; while (!done) { Q_ASSERT(node->isLeaf()); Q_ASSERT(!node->isOccupied); - if (node->parent == 0) + if (node->parent == nullptr) return; // No neighbours. SplitType splitType = SplitType(node->parent->splitType); @@ -238,7 +238,7 @@ void QSGAreaAllocator::mergeNodeWithNeighbors(QSGAreaAllocatorNode *node) } sibling->parent = parent->parent; *nodeRef = sibling; - parent->left = parent->right = 0; + parent->left = parent->right = nullptr; delete parent; delete neighbor; done = false; @@ -276,7 +276,7 @@ void QSGAreaAllocator::mergeNodeWithNeighbors(QSGAreaAllocatorNode *node) } sibling->parent = parent->parent; *nodeRef = sibling; - parent->left = parent->right = 0; + parent->left = parent->right = nullptr; delete parent; delete neighbor; done = false; diff --git a/src/quick/scenegraph/util/qsgareaallocator_p.h b/src/quick/scenegraph/util/qsgareaallocator_p.h index aa40ff0a6e..8bc05a5a5b 100644 --- a/src/quick/scenegraph/util/qsgareaallocator_p.h +++ b/src/quick/scenegraph/util/qsgareaallocator_p.h @@ -67,7 +67,7 @@ public: QRect allocate(const QSize &size); bool deallocate(const QRect &rect); - bool isEmpty() const { return m_root == 0; } + bool isEmpty() const { return m_root == nullptr; } QSize size() const { return m_size; } private: bool allocateInNode(const QSize &size, QPoint &result, const QRect ¤tRect, QSGAreaAllocatorNode *node); diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 22f0b13f46..7608a81ddc 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -44,6 +44,7 @@ #include <QtCore/QtMath> #include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLTexture> #include <QtGui/QOpenGLFunctions> #include <QtGui/QGuiApplication> #include <QtGui/QScreen> @@ -51,7 +52,10 @@ #include <QtGui/QWindow> #include <QtGui/qpa/qplatformnativeinterface.h> +#include <private/qqmlglobal_p.h> #include <private/qsgtexture_p.h> +#include <private/qsgcompressedtexture_p.h> +#include <private/qsgcompressedatlastexture_p.h> #include <private/qquickprofiler_p.h> @@ -65,11 +69,13 @@ int qt_sg_envInt(const char *name, int defaultValue); static QElapsedTimer qsg_renderer_timer; +DEFINE_BOOL_CONFIG_OPTION(qsgEnableCompressedAtlas, QSG_ENABLE_COMPRESSED_ATLAS) + namespace QSGAtlasTexture { Manager::Manager() - : m_atlas(0) + : m_atlas(nullptr) { QOpenGLContext *gl = QOpenGLContext::currentContext(); Q_ASSERT(gl); @@ -99,7 +105,8 @@ Manager::Manager() Manager::~Manager() { - Q_ASSERT(m_atlas == 0); + Q_ASSERT(m_atlas == nullptr); + Q_ASSERT(m_atlases.isEmpty()); } void Manager::invalidate() @@ -107,13 +114,21 @@ void Manager::invalidate() if (m_atlas) { m_atlas->invalidate(); m_atlas->deleteLater(); - m_atlas = 0; + m_atlas = nullptr; + } + + QHash<unsigned int, QSGCompressedAtlasTexture::Atlas*>::iterator i = m_atlases.begin(); + while (i != m_atlases.end()) { + i.value()->invalidate(); + i.value()->deleteLater(); + ++i; } + m_atlases.clear(); } QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel) { - Texture *t = 0; + Texture *t = nullptr; if (image.width() < m_atlas_size_limit && image.height() < m_atlas_size_limit) { if (!m_atlas) m_atlas = new Atlas(m_atlas_size); @@ -125,13 +140,147 @@ QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel) return t; } -Atlas::Atlas(const QSize &size) +QSGTexture *Manager::create(const QSGCompressedTextureFactory *factory) +{ + QSGTexture *t = nullptr; + if (!qsgEnableCompressedAtlas() || !factory->m_textureData || !factory->m_textureData->isValid()) + return t; + + // TODO: further abstract the atlas and remove this restriction + unsigned int format = factory->m_textureData->format; + switch (format) { + case QOpenGLTexture::RGB8_ETC1: + case QOpenGLTexture::RGB8_ETC2: + case QOpenGLTexture::RGBA8_ETC2_EAC: + case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: + break; + default: + return t; + } + + QSize size = factory->m_textureData->size; + if (size.width() < m_atlas_size_limit && size.height() < m_atlas_size_limit) { + QHash<unsigned int, QSGCompressedAtlasTexture::Atlas*>::iterator i = m_atlases.find(format); + if (i == m_atlases.end()) + i = m_atlases.insert(format, new QSGCompressedAtlasTexture::Atlas(m_atlas_size, format)); + // must be multiple of 4 + QSize paddedSize(((size.width() + 3) / 4) * 4, ((size.height() + 3) / 4) * 4); + QByteArray data = factory->m_textureData->data; + t = i.value()->create(data, factory->m_textureData->sizeInBytes(), factory->m_textureData->dataOffset, size, paddedSize); + } + return t; +} + +AtlasBase::AtlasBase(const QSize &size) : m_allocator(size) , m_texture_id(0) , m_size(size) - , m_atlas_transient_image_threshold(0) , m_allocated(false) { +} + +AtlasBase::~AtlasBase() +{ + Q_ASSERT(!m_texture_id); +} + +void AtlasBase::invalidate() +{ + if (m_texture_id && QOpenGLContext::currentContext()) + QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id); + m_texture_id = 0; +} + +int AtlasBase::textureId() const +{ + if (!m_texture_id) { + Q_ASSERT(QOpenGLContext::currentContext()); + QOpenGLContext::currentContext()->functions()->glGenTextures(1, &const_cast<AtlasBase *>(this)->m_texture_id); + } + + return m_texture_id; +} + +void AtlasBase::bind(QSGTexture::Filtering filtering) +{ + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + if (!m_allocated) { + m_allocated = true; + + while (funcs->glGetError() != GL_NO_ERROR) ; + + funcs->glGenTextures(1, &m_texture_id); + funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#if !defined(QT_OPENGL_ES_2) + if (!QOpenGLContext::currentContext()->isOpenGLES()) + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); +#endif + generateTexture(); + + GLenum errorCode = funcs->glGetError(); + if (errorCode == GL_OUT_OF_MEMORY) { + qDebug("QSGTextureAtlas: texture atlas allocation failed, out of memory"); + funcs->glDeleteTextures(1, &m_texture_id); + m_texture_id = 0; + } else if (errorCode != GL_NO_ERROR) { + qDebug("QSGTextureAtlas: texture atlas allocation failed, code=%x", errorCode); + funcs->glDeleteTextures(1, &m_texture_id); + m_texture_id = 0; + } + } else { + funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); + } + + if (m_texture_id == 0) + return; + + // Upload all pending images.. + for (int i=0; i<m_pending_uploads.size(); ++i) { + + bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled(); + if (profileFrames) + qsg_renderer_timer.start(); + + Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare); + + // Skip bind, convert, swizzle; they're irrelevant + Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, + QQuickProfiler::SceneGraphTexturePrepareStart, 3); + + uploadPendingTexture(i); + + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare, + QQuickProfiler::SceneGraphTexturePrepareUpload); + + // Skip mipmap; unused + Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, + QQuickProfiler::SceneGraphTexturePrepareUpload, 1); + Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare, + QQuickProfiler::SceneGraphTexturePrepareMipmap); + } + + GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR; + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f); + + m_pending_uploads.clear(); +} + +void AtlasBase::remove(TextureBase *t) +{ + QRect atlasRect = t->atlasSubRect(); + m_allocator.deallocate(atlasRect); + m_pending_uploads.removeOne(t); +} + +Atlas::Atlas(const QSize &size) + : AtlasBase(size) + , m_atlas_transient_image_threshold(0) +{ m_internalFormat = GL_RGBA; m_externalFormat = GL_BGRA; @@ -188,14 +337,6 @@ Atlas::Atlas(const QSize &size) Atlas::~Atlas() { - Q_ASSERT(!m_texture_id); -} - -void Atlas::invalidate() -{ - if (m_texture_id && QOpenGLContext::currentContext()) - QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id); - m_texture_id = 0; } Texture *Atlas::create(const QImage &image) @@ -207,18 +348,7 @@ Texture *Atlas::create(const QImage &image) m_pending_uploads << t; return t; } - return 0; -} - - -int Atlas::textureId() const -{ - if (!m_texture_id) { - Q_ASSERT(QOpenGLContext::currentContext()); - QOpenGLContext::currentContext()->functions()->glGenTextures(1, &const_cast<Atlas *>(this)->m_texture_id); - } - - return m_texture_id; + return nullptr; } static void swizzleBGRAToRGBA(QImage *image) @@ -334,122 +464,70 @@ void Atlas::uploadBgra(Texture *texture) } } -void Atlas::bind(QSGTexture::Filtering filtering) +void Atlas::generateTexture() { QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - if (!m_allocated) { - m_allocated = true; - - while (funcs->glGetError() != GL_NO_ERROR) ; - - funcs->glGenTextures(1, &m_texture_id); - funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); -#endif - funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, 0); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, nullptr); #if 0 - QImage pink(m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied); - pink.fill(0); - QPainter p(&pink); - QLinearGradient redGrad(0, 0, m_size.width(), 0); - redGrad.setColorAt(0, Qt::black); - redGrad.setColorAt(1, Qt::red); - p.fillRect(0, 0, m_size.width(), m_size.height(), redGrad); - p.setCompositionMode(QPainter::CompositionMode_Plus); - QLinearGradient blueGrad(0, 0, 0, m_size.height()); - blueGrad.setColorAt(0, Qt::black); - blueGrad.setColorAt(1, Qt::blue); - p.fillRect(0, 0, m_size.width(), m_size.height(), blueGrad); - p.end(); - - funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, pink.constBits()); + QImage pink(m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied); + pink.fill(0); + QPainter p(&pink); + QLinearGradient redGrad(0, 0, m_size.width(), 0); + redGrad.setColorAt(0, Qt::black); + redGrad.setColorAt(1, Qt::red); + p.fillRect(0, 0, m_size.width(), m_size.height(), redGrad); + p.setCompositionMode(QPainter::CompositionMode_Plus); + QLinearGradient blueGrad(0, 0, 0, m_size.height()); + blueGrad.setColorAt(0, Qt::black); + blueGrad.setColorAt(1, Qt::blue); + p.fillRect(0, 0, m_size.width(), m_size.height(), blueGrad); + p.end(); + + funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, pink.constBits()); #endif +} - GLenum errorCode = funcs->glGetError(); - if (errorCode == GL_OUT_OF_MEMORY) { - qDebug("QSGTextureAtlas: texture atlas allocation failed, out of memory"); - funcs->glDeleteTextures(1, &m_texture_id); - m_texture_id = 0; - } else if (errorCode != GL_NO_ERROR) { - qDebug("QSGTextureAtlas: texture atlas allocation failed, code=%x", errorCode); - funcs->glDeleteTextures(1, &m_texture_id); - m_texture_id = 0; - } +void Atlas::uploadPendingTexture(int i) +{ + Texture *t = static_cast<Texture*>(m_pending_uploads.at(i)); + if (m_externalFormat == GL_BGRA && + !m_use_bgra_fallback) { + uploadBgra(t); } else { - funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); + upload(t); } - - if (m_texture_id == 0) - return; - - // Upload all pending images.. - for (int i=0; i<m_pending_uploads.size(); ++i) { - - bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled(); - if (profileFrames) - qsg_renderer_timer.start(); - - Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare); - - // Skip bind, convert, swizzle; they're irrelevant - Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, - QQuickProfiler::SceneGraphTexturePrepareStart, 3); - - Texture *t = m_pending_uploads.at(i); - if (m_externalFormat == GL_BGRA && - !m_use_bgra_fallback) { - uploadBgra(t); - } else { - upload(t); - } - const QSize textureSize = t->textureSize(); - if (textureSize.width() > m_atlas_transient_image_threshold || - textureSize.height() > m_atlas_transient_image_threshold) - t->releaseImage(); - - qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed() - << "ms (" << t->textureSize().width() << "x" - << t->textureSize().height() << ")"; - - Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare, - QQuickProfiler::SceneGraphTexturePrepareUpload); - - // Skip mipmap; unused - Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, - QQuickProfiler::SceneGraphTexturePrepareUpload, 1); - Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare, - QQuickProfiler::SceneGraphTexturePrepareMipmap); - } - - GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR; - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f); - - m_pending_uploads.clear(); + const QSize textureSize = t->textureSize(); + if (textureSize.width() > m_atlas_transient_image_threshold || + textureSize.height() > m_atlas_transient_image_threshold) + t->releaseImage(); + + qCDebug(QSG_LOG_TIME_TEXTURE, "atlastexture uploaded in: %lldms (%dx%d)", + qsg_renderer_timer.elapsed(), + t->textureSize().width(), + t->textureSize().height()); } -void Atlas::remove(Texture *t) +TextureBase::TextureBase(AtlasBase *atlas, const QRect &textureRect) + : m_allocated_rect(textureRect) + , m_atlas(atlas) { - QRect atlasRect = t->atlasSubRect(); - m_allocator.deallocate(atlasRect); - m_pending_uploads.removeOne(t); } +TextureBase::~TextureBase() +{ + m_atlas->remove(this); +} +void TextureBase::bind() +{ + m_atlas->bind(filtering()); +} Texture::Texture(Atlas *atlas, const QRect &textureRect, const QImage &image) - : QSGTexture() - , m_allocated_rect(textureRect) + : TextureBase(atlas, textureRect) , m_image(image) - , m_atlas(atlas) - , m_nonatlas_texture(0) + , m_nonatlas_texture(nullptr) , m_has_alpha(image.hasAlphaChannel()) { float w = atlas->size().width(); @@ -463,16 +541,10 @@ Texture::Texture(Atlas *atlas, const QRect &textureRect, const QImage &image) Texture::~Texture() { - m_atlas->remove(this); if (m_nonatlas_texture) delete m_nonatlas_texture; } -void Texture::bind() -{ - m_atlas->bind(filtering()); -} - QSGTexture *Texture::removedFromAtlas() const { if (m_nonatlas_texture) { @@ -508,7 +580,7 @@ QSGTexture *Texture::removedFromAtlas() const QRect r = atlasSubRectWithoutPadding(); // and copy atlas into our texture. while (f->glGetError() != GL_NO_ERROR) ; - f->glCopyTexImage2D(GL_TEXTURE_2D, 0, m_atlas->internalFormat(), r.x(), r.y(), r.width(), r.height(), 0); + f->glCopyTexImage2D(GL_TEXTURE_2D, 0, static_cast<Atlas*>(m_atlas)->internalFormat(), r.x(), r.y(), r.width(), r.height(), 0); // BGRA may have been rejected by some GLES implementations if (f->glGetError() != GL_NO_ERROR) f->glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r.x(), r.y(), r.width(), r.height(), 0); diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h index 3dee539547..14dc8f7958 100644 --- a/src/quick/scenegraph/util/qsgatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgatlastexture_p.h @@ -61,10 +61,16 @@ QT_BEGIN_NAMESPACE +namespace QSGCompressedAtlasTexture { + class Atlas; +} +class QSGCompressedTextureFactory; + namespace QSGAtlasTexture { class Texture; +class TextureBase; class Atlas; class Manager : public QObject @@ -76,93 +82,121 @@ public: ~Manager(); QSGTexture *create(const QImage &image, bool hasAlphaChannel); + QSGTexture *create(const QSGCompressedTextureFactory *factory); void invalidate(); private: Atlas *m_atlas; + // set of atlases for different compressed formats + QHash<unsigned int, QSGCompressedAtlasTexture::Atlas*> m_atlases; QSize m_atlas_size; int m_atlas_size_limit; }; -class Atlas : public QObject +class AtlasBase : public QObject { + Q_OBJECT public: - Atlas(const QSize &size); - ~Atlas(); + AtlasBase(const QSize &size); + ~AtlasBase(); void invalidate(); int textureId() const; void bind(QSGTexture::Filtering filtering); + void remove(TextureBase *t); + + QSize size() const { return m_size; } + +protected: + virtual void generateTexture() = 0; + virtual void uploadPendingTexture(int i) = 0; + +protected: + QSGAreaAllocator m_allocator; + unsigned int m_texture_id; + QSize m_size; + QList<TextureBase *> m_pending_uploads; + +private: + bool m_allocated; +}; + +class Atlas : public AtlasBase +{ +public: + Atlas(const QSize &size); + ~Atlas(); + + void generateTexture() override; + void uploadPendingTexture(int i) override; + void upload(Texture *texture); void uploadBgra(Texture *texture); Texture *create(const QImage &image); - void remove(Texture *t); - - QSize size() const { return m_size; } uint internalFormat() const { return m_internalFormat; } uint externalFormat() const { return m_externalFormat; } private: - QSGAreaAllocator m_allocator; - unsigned int m_texture_id; - QSize m_size; - QList<Texture *> m_pending_uploads; - uint m_internalFormat; uint m_externalFormat; int m_atlas_transient_image_threshold; - uint m_allocated : 1; uint m_use_bgra_fallback: 1; - uint m_debug_overlay : 1; }; -class Texture : public QSGTexture +class TextureBase : public QSGTexture +{ + Q_OBJECT +public: + TextureBase(AtlasBase *atlas, const QRect &textureRect); + ~TextureBase(); + + int textureId() const override { return m_atlas->textureId(); } + bool isAtlasTexture() const override { return true; } + + QRect atlasSubRect() const { return m_allocated_rect; } + + void bind() override; + +protected: + QRect m_allocated_rect; + AtlasBase *m_atlas; +}; + +class Texture : public TextureBase { Q_OBJECT public: Texture(Atlas *atlas, const QRect &textureRect, const QImage &image); ~Texture(); - int textureId() const override { return m_atlas->textureId(); } QSize textureSize() const override { return atlasSubRectWithoutPadding().size(); } void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; } bool hasAlphaChannel() const override { return m_has_alpha; } bool hasMipmaps() const override { return false; } - bool isAtlasTexture() const override { return true; } QRectF normalizedTextureSubRect() const override { return m_texture_coords_rect; } QRect atlasSubRect() const { return m_allocated_rect; } QRect atlasSubRectWithoutPadding() const { return m_allocated_rect.adjusted(1, 1, -1, -1); } - bool isTexture() const { return true; } - QSGTexture *removedFromAtlas() const override; void releaseImage() { m_image = QImage(); } const QImage &image() const { return m_image; } - void bind() override; - private: - QRect m_allocated_rect; QRectF m_texture_coords_rect; - QImage m_image; - - Atlas *m_atlas; - mutable QSGPlainTexture *m_nonatlas_texture; - - uint m_has_alpha : 1; + bool m_has_alpha; }; } diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp index 9ffd1b4b08..981ea089be 100644 --- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp +++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp @@ -78,11 +78,11 @@ QSGDefaultPainterNode::QSGDefaultPainterNode(QQuickPaintedItem *item) , m_preferredRenderTarget(QQuickPaintedItem::Image) , m_actualRenderTarget(QQuickPaintedItem::Image) , m_item(item) - , m_fbo(0) - , m_multisampledFbo(0) + , m_fbo(nullptr) + , m_multisampledFbo(nullptr) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) - , m_texture(0) - , m_gl_device(0) + , m_texture(nullptr) + , m_gl_device(nullptr) , m_fillColor(Qt::transparent) , m_contentsScale(1.0) , m_dirtyContents(false) @@ -260,8 +260,8 @@ void QSGDefaultPainterNode::updateRenderTarget() delete m_fbo; delete m_multisampledFbo; delete m_gl_device; - m_fbo = m_multisampledFbo = 0; - m_gl_device = 0; + m_fbo = m_multisampledFbo = nullptr; + m_gl_device = nullptr; } if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject || @@ -275,7 +275,7 @@ void QSGDefaultPainterNode::updateRenderTarget() delete m_fbo; delete m_multisampledFbo; - m_fbo = m_multisampledFbo = 0; + m_fbo = m_multisampledFbo = nullptr; if (m_gl_device) m_gl_device->setSize(m_fboSize); diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp index ba0207aca8..56508af152 100644 --- a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp +++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE QSGDepthStencilBuffer::QSGDepthStencilBuffer(QOpenGLContext *context, const Format &format) : m_functions(context) - , m_manager(0) + , m_manager(nullptr) , m_format(format) , m_depthBuffer(0) , m_stencilBuffer(0) @@ -160,7 +160,7 @@ QSGDepthStencilBufferManager::~QSGDepthStencilBufferManager() for (Hash::const_iterator it = m_buffers.constBegin(), cend = m_buffers.constEnd(); it != cend; ++it) { QSGDepthStencilBuffer *buffer = it.value().data(); buffer->free(); - buffer->m_manager = 0; + buffer->m_manager = nullptr; } } @@ -174,7 +174,7 @@ QSharedPointer<QSGDepthStencilBuffer> QSGDepthStencilBufferManager::bufferForFor void QSGDepthStencilBufferManager::insertBuffer(const QSharedPointer<QSGDepthStencilBuffer> &buffer) { - Q_ASSERT(buffer->m_manager == 0); + Q_ASSERT(buffer->m_manager == nullptr); Q_ASSERT(!m_buffers.contains(buffer->m_format)); buffer->m_manager = this; m_buffers.insert(buffer->m_format, buffer.toWeakRef()); diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp index dffe199224..91fa46033c 100644 --- a/src/quick/scenegraph/util/qsgengine.cpp +++ b/src/quick/scenegraph/util/qsgengine.cpp @@ -157,7 +157,7 @@ QSGAbstractRenderer *QSGEngine::createRenderer() const { Q_D(const QSGEngine); if (!d->sgRenderContext->isValid()) - return 0; + return nullptr; QSGRenderer *renderer = d->sgRenderContext->createRenderer(); renderer->setCustomRenderMode(qgetenv("QSG_VISUALIZE")); @@ -178,7 +178,7 @@ QSGTexture *QSGEngine::createTextureFromImage(const QImage &image, CreateTexture { Q_D(const QSGEngine); if (!d->sgRenderContext->isValid()) - return 0; + return nullptr; uint flags = 0; if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas; if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha; @@ -206,7 +206,7 @@ QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, CreateTex texture->setTextureSize(size); return texture; } - return 0; + return nullptr; } /*! diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h index 514e6e8c2b..e9e01dc710 100644 --- a/src/quick/scenegraph/util/qsgengine.h +++ b/src/quick/scenegraph/util/qsgengine.h @@ -68,7 +68,7 @@ public: Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption) explicit QSGEngine(QObject *parent = nullptr); - ~QSGEngine(); + ~QSGEngine() override; void initialize(QOpenGLContext *context); void invalidate(); diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp index a0c71b5340..28f6113a60 100644 --- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp +++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp @@ -77,13 +77,13 @@ FlatColorMaterialShader::FlatColorMaterialShader() void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) { #if QT_CONFIG(opengl) - Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type()); + Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type()); QSGFlatColorMaterial *oldMaterial = static_cast<QSGFlatColorMaterial *>(oldEffect); QSGFlatColorMaterial *newMaterial = static_cast<QSGFlatColorMaterial *>(newEffect); const QColor &c = newMaterial->color(); - if (oldMaterial == 0 || c != oldMaterial->color() || state.isOpacityDirty()) { + if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) { float opacity = state.opacity() * c.alphaF(); QVector4D v(c.redF() * opacity, c.greenF() * opacity, @@ -103,7 +103,7 @@ void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial char const *const *FlatColorMaterialShader::attributeNames() const { - static char const *const attr[] = { "vCoord", 0 }; + static char const *const attr[] = { "vCoord", nullptr }; return attr; } diff --git a/src/quick/scenegraph/util/qsgimagenode.cpp b/src/quick/scenegraph/util/qsgimagenode.cpp index c03c91d1cb..b154023247 100644 --- a/src/quick/scenegraph/util/qsgimagenode.cpp +++ b/src/quick/scenegraph/util/qsgimagenode.cpp @@ -168,7 +168,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QSGImageNode::TextureCoordinatesTransformMode textureCoordinatesTransform() const + \fn QSGImageNode::TextureCoordinatesTransformMode QSGImageNode::textureCoordinatesTransform() const Returns the mode used to generate texture coordinates for this node. */ @@ -187,6 +187,15 @@ QT_BEGIN_NAMESPACE \return \c true if the node takes ownership of the texture; otherwise \c false. */ +/*! + Updates the geometry \a g with the \a texture, the coordinates + in \a rect, and the texture coordinates from \a sourceRect. + + \a g is assumed to be a triangle strip of four vertices of type + QSGGeometry::TexturedPoint2D. + + \a texCoordMode is used for normalizing the \a sourceRect. + */ void QSGImageNode::rebuildGeometry(QSGGeometry *g, QSGTexture *texture, const QRectF &rect, diff --git a/src/quick/scenegraph/util/qsgimagenode.h b/src/quick/scenegraph/util/qsgimagenode.h index 0e053c307f..526f52b7e5 100644 --- a/src/quick/scenegraph/util/qsgimagenode.h +++ b/src/quick/scenegraph/util/qsgimagenode.h @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE class Q_QUICK_EXPORT QSGImageNode : public QSGGeometryNode { public: - virtual ~QSGImageNode() { } + ~QSGImageNode() override { } virtual void setRect(const QRectF &rect) = 0; inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); } diff --git a/src/quick/scenegraph/util/qsgninepatchnode.h b/src/quick/scenegraph/util/qsgninepatchnode.h index 8509cbd326..e76afd3c4a 100644 --- a/src/quick/scenegraph/util/qsgninepatchnode.h +++ b/src/quick/scenegraph/util/qsgninepatchnode.h @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE class Q_QUICK_EXPORT QSGNinePatchNode : public QSGGeometryNode { public: - virtual ~QSGNinePatchNode() { } + ~QSGNinePatchNode() override { } virtual void setTexture(QSGTexture *texture) = 0; virtual void setBounds(const QRectF &bounds) = 0; diff --git a/src/quick/scenegraph/util/qsgrectanglenode.h b/src/quick/scenegraph/util/qsgrectanglenode.h index 8e0da1d9c7..ba52b65b07 100644 --- a/src/quick/scenegraph/util/qsgrectanglenode.h +++ b/src/quick/scenegraph/util/qsgrectanglenode.h @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE class Q_QUICK_EXPORT QSGRectangleNode : public QSGGeometryNode { public: - virtual ~QSGRectangleNode() { } + ~QSGRectangleNode() override { } virtual void setRect(const QRectF &rect) = 0; inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); } diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index e134a5d4d3..93fc213f2e 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -262,8 +262,8 @@ void QSGShaderSourceBuilder::addDefinition(const QByteArray &definition) tok.initialize(input); // First find #version, #extension's and "void main() { ... " - const char *versionPos = 0; - const char *extensionPos = 0; + const char *versionPos = nullptr; + const char *extensionPos = nullptr; bool inSingleLineComment = false; bool inMultiLineComment = false; bool foundVersionStart = false; @@ -325,8 +325,8 @@ void QSGShaderSourceBuilder::removeVersion() tok.initialize(input); // First find #version beginning and end (if present) - const char *versionStartPos = 0; - const char *versionEndPos = 0; + const char *versionStartPos = nullptr; + const char *versionEndPos = nullptr; bool inSingleLineComment = false; bool inMultiLineComment = false; bool foundVersionStart = false; @@ -361,7 +361,7 @@ void QSGShaderSourceBuilder::removeVersion() t = tok.next(); } - if (versionStartPos == 0) + if (versionStartPos == nullptr) return; // Construct a new shader string, inserting the definition diff --git a/src/quick/scenegraph/util/qsgsimplematerial.cpp b/src/quick/scenegraph/util/qsgsimplematerial.cpp index f29c58ad9e..376f7dce5c 100644 --- a/src/quick/scenegraph/util/qsgsimplematerial.cpp +++ b/src/quick/scenegraph/util/qsgsimplematerial.cpp @@ -173,17 +173,17 @@ /*! - \fn char const *const *QSGSimpleMaterialShader::attributeNames() const + \fn template <typename State> char const *const *QSGSimpleMaterialShader<State>::attributeNames() const \internal */ /*! - \fn void QSGSimpleMaterialShader::initialize() + \fn template <typename State> void QSGSimpleMaterialShader<State>::initialize() \internal */ /*! - \fn void QSGSimpleMaterialShader::resolveUniforms() + \fn template <typename State> void QSGSimpleMaterialShader<State>::resolveUniforms() Reimplement this function to resolve the location of named uniforms in the shader program. @@ -192,34 +192,34 @@ */ /*! - \fn const char *QSGSimpleMaterialShader::uniformMatrixName() const + \fn template <typename State> const char *QSGSimpleMaterialShader<State>::uniformMatrixName() const Returns the name for the transform matrix uniform of this item. The default value is \c qt_Matrix. */ /*! - \fn const char *QSGSimpleMaterialShader::uniformOpacityName() const + \fn template <typename State> const char *QSGSimpleMaterialShader<State>::uniformOpacityName() const Returns the name for the opacity uniform of this item. The default value is \c qt_Opacity. */ /*! - \fn void QSGSimpleMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) + \fn template <typename State> void QSGSimpleMaterialShader<State>::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) \internal */ /*! - \fn QList<QByteArray> QSGSimpleMaterialShader::attributes() const + \fn template <typename State> QList<QByteArray> QSGSimpleMaterialShader<State>::attributes() const Returns a list of names, declaring the vertex attributes in the vertex shader. */ /*! - \fn void QSGSimpleMaterialShader::updateState(const State *newState, const State *oldState) + \fn template <typename State> void QSGSimpleMaterialShader<State>::updateState(const State *newState, const State *oldState) Called whenever the state of this shader should be updated from \a oldState to \a newState, typical for each new set of diff --git a/src/quick/scenegraph/util/qsgsimplematerial.h b/src/quick/scenegraph/util/qsgsimplematerial.h index b5b8815b4a..79180ca8e2 100644 --- a/src/quick/scenegraph/util/qsgsimplematerial.h +++ b/src/quick/scenegraph/util/qsgsimplematerial.h @@ -138,7 +138,7 @@ template <typename State> class QSGSimpleMaterial : public QSGMaterial { public: -#ifndef qdoc +#ifndef Q_CLANG_QDOC QSGSimpleMaterial(const State &aState, PtrShaderCreateFunc func) : m_state(aState) , m_func(func) @@ -185,7 +185,7 @@ public: QSGSimpleMaterialComparableMaterial(PtrShaderCreateFunc func) : QSGSimpleMaterial<State>(func) {} - int compare(const QSGMaterial *other) const { + int compare(const QSGMaterial *other) const override { return QSGSimpleMaterialComparableMaterial<State>::state()->compare(static_cast<const QSGSimpleMaterialComparableMaterial<State> *>(other)->state()); } }; @@ -207,7 +207,7 @@ Q_INLINE_TEMPLATE void QSGSimpleMaterialShader<State>::updateState(const RenderS Q_UNUSED(state) #endif State *ns = static_cast<QSGSimpleMaterial<State> *>(newMaterial)->state(); - State *old = 0; + State *old = nullptr; if (oldMaterial) old = static_cast<QSGSimpleMaterial<State> *>(oldMaterial)->state(); updateState(ns, old); diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 6ce37de7cb..0c49ca9aa5 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -47,8 +47,7 @@ class QSGSimpleTextureNodePrivate : public QSGGeometryNodePrivate { public: QSGSimpleTextureNodePrivate() - : QSGGeometryNodePrivate() - , texCoordMode(QSGSimpleTextureNode::NoTransform) + : texCoordMode(QSGSimpleTextureNode::NoTransform) , isAtlasTexture(false) , ownsTexture(false) {} diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h index 09e4277c66..010463d3c6 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.h +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h @@ -52,7 +52,7 @@ class Q_QUICK_EXPORT QSGSimpleTextureNode : public QSGGeometryNode { public: QSGSimpleTextureNode(); - ~QSGSimpleTextureNode(); + ~QSGSimpleTextureNode() override; void setRect(const QRectF &rect); inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); } diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index 4f11d95e70..fea92a5121 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -53,7 +53,7 @@ #endif #include <private/qsgmaterialshader_p.h> -#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(__UCLIBC__) +#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && defined(__GLIBC__) #define CAN_BACKTRACE_EXECINFO #endif @@ -399,7 +399,7 @@ QSGTexture::~QSGTexture() QSGTexture *QSGTexture::removedFromAtlas() const { Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture"); - return 0; + return nullptr; } /*! diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h index 032129434e..7bd57a16e3 100644 --- a/src/quick/scenegraph/util/qsgtexture.h +++ b/src/quick/scenegraph/util/qsgtexture.h @@ -54,7 +54,7 @@ class Q_QUICK_EXPORT QSGTexture : public QObject public: QSGTexture(); - ~QSGTexture(); + ~QSGTexture() override; enum WrapMode { Repeat, diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h index 52dc6db2d0..18dd5eff68 100644 --- a/src/quick/scenegraph/util/qsgtexture_p.h +++ b/src/quick/scenegraph/util/qsgtexture_p.h @@ -83,7 +83,7 @@ class Q_QUICK_PRIVATE_EXPORT QSGPlainTexture : public QSGTexture Q_OBJECT public: QSGPlainTexture(); - virtual ~QSGPlainTexture(); + ~QSGPlainTexture() override; void setOwnsTexture(bool owns) { m_owns_texture = owns; } bool ownsTexture() const { return m_owns_texture; } diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index fbc8f27a63..7b1d5abb26 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -57,7 +57,6 @@ inline static bool isPowerOfTwo(int x) QSGMaterialType QSGOpaqueTextureMaterialShader::type; QSGOpaqueTextureMaterialShader::QSGOpaqueTextureMaterialShader() - : QSGMaterialShader() { #if QT_CONFIG(opengl) setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/opaquetexture.vert")); @@ -67,7 +66,7 @@ QSGOpaqueTextureMaterialShader::QSGOpaqueTextureMaterialShader() char const *const *QSGOpaqueTextureMaterialShader::attributeNames() const { - static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 }; + static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", nullptr }; return attr; } @@ -80,7 +79,7 @@ void QSGOpaqueTextureMaterialShader::initialize() void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) { - Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type()); + Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type()); QSGOpaqueTextureMaterial *tx = static_cast<QSGOpaqueTextureMaterial *>(newEffect); QSGOpaqueTextureMaterial *oldTx = static_cast<QSGOpaqueTextureMaterial *>(oldEffect); @@ -112,7 +111,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa t->setMipmapFiltering(tx->mipmapFiltering()); t->setAnisotropyLevel(tx->anisotropyLevel()); - if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId()) + if (oldTx == nullptr || oldTx->texture()->textureId() != t->textureId()) t->bind(); else t->updateBindOptions(); @@ -169,7 +168,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa */ QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial() - : m_texture(0) + : m_texture(nullptr) , m_filtering(QSGTexture::Nearest) , m_mipmap_filtering(QSGTexture::None) , m_horizontal_wrap(QSGTexture::ClampToEdge) @@ -304,7 +303,17 @@ void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture) The default vertical wrap mode is \c QSGTexture::ClampToEdge. */ +/*! + \fn void QSGOpaqueTextureMaterial::setAnisotropyLevel(QSGTexture::AnisotropyLevel level) + + Sets this material's anistropy level to \a level. +*/ + +/*! + \fn QSGTexture::AnisotropyLevel QSGOpaqueTextureMaterial::anisotropyLevel() const + Returns this material's anistropy level. +*/ /*! \internal @@ -388,7 +397,7 @@ QSGTextureMaterialShader::QSGTextureMaterialShader() void QSGTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) { - Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type()); + Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type()); #if QT_CONFIG(opengl) if (state.isOpacityDirty()) program()->setUniformValue(m_opacity_id, state.opacity()); diff --git a/src/quick/scenegraph/util/qsgtexturereader.cpp b/src/quick/scenegraph/util/qsgtexturereader.cpp index 61729ada18..8af2c8e7cd 100644 --- a/src/quick/scenegraph/util/qsgtexturereader.cpp +++ b/src/quick/scenegraph/util/qsgtexturereader.cpp @@ -43,40 +43,71 @@ #if QT_CONFIG(opengl) #include <private/qsgpkmhandler_p.h> +#include <private/qsgktxhandler_p.h> #endif +#include <QFileInfo> + QT_BEGIN_NAMESPACE -QSGTextureReader::QSGTextureReader() +QSGTextureReader::QSGTextureReader(QIODevice *device, const QString &fileName) + : m_device(device), m_fileInfo(fileName) { +} +QSGTextureReader::~QSGTextureReader() +{ + delete m_handler; } -QQuickTextureFactory *QSGTextureReader::read(QIODevice *device, const QByteArray &format) +QQuickTextureFactory *QSGTextureReader::read() { #if QT_CONFIG(opengl) - if (format == QByteArrayLiteral("pkm")) { - QSGPkmHandler handler; - return handler.read(device); - } + if (!isTexture()) + return nullptr; + return m_handler->read(); #else - Q_UNUSED(device) - Q_UNUSED(format) -#endif return nullptr; +#endif } -bool QSGTextureReader::isTexture(QIODevice *device, const QByteArray &format) +bool QSGTextureReader::isTexture() { #if QT_CONFIG(opengl) - if (format == QByteArrayLiteral("pkm")) { - return device->peek(4) == QByteArrayLiteral("PKM "); + if (!checked) { + checked = true; + if (!init()) + return false; + + QByteArray headerBlock = m_device->peek(64); + QByteArray suffix = m_fileInfo.suffix().toLower().toLatin1(); + QByteArray logName = m_fileInfo.fileName().toUtf8(); + + // Currently the handlers are hardcoded; later maybe a list of plugins + if (QSGPkmHandler::canRead(suffix, headerBlock)) { + m_handler = new QSGPkmHandler(m_device, logName); + } else if (QSGKtxHandler::canRead(suffix, headerBlock)) { + m_handler = new QSGKtxHandler(m_device, logName); + } + // else if OtherHandler::canRead() ...etc. } + return (m_handler != nullptr); #else - Q_UNUSED(device) - Q_UNUSED(format) -#endif return false; +#endif +} + +QList<QByteArray> QSGTextureReader::supportedFileFormats() +{ + // Hardcoded for now + return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")}; +} + +bool QSGTextureReader::init() +{ + if (!m_device) + return false; + return m_device->isReadable(); } QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgtexturereader_p.h b/src/quick/scenegraph/util/qsgtexturereader_p.h index 7d2fc314a6..19e33bf5c3 100644 --- a/src/quick/scenegraph/util/qsgtexturereader_p.h +++ b/src/quick/scenegraph/util/qsgtexturereader_p.h @@ -52,19 +52,34 @@ // #include <QString> +#include <QFileInfo> QT_BEGIN_NAMESPACE class QIODevice; class QQuickTextureFactory; +class QSGTextureFileHandler; class QSGTextureReader { public: - QSGTextureReader(); + QSGTextureReader(QIODevice *device, const QString &fileName = QString()); + ~QSGTextureReader(); - static QQuickTextureFactory *read(QIODevice *device, const QByteArray &format); - static bool isTexture(QIODevice *device, const QByteArray &format); + QQuickTextureFactory *read(); + bool isTexture(); + + // TBD access function to params + // TBD ask for identified fmt + + static QList<QByteArray> supportedFileFormats(); + +private: + bool init(); + QIODevice *m_device = nullptr; + QFileInfo m_fileInfo; + QSGTextureFileHandler *m_handler = nullptr; + bool checked = false; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp index 42c589b14a..cb61430e2e 100644 --- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp +++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp @@ -64,7 +64,6 @@ private: QSGMaterialType QSGVertexColorMaterialShader::type; QSGVertexColorMaterialShader::QSGVertexColorMaterialShader() - : QSGMaterialShader() { #if QT_CONFIG(opengl) setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/vertexcolor.vert")); @@ -87,7 +86,7 @@ void QSGVertexColorMaterialShader::updateState(const RenderState &state, QSGMate char const *const *QSGVertexColorMaterialShader::attributeNames() const { - static const char *const attr[] = { "vertexCoord", "vertexColor", 0 }; + static const char *const attr[] = { "vertexCoord", "vertexColor", nullptr }; return attr; } |