<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>