diff options
author | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2015-01-29 12:26:31 +0000 |
---|---|---|
committer | Gunnar Sletta <gunnar@sletta.org> | 2015-02-03 13:58:00 +0000 |
commit | a49b0ad7866046c28fb38f0f70ddf626e12c3099 (patch) | |
tree | fd630807d84f151d9c086d21d47c7acb62214c0a /src/quick/scenegraph/util/qsgatlastexture.cpp | |
parent | d302abb3d056a1ae0997ef03f442bfbd6547be0c (diff) |
Release atlas texture's image instance once uploaded
Sitting on the instance makes it impossible for custom texture
factories to release images to keep down memory.
Also, ditch the extra QRect used to store the nonpadded atlas rect as
this is easily reachable from the padded one.
Change-Id: I4914753cc43a6f3173cfc9b210e02b2770ef33fd
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Diffstat (limited to 'src/quick/scenegraph/util/qsgatlastexture.cpp')
-rw-r--r-- | src/quick/scenegraph/util/qsgatlastexture.cpp | 64 |
1 files changed, 54 insertions, 10 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; } |