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#include <math.h>
35
36#include "pixman-accessor.h"
37#include "pixman-private.h"
38
39#define CONVERT_RGB24_TO_Y15(s)						\
40    (((((s) >> 16) & 0xff) * 153 +					\
41      (((s) >>  8) & 0xff) * 301 +					\
42      (((s)      ) & 0xff) * 58) >> 2)
43
44#define CONVERT_RGB24_TO_RGB15(s)                                       \
45    ((((s) >> 3) & 0x001f) |                                            \
46     (((s) >> 6) & 0x03e0) |                                            \
47     (((s) >> 9) & 0x7c00))
48
49/* Fetch macros */
50
51#ifdef WORDS_BIGENDIAN
52#define FETCH_1(img,l,o)						\
53    (((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> (0x1f - ((o) & 0x1f))) & 0x1)
54#else
55#define FETCH_1(img,l,o)						\
56    ((((READ ((img), ((uint32_t *)(l)) + ((o) >> 5))) >> ((o) & 0x1f))) & 0x1)
57#endif
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#ifdef WORDS_BIGENDIAN
70#define FETCH_24(img,l,o)                                              \
71    ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16)    |       \
72     (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)     |       \
73     (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
74#else
75#define FETCH_24(img,l,o)						\
76    ((READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0)	|	\
77     (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)	|	\
78     (READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 16))
79#endif
80
81/* Store macros */
82
83#ifdef WORDS_BIGENDIAN
84#define STORE_1(img,l,o,v)						\
85    do									\
86    {									\
87	uint32_t  *__d = ((uint32_t *)(l)) + ((o) >> 5);		\
88	uint32_t __m, __v;						\
89									\
90	__m = 1 << (0x1f - ((o) & 0x1f));				\
91	__v = (v)? __m : 0;						\
92									\
93	WRITE((img), __d, (READ((img), __d) & ~__m) | __v);		\
94    }									\
95    while (0)
96#else
97#define STORE_1(img,l,o,v)						\
98    do									\
99    {									\
100	uint32_t  *__d = ((uint32_t *)(l)) + ((o) >> 5);		\
101	uint32_t __m, __v;						\
102									\
103	__m = 1 << ((o) & 0x1f);					\
104	__v = (v)? __m : 0;						\
105									\
106	WRITE((img), __d, (READ((img), __d) & ~__m) | __v);		\
107    }									\
108    while (0)
109#endif
110
111#define STORE_8(img,l,o,v)  (WRITE (img, (uint8_t *)(l) + ((o) >> 3), (v)))
112
113#ifdef WORDS_BIGENDIAN
114#define STORE_4(img,l,o,v)						\
115    do									\
116    {									\
117	int bo = 4 * (o);						\
118	int v4 = (v) & 0x0f;						\
119									\
120	STORE_8 (img, l, bo, (						\
121		     bo & 4 ?						\
122		     (FETCH_8 (img, l, bo) & 0xf0) | (v4) :		\
123		     (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4)));	\
124    } while (0)
125#else
126#define STORE_4(img,l,o,v)						\
127    do									\
128    {									\
129	int bo = 4 * (o);						\
130	int v4 = (v) & 0x0f;						\
131									\
132	STORE_8 (img, l, bo, (						\
133		     bo & 4 ?						\
134		     (FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) :	\
135		     (FETCH_8 (img, l, bo) & 0xf0) | (v4)));		\
136    } while (0)
137#endif
138
139#ifdef WORDS_BIGENDIAN
140#define STORE_24(img,l,o,v)                                            \
141    do                                                                 \
142    {                                                                  \
143	uint8_t *__tmp = (l) + 3 * (o);				       \
144        							       \
145	WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16);	       \
146	WRITE ((img), __tmp++, ((v) & 0x0000ff00) >>  8);	       \
147	WRITE ((img), __tmp++, ((v) & 0x000000ff) >>  0);	       \
148    }                                                                  \
149    while (0)
150#else
151#define STORE_24(img,l,o,v)                                            \
152    do                                                                 \
153    {                                                                  \
154	uint8_t *__tmp = (l) + 3 * (o);				       \
155        							       \
156	WRITE ((img), __tmp++, ((v) & 0x000000ff) >>  0);	       \
157	WRITE ((img), __tmp++, ((v) & 0x0000ff00) >>  8);	       \
158	WRITE ((img), __tmp++, ((v) & 0x00ff0000) >> 16);	       \
159    }								       \
160    while (0)
161#endif
162
163/*
164 * YV12 setup and access macros
165 */
166
167#define YV12_SETUP(image)                                               \
168    bits_image_t *__bits_image = (bits_image_t *)image;                 \
169    uint32_t *bits = __bits_image->bits;                                \
170    int stride = __bits_image->rowstride;                               \
171    int offset0 = stride < 0 ?                                          \
172    ((-stride) >> 1) * ((__bits_image->height - 1) >> 1) - stride :	\
173    stride * __bits_image->height;					\
174    int offset1 = stride < 0 ?                                          \
175    offset0 + ((-stride) >> 1) * ((__bits_image->height) >> 1) :	\
176	offset0 + (offset0 >> 2)
177
178/* Note no trailing semicolon on the above macro; if it's there, then
179 * the typical usage of YV12_SETUP(image); will have an extra trailing ;
180 * that some compilers will interpret as a statement -- and then any further
181 * variable declarations will cause an error.
182 */
183
184#define YV12_Y(line)                                                    \
185    ((uint8_t *) ((bits) + (stride) * (line)))
186
187#define YV12_U(line)                                                    \
188    ((uint8_t *) ((bits) + offset1 +                                    \
189                  ((stride) >> 1) * ((line) >> 1)))
190
191#define YV12_V(line)                                                    \
192    ((uint8_t *) ((bits) + offset0 +                                    \
193                  ((stride) >> 1) * ((line) >> 1)))
194
195/* Misc. helpers */
196
197static force_inline void
198get_shifts (pixman_format_code_t  format,
199	    int			 *a,
200	    int			 *r,
201	    int                  *g,
202	    int                  *b)
203{
204    switch (PIXMAN_FORMAT_TYPE (format))
205    {
206    case PIXMAN_TYPE_A:
207	*b = 0;
208	*g = 0;
209	*r = 0;
210	*a = 0;
211	break;
212
213    case PIXMAN_TYPE_ARGB:
214    case PIXMAN_TYPE_ARGB_SRGB:
215	*b = 0;
216	*g = *b + PIXMAN_FORMAT_B (format);
217	*r = *g + PIXMAN_FORMAT_G (format);
218	*a = *r + PIXMAN_FORMAT_R (format);
219	break;
220
221    case PIXMAN_TYPE_ABGR:
222	*r = 0;
223	*g = *r + PIXMAN_FORMAT_R (format);
224	*b = *g + PIXMAN_FORMAT_G (format);
225	*a = *b + PIXMAN_FORMAT_B (format);
226	break;
227
228    case PIXMAN_TYPE_BGRA:
229	/* With BGRA formats we start counting at the high end of the pixel */
230	*b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
231	*g = *b - PIXMAN_FORMAT_B (format);
232	*r = *g - PIXMAN_FORMAT_G (format);
233	*a = *r - PIXMAN_FORMAT_R (format);
234	break;
235
236    case PIXMAN_TYPE_RGBA:
237	/* With BGRA formats we start counting at the high end of the pixel */
238	*r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
239	*g = *r - PIXMAN_FORMAT_R (format);
240	*b = *g - PIXMAN_FORMAT_G (format);
241	*a = *b - PIXMAN_FORMAT_B (format);
242	break;
243
244    default:
245	assert (0);
246	break;
247    }
248}
249
250static force_inline uint32_t
251convert_channel (uint32_t pixel, uint32_t def_value,
252		 int n_from_bits, int from_shift,
253		 int n_to_bits, int to_shift)
254{
255    uint32_t v;
256
257    if (n_from_bits && n_to_bits)
258	v  = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits);
259    else if (n_to_bits)
260	v = def_value;
261    else
262	v = 0;
263
264    return (v & ((1 << n_to_bits) - 1)) << to_shift;
265}
266
267static force_inline uint32_t
268convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel)
269{
270    int a_from_shift, r_from_shift, g_from_shift, b_from_shift;
271    int a_to_shift, r_to_shift, g_to_shift, b_to_shift;
272    uint32_t a, r, g, b;
273
274    get_shifts (from, &a_from_shift, &r_from_shift, &g_from_shift, &b_from_shift);
275    get_shifts (to, &a_to_shift, &r_to_shift, &g_to_shift, &b_to_shift);
276
277    a = convert_channel (pixel, ~0,
278			 PIXMAN_FORMAT_A (from), a_from_shift,
279			 PIXMAN_FORMAT_A (to), a_to_shift);
280
281    r = convert_channel (pixel, 0,
282			 PIXMAN_FORMAT_R (from), r_from_shift,
283			 PIXMAN_FORMAT_R (to), r_to_shift);
284
285    g = convert_channel (pixel, 0,
286			 PIXMAN_FORMAT_G (from), g_from_shift,
287			 PIXMAN_FORMAT_G (to), g_to_shift);
288
289    b = convert_channel (pixel, 0,
290			 PIXMAN_FORMAT_B (from), b_from_shift,
291			 PIXMAN_FORMAT_B (to), b_to_shift);
292
293    return a | r | g | b;
294}
295
296static force_inline uint32_t
297convert_pixel_to_a8r8g8b8 (pixman_image_t *image,
298			   pixman_format_code_t format,
299			   uint32_t pixel)
300{
301    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY		||
302	PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
303    {
304	return image->bits.indexed->rgba[pixel];
305    }
306    else
307    {
308	return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
309    }
310}
311
312static force_inline uint32_t
313convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
314			     pixman_format_code_t format, uint32_t pixel)
315{
316    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
317    {
318	pixel = CONVERT_RGB24_TO_Y15 (pixel);
319
320	return image->bits.indexed->ent[pixel & 0x7fff];
321    }
322    else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
323    {
324	pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel);
325
326	return image->bits.indexed->ent[pixel & 0x7fff];
327    }
328    else
329    {
330	return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
331    }
332}
333
334static force_inline uint32_t
335fetch_and_convert_pixel (pixman_image_t	*	image,
336			 const uint8_t *	bits,
337			 int			offset,
338			 pixman_format_code_t	format)
339{
340    uint32_t pixel;
341
342    switch (PIXMAN_FORMAT_BPP (format))
343    {
344    case 1:
345	pixel = FETCH_1 (image, bits, offset);
346	break;
347
348    case 4:
349	pixel = FETCH_4 (image, bits, offset);
350	break;
351
352    case 8:
353	pixel = READ (image, bits + offset);
354	break;
355
356    case 16:
357	pixel = READ (image, ((uint16_t *)bits + offset));
358	break;
359
360    case 24:
361	pixel = FETCH_24 (image, bits, offset);
362	break;
363
364    case 32:
365	pixel = READ (image, ((uint32_t *)bits + offset));
366	break;
367
368    default:
369	pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
370	break;
371    }
372
373    return convert_pixel_to_a8r8g8b8 (image, format, pixel);
374}
375
376static force_inline void
377convert_and_store_pixel (bits_image_t *		image,
378			 uint8_t *		dest,
379			 int                    offset,
380			 pixman_format_code_t	format,
381			 uint32_t		pixel)
382{
383    uint32_t converted = convert_pixel_from_a8r8g8b8 (
384	(pixman_image_t *)image, format, pixel);
385
386    switch (PIXMAN_FORMAT_BPP (format))
387    {
388    case 1:
389	STORE_1 (image, dest, offset, converted & 0x01);
390	break;
391
392    case 4:
393	STORE_4 (image, dest, offset, converted & 0xf);
394	break;
395
396    case 8:
397	WRITE (image, (dest + offset), converted & 0xff);
398	break;
399
400    case 16:
401	WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
402	break;
403
404    case 24:
405	STORE_24 (image, dest, offset, converted);
406	break;
407
408    case 32:
409	WRITE (image, ((uint32_t *)dest + offset), converted);
410	break;
411
412    default:
413	*dest = 0x0;
414	break;
415    }
416}
417
418#define MAKE_ACCESSORS(format)						\
419    static void								\
420    fetch_scanline_ ## format (pixman_image_t *image,			\
421			       int	       x,			\
422			       int             y,			\
423			       int             width,			\
424			       uint32_t *      buffer,			\
425			       const uint32_t *mask)			\
426    {									\
427	uint8_t *bits =							\
428	    (uint8_t *)(image->bits.bits + y * image->bits.rowstride);	\
429	int i;								\
430									\
431	for (i = 0; i < width; ++i)					\
432	{								\
433	    *buffer++ =							\
434		fetch_and_convert_pixel (image, bits, x + i, PIXMAN_ ## format); \
435	}								\
436    }									\
437									\
438    static void								\
439    store_scanline_ ## format (bits_image_t *  image,			\
440			       int             x,			\
441			       int             y,			\
442			       int             width,			\
443			       const uint32_t *values)			\
444    {									\
445	uint8_t *dest =							\
446	    (uint8_t *)(image->bits + y * image->rowstride);		\
447	int i;								\
448									\
449	for (i = 0; i < width; ++i)					\
450	{								\
451	    convert_and_store_pixel (					\
452		image, dest, i + x, PIXMAN_ ## format, values[i]);	\
453	}								\
454    }									\
455									\
456    static uint32_t							\
457    fetch_pixel_ ## format (bits_image_t *image,			\
458			    int		offset,				\
459			    int		line)				\
460    {									\
461	uint8_t *bits =							\
462	    (uint8_t *)(image->bits + line * image->rowstride);		\
463									\
464	return fetch_and_convert_pixel ((pixman_image_t *)image,	\
465					bits, offset, PIXMAN_ ## format); \
466    }									\
467									\
468    static const void *const __dummy__ ## format
469
470MAKE_ACCESSORS(a8r8g8b8);
471MAKE_ACCESSORS(x8r8g8b8);
472MAKE_ACCESSORS(a8b8g8r8);
473MAKE_ACCESSORS(x8b8g8r8);
474MAKE_ACCESSORS(x14r6g6b6);
475MAKE_ACCESSORS(b8g8r8a8);
476MAKE_ACCESSORS(b8g8r8x8);
477MAKE_ACCESSORS(r8g8b8x8);
478MAKE_ACCESSORS(r8g8b8a8);
479MAKE_ACCESSORS(r8g8b8);
480MAKE_ACCESSORS(b8g8r8);
481MAKE_ACCESSORS(r5g6b5);
482MAKE_ACCESSORS(b5g6r5);
483MAKE_ACCESSORS(a1r5g5b5);
484MAKE_ACCESSORS(x1r5g5b5);
485MAKE_ACCESSORS(a1b5g5r5);
486MAKE_ACCESSORS(x1b5g5r5);
487MAKE_ACCESSORS(a4r4g4b4);
488MAKE_ACCESSORS(x4r4g4b4);
489MAKE_ACCESSORS(a4b4g4r4);
490MAKE_ACCESSORS(x4b4g4r4);
491MAKE_ACCESSORS(a8);
492MAKE_ACCESSORS(c8);
493MAKE_ACCESSORS(g8);
494MAKE_ACCESSORS(r3g3b2);
495MAKE_ACCESSORS(b2g3r3);
496MAKE_ACCESSORS(a2r2g2b2);
497MAKE_ACCESSORS(a2b2g2r2);
498MAKE_ACCESSORS(x4a4);
499MAKE_ACCESSORS(a4);
500MAKE_ACCESSORS(g4);
501MAKE_ACCESSORS(c4);
502MAKE_ACCESSORS(r1g2b1);
503MAKE_ACCESSORS(b1g2r1);
504MAKE_ACCESSORS(a1r1g1b1);
505MAKE_ACCESSORS(a1b1g1r1);
506MAKE_ACCESSORS(a1);
507MAKE_ACCESSORS(g1);
508
509/********************************** Fetch ************************************/
510/* Table mapping sRGB-encoded 8 bit numbers to linearly encoded
511 * floating point numbers. We assume that single precision
512 * floating point follows the IEEE 754 format.
513 */
514static const uint32_t to_linear_u[256] =
515{
516    0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61,
517    0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a,
518    0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d,
519    0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152,
520    0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43,
521    0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e,
522    0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601,
523    0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9,
524    0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae,
525    0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380,
526    0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466,
527    0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65,
528    0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48,
529    0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728,
530    0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4,
531    0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16,
532    0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f,
533    0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50,
534    0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a,
535    0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702,
536    0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027,
537    0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf,
538    0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0,
539    0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281,
540    0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0,
541    0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a,
542    0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15,
543    0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14,
544    0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508,
545    0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64,
546    0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594,
547    0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8,
548    0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65,
549    0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237,
550    0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c,
551    0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680,
552    0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24,
553    0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e,
554    0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8,
555    0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de,
556    0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6,
557    0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae,
558    0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000
559};
560
561static const float * const to_linear = (const float *)to_linear_u;
562
563static uint8_t
564to_srgb (float f)
565{
566    uint8_t low = 0;
567    uint8_t high = 255;
568
569    while (high - low > 1)
570    {
571	uint8_t mid = (low + high) / 2;
572
573	if (to_linear[mid] > f)
574	    high = mid;
575	else
576	    low = mid;
577    }
578
579    if (to_linear[high] - f < f - to_linear[low])
580	return high;
581    else
582	return low;
583}
584
585static void
586fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image,
587				    int             x,
588				    int             y,
589				    int             width,
590				    uint32_t *      b,
591				    const uint32_t *mask)
592{
593    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
594    const uint32_t *pixel = bits + x;
595    const uint32_t *end = pixel + width;
596    argb_t *buffer = (argb_t *)b;
597
598    while (pixel < end)
599    {
600	uint32_t p = READ (image, pixel++);
601	argb_t *argb = buffer;
602
603	argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
604
605	argb->r = to_linear [(p >> 16) & 0xff];
606	argb->g = to_linear [(p >>  8) & 0xff];
607	argb->b = to_linear [(p >>  0) & 0xff];
608
609	buffer++;
610    }
611}
612
613/* Expects a float buffer */
614static void
615fetch_scanline_a2r10g10b10_float (pixman_image_t *image,
616				  int             x,
617				  int             y,
618				  int             width,
619				  uint32_t *      b,
620				  const uint32_t *mask)
621{
622    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
623    const uint32_t *pixel = bits + x;
624    const uint32_t *end = pixel + width;
625    argb_t *buffer = (argb_t *)b;
626
627    while (pixel < end)
628    {
629	uint32_t p = READ (image, pixel++);
630	uint64_t a = p >> 30;
631	uint64_t r = (p >> 20) & 0x3ff;
632	uint64_t g = (p >> 10) & 0x3ff;
633	uint64_t b = p & 0x3ff;
634
635	buffer->a = pixman_unorm_to_float (a, 2);
636	buffer->r = pixman_unorm_to_float (r, 10);
637	buffer->g = pixman_unorm_to_float (g, 10);
638	buffer->b = pixman_unorm_to_float (b, 10);
639
640	buffer++;
641    }
642}
643
644/* Expects a float buffer */
645static void
646fetch_scanline_x2r10g10b10_float (pixman_image_t *image,
647				  int             x,
648				  int             y,
649				  int             width,
650				  uint32_t *      b,
651				  const uint32_t *mask)
652{
653    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
654    const uint32_t *pixel = (uint32_t *)bits + x;
655    const uint32_t *end = pixel + width;
656    argb_t *buffer = (argb_t *)b;
657
658    while (pixel < end)
659    {
660	uint32_t p = READ (image, pixel++);
661	uint64_t r = (p >> 20) & 0x3ff;
662	uint64_t g = (p >> 10) & 0x3ff;
663	uint64_t b = p & 0x3ff;
664
665	buffer->a = 1.0;
666	buffer->r = pixman_unorm_to_float (r, 10);
667	buffer->g = pixman_unorm_to_float (g, 10);
668	buffer->b = pixman_unorm_to_float (b, 10);
669
670	buffer++;
671    }
672}
673
674/* Expects a float buffer */
675static void
676fetch_scanline_a2b10g10r10_float (pixman_image_t *image,
677				  int             x,
678				  int             y,
679				  int             width,
680				  uint32_t *      b,
681				  const uint32_t *mask)
682{
683    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
684    const uint32_t *pixel = bits + x;
685    const uint32_t *end = pixel + width;
686    argb_t *buffer = (argb_t *)b;
687
688    while (pixel < end)
689    {
690	uint32_t p = READ (image, pixel++);
691	uint64_t a = p >> 30;
692	uint64_t b = (p >> 20) & 0x3ff;
693	uint64_t g = (p >> 10) & 0x3ff;
694	uint64_t r = p & 0x3ff;
695
696	buffer->a = pixman_unorm_to_float (a, 2);
697	buffer->r = pixman_unorm_to_float (r, 10);
698	buffer->g = pixman_unorm_to_float (g, 10);
699	buffer->b = pixman_unorm_to_float (b, 10);
700
701	buffer++;
702    }
703}
704
705/* Expects a float buffer */
706static void
707fetch_scanline_x2b10g10r10_float (pixman_image_t *image,
708				  int             x,
709				  int             y,
710				  int             width,
711				  uint32_t *      b,
712				  const uint32_t *mask)
713{
714    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
715    const uint32_t *pixel = (uint32_t *)bits + x;
716    const uint32_t *end = pixel + width;
717    argb_t *buffer = (argb_t *)b;
718
719    while (pixel < end)
720    {
721	uint32_t p = READ (image, pixel++);
722	uint64_t b = (p >> 20) & 0x3ff;
723	uint64_t g = (p >> 10) & 0x3ff;
724	uint64_t r = p & 0x3ff;
725
726	buffer->a = 1.0;
727	buffer->r = pixman_unorm_to_float (r, 10);
728	buffer->g = pixman_unorm_to_float (g, 10);
729	buffer->b = pixman_unorm_to_float (b, 10);
730
731	buffer++;
732    }
733}
734
735static void
736fetch_scanline_yuy2 (pixman_image_t *image,
737                     int             x,
738                     int             line,
739                     int             width,
740                     uint32_t *      buffer,
741                     const uint32_t *mask)
742{
743    const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
744    int i;
745
746    for (i = 0; i < width; i++)
747    {
748	int16_t y, u, v;
749	int32_t r, g, b;
750
751	y = ((uint8_t *) bits)[(x + i) << 1] - 16;
752	u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
753	v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
754
755	/* R = 1.164(Y - 16) + 1.596(V - 128) */
756	r = 0x012b27 * y + 0x019a2e * v;
757	/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
758	g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
759	/* B = 1.164(Y - 16) + 2.018(U - 128) */
760	b = 0x012b27 * y + 0x0206a2 * u;
761
762	*buffer++ = 0xff000000 |
763	    (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
764	    (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
765	    (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
766    }
767}
768
769static void
770fetch_scanline_yv12 (pixman_image_t *image,
771                     int             x,
772                     int             line,
773                     int             width,
774                     uint32_t *      buffer,
775                     const uint32_t *mask)
776{
777    YV12_SETUP (image);
778    uint8_t *y_line = YV12_Y (line);
779    uint8_t *u_line = YV12_U (line);
780    uint8_t *v_line = YV12_V (line);
781    int i;
782
783    for (i = 0; i < width; i++)
784    {
785	int16_t y, u, v;
786	int32_t r, g, b;
787
788	y = y_line[x + i] - 16;
789	u = u_line[(x + i) >> 1] - 128;
790	v = v_line[(x + i) >> 1] - 128;
791
792	/* R = 1.164(Y - 16) + 1.596(V - 128) */
793	r = 0x012b27 * y + 0x019a2e * v;
794	/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
795	g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
796	/* B = 1.164(Y - 16) + 2.018(U - 128) */
797	b = 0x012b27 * y + 0x0206a2 * u;
798
799	*buffer++ = 0xff000000 |
800	    (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
801	    (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
802	    (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
803    }
804}
805
806/**************************** Pixel wise fetching *****************************/
807
808static argb_t
809fetch_pixel_x2r10g10b10_float (bits_image_t *image,
810			       int	   offset,
811			       int           line)
812{
813    uint32_t *bits = image->bits + line * image->rowstride;
814    uint32_t p = READ (image, bits + offset);
815    uint64_t r = (p >> 20) & 0x3ff;
816    uint64_t g = (p >> 10) & 0x3ff;
817    uint64_t b = p & 0x3ff;
818    argb_t argb;
819
820    argb.a = 1.0;
821    argb.r = pixman_unorm_to_float (r, 10);
822    argb.g = pixman_unorm_to_float (g, 10);
823    argb.b = pixman_unorm_to_float (b, 10);
824
825    return argb;
826}
827
828static argb_t
829fetch_pixel_a2r10g10b10_float (bits_image_t *image,
830			       int	     offset,
831			       int           line)
832{
833    uint32_t *bits = image->bits + line * image->rowstride;
834    uint32_t p = READ (image, bits + offset);
835    uint64_t a = p >> 30;
836    uint64_t r = (p >> 20) & 0x3ff;
837    uint64_t g = (p >> 10) & 0x3ff;
838    uint64_t b = p & 0x3ff;
839    argb_t argb;
840
841    argb.a = pixman_unorm_to_float (a, 2);
842    argb.r = pixman_unorm_to_float (r, 10);
843    argb.g = pixman_unorm_to_float (g, 10);
844    argb.b = pixman_unorm_to_float (b, 10);
845
846    return argb;
847}
848
849static argb_t
850fetch_pixel_a2b10g10r10_float (bits_image_t *image,
851			       int           offset,
852			       int           line)
853{
854    uint32_t *bits = image->bits + line * image->rowstride;
855    uint32_t p = READ (image, bits + offset);
856    uint64_t a = p >> 30;
857    uint64_t b = (p >> 20) & 0x3ff;
858    uint64_t g = (p >> 10) & 0x3ff;
859    uint64_t r = p & 0x3ff;
860    argb_t argb;
861
862    argb.a = pixman_unorm_to_float (a, 2);
863    argb.r = pixman_unorm_to_float (r, 10);
864    argb.g = pixman_unorm_to_float (g, 10);
865    argb.b = pixman_unorm_to_float (b, 10);
866
867    return argb;
868}
869
870static argb_t
871fetch_pixel_x2b10g10r10_float (bits_image_t *image,
872			       int           offset,
873			       int           line)
874{
875    uint32_t *bits = image->bits + line * image->rowstride;
876    uint32_t p = READ (image, bits + offset);
877    uint64_t b = (p >> 20) & 0x3ff;
878    uint64_t g = (p >> 10) & 0x3ff;
879    uint64_t r = p & 0x3ff;
880    argb_t argb;
881
882    argb.a = 1.0;
883    argb.r = pixman_unorm_to_float (r, 10);
884    argb.g = pixman_unorm_to_float (g, 10);
885    argb.b = pixman_unorm_to_float (b, 10);
886
887    return argb;
888}
889
890static argb_t
891fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
892				 int	       offset,
893				 int           line)
894{
895    uint32_t *bits = image->bits + line * image->rowstride;
896    uint32_t p = READ (image, bits + offset);
897    argb_t argb;
898
899    argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
900
901    argb.r = to_linear [(p >> 16) & 0xff];
902    argb.g = to_linear [(p >>  8) & 0xff];
903    argb.b = to_linear [(p >>  0) & 0xff];
904
905    return argb;
906}
907
908static uint32_t
909fetch_pixel_yuy2 (bits_image_t *image,
910		  int           offset,
911		  int           line)
912{
913    const uint32_t *bits = image->bits + image->rowstride * line;
914
915    int16_t y, u, v;
916    int32_t r, g, b;
917
918    y = ((uint8_t *) bits)[offset << 1] - 16;
919    u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
920    v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
921
922    /* R = 1.164(Y - 16) + 1.596(V - 128) */
923    r = 0x012b27 * y + 0x019a2e * v;
924
925    /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
926    g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
927
928    /* B = 1.164(Y - 16) + 2.018(U - 128) */
929    b = 0x012b27 * y + 0x0206a2 * u;
930
931    return 0xff000000 |
932	(r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
933	(g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
934	(b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
935}
936
937static uint32_t
938fetch_pixel_yv12 (bits_image_t *image,
939		  int           offset,
940		  int           line)
941{
942    YV12_SETUP (image);
943    int16_t y = YV12_Y (line)[offset] - 16;
944    int16_t u = YV12_U (line)[offset >> 1] - 128;
945    int16_t v = YV12_V (line)[offset >> 1] - 128;
946    int32_t r, g, b;
947
948    /* R = 1.164(Y - 16) + 1.596(V - 128) */
949    r = 0x012b27 * y + 0x019a2e * v;
950
951    /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
952    g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
953
954    /* B = 1.164(Y - 16) + 2.018(U - 128) */
955    b = 0x012b27 * y + 0x0206a2 * u;
956
957    return 0xff000000 |
958	(r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
959	(g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
960	(b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
961}
962
963/*********************************** Store ************************************/
964
965static void
966store_scanline_a2r10g10b10_float (bits_image_t *  image,
967				  int             x,
968				  int             y,
969				  int             width,
970				  const uint32_t *v)
971{
972    uint32_t *bits = image->bits + image->rowstride * y;
973    uint32_t *pixel = bits + x;
974    argb_t *values = (argb_t *)v;
975    int i;
976
977    for (i = 0; i < width; ++i)
978    {
979	uint16_t a, r, g, b;
980
981	a = pixman_float_to_unorm (values[i].a, 2);
982	r = pixman_float_to_unorm (values[i].r, 10);
983	g = pixman_float_to_unorm (values[i].g, 10);
984	b = pixman_float_to_unorm (values[i].b, 10);
985
986	WRITE (image, pixel++,
987	       (a << 30) | (r << 20) | (g << 10) | b);
988    }
989}
990
991static void
992store_scanline_x2r10g10b10_float (bits_image_t *  image,
993				  int             x,
994				  int             y,
995				  int             width,
996				  const uint32_t *v)
997{
998    uint32_t *bits = image->bits + image->rowstride * y;
999    uint32_t *pixel = bits + x;
1000    argb_t *values = (argb_t *)v;
1001    int i;
1002
1003    for (i = 0; i < width; ++i)
1004    {
1005	uint16_t r, g, b;
1006
1007	r = pixman_float_to_unorm (values[i].r, 10);
1008	g = pixman_float_to_unorm (values[i].g, 10);
1009	b = pixman_float_to_unorm (values[i].b, 10);
1010
1011	WRITE (image, pixel++,
1012	       (r << 20) | (g << 10) | b);
1013    }
1014}
1015
1016static void
1017store_scanline_a2b10g10r10_float (bits_image_t *  image,
1018				  int             x,
1019				  int             y,
1020				  int             width,
1021				  const uint32_t *v)
1022{
1023    uint32_t *bits = image->bits + image->rowstride * y;
1024    uint32_t *pixel = bits + x;
1025    argb_t *values = (argb_t *)v;
1026    int i;
1027
1028    for (i = 0; i < width; ++i)
1029    {
1030	uint16_t a, r, g, b;
1031
1032	a = pixman_float_to_unorm (values[i].a, 2);
1033	r = pixman_float_to_unorm (values[i].r, 10);
1034	g = pixman_float_to_unorm (values[i].g, 10);
1035	b = pixman_float_to_unorm (values[i].b, 10);
1036
1037	WRITE (image, pixel++,
1038	       (a << 30) | (b << 20) | (g << 10) | r);
1039    }
1040}
1041
1042static void
1043store_scanline_x2b10g10r10_float (bits_image_t *  image,
1044				  int             x,
1045				  int             y,
1046				  int             width,
1047				  const uint32_t *v)
1048{
1049    uint32_t *bits = image->bits + image->rowstride * y;
1050    uint32_t *pixel = bits + x;
1051    argb_t *values = (argb_t *)v;
1052    int i;
1053
1054    for (i = 0; i < width; ++i)
1055    {
1056	uint16_t r, g, b;
1057
1058	r = pixman_float_to_unorm (values[i].r, 10);
1059	g = pixman_float_to_unorm (values[i].g, 10);
1060	b = pixman_float_to_unorm (values[i].b, 10);
1061
1062	WRITE (image, pixel++,
1063	       (b << 20) | (g << 10) | r);
1064    }
1065}
1066
1067static void
1068store_scanline_a8r8g8b8_sRGB_float (bits_image_t *  image,
1069				    int             x,
1070				    int             y,
1071				    int             width,
1072				    const uint32_t *v)
1073{
1074    uint32_t *bits = image->bits + image->rowstride * y;
1075    uint32_t *pixel = bits + x;
1076    argb_t *values = (argb_t *)v;
1077    int i;
1078
1079    for (i = 0; i < width; ++i)
1080    {
1081	uint8_t a, r, g, b;
1082
1083	a = pixman_float_to_unorm (values[i].a, 8);
1084	r = to_srgb (values[i].r);
1085	g = to_srgb (values[i].g);
1086	b = to_srgb (values[i].b);
1087
1088	WRITE (image, pixel++,
1089	       (a << 24) | (r << 16) | (g << 8) | b);
1090    }
1091}
1092
1093/*
1094 * Contracts a floating point image to 32bpp and then stores it using a
1095 * regular 32-bit store proc. Despite the type, this function expects an
1096 * argb_t buffer.
1097 */
1098static void
1099store_scanline_generic_float (bits_image_t *  image,
1100			      int             x,
1101			      int             y,
1102			      int             width,
1103			      const uint32_t *values)
1104{
1105    uint32_t *argb8_pixels;
1106
1107    assert (image->common.type == BITS);
1108
1109    argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1110    if (!argb8_pixels)
1111	return;
1112
1113    /* Contract the scanline.  We could do this in place if values weren't
1114     * const.
1115     */
1116    pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1117
1118    image->store_scanline_32 (image, x, y, width, argb8_pixels);
1119
1120    free (argb8_pixels);
1121}
1122
1123static void
1124fetch_scanline_generic_float (pixman_image_t *image,
1125			      int	      x,
1126			      int	      y,
1127			      int	      width,
1128			      uint32_t *      buffer,
1129			      const uint32_t *mask)
1130{
1131    image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
1132
1133    pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
1134}
1135
1136/* The 32_sRGB paths should be deleted after narrow processing
1137 * is no longer invoked for formats that are considered wide.
1138 * (Also see fetch_pixel_generic_lossy_32) */
1139static void
1140fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
1141                                 int             x,
1142                                 int             y,
1143                                 int             width,
1144                                 uint32_t       *buffer,
1145                                 const uint32_t *mask)
1146{
1147    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
1148    const uint32_t *pixel = (uint32_t *)bits + x;
1149    const uint32_t *end = pixel + width;
1150    uint32_t tmp;
1151
1152    while (pixel < end)
1153    {
1154	uint8_t a, r, g, b;
1155
1156	tmp = READ (image, pixel++);
1157
1158	a = (tmp >> 24) & 0xff;
1159	r = (tmp >> 16) & 0xff;
1160	g = (tmp >> 8) & 0xff;
1161	b = (tmp >> 0) & 0xff;
1162
1163	r = to_linear[r] * 255.0f + 0.5f;
1164	g = to_linear[g] * 255.0f + 0.5f;
1165	b = to_linear[b] * 255.0f + 0.5f;
1166
1167	*buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1168    }
1169}
1170
1171static uint32_t
1172fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1173			      int           offset,
1174			      int           line)
1175{
1176    uint32_t *bits = image->bits + line * image->rowstride;
1177    uint32_t tmp = READ (image, bits + offset);
1178    uint8_t a, r, g, b;
1179
1180    a = (tmp >> 24) & 0xff;
1181    r = (tmp >> 16) & 0xff;
1182    g = (tmp >> 8) & 0xff;
1183    b = (tmp >> 0) & 0xff;
1184
1185    r = to_linear[r] * 255.0f + 0.5f;
1186    g = to_linear[g] * 255.0f + 0.5f;
1187    b = to_linear[b] * 255.0f + 0.5f;
1188
1189    return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1190}
1191
1192static void
1193store_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
1194                                 int             x,
1195                                 int             y,
1196                                 int             width,
1197                                 const uint32_t *v)
1198{
1199    uint32_t *bits = image->bits + image->rowstride * y;
1200    uint64_t *values = (uint64_t *)v;
1201    uint32_t *pixel = bits + x;
1202    uint64_t tmp;
1203    int i;
1204
1205    for (i = 0; i < width; ++i)
1206    {
1207	uint8_t a, r, g, b;
1208
1209	tmp = values[i];
1210
1211	a = (tmp >> 24) & 0xff;
1212	r = (tmp >> 16) & 0xff;
1213	g = (tmp >> 8) & 0xff;
1214	b = (tmp >> 0) & 0xff;
1215
1216	r = to_srgb (r * (1/255.0f));
1217	g = to_srgb (g * (1/255.0f));
1218	b = to_srgb (b * (1/255.0f));
1219
1220	WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1221    }
1222}
1223
1224static argb_t
1225fetch_pixel_generic_float (bits_image_t *image,
1226			   int		 offset,
1227			   int           line)
1228{
1229    uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1230    argb_t f;
1231
1232    pixman_expand_to_float (&f, &pixel32, image->format, 1);
1233
1234    return f;
1235}
1236
1237/*
1238 * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1239 * paths have wide versions, this can be removed.
1240 *
1241 * WARNING: This function loses precision!
1242 */
1243static uint32_t
1244fetch_pixel_generic_lossy_32 (bits_image_t *image,
1245			      int           offset,
1246			      int           line)
1247{
1248    argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1249    uint32_t result;
1250
1251    pixman_contract_from_float (&result, &pixel64, 1);
1252
1253    return result;
1254}
1255
1256typedef struct
1257{
1258    pixman_format_code_t	format;
1259    fetch_scanline_t		fetch_scanline_32;
1260    fetch_scanline_t		fetch_scanline_float;
1261    fetch_pixel_32_t		fetch_pixel_32;
1262    fetch_pixel_float_t		fetch_pixel_float;
1263    store_scanline_t		store_scanline_32;
1264    store_scanline_t		store_scanline_float;
1265} format_info_t;
1266
1267#define FORMAT_INFO(format) 						\
1268    {									\
1269	PIXMAN_ ## format,						\
1270	    fetch_scanline_ ## format,					\
1271	    fetch_scanline_generic_float,				\
1272	    fetch_pixel_ ## format,					\
1273	    fetch_pixel_generic_float,					\
1274	    store_scanline_ ## format,					\
1275	    store_scanline_generic_float				\
1276    }
1277
1278static const format_info_t accessors[] =
1279{
1280/* 32 bpp formats */
1281    FORMAT_INFO (a8r8g8b8),
1282    FORMAT_INFO (x8r8g8b8),
1283    FORMAT_INFO (a8b8g8r8),
1284    FORMAT_INFO (x8b8g8r8),
1285    FORMAT_INFO (b8g8r8a8),
1286    FORMAT_INFO (b8g8r8x8),
1287    FORMAT_INFO (r8g8b8a8),
1288    FORMAT_INFO (r8g8b8x8),
1289    FORMAT_INFO (x14r6g6b6),
1290
1291/* sRGB formats */
1292  { PIXMAN_a8r8g8b8_sRGB,
1293    fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
1294    fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
1295    store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
1296  },
1297
1298/* 24bpp formats */
1299    FORMAT_INFO (r8g8b8),
1300    FORMAT_INFO (b8g8r8),
1301
1302/* 16bpp formats */
1303    FORMAT_INFO (r5g6b5),
1304    FORMAT_INFO (b5g6r5),
1305
1306    FORMAT_INFO (a1r5g5b5),
1307    FORMAT_INFO (x1r5g5b5),
1308    FORMAT_INFO (a1b5g5r5),
1309    FORMAT_INFO (x1b5g5r5),
1310    FORMAT_INFO (a4r4g4b4),
1311    FORMAT_INFO (x4r4g4b4),
1312    FORMAT_INFO (a4b4g4r4),
1313    FORMAT_INFO (x4b4g4r4),
1314
1315/* 8bpp formats */
1316    FORMAT_INFO (a8),
1317    FORMAT_INFO (r3g3b2),
1318    FORMAT_INFO (b2g3r3),
1319    FORMAT_INFO (a2r2g2b2),
1320    FORMAT_INFO (a2b2g2r2),
1321
1322    FORMAT_INFO (c8),
1323
1324    FORMAT_INFO (g8),
1325
1326#define fetch_scanline_x4c4 fetch_scanline_c8
1327#define fetch_pixel_x4c4 fetch_pixel_c8
1328#define store_scanline_x4c4 store_scanline_c8
1329    FORMAT_INFO (x4c4),
1330
1331#define fetch_scanline_x4g4 fetch_scanline_g8
1332#define fetch_pixel_x4g4 fetch_pixel_g8
1333#define store_scanline_x4g4 store_scanline_g8
1334    FORMAT_INFO (x4g4),
1335
1336    FORMAT_INFO (x4a4),
1337
1338/* 4bpp formats */
1339    FORMAT_INFO (a4),
1340    FORMAT_INFO (r1g2b1),
1341    FORMAT_INFO (b1g2r1),
1342    FORMAT_INFO (a1r1g1b1),
1343    FORMAT_INFO (a1b1g1r1),
1344
1345    FORMAT_INFO (c4),
1346
1347    FORMAT_INFO (g4),
1348
1349/* 1bpp formats */
1350    FORMAT_INFO (a1),
1351    FORMAT_INFO (g1),
1352
1353/* Wide formats */
1354
1355    { PIXMAN_a2r10g10b10,
1356      NULL, fetch_scanline_a2r10g10b10_float,
1357      fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
1358      NULL, store_scanline_a2r10g10b10_float },
1359
1360    { PIXMAN_x2r10g10b10,
1361      NULL, fetch_scanline_x2r10g10b10_float,
1362      fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
1363      NULL, store_scanline_x2r10g10b10_float },
1364
1365    { PIXMAN_a2b10g10r10,
1366      NULL, fetch_scanline_a2b10g10r10_float,
1367      fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
1368      NULL, store_scanline_a2b10g10r10_float },
1369
1370    { PIXMAN_x2b10g10r10,
1371      NULL, fetch_scanline_x2b10g10r10_float,
1372      fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
1373      NULL, store_scanline_x2b10g10r10_float },
1374
1375/* YUV formats */
1376    { PIXMAN_yuy2,
1377      fetch_scanline_yuy2, fetch_scanline_generic_float,
1378      fetch_pixel_yuy2, fetch_pixel_generic_float,
1379      NULL, NULL },
1380
1381    { PIXMAN_yv12,
1382      fetch_scanline_yv12, fetch_scanline_generic_float,
1383      fetch_pixel_yv12, fetch_pixel_generic_float,
1384      NULL, NULL },
1385
1386    { PIXMAN_null },
1387};
1388
1389static void
1390setup_accessors (bits_image_t *image)
1391{
1392    const format_info_t *info = accessors;
1393
1394    while (info->format != PIXMAN_null)
1395    {
1396	if (info->format == image->format)
1397	{
1398	    image->fetch_scanline_32 = info->fetch_scanline_32;
1399	    image->fetch_scanline_float = info->fetch_scanline_float;
1400	    image->fetch_pixel_32 = info->fetch_pixel_32;
1401	    image->fetch_pixel_float = info->fetch_pixel_float;
1402	    image->store_scanline_32 = info->store_scanline_32;
1403	    image->store_scanline_float = info->store_scanline_float;
1404
1405	    return;
1406	}
1407
1408	info++;
1409    }
1410}
1411
1412#ifndef PIXMAN_FB_ACCESSORS
1413void
1414_pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1415
1416void
1417_pixman_bits_image_setup_accessors (bits_image_t *image)
1418{
1419    if (image->read_func || image->write_func)
1420	_pixman_bits_image_setup_accessors_accessors (image);
1421    else
1422	setup_accessors (image);
1423}
1424
1425#else
1426
1427void
1428_pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1429{
1430    setup_accessors (image);
1431}
1432
1433#endif
1434