gfx/cairo/pixman-lowres-interp.patch

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:ee8f64002042
1 summary: Bug 689707. Use lower precision bilinear interpolation. r=joe
2
3 diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c
4 --- a/gfx/cairo/libpixman/src/pixman-bits-image.c
5 +++ b/gfx/cairo/libpixman/src/pixman-bits-image.c
6 @@ -124,18 +124,18 @@ bits_image_fetch_pixel_bilinear (bits_im
7 int height = image->height;
8 int x1, y1, x2, y2;
9 uint32_t tl, tr, bl, br;
10 int32_t distx, disty;
11
12 x1 = x - pixman_fixed_1 / 2;
13 y1 = y - pixman_fixed_1 / 2;
14
15 - distx = (x1 >> 8) & 0xff;
16 - disty = (y1 >> 8) & 0xff;
17 + distx = interpolation_coord(x1);
18 + disty = interpolation_coord(y1);
19
20 x1 = pixman_fixed_to_int (x1);
21 y1 = pixman_fixed_to_int (y1);
22 x2 = x1 + 1;
23 y2 = y1 + 1;
24
25 if (repeat_mode != PIXMAN_REPEAT_NONE)
26 {
27 @@ -190,17 +190,17 @@ bits_image_fetch_bilinear_no_repeat_8888
28
29 if (!pixman_transform_point_3d (bits->common.transform, &v))
30 return;
31
32 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
33 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
34
35 y = v.vector[1] - pixman_fixed_1/2;
36 - disty = (y >> 8) & 0xff;
37 + disty = interpolation_coord(y);
38
39 /* Load the pointers to the first and second lines from the source
40 * image that bilinear code must read.
41 *
42 * The main trick in this code is about the check if any line are
43 * outside of the image;
44 *
45 * When I realize that a line (any one) is outside, I change
46 @@ -299,17 +299,17 @@ bits_image_fetch_bilinear_no_repeat_8888
47 while (buffer < end && x < 0)
48 {
49 uint32_t tr, br;
50 int32_t distx;
51
52 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
53 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
54
55 - distx = (x >> 8) & 0xff;
56 + distx = interpolation_coord(x);
57
58 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
59
60 x += ux;
61 x_top += ux_top;
62 x_bottom += ux_bottom;
63 mask += mask_inc;
64 }
65 @@ -324,17 +324,17 @@ bits_image_fetch_bilinear_no_repeat_8888
66 uint32_t tl, tr, bl, br;
67 int32_t distx;
68
69 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
70 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
71 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
72 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
73
74 - distx = (x >> 8) & 0xff;
75 + distx = interpolation_coord(x);
76
77 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
78 }
79
80 buffer++;
81 x += ux;
82 x_top += ux_top;
83 x_bottom += ux_bottom;
84 @@ -348,17 +348,17 @@ bits_image_fetch_bilinear_no_repeat_8888
85 if (*mask)
86 {
87 uint32_t tl, bl;
88 int32_t distx;
89
90 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
91 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
92
93 - distx = (x >> 8) & 0xff;
94 + distx = interpolation_coord(x);
95
96 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
97 }
98
99 buffer++;
100 x += ux;
101 x_top += ux_top;
102 x_bottom += ux_bottom;
103 @@ -675,18 +675,18 @@ bits_image_fetch_bilinear_affine (pixman
104 const uint8_t *row2;
105
106 if (mask && !mask[i])
107 goto next;
108
109 x1 = x - pixman_fixed_1 / 2;
110 y1 = y - pixman_fixed_1 / 2;
111
112 - distx = (x1 >> 8) & 0xff;
113 - disty = (y1 >> 8) & 0xff;
114 + distx = interpolation_coord(x1);
115 + disty = interpolation_coord(y1);
116
117 y1 = pixman_fixed_to_int (y1);
118 y2 = y1 + 1;
119 x1 = pixman_fixed_to_int (x1);
120 x2 = x1 + 1;
121
122 if (repeat_mode != PIXMAN_REPEAT_NONE)
123 {
124 diff --git a/gfx/cairo/libpixman/src/pixman-inlines.h b/gfx/cairo/libpixman/src/pixman-inlines.h
125 --- a/gfx/cairo/libpixman/src/pixman-inlines.h
126 +++ b/gfx/cairo/libpixman/src/pixman-inlines.h
127 @@ -76,16 +76,31 @@ repeat (pixman_repeat_t repeat, int *c,
128 {
129 *c = MOD (*c, size * 2);
130 if (*c >= size)
131 *c = size * 2 - *c - 1;
132 }
133 return TRUE;
134 }
135
136 +#ifdef MOZ_GFX_OPTIMIZE_MOBILE
137 +#define LOW_QUALITY_INTERPOLATION
138 +#endif
139 +
140 +static force_inline int32_t
141 +interpolation_coord(pixman_fixed_t t)
142 +{
143 +#ifdef LOW_QUALITY_INTERPOLATION
144 + return (t >> 12) & 0xf;
145 +#else
146 + return (t >> 8) & 0xff;
147 +#endif
148 +}
149 +
150 +
151 #if SIZEOF_LONG > 4
152
153 static force_inline uint32_t
154 bilinear_interpolation (uint32_t tl, uint32_t tr,
155 uint32_t bl, uint32_t br,
156 int distx, int disty)
157 {
158 uint64_t distxy, distxiy, distixy, distixiy;
159 @@ -122,16 +137,44 @@ bilinear_interpolation (uint32_t tl, uin
160 f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
161 r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
162
163 return (uint32_t)(r >> 16);
164 }
165
166 #else
167
168 +#ifdef LOW_QUALITY_INTERPOLATION
169 +/* Based on Filter_32_opaque_portable from Skia */
170 +static force_inline uint32_t
171 +bilinear_interpolation(uint32_t a00, uint32_t a01,
172 + uint32_t a10, uint32_t a11,
173 + int x, int y)
174 +{
175 + int xy = x * y;
176 + static const uint32_t mask = 0xff00ff;
177 +
178 + int scale = 256 - 16*y - 16*x + xy;
179 + uint32_t lo = (a00 & mask) * scale;
180 + uint32_t hi = ((a00 >> 8) & mask) * scale;
181 +
182 + scale = 16*x - xy;
183 + lo += (a01 & mask) * scale;
184 + hi += ((a01 >> 8) & mask) * scale;
185 +
186 + scale = 16*y - xy;
187 + lo += (a10 & mask) * scale;
188 + hi += ((a10 >> 8) & mask) * scale;
189 +
190 + lo += (a11 & mask) * xy;
191 + hi += ((a11 >> 8) & mask) * xy;
192 +
193 + return ((lo >> 8) & mask) | (hi & ~mask);
194 +}
195 +#else
196 static force_inline uint32_t
197 bilinear_interpolation (uint32_t tl, uint32_t tr,
198 uint32_t bl, uint32_t br,
199 int distx, int disty)
200 {
201 int distxy, distxiy, distixy, distixiy;
202 uint32_t f, r;
203
204 @@ -164,17 +207,17 @@ bilinear_interpolation (uint32_t tl, uin
205
206 /* Alpha */
207 f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
208 + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
209 r |= f & 0xff000000;
210
211 return r;
212 }
213 -
214 +#endif
215 #endif
216
217 /*
218 * For each scanline fetched from source image with PAD repeat:
219 * - calculate how many pixels need to be padded on the left side
220 * - calculate how many pixels need to be padded on the right side
221 * - update width to only count pixels which are fetched from the image
222 * All this information is returned via 'width', 'left_pad', 'right_pad'

mercurial