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
This commit is contained in:
parent
66d796002f
commit
f060c3bfbb
7 changed files with 61 additions and 10 deletions
|
@ -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" )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
}
|
||||
|
|
3
scene.h
3
scene.h
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue