Use MAKE_ACCESSORS() to generate accessors for 4 bpp RGB formats
[profile/ivi/pixman.git] / pixman / pixman-access.c
1 /*
2  *
3  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4  *             2005 Lars Knoll & Zack Rusin, Trolltech
5  *             2008 Aaron Plattner, NVIDIA Corporation
6  *
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.
16  *
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
24  * SOFTWARE.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34
35 #include "pixman-private.h"
36 #include "pixman-accessor.h"
37
38 #define CONVERT_RGB24_TO_Y15(s)                                         \
39     (((((s) >> 16) & 0xff) * 153 +                                      \
40       (((s) >>  8) & 0xff) * 301 +                                      \
41       (((s)      ) & 0xff) * 58) >> 2)
42
43 #define CONVERT_RGB24_TO_RGB15(s)                                       \
44     ((((s) >> 3) & 0x001f) |                                            \
45      (((s) >> 6) & 0x03e0) |                                            \
46      (((s) >> 9) & 0x7c00))
47
48 #define RGB15_TO_ENTRY(mif,rgb15)                                       \
49     ((mif)->ent[rgb15])
50
51 #define RGB24_TO_ENTRY(mif,rgb24)                                       \
52     RGB15_TO_ENTRY (mif,CONVERT_RGB24_TO_RGB15 (rgb24))
53
54 #define RGB24_TO_ENTRY_Y(mif,rgb24)                                     \
55     ((mif)->ent[CONVERT_RGB24_TO_Y15 (rgb24)])
56
57 /* Fetch macros */
58
59 #define FETCH_8(img,l,o)    (READ (img, (((uint8_t *)(l)) + ((o) >> 3))))
60
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))
64 #else
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))
67 #endif
68
69 /* Store macros */
70
71 #define STORE_8(img,l,o,v)  (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v)))
72
73 #ifdef WORDS_BIGENDIAN
74 #define STORE_4(img,l,o,v)                                              \
75     do                                                                  \
76     {                                                                   \
77         int bo = 4 * (o);                                               \
78         int v4 = (v) & 0x0f;                                            \
79                                                                         \
80         STORE_8 (img, l, bo, (                                          \
81                      bo & 4 ?                                           \
82                      (FETCH_8 (img, l, bo) & 0xf0) | (v4) :             \
83                      (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4)));       \
84     } while (0)
85 #else
86 #define STORE_4(img,l,o,v)                                              \
87     do                                                                  \
88     {                                                                   \
89         int bo = 4 * (o);                                               \
90         int v4 = (v) & 0x0f;                                            \
91                                                                         \
92         STORE_8 (img, l, bo, (                                          \
93                      bo & 4 ?                                           \
94                      (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) :        \
95                      (FETCH_8 (img, l, bo) & 0xf0) | (v4)));            \
96     } while (0)
97 #endif
98
99 /*
100  * YV12 setup and access macros
101  */
102
103 #define YV12_SETUP(image)                                               \
104     bits_image_t *__bits_image = (bits_image_t *)image;                 \
105     uint32_t *bits = __bits_image->bits;                                \
106     int stride = __bits_image->rowstride;                               \
107     int offset0 = stride < 0 ?                                          \
108     ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride :     \
109     stride * __bits_image->height;                                      \
110     int offset1 = stride < 0 ?                                          \
111     offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) :        \
112         offset0 + (offset0 >> 2)
113
114 /* Note no trailing semicolon on the above macro; if it's there, then
115  * the typical usage of YV12_SETUP(image); will have an extra trailing ;
116  * that some compilers will interpret as a statement -- and then any further
117  * variable declarations will cause an error.
118  */
119
120 #define YV12_Y(line)                                                    \
121     ((uint8_t *) ((bits) + (stride) * (line)))
122
123 #define YV12_U(line)                                                    \
124     ((uint8_t *) ((bits) + offset1 +                                    \
125                   ((stride) >> 1) * ((line) >> 1)))
126
127 #define YV12_V(line)                                                    \
128     ((uint8_t *) ((bits) + offset0 +                                    \
129                   ((stride) >> 1) * ((line) >> 1)))
130
131 /* Misc. helpers */
132
133 static force_inline void
134 get_shifts (pixman_format_code_t  format,
135             int                  *a,
136             int                  *r,
137             int                  *g,
138             int                  *b)
139 {
140     switch (PIXMAN_FORMAT_TYPE (format))
141     {
142     case PIXMAN_TYPE_A:
143         *b = 0;
144         *g = 0;
145         *r = 0;
146         *a = 0;
147         break;
148
149     case PIXMAN_TYPE_ARGB:
150         *b = 0;
151         *g = *b + PIXMAN_FORMAT_B (format);
152         *r = *g + PIXMAN_FORMAT_G (format);
153         *a = *r + PIXMAN_FORMAT_R (format);
154         break;
155
156     case PIXMAN_TYPE_ABGR:
157         *r = 0;
158         *g = *r + PIXMAN_FORMAT_R (format);
159         *b = *g + PIXMAN_FORMAT_G (format);
160         *a = *b + PIXMAN_FORMAT_B (format);
161         break;
162
163     case PIXMAN_TYPE_BGRA:
164         /* With BGRA formats we start counting at the high end of the pixel */
165         *b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
166         *g = *b - PIXMAN_FORMAT_B (format);
167         *r = *g - PIXMAN_FORMAT_G (format);
168         *a = *r - PIXMAN_FORMAT_R (format);
169         break;
170
171     case PIXMAN_TYPE_RGBA:
172         /* With BGRA formats we start counting at the high end of the pixel */
173         *r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
174         *g = *r - PIXMAN_FORMAT_R (format);
175         *b = *g - PIXMAN_FORMAT_G (format);
176         *a = *b - PIXMAN_FORMAT_B (format);
177         break;
178
179     default:
180         assert (0);
181         break;
182     }
183 }
184
185 static force_inline uint32_t
186 convert_channel (uint32_t pixel, uint32_t def_value,
187                  int n_from_bits, int from_shift,
188                  int n_to_bits, int to_shift)
189 {
190     uint32_t v;
191
192     if (n_from_bits && n_to_bits)
193         v  = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits);
194     else if (n_to_bits)
195         v = def_value;
196     else
197         v = 0;
198
199     return (v & ((1 << n_to_bits) - 1)) << to_shift;
200 }
201
202 static force_inline uint32_t
203 convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel)
204 {
205     int a_from_shift, r_from_shift, g_from_shift, b_from_shift;
206     int a_to_shift, r_to_shift, g_to_shift, b_to_shift;
207     uint32_t a, r, g, b;
208
209     get_shifts (from, &a_from_shift, &r_from_shift, &g_from_shift, &b_from_shift);
210     get_shifts (to, &a_to_shift, &r_to_shift, &g_to_shift, &b_to_shift);
211
212     a = convert_channel (pixel, ~0,
213                          PIXMAN_FORMAT_A (from), a_from_shift,
214                          PIXMAN_FORMAT_A (to), a_to_shift);
215
216     r = convert_channel (pixel, 0,
217                          PIXMAN_FORMAT_R (from), r_from_shift,
218                          PIXMAN_FORMAT_R (to), r_to_shift);
219
220     g = convert_channel (pixel, 0,
221                          PIXMAN_FORMAT_G (from), g_from_shift,
222                          PIXMAN_FORMAT_G (to), g_to_shift);
223
224     b = convert_channel (pixel, 0,
225                          PIXMAN_FORMAT_B (from), b_from_shift,
226                          PIXMAN_FORMAT_B (to), b_to_shift);
227
228     return a | r | g | b;
229 }
230
231 static force_inline uint32_t
232 convert_pixel_from_a8r8g8b8 (pixman_format_code_t format, uint32_t pixel)
233 {
234     return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
235 }
236
237 static force_inline uint32_t
238 convert_pixel_to_a8r8g8b8 (pixman_format_code_t format, uint32_t pixel)
239 {
240     return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
241 }
242
243 static force_inline uint32_t
244 fetch_and_convert_pixel (pixman_image_t *       image,
245                          const uint8_t *        bits,
246                          int                    offset,
247                          pixman_format_code_t   format)
248 {
249     uint32_t pixel;
250
251     switch (PIXMAN_FORMAT_BPP (format))
252     {
253     case 4:
254         pixel = FETCH_4 (image, bits, offset);
255         break;
256
257     case 8:
258         pixel = READ (image, bits + offset);
259         break;
260
261     case 16:
262         pixel = READ (image, ((uint16_t *)bits + offset));
263         break;
264
265     case 32:
266         pixel = READ (image, ((uint32_t *)bits + offset));
267         break;
268
269     default:
270         pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
271         break;
272     }
273
274     return convert_pixel_to_a8r8g8b8 (format, pixel);
275 }
276
277 static force_inline void
278 convert_and_store_pixel (bits_image_t *         image,
279                          uint8_t *              dest,
280                          int                    offset,
281                          pixman_format_code_t   format,
282                          uint32_t               pixel)
283 {
284     uint32_t converted = convert_pixel_from_a8r8g8b8 (format, pixel);
285
286     switch (PIXMAN_FORMAT_BPP (format))
287     {
288     case 4:
289         STORE_4 (image, dest, offset, converted & 0xf);
290         break;
291
292     case 8:
293         WRITE (image, (dest + offset), converted & 0xff);
294         break;
295
296     case 16:
297         WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
298         break;
299
300     case 32:
301         WRITE (image, ((uint32_t *)dest + offset), converted);
302         break;
303
304     default:
305         *dest = 0x0;
306         break;
307     }
308 }
309
310 #define MAKE_ACCESSORS(format)                                          \
311     static void                                                         \
312     fetch_scanline_ ## format (pixman_image_t *image,                   \
313                                int             x,                       \
314                                int             y,                       \
315                                int             width,                   \
316                                uint32_t *      buffer,                  \
317                                const uint32_t *mask)                    \
318     {                                                                   \
319         uint8_t *bits =                                                 \
320             (uint8_t *)(image->bits.bits + y * image->bits.rowstride);  \
321         int i;                                                          \
322                                                                         \
323         for (i = 0; i < width; ++i)                                     \
324         {                                                               \
325             *buffer++ =                                                 \
326                 fetch_and_convert_pixel (image, bits, x + i, PIXMAN_ ## format); \
327         }                                                               \
328     }                                                                   \
329                                                                         \
330     static void                                                         \
331     store_scanline_ ## format (bits_image_t *  image,                   \
332                                int             x,                       \
333                                int             y,                       \
334                                int             width,                   \
335                                const uint32_t *values)                  \
336     {                                                                   \
337         uint8_t *dest =                                                 \
338             (uint8_t *)(image->bits + y * image->rowstride);            \
339         int i;                                                          \
340                                                                         \
341         for (i = 0; i < width; ++i)                                     \
342         {                                                               \
343             convert_and_store_pixel (                                   \
344                 image, dest, i + x, PIXMAN_ ## format, values[i]);      \
345         }                                                               \
346     }                                                                   \
347                                                                         \
348     static uint32_t                                                     \
349     fetch_pixel_ ## format (bits_image_t *image,                        \
350                             int         offset,                         \
351                             int         line)                           \
352     {                                                                   \
353         uint8_t *bits =                                                 \
354             (uint8_t *)(image->bits + line * image->rowstride);         \
355                                                                         \
356         return fetch_and_convert_pixel ((pixman_image_t *)image,        \
357                                         bits, offset, PIXMAN_ ## format); \
358     }                                                                   \
359                                                                         \
360     static const void *const __dummy__ ## format
361
362 MAKE_ACCESSORS(a8r8g8b8);
363 MAKE_ACCESSORS(x8r8g8b8);
364 MAKE_ACCESSORS(a8b8g8r8);
365 MAKE_ACCESSORS(x8b8g8r8);
366 MAKE_ACCESSORS(x14r6g6b6);
367 MAKE_ACCESSORS(b8g8r8a8);
368 MAKE_ACCESSORS(b8g8r8x8);
369 MAKE_ACCESSORS(r8g8b8x8);
370 MAKE_ACCESSORS(r8g8b8a8);
371 MAKE_ACCESSORS(r5g6b5);
372 MAKE_ACCESSORS(b5g6r5);
373 MAKE_ACCESSORS(a1r5g5b5);
374 MAKE_ACCESSORS(x1r5g5b5);
375 MAKE_ACCESSORS(a1b5g5r5);
376 MAKE_ACCESSORS(x1b5g5r5);
377 MAKE_ACCESSORS(a4r4g4b4);
378 MAKE_ACCESSORS(x4r4g4b4);
379 MAKE_ACCESSORS(a4b4g4r4);
380 MAKE_ACCESSORS(x4b4g4r4);
381 MAKE_ACCESSORS(a8);
382 MAKE_ACCESSORS(r3g3b2);
383 MAKE_ACCESSORS(b2g3r3);
384 MAKE_ACCESSORS(a2r2g2b2);
385 MAKE_ACCESSORS(a2b2g2r2);
386 MAKE_ACCESSORS(x4a4);
387 MAKE_ACCESSORS(a4);
388 MAKE_ACCESSORS(r1g2b1);
389 MAKE_ACCESSORS(b1g2r1);
390 MAKE_ACCESSORS(a1r1g1b1);
391 MAKE_ACCESSORS(a1b1g1r1);
392
393 /********************************** Fetch ************************************/
394
395 /* Expects a uint64_t buffer */
396 static void
397 fetch_scanline_a2r10g10b10 (pixman_image_t *image,
398                             int             x,
399                             int             y,
400                             int             width,
401                             uint32_t *      b,
402                             const uint32_t *mask)
403 {
404     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
405     const uint32_t *pixel = bits + x;
406     const uint32_t *end = pixel + width;
407     uint64_t *buffer = (uint64_t *)b;
408
409     while (pixel < end)
410     {
411         uint32_t p = READ (image, pixel++);
412         uint64_t a = p >> 30;
413         uint64_t r = (p >> 20) & 0x3ff;
414         uint64_t g = (p >> 10) & 0x3ff;
415         uint64_t b = p & 0x3ff;
416
417         r = r << 6 | r >> 4;
418         g = g << 6 | g >> 4;
419         b = b << 6 | b >> 4;
420
421         a <<= 14;
422         a |= a >> 2;
423         a |= a >> 4;
424         a |= a >> 8;
425
426         *buffer++ = a << 48 | r << 32 | g << 16 | b;
427     }
428 }
429
430 /* Expects a uint64_t buffer */
431 static void
432 fetch_scanline_x2r10g10b10 (pixman_image_t *image,
433                             int             x,
434                             int             y,
435                             int             width,
436                             uint32_t *      b,
437                             const uint32_t *mask)
438 {
439     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
440     const uint32_t *pixel = (uint32_t *)bits + x;
441     const uint32_t *end = pixel + width;
442     uint64_t *buffer = (uint64_t *)b;
443     
444     while (pixel < end)
445     {
446         uint32_t p = READ (image, pixel++);
447         uint64_t r = (p >> 20) & 0x3ff;
448         uint64_t g = (p >> 10) & 0x3ff;
449         uint64_t b = p & 0x3ff;
450         
451         r = r << 6 | r >> 4;
452         g = g << 6 | g >> 4;
453         b = b << 6 | b >> 4;
454         
455         *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
456     }
457 }
458
459 /* Expects a uint64_t buffer */
460 static void
461 fetch_scanline_a2b10g10r10 (pixman_image_t *image,
462                             int             x,
463                             int             y,
464                             int             width,
465                             uint32_t *      b,
466                             const uint32_t *mask)
467 {
468     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
469     const uint32_t *pixel = bits + x;
470     const uint32_t *end = pixel + width;
471     uint64_t *buffer = (uint64_t *)b;
472     
473     while (pixel < end)
474     {
475         uint32_t p = READ (image, pixel++);
476         uint64_t a = p >> 30;
477         uint64_t b = (p >> 20) & 0x3ff;
478         uint64_t g = (p >> 10) & 0x3ff;
479         uint64_t r = p & 0x3ff;
480         
481         r = r << 6 | r >> 4;
482         g = g << 6 | g >> 4;
483         b = b << 6 | b >> 4;
484         
485         a <<= 14;
486         a |= a >> 2;
487         a |= a >> 4;
488         a |= a >> 8;
489
490         *buffer++ = a << 48 | r << 32 | g << 16 | b;
491     }
492 }
493
494 /* Expects a uint64_t buffer */
495 static void
496 fetch_scanline_x2b10g10r10 (pixman_image_t *image,
497                             int             x,
498                             int             y,
499                             int             width,
500                             uint32_t *      b,
501                             const uint32_t *mask)
502 {
503     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
504     const uint32_t *pixel = (uint32_t *)bits + x;
505     const uint32_t *end = pixel + width;
506     uint64_t *buffer = (uint64_t *)b;
507     
508     while (pixel < end)
509     {
510         uint32_t p = READ (image, pixel++);
511         uint64_t b = (p >> 20) & 0x3ff;
512         uint64_t g = (p >> 10) & 0x3ff;
513         uint64_t r = p & 0x3ff;
514         
515         r = r << 6 | r >> 4;
516         g = g << 6 | g >> 4;
517         b = b << 6 | b >> 4;
518         
519         *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
520     }
521 }
522
523 static void
524 fetch_scanline_r8g8b8 (pixman_image_t *image,
525                        int             x,
526                        int             y,
527                        int             width,
528                        uint32_t *      buffer,
529                        const uint32_t *mask)
530 {
531     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
532     const uint8_t *pixel = (const uint8_t *)bits + 3 * x;
533     const uint8_t *end = pixel + 3 * width;
534     
535     while (pixel < end)
536     {
537         uint32_t b = 0xff000000;
538         
539 #ifdef WORDS_BIGENDIAN
540         b |= (READ (image, pixel++) << 16);
541         b |= (READ (image, pixel++) << 8);
542         b |= (READ (image, pixel++));
543 #else
544         b |= (READ (image, pixel++));
545         b |= (READ (image, pixel++) << 8);
546         b |= (READ (image, pixel++) << 16);
547 #endif
548         
549         *buffer++ = b;
550     }
551 }
552
553 static void
554 fetch_scanline_b8g8r8 (pixman_image_t *image,
555                        int             x,
556                        int             y,
557                        int             width,
558                        uint32_t *      buffer,
559                        const uint32_t *mask)
560 {
561     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
562     const uint8_t *pixel = (const uint8_t *)bits + 3 * x;
563     const uint8_t *end = pixel + 3 * width;
564     
565     while (pixel < end)
566     {
567         uint32_t b = 0xff000000;
568 #ifdef WORDS_BIGENDIAN
569         b |= (READ (image, pixel++));
570         b |= (READ (image, pixel++) << 8);
571         b |= (READ (image, pixel++) << 16);
572 #else
573         b |= (READ (image, pixel++) << 16);
574         b |= (READ (image, pixel++) << 8);
575         b |= (READ (image, pixel++));
576 #endif
577         *buffer++ = b;
578     }
579 }
580
581 static void
582 fetch_scanline_c8 (pixman_image_t *image,
583                    int             x,
584                    int             y,
585                    int             width,
586                    uint32_t *      buffer,
587                    const uint32_t *mask)
588 {
589     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
590     const pixman_indexed_t * indexed = image->bits.indexed;
591     const uint8_t *pixel = (const uint8_t *)bits + x;
592     const uint8_t *end = pixel + width;
593     
594     while (pixel < end)
595     {
596         uint32_t p = READ (image, pixel++);
597         
598         *buffer++ = indexed->rgba[p];
599     }
600 }
601
602 static void
603 fetch_scanline_c4 (pixman_image_t *image,
604                    int             x,
605                    int             y,
606                    int             width,
607                    uint32_t *      buffer,
608                    const uint32_t *mask)
609 {
610     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
611     const pixman_indexed_t * indexed = image->bits.indexed;
612     int i;
613     
614     for (i = 0; i < width; ++i)
615     {
616         uint32_t p = FETCH_4 (image, bits, i + x);
617         
618         *buffer++ = indexed->rgba[p];
619     }
620 }
621
622 static void
623 fetch_scanline_a1 (pixman_image_t *image,
624                    int             x,
625                    int             y,
626                    int             width,
627                    uint32_t *      buffer,
628                    const uint32_t *mask)
629 {
630     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
631     int i;
632     
633     for (i = 0; i < width; ++i)
634     {
635         uint32_t p = READ (image, bits + ((i + x) >> 5));
636         uint32_t a;
637         
638 #ifdef WORDS_BIGENDIAN
639         a = p >> (0x1f - ((i + x) & 0x1f));
640 #else
641         a = p >> ((i + x) & 0x1f);
642 #endif
643         a = a & 1;
644         a |= a << 1;
645         a |= a << 2;
646         a |= a << 4;
647         
648         *buffer++ = a << 24;
649     }
650 }
651
652 static void
653 fetch_scanline_g1 (pixman_image_t *image,
654                    int             x,
655                    int             y,
656                    int             width,
657                    uint32_t *      buffer,
658                    const uint32_t *mask)
659 {
660     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
661     const pixman_indexed_t * indexed = image->bits.indexed;
662     int i;
663     
664     for (i = 0; i < width; ++i)
665     {
666         uint32_t p = READ (image, bits + ((i + x) >> 5));
667         uint32_t a;
668         
669 #ifdef WORDS_BIGENDIAN
670         a = p >> (0x1f - ((i + x) & 0x1f));
671 #else
672         a = p >> ((i + x) & 0x1f);
673 #endif
674         a = a & 1;
675         
676         *buffer++ = indexed->rgba[a];
677     }
678 }
679
680 static void
681 fetch_scanline_yuy2 (pixman_image_t *image,
682                      int             x,
683                      int             line,
684                      int             width,
685                      uint32_t *      buffer,
686                      const uint32_t *mask)
687 {
688     const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
689     int i;
690     
691     for (i = 0; i < width; i++)
692     {
693         int16_t y, u, v;
694         int32_t r, g, b;
695         
696         y = ((uint8_t *) bits)[(x + i) << 1] - 16;
697         u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
698         v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
699         
700         /* R = 1.164(Y - 16) + 1.596(V - 128) */
701         r = 0x012b27 * y + 0x019a2e * v;
702         /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
703         g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
704         /* B = 1.164(Y - 16) + 2.018(U - 128) */
705         b = 0x012b27 * y + 0x0206a2 * u;
706         
707         *buffer++ = 0xff000000 |
708             (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
709             (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
710             (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
711     }
712 }
713
714 static void
715 fetch_scanline_yv12 (pixman_image_t *image,
716                      int             x,
717                      int             line,
718                      int             width,
719                      uint32_t *      buffer,
720                      const uint32_t *mask)
721 {
722     YV12_SETUP (image);
723     uint8_t *y_line = YV12_Y (line);
724     uint8_t *u_line = YV12_U (line);
725     uint8_t *v_line = YV12_V (line);
726     int i;
727     
728     for (i = 0; i < width; i++)
729     {
730         int16_t y, u, v;
731         int32_t r, g, b;
732
733         y = y_line[x + i] - 16;
734         u = u_line[(x + i) >> 1] - 128;
735         v = v_line[(x + i) >> 1] - 128;
736
737         /* R = 1.164(Y - 16) + 1.596(V - 128) */
738         r = 0x012b27 * y + 0x019a2e * v;
739         /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
740         g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
741         /* B = 1.164(Y - 16) + 2.018(U - 128) */
742         b = 0x012b27 * y + 0x0206a2 * u;
743
744         *buffer++ = 0xff000000 |
745             (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
746             (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
747             (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
748     }
749 }
750
751 /**************************** Pixel wise fetching *****************************/
752
753 /* Despite the type, expects a uint64_t buffer */
754 static uint64_t
755 fetch_pixel_a2r10g10b10 (bits_image_t *image,
756                          int              offset,
757                          int           line)
758 {
759     uint32_t *bits = image->bits + line * image->rowstride;
760     uint32_t p = READ (image, bits + offset);
761     uint64_t a = p >> 30;
762     uint64_t r = (p >> 20) & 0x3ff;
763     uint64_t g = (p >> 10) & 0x3ff;
764     uint64_t b = p & 0x3ff;
765
766     r = r << 6 | r >> 4;
767     g = g << 6 | g >> 4;
768     b = b << 6 | b >> 4;
769
770     a <<= 14;
771     a |= a >> 2;
772     a |= a >> 4;
773     a |= a >> 8;
774
775     return a << 48 | r << 32 | g << 16 | b;
776 }
777
778 /* Despite the type, this function expects a uint64_t buffer */
779 static uint64_t
780 fetch_pixel_x2r10g10b10 (bits_image_t *image,
781                          int       offset,
782                          int           line)
783 {
784     uint32_t *bits = image->bits + line * image->rowstride;
785     uint32_t p = READ (image, bits + offset);
786     uint64_t r = (p >> 20) & 0x3ff;
787     uint64_t g = (p >> 10) & 0x3ff;
788     uint64_t b = p & 0x3ff;
789     
790     r = r << 6 | r >> 4;
791     g = g << 6 | g >> 4;
792     b = b << 6 | b >> 4;
793     
794     return 0xffffULL << 48 | r << 32 | g << 16 | b;
795 }
796
797 /* Despite the type, expects a uint64_t buffer */
798 static uint64_t
799 fetch_pixel_a2b10g10r10 (bits_image_t *image,
800                          int           offset,
801                          int           line)
802 {
803     uint32_t *bits = image->bits + line * image->rowstride;
804     uint32_t p = READ (image, bits + offset);
805     uint64_t a = p >> 30;
806     uint64_t b = (p >> 20) & 0x3ff;
807     uint64_t g = (p >> 10) & 0x3ff;
808     uint64_t r = p & 0x3ff;
809     
810     r = r << 6 | r >> 4;
811     g = g << 6 | g >> 4;
812     b = b << 6 | b >> 4;
813     
814     a <<= 14;
815     a |= a >> 2;
816     a |= a >> 4;
817     a |= a >> 8;
818     
819     return a << 48 | r << 32 | g << 16 | b;
820 }
821
822 /* Despite the type, this function expects a uint64_t buffer */
823 static uint64_t
824 fetch_pixel_x2b10g10r10 (bits_image_t *image,
825                          int           offset,
826                          int           line)
827 {
828     uint32_t *bits = image->bits + line * image->rowstride;
829     uint32_t p = READ (image, bits + offset);
830     uint64_t b = (p >> 20) & 0x3ff;
831     uint64_t g = (p >> 10) & 0x3ff;
832     uint64_t r = p & 0x3ff;
833     
834     r = r << 6 | r >> 4;
835     g = g << 6 | g >> 4;
836     b = b << 6 | b >> 4;
837     
838     return 0xffffULL << 48 | r << 32 | g << 16 | b;
839 }
840
841 static uint32_t
842 fetch_pixel_r8g8b8 (bits_image_t *image,
843                     int           offset,
844                     int           line)
845 {
846     uint32_t *bits = image->bits + line * image->rowstride;
847     uint8_t   *pixel = ((uint8_t *) bits) + (offset * 3);
848     
849 #ifdef WORDS_BIGENDIAN
850     return (0xff000000 |
851             (READ (image, pixel + 0) << 16) |
852             (READ (image, pixel + 1) << 8) |
853             (READ (image, pixel + 2)));
854 #else
855     return (0xff000000 |
856             (READ (image, pixel + 2) << 16) |
857             (READ (image, pixel + 1) << 8) |
858             (READ (image, pixel + 0)));
859 #endif
860 }
861
862 static uint32_t
863 fetch_pixel_b8g8r8 (bits_image_t *image,
864                     int           offset,
865                     int           line)
866 {
867     uint32_t *bits = image->bits + line * image->rowstride;
868     uint8_t   *pixel = ((uint8_t *) bits) + (offset * 3);
869 #ifdef WORDS_BIGENDIAN
870     return (0xff000000 |
871             (READ (image, pixel + 2) << 16) |
872             (READ (image, pixel + 1) << 8) |
873             (READ (image, pixel + 0)));
874 #else
875     return (0xff000000 |
876             (READ (image, pixel + 0) << 16) |
877             (READ (image, pixel + 1) << 8) |
878             (READ (image, pixel + 2)));
879 #endif
880 }
881
882 static uint32_t
883 fetch_pixel_c8 (bits_image_t *image,
884                 int           offset,
885                 int           line)
886 {
887     uint32_t *bits = image->bits + line * image->rowstride;
888     uint32_t pixel = READ (image, (uint8_t *) bits + offset);
889     const pixman_indexed_t * indexed = image->indexed;
890     
891     return indexed->rgba[pixel];
892 }
893
894 static uint32_t
895 fetch_pixel_c4 (bits_image_t *image,
896                 int           offset,
897                 int           line)
898 {
899     uint32_t *bits = image->bits + line * image->rowstride;
900     uint32_t pixel = FETCH_4 (image, bits, offset);
901     const pixman_indexed_t * indexed = image->indexed;
902
903     return indexed->rgba[pixel];
904 }
905
906 static uint32_t
907 fetch_pixel_a1 (bits_image_t *image,
908                 int           offset,
909                 int           line)
910 {
911     uint32_t *bits = image->bits + line * image->rowstride;
912     uint32_t pixel = READ (image, bits + (offset >> 5));
913     uint32_t a;
914     
915 #ifdef WORDS_BIGENDIAN
916     a = pixel >> (0x1f - (offset & 0x1f));
917 #else
918     a = pixel >> (offset & 0x1f);
919 #endif
920     a = a & 1;
921     a |= a << 1;
922     a |= a << 2;
923     a |= a << 4;
924     
925     return a << 24;
926 }
927
928 static uint32_t
929 fetch_pixel_g1 (bits_image_t *image,
930                 int           offset,
931                 int           line)
932 {
933     uint32_t *bits = image->bits + line * image->rowstride;
934     uint32_t pixel = READ (image, bits + (offset >> 5));
935     const pixman_indexed_t * indexed = image->indexed;
936     uint32_t a;
937     
938 #ifdef WORDS_BIGENDIAN
939     a = pixel >> (0x1f - (offset & 0x1f));
940 #else
941     a = pixel >> (offset & 0x1f);
942 #endif
943     a = a & 1;
944     
945     return indexed->rgba[a];
946 }
947
948 static uint32_t
949 fetch_pixel_yuy2 (bits_image_t *image,
950                   int           offset,
951                   int           line)
952 {
953     const uint32_t *bits = image->bits + image->rowstride * line;
954     
955     int16_t y, u, v;
956     int32_t r, g, b;
957     
958     y = ((uint8_t *) bits)[offset << 1] - 16;
959     u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
960     v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
961     
962     /* R = 1.164(Y - 16) + 1.596(V - 128) */
963     r = 0x012b27 * y + 0x019a2e * v;
964     
965     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
966     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
967     
968     /* B = 1.164(Y - 16) + 2.018(U - 128) */
969     b = 0x012b27 * y + 0x0206a2 * u;
970     
971     return 0xff000000 |
972         (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
973         (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
974         (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
975 }
976
977 static uint32_t
978 fetch_pixel_yv12 (bits_image_t *image,
979                   int           offset,
980                   int           line)
981 {
982     YV12_SETUP (image);
983     int16_t y = YV12_Y (line)[offset] - 16;
984     int16_t u = YV12_U (line)[offset >> 1] - 128;
985     int16_t v = YV12_V (line)[offset >> 1] - 128;
986     int32_t r, g, b;
987     
988     /* R = 1.164(Y - 16) + 1.596(V - 128) */
989     r = 0x012b27 * y + 0x019a2e * v;
990     
991     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
992     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
993     
994     /* B = 1.164(Y - 16) + 2.018(U - 128) */
995     b = 0x012b27 * y + 0x0206a2 * u;
996     
997     return 0xff000000 |
998         (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
999         (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
1000         (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
1001 }
1002
1003 /*********************************** Store ************************************/
1004
1005 static void
1006 store_scanline_a2r10g10b10 (bits_image_t *  image,
1007                             int             x,
1008                             int             y,
1009                             int             width,
1010                             const uint32_t *v)
1011 {
1012     uint32_t *bits = image->bits + image->rowstride * y;
1013     uint32_t *pixel = bits + x;
1014     uint64_t *values = (uint64_t *)v;
1015     int i;
1016     
1017     for (i = 0; i < width; ++i)
1018     {
1019         WRITE (image, pixel++,
1020                ((values[i] >> 32) & 0xc0000000) |
1021                ((values[i] >> 18) & 0x3ff00000) |
1022                ((values[i] >> 12) & 0xffc00) | 
1023                ((values[i] >> 6) & 0x3ff));    
1024     }
1025 }
1026
1027 static void
1028 store_scanline_x2r10g10b10 (bits_image_t *  image,
1029                             int             x,
1030                             int             y,
1031                             int             width,
1032                             const uint32_t *v)
1033 {
1034     uint32_t *bits = image->bits + image->rowstride * y;
1035     uint64_t *values = (uint64_t *)v;
1036     uint32_t *pixel = bits + x;
1037     int i;
1038     
1039     for (i = 0; i < width; ++i)
1040     {
1041         WRITE (image, pixel++,
1042                ((values[i] >> 18) & 0x3ff00000) | 
1043                ((values[i] >> 12) & 0xffc00) |
1044                ((values[i] >> 6) & 0x3ff));
1045     }
1046 }
1047
1048 static void
1049 store_scanline_a2b10g10r10 (bits_image_t *  image,
1050                             int             x,
1051                             int             y,
1052                             int             width,
1053                             const uint32_t *v)
1054 {
1055     uint32_t *bits = image->bits + image->rowstride * y;
1056     uint32_t *pixel = bits + x;
1057     uint64_t *values = (uint64_t *)v;
1058     int i;
1059     
1060     for (i = 0; i < width; ++i)
1061     {
1062         WRITE (image, pixel++,
1063                ((values[i] >> 32) & 0xc0000000) |
1064                ((values[i] >> 38) & 0x3ff) |
1065                ((values[i] >> 12) & 0xffc00) |
1066                ((values[i] << 14) & 0x3ff00000));
1067     }
1068 }
1069
1070 static void
1071 store_scanline_x2b10g10r10 (bits_image_t *  image,
1072                             int             x,
1073                             int             y,
1074                             int             width,
1075                             const uint32_t *v)
1076 {
1077     uint32_t *bits = image->bits + image->rowstride * y;
1078     uint64_t *values = (uint64_t *)v;
1079     uint32_t *pixel = bits + x;
1080     int i;
1081     
1082     for (i = 0; i < width; ++i)
1083     {
1084         WRITE (image, pixel++,
1085                ((values[i] >> 38) & 0x3ff) |
1086                ((values[i] >> 12) & 0xffc00) |
1087                ((values[i] << 14) & 0x3ff00000));
1088     }
1089 }
1090
1091 static void
1092 store_scanline_r8g8b8 (bits_image_t *  image,
1093                        int             x,
1094                        int             y,
1095                        int             width,
1096                        const uint32_t *values)
1097 {
1098     uint32_t *bits = image->bits + image->rowstride * y;
1099     uint8_t *pixel = ((uint8_t *) bits) + 3 * x;
1100     int i;
1101     
1102     for (i = 0; i < width; ++i)
1103     {
1104         uint32_t val = values[i];
1105         
1106 #ifdef WORDS_BIGENDIAN
1107         WRITE (image, pixel++, (val & 0x00ff0000) >> 16);
1108         WRITE (image, pixel++, (val & 0x0000ff00) >>  8);
1109         WRITE (image, pixel++, (val & 0x000000ff) >>  0);
1110 #else
1111         WRITE (image, pixel++, (val & 0x000000ff) >>  0);
1112         WRITE (image, pixel++, (val & 0x0000ff00) >>  8);
1113         WRITE (image, pixel++, (val & 0x00ff0000) >> 16);
1114 #endif
1115     }
1116 }
1117
1118 static void
1119 store_scanline_b8g8r8 (bits_image_t *  image,
1120                        int             x,
1121                        int             y,
1122                        int             width,
1123                        const uint32_t *values)
1124 {
1125     uint32_t *bits = image->bits + image->rowstride * y;
1126     uint8_t *pixel = ((uint8_t *) bits) + 3 * x;
1127     int i;
1128     
1129     for (i = 0; i < width; ++i)
1130     {
1131         uint32_t val = values[i];
1132         
1133 #ifdef WORDS_BIGENDIAN
1134         WRITE (image, pixel++, (val & 0x000000ff) >>  0);
1135         WRITE (image, pixel++, (val & 0x0000ff00) >>  8);
1136         WRITE (image, pixel++, (val & 0x00ff0000) >> 16);
1137 #else
1138         WRITE (image, pixel++, (val & 0x00ff0000) >> 16);
1139         WRITE (image, pixel++, (val & 0x0000ff00) >>  8);
1140         WRITE (image, pixel++, (val & 0x000000ff) >>  0);
1141 #endif
1142     }
1143 }
1144
1145 static void
1146 store_scanline_c8 (bits_image_t *  image,
1147                    int             x,
1148                    int             y,
1149                    int             width,
1150                    const uint32_t *values)
1151 {
1152     uint32_t *bits = image->bits + image->rowstride * y;
1153     uint8_t *pixel = ((uint8_t *) bits) + x;
1154     const pixman_indexed_t *indexed = image->indexed;
1155     int i;
1156     
1157     for (i = 0; i < width; ++i)
1158         WRITE (image, pixel++, RGB24_TO_ENTRY (indexed,values[i]));
1159 }
1160
1161 static void
1162 store_scanline_g8 (bits_image_t *  image,
1163                    int             x,
1164                    int             y,
1165                    int             width,
1166                    const uint32_t *values)
1167 {
1168     uint32_t *bits = image->bits + image->rowstride * y;
1169     uint8_t *pixel = ((uint8_t *) bits) + x;
1170     const pixman_indexed_t *indexed = image->indexed;
1171     int i;
1172
1173     for (i = 0; i < width; ++i)
1174         WRITE (image, pixel++, RGB24_TO_ENTRY_Y (indexed,values[i]));
1175 }
1176
1177 static void
1178 store_scanline_c4 (bits_image_t *  image,
1179                    int             x,
1180                    int             y,
1181                    int             width,
1182                    const uint32_t *values)
1183 {
1184     uint32_t *bits = image->bits + image->rowstride * y;
1185     const pixman_indexed_t *indexed = image->indexed;
1186     int i;
1187     
1188     for (i = 0; i < width; ++i)
1189     {
1190         uint32_t pixel;
1191         
1192         pixel = RGB24_TO_ENTRY (indexed, values[i]);
1193         STORE_4 (image, bits, i + x, pixel);
1194     }
1195 }
1196
1197 static void
1198 store_scanline_g4 (bits_image_t *  image,
1199                    int             x,
1200                    int             y,
1201                    int             width,
1202                    const uint32_t *values)
1203 {
1204     uint32_t *bits = image->bits + image->rowstride * y;
1205     const pixman_indexed_t *indexed = image->indexed;
1206     int i;
1207     
1208     for (i = 0; i < width; ++i)
1209     {
1210         uint32_t pixel;
1211         
1212         pixel = RGB24_TO_ENTRY_Y (indexed, values[i]);
1213         STORE_4 (image, bits, i + x, pixel);
1214     }
1215 }
1216
1217 static void
1218 store_scanline_a1 (bits_image_t *  image,
1219                    int             x,
1220                    int             y,
1221                    int             width,
1222                    const uint32_t *values)
1223 {
1224     uint32_t *bits = image->bits + image->rowstride * y;
1225     int i;
1226     
1227     for (i = 0; i < width; ++i)
1228     {
1229         uint32_t  *pixel = ((uint32_t *) bits) + ((i + x) >> 5);
1230         uint32_t mask, v;
1231         
1232 #ifdef WORDS_BIGENDIAN
1233         mask = 1 << (0x1f - ((i + x) & 0x1f));
1234 #else
1235         mask = 1 << ((i + x) & 0x1f);
1236 #endif
1237         v = values[i] & 0x80000000 ? mask : 0;
1238         
1239         WRITE (image, pixel, (READ (image, pixel) & ~mask) | v);
1240     }
1241 }
1242
1243 static void
1244 store_scanline_g1 (bits_image_t *  image,
1245                    int             x,
1246                    int             y,
1247                    int             width,
1248                    const uint32_t *values)
1249 {
1250     uint32_t *bits = image->bits + image->rowstride * y;
1251     const pixman_indexed_t *indexed = image->indexed;
1252     int i;
1253     
1254     for (i = 0; i < width; ++i)
1255     {
1256         uint32_t  *pixel = ((uint32_t *) bits) + ((i + x) >> 5);
1257         uint32_t mask, v;
1258         
1259 #ifdef WORDS_BIGENDIAN
1260         mask = 1 << (0x1f - ((i + x) & 0x1f));
1261 #else
1262         mask = 1 << ((i + x) & 0x1f);
1263 #endif
1264         v = RGB24_TO_ENTRY_Y (indexed, values[i]) & 0x1 ? mask : 0;
1265         
1266         WRITE (image, pixel, (READ (image, pixel) & ~mask) | v);
1267     }
1268 }
1269
1270 /*
1271  * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit
1272  * store proc. Despite the type, this function expects a uint64_t buffer.
1273  */
1274 static void
1275 store_scanline_generic_64 (bits_image_t *  image,
1276                            int             x,
1277                            int             y,
1278                            int             width,
1279                            const uint32_t *values)
1280 {
1281     uint32_t *argb8_pixels;
1282     
1283     assert (image->common.type == BITS);
1284     
1285     argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1286     if (!argb8_pixels)
1287         return;
1288     
1289     /* Contract the scanline.  We could do this in place if values weren't
1290      * const.
1291      */
1292     pixman_contract (argb8_pixels, (uint64_t *)values, width);
1293     
1294     image->store_scanline_32 (image, x, y, width, argb8_pixels);
1295     
1296     free (argb8_pixels);
1297 }
1298
1299 /* Despite the type, this function expects both buffer
1300  * and mask to be uint64_t
1301  */
1302 static void
1303 fetch_scanline_generic_64 (pixman_image_t *image,
1304                            int             x,
1305                            int             y,
1306                            int             width,
1307                            uint32_t *      buffer,
1308                            const uint32_t *mask)
1309 {
1310     pixman_format_code_t format;
1311     
1312     /* Fetch the pixels into the first half of buffer and then expand them in
1313      * place.
1314      */
1315     image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
1316
1317     format = image->bits.format;
1318     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR        ||
1319         PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
1320     {
1321         /* Indexed formats are mapped to a8r8g8b8 with full
1322          * precision, so when expanding we shouldn't correct
1323          * for the width of the channels
1324          */
1325         
1326         format = PIXMAN_a8r8g8b8;
1327     }
1328     
1329     pixman_expand ((uint64_t *)buffer, buffer, format, width);
1330 }
1331
1332 /* Despite the type, this function expects a uint64_t *buffer */
1333 static uint64_t
1334 fetch_pixel_generic_64 (bits_image_t *image,
1335                         int           offset,
1336                         int           line)
1337 {
1338     uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1339     uint64_t result;
1340     pixman_format_code_t format;
1341
1342     format = image->format;
1343     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR        ||
1344         PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
1345     {
1346         /* Indexed formats are mapped to a8r8g8b8 with full
1347          * precision, so when expanding we shouldn't correct
1348          * for the width of the channels
1349          */
1350         
1351         format = PIXMAN_a8r8g8b8;
1352     }
1353     
1354     pixman_expand ((uint64_t *)&result, &pixel32, format, 1);
1355
1356     return result;
1357 }
1358
1359 /*
1360  * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1361  * paths have wide versions, this can be removed.
1362  *
1363  * WARNING: This function loses precision!
1364  */
1365 static uint32_t
1366 fetch_pixel_generic_lossy_32 (bits_image_t *image,
1367                               int           offset,
1368                               int           line)
1369 {
1370     uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line);
1371     uint32_t result;
1372     
1373     pixman_contract (&result, &pixel64, 1);
1374
1375     return result;
1376 }
1377
1378 typedef struct
1379 {
1380     pixman_format_code_t        format;
1381     fetch_scanline_t            fetch_scanline_32;
1382     fetch_scanline_t            fetch_scanline_64;
1383     fetch_pixel_32_t            fetch_pixel_32;
1384     fetch_pixel_64_t            fetch_pixel_64;
1385     store_scanline_t            store_scanline_32;
1386     store_scanline_t            store_scanline_64;
1387 } format_info_t;
1388
1389 #define FORMAT_INFO(format)                                             \
1390     {                                                                   \
1391         PIXMAN_ ## format,                                              \
1392             fetch_scanline_ ## format,                                  \
1393             fetch_scanline_generic_64,                                  \
1394             fetch_pixel_ ## format, fetch_pixel_generic_64,             \
1395             store_scanline_ ## format, store_scanline_generic_64        \
1396     }
1397
1398 static const format_info_t accessors[] =
1399 {
1400 /* 32 bpp formats */
1401     FORMAT_INFO (a8r8g8b8),
1402     FORMAT_INFO (x8r8g8b8),
1403     FORMAT_INFO (a8b8g8r8),
1404     FORMAT_INFO (x8b8g8r8),
1405     FORMAT_INFO (b8g8r8a8),
1406     FORMAT_INFO (b8g8r8x8),
1407     FORMAT_INFO (r8g8b8a8),
1408     FORMAT_INFO (r8g8b8x8),
1409     FORMAT_INFO (x14r6g6b6),
1410
1411 /* 24bpp formats */
1412     FORMAT_INFO (r8g8b8),
1413     FORMAT_INFO (b8g8r8),
1414     
1415 /* 16bpp formats */
1416     FORMAT_INFO (r5g6b5),
1417     FORMAT_INFO (b5g6r5),
1418     
1419     FORMAT_INFO (a1r5g5b5),
1420     FORMAT_INFO (x1r5g5b5),
1421     FORMAT_INFO (a1b5g5r5),
1422     FORMAT_INFO (x1b5g5r5),
1423     FORMAT_INFO (a4r4g4b4),
1424     FORMAT_INFO (x4r4g4b4),
1425     FORMAT_INFO (a4b4g4r4),
1426     FORMAT_INFO (x4b4g4r4),
1427     
1428 /* 8bpp formats */
1429     FORMAT_INFO (a8),
1430     FORMAT_INFO (r3g3b2),
1431     FORMAT_INFO (b2g3r3),
1432     FORMAT_INFO (a2r2g2b2),
1433     FORMAT_INFO (a2b2g2r2),
1434     
1435     FORMAT_INFO (c8),
1436     
1437 #define fetch_scanline_g8 fetch_scanline_c8
1438 #define fetch_pixel_g8 fetch_pixel_c8
1439     FORMAT_INFO (g8),
1440     
1441 #define fetch_scanline_x4c4 fetch_scanline_c8
1442 #define fetch_pixel_x4c4 fetch_pixel_c8
1443 #define store_scanline_x4c4 store_scanline_c8
1444     FORMAT_INFO (x4c4),
1445     
1446 #define fetch_scanline_x4g4 fetch_scanline_c8
1447 #define fetch_pixel_x4g4 fetch_pixel_c8
1448 #define store_scanline_x4g4 store_scanline_g8
1449     FORMAT_INFO (x4g4),
1450     
1451     FORMAT_INFO (x4a4),
1452     
1453 /* 4bpp formats */
1454     FORMAT_INFO (a4),
1455     FORMAT_INFO (r1g2b1),
1456     FORMAT_INFO (b1g2r1),
1457     FORMAT_INFO (a1r1g1b1),
1458     FORMAT_INFO (a1b1g1r1),
1459     
1460     FORMAT_INFO (c4),
1461     
1462 #define fetch_scanline_g4 fetch_scanline_c4
1463 #define fetch_pixel_g4 fetch_pixel_c4
1464     FORMAT_INFO (g4),
1465     
1466 /* 1bpp formats */
1467     FORMAT_INFO (a1),
1468     FORMAT_INFO (g1),
1469     
1470 /* Wide formats */
1471     
1472     { PIXMAN_a2r10g10b10,
1473       NULL, fetch_scanline_a2r10g10b10,
1474       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10,
1475       NULL, store_scanline_a2r10g10b10 },
1476     
1477     { PIXMAN_x2r10g10b10,
1478       NULL, fetch_scanline_x2r10g10b10,
1479       fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10,
1480       NULL, store_scanline_x2r10g10b10 },
1481     
1482     { PIXMAN_a2b10g10r10,
1483       NULL, fetch_scanline_a2b10g10r10,
1484       fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10,
1485       NULL, store_scanline_a2b10g10r10 },
1486     
1487     { PIXMAN_x2b10g10r10,
1488       NULL, fetch_scanline_x2b10g10r10,
1489       fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10,
1490       NULL, store_scanline_x2b10g10r10 },
1491     
1492 /* YUV formats */
1493     { PIXMAN_yuy2,
1494       fetch_scanline_yuy2, fetch_scanline_generic_64,
1495       fetch_pixel_yuy2, fetch_pixel_generic_64,
1496       NULL, NULL },
1497     
1498     { PIXMAN_yv12,
1499       fetch_scanline_yv12, fetch_scanline_generic_64,
1500       fetch_pixel_yv12, fetch_pixel_generic_64,
1501       NULL, NULL },
1502     
1503     { PIXMAN_null },
1504 };
1505
1506 static void
1507 setup_accessors (bits_image_t *image)
1508 {
1509     const format_info_t *info = accessors;
1510     
1511     while (info->format != PIXMAN_null)
1512     {
1513         if (info->format == image->format)
1514         {
1515             image->fetch_scanline_32 = info->fetch_scanline_32;
1516             image->fetch_scanline_64 = info->fetch_scanline_64;
1517             image->fetch_pixel_32 = info->fetch_pixel_32;
1518             image->fetch_pixel_64 = info->fetch_pixel_64;
1519             image->store_scanline_32 = info->store_scanline_32;
1520             image->store_scanline_64 = info->store_scanline_64;
1521             
1522             return;
1523         }
1524         
1525         info++;
1526     }
1527 }
1528
1529 #ifndef PIXMAN_FB_ACCESSORS
1530 void
1531 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1532
1533 void
1534 _pixman_bits_image_setup_accessors (bits_image_t *image)
1535 {
1536     if (image->read_func || image->write_func)
1537         _pixman_bits_image_setup_accessors_accessors (image);
1538     else
1539         setup_accessors (image);
1540 }
1541
1542 #else
1543
1544 void
1545 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1546 {
1547     setup_accessors (image);
1548 }
1549
1550 #endif