[Pixman] [PATCH 7/7] utils.c: Increase acceptable deviation to 0.0064 in pixel_checker_t

Siarhei Siamashka siarhei.siamashka at gmail.com
Wed Jan 30 04:09:08 PST 2013


On Thu, 24 Jan 2013 10:52:59 -0500
Søren Sandmann <sandmann at cs.au.dk> wrote:

> From: Søren Sandmann Pedersen <ssp at redhat.com>
> 
> The check-formats programs reveals that the 8 bit pipeline cannot meet
> the current 0.004 acceptable deviation specified in utils.c, so we
> have to increase it. Some of the failing pixels were captured in
> pixel-test, which with this commit now passes.
> 
> == a4r4g4b4 DISJOINT_XOR a8r8g8b8 ==
> 
> The DISJOINT_XOR operator applied to an a4r4g4b4 source pixel of
> 0xd0c0 and a destination pixel of 0x5300ea00 results in the exact
> value:
> 
>     fa = (1 - da) / sa = (1 - 0x53 / 255.0) / (0xd / 15.0) = 0.7782
>     fb = (1 - sa) / da = (1 - 0xd / 15.0) / (0x53 / 255.0) = 0.4096
> 
>     r = fa * (0xc / 15.0) + fb * (0xea / 255.0) = 0.99853
> 
> But when computing in 8 bits, we get:
> 
>     fa8 = ((255 - 0x53) * 255 + 0xdd / 2) / 0xdd = 0xc6
>     fb8 = ((255 - 0xdd) * 255 + 0x53 / 3) / 0x53 = 0x68
> 
>     r8 = (fa8 * 0xcc + 127) / 255 + (fb8 * 0xea + 127) / 255 = 0xfd
> 
> and
> 
>     0xfd / 255.0 = 0.9921568627450981
> 
> for a deviation of 0.00637118610187, which we then have to consider
> acceptable given the current implementation.
> 
> By switching to computing the result with
> 
>    r = (fa * s + fb * d + 127) / 255
> 
> rather than
> 
>    r = (fa * s + 127) / 255 + (fb * d + 127) / 255
>
> the deviation would be only 0.00244961747442, so at some point it may
> be worth doing either this, or switching to floating point for
> operators that involve divisions.

This reminds me of

    http://cgit.freedesktop.org/pixman/commit/?id=a075a870fd7e1fa7

Both performance and accuracy were sacrificed to get bitexact results
when compared to generic C implementation.

> Note that the conversion from 4 bits to 8 bits does not cause any
> error in this case because both rounding and bit replication produces
> an exact result when the number of from-bits divide the number of
> to-bits.
> 
> == a8r8g8b8 OVER r5g6b5 ==
> 
> When OVER compositing the a8r8g8b8 pixel 0x0f00c300 with the x14r5g6b5

Did you actually mean x14r6g6b6?

> pixel 0x03c0, the true floating point value of the resulting green
> channel is:
> 
>    0xc3 / 255.0 + (1.0 - 0x0f / 255.0) * (0x0f / 63.0) = 0.9887955
> 
> but when compositing 8 bit values, where the 6-bit green channel is
> converted to 8 bit through bit replication, the 8-bit result is:
> 
>    0xc3 + ((255 - 0x0f) * 0x3c + 127) / 255 = 251
> 
> which corresponds to a real value of 0.984314. The difference from the
> true value is 0.004482 which is bigger than the acceptable deviation
> of 0.004. So, if we were to compute all the CONJOINT/DISJOINT
> operators in floating point, or otherwise make them more accurate, the
> acceptable deviation could be set at 0.0045.
> 
> If we were doing the 6-bit conversion with rounding:
> 
>    (x / 63.0 * 255.0 + 0.5)
> 
> instead of bit replication, the deviation in this particular case
> would be only 0.0005, so we may want to consider this at some
> point.

This has been also discussed here:

    http://comments.gmane.org/gmane.comp.graphics.pixman/1891

Though the bit replication when converting to 8-bit is not so bad.
Dropping lower bits when converting back introduces a bigger error.

Anyway, if I remember correctly, the accuracy loss has been well known
since the time when bitexact testing was introduced. Other than using
less accurate but faster conversion approximations, currently there
is also an assumption that separate "fetch -> combine -> store" steps
must provide exactly the same results as the fast path functions doing
the same operations in one go. This restriction surely inhibits
performance and accuracy. Certain platforms (ARM11 and MIPS32) should
be able to improve performance a bit if we go away from bitexact
correctness testing and allow more freedom in implementations. So this
patchset indeed looks rather useful.

However I think that we may need to come to an agreement on the primary
purpose of the 8-bit pipeline, especially now that we also have a
floating point pipeline. In my opinion, the 8-bit integer pipeline
should always favour performance over accuracy in the case of doubt.
Moreover, anyone using r5g6b5 format is most likely either memory or
performance constrained, so they would not particularly appreciate the
more accurate, but slower conversion between a8r8g8b8 and r5g6b5.
There are also other libraries and alternative solutions out there. The
competition between different mobile browsers and UI toolkits for the
embedded systems seems to be heavily focused on performance. Every
little bit is relevant. And while we are talking about this, bilinear
interpolation precision is also somewhat related here (the choice
of 7-bit vs. 4-bit) and whether we can avoid doing correct rounding
for it or not.

On the other hand, the floating point pipeline is a good place to
implement sRGB, accurate format conversions and the other nice things.
In other words, it can favour accuracy over performance.

-- 
Best regards,
Siarhei Siamashka


More information about the Pixman mailing list