[cairo] potential bug in cairo relative to intel drivers

Carl Worth cworth at cworth.org
Thu Jul 30 10:38:07 PDT 2009


On Wed, 2009-07-29 at 14:35 -0400, Mike Gualtieri wrote:
> I have also noticed that this issue disappears when I add the
> following in the drivers section of my xorg.conf:
> 
> Option     "NoAccel"     "true"
> 
> This leads me to believe it has something to do with dri or some other
> 3D acceleration extension.

Hi Mike!

You're correct that it's quite telling that changing NoAccel changes the
behavior. That definitely indicates that there's a bug either in the
driver acceleration code *or* in the software implementation in the X
server. Because, clearly they should be the same.

> In my application, I have a variety of custom gtk/cairo objects to
> draw components on the screen.  Most of these objects also have a
> background image, placed into a cairo surface, that I scale to fit the
> widget size.  If I leave the background image on a 1:1 scale
> everything looks appropriate.  If I scale the image either smaller or
> larger, the edges of the image look like they are alpha blended with
> the widget background color.

I understand that the blending on the edges you are getting is
undesired, but it sounds to me that you are getting the correct
behavior.

The first thing to understand is that when you set the source surface,
cairo implicitly creates a source pattern for you. Also, in cairo, all
patterns are infinite, and there are various options for determining how
to interpret the pixels of the pattern that are "outside" your surface,
(we call these options extend modes).

What's happening here is that the default extend mode for your source
pattern is CAIRO_EXTEND_NONE. This mode works by assuming that all
pixels outside the surface are transparent. So when you scale up, (as
opposed to just painting with a 1:1 transform), some of those
transparent pixels get sampled and you get the blending.

> Essentially my code looks like this (this is stripped out of a few
> function calls):
> 
> cairo_surface_t *bg_image_surface;
> bg_image_surface = cairo_image_surface_create_from_png (bg_img);
> 
> cairo_t *cr;
> cr = gdk_cairo_create (widget->window);
> 
> cairo_scale (cr, bg_scale_width,  bg_scale_height);
> cairo_set_source_surface (cr, widget->bg_image_surface, 0, 0);
> cairo_paint (cr);

To fix this you'll want to set CAIRO_EXTEND_PAD on the pattern. You can
do this right after cairo_set_source_surface like this:

cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);

If you make only that change you should see very clearly how
CAIRO_EXTEND_PAD works. It interprets all pixels outside the surface as
the same color as the nearest pixel in the surface. But you'll also see
that the source pattern is indeed infinite, and that that's not what you
want here.

So you'll also want to replace cairo_paint (cr) with something like:

	cairo_rectangle (cr, x, y, width, height);
	cairo_fill (cr);

I hope that helps!

Have fun with cairo,

-Carl

PS. We should still figure out who's doing the wrong thing with the
change that comes from toggling NoAccel.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://lists.cairographics.org/archives/cairo/attachments/20090730/5eb909d1/attachment-0001.pgp 


More information about the cairo mailing list