Hi. My background is in video compression and OpenGL (3D stuff) but perhaps I have something useful to contribute to this discussion. Also, I am an old SodiPodi user and have been using Inkscape since shortly after it forked. Currently I use Inkscape to do all my drawings for school. Anything which would help improve the responsiveness of Inkscape would be a boon to me personally.
bulia byak wrote:
2010/4/26 Krzysztof KosiĆski <tweenk.pl@...400...>:
It's not necessary to switch to the Illustrator method (which by the way I find very hard to justify). What I wanted is to redraw everything in one go. It would make the renderer less responsive, but I intended that to be overcome by the speed increase from hardware acceleration.
Please don't do that. No matter how fast is renderer, there will always be documents for which it's not fast enough. Especially since our format is SVG, where it takes just minutes to write a script generating a document with thousands of objects.
Obviously there are two conflicting goals:
- Respond to user actions as quickly as possible.
- Do not show a partially redrawn screen.
I really don't see why 2 is a goal at all. If the renderer becomes as fast as you seem to imply, then this partial render will be simply impossible to notice! On the other hand, if it _can_ be noticed, it means the rendering is not fast enough, and we need to spend all effort on achieving goal 1.
I agree that 2 should not be a goal. -- Yet, I do not know why things should be rendered on screen. I am not familure with Cairo and the choices available probably differ, but in OpenGL rendering in an off screen buffer and then calling swapbuffers() is about an order of magnitude faster than rendering on screen. You could ever do it iteratively -- render first slice off screen, dump to current screen, render next slice off screen, compose with first, dump updated buffer to screen buffer, repeat until complete. Mmmmmuch faster.
First, I would make the renderer reasonably interruptible. Then I would set a configurable threshold, say 20ms, for what should be considered "instantaneous". On every redraw I set a 20ms timer. If the timer expires before I'm done, I throw away whatever I was doing, split the image into 4 tiles and start over. When drawing each tile I set a timer as well, and I progressively reduce the tile size as the timers expire before I'm done, until I hit some minimum tile size at which expiring timers do not cause a tile shrink. I would keep rendering at that tiling level as long as the redraw of each tile takes more than 1/4 of the time limit.
Oh. Are you really suggesting to do all this during interactive work? Did you make an estimate of how much time this would waste in the worst case? And why all this waste - just for the sake of "all at once" redraw?
Let's say it was off by a factor of 1000. 4^5 = 1024 so 20ms * 5 iterations = 100ms. Not bad.
On the other hand, some kind of adaptive buffer sizing may be beneficial indeed. But it must go in the opposite direction - and never discard anything. Namely: time the render of each buffer; if it was rendered fast enough, double the size of the next buffer (i.e. render two buffers at once); if it was rendered slow, halve the next buffer until some fixed minimum is reached. This strategy may reduce the overall number of buffer strips on the screen and perhaps speed it up somewhat without damaging interactivity too much.
This is better though. Don't throw away rendered restate which has not been invalidated. If it is necessary to render on screen then altering the size of the slices is a good way to keep the updates flowing so the user knows Inkscape is still hard at work. Also, depending on what the performance hit associated with doing slices is... (if there isn't one, render line by line) we will want to increase the slice size if it falls below some value, say 5ms. This will help keep the render preforming at a visually consistent rate. See Jasper's email.
This is basically the same trick I used in the SV3 codex for quicktime. If it's taking too long/over size, reduce the next frame/slice, but keep the current one. Everyone seemed to like it in quicktime. Because the stream was buffered for video, if one frame was oversize that was alright, as long as we adjusted the size of future frames to keep the overall stream size on target. -- Then we did the two pass compressor... (not appropriate for Inkscape)
Another reason this approach is better than yours is that for your proposal to work, you need a way to be able to stop the actual render at a given time. There's no guarantee Cairo will allow you to do that. If it _were_ possible to "pause" rendering at a given time, retrieve the partial results and then resume the render from this place _without_ the renderer losing its setup and path data, then it would be the ideal solution for us - we would have fine-grained interactive response and no time wasted on setting up buffers, re-tesselating paths, etc. But I really doubt Cairo will be that nice :)
Humm, I don't know enough about Cairo...
*snip*
From a user perspective the Illustrator render method is a real downer, please don't do that. Objects poping up (or under), one is never quite sure it's finished, or if the piece I'm looking at is done, yuck.
Also, if all invalidated screen areas can't be updated in say 200ms, drop back to a faster rendering mode (outline) and then progressively fill in the finished render, while fielding user events (keystrokes). Think something similar to Vectorworks. Doing this would be a great improvement for scroll, zoom, interactive rotate, scale, etc!
Any way, sorry for butting in uninvited. I wish everyone the best in helping improve Inkscape.
-Sam George (ciradrak)