[Pixman] [RFC] dithering 16 bit gradients

Søren Sandmann sandmann at cs.au.dk
Thu Jul 12 04:59:10 PDT 2012


> Here's a work in progress that adds dithering for 16 bit
> gradients. This does a 2x2 ordered dither in the same way that Skia
> does. Skia and Coregraphics also do dithering of 32bit gradients which
> I expect would also be useful for pixman in the future too.

> This patch adds a partial implementation of a 16 bit pipeline in
> addition to the existing wide and narrow ones. This probably isn't
> strictly necessary, but is important for decent performance. The 16
> bit pipeline is only used in the specific cases where it is supported,
> everything else is left unimplemented.
> One of the things I'm currently unhappy with is that it duplicates the
> gradient walker code for 16 bits. We could turn it into a large macro
> that does the appropriate things for 16 bit and 32 bit versions, but
> that's not particularly appealing.
> Does anyone have any other thoughts on this?

Dithering is clearly needed for gradients on 16 bit destinations, and
also a noticable improvement for 32 bit destinations, so thanks for
looking into this. Some thoughts on the subject:

- Dithering before or after compositing?

Conceptually, it seems to me that it makes more sense to composite first
and then dither the result just before writing back to the destination,
because this is the point where quantization to 565 takes place. This
also would give us dithering of regular sampled images for free.

Implementing this would be straightforward in principle: just add a
dither signal to the buffer in dest_write_back_narrow/wide(), although
there would be some additional work to ensure that the various fast path
blitters are not taken when dithering is enabled.

Regarding performance, note that there is no requirement that gradients
have to composited by the general implementation. There is nothing that
prevents fast paths from being written that composited and dithered
gradients. Such fast paths could make use of the gradient iterators, or
they could reimplement the gradients themselves.

- Roundtripping

There are some potential issues with roundtripping. For example if you
composite x8r8g8b8 to a4r4g4b4, the resulting alpha channel should
really be solid 0xf and not, say, alternate between 0xe and 0xf. Also,
it would be desirable to have SRC 565 to 565 be just a blit even with
dithering enabled. 

This may just be a question of doing the dithering carefully though.

- 16 bit pipe

If we dither after compositing, that may make the question of a 16 bit
pipe irrelevant for gradient dithering since the output of compositing
would clearly have to be 32+ bits for dithering to make sense.

But as a tangent, allowing iterators to generate other formats than
a8r8g8b8 is not a bad idea. It's especially tempting if it would make
noop 565 iterators possible so that 565 images could be composited by
having a 565_565 combiner read directly from the images. I'm not wild
about the special-casing that this patch adds in pixman-general.c,
though. A trend over the last many releases has been to get rid of
special cases or to at least cleanly separate them from general-purpose

So while it might be worthwhile generalizing the general code so that it
can deal with more intermediate pixel formats than just a8r8g8b8, doing
it properly would likely involve turning the look-up of iterators and
combiners into something similar to the current fast path lookup (and
caching the resulting combinations).

- Scrolling

Suppose you scroll a pixmap one pixel up and then render the exposed
area. If the dither matrix is positioned at the same place as before
scrolling, vertical stripes will be produced. GTK+ solved this by having
a user-settable "dither offset" that would be added to the destination
position before accessing the dither matrix.

- Dither matrix quality

It's possible to do a lot better than a 2x2 Bayer matrix, although for a
first implementation I guess it's better than nothing.


More information about the Pixman mailing list