3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4 * 2005 Lars Knoll & Zack Rusin, Trolltech
5 * 2008 Aaron Plattner, NVIDIA Corporation
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Keith Packard not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Keith Packard makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
36 #include "pixman-accessor.h"
37 #include "pixman-private.h"
39 #define CONVERT_RGB24_TO_Y15(s) \
40 (((((s) >> 16) & 0xff) * 153 + \
41 (((s) >> 8) & 0xff) * 301 + \
42 (((s) ) & 0xff) * 58) >> 2)
44 #define CONVERT_RGB24_TO_RGB15(s) \
45 ((((s) >> 3) & 0x001f) | \
46 (((s) >> 6) & 0x03e0) | \
47 (((s) >> 9) & 0x7c00))
51 #ifdef WORDS_BIGENDIAN
52 #define FETCH_1(img,l,o) \
53 (((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> (0x1f - ((o) & 0x1f))) & 0x1)
55 #define FETCH_1(img,l,o) \
56 ((((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> ((o) & 0x1f))) & 0x1)
59 #define FETCH_8(img,l,o) (READ (img, (((uint8_t *)(l)) + ((o) >> 3))))
61 #ifdef WORDS_BIGENDIAN
62 #define FETCH_4(img,l,o) \
63 (((4 * (o)) & 4) ? (FETCH_8 (img,l, 4 * (o)) & 0xf) : (FETCH_8 (img,l,(4 * (o))) >> 4))
65 #define FETCH_4(img,l,o) \
66 (((4 * (o)) & 4) ? (FETCH_8 (img, l, 4 * (o)) >> 4) : (FETCH_8 (img, l, (4 * (o))) & 0xf))
69 #ifdef WORDS_BIGENDIAN
70 #define FETCH_24(img,l,o) \
71 ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16) | \
72 (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
73 (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
75 #define FETCH_24(img,l,o) \
76 ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0) | \
77 (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8) | \
78 (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16))
83 #ifdef WORDS_BIGENDIAN
84 #define STORE_1(img,l,o,v) \
87 uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \
90 __m = 1 << (0x1f - ((o) & 0x1f)); \
93 WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \
97 #define STORE_1(img,l,o,v) \
100 uint32_t *__d = ((uint32_t *)(l)) + ((o) >> 5); \
103 __m = 1 << ((o) & 0x1f); \
104 __v = (v)? __m : 0; \
106 WRITE((img), __d, (READ((img), __d) & ~__m) | __v); \
111 #define STORE_8(img,l,o,v) (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v)))
113 #ifdef WORDS_BIGENDIAN
114 #define STORE_4(img,l,o,v) \
118 int v4 = (v) & 0x0f; \
120 STORE_8 (img, l, bo, ( \
122 (FETCH_8 (img, l, bo) & 0xf0) | (v4) : \
123 (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4))); \
126 #define STORE_4(img,l,o,v) \
130 int v4 = (v) & 0x0f; \
132 STORE_8 (img, l, bo, ( \
134 (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) : \
135 (FETCH_8 (img, l, bo) & 0xf0) | (v4))); \
139 #ifdef WORDS_BIGENDIAN
140 #define STORE_24(img,l,o,v) \
143 uint8_t *__tmp = (l) + 3 * (o); \
145 WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16); \
146 WRITE ((img), __tmp++, ((v) & 0x0000ff00) >> 8); \
147 WRITE ((img), __tmp++, ((v) & 0x000000ff) >> 0); \
151 #define STORE_24(img,l,o,v) \
154 uint8_t *__tmp = (l) + 3 * (o); \
156 WRITE ((img), __tmp++, ((v) & 0x000000ff) >> 0); \
157 WRITE ((img), __tmp++, ((v) & 0x0000ff00) >> 8); \
158 WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16); \
164 * YV12 setup and access macros
167 #define YV12_SETUP(image) \
168 bits_image_t *__bits_image = (bits_image_t *)image; \
169 uint32_t *bits = __bits_image->bits; \
170 int stride = __bits_image->rowstride; \
171 int offset0 = stride < 0 ? \
172 ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride : \
173 stride * __bits_image->height; \
174 int offset1 = stride < 0 ? \
175 offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) : \
176 offset0 + (offset0 >> 2)
178 /* Note no trailing semicolon on the above macro; if it's there, then
179 * the typical usage of YV12_SETUP(image); will have an extra trailing ;
180 * that some compilers will interpret as a statement -- and then any further
181 * variable declarations will cause an error.
184 #define YV12_Y(line) \
185 ((uint8_t *) ((bits) + (stride) * (line)))
187 #define YV12_U(line) \
188 ((uint8_t *) ((bits) + offset1 + \
189 ((stride) >> 1) * ((line) >> 1)))
191 #define YV12_V(line) \
192 ((uint8_t *) ((bits) + offset0 + \
193 ((stride) >> 1) * ((line) >> 1)))
197 static force_inline void
198 get_shifts (pixman_format_code_t format,
204 switch (PIXMAN_FORMAT_TYPE (format))
213 case PIXMAN_TYPE_ARGB:
214 case PIXMAN_TYPE_ARGB_SRGB:
216 *g = *b + PIXMAN_FORMAT_B (format);
217 *r = *g + PIXMAN_FORMAT_G (format);
218 *a = *r + PIXMAN_FORMAT_R (format);
221 case PIXMAN_TYPE_ABGR:
223 *g = *r + PIXMAN_FORMAT_R (format);
224 *b = *g + PIXMAN_FORMAT_G (format);
225 *a = *b + PIXMAN_FORMAT_B (format);
228 case PIXMAN_TYPE_BGRA:
229 /* With BGRA formats we start counting at the high end of the pixel */
230 *b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
231 *g = *b - PIXMAN_FORMAT_B (format);
232 *r = *g - PIXMAN_FORMAT_G (format);
233 *a = *r - PIXMAN_FORMAT_R (format);
236 case PIXMAN_TYPE_RGBA:
237 /* With BGRA formats we start counting at the high end of the pixel */
238 *r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
239 *g = *r - PIXMAN_FORMAT_R (format);
240 *b = *g - PIXMAN_FORMAT_G (format);
241 *a = *b - PIXMAN_FORMAT_B (format);
250 static force_inline uint32_t
251 convert_channel (uint32_t pixel, uint32_t def_value,
252 int n_from_bits, int from_shift,
253 int n_to_bits, int to_shift)
257 if (n_from_bits && n_to_bits)
258 v = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits);
264 return (v & ((1 << n_to_bits) - 1)) << to_shift;
267 static force_inline uint32_t
268 convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel)
270 int a_from_shift, r_from_shift, g_from_shift, b_from_shift;
271 int a_to_shift, r_to_shift, g_to_shift, b_to_shift;
274 get_shifts (from, &a_from_shift, &r_from_shift, &g_from_shift, &b_from_shift);
275 get_shifts (to, &a_to_shift, &r_to_shift, &g_to_shift, &b_to_shift);
277 a = convert_channel (pixel, ~0,
278 PIXMAN_FORMAT_A (from), a_from_shift,
279 PIXMAN_FORMAT_A (to), a_to_shift);
281 r = convert_channel (pixel, 0,
282 PIXMAN_FORMAT_R (from), r_from_shift,
283 PIXMAN_FORMAT_R (to), r_to_shift);
285 g = convert_channel (pixel, 0,
286 PIXMAN_FORMAT_G (from), g_from_shift,
287 PIXMAN_FORMAT_G (to), g_to_shift);
289 b = convert_channel (pixel, 0,
290 PIXMAN_FORMAT_B (from), b_from_shift,
291 PIXMAN_FORMAT_B (to), b_to_shift);
293 return a | r | g | b;
296 static force_inline uint32_t
297 convert_pixel_to_a8r8g8b8 (bits_image_t *image,
298 pixman_format_code_t format,
301 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY ||
302 PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
304 return image->indexed->rgba[pixel];
308 return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
312 static force_inline uint32_t
313 convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
314 pixman_format_code_t format, uint32_t pixel)
316 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
318 pixel = CONVERT_RGB24_TO_Y15 (pixel);
320 return image->bits.indexed->ent[pixel & 0x7fff];
322 else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
324 pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel);
326 return image->bits.indexed->ent[pixel & 0x7fff];
330 return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
334 static force_inline uint32_t
335 fetch_and_convert_pixel (bits_image_t * image,
336 const uint8_t * bits,
338 pixman_format_code_t format)
342 switch (PIXMAN_FORMAT_BPP (format))
345 pixel = FETCH_1 (image, bits, offset);
349 pixel = FETCH_4 (image, bits, offset);
353 pixel = READ (image, bits + offset);
357 pixel = READ (image, ((uint16_t *)bits + offset));
361 pixel = FETCH_24 (image, bits, offset);
365 pixel = READ (image, ((uint32_t *)bits + offset));
369 pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
373 return convert_pixel_to_a8r8g8b8 (image, format, pixel);
376 static force_inline void
377 convert_and_store_pixel (bits_image_t * image,
380 pixman_format_code_t format,
383 uint32_t converted = convert_pixel_from_a8r8g8b8 (
384 (pixman_image_t *)image, format, pixel);
386 switch (PIXMAN_FORMAT_BPP (format))
389 STORE_1 (image, dest, offset, converted & 0x01);
393 STORE_4 (image, dest, offset, converted & 0xf);
397 WRITE (image, (dest + offset), converted & 0xff);
401 WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
405 STORE_24 (image, dest, offset, converted);
409 WRITE (image, ((uint32_t *)dest + offset), converted);
418 #define MAKE_ACCESSORS(format) \
420 fetch_scanline_ ## format (bits_image_t *image, \
425 const uint32_t *mask) \
428 (uint8_t *)(image->bits + y * image->rowstride); \
431 for (i = 0; i < width; ++i) \
434 fetch_and_convert_pixel (image, bits, x + i, PIXMAN_ ## format); \
439 store_scanline_ ## format (bits_image_t * image, \
443 const uint32_t *values) \
446 (uint8_t *)(image->bits + y * image->rowstride); \
449 for (i = 0; i < width; ++i) \
451 convert_and_store_pixel ( \
452 image, dest, i + x, PIXMAN_ ## format, values[i]); \
457 fetch_pixel_ ## format (bits_image_t *image, \
462 (uint8_t *)(image->bits + line * image->rowstride); \
464 return fetch_and_convert_pixel ( \
465 image, bits, offset, PIXMAN_ ## format); \
468 static const void *const __dummy__ ## format
470 MAKE_ACCESSORS(a8r8g8b8);
471 MAKE_ACCESSORS(x8r8g8b8);
472 MAKE_ACCESSORS(a8b8g8r8);
473 MAKE_ACCESSORS(x8b8g8r8);
474 MAKE_ACCESSORS(x14r6g6b6);
475 MAKE_ACCESSORS(b8g8r8a8);
476 MAKE_ACCESSORS(b8g8r8x8);
477 MAKE_ACCESSORS(r8g8b8x8);
478 MAKE_ACCESSORS(r8g8b8a8);
479 MAKE_ACCESSORS(r8g8b8);
480 MAKE_ACCESSORS(b8g8r8);
481 MAKE_ACCESSORS(r5g6b5);
482 MAKE_ACCESSORS(b5g6r5);
483 MAKE_ACCESSORS(a1r5g5b5);
484 MAKE_ACCESSORS(x1r5g5b5);
485 MAKE_ACCESSORS(a1b5g5r5);
486 MAKE_ACCESSORS(x1b5g5r5);
487 MAKE_ACCESSORS(a4r4g4b4);
488 MAKE_ACCESSORS(x4r4g4b4);
489 MAKE_ACCESSORS(a4b4g4r4);
490 MAKE_ACCESSORS(x4b4g4r4);
494 MAKE_ACCESSORS(r3g3b2);
495 MAKE_ACCESSORS(b2g3r3);
496 MAKE_ACCESSORS(a2r2g2b2);
497 MAKE_ACCESSORS(a2b2g2r2);
498 MAKE_ACCESSORS(x4a4);
502 MAKE_ACCESSORS(r1g2b1);
503 MAKE_ACCESSORS(b1g2r1);
504 MAKE_ACCESSORS(a1r1g1b1);
505 MAKE_ACCESSORS(a1b1g1r1);
509 /********************************** Fetch ************************************/
510 /* Table mapping sRGB-encoded 8 bit numbers to linearly encoded
511 * floating point numbers. We assume that single precision
512 * floating point follows the IEEE 754 format.
514 static const uint32_t to_linear_u[256] =
516 0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61,
517 0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a,
518 0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d,
519 0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152,
520 0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43,
521 0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e,
522 0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601,
523 0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9,
524 0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae,
525 0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380,
526 0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466,
527 0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65,
528 0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48,
529 0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728,
530 0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4,
531 0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16,
532 0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f,
533 0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50,
534 0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a,
535 0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702,
536 0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027,
537 0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf,
538 0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0,
539 0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281,
540 0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0,
541 0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a,
542 0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15,
543 0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14,
544 0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508,
545 0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64,
546 0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594,
547 0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8,
548 0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65,
549 0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237,
550 0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c,
551 0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680,
552 0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24,
553 0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e,
554 0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8,
555 0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de,
556 0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6,
557 0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae,
558 0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000
561 static const float * const to_linear = (const float *)to_linear_u;
569 while (high - low > 1)
571 uint8_t mid = (low + high) / 2;
573 if (to_linear[mid] > f)
579 if (to_linear[high] - f < f - to_linear[low])
586 fetch_scanline_a8r8g8b8_sRGB_float (bits_image_t * image,
591 const uint32_t *mask)
593 const uint32_t *bits = image->bits + y * image->rowstride;
594 const uint32_t *pixel = bits + x;
595 const uint32_t *end = pixel + width;
596 argb_t *buffer = (argb_t *)b;
600 uint32_t p = READ (image, pixel++);
601 argb_t *argb = buffer;
603 argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
605 argb->r = to_linear [(p >> 16) & 0xff];
606 argb->g = to_linear [(p >> 8) & 0xff];
607 argb->b = to_linear [(p >> 0) & 0xff];
613 /* Expects a float buffer */
615 fetch_scanline_a2r10g10b10_float (bits_image_t * image,
620 const uint32_t *mask)
622 const uint32_t *bits = image->bits + y * image->rowstride;
623 const uint32_t *pixel = bits + x;
624 const uint32_t *end = pixel + width;
625 argb_t *buffer = (argb_t *)b;
629 uint32_t p = READ (image, pixel++);
630 uint64_t a = p >> 30;
631 uint64_t r = (p >> 20) & 0x3ff;
632 uint64_t g = (p >> 10) & 0x3ff;
633 uint64_t b = p & 0x3ff;
635 buffer->a = pixman_unorm_to_float (a, 2);
636 buffer->r = pixman_unorm_to_float (r, 10);
637 buffer->g = pixman_unorm_to_float (g, 10);
638 buffer->b = pixman_unorm_to_float (b, 10);
644 /* Expects a float buffer */
646 fetch_scanline_x2r10g10b10_float (bits_image_t *image,
651 const uint32_t *mask)
653 const uint32_t *bits = image->bits + y * image->rowstride;
654 const uint32_t *pixel = (uint32_t *)bits + x;
655 const uint32_t *end = pixel + width;
656 argb_t *buffer = (argb_t *)b;
660 uint32_t p = READ (image, pixel++);
661 uint64_t r = (p >> 20) & 0x3ff;
662 uint64_t g = (p >> 10) & 0x3ff;
663 uint64_t b = p & 0x3ff;
666 buffer->r = pixman_unorm_to_float (r, 10);
667 buffer->g = pixman_unorm_to_float (g, 10);
668 buffer->b = pixman_unorm_to_float (b, 10);
674 /* Expects a float buffer */
676 fetch_scanline_a2b10g10r10_float (bits_image_t *image,
681 const uint32_t *mask)
683 const uint32_t *bits = image->bits + y * image->rowstride;
684 const uint32_t *pixel = bits + x;
685 const uint32_t *end = pixel + width;
686 argb_t *buffer = (argb_t *)b;
690 uint32_t p = READ (image, pixel++);
691 uint64_t a = p >> 30;
692 uint64_t b = (p >> 20) & 0x3ff;
693 uint64_t g = (p >> 10) & 0x3ff;
694 uint64_t r = p & 0x3ff;
696 buffer->a = pixman_unorm_to_float (a, 2);
697 buffer->r = pixman_unorm_to_float (r, 10);
698 buffer->g = pixman_unorm_to_float (g, 10);
699 buffer->b = pixman_unorm_to_float (b, 10);
705 /* Expects a float buffer */
707 fetch_scanline_x2b10g10r10_float (bits_image_t *image,
712 const uint32_t *mask)
714 const uint32_t *bits = image->bits + y * image->rowstride;
715 const uint32_t *pixel = (uint32_t *)bits + x;
716 const uint32_t *end = pixel + width;
717 argb_t *buffer = (argb_t *)b;
721 uint32_t p = READ (image, pixel++);
722 uint64_t b = (p >> 20) & 0x3ff;
723 uint64_t g = (p >> 10) & 0x3ff;
724 uint64_t r = p & 0x3ff;
727 buffer->r = pixman_unorm_to_float (r, 10);
728 buffer->g = pixman_unorm_to_float (g, 10);
729 buffer->b = pixman_unorm_to_float (b, 10);
736 fetch_scanline_yuy2 (bits_image_t *image,
741 const uint32_t *mask)
743 const uint32_t *bits = image->bits + image->rowstride * line;
746 for (i = 0; i < width; i++)
751 y = ((uint8_t *) bits)[(x + i) << 1] - 16;
752 u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
753 v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
755 /* R = 1.164(Y - 16) + 1.596(V - 128) */
756 r = 0x012b27 * y + 0x019a2e * v;
757 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
758 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
759 /* B = 1.164(Y - 16) + 2.018(U - 128) */
760 b = 0x012b27 * y + 0x0206a2 * u;
762 *buffer++ = 0xff000000 |
763 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
764 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
765 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
770 fetch_scanline_yv12 (bits_image_t *image,
775 const uint32_t *mask)
778 uint8_t *y_line = YV12_Y (line);
779 uint8_t *u_line = YV12_U (line);
780 uint8_t *v_line = YV12_V (line);
783 for (i = 0; i < width; i++)
788 y = y_line[x + i] - 16;
789 u = u_line[(x + i) >> 1] - 128;
790 v = v_line[(x + i) >> 1] - 128;
792 /* R = 1.164(Y - 16) + 1.596(V - 128) */
793 r = 0x012b27 * y + 0x019a2e * v;
794 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
795 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
796 /* B = 1.164(Y - 16) + 2.018(U - 128) */
797 b = 0x012b27 * y + 0x0206a2 * u;
799 *buffer++ = 0xff000000 |
800 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
801 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
802 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
806 /**************************** Pixel wise fetching *****************************/
809 fetch_pixel_x2r10g10b10_float (bits_image_t *image,
813 uint32_t *bits = image->bits + line * image->rowstride;
814 uint32_t p = READ (image, bits + offset);
815 uint64_t r = (p >> 20) & 0x3ff;
816 uint64_t g = (p >> 10) & 0x3ff;
817 uint64_t b = p & 0x3ff;
821 argb.r = pixman_unorm_to_float (r, 10);
822 argb.g = pixman_unorm_to_float (g, 10);
823 argb.b = pixman_unorm_to_float (b, 10);
829 fetch_pixel_a2r10g10b10_float (bits_image_t *image,
833 uint32_t *bits = image->bits + line * image->rowstride;
834 uint32_t p = READ (image, bits + offset);
835 uint64_t a = p >> 30;
836 uint64_t r = (p >> 20) & 0x3ff;
837 uint64_t g = (p >> 10) & 0x3ff;
838 uint64_t b = p & 0x3ff;
841 argb.a = pixman_unorm_to_float (a, 2);
842 argb.r = pixman_unorm_to_float (r, 10);
843 argb.g = pixman_unorm_to_float (g, 10);
844 argb.b = pixman_unorm_to_float (b, 10);
850 fetch_pixel_a2b10g10r10_float (bits_image_t *image,
854 uint32_t *bits = image->bits + line * image->rowstride;
855 uint32_t p = READ (image, bits + offset);
856 uint64_t a = p >> 30;
857 uint64_t b = (p >> 20) & 0x3ff;
858 uint64_t g = (p >> 10) & 0x3ff;
859 uint64_t r = p & 0x3ff;
862 argb.a = pixman_unorm_to_float (a, 2);
863 argb.r = pixman_unorm_to_float (r, 10);
864 argb.g = pixman_unorm_to_float (g, 10);
865 argb.b = pixman_unorm_to_float (b, 10);
871 fetch_pixel_x2b10g10r10_float (bits_image_t *image,
875 uint32_t *bits = image->bits + line * image->rowstride;
876 uint32_t p = READ (image, bits + offset);
877 uint64_t b = (p >> 20) & 0x3ff;
878 uint64_t g = (p >> 10) & 0x3ff;
879 uint64_t r = p & 0x3ff;
883 argb.r = pixman_unorm_to_float (r, 10);
884 argb.g = pixman_unorm_to_float (g, 10);
885 argb.b = pixman_unorm_to_float (b, 10);
891 fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
895 uint32_t *bits = image->bits + line * image->rowstride;
896 uint32_t p = READ (image, bits + offset);
899 argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
901 argb.r = to_linear [(p >> 16) & 0xff];
902 argb.g = to_linear [(p >> 8) & 0xff];
903 argb.b = to_linear [(p >> 0) & 0xff];
909 fetch_pixel_yuy2 (bits_image_t *image,
913 const uint32_t *bits = image->bits + image->rowstride * line;
918 y = ((uint8_t *) bits)[offset << 1] - 16;
919 u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
920 v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
922 /* R = 1.164(Y - 16) + 1.596(V - 128) */
923 r = 0x012b27 * y + 0x019a2e * v;
925 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
926 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
928 /* B = 1.164(Y - 16) + 2.018(U - 128) */
929 b = 0x012b27 * y + 0x0206a2 * u;
932 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
933 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
934 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
938 fetch_pixel_yv12 (bits_image_t *image,
943 int16_t y = YV12_Y (line)[offset] - 16;
944 int16_t u = YV12_U (line)[offset >> 1] - 128;
945 int16_t v = YV12_V (line)[offset >> 1] - 128;
948 /* R = 1.164(Y - 16) + 1.596(V - 128) */
949 r = 0x012b27 * y + 0x019a2e * v;
951 /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
952 g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
954 /* B = 1.164(Y - 16) + 2.018(U - 128) */
955 b = 0x012b27 * y + 0x0206a2 * u;
958 (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
959 (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
960 (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
963 /*********************************** Store ************************************/
966 store_scanline_a2r10g10b10_float (bits_image_t * image,
972 uint32_t *bits = image->bits + image->rowstride * y;
973 uint32_t *pixel = bits + x;
974 argb_t *values = (argb_t *)v;
977 for (i = 0; i < width; ++i)
981 a = pixman_float_to_unorm (values[i].a, 2);
982 r = pixman_float_to_unorm (values[i].r, 10);
983 g = pixman_float_to_unorm (values[i].g, 10);
984 b = pixman_float_to_unorm (values[i].b, 10);
986 WRITE (image, pixel++,
987 (a << 30) | (r << 20) | (g << 10) | b);
992 store_scanline_x2r10g10b10_float (bits_image_t * image,
998 uint32_t *bits = image->bits + image->rowstride * y;
999 uint32_t *pixel = bits + x;
1000 argb_t *values = (argb_t *)v;
1003 for (i = 0; i < width; ++i)
1007 r = pixman_float_to_unorm (values[i].r, 10);
1008 g = pixman_float_to_unorm (values[i].g, 10);
1009 b = pixman_float_to_unorm (values[i].b, 10);
1011 WRITE (image, pixel++,
1012 (r << 20) | (g << 10) | b);
1017 store_scanline_a2b10g10r10_float (bits_image_t * image,
1023 uint32_t *bits = image->bits + image->rowstride * y;
1024 uint32_t *pixel = bits + x;
1025 argb_t *values = (argb_t *)v;
1028 for (i = 0; i < width; ++i)
1030 uint16_t a, r, g, b;
1032 a = pixman_float_to_unorm (values[i].a, 2);
1033 r = pixman_float_to_unorm (values[i].r, 10);
1034 g = pixman_float_to_unorm (values[i].g, 10);
1035 b = pixman_float_to_unorm (values[i].b, 10);
1037 WRITE (image, pixel++,
1038 (a << 30) | (b << 20) | (g << 10) | r);
1043 store_scanline_x2b10g10r10_float (bits_image_t * image,
1049 uint32_t *bits = image->bits + image->rowstride * y;
1050 uint32_t *pixel = bits + x;
1051 argb_t *values = (argb_t *)v;
1054 for (i = 0; i < width; ++i)
1058 r = pixman_float_to_unorm (values[i].r, 10);
1059 g = pixman_float_to_unorm (values[i].g, 10);
1060 b = pixman_float_to_unorm (values[i].b, 10);
1062 WRITE (image, pixel++,
1063 (b << 20) | (g << 10) | r);
1068 store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image,
1074 uint32_t *bits = image->bits + image->rowstride * y;
1075 uint32_t *pixel = bits + x;
1076 argb_t *values = (argb_t *)v;
1079 for (i = 0; i < width; ++i)
1083 a = pixman_float_to_unorm (values[i].a, 8);
1084 r = to_srgb (values[i].r);
1085 g = to_srgb (values[i].g);
1086 b = to_srgb (values[i].b);
1088 WRITE (image, pixel++,
1089 (a << 24) | (r << 16) | (g << 8) | b);
1094 * Contracts a floating point image to 32bpp and then stores it using a
1095 * regular 32-bit store proc. Despite the type, this function expects an
1099 store_scanline_generic_float (bits_image_t * image,
1103 const uint32_t *values)
1105 uint32_t *argb8_pixels;
1107 assert (image->common.type == BITS);
1109 argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1113 /* Contract the scanline. We could do this in place if values weren't
1116 pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1118 image->store_scanline_32 (image, x, y, width, argb8_pixels);
1120 free (argb8_pixels);
1124 fetch_scanline_generic_float (bits_image_t * image,
1129 const uint32_t *mask)
1131 image->fetch_scanline_32 (image, x, y, width, buffer, NULL);
1133 pixman_expand_to_float ((argb_t *)buffer, buffer, image->format, width);
1136 /* The 32_sRGB paths should be deleted after narrow processing
1137 * is no longer invoked for formats that are considered wide.
1138 * (Also see fetch_pixel_generic_lossy_32) */
1140 fetch_scanline_a8r8g8b8_32_sRGB (bits_image_t *image,
1145 const uint32_t *mask)
1147 const uint32_t *bits = image->bits + y * image->rowstride;
1148 const uint32_t *pixel = (uint32_t *)bits + x;
1149 const uint32_t *end = pixel + width;
1156 tmp = READ (image, pixel++);
1158 a = (tmp >> 24) & 0xff;
1159 r = (tmp >> 16) & 0xff;
1160 g = (tmp >> 8) & 0xff;
1161 b = (tmp >> 0) & 0xff;
1163 r = to_linear[r] * 255.0f + 0.5f;
1164 g = to_linear[g] * 255.0f + 0.5f;
1165 b = to_linear[b] * 255.0f + 0.5f;
1167 *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1172 fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1176 uint32_t *bits = image->bits + line * image->rowstride;
1177 uint32_t tmp = READ (image, bits + offset);
1180 a = (tmp >> 24) & 0xff;
1181 r = (tmp >> 16) & 0xff;
1182 g = (tmp >> 8) & 0xff;
1183 b = (tmp >> 0) & 0xff;
1185 r = to_linear[r] * 255.0f + 0.5f;
1186 g = to_linear[g] * 255.0f + 0.5f;
1187 b = to_linear[b] * 255.0f + 0.5f;
1189 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1193 store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image,
1199 uint32_t *bits = image->bits + image->rowstride * y;
1200 uint64_t *values = (uint64_t *)v;
1201 uint32_t *pixel = bits + x;
1205 for (i = 0; i < width; ++i)
1211 a = (tmp >> 24) & 0xff;
1212 r = (tmp >> 16) & 0xff;
1213 g = (tmp >> 8) & 0xff;
1214 b = (tmp >> 0) & 0xff;
1216 r = to_srgb (r * (1/255.0f));
1217 g = to_srgb (g * (1/255.0f));
1218 b = to_srgb (b * (1/255.0f));
1220 WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1225 fetch_pixel_generic_float (bits_image_t *image,
1229 uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1232 pixman_expand_to_float (&f, &pixel32, image->format, 1);
1238 * XXX: The transformed fetch path only works at 32-bpp so far. When all
1239 * paths have wide versions, this can be removed.
1241 * WARNING: This function loses precision!
1244 fetch_pixel_generic_lossy_32 (bits_image_t *image,
1248 argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1251 pixman_contract_from_float (&result, &pixel64, 1);
1258 pixman_format_code_t format;
1259 fetch_scanline_t fetch_scanline_32;
1260 fetch_scanline_t fetch_scanline_float;
1261 fetch_pixel_32_t fetch_pixel_32;
1262 fetch_pixel_float_t fetch_pixel_float;
1263 store_scanline_t store_scanline_32;
1264 store_scanline_t store_scanline_float;
1267 #define FORMAT_INFO(format) \
1269 PIXMAN_ ## format, \
1270 fetch_scanline_ ## format, \
1271 fetch_scanline_generic_float, \
1272 fetch_pixel_ ## format, \
1273 fetch_pixel_generic_float, \
1274 store_scanline_ ## format, \
1275 store_scanline_generic_float \
1278 static const format_info_t accessors[] =
1280 /* 32 bpp formats */
1281 FORMAT_INFO (a8r8g8b8),
1282 FORMAT_INFO (x8r8g8b8),
1283 FORMAT_INFO (a8b8g8r8),
1284 FORMAT_INFO (x8b8g8r8),
1285 FORMAT_INFO (b8g8r8a8),
1286 FORMAT_INFO (b8g8r8x8),
1287 FORMAT_INFO (r8g8b8a8),
1288 FORMAT_INFO (r8g8b8x8),
1289 FORMAT_INFO (x14r6g6b6),
1292 { PIXMAN_a8r8g8b8_sRGB,
1293 fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
1294 fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
1295 store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
1299 FORMAT_INFO (r8g8b8),
1300 FORMAT_INFO (b8g8r8),
1303 FORMAT_INFO (r5g6b5),
1304 FORMAT_INFO (b5g6r5),
1306 FORMAT_INFO (a1r5g5b5),
1307 FORMAT_INFO (x1r5g5b5),
1308 FORMAT_INFO (a1b5g5r5),
1309 FORMAT_INFO (x1b5g5r5),
1310 FORMAT_INFO (a4r4g4b4),
1311 FORMAT_INFO (x4r4g4b4),
1312 FORMAT_INFO (a4b4g4r4),
1313 FORMAT_INFO (x4b4g4r4),
1317 FORMAT_INFO (r3g3b2),
1318 FORMAT_INFO (b2g3r3),
1319 FORMAT_INFO (a2r2g2b2),
1320 FORMAT_INFO (a2b2g2r2),
1326 #define fetch_scanline_x4c4 fetch_scanline_c8
1327 #define fetch_pixel_x4c4 fetch_pixel_c8
1328 #define store_scanline_x4c4 store_scanline_c8
1331 #define fetch_scanline_x4g4 fetch_scanline_g8
1332 #define fetch_pixel_x4g4 fetch_pixel_g8
1333 #define store_scanline_x4g4 store_scanline_g8
1340 FORMAT_INFO (r1g2b1),
1341 FORMAT_INFO (b1g2r1),
1342 FORMAT_INFO (a1r1g1b1),
1343 FORMAT_INFO (a1b1g1r1),
1355 { PIXMAN_a2r10g10b10,
1356 NULL, fetch_scanline_a2r10g10b10_float,
1357 fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
1358 NULL, store_scanline_a2r10g10b10_float },
1360 { PIXMAN_x2r10g10b10,
1361 NULL, fetch_scanline_x2r10g10b10_float,
1362 fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
1363 NULL, store_scanline_x2r10g10b10_float },
1365 { PIXMAN_a2b10g10r10,
1366 NULL, fetch_scanline_a2b10g10r10_float,
1367 fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
1368 NULL, store_scanline_a2b10g10r10_float },
1370 { PIXMAN_x2b10g10r10,
1371 NULL, fetch_scanline_x2b10g10r10_float,
1372 fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
1373 NULL, store_scanline_x2b10g10r10_float },
1377 fetch_scanline_yuy2, fetch_scanline_generic_float,
1378 fetch_pixel_yuy2, fetch_pixel_generic_float,
1382 fetch_scanline_yv12, fetch_scanline_generic_float,
1383 fetch_pixel_yv12, fetch_pixel_generic_float,
1390 setup_accessors (bits_image_t *image)
1392 const format_info_t *info = accessors;
1394 while (info->format != PIXMAN_null)
1396 if (info->format == image->format)
1398 image->fetch_scanline_32 = info->fetch_scanline_32;
1399 image->fetch_scanline_float = info->fetch_scanline_float;
1400 image->fetch_pixel_32 = info->fetch_pixel_32;
1401 image->fetch_pixel_float = info->fetch_pixel_float;
1402 image->store_scanline_32 = info->store_scanline_32;
1403 image->store_scanline_float = info->store_scanline_float;
1412 #ifndef PIXMAN_FB_ACCESSORS
1414 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1417 _pixman_bits_image_setup_accessors (bits_image_t *image)
1419 if (image->read_func || image->write_func)
1420 _pixman_bits_image_setup_accessors_accessors (image);
1422 setup_accessors (image);
1428 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1430 setup_accessors (image);