On Wed, 15 Apr 2015 10:39:54 +0100,
Pekka Paalanen <ppaala...@gmail.com> wrote:

On Tue, 14 Apr 2015 19:00:58 +0100
"Ben Avison" <bavi...@riscosopen.org> wrote:

Assume the reasonable case that you want to plot the whole of
an image of size x,y at a size m,n. You need to set the diagonals of
the transform to

floor(pixman_fixed_1*(x-1)/(m-1))
floor(pixman_fixed_1*(y-1)/(n-1))
1

and then solve for

    / 0.5 \   / 0.5 \
T . | 0.5 | = | 0.5 |
    \ 1   /   \ 1   /

to find the translation coefficients that will ensure the top-left
source pixel aligns exactly to the top-left destination pixel.

Urgh, I don't think we account for *that* in e.g. Weston's Pixman
renderer. I could bet Weston follows the GL convention of defining the
extents of an image region to be the boundaries of the image, not the
pixel centers which would leave a half pixel margin outside of the
region. I mean, Weston works as if you are transforming geometric
primitives like triangles, and rasterization happens later, while it
still uses pixel centers at .5 coordinates, meaning that a single pixel
covers the X-coordinates [0.0, 1.0).

Are you saying that this idea doesn't work with Pixman?

I had a recollection of Pixman's geometric model, but given that there's
no documentation I felt the need to go back and check the source code, as
it can be very easy to get this sort of thing subtly wrong:

Pixman's scaling is such that pixel centres are similarly positioned
irrespective of whether you're doing nearest-neighbour or bilinear
scaling.

For nearest-neighbour scaling, the nth pixel of a source or mask image is
considered to cover the space (n, n+1]. Yes, that's inclusive at the
upper end and exclusive at the lower end, not what you might expect (and
this is the reason for adjustments by pixman_fixed_e in various places).

For bilinear scaling, the contribution of the nth pixel scales up
linearly from 0 at n-0.5 to 1 at n+0.5 then back down to 0 at n+1.5, so
its overall range of influence is (n-0.5, n+1.5).

Since the centre coordinate of each destination pixel is what is fed
through the transformation matrix, you can see that under the identity
transform, there is always a 1:1 mapping from a single source pixel to a
single destination pixel, irrespective of whether you're nominally doing
nearest or bilinear scaling. This enables Pixman to select unscaled fast
paths just by examining the transform.

If you scale from the outer extents (in other words, use scale factors of
x/m, y/n rather than (x-1)/(m-1), (y-1)/(n-1), and align the top-left of
the first source pixel with the top-left of the first destination pixel)
then that's fine, as long as:

a) you're using nearest-neighbour scaling
or
b) you're using bilinear scaling and a scale factor > 1 (i.e. reduction
   rather than enlargement)

otherwise Pixman will decide that it needs to use a small contribution
from a single-pixel border just outside the bounds of the source image,
for which it then needs to start following the repeat-type rules (pad/
tile/reflect/none).

Hmm, sure, Pixman needs to transform pixel centers internally, since it
rasterizes on the destination image... so what
compute_transformed_extents() does is that it assumes the input is
geometry, converts corner pixels into pixel centers for rasterization,
and returns the bounding box of the transformed pixel centers.
Then that is used to calculate what pixels would be accessed in the
source image.

Did I get that right?

Yes. Its only purpose is to determine the (inclusive) first and last
source pixels required, so that the caller can then check to see if they
are within bounds.

Btw. are you sure there cannot be rounding in the hand-written fast
paths? If some assembly path computes an approximation of source
coordinates, could it not hit the "wrong" pixel? Zero coefficient or
not.

I'm pretty sure, yes - at least for affine transforms. The transform
coefficients, inputs and outputs are all x.16 fixed point, with a rule
for handling rounding for the multiplications (round to nearest with
halfs rounding to +infinity) that's enforced in platform-neutral code
like pixman_transform_point_31_16(). As a fast path steps along a
destination row, there are no further multiplications, it just adds the
transform coefficients from the first column to the running total, and no
rounding is therefore needed.

If any fast path deviated from this, it would fail the test suite, which
requires binary-identical output. Actually, I wonder if this rounding
issue is the reason why projective transforms aren't more widely featured
in the tests?

Ben
_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to