diff options
-rw-r--r-- | src/quick/scenegraph/util/qsgatlastexture.cpp | 64 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgatlastexture_p.h | 12 |
2 files changed, 62 insertions, 14 deletions
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index cb82d721ca..cfff35904f 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -384,12 +384,14 @@ void Atlas::bind(QSGTexture::Filtering filtering) Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare); Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, 3); + Texture *t = m_pending_uploads.at(i); if (m_externalFormat == GL_BGRA && !m_use_bgra_fallback) { - uploadBgra(m_pending_uploads.at(i)); + uploadBgra(t); } else { - upload(m_pending_uploads.at(i)); + upload(t); } + t->releaseImage(); qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed() << "ms (" << m_pending_uploads.at(i)->image().width() << "x" @@ -423,15 +425,15 @@ Texture::Texture(Atlas *atlas, const QRect &textureRect, const QImage &image) , m_image(image) , m_atlas(atlas) , m_nonatlas_texture(0) + , m_has_alpha(image.hasAlphaChannel()) { - m_allocated_rect_without_padding = m_allocated_rect.adjusted(1, 1, -1, -1); float w = atlas->size().width(); float h = atlas->size().height(); - - m_texture_coords_rect = QRectF(m_allocated_rect_without_padding.x() / w, - m_allocated_rect_without_padding.y() / h, - m_allocated_rect_without_padding.width() / w, - m_allocated_rect_without_padding.height() / h); + QRect nopad = atlasSubRectWithoutPadding(); + m_texture_coords_rect = QRectF(nopad.x() / w, + nopad.y() / h, + nopad.width() / w, + nopad.height() / h); } Texture::~Texture() @@ -448,12 +450,54 @@ void Texture::bind() QSGTexture *Texture::removedFromAtlas() const { - if (!m_nonatlas_texture) { + if (m_nonatlas_texture) { + m_nonatlas_texture->setMipmapFiltering(mipmapFiltering()); + m_nonatlas_texture->setFiltering(filtering()); + return m_nonatlas_texture; + } + + if (!m_image.isNull()) { m_nonatlas_texture = new QSGPlainTexture(); m_nonatlas_texture->setImage(m_image); m_nonatlas_texture->setFiltering(filtering()); - m_nonatlas_texture->setMipmapFiltering(mipmapFiltering()); + + } else { + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + // bind the atlas texture as an fbo and extract the texture.. + + // First extract the currently bound fbo so we can restore it later. + GLint currentFbo; + f->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFbo); + + // Create an FBO and bind the atlas texture into it. + GLuint fbo; + f->glGenFramebuffers(1, &fbo); + f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); + f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_atlas->textureId(), 0); + + // Create the target texture, QSGPlainTexture below will deal with the texparams, so we don't + // need to worry about those here. + GLuint texture; + f->glGenTextures(1, &texture); + f->glBindTexture(GL_TEXTURE_2D, texture); + QRect r = atlasSubRectWithoutPadding(); + // and copy atlas into our texture. + f->glCopyTexImage2D(GL_TEXTURE_2D, 0, m_atlas->internalFormat(), r.x(), r.y(), r.width(), r.height(), 0); + + m_nonatlas_texture = new QSGPlainTexture(); + m_nonatlas_texture->setTextureId(texture); + m_nonatlas_texture->setOwnsTexture(true); + m_nonatlas_texture->setHasAlphaChannel(m_has_alpha); + m_nonatlas_texture->setTextureSize(r.size()); + + // cleanup: unbind our atlas from the fbo, rebind the old default and delete the fbo. + f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + f->glBindFramebuffer(GL_FRAMEBUFFER, (GLuint) currentFbo); + f->glDeleteFramebuffers(1, &fbo); } + + m_nonatlas_texture->setMipmapFiltering(mipmapFiltering()); + m_nonatlas_texture->setFiltering(filtering()); return m_nonatlas_texture; } diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h index 639bdc291e..29eced9eb4 100644 --- a/src/quick/scenegraph/util/qsgatlastexture_p.h +++ b/src/quick/scenegraph/util/qsgatlastexture_p.h @@ -87,6 +87,9 @@ public: QSize size() const { return m_size; } + GLuint internalFormat() const { return m_internalFormat; } + GLuint externalFormat() const { return m_externalFormat; } + private: QSGAreaAllocator m_allocator; GLuint m_texture_id; @@ -110,26 +113,26 @@ public: ~Texture(); int textureId() const { return m_atlas->textureId(); } - QSize textureSize() const { return m_allocated_rect_without_padding.size(); } - bool hasAlphaChannel() const { return m_image.hasAlphaChannel(); } + QSize textureSize() const { return atlasSubRectWithoutPadding().size(); } + bool hasAlphaChannel() const { return m_has_alpha; } bool hasMipmaps() const { return false; } bool isAtlasTexture() const { return true; } QRectF normalizedTextureSubRect() const { return m_texture_coords_rect; } QRect atlasSubRect() const { return m_allocated_rect; } - QRect atlasSubRectWithoutPadding() const { return m_allocated_rect_without_padding; } + QRect atlasSubRectWithoutPadding() const { return m_allocated_rect.adjusted(1, 1, -1, -1); } bool isTexture() const { return true; } QSGTexture *removedFromAtlas() const; + void releaseImage() { m_image = QImage(); } const QImage &image() const { return m_image; } void bind(); private: - QRect m_allocated_rect_without_padding; QRect m_allocated_rect; QRectF m_texture_coords_rect; @@ -139,6 +142,7 @@ private: mutable QSGPlainTexture *m_nonatlas_texture; + uint m_has_alpha : 1; }; } |