1 /*
2 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
3 * 2005 Lars Knoll & Zack Rusin, Trolltech
4 * 2008 Aaron Plattner, NVIDIA Corporation
5 * Copyright © 2000 SuSE, Inc.
6 * Copyright © 2007, 2009 Red Hat, Inc.
7 * Copyright © 2008 André Tupinambá <andrelrt@gmail.com>
8 *
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation, and that the name of Keith Packard not be used in
14 * advertising or publicity pertaining to distribution of the software without
15 * specific, written prior permission. Keith Packard makes no
16 * representations about the suitability of this software for any purpose. It
17 * is provided "as is" without express or implied warranty.
18 *
19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 * SOFTWARE.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include "pixman-private.h"
36 #include "pixman-combine32.h"
37 #include "pixman-inlines.h"
38
39 static uint32_t *
_pixman_image_get_scanline_generic_float(pixman_iter_t * iter,const uint32_t * mask)40 _pixman_image_get_scanline_generic_float (pixman_iter_t * iter,
41 const uint32_t *mask)
42 {
43 pixman_iter_get_scanline_t fetch_32 = iter->data;
44 uint32_t *buffer = iter->buffer;
45
46 fetch_32 (iter, NULL);
47
48 pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
49
50 return iter->buffer;
51 }
52
53 /* Fetch functions */
54
55 static force_inline uint32_t
fetch_pixel_no_alpha(bits_image_t * image,int x,int y,pixman_bool_t check_bounds)56 fetch_pixel_no_alpha (bits_image_t *image,
57 int x, int y, pixman_bool_t check_bounds)
58 {
59 if (check_bounds &&
60 (x < 0 || x >= image->width || y < 0 || y >= image->height))
61 {
62 return 0;
63 }
64
65 return image->fetch_pixel_32 (image, x, y);
66 }
67
68 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
69 int x, int y, pixman_bool_t check_bounds);
70
71 static force_inline uint32_t
bits_image_fetch_pixel_nearest(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)72 bits_image_fetch_pixel_nearest (bits_image_t *image,
73 pixman_fixed_t x,
74 pixman_fixed_t y,
75 get_pixel_t get_pixel)
76 {
77 int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
78 int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
79
80 if (image->common.repeat != PIXMAN_REPEAT_NONE)
81 {
82 repeat (image->common.repeat, &x0, image->width);
83 repeat (image->common.repeat, &y0, image->height);
84
85 return get_pixel (image, x0, y0, FALSE);
86 }
87 else
88 {
89 return get_pixel (image, x0, y0, TRUE);
90 }
91 }
92
93 static force_inline uint32_t
bits_image_fetch_pixel_bilinear(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)94 bits_image_fetch_pixel_bilinear (bits_image_t *image,
95 pixman_fixed_t x,
96 pixman_fixed_t y,
97 get_pixel_t get_pixel)
98 {
99 pixman_repeat_t repeat_mode = image->common.repeat;
100 int width = image->width;
101 int height = image->height;
102 int x1, y1, x2, y2;
103 uint32_t tl, tr, bl, br;
104 int32_t distx, disty;
105
106 x1 = x - pixman_fixed_1 / 2;
107 y1 = y - pixman_fixed_1 / 2;
108
109 distx = pixman_fixed_to_bilinear_weight (x1);
110 disty = pixman_fixed_to_bilinear_weight (y1);
111
112 x1 = pixman_fixed_to_int (x1);
113 y1 = pixman_fixed_to_int (y1);
114 x2 = x1 + 1;
115 y2 = y1 + 1;
116
117 if (repeat_mode != PIXMAN_REPEAT_NONE)
118 {
119 repeat (repeat_mode, &x1, width);
120 repeat (repeat_mode, &y1, height);
121 repeat (repeat_mode, &x2, width);
122 repeat (repeat_mode, &y2, height);
123
124 tl = get_pixel (image, x1, y1, FALSE);
125 bl = get_pixel (image, x1, y2, FALSE);
126 tr = get_pixel (image, x2, y1, FALSE);
127 br = get_pixel (image, x2, y2, FALSE);
128 }
129 else
130 {
131 tl = get_pixel (image, x1, y1, TRUE);
132 tr = get_pixel (image, x2, y1, TRUE);
133 bl = get_pixel (image, x1, y2, TRUE);
134 br = get_pixel (image, x2, y2, TRUE);
135 }
136
137 return bilinear_interpolation (tl, tr, bl, br, distx, disty);
138 }
139
140 static uint32_t *
bits_image_fetch_bilinear_no_repeat_8888(pixman_iter_t * iter,const uint32_t * mask)141 bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
142 const uint32_t *mask)
143 {
144
145 pixman_image_t * ima = iter->image;
146 int offset = iter->x;
147 int line = iter->y++;
148 int width = iter->width;
149 uint32_t * buffer = iter->buffer;
150
151 bits_image_t *bits = &ima->bits;
152 pixman_fixed_t x_top, x_bottom, x;
153 pixman_fixed_t ux_top, ux_bottom, ux;
154 pixman_vector_t v;
155 uint32_t top_mask, bottom_mask;
156 uint32_t *top_row;
157 uint32_t *bottom_row;
158 uint32_t *end;
159 uint32_t zero[2] = { 0, 0 };
160 uint32_t one = 1;
161 int y, y1, y2;
162 int disty;
163 int mask_inc;
164 int w;
165
166 /* reference point is the center of the pixel */
167 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
168 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
169 v.vector[2] = pixman_fixed_1;
170
171 if (!pixman_transform_point_3d (bits->common.transform, &v))
172 return iter->buffer;
173
174 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
175 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
176
177 y = v.vector[1] - pixman_fixed_1/2;
178 disty = pixman_fixed_to_bilinear_weight (y);
179
180 /* Load the pointers to the first and second lines from the source
181 * image that bilinear code must read.
182 *
183 * The main trick in this code is about the check if any line are
184 * outside of the image;
185 *
186 * When I realize that a line (any one) is outside, I change
187 * the pointer to a dummy area with zeros. Once I change this, I
188 * must be sure the pointer will not change, so I set the
189 * variables to each pointer increments inside the loop.
190 */
191 y1 = pixman_fixed_to_int (y);
192 y2 = y1 + 1;
193
194 if (y1 < 0 || y1 >= bits->height)
195 {
196 top_row = zero;
197 x_top = 0;
198 ux_top = 0;
199 }
200 else
201 {
202 top_row = bits->bits + y1 * bits->rowstride;
203 x_top = x;
204 ux_top = ux;
205 }
206
207 if (y2 < 0 || y2 >= bits->height)
208 {
209 bottom_row = zero;
210 x_bottom = 0;
211 ux_bottom = 0;
212 }
213 else
214 {
215 bottom_row = bits->bits + y2 * bits->rowstride;
216 x_bottom = x;
217 ux_bottom = ux;
218 }
219
220 /* Instead of checking whether the operation uses the mast in
221 * each loop iteration, verify this only once and prepare the
222 * variables to make the code smaller inside the loop.
223 */
224 if (!mask)
225 {
226 mask_inc = 0;
227 mask = &one;
228 }
229 else
230 {
231 /* If have a mask, prepare the variables to check it */
232 mask_inc = 1;
233 }
234
235 /* If both are zero, then the whole thing is zero */
236 if (top_row == zero && bottom_row == zero)
237 {
238 memset (buffer, 0, width * sizeof (uint32_t));
239 return iter->buffer;
240 }
241 else if (bits->format == PIXMAN_x8r8g8b8)
242 {
243 if (top_row == zero)
244 {
245 top_mask = 0;
246 bottom_mask = 0xff000000;
247 }
248 else if (bottom_row == zero)
249 {
250 top_mask = 0xff000000;
251 bottom_mask = 0;
252 }
253 else
254 {
255 top_mask = 0xff000000;
256 bottom_mask = 0xff000000;
257 }
258 }
259 else
260 {
261 top_mask = 0;
262 bottom_mask = 0;
263 }
264
265 end = buffer + width;
266
267 /* Zero fill to the left of the image */
268 while (buffer < end && x < pixman_fixed_minus_1)
269 {
270 *buffer++ = 0;
271 x += ux;
272 x_top += ux_top;
273 x_bottom += ux_bottom;
274 mask += mask_inc;
275 }
276
277 /* Left edge
278 */
279 while (buffer < end && x < 0)
280 {
281 uint32_t tr, br;
282 int32_t distx;
283
284 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
285 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
286
287 distx = pixman_fixed_to_bilinear_weight (x);
288
289 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
290
291 x += ux;
292 x_top += ux_top;
293 x_bottom += ux_bottom;
294 mask += mask_inc;
295 }
296
297 /* Main part */
298 w = pixman_int_to_fixed (bits->width - 1);
299
300 while (buffer < end && x < w)
301 {
302 if (*mask)
303 {
304 uint32_t tl, tr, bl, br;
305 int32_t distx;
306
307 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
308 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
309 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
310 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
311
312 distx = pixman_fixed_to_bilinear_weight (x);
313
314 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
315 }
316
317 buffer++;
318 x += ux;
319 x_top += ux_top;
320 x_bottom += ux_bottom;
321 mask += mask_inc;
322 }
323
324 /* Right Edge */
325 w = pixman_int_to_fixed (bits->width);
326 while (buffer < end && x < w)
327 {
328 if (*mask)
329 {
330 uint32_t tl, bl;
331 int32_t distx;
332
333 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
334 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
335
336 distx = pixman_fixed_to_bilinear_weight (x);
337
338 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
339 }
340
341 buffer++;
342 x += ux;
343 x_top += ux_top;
344 x_bottom += ux_bottom;
345 mask += mask_inc;
346 }
347
348 /* Zero fill to the left of the image */
349 while (buffer < end)
350 *buffer++ = 0;
351
352 return iter->buffer;
353 }
354
355 static force_inline uint32_t
bits_image_fetch_pixel_convolution(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)356 bits_image_fetch_pixel_convolution (bits_image_t *image,
357 pixman_fixed_t x,
358 pixman_fixed_t y,
359 get_pixel_t get_pixel)
360 {
361 pixman_fixed_t *params = image->common.filter_params;
362 int x_off = (params[0] - pixman_fixed_1) >> 1;
363 int y_off = (params[1] - pixman_fixed_1) >> 1;
364 int32_t cwidth = pixman_fixed_to_int (params[0]);
365 int32_t cheight = pixman_fixed_to_int (params[1]);
366 int32_t i, j, x1, x2, y1, y2;
367 pixman_repeat_t repeat_mode = image->common.repeat;
368 int width = image->width;
369 int height = image->height;
370 int srtot, sgtot, sbtot, satot;
371
372 params += 2;
373
374 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
375 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
376 x2 = x1 + cwidth;
377 y2 = y1 + cheight;
378
379 srtot = sgtot = sbtot = satot = 0;
380
381 for (i = y1; i < y2; ++i)
382 {
383 for (j = x1; j < x2; ++j)
384 {
385 int rx = j;
386 int ry = i;
387
388 pixman_fixed_t f = *params;
389
390 if (f)
391 {
392 uint32_t pixel;
393
394 if (repeat_mode != PIXMAN_REPEAT_NONE)
395 {
396 repeat (repeat_mode, &rx, width);
397 repeat (repeat_mode, &ry, height);
398
399 pixel = get_pixel (image, rx, ry, FALSE);
400 }
401 else
402 {
403 pixel = get_pixel (image, rx, ry, TRUE);
404 }
405
406 srtot += (int)RED_8 (pixel) * f;
407 sgtot += (int)GREEN_8 (pixel) * f;
408 sbtot += (int)BLUE_8 (pixel) * f;
409 satot += (int)ALPHA_8 (pixel) * f;
410 }
411
412 params++;
413 }
414 }
415
416 satot = (satot + 0x8000) >> 16;
417 srtot = (srtot + 0x8000) >> 16;
418 sgtot = (sgtot + 0x8000) >> 16;
419 sbtot = (sbtot + 0x8000) >> 16;
420
421 satot = CLIP (satot, 0, 0xff);
422 srtot = CLIP (srtot, 0, 0xff);
423 sgtot = CLIP (sgtot, 0, 0xff);
424 sbtot = CLIP (sbtot, 0, 0xff);
425
426 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
427 }
428
429 static uint32_t
bits_image_fetch_pixel_separable_convolution(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)430 bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
431 pixman_fixed_t x,
432 pixman_fixed_t y,
433 get_pixel_t get_pixel)
434 {
435 pixman_fixed_t *params = image->common.filter_params;
436 pixman_repeat_t repeat_mode = image->common.repeat;
437 int width = image->width;
438 int height = image->height;
439 int cwidth = pixman_fixed_to_int (params[0]);
440 int cheight = pixman_fixed_to_int (params[1]);
441 int x_phase_bits = pixman_fixed_to_int (params[2]);
442 int y_phase_bits = pixman_fixed_to_int (params[3]);
443 int x_phase_shift = 16 - x_phase_bits;
444 int y_phase_shift = 16 - y_phase_bits;
445 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
446 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
447 pixman_fixed_t *y_params;
448 int srtot, sgtot, sbtot, satot;
449 int32_t x1, x2, y1, y2;
450 int32_t px, py;
451 int i, j;
452
453 /* Round x and y to the middle of the closest phase before continuing. This
454 * ensures that the convolution matrix is aligned right, since it was
455 * positioned relative to a particular phase (and not relative to whatever
456 * exact fraction we happen to get here).
457 */
458 x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
459 y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
460
461 px = (x & 0xffff) >> x_phase_shift;
462 py = (y & 0xffff) >> y_phase_shift;
463
464 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
465
466 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
467 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
468 x2 = x1 + cwidth;
469 y2 = y1 + cheight;
470
471 srtot = sgtot = sbtot = satot = 0;
472
473 for (i = y1; i < y2; ++i)
474 {
475 pixman_fixed_48_16_t fy = *y_params++;
476 pixman_fixed_t *x_params = params + 4 + px * cwidth;
477
478 if (fy)
479 {
480 for (j = x1; j < x2; ++j)
481 {
482 pixman_fixed_t fx = *x_params++;
483 int rx = j;
484 int ry = i;
485
486 if (fx)
487 {
488 pixman_fixed_t f;
489 uint32_t pixel;
490
491 if (repeat_mode != PIXMAN_REPEAT_NONE)
492 {
493 repeat (repeat_mode, &rx, width);
494 repeat (repeat_mode, &ry, height);
495
496 pixel = get_pixel (image, rx, ry, FALSE);
497 }
498 else
499 {
500 pixel = get_pixel (image, rx, ry, TRUE);
501 }
502
503 f = (fy * fx + 0x8000) >> 16;
504
505 srtot += (int)RED_8 (pixel) * f;
506 sgtot += (int)GREEN_8 (pixel) * f;
507 sbtot += (int)BLUE_8 (pixel) * f;
508 satot += (int)ALPHA_8 (pixel) * f;
509 }
510 }
511 }
512 }
513
514 satot = (satot + 0x8000) >> 16;
515 srtot = (srtot + 0x8000) >> 16;
516 sgtot = (sgtot + 0x8000) >> 16;
517 sbtot = (sbtot + 0x8000) >> 16;
518
519 satot = CLIP (satot, 0, 0xff);
520 srtot = CLIP (srtot, 0, 0xff);
521 sgtot = CLIP (sgtot, 0, 0xff);
522 sbtot = CLIP (sbtot, 0, 0xff);
523
524 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
525 }
526
527 static force_inline uint32_t
bits_image_fetch_pixel_filtered(bits_image_t * image,pixman_fixed_t x,pixman_fixed_t y,get_pixel_t get_pixel)528 bits_image_fetch_pixel_filtered (bits_image_t *image,
529 pixman_fixed_t x,
530 pixman_fixed_t y,
531 get_pixel_t get_pixel)
532 {
533 switch (image->common.filter)
534 {
535 case PIXMAN_FILTER_NEAREST:
536 case PIXMAN_FILTER_FAST:
537 return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
538 break;
539
540 case PIXMAN_FILTER_BILINEAR:
541 case PIXMAN_FILTER_GOOD:
542 case PIXMAN_FILTER_BEST:
543 return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
544 break;
545
546 case PIXMAN_FILTER_CONVOLUTION:
547 return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
548 break;
549
550 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
551 return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel);
552 break;
553
554 default:
555 break;
556 }
557
558 return 0;
559 }
560
561 static uint32_t *
bits_image_fetch_affine_no_alpha(pixman_iter_t * iter,const uint32_t * mask)562 bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
563 const uint32_t * mask)
564 {
565 pixman_image_t *image = iter->image;
566 int offset = iter->x;
567 int line = iter->y++;
568 int width = iter->width;
569 uint32_t * buffer = iter->buffer;
570
571 pixman_fixed_t x, y;
572 pixman_fixed_t ux, uy;
573 pixman_vector_t v;
574 int i;
575
576 /* reference point is the center of the pixel */
577 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
578 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
579 v.vector[2] = pixman_fixed_1;
580
581 if (image->common.transform)
582 {
583 if (!pixman_transform_point_3d (image->common.transform, &v))
584 return iter->buffer;
585
586 ux = image->common.transform->matrix[0][0];
587 uy = image->common.transform->matrix[1][0];
588 }
589 else
590 {
591 ux = pixman_fixed_1;
592 uy = 0;
593 }
594
595 x = v.vector[0];
596 y = v.vector[1];
597
598 for (i = 0; i < width; ++i)
599 {
600 if (!mask || mask[i])
601 {
602 buffer[i] = bits_image_fetch_pixel_filtered (
603 &image->bits, x, y, fetch_pixel_no_alpha);
604 }
605
606 x += ux;
607 y += uy;
608 }
609
610 return buffer;
611 }
612
613 /* General fetcher */
614 static force_inline uint32_t
fetch_pixel_general(bits_image_t * image,int x,int y,pixman_bool_t check_bounds)615 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
616 {
617 uint32_t pixel;
618
619 if (check_bounds &&
620 (x < 0 || x >= image->width || y < 0 || y >= image->height))
621 {
622 return 0;
623 }
624
625 pixel = image->fetch_pixel_32 (image, x, y);
626
627 if (image->common.alpha_map)
628 {
629 uint32_t pixel_a;
630
631 x -= image->common.alpha_origin_x;
632 y -= image->common.alpha_origin_y;
633
634 if (x < 0 || x >= image->common.alpha_map->width ||
635 y < 0 || y >= image->common.alpha_map->height)
636 {
637 pixel_a = 0;
638 }
639 else
640 {
641 pixel_a = image->common.alpha_map->fetch_pixel_32 (
642 image->common.alpha_map, x, y);
643
644 pixel_a = ALPHA_8 (pixel_a);
645 }
646
647 pixel &= 0x00ffffff;
648 pixel |= (pixel_a << 24);
649 }
650
651 return pixel;
652 }
653
654 static uint32_t *
bits_image_fetch_general(pixman_iter_t * iter,const uint32_t * mask)655 bits_image_fetch_general (pixman_iter_t *iter,
656 const uint32_t *mask)
657 {
658 pixman_image_t *image = iter->image;
659 int offset = iter->x;
660 int line = iter->y++;
661 int width = iter->width;
662 uint32_t * buffer = iter->buffer;
663
664 pixman_fixed_t x, y, w;
665 pixman_fixed_t ux, uy, uw;
666 pixman_vector_t v;
667 int i;
668
669 /* reference point is the center of the pixel */
670 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
671 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
672 v.vector[2] = pixman_fixed_1;
673
674 if (image->common.transform)
675 {
676 if (!pixman_transform_point_3d (image->common.transform, &v))
677 return buffer;
678
679 ux = image->common.transform->matrix[0][0];
680 uy = image->common.transform->matrix[1][0];
681 uw = image->common.transform->matrix[2][0];
682 }
683 else
684 {
685 ux = pixman_fixed_1;
686 uy = 0;
687 uw = 0;
688 }
689
690 x = v.vector[0];
691 y = v.vector[1];
692 w = v.vector[2];
693
694 for (i = 0; i < width; ++i)
695 {
696 pixman_fixed_t x0, y0;
697
698 if (!mask || mask[i])
699 {
700 if (w != 0)
701 {
702 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
703 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
704 }
705 else
706 {
707 x0 = 0;
708 y0 = 0;
709 }
710
711 buffer[i] = bits_image_fetch_pixel_filtered (
712 &image->bits, x0, y0, fetch_pixel_general);
713 }
714
715 x += ux;
716 y += uy;
717 w += uw;
718 }
719
720 return buffer;
721 }
722
723 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
724
725 static force_inline void
bits_image_fetch_separable_convolution_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)726 bits_image_fetch_separable_convolution_affine (pixman_image_t * image,
727 int offset,
728 int line,
729 int width,
730 uint32_t * buffer,
731 const uint32_t * mask,
732
733 convert_pixel_t convert_pixel,
734 pixman_format_code_t format,
735 pixman_repeat_t repeat_mode)
736 {
737 bits_image_t *bits = &image->bits;
738 pixman_fixed_t *params = image->common.filter_params;
739 int cwidth = pixman_fixed_to_int (params[0]);
740 int cheight = pixman_fixed_to_int (params[1]);
741 int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1;
742 int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
743 int x_phase_bits = pixman_fixed_to_int (params[2]);
744 int y_phase_bits = pixman_fixed_to_int (params[3]);
745 int x_phase_shift = 16 - x_phase_bits;
746 int y_phase_shift = 16 - y_phase_bits;
747 pixman_fixed_t vx, vy;
748 pixman_fixed_t ux, uy;
749 pixman_vector_t v;
750 int k;
751
752 /* reference point is the center of the pixel */
753 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
754 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
755 v.vector[2] = pixman_fixed_1;
756
757 if (!pixman_transform_point_3d (image->common.transform, &v))
758 return;
759
760 ux = image->common.transform->matrix[0][0];
761 uy = image->common.transform->matrix[1][0];
762
763 vx = v.vector[0];
764 vy = v.vector[1];
765
766 for (k = 0; k < width; ++k)
767 {
768 pixman_fixed_t *y_params;
769 int satot, srtot, sgtot, sbtot;
770 pixman_fixed_t x, y;
771 int32_t x1, x2, y1, y2;
772 int32_t px, py;
773 int i, j;
774
775 if (mask && !mask[k])
776 goto next;
777
778 /* Round x and y to the middle of the closest phase before continuing. This
779 * ensures that the convolution matrix is aligned right, since it was
780 * positioned relative to a particular phase (and not relative to whatever
781 * exact fraction we happen to get here).
782 */
783 x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
784 y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
785
786 px = (x & 0xffff) >> x_phase_shift;
787 py = (y & 0xffff) >> y_phase_shift;
788
789 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
790 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
791 x2 = x1 + cwidth;
792 y2 = y1 + cheight;
793
794 satot = srtot = sgtot = sbtot = 0;
795
796 y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight;
797
798 for (i = y1; i < y2; ++i)
799 {
800 pixman_fixed_t fy = *y_params++;
801
802 if (fy)
803 {
804 pixman_fixed_t *x_params = params + 4 + px * cwidth;
805
806 for (j = x1; j < x2; ++j)
807 {
808 pixman_fixed_t fx = *x_params++;
809 int rx = j;
810 int ry = i;
811
812 if (fx)
813 {
814 pixman_fixed_t f;
815 uint32_t pixel, mask;
816 uint8_t *row;
817
818 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
819
820 if (repeat_mode != PIXMAN_REPEAT_NONE)
821 {
822 repeat (repeat_mode, &rx, bits->width);
823 repeat (repeat_mode, &ry, bits->height);
824
825 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
826 pixel = convert_pixel (row, rx) | mask;
827 }
828 else
829 {
830 if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height)
831 {
832 pixel = 0;
833 }
834 else
835 {
836 row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry;
837 pixel = convert_pixel (row, rx) | mask;
838 }
839 }
840
841 f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16;
842 srtot += (int)RED_8 (pixel) * f;
843 sgtot += (int)GREEN_8 (pixel) * f;
844 sbtot += (int)BLUE_8 (pixel) * f;
845 satot += (int)ALPHA_8 (pixel) * f;
846 }
847 }
848 }
849 }
850
851 satot = (satot + 0x8000) >> 16;
852 srtot = (srtot + 0x8000) >> 16;
853 sgtot = (sgtot + 0x8000) >> 16;
854 sbtot = (sbtot + 0x8000) >> 16;
855
856 satot = CLIP (satot, 0, 0xff);
857 srtot = CLIP (srtot, 0, 0xff);
858 sgtot = CLIP (sgtot, 0, 0xff);
859 sbtot = CLIP (sbtot, 0, 0xff);
860
861 buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
862
863 next:
864 vx += ux;
865 vy += uy;
866 }
867 }
868
869 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
870
871 static force_inline void
bits_image_fetch_bilinear_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)872 bits_image_fetch_bilinear_affine (pixman_image_t * image,
873 int offset,
874 int line,
875 int width,
876 uint32_t * buffer,
877 const uint32_t * mask,
878
879 convert_pixel_t convert_pixel,
880 pixman_format_code_t format,
881 pixman_repeat_t repeat_mode)
882 {
883 pixman_fixed_t x, y;
884 pixman_fixed_t ux, uy;
885 pixman_vector_t v;
886 bits_image_t *bits = &image->bits;
887 int i;
888
889 /* reference point is the center of the pixel */
890 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
891 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
892 v.vector[2] = pixman_fixed_1;
893
894 if (!pixman_transform_point_3d (image->common.transform, &v))
895 return;
896
897 ux = image->common.transform->matrix[0][0];
898 uy = image->common.transform->matrix[1][0];
899
900 x = v.vector[0];
901 y = v.vector[1];
902
903 for (i = 0; i < width; ++i)
904 {
905 int x1, y1, x2, y2;
906 uint32_t tl, tr, bl, br;
907 int32_t distx, disty;
908 int width = image->bits.width;
909 int height = image->bits.height;
910 const uint8_t *row1;
911 const uint8_t *row2;
912
913 if (mask && !mask[i])
914 goto next;
915
916 x1 = x - pixman_fixed_1 / 2;
917 y1 = y - pixman_fixed_1 / 2;
918
919 distx = pixman_fixed_to_bilinear_weight (x1);
920 disty = pixman_fixed_to_bilinear_weight (y1);
921
922 y1 = pixman_fixed_to_int (y1);
923 y2 = y1 + 1;
924 x1 = pixman_fixed_to_int (x1);
925 x2 = x1 + 1;
926
927 if (repeat_mode != PIXMAN_REPEAT_NONE)
928 {
929 uint32_t mask;
930
931 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
932
933 repeat (repeat_mode, &x1, width);
934 repeat (repeat_mode, &y1, height);
935 repeat (repeat_mode, &x2, width);
936 repeat (repeat_mode, &y2, height);
937
938 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
939 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
940
941 tl = convert_pixel (row1, x1) | mask;
942 tr = convert_pixel (row1, x2) | mask;
943 bl = convert_pixel (row2, x1) | mask;
944 br = convert_pixel (row2, x2) | mask;
945 }
946 else
947 {
948 uint32_t mask1, mask2;
949 int bpp;
950
951 /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
952 * which means if you use it in expressions, those
953 * expressions become unsigned themselves. Since
954 * the variables below can be negative in some cases,
955 * that will lead to crashes on 64 bit architectures.
956 *
957 * So this line makes sure bpp is signed
958 */
959 bpp = PIXMAN_FORMAT_BPP (format);
960
961 if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
962 {
963 buffer[i] = 0;
964 goto next;
965 }
966
967 if (y2 == 0)
968 {
969 row1 = zero;
970 mask1 = 0;
971 }
972 else
973 {
974 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
975 row1 += bpp / 8 * x1;
976
977 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
978 }
979
980 if (y1 == height - 1)
981 {
982 row2 = zero;
983 mask2 = 0;
984 }
985 else
986 {
987 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
988 row2 += bpp / 8 * x1;
989
990 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
991 }
992
993 if (x2 == 0)
994 {
995 tl = 0;
996 bl = 0;
997 }
998 else
999 {
1000 tl = convert_pixel (row1, 0) | mask1;
1001 bl = convert_pixel (row2, 0) | mask2;
1002 }
1003
1004 if (x1 == width - 1)
1005 {
1006 tr = 0;
1007 br = 0;
1008 }
1009 else
1010 {
1011 tr = convert_pixel (row1, 1) | mask1;
1012 br = convert_pixel (row2, 1) | mask2;
1013 }
1014 }
1015
1016 buffer[i] = bilinear_interpolation (
1017 tl, tr, bl, br, distx, disty);
1018
1019 next:
1020 x += ux;
1021 y += uy;
1022 }
1023 }
1024
1025 static force_inline void
bits_image_fetch_nearest_affine(pixman_image_t * image,int offset,int line,int width,uint32_t * buffer,const uint32_t * mask,convert_pixel_t convert_pixel,pixman_format_code_t format,pixman_repeat_t repeat_mode)1026 bits_image_fetch_nearest_affine (pixman_image_t * image,
1027 int offset,
1028 int line,
1029 int width,
1030 uint32_t * buffer,
1031 const uint32_t * mask,
1032
1033 convert_pixel_t convert_pixel,
1034 pixman_format_code_t format,
1035 pixman_repeat_t repeat_mode)
1036 {
1037 pixman_fixed_t x, y;
1038 pixman_fixed_t ux, uy;
1039 pixman_vector_t v;
1040 bits_image_t *bits = &image->bits;
1041 int i;
1042
1043 /* reference point is the center of the pixel */
1044 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
1045 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
1046 v.vector[2] = pixman_fixed_1;
1047
1048 if (!pixman_transform_point_3d (image->common.transform, &v))
1049 return;
1050
1051 ux = image->common.transform->matrix[0][0];
1052 uy = image->common.transform->matrix[1][0];
1053
1054 x = v.vector[0];
1055 y = v.vector[1];
1056
1057 for (i = 0; i < width; ++i)
1058 {
1059 int width, height, x0, y0;
1060 const uint8_t *row;
1061
1062 if (mask && !mask[i])
1063 goto next;
1064
1065 width = image->bits.width;
1066 height = image->bits.height;
1067 x0 = pixman_fixed_to_int (x - pixman_fixed_e);
1068 y0 = pixman_fixed_to_int (y - pixman_fixed_e);
1069
1070 if (repeat_mode == PIXMAN_REPEAT_NONE &&
1071 (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
1072 {
1073 buffer[i] = 0;
1074 }
1075 else
1076 {
1077 uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
1078
1079 if (repeat_mode != PIXMAN_REPEAT_NONE)
1080 {
1081 repeat (repeat_mode, &x0, width);
1082 repeat (repeat_mode, &y0, height);
1083 }
1084
1085 row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
1086
1087 buffer[i] = convert_pixel (row, x0) | mask;
1088 }
1089
1090 next:
1091 x += ux;
1092 y += uy;
1093 }
1094 }
1095
1096 static force_inline uint32_t
convert_a8r8g8b8(const uint8_t * row,int x)1097 convert_a8r8g8b8 (const uint8_t *row, int x)
1098 {
1099 return *(((uint32_t *)row) + x);
1100 }
1101
1102 static force_inline uint32_t
convert_x8r8g8b8(const uint8_t * row,int x)1103 convert_x8r8g8b8 (const uint8_t *row, int x)
1104 {
1105 return *(((uint32_t *)row) + x);
1106 }
1107
1108 static force_inline uint32_t
convert_a8(const uint8_t * row,int x)1109 convert_a8 (const uint8_t *row, int x)
1110 {
1111 return *(row + x) << 24;
1112 }
1113
1114 static force_inline uint32_t
convert_r5g6b5(const uint8_t * row,int x)1115 convert_r5g6b5 (const uint8_t *row, int x)
1116 {
1117 return convert_0565_to_0888 (*((uint16_t *)row + x));
1118 }
1119
1120 #define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \
1121 static uint32_t * \
1122 bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \
1123 const uint32_t * mask) \
1124 { \
1125 bits_image_fetch_separable_convolution_affine ( \
1126 iter->image, \
1127 iter->x, iter->y++, \
1128 iter->width, \
1129 iter->buffer, mask, \
1130 convert_ ## format, \
1131 PIXMAN_ ## format, \
1132 repeat_mode); \
1133 \
1134 return iter->buffer; \
1135 }
1136
1137 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
1138 static uint32_t * \
1139 bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \
1140 const uint32_t * mask) \
1141 { \
1142 bits_image_fetch_bilinear_affine (iter->image, \
1143 iter->x, iter->y++, \
1144 iter->width, \
1145 iter->buffer, mask, \
1146 convert_ ## format, \
1147 PIXMAN_ ## format, \
1148 repeat_mode); \
1149 return iter->buffer; \
1150 }
1151
1152 #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \
1153 static uint32_t * \
1154 bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \
1155 const uint32_t * mask) \
1156 { \
1157 bits_image_fetch_nearest_affine (iter->image, \
1158 iter->x, iter->y++, \
1159 iter->width, \
1160 iter->buffer, mask, \
1161 convert_ ## format, \
1162 PIXMAN_ ## format, \
1163 repeat_mode); \
1164 return iter->buffer; \
1165 }
1166
1167 #define MAKE_FETCHERS(name, format, repeat_mode) \
1168 MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
1169 MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \
1170 MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode)
1171
MAKE_FETCHERS(pad_a8r8g8b8,a8r8g8b8,PIXMAN_REPEAT_PAD)1172 MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
1173 MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
1174 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
1175 MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
1176 MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
1177 MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
1178 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
1179 MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
1180 MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
1181 MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
1182 MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
1183 MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
1184 MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
1185 MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
1186 MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
1187 MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
1188
1189 static void
1190 replicate_pixel_32 (bits_image_t * bits,
1191 int x,
1192 int y,
1193 int width,
1194 uint32_t * buffer)
1195 {
1196 uint32_t color;
1197 uint32_t *end;
1198
1199 color = bits->fetch_pixel_32 (bits, x, y);
1200
1201 end = buffer + width;
1202 while (buffer < end)
1203 *(buffer++) = color;
1204 }
1205
1206 static void
replicate_pixel_float(bits_image_t * bits,int x,int y,int width,uint32_t * b)1207 replicate_pixel_float (bits_image_t * bits,
1208 int x,
1209 int y,
1210 int width,
1211 uint32_t * b)
1212 {
1213 argb_t color;
1214 argb_t *buffer = (argb_t *)b;
1215 argb_t *end;
1216
1217 color = bits->fetch_pixel_float (bits, x, y);
1218
1219 end = buffer + width;
1220 while (buffer < end)
1221 *(buffer++) = color;
1222 }
1223
1224 static void
bits_image_fetch_untransformed_repeat_none(bits_image_t * image,pixman_bool_t wide,int x,int y,int width,uint32_t * buffer)1225 bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
1226 pixman_bool_t wide,
1227 int x,
1228 int y,
1229 int width,
1230 uint32_t * buffer)
1231 {
1232 uint32_t w;
1233
1234 if (y < 0 || y >= image->height)
1235 {
1236 memset (buffer, 0, width * (wide? sizeof (argb_t) : 4));
1237 return;
1238 }
1239
1240 if (x < 0)
1241 {
1242 w = MIN (width, -x);
1243
1244 memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4));
1245
1246 width -= w;
1247 buffer += w * (wide? 4 : 1);
1248 x += w;
1249 }
1250
1251 if (x < image->width)
1252 {
1253 w = MIN (width, image->width - x);
1254
1255 if (wide)
1256 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
1257 else
1258 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1259
1260 width -= w;
1261 buffer += w * (wide? 4 : 1);
1262 x += w;
1263 }
1264
1265 memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4));
1266 }
1267
1268 static void
bits_image_fetch_untransformed_repeat_normal(bits_image_t * image,pixman_bool_t wide,int x,int y,int width,uint32_t * buffer)1269 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
1270 pixman_bool_t wide,
1271 int x,
1272 int y,
1273 int width,
1274 uint32_t * buffer)
1275 {
1276 uint32_t w;
1277
1278 while (y < 0)
1279 y += image->height;
1280
1281 while (y >= image->height)
1282 y -= image->height;
1283
1284 if (image->width == 1)
1285 {
1286 if (wide)
1287 replicate_pixel_float (image, 0, y, width, buffer);
1288 else
1289 replicate_pixel_32 (image, 0, y, width, buffer);
1290
1291 return;
1292 }
1293
1294 while (width)
1295 {
1296 while (x < 0)
1297 x += image->width;
1298 while (x >= image->width)
1299 x -= image->width;
1300
1301 w = MIN (width, image->width - x);
1302
1303 if (wide)
1304 image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL);
1305 else
1306 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1307
1308 buffer += w * (wide? 4 : 1);
1309 x += w;
1310 width -= w;
1311 }
1312 }
1313
1314 static uint32_t *
bits_image_fetch_untransformed_32(pixman_iter_t * iter,const uint32_t * mask)1315 bits_image_fetch_untransformed_32 (pixman_iter_t * iter,
1316 const uint32_t *mask)
1317 {
1318 pixman_image_t *image = iter->image;
1319 int x = iter->x;
1320 int y = iter->y;
1321 int width = iter->width;
1322 uint32_t * buffer = iter->buffer;
1323
1324 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1325 {
1326 bits_image_fetch_untransformed_repeat_none (
1327 &image->bits, FALSE, x, y, width, buffer);
1328 }
1329 else
1330 {
1331 bits_image_fetch_untransformed_repeat_normal (
1332 &image->bits, FALSE, x, y, width, buffer);
1333 }
1334
1335 iter->y++;
1336 return buffer;
1337 }
1338
1339 static uint32_t *
bits_image_fetch_untransformed_float(pixman_iter_t * iter,const uint32_t * mask)1340 bits_image_fetch_untransformed_float (pixman_iter_t * iter,
1341 const uint32_t *mask)
1342 {
1343 pixman_image_t *image = iter->image;
1344 int x = iter->x;
1345 int y = iter->y;
1346 int width = iter->width;
1347 uint32_t * buffer = iter->buffer;
1348
1349 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1350 {
1351 bits_image_fetch_untransformed_repeat_none (
1352 &image->bits, TRUE, x, y, width, buffer);
1353 }
1354 else
1355 {
1356 bits_image_fetch_untransformed_repeat_normal (
1357 &image->bits, TRUE, x, y, width, buffer);
1358 }
1359
1360 iter->y++;
1361 return buffer;
1362 }
1363
1364 typedef struct
1365 {
1366 pixman_format_code_t format;
1367 uint32_t flags;
1368 pixman_iter_get_scanline_t get_scanline_32;
1369 pixman_iter_get_scanline_t get_scanline_float;
1370 } fetcher_info_t;
1371
1372 static const fetcher_info_t fetcher_info[] =
1373 {
1374 { PIXMAN_any,
1375 (FAST_PATH_NO_ALPHA_MAP |
1376 FAST_PATH_ID_TRANSFORM |
1377 FAST_PATH_NO_CONVOLUTION_FILTER |
1378 FAST_PATH_NO_PAD_REPEAT |
1379 FAST_PATH_NO_REFLECT_REPEAT),
1380 bits_image_fetch_untransformed_32,
1381 bits_image_fetch_untransformed_float
1382 },
1383
1384 #define FAST_BILINEAR_FLAGS \
1385 (FAST_PATH_NO_ALPHA_MAP | \
1386 FAST_PATH_NO_ACCESSORS | \
1387 FAST_PATH_HAS_TRANSFORM | \
1388 FAST_PATH_AFFINE_TRANSFORM | \
1389 FAST_PATH_X_UNIT_POSITIVE | \
1390 FAST_PATH_Y_UNIT_ZERO | \
1391 FAST_PATH_NONE_REPEAT | \
1392 FAST_PATH_BILINEAR_FILTER)
1393
1394 { PIXMAN_a8r8g8b8,
1395 FAST_BILINEAR_FLAGS,
1396 bits_image_fetch_bilinear_no_repeat_8888,
1397 _pixman_image_get_scanline_generic_float
1398 },
1399
1400 { PIXMAN_x8r8g8b8,
1401 FAST_BILINEAR_FLAGS,
1402 bits_image_fetch_bilinear_no_repeat_8888,
1403 _pixman_image_get_scanline_generic_float
1404 },
1405
1406 #define GENERAL_BILINEAR_FLAGS \
1407 (FAST_PATH_NO_ALPHA_MAP | \
1408 FAST_PATH_NO_ACCESSORS | \
1409 FAST_PATH_HAS_TRANSFORM | \
1410 FAST_PATH_AFFINE_TRANSFORM | \
1411 FAST_PATH_BILINEAR_FILTER)
1412
1413 #define GENERAL_NEAREST_FLAGS \
1414 (FAST_PATH_NO_ALPHA_MAP | \
1415 FAST_PATH_NO_ACCESSORS | \
1416 FAST_PATH_HAS_TRANSFORM | \
1417 FAST_PATH_AFFINE_TRANSFORM | \
1418 FAST_PATH_NEAREST_FILTER)
1419
1420 #define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \
1421 (FAST_PATH_NO_ALPHA_MAP | \
1422 FAST_PATH_NO_ACCESSORS | \
1423 FAST_PATH_HAS_TRANSFORM | \
1424 FAST_PATH_AFFINE_TRANSFORM | \
1425 FAST_PATH_SEPARABLE_CONVOLUTION_FILTER)
1426
1427 #define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
1428 { PIXMAN_ ## format, \
1429 GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1430 bits_image_fetch_separable_convolution_affine_ ## name, \
1431 _pixman_image_get_scanline_generic_float \
1432 },
1433
1434 #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1435 { PIXMAN_ ## format, \
1436 GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1437 bits_image_fetch_bilinear_affine_ ## name, \
1438 _pixman_image_get_scanline_generic_float \
1439 },
1440
1441 #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
1442 { PIXMAN_ ## format, \
1443 GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1444 bits_image_fetch_nearest_affine_ ## name, \
1445 _pixman_image_get_scanline_generic_float \
1446 },
1447
1448 #define AFFINE_FAST_PATHS(name, format, repeat) \
1449 SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \
1450 BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1451 NEAREST_AFFINE_FAST_PATH(name, format, repeat)
1452
1453 AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
1454 AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
1455 AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
1456 AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
1457 AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
1458 AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
1459 AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
1460 AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
1461 AFFINE_FAST_PATHS (pad_a8, a8, PAD)
1462 AFFINE_FAST_PATHS (none_a8, a8, NONE)
1463 AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
1464 AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
1465 AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
1466 AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
1467 AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
1468 AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
1469
1470 /* Affine, no alpha */
1471 { PIXMAN_any,
1472 (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
1473 bits_image_fetch_affine_no_alpha,
1474 _pixman_image_get_scanline_generic_float
1475 },
1476
1477 /* General */
1478 { PIXMAN_any,
1479 0,
1480 bits_image_fetch_general,
1481 _pixman_image_get_scanline_generic_float
1482 },
1483
1484 { PIXMAN_null },
1485 };
1486
1487 static void
bits_image_property_changed(pixman_image_t * image)1488 bits_image_property_changed (pixman_image_t *image)
1489 {
1490 _pixman_bits_image_setup_accessors (&image->bits);
1491 }
1492
1493 void
_pixman_bits_image_src_iter_init(pixman_image_t * image,pixman_iter_t * iter)1494 _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1495 {
1496 pixman_format_code_t format = image->common.extended_format_code;
1497 uint32_t flags = image->common.flags;
1498 const fetcher_info_t *info;
1499
1500 for (info = fetcher_info; info->format != PIXMAN_null; ++info)
1501 {
1502 if ((info->format == format || info->format == PIXMAN_any) &&
1503 (info->flags & flags) == info->flags)
1504 {
1505 if (iter->iter_flags & ITER_NARROW)
1506 {
1507 iter->get_scanline = info->get_scanline_32;
1508 }
1509 else
1510 {
1511 iter->data = info->get_scanline_32;
1512 iter->get_scanline = info->get_scanline_float;
1513 }
1514 return;
1515 }
1516 }
1517
1518 /* Just in case we somehow didn't find a scanline function */
1519 iter->get_scanline = _pixman_iter_get_scanline_noop;
1520 }
1521
1522 static uint32_t *
dest_get_scanline_narrow(pixman_iter_t * iter,const uint32_t * mask)1523 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
1524 {
1525 pixman_image_t *image = iter->image;
1526 int x = iter->x;
1527 int y = iter->y;
1528 int width = iter->width;
1529 uint32_t * buffer = iter->buffer;
1530
1531 image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
1532 if (image->common.alpha_map)
1533 {
1534 uint32_t *alpha;
1535
1536 if ((alpha = malloc (width * sizeof (uint32_t))))
1537 {
1538 int i;
1539
1540 x -= image->common.alpha_origin_x;
1541 y -= image->common.alpha_origin_y;
1542
1543 image->common.alpha_map->fetch_scanline_32 (
1544 (pixman_image_t *)image->common.alpha_map,
1545 x, y, width, alpha, mask);
1546
1547 for (i = 0; i < width; ++i)
1548 {
1549 buffer[i] &= ~0xff000000;
1550 buffer[i] |= (alpha[i] & 0xff000000);
1551 }
1552
1553 free (alpha);
1554 }
1555 }
1556
1557 return iter->buffer;
1558 }
1559
1560 static uint32_t *
dest_get_scanline_wide(pixman_iter_t * iter,const uint32_t * mask)1561 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
1562 {
1563 bits_image_t * image = &iter->image->bits;
1564 int x = iter->x;
1565 int y = iter->y;
1566 int width = iter->width;
1567 argb_t * buffer = (argb_t *)iter->buffer;
1568
1569 image->fetch_scanline_float (
1570 (pixman_image_t *)image, x, y, width, (uint32_t *)buffer, mask);
1571 if (image->common.alpha_map)
1572 {
1573 argb_t *alpha;
1574
1575 if ((alpha = malloc (width * sizeof (argb_t))))
1576 {
1577 int i;
1578
1579 x -= image->common.alpha_origin_x;
1580 y -= image->common.alpha_origin_y;
1581
1582 image->common.alpha_map->fetch_scanline_float (
1583 (pixman_image_t *)image->common.alpha_map,
1584 x, y, width, (uint32_t *)alpha, mask);
1585
1586 for (i = 0; i < width; ++i)
1587 buffer[i].a = alpha[i].a;
1588
1589 free (alpha);
1590 }
1591 }
1592
1593 return iter->buffer;
1594 }
1595
1596 static void
dest_write_back_narrow(pixman_iter_t * iter)1597 dest_write_back_narrow (pixman_iter_t *iter)
1598 {
1599 bits_image_t * image = &iter->image->bits;
1600 int x = iter->x;
1601 int y = iter->y;
1602 int width = iter->width;
1603 const uint32_t *buffer = iter->buffer;
1604
1605 image->store_scanline_32 (image, x, y, width, buffer);
1606
1607 if (image->common.alpha_map)
1608 {
1609 x -= image->common.alpha_origin_x;
1610 y -= image->common.alpha_origin_y;
1611
1612 image->common.alpha_map->store_scanline_32 (
1613 image->common.alpha_map, x, y, width, buffer);
1614 }
1615
1616 iter->y++;
1617 }
1618
1619 static void
dest_write_back_wide(pixman_iter_t * iter)1620 dest_write_back_wide (pixman_iter_t *iter)
1621 {
1622 bits_image_t * image = &iter->image->bits;
1623 int x = iter->x;
1624 int y = iter->y;
1625 int width = iter->width;
1626 const uint32_t *buffer = iter->buffer;
1627
1628 image->store_scanline_float (image, x, y, width, buffer);
1629
1630 if (image->common.alpha_map)
1631 {
1632 x -= image->common.alpha_origin_x;
1633 y -= image->common.alpha_origin_y;
1634
1635 image->common.alpha_map->store_scanline_float (
1636 image->common.alpha_map, x, y, width, buffer);
1637 }
1638
1639 iter->y++;
1640 }
1641
1642 void
_pixman_bits_image_dest_iter_init(pixman_image_t * image,pixman_iter_t * iter)1643 _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter)
1644 {
1645 if (iter->iter_flags & ITER_NARROW)
1646 {
1647 if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
1648 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
1649 {
1650 iter->get_scanline = _pixman_iter_get_scanline_noop;
1651 }
1652 else
1653 {
1654 iter->get_scanline = dest_get_scanline_narrow;
1655 }
1656
1657 iter->write_back = dest_write_back_narrow;
1658 }
1659 else
1660 {
1661 iter->get_scanline = dest_get_scanline_wide;
1662 iter->write_back = dest_write_back_wide;
1663 }
1664 }
1665
1666 static uint32_t *
create_bits(pixman_format_code_t format,int width,int height,int * rowstride_bytes,pixman_bool_t clear)1667 create_bits (pixman_format_code_t format,
1668 int width,
1669 int height,
1670 int * rowstride_bytes,
1671 pixman_bool_t clear)
1672 {
1673 int stride;
1674 size_t buf_size;
1675 int bpp;
1676
1677 /* what follows is a long-winded way, avoiding any possibility of integer
1678 * overflows, of saying:
1679 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
1680 */
1681
1682 bpp = PIXMAN_FORMAT_BPP (format);
1683 if (_pixman_multiply_overflows_int (width, bpp))
1684 return NULL;
1685
1686 stride = width * bpp;
1687 if (_pixman_addition_overflows_int (stride, 0x1f))
1688 return NULL;
1689
1690 stride += 0x1f;
1691 stride >>= 5;
1692
1693 stride *= sizeof (uint32_t);
1694
1695 if (_pixman_multiply_overflows_size (height, stride))
1696 return NULL;
1697
1698 buf_size = height * stride;
1699
1700 if (rowstride_bytes)
1701 *rowstride_bytes = stride;
1702
1703 if (clear)
1704 return calloc (buf_size, 1);
1705 else
1706 return malloc (buf_size);
1707 }
1708
1709 pixman_bool_t
_pixman_bits_image_init(pixman_image_t * image,pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride,pixman_bool_t clear)1710 _pixman_bits_image_init (pixman_image_t * image,
1711 pixman_format_code_t format,
1712 int width,
1713 int height,
1714 uint32_t * bits,
1715 int rowstride,
1716 pixman_bool_t clear)
1717 {
1718 uint32_t *free_me = NULL;
1719
1720 if (!bits && width && height)
1721 {
1722 int rowstride_bytes;
1723
1724 free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear);
1725
1726 if (!bits)
1727 return FALSE;
1728
1729 rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1730 }
1731
1732 _pixman_image_init (image);
1733
1734 image->type = BITS;
1735 image->bits.format = format;
1736 image->bits.width = width;
1737 image->bits.height = height;
1738 image->bits.bits = bits;
1739 image->bits.free_me = free_me;
1740 image->bits.read_func = NULL;
1741 image->bits.write_func = NULL;
1742 image->bits.rowstride = rowstride;
1743 image->bits.indexed = NULL;
1744
1745 image->common.property_changed = bits_image_property_changed;
1746
1747 _pixman_image_reset_clip_region (image);
1748
1749 return TRUE;
1750 }
1751
1752 static pixman_image_t *
create_bits_image_internal(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes,pixman_bool_t clear)1753 create_bits_image_internal (pixman_format_code_t format,
1754 int width,
1755 int height,
1756 uint32_t * bits,
1757 int rowstride_bytes,
1758 pixman_bool_t clear)
1759 {
1760 pixman_image_t *image;
1761
1762 /* must be a whole number of uint32_t's
1763 */
1764 return_val_if_fail (
1765 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1766
1767 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1768
1769 image = _pixman_image_allocate ();
1770
1771 if (!image)
1772 return NULL;
1773
1774 if (!_pixman_bits_image_init (image, format, width, height, bits,
1775 rowstride_bytes / (int) sizeof (uint32_t),
1776 clear))
1777 {
1778 free (image);
1779 return NULL;
1780 }
1781
1782 return image;
1783 }
1784
1785 /* If bits is NULL, a buffer will be allocated and initialized to 0 */
1786 PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)1787 pixman_image_create_bits (pixman_format_code_t format,
1788 int width,
1789 int height,
1790 uint32_t * bits,
1791 int rowstride_bytes)
1792 {
1793 return create_bits_image_internal (
1794 format, width, height, bits, rowstride_bytes, TRUE);
1795 }
1796
1797
1798 /* If bits is NULL, a buffer will be allocated and _not_ initialized */
1799 PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits_no_clear(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)1800 pixman_image_create_bits_no_clear (pixman_format_code_t format,
1801 int width,
1802 int height,
1803 uint32_t * bits,
1804 int rowstride_bytes)
1805 {
1806 return create_bits_image_internal (
1807 format, width, height, bits, rowstride_bytes, FALSE);
1808 }
1809