[cairo] Cairo efficiency with massively long lines
damon at karuna.eclipse.co.uk
Fri Feb 23 14:36:58 PST 2007
On Fri, 2007-02-23 at 16:43 -0500, Paul Davis wrote:
> On Fri, 2007-02-23 at 21:26 +0000, Damon Chaplin wrote:
> > On Thu, 2007-02-22 at 13:09 -0500, Paul Davis wrote:
> > > Greetings Cairo folks. A few people here were incredibly helpful with my
> > > last questions about planning the move of Ardour (http://ardour.org) to
> > > a Cairo-based canvas. We've run into another issue with our current use
> > > of GnomeCanvas, and I wanted to check that Cairo would handle it
> > > properly before I waste time trying to find a workaround.
> > >
> > > Will Cairo efficiently render a line that has two coordinates at zero
> > > and (say) 2^32-1 or 2^64-1 (on the x-axis) ?
> > You might run into cairo's fixed point integers limit (internally it
> > uses a 32-bit int with 16 bits for the integer value and 16-bits for the
> > fractional part).
> oh no. thats a disaster for us. the old GnomeCanvas used floats and we
> had all kinds of icky hacks to deal with the fact that it wasn't
> accurate over the full range that we actually needed. now it uses
> doubles (life is good!), and we're about ready to move on to 64 bit
> ranges. this could be a nasty setback. our coordinate space spans the
> entire range of possible sample values from 0 .. 2^N-1 where N is
> currently 32 and will move to 64.
It's not as bad as it sounds. The 16-bit limit only applies to the
transformed coordinates of the paths to be drawn. So as long as you
don't have a screen with 65536 pixels across you should be able to work
GooCanvas already has code to work around the limit, so I think it is
now only limited by the size of the scrolled GDK window, which is a
signed 32-bit int. (Though I haven't tested it up to that limit yet.)
I have even thought of adding another mode to the canvas where it
handles scrolling itself, without scrolling a GDK window. Then we would
only be limited by the double coordinates. I'm not sure how many people
would need this though.
> > > The current GnomeCanvas code generates a "micro-tile array" (UTA; a list
> > > of 32x32 pixel cells) to describe the areas of the image that need to be
> > > re-rendered, and with a line like this, the UTA is obvously huge - it
> > > correctly reflects the fact that the area to be re-rendered is enormous.
> > > As a result, when our canvas has numerous of these objects on it, any
> > > operations that cause a recomputation of what needs to be rendered are
> > > dog slow.
> > >
> > > Does Cairo's internal implementation correctly handle this kind of
> > > situation? Presumably, the correct limitation is to not compute a UTA
> > > that extends beyond the current visible bounds of the
> > > image/canvas/pixbuf. I'd appreciate clarification on how Cairo does
> > > this.
> > My inclination would be to write your own custom canvas items that only
> > draw what is visible. Though I hope someone who knows more can give a
> > definitive answer.
> I know enough about the canvas to know what is going on here. The
> problem isn't drawing. The canvas has an update phase, done once per
> redraw, and the update phase lets the items that will be rendered update
> their data structures (e.g. after they've had a color or coordinate or
> other property change). The existing line item needs to figure out what
> parts of itself might need redrawing, and after we change some
> properties, the answer is "everything". this means 2^N-1 pixels (at
> least). the slowdown doesn't occur during rendering - in fact, the lines
> in question are not even visible. the slowdown is all during this
> "update" phase.
> changing the canvas architecture doesn't seem like an option for us, but
> what is really needed is an update phase that says "update your own
> stuff, oh, and by the way, the only part of you that will be rendered
> lies within the following clip path ...."
> this would allow the item to do a saner evaluation of "what needs to be
> re-rendered next time we are rendered" than the current design, which
> says "update your own stuff, and i'll give you no hints at all about
> which parts of you are visible", thus forcing an evaluation of the
> entire extent of the item.
I don't think you'll have a problem with GooCanvas there. In your item's
update function you just need to update the item's bounds and call
request_redraw() on the old & new bounds. GooCanvas should calculate
what parts of the visible window need redrawing. It doesn't use anything
like a microtile array so should be very quick.
My main concern would be rendering speed, though you could try it out to
see if it is fast enough.
More information about the cairo