From 450be6a3782bfb3c837a98e080b155cdbfcff0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Wed, 10 Dec 2014 20:26:23 +0100 Subject: [PATCH] Add a levels parameter to the GLTexture ctor Prior to this commit we didn't know if mipmaps were going to be used when we created the GL texture, which meant that we couldn't tell the driver whether to allocate storage for mipmaps or not. This resulted in one of two things happening depending on the driver; either it would allocate storage for mipmaps that in most cases would never be used, or it wouldn't and would later be forced to reallocate the texture when mipmaps were added. By adding this parameter we can now explicitly tell the driver how many mipmap levels will be used. The parameter is only added to the non-image constructor for now. The image constructor is changed to only allocate a single level, which matches how textures created from images are used in kwin. This may need to be revisited in the future. --- effects/logout/logout.cpp | 5 ++++- effects/lookingglass/lookingglass.cpp | 5 ++++- libkwineffects/kwingltexture.cpp | 16 +++++++++++----- libkwineffects/kwingltexture.h | 4 ++-- libkwineffects/kwingltexture_p.h | 1 + 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/effects/logout/logout.cpp b/effects/logout/logout.cpp index 59c078becc..34fa81d024 100644 --- a/effects/logout/logout.cpp +++ b/effects/logout/logout.cpp @@ -109,7 +109,10 @@ void LogoutEffect::prePaintScreen(ScreenPrePaintData& data, int time) // TODO: It seems that it is not possible to create a GLRenderTarget that has // a different size than the display right now. Most likely a KWin core bug. // Create texture and render target - blurTexture = new GLTexture(effects->virtualScreenSize()); + const QSize size = effects->virtualScreenSize(); + + // The fragment shader uses a LOD bias of 1.75, so we need 3 mipmap levels. + blurTexture = new GLTexture(size, 3); blurTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR); blurTexture->setWrapMode(GL_CLAMP_TO_EDGE); diff --git a/effects/lookingglass/lookingglass.cpp b/effects/lookingglass/lookingglass.cpp index 784b303a66..e6b5c83316 100644 --- a/effects/lookingglass/lookingglass.cpp +++ b/effects/lookingglass/lookingglass.cpp @@ -35,6 +35,8 @@ along with this program. If not, see . #include +#include + namespace KWin { @@ -99,7 +101,8 @@ bool LookingGlassEffect::loadData() int texh = screenSize.height(); // Create texture and render target - m_texture = new GLTexture(texw, texh); + const int levels = std::log2(qMin(texw, texh)) + 1; + m_texture = new GLTexture(texw, texh, levels); m_texture->setFilter(GL_LINEAR_MIPMAP_LINEAR); m_texture->setWrapMode(GL_CLAMP_TO_EDGE); diff --git a/libkwineffects/kwingltexture.cpp b/libkwineffects/kwingltexture.cpp index 8eb8a82984..beed208232 100644 --- a/libkwineffects/kwingltexture.cpp +++ b/libkwineffects/kwingltexture.cpp @@ -77,15 +77,15 @@ GLTexture::GLTexture(const QImage& image, GLenum target) if (d->m_target != GL_TEXTURE_RECTANGLE_ARB) { d->m_scale.setWidth(1.0 / image.width()); d->m_scale.setHeight(1.0 / image.height()); - d->m_canUseMipmaps = true; } else { d->m_scale.setWidth(1.0); d->m_scale.setHeight(1.0); - d->m_canUseMipmaps = false; } d->m_size = image.size(); d->m_yInverted = true; + d->m_canUseMipmaps = false; + d->m_mipLevels = 1; d->updateMatrix(); @@ -94,6 +94,7 @@ GLTexture::GLTexture(const QImage& image, GLenum target) if (!GLPlatform::instance()->isGLES()) { const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, d->m_mipLevels - 1); glTexImage2D(d->m_target, 0, GL_RGBA8, im.width(), im.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, im.bits()); } else { @@ -122,7 +123,7 @@ GLTexture::GLTexture(const QString& fileName) { } -GLTexture::GLTexture(int width, int height) +GLTexture::GLTexture(int width, int height, int levels) : d_ptr(new GLTexturePrivate()) { Q_D(GLTexture); @@ -131,7 +132,10 @@ GLTexture::GLTexture(int width, int height) d->m_scale.setWidth(1.0 / width); d->m_scale.setHeight(1.0 / height); d->m_size = QSize(width, height); + d->m_canUseMipmaps = levels > 1; + d->m_mipLevels = levels; d->m_canUseMipmaps = true; + d->m_filter = levels > 1 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST; d->updateMatrix(); @@ -139,6 +143,7 @@ GLTexture::GLTexture(int width, int height) bind(); if (!GLPlatform::instance()->isGLES()) { + glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, levels - 1); glTexImage2D(d->m_target, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); } else { @@ -153,8 +158,8 @@ GLTexture::GLTexture(int width, int height) unbind(); } -GLTexture::GLTexture(const QSize &size) - : GLTexture(size.width(), size.height()) +GLTexture::GLTexture(const QSize &size, int levels) + : GLTexture(size.width(), size.height(), levels) { } @@ -176,6 +181,7 @@ GLTexturePrivate::GLTexturePrivate() m_wrapMode = GL_REPEAT; m_yInverted = false; m_canUseMipmaps = false; + m_mipLevels = 1; m_markedDirty = false; m_unnormalizeActive = 0; m_normalizeActive = 0; diff --git a/libkwineffects/kwingltexture.h b/libkwineffects/kwingltexture.h index d559ab0bbe..3b9b012977 100644 --- a/libkwineffects/kwingltexture.h +++ b/libkwineffects/kwingltexture.h @@ -55,8 +55,8 @@ public: explicit GLTexture(const QImage& image, GLenum target = GL_TEXTURE_2D); explicit GLTexture(const QPixmap& pixmap, GLenum target = GL_TEXTURE_2D); explicit GLTexture(const QString& fileName); - GLTexture(int width, int height); - explicit GLTexture(const QSize &size); + GLTexture(int width, int height, int levels = 1); + explicit GLTexture(const QSize &size, int levels = 1); virtual ~GLTexture(); GLTexture & operator = (const GLTexture& tex); diff --git a/libkwineffects/kwingltexture_p.h b/libkwineffects/kwingltexture_p.h index 3cbb0bb12e..d44b20d698 100644 --- a/libkwineffects/kwingltexture_p.h +++ b/libkwineffects/kwingltexture_p.h @@ -58,6 +58,7 @@ public: bool m_markedDirty; bool m_filterChanged; bool m_wrapModeChanged; + int m_mipLevels; int m_unnormalizeActive; // 0 - no, otherwise refcount int m_normalizeActive; // 0 - no, otherwise refcount