1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/pixman-lowres-interp.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,222 @@ 1.4 +summary: Bug 689707. Use lower precision bilinear interpolation. r=joe 1.5 + 1.6 +diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c 1.7 +--- a/gfx/cairo/libpixman/src/pixman-bits-image.c 1.8 ++++ b/gfx/cairo/libpixman/src/pixman-bits-image.c 1.9 +@@ -124,18 +124,18 @@ bits_image_fetch_pixel_bilinear (bits_im 1.10 + int height = image->height; 1.11 + int x1, y1, x2, y2; 1.12 + uint32_t tl, tr, bl, br; 1.13 + int32_t distx, disty; 1.14 + 1.15 + x1 = x - pixman_fixed_1 / 2; 1.16 + y1 = y - pixman_fixed_1 / 2; 1.17 + 1.18 +- distx = (x1 >> 8) & 0xff; 1.19 +- disty = (y1 >> 8) & 0xff; 1.20 ++ distx = interpolation_coord(x1); 1.21 ++ disty = interpolation_coord(y1); 1.22 + 1.23 + x1 = pixman_fixed_to_int (x1); 1.24 + y1 = pixman_fixed_to_int (y1); 1.25 + x2 = x1 + 1; 1.26 + y2 = y1 + 1; 1.27 + 1.28 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.29 + { 1.30 +@@ -190,17 +190,17 @@ bits_image_fetch_bilinear_no_repeat_8888 1.31 + 1.32 + if (!pixman_transform_point_3d (bits->common.transform, &v)) 1.33 + return; 1.34 + 1.35 + ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; 1.36 + x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; 1.37 + 1.38 + y = v.vector[1] - pixman_fixed_1/2; 1.39 +- disty = (y >> 8) & 0xff; 1.40 ++ disty = interpolation_coord(y); 1.41 + 1.42 + /* Load the pointers to the first and second lines from the source 1.43 + * image that bilinear code must read. 1.44 + * 1.45 + * The main trick in this code is about the check if any line are 1.46 + * outside of the image; 1.47 + * 1.48 + * When I realize that a line (any one) is outside, I change 1.49 +@@ -299,17 +299,17 @@ bits_image_fetch_bilinear_no_repeat_8888 1.50 + while (buffer < end && x < 0) 1.51 + { 1.52 + uint32_t tr, br; 1.53 + int32_t distx; 1.54 + 1.55 + tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; 1.56 + br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 1.57 + 1.58 +- distx = (x >> 8) & 0xff; 1.59 ++ distx = interpolation_coord(x); 1.60 + 1.61 + *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); 1.62 + 1.63 + x += ux; 1.64 + x_top += ux_top; 1.65 + x_bottom += ux_bottom; 1.66 + mask += mask_inc; 1.67 + } 1.68 +@@ -324,17 +324,17 @@ bits_image_fetch_bilinear_no_repeat_8888 1.69 + uint32_t tl, tr, bl, br; 1.70 + int32_t distx; 1.71 + 1.72 + tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 1.73 + tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask; 1.74 + bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 1.75 + br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; 1.76 + 1.77 +- distx = (x >> 8) & 0xff; 1.78 ++ distx = interpolation_coord(x); 1.79 + 1.80 + *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); 1.81 + } 1.82 + 1.83 + buffer++; 1.84 + x += ux; 1.85 + x_top += ux_top; 1.86 + x_bottom += ux_bottom; 1.87 +@@ -348,17 +348,17 @@ bits_image_fetch_bilinear_no_repeat_8888 1.88 + if (*mask) 1.89 + { 1.90 + uint32_t tl, bl; 1.91 + int32_t distx; 1.92 + 1.93 + tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; 1.94 + bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; 1.95 + 1.96 +- distx = (x >> 8) & 0xff; 1.97 ++ distx = interpolation_coord(x); 1.98 + 1.99 + *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); 1.100 + } 1.101 + 1.102 + buffer++; 1.103 + x += ux; 1.104 + x_top += ux_top; 1.105 + x_bottom += ux_bottom; 1.106 +@@ -675,18 +675,18 @@ bits_image_fetch_bilinear_affine (pixman 1.107 + const uint8_t *row2; 1.108 + 1.109 + if (mask && !mask[i]) 1.110 + goto next; 1.111 + 1.112 + x1 = x - pixman_fixed_1 / 2; 1.113 + y1 = y - pixman_fixed_1 / 2; 1.114 + 1.115 +- distx = (x1 >> 8) & 0xff; 1.116 +- disty = (y1 >> 8) & 0xff; 1.117 ++ distx = interpolation_coord(x1); 1.118 ++ disty = interpolation_coord(y1); 1.119 + 1.120 + y1 = pixman_fixed_to_int (y1); 1.121 + y2 = y1 + 1; 1.122 + x1 = pixman_fixed_to_int (x1); 1.123 + x2 = x1 + 1; 1.124 + 1.125 + if (repeat_mode != PIXMAN_REPEAT_NONE) 1.126 + { 1.127 +diff --git a/gfx/cairo/libpixman/src/pixman-inlines.h b/gfx/cairo/libpixman/src/pixman-inlines.h 1.128 +--- a/gfx/cairo/libpixman/src/pixman-inlines.h 1.129 ++++ b/gfx/cairo/libpixman/src/pixman-inlines.h 1.130 +@@ -76,16 +76,31 @@ repeat (pixman_repeat_t repeat, int *c, 1.131 + { 1.132 + *c = MOD (*c, size * 2); 1.133 + if (*c >= size) 1.134 + *c = size * 2 - *c - 1; 1.135 + } 1.136 + return TRUE; 1.137 + } 1.138 + 1.139 ++#ifdef MOZ_GFX_OPTIMIZE_MOBILE 1.140 ++#define LOW_QUALITY_INTERPOLATION 1.141 ++#endif 1.142 ++ 1.143 ++static force_inline int32_t 1.144 ++interpolation_coord(pixman_fixed_t t) 1.145 ++{ 1.146 ++#ifdef LOW_QUALITY_INTERPOLATION 1.147 ++ return (t >> 12) & 0xf; 1.148 ++#else 1.149 ++ return (t >> 8) & 0xff; 1.150 ++#endif 1.151 ++} 1.152 ++ 1.153 ++ 1.154 + #if SIZEOF_LONG > 4 1.155 + 1.156 + static force_inline uint32_t 1.157 + bilinear_interpolation (uint32_t tl, uint32_t tr, 1.158 + uint32_t bl, uint32_t br, 1.159 + int distx, int disty) 1.160 + { 1.161 + uint64_t distxy, distxiy, distixy, distixiy; 1.162 +@@ -122,16 +137,44 @@ bilinear_interpolation (uint32_t tl, uin 1.163 + f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy; 1.164 + r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull); 1.165 + 1.166 + return (uint32_t)(r >> 16); 1.167 + } 1.168 + 1.169 + #else 1.170 + 1.171 ++#ifdef LOW_QUALITY_INTERPOLATION 1.172 ++/* Based on Filter_32_opaque_portable from Skia */ 1.173 ++static force_inline uint32_t 1.174 ++bilinear_interpolation(uint32_t a00, uint32_t a01, 1.175 ++ uint32_t a10, uint32_t a11, 1.176 ++ int x, int y) 1.177 ++{ 1.178 ++ int xy = x * y; 1.179 ++ static const uint32_t mask = 0xff00ff; 1.180 ++ 1.181 ++ int scale = 256 - 16*y - 16*x + xy; 1.182 ++ uint32_t lo = (a00 & mask) * scale; 1.183 ++ uint32_t hi = ((a00 >> 8) & mask) * scale; 1.184 ++ 1.185 ++ scale = 16*x - xy; 1.186 ++ lo += (a01 & mask) * scale; 1.187 ++ hi += ((a01 >> 8) & mask) * scale; 1.188 ++ 1.189 ++ scale = 16*y - xy; 1.190 ++ lo += (a10 & mask) * scale; 1.191 ++ hi += ((a10 >> 8) & mask) * scale; 1.192 ++ 1.193 ++ lo += (a11 & mask) * xy; 1.194 ++ hi += ((a11 >> 8) & mask) * xy; 1.195 ++ 1.196 ++ return ((lo >> 8) & mask) | (hi & ~mask); 1.197 ++} 1.198 ++#else 1.199 + static force_inline uint32_t 1.200 + bilinear_interpolation (uint32_t tl, uint32_t tr, 1.201 + uint32_t bl, uint32_t br, 1.202 + int distx, int disty) 1.203 + { 1.204 + int distxy, distxiy, distixy, distixiy; 1.205 + uint32_t f, r; 1.206 + 1.207 +@@ -164,17 +207,17 @@ bilinear_interpolation (uint32_t tl, uin 1.208 + 1.209 + /* Alpha */ 1.210 + f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy 1.211 + + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy; 1.212 + r |= f & 0xff000000; 1.213 + 1.214 + return r; 1.215 + } 1.216 +- 1.217 ++#endif 1.218 + #endif 1.219 + 1.220 + /* 1.221 + * For each scanline fetched from source image with PAD repeat: 1.222 + * - calculate how many pixels need to be padded on the left side 1.223 + * - calculate how many pixels need to be padded on the right side 1.224 + * - update width to only count pixels which are fetched from the image 1.225 + * All this information is returned via 'width', 'left_pad', 'right_pad'