<div dir="ltr">Looks good to me<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 16, 2016 at 9:14 PM, Søren Sandmann Pedersen <span dir="ltr"><<a href="mailto:soren.sandmann@gmail.com" target="_blank">soren.sandmann@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Generalize and simplify the code that reduces BILINEAR to NEAREST so<br>
that all the reduction happens for all affine transformations where<br>
t00..t12 are integers and (t00 + t01) and (t10 + t11) are both<br>
odd. This is a sufficient condition for the resulting transformed<br>
coordinates to be exactly at the center of a pixel so that BILINEAR<br>
becomes identical to NEAREST.<br>
<br>
V2: Address some comments by Bill Spitzak<br>
<br>
Signed-off-by: Søren Sandmann <<a href="mailto:soren.sandmann@gmail.com">soren.sandmann@gmail.com</a>><br>
---<br>
 pixman/pixman-image.c | 66 +++++++++++++++++++++++++++++----------------------<br>
 1 file changed, 38 insertions(+), 28 deletions(-)<br>
<br>
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c<br>
index 1ff1a49..681864e 100644<br>
--- a/pixman/pixman-image.c<br>
+++ b/pixman/pixman-image.c<br>
@@ -335,37 +335,47 @@ compute_image_info (pixman_image_t *image)<br>
        {<br>
            flags |= FAST_PATH_NEAREST_FILTER;<br>
        }<br>
-       else if (<br>
-           /* affine and integer translation components in matrix ... */<br>
-           ((flags & FAST_PATH_AFFINE_TRANSFORM) &&<br>
-            !pixman_fixed_frac (image->common.transform->matrix[0][2] |<br>
-                                image->common.transform->matrix[1][2])) &&<br>
-           (<br>
-               /* ... combined with a simple rotation */<br>
-               (flags & (FAST_PATH_ROTATE_90_TRANSFORM |<br>
-                         FAST_PATH_ROTATE_180_TRANSFORM |<br>
-                         FAST_PATH_ROTATE_270_TRANSFORM)) ||<br>
-               /* ... or combined with a simple non-rotated translation */<br>
-               (image->common.transform->matrix[0][0] == pixman_fixed_1 &&<br>
-                image->common.transform->matrix[1][1] == pixman_fixed_1 &&<br>
-                image->common.transform->matrix[0][1] == 0 &&<br>
-                image->common.transform->matrix[1][0] == 0)<br>
-               )<br>
-           )<br>
+       else if (flags & FAST_PATH_AFFINE_TRANSFORM)<br>
        {<br>
-           /* FIXME: there are some affine-test failures, showing that<br>
-            * handling of BILINEAR and NEAREST filter is not quite<br>
-            * equivalent when getting close to 32K for the translation<br>
-            * components of the matrix. That's likely some bug, but for<br>
-            * now just skip BILINEAR->NEAREST optimization in this case.<br>
+           /* Suppose the transform is<br>
+            *<br>
+            *    [ t00, t01, t02 ]<br>
+            *    [ t10, t11, t12 ]<br>
+            *    [   0,   0,   1 ]<br>
+            *<br>
+            * and the destination coordinates are (n + 0.5, m + 0.5). Then<br>
+            * the transformed x coordinate is:<br>
+            *<br>
+            *     tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02<br>
+            *        = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5<br>
+            *<br>
+            * which implies that if t00, t01 and t02 are all integers<br>
+            * and (t00 + t01) is odd, then tx will be an integer plus 0.5,<br>
+            * which means a BILINEAR filter will reduce to NEAREST. The same<br>
+            * applies in the y direction<br>
             */<br>
-           pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);<br>
-           if (image->common.transform->matrix[0][2] <= magic_limit  &&<br>
-               image->common.transform->matrix[1][2] <= magic_limit  &&<br>
-               image->common.transform->matrix[0][2] >= -magic_limit &&<br>
-               image->common.transform->matrix[1][2] >= -magic_limit)<br>
+           pixman_fixed_t (*t)[3] = image->common.transform->matrix;<br>
+<br>
+           if ((pixman_fixed_frac (<br>
+                    t[0][0] | t[0][1] | t[0][2] |<br>
+                    t[1][0] | t[1][1] | t[1][2]) == 0)                 &&<br>
+               (pixman_fixed_to_int (<br>
+                   (t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1)<br></blockquote><div><br></div><div>Very clever! This optimization looks correct.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
            {<br>
-               flags |= FAST_PATH_NEAREST_FILTER;<br>
+               /* FIXME: there are some affine-test failures, showing that<br>
+                * handling of BILINEAR and NEAREST filter is not quite<br>
+                * equivalent when getting close to 32K for the translation<br>
+                * components of the matrix. That's likely some bug, but for<br>
+                * now just skip BILINEAR->NEAREST optimization in this case.<br>
+                */<br>
+               pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);<br>
+               if (image->common.transform->matrix[0][2] <= magic_limit  &&<br>
+                   image->common.transform->matrix[1][2] <= magic_limit  &&<br>
+                   image->common.transform->matrix[0][2] >= -magic_limit &&<br>
+                   image->common.transform->matrix[1][2] >= -magic_limit)<br>
+               {<br>
+                   flags |= FAST_PATH_NEAREST_FILTER;<br>
+               }<br>
            }<br>
        }<br>
        break;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.11.7<br>
<br>
_______________________________________________<br>
Pixman mailing list<br>
<a href="mailto:Pixman@lists.freedesktop.org">Pixman@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/pixman" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/pixman</a><br>
</font></span></blockquote></div><br></div></div>