DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (31ec81b5d7bb)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
summary:     Bug 689707. Use lower precision bilinear interpolation. r=joe

diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c
--- a/gfx/cairo/libpixman/src/pixman-bits-image.c
+++ b/gfx/cairo/libpixman/src/pixman-bits-image.c
@@ -124,18 +124,18 @@ bits_image_fetch_pixel_bilinear (bits_im
     int height = image->height;
     int x1, y1, x2, y2;
     uint32_t tl, tr, bl, br;
     int32_t distx, disty;
 
     x1 = x - pixman_fixed_1 / 2;
     y1 = y - pixman_fixed_1 / 2;
 
-    distx = (x1 >> 8) & 0xff;
-    disty = (y1 >> 8) & 0xff;
+    distx = interpolation_coord(x1);
+    disty = interpolation_coord(y1);
 
     x1 = pixman_fixed_to_int (x1);
     y1 = pixman_fixed_to_int (y1);
     x2 = x1 + 1;
     y2 = y1 + 1;
 
     if (repeat_mode != PIXMAN_REPEAT_NONE)
     {
@@ -190,17 +190,17 @@ bits_image_fetch_bilinear_no_repeat_8888
 
     if (!pixman_transform_point_3d (bits->common.transform, &v))
 	return;
 
     ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
     x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
 
     y = v.vector[1] - pixman_fixed_1/2;
-    disty = (y >> 8) & 0xff;
+    disty = interpolation_coord(y);
 
     /* Load the pointers to the first and second lines from the source
      * image that bilinear code must read.
      *
      * The main trick in this code is about the check if any line are
      * outside of the image;
      *
      * When I realize that a line (any one) is outside, I change
@@ -299,17 +299,17 @@ bits_image_fetch_bilinear_no_repeat_8888
     while (buffer < end && x < 0)
     {
 	uint32_t tr, br;
 	int32_t distx;
 
 	tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
 	br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
 
-	distx = (x >> 8) & 0xff;
+	distx = interpolation_coord(x);
 
 	*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
 
 	x += ux;
 	x_top += ux_top;
 	x_bottom += ux_bottom;
 	mask += mask_inc;
     }
@@ -324,17 +324,17 @@ bits_image_fetch_bilinear_no_repeat_8888
 	    uint32_t tl, tr, bl, br;
 	    int32_t distx;
 
 	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
 	    tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
 	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
 	    br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
 
-	    distx = (x >> 8) & 0xff;
+	    distx = interpolation_coord(x);
 
 	    *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
 	}
 
 	buffer++;
 	x += ux;
 	x_top += ux_top;
 	x_bottom += ux_bottom;
@@ -348,17 +348,17 @@ bits_image_fetch_bilinear_no_repeat_8888
 	if (*mask)
 	{
 	    uint32_t tl, bl;
 	    int32_t distx;
 
 	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
 	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
 
-	    distx = (x >> 8) & 0xff;
+	    distx = interpolation_coord(x);
 
 	    *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
 	}
 
 	buffer++;
 	x += ux;
 	x_top += ux_top;
 	x_bottom += ux_bottom;
@@ -675,18 +675,18 @@ bits_image_fetch_bilinear_affine (pixman
 	const uint8_t *row2;
 
 	if (mask && !mask[i])
 	    goto next;
 
 	x1 = x - pixman_fixed_1 / 2;
 	y1 = y - pixman_fixed_1 / 2;
 
-	distx = (x1 >> 8) & 0xff;
-	disty = (y1 >> 8) & 0xff;
+	distx = interpolation_coord(x1);
+	disty = interpolation_coord(y1);
 
 	y1 = pixman_fixed_to_int (y1);
 	y2 = y1 + 1;
 	x1 = pixman_fixed_to_int (x1);
 	x2 = x1 + 1;
 
 	if (repeat_mode != PIXMAN_REPEAT_NONE)
 	{
diff --git a/gfx/cairo/libpixman/src/pixman-inlines.h b/gfx/cairo/libpixman/src/pixman-inlines.h
--- a/gfx/cairo/libpixman/src/pixman-inlines.h
+++ b/gfx/cairo/libpixman/src/pixman-inlines.h
@@ -76,16 +76,31 @@ repeat (pixman_repeat_t repeat, int *c, 
     {
 	*c = MOD (*c, size * 2);
 	if (*c >= size)
 	    *c = size * 2 - *c - 1;
     }
     return TRUE;
 }
 
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+#define LOW_QUALITY_INTERPOLATION
+#endif
+
+static force_inline int32_t
+interpolation_coord(pixman_fixed_t t)
+{
+#ifdef LOW_QUALITY_INTERPOLATION
+    return (t >> 12) & 0xf;
+#else
+    return (t >> 8) & 0xff;
+#endif
+}
+
+
 #if SIZEOF_LONG > 4
 
 static force_inline uint32_t
 bilinear_interpolation (uint32_t tl, uint32_t tr,
 			uint32_t bl, uint32_t br,
 			int distx, int disty)
 {
     uint64_t distxy, distxiy, distixy, distixiy;
@@ -122,16 +137,44 @@ bilinear_interpolation (uint32_t tl, uin
     f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
     r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
 
     return (uint32_t)(r >> 16);
 }
 
 #else
 
+#ifdef LOW_QUALITY_INTERPOLATION
+/* Based on Filter_32_opaque_portable from Skia */
+static force_inline uint32_t
+bilinear_interpolation(uint32_t a00, uint32_t a01,
+		       uint32_t a10, uint32_t a11,
+		       int x, int y)
+{
+    int xy = x * y;
+    static const uint32_t mask = 0xff00ff;
+
+    int scale = 256 - 16*y - 16*x + xy;
+    uint32_t lo = (a00 & mask) * scale;
+    uint32_t hi = ((a00 >> 8) & mask) * scale;
+
+    scale = 16*x - xy;
+    lo += (a01 & mask) * scale;
+    hi += ((a01 >> 8) & mask) * scale;
+
+    scale = 16*y - xy;
+    lo += (a10 & mask) * scale;
+    hi += ((a10 >> 8) & mask) * scale;
+
+    lo += (a11 & mask) * xy;
+    hi += ((a11 >> 8) & mask) * xy;
+
+    return ((lo >> 8) & mask) | (hi & ~mask);
+}
+#else
 static force_inline uint32_t
 bilinear_interpolation (uint32_t tl, uint32_t tr,
 			uint32_t bl, uint32_t br,
 			int distx, int disty)
 {
     int distxy, distxiy, distixy, distixiy;
     uint32_t f, r;
 
@@ -164,17 +207,17 @@ bilinear_interpolation (uint32_t tl, uin
 
     /* Alpha */
     f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
       + (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy;
     r |= f & 0xff000000;
 
     return r;
 }
-
+#endif
 #endif
 
 /*
  * For each scanline fetched from source image with PAD repeat:
  * - calculate how many pixels need to be padded on the left side
  * - calculate how many pixels need to be padded on the right side
  * - update width to only count pixels which are fetched from the image
  * All this information is returned via 'width', 'left_pad', 'right_pad'