[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kde-workspace] kwin: kwin: improving the texture update handling
From:       Philipp Knechtges <philipp-dev () knechtges ! com>
Date:       2012-01-31 22:15:48
Message-ID: 20120131221548.F3538A60A6 () git ! kde ! org
[Download RAW message or body]

Git commit f6cef28ebd6d832e13f0cf7d4b81ed5d3e0aae2c by Philipp Knechtges.
Committed on 07/01/2012 at 12:12.
Pushed by knechtges into branch 'master'.

kwin: improving the texture update handling

This patch changes the behavior of strictly bound textures such that
they are only updated if the corresponding window has been damaged.
Additionally GLTexture now keeps track of the current filter and
wrapmode setting.

REVIEW: 103655

M  +56   -43   kwin/libkwineffects/kwingltexture.cpp
M  +0    -1    kwin/libkwineffects/kwingltexture.h
M  +5    -2    kwin/libkwineffects/kwingltexture_p.h
M  +1    -0    kwin/scene_opengl.h
M  +10   -6    kwin/scene_opengl_egl.cpp
M  +8    -8    kwin/scene_opengl_glx.cpp

http://commits.kde.org/kde-workspace/f6cef28ebd6d832e13f0cf7d4b81ed5d3e0aae2c

diff --git a/kwin/libkwineffects/kwingltexture.cpp b/kwin/libkwineffects/kwingltexture.cpp
index 4155fb1..9e577e8 100644
--- a/kwin/libkwineffects/kwingltexture.cpp
+++ b/kwin/libkwineffects/kwingltexture.cpp
@@ -4,6 +4,7 @@
 
 Copyright (C) 2006-2007 Rivo Laks <rivolaks@hot.ee>
 Copyright (C) 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
+Copyright (C) 2012 Philipp Knechtges <philipp-dev@knechtges.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -117,13 +118,16 @@ GLTexturePrivate::GLTexturePrivate()
 {
     m_texture = 0;
     m_target = 0;
-    m_filter = 0;
+    m_filter = GL_NEAREST_MIPMAP_LINEAR;
+    m_wrapMode = GL_REPEAT;
     m_yInverted = false;
     m_canUseMipmaps = false;
-    m_hasValidMipmaps = false;
+    m_markedDirty = false;
     m_unnormalizeActive = 0;
     m_normalizeActive = 0;
     m_vbo = 0;
+    m_filterChanged = false;
+    m_wrapModeChanged = false;
 }
 
 GLTexturePrivate::~GLTexturePrivate()
@@ -192,13 +196,11 @@ bool GLTexture::load(const QImage& image, GLenum target)
         d->m_canUseMipmaps = false;
     }
 #endif
-    setFilter(GL_LINEAR);
     d->m_size = img.size();
     d->m_yInverted = true;
 
     img = d->convertToGLFormat(img);
 
-    setDirty();
     if (isNull()) {
         glGenTextures(1, &d->m_texture);
     }
@@ -212,6 +214,7 @@ bool GLTexture::load(const QImage& image, GLenum target)
                  GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
 #endif
     unbind();
+    setFilter(GL_LINEAR);
     return true;
 }
 
@@ -240,13 +243,44 @@ void GLTexturePrivate::bind()
     glEnable(m_target);
 #endif
     glBindTexture(m_target, m_texture);
-    enableFilter();
 }
 
 void GLTexture::bind()
 {
     Q_D(GLTexture);
     d->bind();
+    if (d->m_markedDirty) {
+        d->onDamage();
+    }
+    if (d->m_filterChanged) {
+        if (d->m_filter == GL_LINEAR_MIPMAP_LINEAR) {
+            // trilinear filtering requested, but is it possible?
+            if (d->sNPOTTextureSupported
+                    && d->sFramebufferObjectSupported
+                    && d->m_canUseMipmaps) {
+                glTexParameteri(d->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+                glTexParameteri(d->m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                glGenerateMipmap(d->m_target);
+            } else {
+                // can't use trilinear, so use bilinear
+                d->m_filter = GL_LINEAR;
+                glTexParameteri(d->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                glTexParameteri(d->m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            }
+        } else if (d->m_filter == GL_LINEAR) {
+            glTexParameteri(d->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(d->m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        } else {
+            // if neither trilinear nor bilinear, default to fast filtering
+            d->m_filter = GL_NEAREST;
+            glTexParameteri(d->m_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(d->m_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        }
+    }
+    if (d->m_wrapModeChanged) {
+        glTexParameteri(d->m_target, GL_TEXTURE_WRAP_S, d->m_wrapMode);
+        glTexParameteri(d->m_target, GL_TEXTURE_WRAP_T, d->m_wrapMode);
+    }
 }
 
 void GLTexturePrivate::unbind()
@@ -334,13 +368,13 @@ GLenum GLTexture::filter() const
 bool GLTexture::isDirty() const
 {
     Q_D(const GLTexture);
-    return d->m_hasValidMipmaps;
+    return d->m_markedDirty;
 }
 
 void GLTexture::setTexture(GLuint texture)
 {
-    Q_D(GLTexture);
     discard();
+    Q_D(GLTexture);
     d->m_texture = texture;
 }
 
@@ -353,53 +387,32 @@ void GLTexture::setTarget(GLenum target)
 void GLTexture::setFilter(GLenum filter)
 {
     Q_D(GLTexture);
-    d->m_filter = filter;
+    if (filter != d->m_filter) {
+        d->m_filter = filter;
+        d->m_filterChanged = true;
+    }
 }
 
 void GLTexture::setWrapMode(GLenum mode)
 {
     Q_D(GLTexture);
-    bind();
-    glTexParameteri(d->m_target, GL_TEXTURE_WRAP_S, mode);
-    glTexParameteri(d->m_target, GL_TEXTURE_WRAP_T, mode);
-    unbind();
+    if (mode != d->m_wrapMode) {
+        d->m_wrapMode = mode;
+        d->m_wrapModeChanged=true;
+    }
 }
 
-void GLTexture::setDirty()
+void GLTexturePrivate::onDamage()
 {
-    Q_D(GLTexture);
-    d->m_hasValidMipmaps = false;
+    if (m_filter == GL_LINEAR_MIPMAP_LINEAR && !m_filterChanged) {
+        glGenerateMipmap(m_target);
+    }
 }
 
-
-void GLTexturePrivate::enableFilter()
+void GLTexture::setDirty()
 {
-    if (m_filter == GL_LINEAR_MIPMAP_LINEAR) {
-        // trilinear filtering requested, but is it possible?
-        if (sNPOTTextureSupported
-                && sFramebufferObjectSupported
-                && m_canUseMipmaps) {
-            glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-            glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-            if (!m_hasValidMipmaps) {
-                glGenerateMipmap(m_target);
-                m_hasValidMipmaps = true;
-            }
-        } else {
-            // can't use trilinear, so use bilinear
-            m_filter = GL_LINEAR;
-            glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-            glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        }
-    } else if (m_filter == GL_LINEAR) {
-        glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    } else {
-        // if neither trilinear nor bilinear, default to fast filtering
-        m_filter = GL_NEAREST;
-        glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    }
+    Q_D(GLTexture);
+    d->m_markedDirty = true;
 }
 
 QImage GLTexturePrivate::convertToGLFormat(const QImage& img) const
diff --git a/kwin/libkwineffects/kwingltexture.h b/kwin/libkwineffects/kwingltexture.h
index 6795d0d..b913eca 100644
--- a/kwin/libkwineffects/kwingltexture.h
+++ b/kwin/libkwineffects/kwingltexture.h
@@ -94,7 +94,6 @@ public:
     static bool saturationSupported();
 
 protected:
-    void enableFilter();
     QImage convertToGLFormat(const QImage& img) const;
 
     QExplicitlySharedDataPointer<GLTexturePrivate> d_ptr;
diff --git a/kwin/libkwineffects/kwingltexture_p.h b/kwin/libkwineffects/kwingltexture_p.h
index 7e04305..27c14db 100644
--- a/kwin/libkwineffects/kwingltexture_p.h
+++ b/kwin/libkwineffects/kwingltexture_p.h
@@ -42,18 +42,21 @@ public:
     virtual void bind();
     virtual void unbind();
     virtual void release();
+    virtual void onDamage();
 
-    void enableFilter();
     QImage convertToGLFormat(const QImage& img) const;
 
     GLuint m_texture;
     GLenum m_target;
     GLenum m_filter;
+    GLenum m_wrapMode;
     QSize m_size;
     QSizeF m_scale; // to un-normalize GL_TEXTURE_2D
     bool m_yInverted; // texture has y inverted
     bool m_canUseMipmaps;
-    bool m_hasValidMipmaps;
+    bool m_markedDirty;
+    bool m_filterChanged;
+    bool m_wrapModeChanged;
 
     int m_unnormalizeActive; // 0 - no, otherwise refcount
     int m_normalizeActive; // 0 - no, otherwise refcount
diff --git a/kwin/scene_opengl.h b/kwin/scene_opengl.h
index 5bc9d5e..957b6b7 100644
--- a/kwin/scene_opengl.h
+++ b/kwin/scene_opengl.h
@@ -117,6 +117,7 @@ public:
     virtual void bind();
     virtual void unbind();
     virtual void release();
+    virtual void onDamage();
 
 #ifndef KWIN_HAVE_OPENGLES
     GLXPixmap m_glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode
diff --git a/kwin/scene_opengl_egl.cpp b/kwin/scene_opengl_egl.cpp
index 9084133..6855133 100644
--- a/kwin/scene_opengl_egl.cpp
+++ b/kwin/scene_opengl_egl.cpp
@@ -266,11 +266,9 @@ bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
         return false;
 
     glGenTextures(1, &d->m_texture);
+    setWrapMode(GL_CLAMP_TO_EDGE);
+    setFilter(GL_LINEAR);
     bind();
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     const EGLint attribs[] = {
         EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
         EGL_NONE
@@ -281,6 +279,7 @@ bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
     if (EGL_NO_IMAGE_KHR == d->m_image) {
         kDebug(1212) << "failed to create egl image";
         unbind();
+        discard();
         return false;
     }
     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)d->m_image);
@@ -291,15 +290,20 @@ bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
     return true;
 }
 
-void SceneOpenGL::TexturePrivate::bind()
+void SceneOpenGL::TexturePrivate::onDamage()
 {
-    GLTexturePrivate::bind();
     if (options->glStrictBinding) {
         // This is just implemented to be consistent with
         // the example in mesa/demos/src/egl/opengles1/texture_from_pixmap.c
         eglWaitNative(EGL_CORE_NATIVE_ENGINE);
         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) m_image);
     }
+    GLTexturePrivate::onDamage();
+}
+
+void SceneOpenGL::TexturePrivate::bind()
+{
+    GLTexturePrivate::bind();
 }
 
 void SceneOpenGL::TexturePrivate::unbind()
diff --git a/kwin/scene_opengl_glx.cpp b/kwin/scene_opengl_glx.cpp
index 88c3139..5290ede 100644
--- a/kwin/scene_opengl_glx.cpp
+++ b/kwin/scene_opengl_glx.cpp
@@ -721,18 +721,22 @@ bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
 #ifdef CHECK_GL_ERROR
     checkGLError("TextureLoad0");
 #endif
+    unbind();
     return true;
 }
 
-void SceneOpenGL::TexturePrivate::bind()
+void SceneOpenGL::TexturePrivate::onDamage()
 {
-    GLTexturePrivate::bind();
     if (options->glStrictBinding && m_glxpixmap) {
         glXReleaseTexImageEXT(display(), m_glxpixmap, GLX_FRONT_LEFT_EXT);
         glXBindTexImageEXT(display(), m_glxpixmap, GLX_FRONT_LEFT_EXT, NULL);
-        m_hasValidMipmaps = false; // Mipmaps have to be regenerated after updating the texture
     }
-    enableFilter();
+    GLTexturePrivate::onDamage();
+}
+
+void SceneOpenGL::TexturePrivate::bind()
+{
+    GLTexturePrivate::bind();
     if (hasGLVersion(1, 4, 0)) {
         // Lod bias makes the trilinear-filtered texture look a bit sharper
         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -1.0f);
@@ -744,10 +748,6 @@ void SceneOpenGL::TexturePrivate::unbind()
     if (hasGLVersion(1, 4, 0)) {
         glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
     }
-    if (options->glStrictBinding && m_glxpixmap) {
-        glBindTexture(m_target, m_texture);
-        glXReleaseTexImageEXT(display(), m_glxpixmap, GLX_FRONT_LEFT_EXT);
-    }
 
     GLTexturePrivate::unbind();
 }

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic