[cairo] Using pre-existing textures

Matt Hoosier matt.hoosier at gmail.com
Fri Feb 8 06:35:20 PST 2008


Thanks, Robert and Carl. I've pieced together a version of what I had
in mind by using raw Xlib and XRender calls, but doing it with Cairo
would certainly be much less error-prone and more general. A couple
small followups to your replies follow.

> On Fri, 08 Feb 2008 07:04:51 +1100, Robert Norris wrote:
> > Is there a way to use existing image data as a texture/pattern? I'd
> > like to exploit Cairo's nice XRender backend to do accelerated blits
> > of those from a Gtk program.

Well, yes and no. There are plenty of ways to get Gtk to display raw
image data, but all which support alpha blending require re-uploading
the image data to X every time you expose.

On Feb 7, 2008 5:09 PM, Carl Worth <cworth at cworth.org> wrote:
> >
> > You want cairo_image_surface_create_for_data().
>
> Yes, but there's also more to it than that.
>
> If you want a Render-accelerated blit, then you'll need to get data to
> an xlib surface and the Render blit will be painting from one cairo
> xlib surface to another.

Right, the part which wasn't clear was how to get the data resident on
an underlying X drawable/picture so that it wasn't transported again
every time that I paint the cairo_t.

>
> And just like with any other backend, the best way to create that
> intermediate surface is with cairo_surface_create_similar, (that is,
> if you've got one cairo xlib surface 'surface' then
> 'cairo_surface_create_similar (surface, ...);' will create another one
> for you.
>
> So then you've got a cairo xlib surface that will work efficiently as
> a source, but you have your existing image data that you want to
> upload to it. This is where cairo_image_surface_create_for_data comes
> in. So an entire sequence might be:
>
> /* Create an intermediate surface with data from "image"
>  * and of an appropriate type to work efficiently with "other"
>  */
> cairo_surface_t *
> create_intermediate_surface (cairo_surface_t *other,
>                              unsigned char *data,
>                              cairo_format_t format,
>                              int width, int height,
>                              int stride)


A small point about which I've never been sure: the normal idiom that
one seems in example Gtk code which draws using Cairo, is

gboolean
expose_event (GtkWidget *w, GdkEventExpose *event)
  {
    cairo_t *cr = gdk_cairo_create (...);

    /* draw */

    cairo_destroy (cr);
    ...
  }

But that would require you to toss away any X backend state
accumulated at the end of the expose handler. Is it legal to keep a
cairo surface like the intermediate one returned by your function
above, alive beyond the immediate expose cycle? E.g., is it referring
to the double-buffered short-lived X pixmaps that back the GdkDrawable
during expose cycles?

It would be extremely nice to just hold this surface and do a simple
fills from it in successive expose handlers.

Thanks


More information about the cairo mailing list