Only call glXBindTexImageEXT() when the contents of the pixmap has changed.

We don't need to do this every time we bind the texture to a GL context,
even with strict binding.

svn path=/trunk/KDE/kdebase/workspace/; revision=1182198
icc-effect-5.14.5
Fredrik Höglund 2010-10-03 18:49:36 +00:00
parent cf28eb22c7
commit 15033a9a8e
2 changed files with 32 additions and 25 deletions

View File

@ -991,7 +991,8 @@ SceneOpenGL::Texture::~Texture()
void SceneOpenGL::Texture::init() void SceneOpenGL::Texture::init()
{ {
bound_glxpixmap = None; damaged = true;
glxpixmap = None;
} }
void SceneOpenGL::Texture::createTexture() void SceneOpenGL::Texture::createTexture()
@ -1008,20 +1009,19 @@ void SceneOpenGL::Texture::discard()
void SceneOpenGL::Texture::release() void SceneOpenGL::Texture::release()
{ {
if( tfp_mode && bound_glxpixmap != None ) if( tfp_mode && glxpixmap != None )
{ {
if( !options->glStrictBinding ) glXReleaseTexImageEXT( display(), glxpixmap, GLX_FRONT_LEFT_EXT );
glXReleaseTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT ); glXDestroyPixmap( display(), glxpixmap );
glXDestroyPixmap( display(), bound_glxpixmap ); glxpixmap = None;
bound_glxpixmap = None;
} }
} }
void SceneOpenGL::Texture::findTarget() void SceneOpenGL::Texture::findTarget()
{ {
unsigned int new_target = 0; unsigned int new_target = 0;
if( tfp_mode && glXQueryDrawable && bound_glxpixmap != None ) if( tfp_mode && glXQueryDrawable && glxpixmap != None )
glXQueryDrawable( display(), bound_glxpixmap, GLX_TEXTURE_TARGET_EXT, &new_target ); glXQueryDrawable( display(), glxpixmap, GLX_TEXTURE_TARGET_EXT, &new_target );
// Hack for XGL - this should not be a fallback for glXQueryDrawable() but instead the case // Hack for XGL - this should not be a fallback for glXQueryDrawable() but instead the case
// when glXQueryDrawable is not available. However this call fails with XGL, unless KWin // when glXQueryDrawable is not available. However this call fails with XGL, unless KWin
// is compiled statically with the libGL that Compiz is built against (without which neither // is compiled statically with the libGL that Compiz is built against (without which neither
@ -1098,9 +1098,13 @@ bool SceneOpenGL::Texture::load( const Pixmap& pix, const QSize& size,
{ // tfp mode, simply bind the pixmap to texture { // tfp mode, simply bind the pixmap to texture
if( mTexture == None ) if( mTexture == None )
createTexture(); createTexture();
// when the pixmap is bound to the texture, they share the same data, so the texture // The GLX pixmap references the contents of the original pixmap, so it doesn't
// updates automatically - no need to do anything in such case // need to be recreated when the contents change.
if( bound_glxpixmap != None ) // The texture may or may not use the same storage depending on the EXT_tfp
// implementation. When options->glStrictBinding is true, the texture uses
// a different storage and needs to be updated with a call to
// glXBindTexImageEXT() when the contents of the pixmap has changed.
if( glxpixmap != None )
glBindTexture( mTarget, mTexture ); glBindTexture( mTarget, mTexture );
else else
{ {
@ -1110,9 +1114,7 @@ bool SceneOpenGL::Texture::load( const Pixmap& pix, const QSize& size,
GLX_MIPMAP_TEXTURE_EXT, fbcdrawableinfo[ depth ].mipmap, GLX_MIPMAP_TEXTURE_EXT, fbcdrawableinfo[ depth ].mipmap,
None None
}; };
// the GLXPixmap will reference the X pixmap, so it will be freed automatically glxpixmap = glXCreatePixmap( display(), fbcdrawableinfo[ depth ].fbconfig, pix, attrs );
// when no longer needed
bound_glxpixmap = glXCreatePixmap( display(), fbcdrawableinfo[ depth ].fbconfig, pix, attrs );
#ifdef CHECK_GL_ERROR #ifdef CHECK_GL_ERROR
checkGLError( "TextureLoadTFP1" ); checkGLError( "TextureLoadTFP1" );
#endif #endif
@ -1124,8 +1126,11 @@ bool SceneOpenGL::Texture::load( const Pixmap& pix, const QSize& size,
checkGLError( "TextureLoadTFP2" ); checkGLError( "TextureLoadTFP2" );
#endif #endif
if( !options->glStrictBinding ) if( !options->glStrictBinding )
glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL ); glXBindTexImageEXT( display(), glxpixmap, GLX_FRONT_LEFT_EXT, NULL );
} }
if( options->glStrictBinding )
// Mark the texture as damaged so it will be updated on the next call to bind()
damaged = true;
} }
else if( shm_mode ) else if( shm_mode )
{ // copy pixmap contents to a texture via shared memory { // copy pixmap contents to a texture via shared memory
@ -1263,10 +1268,17 @@ void SceneOpenGL::Texture::bind()
{ {
glEnable( mTarget ); glEnable( mTarget );
glBindTexture( mTarget, mTexture ); glBindTexture( mTarget, mTexture );
if( tfp_mode && options->glStrictBinding ) if( tfp_mode )
{ {
assert( bound_glxpixmap != None ); if ( options->glStrictBinding && damaged )
glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL ); {
// Update the texture with the new pixmap contents
assert( glxpixmap != None );
glXReleaseTexImageEXT( display(), glxpixmap, GLX_FRONT_LEFT_EXT );
glXBindTexImageEXT( display(), glxpixmap, GLX_FRONT_LEFT_EXT, NULL );
setDirty(); // Mipmaps have to be regenerated after updating the texture
}
damaged = false;
} }
enableFilter(); enableFilter();
if( hasGLVersion( 1, 4, 0 )) if( hasGLVersion( 1, 4, 0 ))
@ -1282,12 +1294,6 @@ void SceneOpenGL::Texture::unbind()
{ {
glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f ); glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f );
} }
if( tfp_mode && options->glStrictBinding )
{
assert( bound_glxpixmap != None );
glBindTexture( mTarget, mTexture );
glXReleaseTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT );
}
GLTexture::unbind(); GLTexture::unbind();
} }

View File

@ -124,7 +124,8 @@ class SceneOpenGL::Texture
private: private:
void init(); void init();
GLXPixmap bound_glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode GLXPixmap glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode
bool damaged;
}; };
class SceneOpenGL::Window class SceneOpenGL::Window