Detect screen refresh rate for finding out optimal compositing

redraw speed. Patch by Philip Falkner.


svn path=/branches/work/kwin_composite/; revision=607253
This commit is contained in:
Luboš Luňák 2006-11-23 21:16:49 +00:00
parent 8bbf28ed9c
commit 38f4f76b31
7 changed files with 72 additions and 13 deletions

View file

@ -71,6 +71,9 @@ target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} kdecorations ${X11_LIBRAR
target_link_libraries(kdeinit_kwin -lGL) target_link_libraries(kdeinit_kwin -lGL)
# -ldl used by OpenGL code # -ldl used by OpenGL code
target_link_libraries(kdeinit_kwin -ldl) target_link_libraries(kdeinit_kwin -ldl)
if (X11_Xrandr_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xrandr_LIB})
endif (X11_Xrandr_FOUND)
if (X11_Xcomposite_FOUND) if (X11_Xcomposite_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xcomposite_LIB}) target_link_libraries(kdeinit_kwin ${X11_Xcomposite_LIB})
endif (X11_Xcomposite_FOUND) endif (X11_Xcomposite_FOUND)

View file

@ -16,6 +16,7 @@ TODO
- in other words, these should be the best if you want to get started with the code - in other words, these should be the best if you want to get started with the code
/ = work in progress / = work in progress
? = should it be done? ? = should it be done?
% = should be probably done later, during cleanups and preparations for being stable
General TODO General TODO
@ -40,7 +41,7 @@ General TODO
- maybe posted paint events need to be processed immediatelly, or maybe the compositing - maybe posted paint events need to be processed immediatelly, or maybe the compositing
code should not update the window until the decoration is finished painting code should not update the window until the decoration is finished painting
* handle XRandr changes / handle XRandr changes
- output buffers and similar probably need recreating when the screen size changes - output buffers and similar probably need recreating when the screen size changes
! compile even without OpenGL or XRender ! compile even without OpenGL or XRender
@ -51,17 +52,18 @@ General TODO
? Expose events for overlay window - is it necessary to track it, like with root window? ? Expose events for overlay window - is it necessary to track it, like with root window?
% paint throttling
- there's 5ms grace period per repaint to avoid overloading the system with just compositing
and not letting the system do anything else - check and evaluate
OpenGL TODO OpenGL TODO
================================= =================================
+ Check/make it work with other gfx cards + Check/make it work with other gfx cards
- I've tested only with nvidia with the 9625 beta drivers and 8776 stable drivers so far - I've tested only with nvidia with the 9625 beta drivers and 8776 stable drivers so far
- ATI - some (especially R200 chips) seem to work
- I have absolutely no idea about other gfx cards, needs to be tested - I have absolutely no idea about other gfx cards, needs to be tested
- ati
! - does kwin_composite work there at all?
! - does glcompmgr work there at all? (even with the various switches in the source)
+ - make kwin_composite work there if it doesn't
- intel - intel
! - does kwin_composite work there at all? ! - does kwin_composite work there at all?
! - does glcompmgr work there at all? (even with the various switches in the source) ! - does glcompmgr work there at all? (even with the various switches in the source)
@ -80,9 +82,8 @@ OpenGL TODO
? - is there a good reason to support Xgl? With the 9625 nvidia drivers ? - is there a good reason to support Xgl? With the 9625 nvidia drivers
it seems to work fine without them and there's AIGLX it seems to work fine without them and there's AIGLX
? AIGLX support + AIGLX support
- no idea about this at all - kind of works, needs more work
+ - find out if it works
! improved GLXFBConfig support ! improved GLXFBConfig support
- it seems a different config for each depth would be needed - it seems a different config for each depth would be needed
@ -96,10 +97,6 @@ OpenGL TODO
one for the root window (or for the window used in the XComposite overlay) one for the root window (or for the window used in the XComposite overlay)
and the best one for every depth of drawables and the best one for every depth of drawables
/ sync to vblank
- currently the compositing code is run with 20ms timer, i.e. constant 50fps
- the GLX_SGI_video_sync extension should be used
+ GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two + GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two
- code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using - code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using
normal textures when GL_ARB_texture_non_power_of_two is available should(?) be normal textures when GL_ARB_texture_non_power_of_two is available should(?) be

View file

@ -80,7 +80,34 @@ void Workspace::setupCompositing()
kDebug( 1212 ) << "No compositing" << endl; kDebug( 1212 ) << "No compositing" << endl;
return; return;
} }
compositeTimer.start( 20 ); int rate = 0;
if( options->refreshRate > 0 )
{ // use manually configured refresh rate
rate = options->refreshRate;
}
#ifdef HAVE_XRANDR
else
{ // autoconfigure refresh rate based on XRandR info
if( Extensions::randrAvailable() )
{
XRRScreenConfiguration *config;
config = XRRGetScreenInfo( display(), rootWindow() );
rate = XRRConfigCurrentRate( config );
XRRFreeScreenConfigInfo( config );
}
}
#endif
// 0Hz or less is invalid, so we fallback to a default rate
if( rate <= 0 )
rate = 50;
// QTimer gives us 1msec (1000Hz) at best, so we ignore anything higher;
// however, since compositing is limited to no more than once per 5msec,
// 200Hz to 1000Hz are effectively identical
else if( rate > 1000 )
rate = 1000;
kDebug( 1212 ) << "Refresh rate " << rate << "Hz" << endl;
compositeTimer.start( 1000 / rate );
lastCompositePaint.start(); lastCompositePaint.start();
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual ); XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
if( dynamic_cast< SceneOpenGL* >( scene )) if( dynamic_cast< SceneOpenGL* >( scene ))

View file

@ -194,6 +194,7 @@ unsigned long Options::updateSettings()
removeShadowsOnResize = config->readEntry("RemoveShadowsOnResize", QVariant(true)).toBool(); removeShadowsOnResize = config->readEntry("RemoveShadowsOnResize", QVariant(true)).toBool();
onlyDecoTranslucent = config->readEntry("OnlyDecoTranslucent", QVariant(false)).toBool(); onlyDecoTranslucent = config->readEntry("OnlyDecoTranslucent", QVariant(false)).toBool();
refreshRate = config->readEntry( "RefreshRate", 0 );
QString glmode = config->readEntry("GLMode", "TFP" ).upper(); QString glmode = config->readEntry("GLMode", "TFP" ).upper();
if( glmode == "TFP" ) if( glmode == "TFP" )
glMode = GLTFP; glMode = GLTFP;

View file

@ -300,6 +300,7 @@ class Options : public KDecorationOptions
uint dockShadowSize; uint dockShadowSize;
bool onlyDecoTranslucent; bool onlyDecoTranslucent;
uint refreshRate;
enum GLMode { GLTFP, GLSHM, GLFallback }; enum GLMode { GLTFP, GLSHM, GLFallback };
GLMode glMode; GLMode glMode;
bool glAlwaysRebind; bool glAlwaysRebind;

View file

@ -45,6 +45,8 @@ namespace KWinInternal
bool Extensions::has_shape = false; bool Extensions::has_shape = false;
int Extensions::shape_event_base = 0; int Extensions::shape_event_base = 0;
bool Extensions::has_randr = false;
int Extensions::randr_event_base = 0;
bool Extensions::has_damage = false; bool Extensions::has_damage = false;
int Extensions::damage_event_base = 0; int Extensions::damage_event_base = 0;
bool Extensions::has_composite = false; bool Extensions::has_composite = false;
@ -55,6 +57,17 @@ void Extensions::init()
{ {
int dummy; int dummy;
has_shape = XShapeQueryExtension( display(), &shape_event_base, &dummy); has_shape = XShapeQueryExtension( display(), &shape_event_base, &dummy);
#ifdef HAVE_XRANDR
has_randr = XRRQueryExtension( display(), &randr_event_base, &dummy );
if( has_randr )
{
int major, minor;
XRRQueryVersion( display(), &major, &minor );
has_randr = ( major > 1 || ( major == 1 && minor >= 1 ) );
}
#else
has_randr = false;
#endif
#ifdef HAVE_XDAMAGE #ifdef HAVE_XDAMAGE
has_damage = XDamageQueryExtension( display(), &damage_event_base, &dummy ); has_damage = XDamageQueryExtension( display(), &damage_event_base, &dummy );
#else #else
@ -99,6 +112,15 @@ bool Extensions::hasShape( Window w )
return boundingShaped != 0; return boundingShaped != 0;
} }
int Extensions::randrNotifyEvent()
{
#ifdef HAVE_XRANDR
return randr_event_base + RRScreenChangeNotify;
#else
return 0;
#endif
}
int Extensions::damageNotifyEvent() int Extensions::damageNotifyEvent()
{ {
#ifdef HAVE_XDAMAGE #ifdef HAVE_XDAMAGE

View file

@ -17,6 +17,10 @@ License. See the file "COPYING" for the exact licensing terms.
#include <X11/Xlib.h> #include <X11/Xlib.h>
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XCOMPOSITE #ifdef HAVE_XCOMPOSITE
#include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xcomposite.h>
#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3 #if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
@ -151,6 +155,8 @@ class Extensions
static void init(); static void init();
static bool shapeAvailable() { return has_shape; } static bool shapeAvailable() { return has_shape; }
static int shapeNotifyEvent(); static int shapeNotifyEvent();
static bool randrAvailable() { return has_randr; }
static int randrNotifyEvent();
static bool damageAvailable() { return has_damage; } static bool damageAvailable() { return has_damage; }
static int damageNotifyEvent(); static int damageNotifyEvent();
static bool compositeAvailable() { return has_composite; } static bool compositeAvailable() { return has_composite; }
@ -160,6 +166,8 @@ class Extensions
private: private:
static bool has_shape; static bool has_shape;
static int shape_event_base; static int shape_event_base;
static bool has_randr;
static int randr_event_base;
static bool has_damage; static bool has_damage;
static int damage_event_base; static int damage_event_base;
static bool has_composite; static bool has_composite;