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>
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.
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
35 #include "pixman-private.h"
36 #include "pixman-combine32.h"
40 _pixman_image_store_scanline_32 (bits_image_t * image,
44 const uint32_t *buffer)
46 image->store_scanline_32 (image, x, y, width, buffer);
48 if (image->common.alpha_map)
50 x -= image->common.alpha_origin_x;
51 y -= image->common.alpha_origin_y;
53 image->common.alpha_map->store_scanline_32 (
54 image->common.alpha_map, x, y, width, buffer);
59 _pixman_image_store_scanline_64 (bits_image_t * image,
63 const uint32_t *buffer)
65 image->store_scanline_64 (image, x, y, width, buffer);
67 if (image->common.alpha_map)
69 x -= image->common.alpha_origin_x;
70 y -= image->common.alpha_origin_y;
72 image->common.alpha_map->store_scanline_64 (
73 image->common.alpha_map, x, y, width, buffer);
79 static force_inline uint32_t
80 fetch_pixel_no_alpha (bits_image_t *image,
81 int x, int y, pixman_bool_t check_bounds)
84 (x < 0 || x >= image->width || y < 0 || y >= image->height))
89 return image->fetch_pixel_32 (image, x, y);
92 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
93 int x, int y, pixman_bool_t check_bounds);
95 static force_inline void
96 repeat (pixman_repeat_t repeat, int size, int *coord)
100 case PIXMAN_REPEAT_NORMAL:
101 *coord = MOD (*coord, size);
104 case PIXMAN_REPEAT_PAD:
105 *coord = CLIP (*coord, 0, size - 1);
108 case PIXMAN_REPEAT_REFLECT:
109 *coord = MOD (*coord, size * 2);
112 *coord = size * 2 - *coord - 1;
115 case PIXMAN_REPEAT_NONE:
123 static force_inline uint32_t
124 bits_image_fetch_pixel_nearest (bits_image_t *image,
127 get_pixel_t get_pixel)
129 int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
130 int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
132 if (image->common.repeat != PIXMAN_REPEAT_NONE)
134 repeat (image->common.repeat, image->width, &x0);
135 repeat (image->common.repeat, image->height, &y0);
137 return get_pixel (image, x0, y0, FALSE);
141 return get_pixel (image, x0, y0, TRUE);
147 static force_inline uint32_t
148 bilinear_interpolation (uint32_t tl, uint32_t tr,
149 uint32_t bl, uint32_t br,
150 int distx, int disty)
152 uint64_t distxy, distxiy, distixy, distixiy;
153 uint64_t tl64, tr64, bl64, br64;
156 distxy = distx * disty;
157 distxiy = distx * (256 - disty);
158 distixy = (256 - distx) * disty;
159 distixiy = (256 - distx) * (256 - disty);
162 tl64 = tl & 0xff0000ff;
163 tr64 = tr & 0xff0000ff;
164 bl64 = bl & 0xff0000ff;
165 br64 = br & 0xff0000ff;
167 f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
168 r = f & 0x0000ff0000ff0000ull;
172 tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
175 tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
178 bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
181 br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
183 f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
184 r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
186 return (uint32_t)(r >> 16);
191 static force_inline uint32_t
192 bilinear_interpolation (uint32_t tl, uint32_t tr,
193 uint32_t bl, uint32_t br,
194 int distx, int disty)
196 int distxy, distxiy, distixy, distixiy;
199 distxy = distx * disty;
200 distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */
201 distixy = (disty << 8) - distxy; /* disty * (256 - distx) */
203 256 * 256 - (disty << 8) -
204 (distx << 8) + distxy; /* (256 - distx) * (256 - disty) */
207 r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
208 + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
211 f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
212 + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
222 f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
223 + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy;
227 f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
228 + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy;
236 static force_inline uint32_t
237 bits_image_fetch_pixel_bilinear (bits_image_t *image,
240 get_pixel_t get_pixel)
242 pixman_repeat_t repeat_mode = image->common.repeat;
243 int width = image->width;
244 int height = image->height;
246 uint32_t tl, tr, bl, br;
247 int32_t distx, disty;
249 x1 = x - pixman_fixed_1 / 2;
250 y1 = y - pixman_fixed_1 / 2;
252 distx = (x1 >> 8) & 0xff;
253 disty = (y1 >> 8) & 0xff;
255 x1 = pixman_fixed_to_int (x1);
256 y1 = pixman_fixed_to_int (y1);
260 if (repeat_mode != PIXMAN_REPEAT_NONE)
262 repeat (repeat_mode, width, &x1);
263 repeat (repeat_mode, height, &y1);
264 repeat (repeat_mode, width, &x2);
265 repeat (repeat_mode, height, &y2);
267 tl = get_pixel (image, x1, y1, FALSE);
268 bl = get_pixel (image, x1, y2, FALSE);
269 tr = get_pixel (image, x2, y1, FALSE);
270 br = get_pixel (image, x2, y2, FALSE);
274 tl = get_pixel (image, x1, y1, TRUE);
275 tr = get_pixel (image, x2, y1, TRUE);
276 bl = get_pixel (image, x1, y2, TRUE);
277 br = get_pixel (image, x2, y2, TRUE);
280 return bilinear_interpolation (tl, tr, bl, br, distx, disty);
284 bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
289 const uint32_t * mask)
291 bits_image_t *bits = &ima->bits;
292 pixman_fixed_t x_top, x_bottom, x;
293 pixman_fixed_t ux_top, ux_bottom, ux;
295 uint32_t top_mask, bottom_mask;
297 uint32_t *bottom_row;
299 uint32_t zero[2] = { 0, 0 };
305 /* reference point is the center of the pixel */
306 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
307 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
308 v.vector[2] = pixman_fixed_1;
310 if (!pixman_transform_point_3d (bits->common.transform, &v))
313 ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
314 x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
316 y = v.vector[1] - pixman_fixed_1/2;
317 disty = (y >> 8) & 0xff;
319 /* Load the pointers to the first and second lines from the source
320 * image that bilinear code must read.
322 * The main trick in this code is about the check if any line are
323 * outside of the image;
325 * When I realize that a line (any one) is outside, I change
326 * the pointer to a dummy area with zeros. Once I change this, I
327 * must be sure the pointer will not change, so I set the
328 * variables to each pointer increments inside the loop.
330 y1 = pixman_fixed_to_int (y);
333 if (y1 < 0 || y1 >= bits->height)
341 top_row = bits->bits + y1 * bits->rowstride;
346 if (y2 < 0 || y2 >= bits->height)
354 bottom_row = bits->bits + y2 * bits->rowstride;
359 /* Instead of checking whether the operation uses the mast in
360 * each loop iteration, verify this only once and prepare the
361 * variables to make the code smaller inside the loop.
365 uint32_t mask_bits = 1;
372 /* If have a mask, prepare the variables to check it */
376 /* If both are zero, then the whole thing is zero */
377 if (top_row == zero && bottom_row == zero)
379 memset (buffer, 0, width * sizeof (uint32_t));
382 else if (bits->format == PIXMAN_x8r8g8b8)
387 bottom_mask = 0xff000000;
389 else if (bottom_row == zero)
391 top_mask = 0xff000000;
396 top_mask = 0xff000000;
397 bottom_mask = 0xff000000;
406 end = buffer + width;
408 /* Zero fill to the left of the image */
409 while (buffer < end && x < pixman_fixed_minus_1)
414 x_bottom += ux_bottom;
420 while (buffer < end && x < 0)
425 tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
426 br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
428 distx = (x >> 8) & 0xff;
430 *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
434 x_bottom += ux_bottom;
439 w = pixman_int_to_fixed (bits->width - 1);
441 while (buffer < end && x < w)
445 uint32_t tl, tr, bl, br;
448 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
449 tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
450 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
451 br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
453 distx = (x >> 8) & 0xff;
455 *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
461 x_bottom += ux_bottom;
466 w = pixman_int_to_fixed (bits->width);
467 while (buffer < end && x < w)
474 tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
475 bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
477 distx = (x >> 8) & 0xff;
479 *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
485 x_bottom += ux_bottom;
489 /* Zero fill to the left of the image */
494 static force_inline uint32_t
495 bits_image_fetch_pixel_convolution (bits_image_t *image,
498 get_pixel_t get_pixel)
500 pixman_fixed_t *params = image->common.filter_params;
501 int x_off = (params[0] - pixman_fixed_1) >> 1;
502 int y_off = (params[1] - pixman_fixed_1) >> 1;
503 int32_t cwidth = pixman_fixed_to_int (params[0]);
504 int32_t cheight = pixman_fixed_to_int (params[1]);
505 int32_t srtot, sgtot, sbtot, satot;
506 int32_t i, j, x1, x2, y1, y2;
507 pixman_repeat_t repeat_mode = image->common.repeat;
508 int width = image->width;
509 int height = image->height;
513 x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
514 y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
518 srtot = sgtot = sbtot = satot = 0;
520 for (i = y1; i < y2; ++i)
522 for (j = x1; j < x2; ++j)
527 pixman_fixed_t f = *params;
533 if (repeat_mode != PIXMAN_REPEAT_NONE)
535 repeat (repeat_mode, width, &rx);
536 repeat (repeat_mode, height, &ry);
538 pixel = get_pixel (image, rx, ry, FALSE);
542 pixel = get_pixel (image, rx, ry, TRUE);
545 srtot += RED_8 (pixel) * f;
546 sgtot += GREEN_8 (pixel) * f;
547 sbtot += BLUE_8 (pixel) * f;
548 satot += ALPHA_8 (pixel) * f;
560 satot = CLIP (satot, 0, 0xff);
561 srtot = CLIP (srtot, 0, 0xff);
562 sgtot = CLIP (sgtot, 0, 0xff);
563 sbtot = CLIP (sbtot, 0, 0xff);
565 return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot));
568 static force_inline uint32_t
569 bits_image_fetch_pixel_filtered (bits_image_t *image,
572 get_pixel_t get_pixel)
574 switch (image->common.filter)
576 case PIXMAN_FILTER_NEAREST:
577 case PIXMAN_FILTER_FAST:
578 return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
581 case PIXMAN_FILTER_BILINEAR:
582 case PIXMAN_FILTER_GOOD:
583 case PIXMAN_FILTER_BEST:
584 return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
587 case PIXMAN_FILTER_CONVOLUTION:
588 return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
599 bits_image_fetch_affine_no_alpha (pixman_image_t * image,
604 const uint32_t * mask)
607 pixman_fixed_t ux, uy;
611 /* reference point is the center of the pixel */
612 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
613 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
614 v.vector[2] = pixman_fixed_1;
616 if (image->common.transform)
618 if (!pixman_transform_point_3d (image->common.transform, &v))
621 ux = image->common.transform->matrix[0][0];
622 uy = image->common.transform->matrix[1][0];
633 for (i = 0; i < width; ++i)
635 if (!mask || mask[i])
637 buffer[i] = bits_image_fetch_pixel_filtered (
638 &image->bits, x, y, fetch_pixel_no_alpha);
646 /* General fetcher */
647 static force_inline uint32_t
648 fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
653 (x < 0 || x >= image->width || y < 0 || y >= image->height))
658 pixel = image->fetch_pixel_32 (image, x, y);
660 if (image->common.alpha_map)
664 x -= image->common.alpha_origin_x;
665 y -= image->common.alpha_origin_y;
667 if (x < 0 || x >= image->common.alpha_map->width ||
668 y < 0 || y >= image->common.alpha_map->height)
674 pixel_a = image->common.alpha_map->fetch_pixel_32 (
675 image->common.alpha_map, x, y);
677 pixel_a = ALPHA_8 (pixel_a);
681 pixel |= (pixel_a << 24);
688 bits_image_fetch_general (pixman_image_t * image,
693 const uint32_t * mask)
695 pixman_fixed_t x, y, w;
696 pixman_fixed_t ux, uy, uw;
700 /* reference point is the center of the pixel */
701 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
702 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
703 v.vector[2] = pixman_fixed_1;
705 if (image->common.transform)
707 if (!pixman_transform_point_3d (image->common.transform, &v))
710 ux = image->common.transform->matrix[0][0];
711 uy = image->common.transform->matrix[1][0];
712 uw = image->common.transform->matrix[2][0];
725 for (i = 0; i < width; ++i)
727 pixman_fixed_t x0, y0;
729 if (!mask || mask[i])
733 x0 = ((pixman_fixed_48_16_t)x << 16) / w;
734 y0 = ((pixman_fixed_48_16_t)y << 16) / w;
742 buffer[i] = bits_image_fetch_pixel_filtered (
743 &image->bits, x0, y0, fetch_pixel_general);
752 static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
754 typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
756 static force_inline void
757 bits_image_fetch_bilinear_affine (pixman_image_t * image,
762 const uint32_t * mask,
764 convert_pixel_t convert_pixel,
765 pixman_format_code_t format,
766 pixman_repeat_t repeat_mode)
769 pixman_fixed_t ux, uy;
771 bits_image_t *bits = &image->bits;
774 /* reference point is the center of the pixel */
775 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
776 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
777 v.vector[2] = pixman_fixed_1;
779 if (!pixman_transform_point_3d (image->common.transform, &v))
782 ux = image->common.transform->matrix[0][0];
783 uy = image->common.transform->matrix[1][0];
788 for (i = 0; i < width; ++i)
791 uint32_t tl, tr, bl, br;
792 int32_t distx, disty;
793 int width = image->bits.width;
794 int height = image->bits.height;
798 if (mask && !mask[i])
801 x1 = x - pixman_fixed_1 / 2;
802 y1 = y - pixman_fixed_1 / 2;
804 distx = (x1 >> 8) & 0xff;
805 disty = (y1 >> 8) & 0xff;
807 y1 = pixman_fixed_to_int (y1);
809 x1 = pixman_fixed_to_int (x1);
812 if (repeat_mode != PIXMAN_REPEAT_NONE)
816 mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
818 repeat (repeat_mode, width, &x1);
819 repeat (repeat_mode, height, &y1);
820 repeat (repeat_mode, width, &x2);
821 repeat (repeat_mode, height, &y2);
823 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
824 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
826 tl = convert_pixel (row1, x1) | mask;
827 tr = convert_pixel (row1, x2) | mask;
828 bl = convert_pixel (row2, x1) | mask;
829 br = convert_pixel (row2, x2) | mask;
833 uint32_t mask1, mask2;
836 /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
837 * which means if you use it in expressions, those
838 * expressions become unsigned themselves. Since
839 * the variables below can be negative in some cases,
840 * that will lead to crashes on 64 bit architectures.
842 * So this line makes sure bpp is signed
844 bpp = PIXMAN_FORMAT_BPP (format);
846 if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
859 row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
860 row1 += bpp / 8 * x1;
862 mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
865 if (y1 == height - 1)
872 row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
873 row2 += bpp / 8 * x1;
875 mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
885 tl = convert_pixel (row1, 0) | mask1;
886 bl = convert_pixel (row2, 0) | mask2;
896 tr = convert_pixel (row1, 1) | mask1;
897 br = convert_pixel (row2, 1) | mask2;
901 buffer[i] = bilinear_interpolation (
902 tl, tr, bl, br, distx, disty);
910 static force_inline void
911 bits_image_fetch_nearest_affine (pixman_image_t * image,
916 const uint32_t * mask,
918 convert_pixel_t convert_pixel,
919 pixman_format_code_t format,
920 pixman_repeat_t repeat_mode)
923 pixman_fixed_t ux, uy;
925 bits_image_t *bits = &image->bits;
928 /* reference point is the center of the pixel */
929 v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
930 v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
931 v.vector[2] = pixman_fixed_1;
933 if (!pixman_transform_point_3d (image->common.transform, &v))
936 ux = image->common.transform->matrix[0][0];
937 uy = image->common.transform->matrix[1][0];
942 for (i = 0; i < width; ++i)
944 int width, height, x0, y0;
947 if (mask && !mask[i])
950 width = image->bits.width;
951 height = image->bits.height;
952 x0 = pixman_fixed_to_int (x - pixman_fixed_e);
953 y0 = pixman_fixed_to_int (y - pixman_fixed_e);
955 if (repeat_mode == PIXMAN_REPEAT_NONE &&
956 (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
962 uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
964 if (repeat_mode != PIXMAN_REPEAT_NONE)
966 repeat (repeat_mode, width, &x0);
967 repeat (repeat_mode, height, &y0);
970 row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;
972 buffer[i] = convert_pixel (row, x0) | mask;
981 static force_inline uint32_t
982 convert_a8r8g8b8 (const uint8_t *row, int x)
984 return *(((uint32_t *)row) + x);
987 static force_inline uint32_t
988 convert_x8r8g8b8 (const uint8_t *row, int x)
990 return *(((uint32_t *)row) + x);
993 static force_inline uint32_t
994 convert_a8 (const uint8_t *row, int x)
996 return *(row + x) << 24;
999 static force_inline uint32_t
1000 convert_r5g6b5 (const uint8_t *row, int x)
1002 return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
1005 #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \
1007 bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image, \
1011 uint32_t * buffer, \
1012 const uint32_t * mask) \
1014 bits_image_fetch_bilinear_affine (image, offset, line, \
1015 width, buffer, mask, \
1016 convert_ ## format, \
1017 PIXMAN_ ## format, \
1021 #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \
1023 bits_image_fetch_nearest_affine_ ## name (pixman_image_t *image, \
1027 uint32_t * buffer, \
1028 const uint32_t * mask) \
1030 bits_image_fetch_nearest_affine (image, offset, line, \
1031 width, buffer, mask, \
1032 convert_ ## format, \
1033 PIXMAN_ ## format, \
1037 #define MAKE_FETCHERS(name, format, repeat_mode) \
1038 MAKE_NEAREST_FETCHER (name, format, repeat_mode) \
1039 MAKE_BILINEAR_FETCHER (name, format, repeat_mode)
1041 MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD)
1042 MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE)
1043 MAKE_FETCHERS (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT)
1044 MAKE_FETCHERS (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL)
1045 MAKE_FETCHERS (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD)
1046 MAKE_FETCHERS (none_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NONE)
1047 MAKE_FETCHERS (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT)
1048 MAKE_FETCHERS (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL)
1049 MAKE_FETCHERS (pad_a8, a8, PIXMAN_REPEAT_PAD)
1050 MAKE_FETCHERS (none_a8, a8, PIXMAN_REPEAT_NONE)
1051 MAKE_FETCHERS (reflect_a8, a8, PIXMAN_REPEAT_REFLECT)
1052 MAKE_FETCHERS (normal_a8, a8, PIXMAN_REPEAT_NORMAL)
1053 MAKE_FETCHERS (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD)
1054 MAKE_FETCHERS (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE)
1055 MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT)
1056 MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL)
1059 bits_image_fetch_solid_32 (pixman_image_t * image,
1064 const uint32_t * mask)
1069 color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
1071 end = buffer + width;
1072 while (buffer < end)
1073 *(buffer++) = color;
1077 bits_image_fetch_solid_64 (pixman_image_t * image,
1082 const uint32_t * unused)
1085 uint64_t *buffer = (uint64_t *)b;
1088 color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
1090 end = buffer + width;
1091 while (buffer < end)
1092 *(buffer++) = color;
1096 bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
1105 if (y < 0 || y >= image->height)
1107 memset (buffer, 0, width * (wide? 8 : 4));
1113 w = MIN (width, -x);
1115 memset (buffer, 0, w * (wide ? 8 : 4));
1118 buffer += w * (wide? 2 : 1);
1122 if (x < image->width)
1124 w = MIN (width, image->width - x);
1127 image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1129 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1132 buffer += w * (wide? 2 : 1);
1136 memset (buffer, 0, width * (wide ? 8 : 4));
1140 bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
1152 while (y >= image->height)
1159 while (x >= image->width)
1162 w = MIN (width, image->width - x);
1165 image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1167 image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1169 buffer += w * (wide? 2 : 1);
1176 bits_image_fetch_untransformed_32 (pixman_image_t * image,
1181 const uint32_t * mask)
1183 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1185 bits_image_fetch_untransformed_repeat_none (
1186 &image->bits, FALSE, x, y, width, buffer);
1190 bits_image_fetch_untransformed_repeat_normal (
1191 &image->bits, FALSE, x, y, width, buffer);
1196 bits_image_fetch_untransformed_64 (pixman_image_t * image,
1201 const uint32_t * unused)
1203 if (image->common.repeat == PIXMAN_REPEAT_NONE)
1205 bits_image_fetch_untransformed_repeat_none (
1206 &image->bits, TRUE, x, y, width, buffer);
1210 bits_image_fetch_untransformed_repeat_normal (
1211 &image->bits, TRUE, x, y, width, buffer);
1217 pixman_format_code_t format;
1219 fetch_scanline_t fetch_32;
1220 fetch_scanline_t fetch_64;
1223 static const fetcher_info_t fetcher_info[] =
1226 FAST_PATH_NO_ALPHA_MAP,
1227 bits_image_fetch_solid_32,
1228 bits_image_fetch_solid_64
1232 (FAST_PATH_NO_ALPHA_MAP |
1233 FAST_PATH_ID_TRANSFORM |
1234 FAST_PATH_NO_CONVOLUTION_FILTER |
1235 FAST_PATH_NO_PAD_REPEAT |
1236 FAST_PATH_NO_REFLECT_REPEAT),
1237 bits_image_fetch_untransformed_32,
1238 bits_image_fetch_untransformed_64
1241 #define FAST_BILINEAR_FLAGS \
1242 (FAST_PATH_NO_ALPHA_MAP | \
1243 FAST_PATH_NO_ACCESSORS | \
1244 FAST_PATH_HAS_TRANSFORM | \
1245 FAST_PATH_AFFINE_TRANSFORM | \
1246 FAST_PATH_X_UNIT_POSITIVE | \
1247 FAST_PATH_Y_UNIT_ZERO | \
1248 FAST_PATH_NONE_REPEAT | \
1249 FAST_PATH_BILINEAR_FILTER)
1252 FAST_BILINEAR_FLAGS,
1253 bits_image_fetch_bilinear_no_repeat_8888,
1254 _pixman_image_get_scanline_generic_64
1258 FAST_BILINEAR_FLAGS,
1259 bits_image_fetch_bilinear_no_repeat_8888,
1260 _pixman_image_get_scanline_generic_64
1263 #define GENERAL_BILINEAR_FLAGS \
1264 (FAST_PATH_NO_ALPHA_MAP | \
1265 FAST_PATH_NO_ACCESSORS | \
1266 FAST_PATH_HAS_TRANSFORM | \
1267 FAST_PATH_AFFINE_TRANSFORM | \
1268 FAST_PATH_BILINEAR_FILTER)
1270 #define GENERAL_NEAREST_FLAGS \
1271 (FAST_PATH_NO_ALPHA_MAP | \
1272 FAST_PATH_NO_ACCESSORS | \
1273 FAST_PATH_HAS_TRANSFORM | \
1274 FAST_PATH_AFFINE_TRANSFORM | \
1275 FAST_PATH_NEAREST_FILTER)
1277 #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1278 { PIXMAN_ ## format, \
1279 GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1280 bits_image_fetch_bilinear_affine_ ## name, \
1281 _pixman_image_get_scanline_generic_64 \
1284 #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
1285 { PIXMAN_ ## format, \
1286 GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \
1287 bits_image_fetch_nearest_affine_ ## name, \
1288 _pixman_image_get_scanline_generic_64 \
1291 #define AFFINE_FAST_PATHS(name, format, repeat) \
1292 BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
1293 NEAREST_AFFINE_FAST_PATH(name, format, repeat)
1295 AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
1296 AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
1297 AFFINE_FAST_PATHS (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
1298 AFFINE_FAST_PATHS (normal_a8r8g8b8, a8r8g8b8, NORMAL)
1299 AFFINE_FAST_PATHS (pad_x8r8g8b8, x8r8g8b8, PAD)
1300 AFFINE_FAST_PATHS (none_x8r8g8b8, x8r8g8b8, NONE)
1301 AFFINE_FAST_PATHS (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
1302 AFFINE_FAST_PATHS (normal_x8r8g8b8, x8r8g8b8, NORMAL)
1303 AFFINE_FAST_PATHS (pad_a8, a8, PAD)
1304 AFFINE_FAST_PATHS (none_a8, a8, NONE)
1305 AFFINE_FAST_PATHS (reflect_a8, a8, REFLECT)
1306 AFFINE_FAST_PATHS (normal_a8, a8, NORMAL)
1307 AFFINE_FAST_PATHS (pad_r5g6b5, r5g6b5, PAD)
1308 AFFINE_FAST_PATHS (none_r5g6b5, r5g6b5, NONE)
1309 AFFINE_FAST_PATHS (reflect_r5g6b5, r5g6b5, REFLECT)
1310 AFFINE_FAST_PATHS (normal_r5g6b5, r5g6b5, NORMAL)
1312 /* Affine, no alpha */
1314 (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
1315 bits_image_fetch_affine_no_alpha,
1316 _pixman_image_get_scanline_generic_64
1320 { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
1326 bits_image_property_changed (pixman_image_t *image)
1328 uint32_t flags = image->common.flags;
1329 pixman_format_code_t format = image->common.extended_format_code;
1330 const fetcher_info_t *info;
1332 _pixman_bits_image_setup_accessors (&image->bits);
1334 info = fetcher_info;
1335 while (info->format != PIXMAN_null)
1337 if ((info->format == format || info->format == PIXMAN_any) &&
1338 (info->flags & flags) == info->flags)
1340 image->common.get_scanline_32 = info->fetch_32;
1341 image->common.get_scanline_64 = info->fetch_64;
1350 create_bits (pixman_format_code_t format,
1353 int * rowstride_bytes)
1359 /* what follows is a long-winded way, avoiding any possibility of integer
1360 * overflows, of saying:
1361 * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
1364 bpp = PIXMAN_FORMAT_BPP (format);
1365 if (pixman_multiply_overflows_int (width, bpp))
1368 stride = width * bpp;
1369 if (pixman_addition_overflows_int (stride, 0x1f))
1375 stride *= sizeof (uint32_t);
1377 if (pixman_multiply_overflows_int (height, stride))
1380 buf_size = height * stride;
1382 if (rowstride_bytes)
1383 *rowstride_bytes = stride;
1385 return calloc (buf_size, 1);
1388 PIXMAN_EXPORT pixman_image_t *
1389 pixman_image_create_bits (pixman_format_code_t format,
1393 int rowstride_bytes)
1395 pixman_image_t *image;
1396 uint32_t *free_me = NULL;
1398 /* must be a whole number of uint32_t's
1400 return_val_if_fail (
1401 bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1403 return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1405 if (!bits && width && height)
1407 free_me = bits = create_bits (format, width, height, &rowstride_bytes);
1412 image = _pixman_image_allocate ();
1423 image->bits.format = format;
1424 image->bits.width = width;
1425 image->bits.height = height;
1426 image->bits.bits = bits;
1427 image->bits.free_me = free_me;
1428 image->bits.read_func = NULL;
1429 image->bits.write_func = NULL;
1431 /* The rowstride is stored in number of uint32_t */
1432 image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1434 image->bits.indexed = NULL;
1436 image->common.property_changed = bits_image_property_changed;
1438 _pixman_image_reset_clip_region (image);