[sugar] Cairo tile engine, and accessing 565 buffers from cairo and C

Dan Williams dcbw at redhat.com
Tue Apr 17 09:53:32 EDT 2007


On Mon, 2007-04-16 at 21:25 -0700, Carl Worth wrote:
> On Mon, 16 Apr 2007 16:59:18 -0700, Don Hopkins wrote:
> > I want to draw RGB tiles (alpha is not necessary) on the screen as fast
> > as possible, double buffering them in 16 bit X images,
> 
> OK, so it sounds like all you need to use are 16-bit cairo xlib
> surfaces, (created with cairo_surface_create_similar with
> CAIRO_CONTENT_COLOR from an existing xlib surface).

Right.  Make sure the whole critical path is 16-bit 565.

> >                                      Is that a valid assumption, or is
> > there a fast path for drawing a surface clipped through a rectangle?
> 
> Drawing a single rectangle, (if pixel aligned---that is, just using
> integer coordinates and an identity transformation), has lots of
> fast-path treatment in cairo, so please take advantage of it. You can
> do that with either:
> 
> 	cairo_rectangle
> 	cairo_clip
> 
> to setup the clipping and then cairo_paint to do the painting, or
> just:
> 
> 	cairo_rectangle
> 	cairo_fill
> 
> to draw the part you want. Either way you should be hitting the same
> path in cairo to ask the X server to do very efficient things.
> 
> > Currently the tile surfaces are 24 bit RGB surfaces, that I create by
> > calling create_similar on the 24 bit RGB tile set I read in from a png
> > file.
> 
> OK, so that's giving you image surfaces, and that's causing the slow
> conversion when drawing to X. So the best would be to do that just
> once, (get your data uploaded into an xlib surface, and then draw from
> there).

Correct; about the only thing you can do here is use create_similar() on
the xlib _window_ surface, draw your 24bpp image surface to that, and
cache the 565 xlib surface for all further drawing.  Note that you will
_not_ get alpha because the surface is 565.

> > xHow do I create an cairo xlib surface from Python? Is there a supported
> > way to call cairo_xlib_surface_create from Python?
> 
> Every cairo function should be callable from python, but I don't know
> if there are python bindings for the xlib stuff you need, (like
> XCreatePixmap to create the pixmap to pass to
> cairo_xlib_surface_create). Fortunately, though you can just use the
> GTK+ bindings.

I looked at this last night.  The current python bindings don't have
support for creating arbitrary Xlib surfaces.  I don't believe you can
call the equivalent of cairo_xlib_surface_create().  The only functions
that are bound for Xlib surfaces are get_depth(), get_height(), and
get_width().  So before we can actually create arbitrary Xlib surfaces
in whatever Xlib visual we want, we'd have to fix up the pycairo
bindings to support that.

I'm not even sure how to start passing in Xlib Display or Visual
structures given that there isn't any Xlib python binding to my
knowledge.  Perhaps PyGTK would have some ideas on how to do this in
it's X11 backend, but I think it only deals with xids and wraps most of
Xlib.

> > Is there an easy way to get ahold of the cairo surface from a cairo
> > context, or from a gdk drawable, from Python?
> 
> For a cairo context you can call cairo_get_target, (probably
> context.get_target in python), to get the surface it's targeting. So
> that should give you the surface you need from which you can call
> create_similar. And for the case of a gdk drawable you can call
> gdk_cairo_create, and then cairo_get_target. (I do think it's a little
> annoying that GTK+ doesn't have a direct way to create a cairo surface
> from a GDK drawable, but the gdk_cairo_create;cairo_get_target
> approach works fine---even if its not quite obvious).

It's pretty easy given a GTK widget.  Embed a GtkDrawingArea subclass in
your window, and then override the 'expose' method of the drawing area
widget.

http://www.pygtk.org/articles/cairo-pygtk-widgets/cairo-pygtk-widgets.htm

Again, ensure that _any_ surfaces you use in your critical paths are
565.  If anything is not 565, you'll be subject to Xlib having to smash
an 888 pixmap down to 565, and that's not very fast, even with MMX.

Also, pycairo may need to be fixed before you can create arbitrary Xlib
surfaces of your desired depth, without using create_similar.  But in
your case, you can probably just use create_similar since you don't need
anything except 565.

Dan

> Anyway, I hope that all works out well for you. And I'm looking
> forward to hearing what kinds of performance improvements you get from
> using cairo xlib surfaces of the desired depth.
> 
> -Carl




More information about the Devel mailing list