From a49b0ad7866046c28fb38f0f70ddf626e12c3099 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 29 Jan 2015 12:26:31 +0000 Subject: 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 --- src/quick/scenegraph/util/qsgatlastexture.cpp | 64 ++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) (limited to 'src/quick/scenegraph/util/qsgatlastexture.cpp') 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; } -- cgit v1.2.3