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.
This commit is contained in:
Fredrik Höglund 2014-12-10 20:26:23 +01:00
parent ccf1bad426
commit 450be6a378
5 changed files with 22 additions and 9 deletions

View file

@ -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);

View file

@ -35,6 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kmessagebox.h>
#include <cmath>
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);

View file

@ -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;

View file

@ -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);

View file

@ -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