[cairo] Best strategy for complex screen drawing

Timothée Lecomte timothee.lecomte at ens.fr
Mon Nov 21 16:05:34 PST 2005


Thanks for your enthusiastic and detailed answers !
Below are my answers, in one mail as your ideas were complementary.



Vladimir Vukicevic wrote:

>>2) Would it be more efficient to use a specific backend ? For example,
>>should I draw to an offscreen Xlib pixmap, and use it as a source
>>surface ? Will I benefit from possible render acceleration ?
>>    
>>
>
>It would be more efficient to use a specific platform offscreen
>surface; the image surface is really the slowest possible path.  Using
>a platform native surface will also let you take advantage of RENDER
>acceleration or specific windows/mac/etc. accelerations.  Using an
>offscreen pixmap also makes your screen update very fast if you use a
>native cairo surface for your X window -- because the blit will
>ideally happen on the video card, or at least in the X server.
>  
>
Ok, I think I understand better the interest of those specific surfaces.

>>3) Are there other solutions that I might have forgotten ?
>>    
>>
>
>Not really; make sure you're following all the FAQs regarding fast
>rendering (e.g. drawing pixel-aligned rectangles and lines correctly).
> Trying to combine your polygons into a single path may help as well? 
>Other than that, some sample code that shows the performance issues
>would be useful.
>
>    - Vladimir
>  
>
Indeed, I follow the FAQ by translating pixel coordinates by 0.5 in each
direction to avoid blurry lines.
Combining polygons is difficult for me. Indeed, I have basically a list
of commands like this :

    cairo_move_to(cr, device_x(corners[0].x), device_y(corners[0].y));

    for (int i=1;i<n;i++) {
        cairo_line_to(cr, device_x(corners[i].x), device_y(corners[i].y));
    }
    cairo_close_path(cr);

    wxt_cairo_fill( fillstyle, fillpar);

    cairo_fill_preserve(cr);
    cairo_set_line_width(cr, 1);
    cairo_stroke(cr);

In this code, in general, n = 3 (4 corners), and wxt_cairo_fill(...)
just sets the color via cairo_set_source_rgb(...).



Jeff Smith wrote:

>In my limited experience, I have found that for more complex images most of the time is
>spent in stroke and fill functions.  This will be a near-constant time as long as the
>backend does not have its own callback for stroke and fill.  In this case, the fallback
>functions are used, which are just not that fast.  Stroke is the worse of the two because
>lines can actually be fairly complex.
>
> -- Jeff Smith
>
If I change cairo_fill_preserve() and cairo_stroke() for a single
cairo_fill(), the drawing time is almost divided by 2. However, the
output is not satisfying, so I keep the two calls.
As Vladimir Vukicevic suggested, I might combine my polygons to a single
path, but I think I can't do it as the color of these paths change.




Federico Mena Quintero wrote:

>That's horrible performance (0.5 milliseconds per polygon).  We should
>be able to provide a really fast, all-software implementation of the
>image surface.
>
>Have you taken profiles of this?  Gnuplot will certainly be an
>interesting use case for Cairo, and it needs to be made fast.
>
>  Federico
>  
>
I have just found a problem in my code (was creating a useless (in most
cases) pattern for each polygon), and I now reach approximately 0.2
milliseconds per polygon when drawing to a X11 pixmap surface. However,
I still too slow compared to pure X11 calls (but not anti-aliased of
course).




Bill Spitzak wrote:

> What you want is double buffering, or backing store, or offscreen
> rendering, or any of a dozen other names. This should be provided by
> the system or the toolkit as some kind of modification to an existing
> window object.
>
> You do not want to do your own "fake" double buffering by allocating
> some other object and doing explicit copies. The reason is that the
> "real" double buffering knows that the image and the window are
> explicitly linked, and can be setup to copy very fast, and it can take
> advantage of the fact that the backing store will not be used for any
> purpose other than to update the visible window. It can resize and
> delete it in sync with the real window, and free it if your window has
> not been displayed for a long time.
> (...)
>
> So the answer is: if you think you have to create two objects, that is
> wrong. Figure out a way so that there is one object per screen area.
> Examine your system and/or toolkit to find out how to turn this on. If
> it does not seem possible, you must switch toolkits.
>
> You may also find that the toolkit provides the interface but
> internally it is using a pixmap just like you were going to. This is
> ok. It indicates the toolkit authors are thinking about the future and
> plan to rewrite this area, so you should plan for it by using their
> interface.

Thanks for these details ! Let's talk about the way I should implement it.
Under X11 via gdk, I draw offscreen to a GdkPixmap thanks to
gtk_cairo_create(GdkPixmap*).
Then, I copy this pixmap to the screen with gdk_draw_drawable() when I
receive a "window-must-be-painted" event.

With such code, the initial drawing takes approximately 0.2 milliseconds
per polygon (pretty slow), and the copy to the screen is almost satisfying.

Does it correspond to the scheme you were describing ? Can this be
improved ?



Thanks for your help !
Yours sincerely,

Timothée






More information about the cairo mailing list