diff options
author | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-08-15 09:26:16 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-08-23 08:00:43 +0200 |
commit | 8d0e307bc7f9f4458e6ea2d2fc0d6cd25be4fda9 (patch) | |
tree | f12a065df95d54699e3266702aa7b62f707fdc33 /src | |
parent | 15ee12508ec8663ae09ebfc61cc4f0725311bdec (diff) |
Downscale textures which exceed the GL texture limit
This way they will at least render.
[ChangeLog][QtQuick] Images exceeding GL_MAX_TEXTURE_SIZE will be
downscaled to fit so they will still show.
Change-Id: I169ecac768036812b8e14265ec1a0a8902655666
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 6 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 3 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgtexture.cpp | 28 |
3 files changed, 29 insertions, 8 deletions
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 6ebc479ec5..4e768574c4 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -253,6 +253,7 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) QSet<QByteArray> exts = renderContext->openglContext()->extensions(); QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e; qCDebug(QSG_LOG_INFO) << "GL_EXTENSIONS: " << all.constData(); + qCDebug(QSG_LOG_INFO) << "Max Texture Size: " << renderContext->maxTextureSize(); } d->mutex.unlock(); @@ -392,6 +393,7 @@ QSGRenderContext::QSGRenderContext(QSGContext *context) , m_atlasManager(0) , m_depthStencilManager(0) , m_distanceFieldCacheManager(0) + , m_maxTextureSize(0) , m_brokenIBOs(false) , m_serializedRender(false) , m_attachToGLContext(true) @@ -493,6 +495,9 @@ void QSGRenderContext::registerFontengineForCleanup(QFontEngine *engine) */ void QSGRenderContext::initialize(QOpenGLContext *context) { + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); + // Sanity check the surface format, in case it was overridden by the application QSurfaceFormat requested = m_sg->defaultSurfaceFormat(); QSurfaceFormat actual = context->format(); @@ -513,7 +518,6 @@ void QSGRenderContext::initialize(QOpenGLContext *context) m_sg->renderContextInitialized(this); #ifdef Q_OS_LINUX - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); const char *vendor = (const char *) funcs->glGetString(GL_VENDOR); if (strstr(vendor, "nouveau")) m_brokenIBOs = true; diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index b5271f9f37..70202264bf 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -126,6 +126,7 @@ public: static QSGRenderContext *from(QOpenGLContext *context); bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; } + int maxTextureSize() const { return m_maxTextureSize; } Q_SIGNALS: void initialized(); @@ -147,7 +148,7 @@ protected: QSGDistanceFieldGlyphCacheManager *m_distanceFieldCacheManager; QSet<QFontEngine *> m_fontEnginesToClean; - + int m_maxTextureSize; bool m_brokenIBOs; bool m_serializedRender; bool m_attachToGLContext; diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index 69edfab379..abd9d480c5 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -671,12 +671,28 @@ void QSGPlainTexture::bind() bindTime = qsg_renderer_timer.nsecsElapsed(); // ### TODO: check for out-of-memory situations... - int w = m_image.width(); - int h = m_image.height(); QImage tmp = (m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied) ? m_image : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + // Downscale the texture to fit inside the max texture limit if it is too big. + // It would be better if the image was already downscaled to the right size, + // but this information is not always available at that time, so as a last + // resort we can do it here. Texture coordinates are normalized, so it + // won't cause any problems and actual texture sizes will be written + // based on QSGTexture::textureSize which is updated after this, so that + // should be ok. + int max; + if (QSGRenderContext *rc = QSGRenderContext::from(context)) + max = rc->maxTextureSize(); + else + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); + if (tmp.width() > max || tmp.height() > max) { + tmp = tmp.scaled(qMin(max, tmp.width()), qMin(max, tmp.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + m_texture_size = tmp.size(); + } + if (tmp.width() * 4 != tmp.bytesPerLine()) tmp = tmp.copy(); @@ -726,7 +742,7 @@ void QSGPlainTexture::bind() if (profileFrames) swizzleTime = qsg_renderer_timer.nsecsElapsed(); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits()); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture_size.width(), m_texture_size.height(), 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits()); qint64 uploadTime = 0; if (profileFrames) @@ -741,7 +757,7 @@ void QSGPlainTexture::bind() if (profileFrames) { mipmapTime = qsg_renderer_timer.nsecsElapsed(); qCDebug(QSG_LOG_TIME_TEXTURE, - "plain texture uploaded in: %dms (%dx%d), bind=%d, convert=%d, swizzle=%d (%s->%s), upload=%d, mipmap=%d", + "plain texture uploaded in: %dms (%dx%d), bind=%d, convert=%d, swizzle=%d (%s->%s), upload=%d, mipmap=%d%s", int(mipmapTime / 1000000), m_texture_size.width(), m_texture_size.height(), int(bindTime / 1000000), @@ -750,7 +766,8 @@ void QSGPlainTexture::bind() (externalFormat == GL_BGRA ? "BGRA" : "RGBA"), (internalFormat == GL_BGRA ? "BGRA" : "RGBA"), int((uploadTime - swizzleTime)/1000000), - int((mipmapTime - uploadTime)/1000000)); + int((mipmapTime - uploadTime)/1000000), + m_texture_size != m_image.size() ? " (scaled to GL_MAX_TEXTURE_SIZE)" : ""); } Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphTexturePrepare, ( @@ -760,7 +777,6 @@ void QSGPlainTexture::bind() uploadTime - swizzleTime, qsg_renderer_timer.nsecsElapsed() - uploadTime)); - m_texture_size = QSize(w, h); m_texture_rect = QRectF(0, 0, 1, 1); m_dirty_bind_options = false; |