[cairo] API proposal: Damage Tracking

Behdad Esfahbod behdad at behdad.org
Thu May 8 13:55:42 PDT 2008

Hi Soeren,

This is all very interesting.  But I think we should think a bit more
about it and definitely improve the naming.  A very similar
functionality is to be able to compute the bounds of drawing operations.
So we have:

  - actual drawing
  - bounds
  - update region
  - hit testing?

The way OpenGL does it is that you can switch between drawing and hit
testing.  In cairo, may be better to be able to turn each on/off.  So
you can do all of:

  - Draw to a local buffer, get update region and push that to your
remote.  It can be used internally to improve xlib fallback backend as
well as directfb kind of backends.  We were talking about this recently.

  - Don't draw, just compute bounds.  Right now for this kind of needs
you have to create a similar surface and draw to it.  You have to use a
similar surface to get the same font options, etc.  Though most of the
times when you need the bounds you need it to create a surface of the
right size.  So I'm not sure how useful this will be.

  - No draw, just get update region for purposes like yours?

And tracking bounds/region per cairo_save() level would be really cool,



On Thu, 2008-05-01 at 02:58 +0200, Soeren Sandmann wrote:
> Hi,
> In a canvas/toolkit type project I am playing around with, I need the
> ability to track the 'damage' done by painting with a cairo context. 
> This is useful to generate repaint areas, ie., the area that the
> application needs to repaint. When something happens that causes a
> canvas item to change it appearance, damage tracking would allow the
> application to simply do this:
>         static void
>         invalidate (Item *item, cairo_t *cr)
>         {
>                 cairo_begin_damage_tracking (cr);
>                 <paint the item>
>                 damaged = cairo_end_damage_tracking (cr);
>                 add_to_repaint_region (damaged);
>                 free (damaged);
>         }
>         void
>         on_event ()
>         {
>                 cairo_t *cr = create_cr();
>                 /* Invalidate old position */
>                 invalidate (item, cr);
>                 <update item information>
>                 /* Invalidate new position */
>                 invalidate (item, cr);
>                 cairo_destroy();
>         }
> The big benefit is that this frees the application from keeping track
> of the exact region that is covering the item. Instead it can just
> compute it as needed.
> Currently the best an application can do is call
> cairo_stroke/fill_extents() after before each paint operation, but (a)
> this is inconvenient, (b) the extent rectangles are too pessimistic in
> many cases, and (c) it may not be possible to do if the painting is
> being done by a library.
> So I am proposing this new API:
>         void                        cairo_begin_damage_tracking (cr);
>         cairo_rectangle_list_t *    cairo_end_damage_tracking (cr);
> Cairo would keep track of a stack of rectangle lists corresponding to
> the nesting level. Whenever cairo_end_damage_tracking() is called, a
> the topmost list is returned after a copy of it was unioned with the
> next list on the stack.
> Open question: In the proposal above, nothing is actually painted when
> tracking damage. I think it could potentially be useful to allow
> damage tracking and painting to go on at the same time, say for
> applications that would like to keep track of the last thing they
> painted.
> A way to accomplish that would be to simply have
> begin_damage_tracking() not turn off painting, but then also provide
> begin/end_disable_painting() calls.
> Soren
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo

"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759

More information about the cairo mailing list