gfx/cairo/pixman-lowres-interp.patch

changeset 0
6474c204b198
     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'

mercurial