[cairo] Cairo double buffer example

Diego Jacobi jacobidiego at gmail.com
Sat Mar 14 16:52:49 PDT 2009


I am not sure if this is Double Buffer. But may be close to it:

I have 3 layers created by 3 functions called at different events.

Layer0 is the background and grid.
Layer1 is actual data displayed.
Layer2 is some information showed when mouse is over.

Each layer looks like the next:

void build_layer0 ( GtkWidget *widget )
{
    cairo_t *cr;

    if (sf0 != NULL)
        cairo_surface_destroy(sf0);

    sf0 = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32 ,
widget->allocation.width, widget->allocation.height );
    cr = cairo_create(sf0);

  // oO Stuff here
    calculate_boxes(widget->allocation);
    draw_boxes(cr);

    cairo_destroy (cr);
}

sf0, sf1 and sf2 are all cairo image surfaces which should be kept
alive on each redraw event.
cairo_surface_t *sf0, *sf1, *sf2;  // Layers

The from any redraw event i call a function called draw:

void draw( GtkWidget *widget, cairo_t *cr )
{
    cairo_save (cr);

    cairo_set_source_surface(cr, sf0, 0, 0);
    cairo_paint(cr);
    cairo_set_source_surface(cr, sf1, 0, 0);
    cairo_paint(cr);
    cairo_set_source_surface(cr, sf2, 0, 0);
    cairo_paint(cr);

    cairo_restore (cr);

}

G_MODULE_EXPORT gboolean on_wattmetergraph_expose_event (GtkWidget
*widget, GdkEventExpose *event)
{
    cairo_t *cr;

    cr = gdk_cairo_create (widget->window);

    cairo_rectangle (cr, event->area.x,     event->area.y,
                         event->area.width, event->area.height);
    cairo_clip (cr);

    draw (widget, cr);

    cairo_destroy (cr);

    return FALSE;
}


This is my aproach to make layers and i think that it shows a double
buffer aproach too, but layer2 is still a little slow.
layer2 should draw an square following mouse cursor, but the square
moves always slower than the cursor, so it may be a much better way.

I hope it helps.

Diego



2009/3/15 cu <cairouser at yahoo.com>:
> Depending on a system, another approach is to always draw into image
> surface and then move image data to whatever screen API you may have.
> That usually does involve at least one "direct copy" function (from
> cairo image surface to whatever bitmap format is native to the system).
>
> However, our application achieves somewhat high frame rates doing just
> that (tested with the same cairo image repeatedly copied, frame rate
> including drawing depends of course on complexity of drawing).
>
> The easiest way to copy is to get access to raw surface image data and
> copy directly into bitmap memory, if your system so permits (as an
> example, you can do that with native Windows API or wxWidgets).
>
> YMMV.
> --M
>
>
> Carl Worth wrote:
>> On Fri, 2009-03-13 at 17:33 +0100, David Björkevik wrote:
>>
>>> Not an example, but an outline and some pointers:
>>> 1. Create a cairo image surface using cairo_image_surface_create
>>> 2. Create a cairo context using cairo_create(surface)
>>> 3. Do drawing to your new context
>>> 4. Destroy the context
>>> 5. Using your original (screen) context, use
>>> cairo_set_source_surface(context,surface,0,0)
>>> 6. Use cairo_paint(contxt) to transfer the thing
>>> 7. cairo_surface_destroy(surface)
>>>
>>
>> That's a good outline, but one improvement would be to create a similar
>> surface rather than an image surface.
>>
>>
>>> For newer cairo you can also use cairo_push_group and
>>> cairo_pop_group_to_source.
>>>
>>
>> And yes, this does make it much easier to follow your recipe, (and does
>> create a similar surface rather than always creating an image surface).
>>
>> -Carl
>>
>>
>
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo


More information about the cairo mailing list