KDE  

Reducing (maybe removing :-) Konqueror's flickering
... and speeding up your browsing !

Last edited on 2004-Jul-11 @ 13:42
  Last patch merged on CVS. The only unapplied patch remains 01, but this can't be applied to qt as it is now.
    Qt4 (tech-preview-01) has a similar patch in the default distribution.
  While busy at school, many other patches took their way to cvs (kmenu, konqueror iconview scaling, etc..)
    thanks goes to Dario, who found many problems and looked for ways fixing them.. now he's got it's own CVS account.  
Previous update on 2004-Apr-06 @ 08:22
  Added patch 06
  Did the same fixes on KFileIconView on CVS


 Introduction  

What's that flickering ?
This document and provided patches are focused on reducing the visual effect that people names 'flicker'. Even if you have a 300MHz cpu or a high end 3GHz processor you can notice it. It might sound stange, but the latter case is 'visually' the worst because people will perceive the screen 'flickering' (and say: "i hate X" :-) while the proud owners of the 300MHz cpu will perceive it as what it really is: a repaint!

Where do the flickering comes from ?
Basically I found 3 classes of problems on our lovely widgets that lead into flickering and visual performance degradation:
  1. graphics updates to the screen while a paint operation is in progress
    example: updating the framebuffer composting a 3 layer image with unpredictable random repainting of the screen (so you'll see the image growing from the background).
  2. uncorrectly handling/redundant paint operations
    example: draw a first block, then a second, then a third, ..., then draw all the widget! (in that case only the last operation should be performed)
  3. excessive repainting
    example: for (10 times) { draw_the_same_thing! };
Only the first case represents the real flickering and it can be solved by buffering drawing operations so slow composting can be done on a pixmap and then blitted to the screen in a small time slot between 2 consecutive X refreshes.
The second case requires identifying unuseful paint operations (to be suppressed) and optimize the graphical flow and the third case requires it too.

How to debug ? And what have you sorted out ?
Just a little note: to be able to catch the problem I changed the cpu frequency to 316.6 MHz and ran konqueror under valgrind! (That means: you see konqueror painted to the screen pixel by pixel and you're slow enough to debug ^_^). When opening a flat konqueror and clicking on the 'home' button I got the following paint operations:
2complete redraws (only background)
25small 'blank' areas with the same size of the 25 items (in my dir)
think at what will happen in a large directory.. below is the answer
2complete redraws (all icons but no previews)
1draw of the top-left corner icon (with 'focus' rectangle this time)
3draws of the previews at the right place

Ok, I see icons in konqy, where is the code that draws them?
QWidget
QFrame
QScrollView
QIconView
KIconView
KonqIconViewWidget
  From now on we'll focus on the konqueror window. When you browse your filesystem in the IconView mode (and in the MultiColumn mode too) what you see is the KonqKfmIconView at work. That class inherits the browsing function from KonqDirPart and represents data using it's internal KonqIconViewWidget.
Here is the inheritance diagram; please note that flickering is introduced at some points in that chain.



 Gimme the patches now! (I can't wait to screw up my system! :-)  
  • 5 patches available
  • 0 things are being investigated (maybe kdesktop repaints in the future)

01 Buffering paint operations on IconViews
Addition: removes flicker on: icon selection/hover, repaints, ...
 Let's take a look at the inheritance chain. A repaint/update operation that occours in the iconview (Q/K/KonqW) is handled by the QScrollView's internal function 'viewportPaintEvent'. Here the painter gets opened to the viewport widget (the main area of the scrollview). This acts like a screen.. the opened painter is passed to the QIconView or deeper childs via 'drawContents' and 'drawBackground' calls. Inside that functions, the QIconView iterates over its 'icons' to draw them.
 In the following patch, paint events on QIconView are caught internally and processed in a function called 'bufferedPaintEvent()'. This opens a painter to a pixmap and passes it to the 'drawContents' functions instead of opening the painter directly to the screen surface. Only that class and its derivates will be doublebuffered.
  01 qiconview_buffered.patch

02 No repaint on activation - Sent to Qt
BugFix: 1 wasted repaint when window loses/gains focus (and maybe more..)
 A complete repaint is made when a window containing a QIconView loses/gains focus.
 This is generated only if the 'viewport' of the QScrollView was set to have a picture in the background. (Try to switch between 2 konqueror windows in iconview mode. You'll notice the flickering only when the background is set to a pixmap and not if is set to a color).
 The following patch fixes the problem that I discovered to be a bug() of the QScrollview's viewport.
  02 qscrollview_fixwindowactivate.patch

03 Saving *lots* of paint operations - Applied in CVS
BugFix: wasted paints when displaying icons
 Here comes a very small patch that leads to big speed increase when browsing large directories. If you take a look at the table with paint operations you'll see what I saw in the right picture: for each item in the directory a paint operation is performed on the top-left corner of the iconview. Fixes introduced with this patch:
- loading times of a 600 files directory went down from ~0.5 to ~0.2 s on a 2.6GHz processor and from 3.2 to 1.3 seconds on a 300MHz processor. (tested with the antiflicker patch; the gain will be lower without it, but we're always talking about a 2x .. 3x speed increase, not some percents :-P)
- the 'mistery of the top-left item flickering' now solved.
- I'm now noticing great visual and speed improvements on the file search dialog!
 The patch acts by disabling the updates while inserting items in the iconview, so this will block paint calls raised in the meanwhile.
  03 konqiconview_fixsingleupdates.patch

04 Strange flicker: unsorted frame - Applied in CVS
BugFix: 1 wasted paint (with bad placed icons)
 This patch removes an annoying visual artifact that shows up sometimes when browsing your filesystem. Sometimes this is preceived as flickering on fast machines, but on slower processor you're able to see "icons in the wrong place (or order) for a short amount of time".
 For example, if a directory will be rendered this way, you can catch for a while (maybe some milliseconds) this image.
 The patch reorders some instructions, so they work in the right order preventing a paint operation before the view gets sorted.
  04 konqiconview_fixbadsort.patch

05/06 Disable clearing background - Applied in CVS
Addition: don't display an empty background before directory contents
 This patch removes an annoying visual artifact that shows up when changing URL. In fact, you see that the viewport gets cleared and the filled up with icons. So it will be useful (and looks so good to me) to remove that "blank paints", so folders are displayed with 'continuity' when browsing.
Here you can see a couple of pictures about the rendering before and after this patch:
before <- here you can see that background is painted 3 times and then the first icon is painted
after <- here you can see that background is painted only one time
 NOTE: To apply this patch you must also apply patches 03 + 04
 The patch disables graphics updates on the viewport during some calls that may clear the viewport and re-enables updates after that calls.
  05 konqiconview_noclearing.patch
 Added the following patch: it clears the viewport after a timeout if the update is taking too long.
  06 konqiconview_cleartimeout.patch


 Conclusions  

You might be interested in seeing the current (re)paint list when updating the view:
1complete redraw
3draws of the previews at the right place
I'm currently running a konqueror with all the patches applied and .. I'm feeling sort of BORED about konqueror's Anti-Flickerness ^_^ (kidding). No more wait-before-content-appears no more flashing icons, no more blinking on window change, .. what will catch my attention now?? Let's revert! :-)
/really now/ -> Try this patches, they're simple but they SpEEdS and C00LS up your browsing :-P


Enjoy the koolest (and flicker-free) lovely desktop ! ^_^. - Enrico Ros