Improved filtering algorithm. Now fast filtering is used by default, while (depending on SmoothScale in kwinrc) bilinear filtering is used on transformed windows and screens.

Optionally, if SmoothScale is set to 2, trilinear filtering will be attempted instead of bilinear.  This requires GL_ARB_texture_non_power_of_two, GL_EXT_framebuffer_object, and valid mipmaps.

svn path=/branches/work/kwin_composite/; revision=629453
icc-effect-5.14.5
Philip Falkner 2007-02-02 19:58:35 +00:00
parent 66d796002f
commit f060c3bfbb
7 changed files with 61 additions and 10 deletions

View File

@ -195,7 +195,7 @@ unsigned long Options::updateSettings()
onlyDecoTranslucent = config->readEntry("OnlyDecoTranslucent", QVariant(false)).toBool();
refreshRate = config->readEntry( "RefreshRate", 0 );
smoothScale = qBound( -1, config->readEntry( "SmoothScale", -1 ), 1 );
smoothScale = qBound( -1, config->readEntry( "SmoothScale", -1 ), 2 );
QString glmode = config->readEntry("GLMode", "TFP" ).upper();
if( glmode == "TFP" )

View File

@ -301,7 +301,9 @@ class Options : public KDecorationOptions
bool onlyDecoTranslucent;
uint refreshRate;
int smoothScale; // 0 = no, 1 = yes, -1 = auto
int smoothScale; // 0 = no, 1 = yes when transformed,
// 2 = try trilinear when transformed; else 1,
// -1 = auto
enum GLMode { GLTFP, GLSHM, GLFallback };
GLMode glMode;

View File

@ -242,6 +242,7 @@ void Scene::finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowP
Scene::Window::Window( Toplevel * c )
: toplevel( c )
, filter( ImageFilterFast )
, shape_valid( false )
{
}

View File

@ -69,6 +69,8 @@ class Scene
// Clear whole background as the very first step, without optimizing it
PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6,
};
// types of filtering available
enum ImageFilterType { ImageFilterFast, ImageFilterGood };
// there's nothing to paint (adjust time_diff later)
void idle();
bool waitSyncAvailable() { return has_waitSync; }
@ -139,6 +141,7 @@ class Scene::Window
Window() {} // QMap sucks even in Qt4
protected:
Toplevel* toplevel;
ImageFilterType filter;
private:
mutable QRegion shape_region;
mutable bool shape_valid;

View File

@ -717,6 +717,7 @@ SceneOpenGL::Window::Window( Toplevel* c )
, texture_y_inverted( false )
, texture_can_use_mipmaps( false )
, texture_has_valid_mipmaps( false )
, texture_filter_trilinear( false )
, bound_glxpixmap( None )
, currentXResolution( -1 )
, currentYResolution( -1 )
@ -1044,16 +1045,29 @@ void SceneOpenGL::Window::enableTexture()
assert( bound_glxpixmap != None );
glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL );
}
if( options->smoothScale != 0 ) // default to yes
{
glTexParameteri( texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
else
if( filter == ImageFilterFast )
{
glTexParameteri( texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
}
else if( filter == ImageFilterGood )
{
if( texture_filter_trilinear )
{
glTexParameteri( texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
if( !texture_has_valid_mipmaps )
{
glGenerateMipmap( texture_target );
texture_has_valid_mipmaps = true;
}
}
else
{
glTexParameteri( texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
}
void SceneOpenGL::Window::disableTexture()
@ -1117,6 +1131,24 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
return;
bindTexture();
glPushMatrix();
// set texture filter
if( options->smoothScale != 0 ) // default to yes
{
if( mask & PAINT_WINDOW_TRANSFORMED )
filter = ImageFilterGood;
else if( mask & PAINT_SCREEN_TRANSFORMED )
filter = ImageFilterGood;
else
filter = ImageFilterFast;
}
else
filter = ImageFilterFast;
// avoid unneeded mipmap generation by only using trilinear filtering
// when it actually makes a difference, that is with minification or
// changed vertices
texture_filter_trilinear = options->smoothScale == 2
&& supports_npot_textures && supports_fbo && texture_can_use_mipmaps
&& ( verticesDirty || data.xScale < 1 || data.yScale < 1 );
// do required transformations
int x = toplevel->x();
int y = toplevel->y();

View File

@ -139,6 +139,7 @@ class SceneOpenGL::Window
bool texture_y_inverted; // texture has y inverted
bool texture_can_use_mipmaps;
bool texture_has_valid_mipmaps;
bool texture_filter_trilinear;
GLXPixmap bound_glxpixmap; // the glx pixmap the texture is bound to, only for tfp_mode
QVector<Vertex> verticeslist;

View File

@ -438,6 +438,18 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
Picture pic = picture(); // get XRender picture
if( pic == None ) // The render format can be null for GL and/or Xv visuals
return;
// set picture filter
if( options->smoothScale > 0 ) // only when forced, it's slow
{
if( mask & PAINT_WINDOW_TRANSFORMED )
filter = ImageFilterGood;
else if( mask & PAINT_SCREEN_TRANSFORMED )
filter = ImageFilterGood;
else
filter = ImageFilterFast;
}
else
filter = ImageFilterFast;
// do required transformations
int x = toplevel->x();
int y = toplevel->y();
@ -472,7 +484,7 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
XRenderSetPictureTransform( display(), pic, &xform );
width = (int)(width * xscale);
height = (int)(height * yscale);
if( options->smoothScale == 1 ) // only when forced, it's slow
if( filter == ImageFilterGood )
XRenderSetPictureFilter( display(), pic, const_cast< char* >( "good" ), NULL, 0 );
// transform the shape for clipping in paintTransformedScreen()
QVector< QRect > rects = transformed_shape.rects();
@ -508,7 +520,7 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
{ XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) }
}};
XRenderSetPictureTransform( display(), pic, &xform );
if( options->smoothScale == 1 )
if( filter == ImageFilterGood )
XRenderSetPictureFilter( display(), pic, const_cast< char* >( "fast" ), NULL, 0 );
}
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );