[cairo] The past, present and future of RGB16_565

Soeren Sandmann sandmann at daimi.au.dk
Tue Jun 16 05:13:29 PDT 2009


Chris Wilson <chris at chris-wilson.co.uk> writes:

> But here we are still exposing a private API, and expecting our users to
> bind a small part of pixman.

Yes, for now, pixman is still an implementation detail of X and
cairo. At some point I think it makes sense to open it up for general
consumption, but we'll likely need an ABI bump before that can
happen. Even then, I don't know that it makes sense to explicitly
expose pixman ABI through cairo.

> The idea I had last night was to introduce cairo_format_options_t, and
> not introduce any new image creation routines. The usage I have in mind
> would look something like:
> 
> format = cairo_format_options_create ();
> cairo_format_options_set_red_mask (format, 0xff, 16);
> cairo_format_options_set_green_mask (format, 0xff, 8);
> cairo_format_options_set_blue_mask (format, 0xff, 0);
> cairo_format_options_set_bits_per_pixel (format, 24);
> cairo_image_surface_create (cairo_format_options_get_id (format),
>                             width, height);
> cairo_format_options_destroy (format);
> 
> By making it an opaque type we can safe-guard against future
> requirements for HDR pixel-formats, or extension to un-premultiplied
> sources etc.

It feels a little clumsy to me that so many separate function calls
would be required just to use a particular format. Also for many new
format types, some of these calls will not really make sense. For
example, how do you specify a format where the channels are single
precision floating point? How do you specify a YUV format or a L*a*b
one, where red/green/blue masks don't make sense?

Would it be possible to just have function calls like this instead:

        cairo_format_t cairo_format_create_argb (
                24, 0x0, 0x0, 0xff, 16, 0xff, 8, 0xff, 0);

Though that is a pretty incomprehensible list of numbers.

Another possibility is to use something similar to the format macros
that pixman inherited from Render. They have actually worked out very
well. It would look like something like this:

    enum {

    CAIRO_FORMAT_ARGB_8888 = CAIRO_MAKE_FORMAT_ARGB (32, 8, 8, 8, 8),
    CAIRO_FORMAT_RGB_565 = CAIRO_MAKE_FORMAT_ARGB (16, 0, 5, 6, 5),
    CAIRO_FORMAT_BGRA_8888 = CAIRO_MAKE_FORMAT_BGRA (32, 8, 8, 8, 8),
    CAIRO_FORMAT_FLOAT_ARGB_32323232 = 
                 = CAIRO_MAKE_FORMAT_FLOAT_ARGB (128, 32, 32, 32, 32),
    ...;

    }

and you have a unique identifier automatically. The existing format
types are all small integers, so they wouldn't clash.

The advantages of this scheme:

        - There is an explicit list of supported formats
        - The formats are easy to convert to strings
        - Formats have ids that are unique across runs.
        - There are no hashtables or memory allocation required
          internally
        - Conversion to pixman formats is very simple.
        - Conversion from X image formats is as simple as conversion
          to pixman formats.

On the other hand this would mean that part of cairo's API would be
specified with macros, so the ability to build formats dynamically
would be more difficult to bind, but this is a fairly specialized
usecase anyway. Normally people know statically what format their data
is in.

> Internally, I expect to currently just wrap _pixman_format_from_masks(),
> throwing the usual errors for anything that isn't a suitable pixman
> destination (though it won't be that difficult to make a read-only image
> surface to hold pixman sources).

The distinction between source and destination pixman formats was
probably a mistake, and if we bump the ABI of pixman at some point,
we'll want to fix it.

So don't base anything around that distinction. Just pretend all
pixman formats that can be used as sources can also be used as
destinations. This will be true for all new formats, and is only false
for YUV formats at the moment. [1]


Soren


[1] The only real reason that YUV images cannot currently be written
to is that the yv12 format has 2x2 chroma subsampling, which means
that to generate one yv12 pixel you need a 2x2 tile of four RGB
pixels. However, pixman is currently storing one scanline at a time,
so we only have two of the four required pixels. Moving to a tile
based system, which is desirable for other reasons as well, would
allow this to work if we are careful to align the tiles right.


More information about the cairo mailing list