Hi Jorge, On Mon, Feb 04, 2008 at 07:31:29PM -0300, Jorge Arellano Cid wrote:
Well an experimental prototype was committed. The original idea here was to use this new API:
void Textblock::flush (bool asap) void FltkViewBase::queueDrawTotal (bool asap)
(asap = "As soon as possible")
and to call the function inmediately when "asap" is true and to otherwise delay to a tunable number of seconds.
After some tests it showed extraordinarily effective. For instance testing with the "All" directory from:
http://chlamydia.fs.ei.tum.de/pub/DragonFly/packages/stable/DragonFly-1.10.1...
it was roughly using 2 to 3 times less CPU (in my notebook) than using the FltkPlatform::generalIdle() throttling patch.
Some glitches remained, and while I was working on it, the test server above went down... :(
I got a big surprise when after some more tests, it worked quite well when ignoring everything but calls with asap=true ! :-)
For instance, now the code reads:
void FltkViewBase::queueDrawTotal (bool asap) { static time_t lastRedraw = 0;
//if (asap || time(0) > lastRedraw + 2) { if (asap) { redraw (DAMAGE_EXPOSE); lastRedraw = time(0); } }
If I understand this correctly, the patch now is equivalent to removing the calls to queueDrawTotal(), where asap == false, right? With this patch I see missing screen updates e.g. when resizing the window.
(lastRedraw is not used).
The patch is much simpler than it looks. Many lines are just for adding the extra parameter.
Images on long pages still queue a resize that produces a total redraw. i.e when an image outside the viewport resizes, the viewport is redrawn causing flickering.
This is not completely trivial because the image resize may change the size of the parent widget, and the parent widget may affect the viewable area.
If this can somehow be avoided, for instance testing whether the parent widget changes its size, it'd be great.
This part of the code clearly needs a review. I wanted to commit early so you guys have the chance to play with it.
First let me explain how I think the drawing and relayout is designed in dillo2. Please correct me if I'm wrong. * Frequent redraws are good if they update the visible content. E.g. when loading a page over a slow line. Immediate feedback to the user is a great feature of dillo. The screen flickering can be avoided with some double buffer mechanism. * queueResize() calls are put into the code whenever the layout might have changed without worrying too much about performance. To make this efficient, queueResize() or queueDrawTotal() just remembers drawing or resizing should be done at some time in the future. * The idle function mechanism then does the actual work of resizing or redrawing. This way many calls to queueResize() can cause many resize operations, or they can be combined to just single resize depending on when the idle functions are called. When loading the same page, dillo can update the screen frequently if enough CPU is available, or less often, if CPU time is not available. I think this is an excellent concept :-) So what do we need to do? * Make the concept work properly. Here I think we need to improve the code where the idle functions are called so that multiple redraws are really combined especially if there is no CPU available. * Of course we still should reconsider each call to queueDrawTotal() or queueResize() and verify whether it is really necessary. However I think we should favor correctness over speed. That means, whenever the layout might have changed, we must call queueResize(). * It would be nice, if we could decide whether a resizing widget affects the layout that is currently visible, so that we could avoid redrawing in this case. This would avoid redrawing when loading very long pages as the DragonFly package list. But I don't think this is easy. Also we should agree on what we actually want to optimize. I don't think CPU usage or number of redraws are enough. Instead dillo should be usable and "feel fast" on fast and slow or loaded systems (if CPU is available, why not use it?). Cheers, Johannes