1 From fc24a2d8d0039cd10de4175da40bb784e2c3bf49 Mon Sep 17 00:00:00 2001
2 From: Siarhei Siamashka <siarhei.siamashka@nokia.com>
3 Date: Fri, 4 Dec 2009 16:49:19 +0000
4 Subject: [PATCH 6/7] A copy-paste version of 16bpp bilinear scanline fetcher
7 pixman/pixman-bits-image.c | 228 +++++++++++++++++++++++++++++++++++++++++++-
8 1 files changed, 223 insertions(+), 5 deletions(-)
10 diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
11 index 3d78ff0..1656975 100644
12 --- a/pixman/pixman-bits-image.c
13 +++ b/pixman/pixman-bits-image.c
14 @@ -535,6 +535,212 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
19 +bits_image_fetch_bilinear_no_repeat_0565 (pixman_image_t * ima,
24 + const uint32_t * mask,
27 + bits_image_t *bits = &ima->bits;
28 + pixman_fixed_t x_top, x_bottom, x;
29 + pixman_fixed_t ux_top, ux_bottom, ux;
31 + uint32_t top_mask, bottom_mask;
33 + uint16_t *bottom_row;
35 + uint16_t zero[2] = { 0, 0 };
41 + /* reference point is the center of the pixel */
42 + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
43 + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
44 + v.vector[2] = pixman_fixed_1;
46 + if (!pixman_transform_point_3d (bits->common.transform, &v))
49 + ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
50 + x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
52 + y = v.vector[1] - pixman_fixed_1/2;
53 + disty = (y >> 8) & 0xff;
55 + /* Load the pointers to the first and second lines from the source
56 + * image that bilinear code must read.
58 + * The main trick in this code is about the check if any line are
59 + * outside of the image;
61 + * When I realize that a line (any one) is outside, I change
62 + * the pointer to a dummy area with zeros. Once I change this, I
63 + * must be sure the pointer will not change, so I set the
64 + * variables to each pointer increments inside the loop.
66 + y1 = pixman_fixed_to_int (y);
69 + if (y1 < 0 || y1 >= bits->height)
77 + top_row = bits->bits + y1 * bits->rowstride;
82 + if (y2 < 0 || y2 >= bits->height)
90 + bottom_row = bits->bits + y2 * bits->rowstride;
95 + /* Instead of checking whether the operation uses the mast in
96 + * each loop iteration, verify this only once and prepare the
97 + * variables to make the code smaller inside the loop.
107 + /* If have a mask, prepare the variables to check it */
111 + /* If both are zero, then the whole thing is zero */
112 + if (top_row == zero && bottom_row == zero)
114 + memset (buffer, 0, width * sizeof (uint32_t));
119 + if (top_row == zero)
122 + bottom_mask = 0xff000000;
124 + else if (bottom_row == zero)
126 + top_mask = 0xff000000;
131 + top_mask = 0xff000000;
132 + bottom_mask = 0xff000000;
136 + end = buffer + width;
138 + /* Zero fill to the left of the image */
139 + while (buffer < end && x < pixman_fixed_minus_1)
144 + x_bottom += ux_bottom;
150 + while (buffer < end && x < 0)
155 + tr = CONVERT_0565_TO_0888 (top_row[pixman_fixed_to_int (x_top) + 1]) | top_mask;
156 + br = CONVERT_0565_TO_0888 (bottom_row[pixman_fixed_to_int (x_bottom) + 1]) | bottom_mask;
158 + distx = (x >> 8) & 0xff;
160 + *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
164 + x_bottom += ux_bottom;
169 + w = pixman_int_to_fixed (bits->width - 1);
171 + while (buffer < end && x < w)
175 + uint32_t tl, tr, bl, br;
178 + tl = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top)]) | top_mask;
179 + tr = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top) + 1]) | top_mask;
180 + bl = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom)]) | bottom_mask;
181 + br = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom) + 1]) | bottom_mask;
183 + distx = (x >> 8) & 0xff;
185 + *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
191 + x_bottom += ux_bottom;
196 + w = pixman_int_to_fixed (bits->width);
197 + while (buffer < end && x < w)
204 + tl = CONVERT_0565_TO_0888 (top_row [pixman_fixed_to_int (x_top)]) | top_mask;
205 + bl = CONVERT_0565_TO_0888 (bottom_row [pixman_fixed_to_int (x_bottom)]) | bottom_mask;
207 + distx = (x >> 8) & 0xff;
209 + *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
215 + x_bottom += ux_bottom;
219 + /* Zero fill to the left of the image */
220 + while (buffer < end)
224 static force_inline uint32_t
225 bits_image_fetch_pixel_convolution (bits_image_t *image,
227 @@ -917,14 +1123,26 @@ bits_image_property_changed (pixman_image_t *image)
228 (bits->common.filter == PIXMAN_FILTER_BILINEAR ||
229 bits->common.filter == PIXMAN_FILTER_GOOD ||
230 bits->common.filter == PIXMAN_FILTER_BEST) &&
231 - bits->common.repeat == PIXMAN_REPEAT_NONE &&
232 - (bits->format == PIXMAN_a8r8g8b8 ||
233 - bits->format == PIXMAN_x8r8g8b8))
234 + bits->common.repeat == PIXMAN_REPEAT_NONE)
236 image->common.get_scanline_64 =
237 _pixman_image_get_scanline_generic_64;
238 - image->common.get_scanline_32 =
239 - bits_image_fetch_bilinear_no_repeat_8888;
241 + if (bits->format == PIXMAN_a8r8g8b8 || bits->format == PIXMAN_x8r8g8b8)
243 + image->common.get_scanline_32 =
244 + bits_image_fetch_bilinear_no_repeat_8888;
246 + else if (bits->format == PIXMAN_r5g6b5)
248 + image->common.get_scanline_32 =
249 + bits_image_fetch_bilinear_no_repeat_0565;
253 + image->common.get_scanline_32 =
254 + bits_image_fetch_transformed;