Re: [Pixman] [PATCH v14 16/22] pixman-filter: distribute normalization error over filter
> Also, I would write the code like this: > > pixman_fixed_t error = pixman_fixed_1 - new_total; > for (x = 0; x < width; ++x) > { > pixman_fixed_t d = error * (x + 1) / width; > p[x] += d; > error -= d; > } > > to get rid of the temporary and to make it more obvious that there is an > error that is being distributed. > I meant ... pixman_fixed_t d = error / (width - x); ... of course, but I guess the rounding-towards-zero behavior of division in C makes this less desirable since it tends to put all the rounding error towards one side of the kernel. Rounding-to-nearest would make it similar to your code: ... pixman_fixed_t d = DIV(error + (width - x - 1) / 2, width - x) ... but then it would be slightly cleaner to make the loop count down: for (x = width; x > 0; --x) { pixman_fixed_t d = DIV(error + (x - 1) / 2, x) p[x] += d; error -= d; } Søren ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH v14 03/22] demos/scale: Only generate filters when used for separable
> This makes the speed of the demo more accurate, as the filter generation > is a visible fraction of the time it takes to do a transform. This also > prevents the output of unused filters in the gnuplot option in the next > patch. > > Note this is not dependent on other patches, as use can choose linear > and bilinear in the existing version. > It really does depend on patch 2. You are referencing "filter_combo_box", which is widget introduced in patch 2. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCHv2 3/3] More general BILINEAR=>NEAREST reduction
Generalize and simplify the code that reduces BILINEAR to NEAREST so that all the reduction happens for all affine transformations where t00..t12 are integers and (t00 + t01) and (t10 + t11) are both odd. This is a sufficient condition for the resulting transformed coordinates to be exactly at the center of a pixel so that BILINEAR becomes identical to NEAREST. V2: Address some comments by Bill Spitzak Signed-off-by: Søren Sandmann--- pixman/pixman-image.c | 66 +-- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 1ff1a49..681864e 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -335,37 +335,47 @@ compute_image_info (pixman_image_t *image) { flags |= FAST_PATH_NEAREST_FILTER; } - else if ( - /* affine and integer translation components in matrix ... */ - ((flags & FAST_PATH_AFFINE_TRANSFORM) && -!pixman_fixed_frac (image->common.transform->matrix[0][2] | -image->common.transform->matrix[1][2])) && - ( - /* ... combined with a simple rotation */ - (flags & (FAST_PATH_ROTATE_90_TRANSFORM | - FAST_PATH_ROTATE_180_TRANSFORM | - FAST_PATH_ROTATE_270_TRANSFORM)) || - /* ... or combined with a simple non-rotated translation */ - (image->common.transform->matrix[0][0] == pixman_fixed_1 && -image->common.transform->matrix[1][1] == pixman_fixed_1 && -image->common.transform->matrix[0][1] == 0 && -image->common.transform->matrix[1][0] == 0) - ) - ) + else if (flags & FAST_PATH_AFFINE_TRANSFORM) { - /* FIXME: there are some affine-test failures, showing that -* handling of BILINEAR and NEAREST filter is not quite -* equivalent when getting close to 32K for the translation -* components of the matrix. That's likely some bug, but for -* now just skip BILINEAR->NEAREST optimization in this case. + /* Suppose the transform is +* +*[ t00, t01, t02 ] +*[ t10, t11, t12 ] +*[ 0, 0, 1 ] +* +* and the destination coordinates are (n + 0.5, m + 0.5). Then +* the transformed x coordinate is: +* +* tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02 +*= t00 * n + t01 * m + t02 + (t00 + t01) * 0.5 +* +* which implies that if t00, t01 and t02 are all integers +* and (t00 + t01) is odd, then tx will be an integer plus 0.5, +* which means a BILINEAR filter will reduce to NEAREST. The same +* applies in the y direction */ - pixman_fixed_t magic_limit = pixman_int_to_fixed (3); - if (image->common.transform->matrix[0][2] <= magic_limit && - image->common.transform->matrix[1][2] <= magic_limit && - image->common.transform->matrix[0][2] >= -magic_limit && - image->common.transform->matrix[1][2] >= -magic_limit) + pixman_fixed_t (*t)[3] = image->common.transform->matrix; + + if ((pixman_fixed_frac ( +t[0][0] | t[0][1] | t[0][2] | +t[1][0] | t[1][1] | t[1][2]) == 0) && + (pixman_fixed_to_int ( + (t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1) { - flags |= FAST_PATH_NEAREST_FILTER; + /* FIXME: there are some affine-test failures, showing that +* handling of BILINEAR and NEAREST filter is not quite +* equivalent when getting close to 32K for the translation +* components of the matrix. That's likely some bug, but for +* now just skip BILINEAR->NEAREST optimization in this case. +*/ + pixman_fixed_t magic_limit = pixman_int_to_fixed (3); + if (image->common.transform->matrix[0][2] <= magic_limit && + image->common.transform->matrix[1][2] <= magic_limit && + image->common.transform->matrix[0][2] >= -magic_limit && + image->common.transform->matrix[1][2] >= -magic_limit) + { + flags |= FAST_PATH_NEAREST_FILTER; + } } } break; -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH v14 04/22] demos/scale: fix blank subsamples spin box
Reviewed-by: Soren SandmannOn Sun, Mar 6, 2016 at 8:06 PM, wrote: > From: Bill Spitzak > > It now shows the initial value of 4 when the demo is started > > Signed-off-by: Bill Spitzak > --- > demos/scale.ui | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/demos/scale.ui b/demos/scale.ui > index b62cbfb..6028ab7 100644 > --- a/demos/scale.ui > +++ b/demos/scale.ui > @@ -321,6 +321,7 @@ > id="subsample_spin_button"> > True > name="adjustment">subsample_adjustment > + 4 > > > 1 > -- > 1.9.1 > > ___ > Pixman mailing list > Pixman@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/pixman > ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCHv2 1/3] pixman-fast-path.c: Pick NEAREST affine fast paths before BILINEAR ones
When a BILINEAR filter is reduced to NEAREST, it is possible for both types of fast paths to run; in this case, the NEAREST ones should be preferred as that is the simpler filter. Signed-off-by: Soren Sandmann--- pixman/pixman-fast-path.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 53d4a1f..b4daa26 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -3258,9 +3258,9 @@ static const pixman_iter_info_t fast_iters[] = }, #define AFFINE_FAST_PATHS(name, format, repeat) \ -SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ +NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ BILINEAR_AFFINE_FAST_PATH(name, format, repeat)\ -NEAREST_AFFINE_FAST_PATH(name, format, repeat) +SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD) AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE) -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH v14 05/22] demos/scale: Default to locked axis
Reviewed-by: Soren SandmannOn Sun, Mar 6, 2016 at 8:06 PM, wrote: > From: Bill Spitzak > > Signed-off-by: Bill Spitzak > --- > demos/scale.ui | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/demos/scale.ui b/demos/scale.ui > index 6028ab7..7e999c1 100644 > --- a/demos/scale.ui > +++ b/demos/scale.ui > @@ -177,6 +177,7 @@ > id="lock_checkbutton"> > Lock X and Y > Dimensions > 0.0 > + True > > > False > -- > 1.9.1 > > ___ > Pixman mailing list > Pixman@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/pixman > ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCHv2 3/3] More general BILINEAR=>NEAREST reduction
Looks good to me On Wed, Mar 16, 2016 at 9:14 PM, Søren Sandmann Pedersen < soren.sandm...@gmail.com> wrote: > Generalize and simplify the code that reduces BILINEAR to NEAREST so > that all the reduction happens for all affine transformations where > t00..t12 are integers and (t00 + t01) and (t10 + t11) are both > odd. This is a sufficient condition for the resulting transformed > coordinates to be exactly at the center of a pixel so that BILINEAR > becomes identical to NEAREST. > > V2: Address some comments by Bill Spitzak > > Signed-off-by: Søren Sandmann> --- > pixman/pixman-image.c | 66 > +-- > 1 file changed, 38 insertions(+), 28 deletions(-) > > diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c > index 1ff1a49..681864e 100644 > --- a/pixman/pixman-image.c > +++ b/pixman/pixman-image.c > @@ -335,37 +335,47 @@ compute_image_info (pixman_image_t *image) > { > flags |= FAST_PATH_NEAREST_FILTER; > } > - else if ( > - /* affine and integer translation components in matrix ... */ > - ((flags & FAST_PATH_AFFINE_TRANSFORM) && > -!pixman_fixed_frac (image->common.transform->matrix[0][2] | > -image->common.transform->matrix[1][2])) && > - ( > - /* ... combined with a simple rotation */ > - (flags & (FAST_PATH_ROTATE_90_TRANSFORM | > - FAST_PATH_ROTATE_180_TRANSFORM | > - FAST_PATH_ROTATE_270_TRANSFORM)) || > - /* ... or combined with a simple non-rotated translation */ > - (image->common.transform->matrix[0][0] == pixman_fixed_1 && > -image->common.transform->matrix[1][1] == pixman_fixed_1 && > -image->common.transform->matrix[0][1] == 0 && > -image->common.transform->matrix[1][0] == 0) > - ) > - ) > + else if (flags & FAST_PATH_AFFINE_TRANSFORM) > { > - /* FIXME: there are some affine-test failures, showing that > -* handling of BILINEAR and NEAREST filter is not quite > -* equivalent when getting close to 32K for the translation > -* components of the matrix. That's likely some bug, but for > -* now just skip BILINEAR->NEAREST optimization in this case. > + /* Suppose the transform is > +* > +*[ t00, t01, t02 ] > +*[ t10, t11, t12 ] > +*[ 0, 0, 1 ] > +* > +* and the destination coordinates are (n + 0.5, m + 0.5). Then > +* the transformed x coordinate is: > +* > +* tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02 > +*= t00 * n + t01 * m + t02 + (t00 + t01) * 0.5 > +* > +* which implies that if t00, t01 and t02 are all integers > +* and (t00 + t01) is odd, then tx will be an integer plus 0.5, > +* which means a BILINEAR filter will reduce to NEAREST. The > same > +* applies in the y direction > */ > - pixman_fixed_t magic_limit = pixman_int_to_fixed (3); > - if (image->common.transform->matrix[0][2] <= magic_limit && > - image->common.transform->matrix[1][2] <= magic_limit && > - image->common.transform->matrix[0][2] >= -magic_limit && > - image->common.transform->matrix[1][2] >= -magic_limit) > + pixman_fixed_t (*t)[3] = image->common.transform->matrix; > + > + if ((pixman_fixed_frac ( > +t[0][0] | t[0][1] | t[0][2] | > +t[1][0] | t[1][1] | t[1][2]) == 0) && > + (pixman_fixed_to_int ( > + (t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1) > Very clever! This optimization looks correct. > { > - flags |= FAST_PATH_NEAREST_FILTER; > + /* FIXME: there are some affine-test failures, showing that > +* handling of BILINEAR and NEAREST filter is not quite > +* equivalent when getting close to 32K for the translation > +* components of the matrix. That's likely some bug, but > for > +* now just skip BILINEAR->NEAREST optimization in this > case. > +*/ > + pixman_fixed_t magic_limit = pixman_int_to_fixed (3); > + if (image->common.transform->matrix[0][2] <= magic_limit > && > + image->common.transform->matrix[1][2] <= magic_limit > && > + image->common.transform->matrix[0][2] >= -magic_limit > && > + image->common.transform->matrix[1][2] >= -magic_limit) > + { > + flags |= FAST_PATH_NEAREST_FILTER; > + } > } >
Re: [Pixman] [PATCH v14 08/22] pixman-filter: rename "scale" to "size" when it is 1/scale
On Thu, Mar 17, 2016 at 10:06 PM, Søren Sandmannwrote: > I suppose it's a little illogical that scale_x and scale_y really are the > reciprocal values of how much the source image should be scaled. I don't > remember exactly what I was thinking, but it might have something like > "this allows you to just pass t[0][0] and t[1][1] if you have a pure > scaling, which avoids a division". There is also kind of precedence in the > Pixman API since the transformation given as in the dst->source direction. > > I don't really like "size" either though. It's not really the size of the > filter that we are specifying; it just happens to be proportional to it. > > If it comes down to "size" and "scale", I prefer "scale". > I tried "width" but it is not actually the filter width. How about "dx" and "dy" since it is almost always the derivative of the x and y in the input (or du,dv or dtx dtx) > > > Søren > > > On Sun, Mar 6, 2016 at 8:06 PM, wrote: > >> From: Bill Spitzak >> >> This is to remove some confusion when reading the code. "scale" gets >> larger >> as the picture gets larger, while "size" (ie the size of the filter) gets >> smaller. >> >> v14: Removed changes to integral function >> >> Signed-off-by: Bill Spitzak >> Reviewed-by: Oded Gabbay >> --- >> pixman/pixman-filter.c | 18 +- >> pixman/pixman.h| 6 +++--- >> 2 files changed, 12 insertions(+), 12 deletions(-) >> >> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c >> index a29116a..c03a7f6 100644 >> --- a/pixman/pixman-filter.c >> +++ b/pixman/pixman-filter.c >> @@ -221,7 +221,7 @@ static void >> create_1d_filter (int width, >> pixman_kernel_t reconstruct, >> pixman_kernel_t sample, >> - double scale, >> + double size, >> int n_phases, >> pixman_fixed_t *p) >> { >> @@ -251,8 +251,8 @@ create_1d_filter (int width, >> double pos = x + 0.5 - frac; >> double rlow = - filters[reconstruct].width / 2.0; >> double rhigh = rlow + filters[reconstruct].width; >> - double slow = pos - scale * filters[sample].width / 2.0; >> - double shigh = slow + scale * filters[sample].width; >> + double slow = pos - size * filters[sample].width / 2.0; >> + double shigh = slow + size * filters[sample].width; >> double c = 0.0; >> double ilow, ihigh; >> >> @@ -262,7 +262,7 @@ create_1d_filter (int width, >> ihigh = MIN (shigh, rhigh); >> >> c = integral (reconstruct, ilow, >> - sample, 1.0 / scale, ilow - pos, >> + sample, 1.0 / size, ilow - pos, >> ihigh - ilow); >> } >> >> @@ -335,12 +335,12 @@ filter_width (pixman_kernel_t reconstruct, >> pixman_kernel_t sample, double size) >> } >> >> /* Create the parameter list for a SEPARABLE_CONVOLUTION filter >> - * with the given kernels and scale parameters >> + * with the given kernels and size parameters >> */ >> PIXMAN_EXPORT pixman_fixed_t * >> pixman_filter_create_separable_convolution (int *n_values, >> - pixman_fixed_t scale_x, >> - pixman_fixed_t scale_y, >> + pixman_fixed_t size_x, >> + pixman_fixed_t size_y, >> pixman_kernel_t >> reconstruct_x, >> pixman_kernel_t >> reconstruct_y, >> pixman_kernel_t sample_x, >> @@ -348,8 +348,8 @@ pixman_filter_create_separable_convolution (int >>*n_values, >> int >> subsample_bits_x, >> int >> subsample_bits_y) >> { >> -double sx = fabs (pixman_fixed_to_double (scale_x)); >> -double sy = fabs (pixman_fixed_to_double (scale_y)); >> +double sx = fabs (pixman_fixed_to_double (size_x)); >> +double sy = fabs (pixman_fixed_to_double (size_y)); >> pixman_fixed_t *params; >> int subsample_x, subsample_y; >> int width, height; >> diff --git a/pixman/pixman.h b/pixman/pixman.h >> index 509ba5e..b012a33 100644 >> --- a/pixman/pixman.h >> +++ b/pixman/pixman.h >> @@ -845,12 +845,12 @@ typedef enum >> } pixman_kernel_t; >> >> /* Create the parameter list for a SEPARABLE_CONVOLUTION filter >> - * with the given kernels and scale parameters. >> + * with the given kernels and size parameters. >> */ >> pixman_fixed_t * >> pixman_filter_create_separable_convolution (int *n_values, >> -
[Pixman] [PATCHv2 2/3] Add new test of filter reduction from BILINEAR to NEAREST
This new test tests a bunch of bilinear downscalings, where many have a transformation such that the BILINEAR filter can be reduced to NEAREST (and many don't). A CRC32 is computed for all the resulting images and compared to a known-good value for both 4-bit and 7-bit interpolation. V2: Remove leftover comment, some minor formatting fixes, use a timestamp as the PRNG seed. Signed-off-by: Søren Sandmann--- test/Makefile.sources| 1 + test/filter-reduction-test.c | 112 +++ 2 files changed, 113 insertions(+) create mode 100644 test/filter-reduction-test.c diff --git a/test/Makefile.sources b/test/Makefile.sources index 5d55e67..0a56231 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -21,6 +21,7 @@ TESTPROGRAMS = \ gradient-crash-test \ pixel-test\ matrix-test \ + filter-reduction-test \ composite-traps-test \ region-contains-test \ glyph-test\ diff --git a/test/filter-reduction-test.c b/test/filter-reduction-test.c new file mode 100644 index 000..705fa4b --- /dev/null +++ b/test/filter-reduction-test.c @@ -0,0 +1,112 @@ +#include +#include +#include "utils.h" + +static const pixman_fixed_t entries[] = +{ +pixman_double_to_fixed (-1.0), +pixman_double_to_fixed (-0.5), +pixman_double_to_fixed (-1/3.0), +pixman_double_to_fixed (0.0), +pixman_double_to_fixed (0.5), +pixman_double_to_fixed (1.0), +pixman_double_to_fixed (1.5), +pixman_double_to_fixed (2.0), +pixman_double_to_fixed (3.0), +}; + +#define SIZE 12 + +static uint32_t +test_scale (const pixman_transform_t *xform, uint32_t crc) +{ +uint32_t *srcbuf, *dstbuf; +pixman_image_t *src, *dest; + +srcbuf = malloc (SIZE * SIZE * 4); +prng_randmemset (srcbuf, SIZE * SIZE * 4, 0); +src = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, SIZE, SIZE, srcbuf, SIZE * 4); + +dstbuf = malloc (SIZE * SIZE * 4); +prng_randmemset (dstbuf, SIZE * SIZE * 4, 0); +dest = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, SIZE, SIZE, dstbuf, SIZE * 4); + +pixman_image_set_transform (src, xform); +pixman_image_set_repeat (src, PIXMAN_REPEAT_NORMAL); +pixman_image_set_filter (src, PIXMAN_FILTER_BILINEAR, NULL, 0); + +image_endian_swap (src); +image_endian_swap (dest); + +pixman_image_composite (PIXMAN_OP_SRC, + src, NULL, dest, + 0, 0, 0, 0, 0, 0, + SIZE, SIZE); + +crc = compute_crc32_for_image (crc, dest); + +pixman_image_unref (src); +pixman_image_unref (dest); + +free (srcbuf); +free (dstbuf); + +return crc; +} + +#if BILINEAR_INTERPOLATION_BITS == 7 +#define CHECKSUM 0x02169677 +#elif BILINEAR_INTERPOLATION_BITS == 4 +#define CHECKSUM 0xE44B29AC +#else +#define CHECKSUM 0x +#endif + +int +main (int argc, const char *argv[]) +{ +const pixman_fixed_t *end = entries + ARRAY_LENGTH (entries); +const pixman_fixed_t *t0, *t1, *t2, *t3, *t4, *t5; +uint32_t crc = 0; + +prng_srand (0x56EA1DBD); + +for (t0 = entries; t0 < end; ++t0) +{ + for (t1 = entries; t1 < end; ++t1) + { + for (t2 = entries; t2 < end; ++t2) + { + for (t3 = entries; t3 < end; ++t3) + { + for (t4 = entries; t4 < end; ++t4) + { + for (t5 = entries; t5 < end; ++t5) + { + pixman_transform_t xform = { + { { *t0, *t1, *t2 }, + { *t3, *t4, *t5 }, + { 0, 0, pixman_fixed_1 } } + }; + + crc = test_scale (, crc); + } + } + } + } + } +} + +if (crc != CHECKSUM) +{ + printf ("filter-reduction-test failed! (checksum=0x%08X, expected 0x%08X)\n", crc, CHECKSUM); + return 1; +} +else +{ + printf ("filter-reduction-test passed (checksum=0x%08X)\n", crc); + return 0; +} +} -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pixman