Android Runtime Detection Support For ARM NEON
[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 #ifdef WORDS_BIGENDIAN
60 #define FETCH_1(img,l,o)                                                \
61     (((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> (0x1f - ((o) & 0x1f))) & 0x1)
62 #else
63 #define FETCH_1(img,l,o)                                                \
64     ((((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> ((o) & 0x1f))) & 0x1)
65 #endif
66
67 #define FETCH_8(img,l,o)    (READ (img, (((uint8_t *)(l)) + ((o) >> 3))))
68
69 #ifdef WORDS_BIGENDIAN
70 #define FETCH_4(img,l,o)                                                \
71     (((4 * (o)) & 4) ? (FETCH_8 (img,l, 4 * (o)) & 0xf) : (FETCH_8 (img,l,(4 * (o))) >> 4))
72 #else
73 #define FETCH_4(img,l,o)                                                \
74     (((4 * (o)) & 4) ? (FETCH_8 (img, l, 4 * (o)) >> 4) : (FETCH_8 (img, l, (4 * (o))) & 0xf))
75 #endif
76
77 #ifdef WORDS_BIGENDIAN
78 #define FETCH_24(img,l,o)                                              \
79     ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16)    |       \
80      (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)     |       \
81      (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
82 #else
83 #define FETCH_24(img,l,o)                                               \
84     ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0)      |       \
85      (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)      |       \
86      (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16))
87 #endif
88
89 /* Store macros */
90
91 #ifdef WORDS_BIGENDIAN
92 #define STORE_1(img,l,o,v)                                              \
93     do                                                                  \
94     {                                                                   \
95         uint32_t  *__d = ((uint32_t *)(l)) + ((o) >> 5);                \
96         uint32_t __m, __v;                                              \
97                                                                         \
98         __m = 1 << (0x1f - ((o) & 0x1f));                               \
99         __v = (v)? __m : 0;                                             \
100                                                                         \
101         WRITE((img), __d, (READ((img), __d) & ~__m) | __v);             \
102     }                                                                   \
103     while (0)
104 #else
105 #define STORE_1(img,l,o,v)                                              \
106     do                                                                  \
107     {                                                                   \
108         uint32_t  *__d = ((uint32_t *)(l)) + ((o) >> 5);                \
109         uint32_t __m, __v;                                              \
110                                                                         \
111         __m = 1 << ((o) & 0x1f);                                        \
112         __v = (v)? __m : 0;                                             \
113                                                                         \
114         WRITE((img), __d, (READ((img), __d) & ~__m) | __v);             \
115     }                                                                   \
116     while (0)
117 #endif
118
119 #define STORE_8(img,l,o,v)  (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v)))
120
121 #ifdef WORDS_BIGENDIAN
122 #define STORE_4(img,l,o,v)                                              \
123     do                                                                  \
124     {                                                                   \
125         int bo = 4 * (o);                                               \
126         int v4 = (v) & 0x0f;                                            \
127                                                                         \
128         STORE_8 (img, l, bo, (                                          \
129                      bo & 4 ?                                           \
130                      (FETCH_8 (img, l, bo) & 0xf0) | (v4) :             \
131                      (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4)));       \
132     } while (0)
133 #else
134 #define STORE_4(img,l,o,v)                                              \
135     do                                                                  \
136     {                                                                   \
137         int bo = 4 * (o);                                               \
138         int v4 = (v) & 0x0f;                                            \
139                                                                         \
140         STORE_8 (img, l, bo, (                                          \
141                      bo & 4 ?                                           \
142                      (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) :        \
143                      (FETCH_8 (img, l, bo) & 0xf0) | (v4)));            \
144     } while (0)
145 #endif
146
147 #ifdef WORDS_BIGENDIAN
148 #define STORE_24(img,l,o,v)                                            \
149     do                                                                 \
150     {                                                                  \
151         uint8_t *__tmp = (l) + 3 * (o);                                \
152                                                                        \
153         WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16);              \
154         WRITE ((img), __tmp++, ((v) & 0x0000ff00) >>  8);              \
155         WRITE ((img), __tmp++, ((v) & 0x000000ff) >>  0);              \
156     }                                                                  \
157     while (0)
158 #else
159 #define STORE_24(img,l,o,v)                                            \
160     do                                                                 \
161     {                                                                  \
162         uint8_t *__tmp = (l) + 3 * (o);                                \
163                                                                        \
164         WRITE ((img), __tmp++, ((v) & 0x000000ff) >>  0);              \
165         WRITE ((img), __tmp++, ((v) & 0x0000ff00) >>  8);              \
166         WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16);              \
167     }                                                                  \
168     while (0)
169 #endif
170
171 /*
172  * YV12 setup and access macros
173  */
174
175 #define YV12_SETUP(image)                                               \
176     bits_image_t *__bits_image = (bits_image_t *)image;                 \
177     uint32_t *bits = __bits_image->bits;                                \
178     int stride = __bits_image->rowstride;                               \
179     int offset0 = stride < 0 ?                                          \
180     ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride :     \
181     stride * __bits_image->height;                                      \
182     int offset1 = stride < 0 ?                                          \
183     offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) :        \
184         offset0 + (offset0 >> 2)
185
186 /* Note no trailing semicolon on the above macro; if it's there, then
187  * the typical usage of YV12_SETUP(image); will have an extra trailing ;
188  * that some compilers will interpret as a statement -- and then any further
189  * variable declarations will cause an error.
190  */
191
192 #define YV12_Y(line)                                                    \
193     ((uint8_t *) ((bits) + (stride) * (line)))
194
195 #define YV12_U(line)                                                    \
196     ((uint8_t *) ((bits) + offset1 +                                    \
197                   ((stride) >> 1) * ((line) >> 1)))
198
199 #define YV12_V(line)                                                    \
200     ((uint8_t *) ((bits) + offset0 +                                    \
201                   ((stride) >> 1) * ((line) >> 1)))
202
203 /* Misc. helpers */
204
205 static force_inline void
206 get_shifts (pixman_format_code_t  format,
207             int                  *a,
208             int                  *r,
209             int                  *g,
210             int                  *b)
211 {
212     switch (PIXMAN_FORMAT_TYPE (format))
213     {
214     case PIXMAN_TYPE_A:
215         *b = 0;
216         *g = 0;
217         *r = 0;
218         *a = 0;
219         break;
220
221     case PIXMAN_TYPE_ARGB:
222         *b = 0;
223         *g = *b + PIXMAN_FORMAT_B (format);
224         *r = *g + PIXMAN_FORMAT_G (format);
225         *a = *r + PIXMAN_FORMAT_R (format);
226         break;
227
228     case PIXMAN_TYPE_ABGR:
229         *r = 0;
230         *g = *r + PIXMAN_FORMAT_R (format);
231         *b = *g + PIXMAN_FORMAT_G (format);
232         *a = *b + PIXMAN_FORMAT_B (format);
233         break;
234
235     case PIXMAN_TYPE_BGRA:
236         /* With BGRA formats we start counting at the high end of the pixel */
237         *b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
238         *g = *b - PIXMAN_FORMAT_B (format);
239         *r = *g - PIXMAN_FORMAT_G (format);
240         *a = *r - PIXMAN_FORMAT_R (format);
241         break;
242
243     case PIXMAN_TYPE_RGBA:
244         /* With BGRA formats we start counting at the high end of the pixel */
245         *r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
246         *g = *r - PIXMAN_FORMAT_R (format);
247         *b = *g - PIXMAN_FORMAT_G (format);
248         *a = *b - PIXMAN_FORMAT_B (format);
249         break;
250
251     default:
252         assert (0);
253         break;
254     }
255 }
256
257 static force_inline uint32_t
258 convert_channel (uint32_t pixel, uint32_t def_value,
259                  int n_from_bits, int from_shift,
260                  int n_to_bits, int to_shift)
261 {
262     uint32_t v;
263
264     if (n_from_bits && n_to_bits)
265         v  = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits);
266     else if (n_to_bits)
267         v = def_value;
268     else
269         v = 0;
270
271     return (v & ((1 << n_to_bits) - 1)) << to_shift;
272 }
273
274 static force_inline uint32_t
275 convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel)
276 {
277     int a_from_shift, r_from_shift, g_from_shift, b_from_shift;
278     int a_to_shift, r_to_shift, g_to_shift, b_to_shift;
279     uint32_t a, r, g, b;
280
281     get_shifts (from, &a_from_shift, &r_from_shift, &g_from_shift, &b_from_shift);
282     get_shifts (to, &a_to_shift, &r_to_shift, &g_to_shift, &b_to_shift);
283
284     a = convert_channel (pixel, ~0,
285                          PIXMAN_FORMAT_A (from), a_from_shift,
286                          PIXMAN_FORMAT_A (to), a_to_shift);
287
288     r = convert_channel (pixel, 0,
289                          PIXMAN_FORMAT_R (from), r_from_shift,
290                          PIXMAN_FORMAT_R (to), r_to_shift);
291
292     g = convert_channel (pixel, 0,
293                          PIXMAN_FORMAT_G (from), g_from_shift,
294                          PIXMAN_FORMAT_G (to), g_to_shift);
295
296     b = convert_channel (pixel, 0,
297                          PIXMAN_FORMAT_B (from), b_from_shift,
298                          PIXMAN_FORMAT_B (to), b_to_shift);
299
300     return a | r | g | b;
301 }
302
303 static force_inline uint32_t
304 convert_pixel_to_a8r8g8b8 (pixman_image_t *image,
305                            pixman_format_code_t format,
306                            uint32_t pixel)
307 {
308     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY         ||
309         PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
310     {
311         return image->bits.indexed->rgba[pixel];
312     }
313     else
314     {
315         return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
316     }
317 }
318
319 static force_inline uint32_t
320 convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
321                              pixman_format_code_t format, uint32_t pixel)
322 {
323     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
324     {
325         pixel = CONVERT_RGB24_TO_Y15 (pixel);
326
327         return image->bits.indexed->ent[pixel & 0x7fff];
328     }
329     else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
330     {
331         pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel);
332
333         return image->bits.indexed->ent[pixel & 0x7fff];
334     }
335     else
336     {
337         return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
338     }
339 }
340
341 static force_inline uint32_t
342 fetch_and_convert_pixel (pixman_image_t *       image,
343                          const uint8_t *        bits,
344                          int                    offset,
345                          pixman_format_code_t   format)
346 {
347     uint32_t pixel;
348
349     switch (PIXMAN_FORMAT_BPP (format))
350     {
351     case 1:
352         pixel = FETCH_1 (image, bits, offset);
353         break;
354
355     case 4:
356         pixel = FETCH_4 (image, bits, offset);
357         break;
358
359     case 8:
360         pixel = READ (image, bits + offset);
361         break;
362
363     case 16:
364         pixel = READ (image, ((uint16_t *)bits + offset));
365         break;
366
367     case 24:
368         pixel = FETCH_24 (image, bits, offset);
369         break;
370
371     case 32:
372         pixel = READ (image, ((uint32_t *)bits + offset));
373         break;
374
375     default:
376         pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
377         break;
378     }
379
380     return convert_pixel_to_a8r8g8b8 (image, format, pixel);
381 }
382
383 static force_inline void
384 convert_and_store_pixel (bits_image_t *         image,
385                          uint8_t *              dest,
386                          int                    offset,
387                          pixman_format_code_t   format,
388                          uint32_t               pixel)
389 {
390     uint32_t converted = convert_pixel_from_a8r8g8b8 (
391         (pixman_image_t *)image, format, pixel);
392
393     switch (PIXMAN_FORMAT_BPP (format))
394     {
395     case 1:
396         STORE_1 (image, dest, offset, converted & 0x01);
397         break;
398
399     case 4:
400         STORE_4 (image, dest, offset, converted & 0xf);
401         break;
402
403     case 8:
404         WRITE (image, (dest + offset), converted & 0xff);
405         break;
406
407     case 16:
408         WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
409         break;
410
411     case 24:
412         STORE_24 (image, dest, offset, converted);
413         break;
414
415     case 32:
416         WRITE (image, ((uint32_t *)dest + offset), converted);
417         break;
418
419     default:
420         *dest = 0x0;
421         break;
422     }
423 }
424
425 #define MAKE_ACCESSORS(format)                                          \
426     static void                                                         \
427     fetch_scanline_ ## format (pixman_image_t *image,                   \
428                                int             x,                       \
429                                int             y,                       \
430                                int             width,                   \
431                                uint32_t *      buffer,                  \
432                                const uint32_t *mask)                    \
433     {                                                                   \
434         uint8_t *bits =                                                 \
435             (uint8_t *)(image->bits.bits + y * image->bits.rowstride);  \
436         int i;                                                          \
437                                                                         \
438         for (i = 0; i < width; ++i)                                     \
439         {                                                               \
440             *buffer++ =                                                 \
441                 fetch_and_convert_pixel (image, bits, x + i, PIXMAN_ ## format); \
442         }                                                               \
443     }                                                                   \
444                                                                         \
445     static void                                                         \
446     store_scanline_ ## format (bits_image_t *  image,                   \
447                                int             x,                       \
448                                int             y,                       \
449                                int             width,                   \
450                                const uint32_t *values)                  \
451     {                                                                   \
452         uint8_t *dest =                                                 \
453             (uint8_t *)(image->bits + y * image->rowstride);            \
454         int i;                                                          \
455                                                                         \
456         for (i = 0; i < width; ++i)                                     \
457         {                                                               \
458             convert_and_store_pixel (                                   \
459                 image, dest, i + x, PIXMAN_ ## format, values[i]);      \
460         }                                                               \
461     }                                                                   \
462                                                                         \
463     static uint32_t                                                     \
464     fetch_pixel_ ## format (bits_image_t *image,                        \
465                             int         offset,                         \
466                             int         line)                           \
467     {                                                                   \
468         uint8_t *bits =                                                 \
469             (uint8_t *)(image->bits + line * image->rowstride);         \
470                                                                         \
471         return fetch_and_convert_pixel ((pixman_image_t *)image,        \
472                                         bits, offset, PIXMAN_ ## format); \
473     }                                                                   \
474                                                                         \
475     static const void *const __dummy__ ## format
476
477 MAKE_ACCESSORS(a8r8g8b8);
478 MAKE_ACCESSORS(x8r8g8b8);
479 MAKE_ACCESSORS(a8b8g8r8);
480 MAKE_ACCESSORS(x8b8g8r8);
481 MAKE_ACCESSORS(x14r6g6b6);
482 MAKE_ACCESSORS(b8g8r8a8);
483 MAKE_ACCESSORS(b8g8r8x8);
484 MAKE_ACCESSORS(r8g8b8x8);
485 MAKE_ACCESSORS(r8g8b8a8);
486 MAKE_ACCESSORS(r8g8b8);
487 MAKE_ACCESSORS(b8g8r8);
488 MAKE_ACCESSORS(r5g6b5);
489 MAKE_ACCESSORS(b5g6r5);
490 MAKE_ACCESSORS(a1r5g5b5);
491 MAKE_ACCESSORS(x1r5g5b5);
492 MAKE_ACCESSORS(a1b5g5r5);
493 MAKE_ACCESSORS(x1b5g5r5);
494 MAKE_ACCESSORS(a4r4g4b4);
495 MAKE_ACCESSORS(x4r4g4b4);
496 MAKE_ACCESSORS(a4b4g4r4);
497 MAKE_ACCESSORS(x4b4g4r4);
498 MAKE_ACCESSORS(a8);
499 MAKE_ACCESSORS(c8);
500 MAKE_ACCESSORS(g8);
501 MAKE_ACCESSORS(r3g3b2);
502 MAKE_ACCESSORS(b2g3r3);
503 MAKE_ACCESSORS(a2r2g2b2);
504 MAKE_ACCESSORS(a2b2g2r2);
505 MAKE_ACCESSORS(x4a4);
506 MAKE_ACCESSORS(a4);
507 MAKE_ACCESSORS(g4);
508 MAKE_ACCESSORS(c4);
509 MAKE_ACCESSORS(r1g2b1);
510 MAKE_ACCESSORS(b1g2r1);
511 MAKE_ACCESSORS(a1r1g1b1);
512 MAKE_ACCESSORS(a1b1g1r1);
513 MAKE_ACCESSORS(a1);
514 MAKE_ACCESSORS(g1);
515
516 /********************************** Fetch ************************************/
517
518 /* Expects a uint64_t buffer */
519 static void
520 fetch_scanline_a2r10g10b10 (pixman_image_t *image,
521                             int             x,
522                             int             y,
523                             int             width,
524                             uint32_t *      b,
525                             const uint32_t *mask)
526 {
527     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
528     const uint32_t *pixel = bits + x;
529     const uint32_t *end = pixel + width;
530     uint64_t *buffer = (uint64_t *)b;
531
532     while (pixel < end)
533     {
534         uint32_t p = READ (image, pixel++);
535         uint64_t a = p >> 30;
536         uint64_t r = (p >> 20) & 0x3ff;
537         uint64_t g = (p >> 10) & 0x3ff;
538         uint64_t b = p & 0x3ff;
539
540         r = r << 6 | r >> 4;
541         g = g << 6 | g >> 4;
542         b = b << 6 | b >> 4;
543
544         a <<= 14;
545         a |= a >> 2;
546         a |= a >> 4;
547         a |= a >> 8;
548
549         *buffer++ = a << 48 | r << 32 | g << 16 | b;
550     }
551 }
552
553 /* Expects a uint64_t buffer */
554 static void
555 fetch_scanline_x2r10g10b10 (pixman_image_t *image,
556                             int             x,
557                             int             y,
558                             int             width,
559                             uint32_t *      b,
560                             const uint32_t *mask)
561 {
562     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
563     const uint32_t *pixel = (uint32_t *)bits + x;
564     const uint32_t *end = pixel + width;
565     uint64_t *buffer = (uint64_t *)b;
566     
567     while (pixel < end)
568     {
569         uint32_t p = READ (image, pixel++);
570         uint64_t r = (p >> 20) & 0x3ff;
571         uint64_t g = (p >> 10) & 0x3ff;
572         uint64_t b = p & 0x3ff;
573         
574         r = r << 6 | r >> 4;
575         g = g << 6 | g >> 4;
576         b = b << 6 | b >> 4;
577         
578         *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
579     }
580 }
581
582 /* Expects a uint64_t buffer */
583 static void
584 fetch_scanline_a2b10g10r10 (pixman_image_t *image,
585                             int             x,
586                             int             y,
587                             int             width,
588                             uint32_t *      b,
589                             const uint32_t *mask)
590 {
591     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
592     const uint32_t *pixel = bits + x;
593     const uint32_t *end = pixel + width;
594     uint64_t *buffer = (uint64_t *)b;
595     
596     while (pixel < end)
597     {
598         uint32_t p = READ (image, pixel++);
599         uint64_t a = p >> 30;
600         uint64_t b = (p >> 20) & 0x3ff;
601         uint64_t g = (p >> 10) & 0x3ff;
602         uint64_t r = p & 0x3ff;
603         
604         r = r << 6 | r >> 4;
605         g = g << 6 | g >> 4;
606         b = b << 6 | b >> 4;
607         
608         a <<= 14;
609         a |= a >> 2;
610         a |= a >> 4;
611         a |= a >> 8;
612
613         *buffer++ = a << 48 | r << 32 | g << 16 | b;
614     }
615 }
616
617 /* Expects a uint64_t buffer */
618 static void
619 fetch_scanline_x2b10g10r10 (pixman_image_t *image,
620                             int             x,
621                             int             y,
622                             int             width,
623                             uint32_t *      b,
624                             const uint32_t *mask)
625 {
626     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
627     const uint32_t *pixel = (uint32_t *)bits + x;
628     const uint32_t *end = pixel + width;
629     uint64_t *buffer = (uint64_t *)b;
630     
631     while (pixel < end)
632     {
633         uint32_t p = READ (image, pixel++);
634         uint64_t b = (p >> 20) & 0x3ff;
635         uint64_t g = (p >> 10) & 0x3ff;
636         uint64_t r = p & 0x3ff;
637         
638         r = r << 6 | r >> 4;
639         g = g << 6 | g >> 4;
640         b = b << 6 | b >> 4;
641         
642         *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b;
643     }
644 }
645
646 static void
647 fetch_scanline_yuy2 (pixman_image_t *image,
648                      int             x,
649                      int             line,
650                      int             width,
651                      uint32_t *      buffer,
652                      const uint32_t *mask)
653 {
654     const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
655     int i;
656     
657     for (i = 0; i < width; i++)
658     {
659         int16_t y, u, v;
660         int32_t r, g, b;
661         
662         y = ((uint8_t *) bits)[(x + i) << 1] - 16;
663         u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
664         v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
665         
666         /* R = 1.164(Y - 16) + 1.596(V - 128) */
667         r = 0x012b27 * y + 0x019a2e * v;
668         /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
669         g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
670         /* B = 1.164(Y - 16) + 2.018(U - 128) */
671         b = 0x012b27 * y + 0x0206a2 * u;
672         
673         *buffer++ = 0xff000000 |
674             (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
675             (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
676             (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
677     }
678 }
679
680 static void
681 fetch_scanline_yv12 (pixman_image_t *image,
682                      int             x,
683                      int             line,
684                      int             width,
685                      uint32_t *      buffer,
686                      const uint32_t *mask)
687 {
688     YV12_SETUP (image);
689     uint8_t *y_line = YV12_Y (line);
690     uint8_t *u_line = YV12_U (line);
691     uint8_t *v_line = YV12_V (line);
692     int i;
693     
694     for (i = 0; i < width; i++)
695     {
696         int16_t y, u, v;
697         int32_t r, g, b;
698
699         y = y_line[x + i] - 16;
700         u = u_line[(x + i) >> 1] - 128;
701         v = v_line[(x + i) >> 1] - 128;
702
703         /* R = 1.164(Y - 16) + 1.596(V - 128) */
704         r = 0x012b27 * y + 0x019a2e * v;
705         /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
706         g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
707         /* B = 1.164(Y - 16) + 2.018(U - 128) */
708         b = 0x012b27 * y + 0x0206a2 * u;
709
710         *buffer++ = 0xff000000 |
711             (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
712             (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
713             (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
714     }
715 }
716
717 /**************************** Pixel wise fetching *****************************/
718
719 /* Despite the type, expects a uint64_t buffer */
720 static uint64_t
721 fetch_pixel_a2r10g10b10 (bits_image_t *image,
722                          int              offset,
723                          int           line)
724 {
725     uint32_t *bits = image->bits + line * image->rowstride;
726     uint32_t p = READ (image, bits + offset);
727     uint64_t a = p >> 30;
728     uint64_t r = (p >> 20) & 0x3ff;
729     uint64_t g = (p >> 10) & 0x3ff;
730     uint64_t b = p & 0x3ff;
731
732     r = r << 6 | r >> 4;
733     g = g << 6 | g >> 4;
734     b = b << 6 | b >> 4;
735
736     a <<= 14;
737     a |= a >> 2;
738     a |= a >> 4;
739     a |= a >> 8;
740
741     return a << 48 | r << 32 | g << 16 | b;
742 }
743
744 /* Despite the type, this function expects a uint64_t buffer */
745 static uint64_t
746 fetch_pixel_x2r10g10b10 (bits_image_t *image,
747                          int       offset,
748                          int           line)
749 {
750     uint32_t *bits = image->bits + line * image->rowstride;
751     uint32_t p = READ (image, bits + offset);
752     uint64_t r = (p >> 20) & 0x3ff;
753     uint64_t g = (p >> 10) & 0x3ff;
754     uint64_t b = p & 0x3ff;
755     
756     r = r << 6 | r >> 4;
757     g = g << 6 | g >> 4;
758     b = b << 6 | b >> 4;
759     
760     return 0xffffULL << 48 | r << 32 | g << 16 | b;
761 }
762
763 /* Despite the type, expects a uint64_t buffer */
764 static uint64_t
765 fetch_pixel_a2b10g10r10 (bits_image_t *image,
766                          int           offset,
767                          int           line)
768 {
769     uint32_t *bits = image->bits + line * image->rowstride;
770     uint32_t p = READ (image, bits + offset);
771     uint64_t a = p >> 30;
772     uint64_t b = (p >> 20) & 0x3ff;
773     uint64_t g = (p >> 10) & 0x3ff;
774     uint64_t r = p & 0x3ff;
775     
776     r = r << 6 | r >> 4;
777     g = g << 6 | g >> 4;
778     b = b << 6 | b >> 4;
779     
780     a <<= 14;
781     a |= a >> 2;
782     a |= a >> 4;
783     a |= a >> 8;
784     
785     return a << 48 | r << 32 | g << 16 | b;
786 }
787
788 /* Despite the type, this function expects a uint64_t buffer */
789 static uint64_t
790 fetch_pixel_x2b10g10r10 (bits_image_t *image,
791                          int           offset,
792                          int           line)
793 {
794     uint32_t *bits = image->bits + line * image->rowstride;
795     uint32_t p = READ (image, bits + offset);
796     uint64_t b = (p >> 20) & 0x3ff;
797     uint64_t g = (p >> 10) & 0x3ff;
798     uint64_t r = p & 0x3ff;
799     
800     r = r << 6 | r >> 4;
801     g = g << 6 | g >> 4;
802     b = b << 6 | b >> 4;
803     
804     return 0xffffULL << 48 | r << 32 | g << 16 | b;
805 }
806
807 static uint32_t
808 fetch_pixel_yuy2 (bits_image_t *image,
809                   int           offset,
810                   int           line)
811 {
812     const uint32_t *bits = image->bits + image->rowstride * line;
813     
814     int16_t y, u, v;
815     int32_t r, g, b;
816     
817     y = ((uint8_t *) bits)[offset << 1] - 16;
818     u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
819     v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
820     
821     /* R = 1.164(Y - 16) + 1.596(V - 128) */
822     r = 0x012b27 * y + 0x019a2e * v;
823     
824     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
825     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
826     
827     /* B = 1.164(Y - 16) + 2.018(U - 128) */
828     b = 0x012b27 * y + 0x0206a2 * u;
829     
830     return 0xff000000 |
831         (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
832         (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
833         (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
834 }
835
836 static uint32_t
837 fetch_pixel_yv12 (bits_image_t *image,
838                   int           offset,
839                   int           line)
840 {
841     YV12_SETUP (image);
842     int16_t y = YV12_Y (line)[offset] - 16;
843     int16_t u = YV12_U (line)[offset >> 1] - 128;
844     int16_t v = YV12_V (line)[offset >> 1] - 128;
845     int32_t r, g, b;
846     
847     /* R = 1.164(Y - 16) + 1.596(V - 128) */
848     r = 0x012b27 * y + 0x019a2e * v;
849     
850     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
851     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
852     
853     /* B = 1.164(Y - 16) + 2.018(U - 128) */
854     b = 0x012b27 * y + 0x0206a2 * u;
855     
856     return 0xff000000 |
857         (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
858         (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
859         (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
860 }
861
862 /*********************************** Store ************************************/
863
864 static void
865 store_scanline_a2r10g10b10 (bits_image_t *  image,
866                             int             x,
867                             int             y,
868                             int             width,
869                             const uint32_t *v)
870 {
871     uint32_t *bits = image->bits + image->rowstride * y;
872     uint32_t *pixel = bits + x;
873     uint64_t *values = (uint64_t *)v;
874     int i;
875     
876     for (i = 0; i < width; ++i)
877     {
878         WRITE (image, pixel++,
879                ((values[i] >> 32) & 0xc0000000) |
880                ((values[i] >> 18) & 0x3ff00000) |
881                ((values[i] >> 12) & 0xffc00) | 
882                ((values[i] >> 6) & 0x3ff));    
883     }
884 }
885
886 static void
887 store_scanline_x2r10g10b10 (bits_image_t *  image,
888                             int             x,
889                             int             y,
890                             int             width,
891                             const uint32_t *v)
892 {
893     uint32_t *bits = image->bits + image->rowstride * y;
894     uint64_t *values = (uint64_t *)v;
895     uint32_t *pixel = bits + x;
896     int i;
897     
898     for (i = 0; i < width; ++i)
899     {
900         WRITE (image, pixel++,
901                ((values[i] >> 18) & 0x3ff00000) | 
902                ((values[i] >> 12) & 0xffc00) |
903                ((values[i] >> 6) & 0x3ff));
904     }
905 }
906
907 static void
908 store_scanline_a2b10g10r10 (bits_image_t *  image,
909                             int             x,
910                             int             y,
911                             int             width,
912                             const uint32_t *v)
913 {
914     uint32_t *bits = image->bits + image->rowstride * y;
915     uint32_t *pixel = bits + x;
916     uint64_t *values = (uint64_t *)v;
917     int i;
918     
919     for (i = 0; i < width; ++i)
920     {
921         WRITE (image, pixel++,
922                ((values[i] >> 32) & 0xc0000000) |
923                ((values[i] >> 38) & 0x3ff) |
924                ((values[i] >> 12) & 0xffc00) |
925                ((values[i] << 14) & 0x3ff00000));
926     }
927 }
928
929 static void
930 store_scanline_x2b10g10r10 (bits_image_t *  image,
931                             int             x,
932                             int             y,
933                             int             width,
934                             const uint32_t *v)
935 {
936     uint32_t *bits = image->bits + image->rowstride * y;
937     uint64_t *values = (uint64_t *)v;
938     uint32_t *pixel = bits + x;
939     int i;
940     
941     for (i = 0; i < width; ++i)
942     {
943         WRITE (image, pixel++,
944                ((values[i] >> 38) & 0x3ff) |
945                ((values[i] >> 12) & 0xffc00) |
946                ((values[i] << 14) & 0x3ff00000));
947     }
948 }
949
950 /*
951  * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit
952  * store proc. Despite the type, this function expects a uint64_t buffer.
953  */
954 static void
955 store_scanline_generic_64 (bits_image_t *  image,
956                            int             x,
957                            int             y,
958                            int             width,
959                            const uint32_t *values)
960 {
961     uint32_t *argb8_pixels;
962     
963     assert (image->common.type == BITS);
964     
965     argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
966     if (!argb8_pixels)
967         return;
968     
969     /* Contract the scanline.  We could do this in place if values weren't
970      * const.
971      */
972     pixman_contract (argb8_pixels, (uint64_t *)values, width);
973     
974     image->store_scanline_32 (image, x, y, width, argb8_pixels);
975     
976     free (argb8_pixels);
977 }
978
979 /* Despite the type, this function expects both buffer
980  * and mask to be uint64_t
981  */
982 static void
983 fetch_scanline_generic_64 (pixman_image_t *image,
984                            int             x,
985                            int             y,
986                            int             width,
987                            uint32_t *      buffer,
988                            const uint32_t *mask)
989 {
990     pixman_format_code_t format;
991
992     /* Fetch the pixels into the first half of buffer and then expand them in
993      * place.
994      */
995     image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
996
997     format = image->bits.format;
998     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR        ||
999         PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
1000     {
1001         /* Indexed formats are mapped to a8r8g8b8 with full
1002          * precision, so when expanding we shouldn't correct
1003          * for the width of the channels
1004          */
1005
1006         format = PIXMAN_a8r8g8b8;
1007     }
1008
1009     pixman_expand ((uint64_t *)buffer, buffer, format, width);
1010 }
1011
1012 /* Despite the type, this function expects a uint64_t *buffer */
1013 static uint64_t
1014 fetch_pixel_generic_64 (bits_image_t *image,
1015                         int           offset,
1016                         int           line)
1017 {
1018     uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1019     uint64_t result;
1020     pixman_format_code_t format;
1021
1022     format = image->format;
1023     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR        ||
1024         PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
1025     {
1026         /* Indexed formats are mapped to a8r8g8b8 with full
1027          * precision, so when expanding we shouldn't correct
1028          * for the width of the channels
1029          */
1030
1031         format = PIXMAN_a8r8g8b8;
1032     }
1033
1034     pixman_expand ((uint64_t *)&result, &pixel32, format, 1);
1035
1036     return result;
1037 }
1038
1039 /*
1040  * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1041  * paths have wide versions, this can be removed.
1042  *
1043  * WARNING: This function loses precision!
1044  */
1045 static uint32_t
1046 fetch_pixel_generic_lossy_32 (bits_image_t *image,
1047                               int           offset,
1048                               int           line)
1049 {
1050     uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line);
1051     uint32_t result;
1052
1053     pixman_contract (&result, &pixel64, 1);
1054
1055     return result;
1056 }
1057
1058 typedef struct
1059 {
1060     pixman_format_code_t        format;
1061     fetch_scanline_t            fetch_scanline_32;
1062     fetch_scanline_t            fetch_scanline_64;
1063     fetch_pixel_32_t            fetch_pixel_32;
1064     fetch_pixel_64_t            fetch_pixel_64;
1065     store_scanline_t            store_scanline_32;
1066     store_scanline_t            store_scanline_64;
1067 } format_info_t;
1068
1069 #define FORMAT_INFO(format)                                             \
1070     {                                                                   \
1071         PIXMAN_ ## format,                                              \
1072             fetch_scanline_ ## format,                                  \
1073             fetch_scanline_generic_64,                                  \
1074             fetch_pixel_ ## format, fetch_pixel_generic_64,             \
1075             store_scanline_ ## format, store_scanline_generic_64        \
1076     }
1077
1078 static const format_info_t accessors[] =
1079 {
1080 /* 32 bpp formats */
1081     FORMAT_INFO (a8r8g8b8),
1082     FORMAT_INFO (x8r8g8b8),
1083     FORMAT_INFO (a8b8g8r8),
1084     FORMAT_INFO (x8b8g8r8),
1085     FORMAT_INFO (b8g8r8a8),
1086     FORMAT_INFO (b8g8r8x8),
1087     FORMAT_INFO (r8g8b8a8),
1088     FORMAT_INFO (r8g8b8x8),
1089     FORMAT_INFO (x14r6g6b6),
1090
1091 /* 24bpp formats */
1092     FORMAT_INFO (r8g8b8),
1093     FORMAT_INFO (b8g8r8),
1094     
1095 /* 16bpp formats */
1096     FORMAT_INFO (r5g6b5),
1097     FORMAT_INFO (b5g6r5),
1098     
1099     FORMAT_INFO (a1r5g5b5),
1100     FORMAT_INFO (x1r5g5b5),
1101     FORMAT_INFO (a1b5g5r5),
1102     FORMAT_INFO (x1b5g5r5),
1103     FORMAT_INFO (a4r4g4b4),
1104     FORMAT_INFO (x4r4g4b4),
1105     FORMAT_INFO (a4b4g4r4),
1106     FORMAT_INFO (x4b4g4r4),
1107     
1108 /* 8bpp formats */
1109     FORMAT_INFO (a8),
1110     FORMAT_INFO (r3g3b2),
1111     FORMAT_INFO (b2g3r3),
1112     FORMAT_INFO (a2r2g2b2),
1113     FORMAT_INFO (a2b2g2r2),
1114     
1115     FORMAT_INFO (c8),
1116     
1117     FORMAT_INFO (g8),
1118     
1119 #define fetch_scanline_x4c4 fetch_scanline_c8
1120 #define fetch_pixel_x4c4 fetch_pixel_c8
1121 #define store_scanline_x4c4 store_scanline_c8
1122     FORMAT_INFO (x4c4),
1123     
1124 #define fetch_scanline_x4g4 fetch_scanline_g8
1125 #define fetch_pixel_x4g4 fetch_pixel_g8
1126 #define store_scanline_x4g4 store_scanline_g8
1127     FORMAT_INFO (x4g4),
1128     
1129     FORMAT_INFO (x4a4),
1130     
1131 /* 4bpp formats */
1132     FORMAT_INFO (a4),
1133     FORMAT_INFO (r1g2b1),
1134     FORMAT_INFO (b1g2r1),
1135     FORMAT_INFO (a1r1g1b1),
1136     FORMAT_INFO (a1b1g1r1),
1137     
1138     FORMAT_INFO (c4),
1139     
1140     FORMAT_INFO (g4),
1141     
1142 /* 1bpp formats */
1143     FORMAT_INFO (a1),
1144     FORMAT_INFO (g1),
1145     
1146 /* Wide formats */
1147     
1148     { PIXMAN_a2r10g10b10,
1149       NULL, fetch_scanline_a2r10g10b10,
1150       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10,
1151       NULL, store_scanline_a2r10g10b10 },
1152     
1153     { PIXMAN_x2r10g10b10,
1154       NULL, fetch_scanline_x2r10g10b10,
1155       fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10,
1156       NULL, store_scanline_x2r10g10b10 },
1157     
1158     { PIXMAN_a2b10g10r10,
1159       NULL, fetch_scanline_a2b10g10r10,
1160       fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10,
1161       NULL, store_scanline_a2b10g10r10 },
1162     
1163     { PIXMAN_x2b10g10r10,
1164       NULL, fetch_scanline_x2b10g10r10,
1165       fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10,
1166       NULL, store_scanline_x2b10g10r10 },
1167     
1168 /* YUV formats */
1169     { PIXMAN_yuy2,
1170       fetch_scanline_yuy2, fetch_scanline_generic_64,
1171       fetch_pixel_yuy2, fetch_pixel_generic_64,
1172       NULL, NULL },
1173     
1174     { PIXMAN_yv12,
1175       fetch_scanline_yv12, fetch_scanline_generic_64,
1176       fetch_pixel_yv12, fetch_pixel_generic_64,
1177       NULL, NULL },
1178     
1179     { PIXMAN_null },
1180 };
1181
1182 static void
1183 setup_accessors (bits_image_t *image)
1184 {
1185     const format_info_t *info = accessors;
1186     
1187     while (info->format != PIXMAN_null)
1188     {
1189         if (info->format == image->format)
1190         {
1191             image->fetch_scanline_32 = info->fetch_scanline_32;
1192             image->fetch_scanline_64 = info->fetch_scanline_64;
1193             image->fetch_pixel_32 = info->fetch_pixel_32;
1194             image->fetch_pixel_64 = info->fetch_pixel_64;
1195             image->store_scanline_32 = info->store_scanline_32;
1196             image->store_scanline_64 = info->store_scanline_64;
1197             
1198             return;
1199         }
1200         
1201         info++;
1202     }
1203 }
1204
1205 #ifndef PIXMAN_FB_ACCESSORS
1206 void
1207 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1208
1209 void
1210 _pixman_bits_image_setup_accessors (bits_image_t *image)
1211 {
1212     if (image->read_func || image->write_func)
1213         _pixman_bits_image_setup_accessors_accessors (image);
1214     else
1215         setup_accessors (image);
1216 }
1217
1218 #else
1219
1220 void
1221 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1222 {
1223     setup_accessors (image);
1224 }
1225
1226 #endif