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 
197 static force_inline void
get_shifts(pixman_format_code_t format,int * a,int * r,int * g,int * b)198 get_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 
250 static force_inline uint32_t
convert_channel(uint32_t pixel,uint32_t def_value,int n_from_bits,int from_shift,int n_to_bits,int to_shift)251 convert_channel (uint32_t pixel, uint32_t def_value,
252 		 int n_from_bits, int from_shift,
253 		 int n_to_bits, int to_shift)
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 
267 static force_inline uint32_t
convert_pixel(pixman_format_code_t from,pixman_format_code_t to,uint32_t pixel)268 convert_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 
296 static force_inline uint32_t
convert_pixel_to_a8r8g8b8(pixman_image_t * image,pixman_format_code_t format,uint32_t pixel)297 convert_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 
312 static force_inline uint32_t
convert_pixel_from_a8r8g8b8(pixman_image_t * image,pixman_format_code_t format,uint32_t pixel)313 convert_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 
334 static force_inline uint32_t
fetch_and_convert_pixel(pixman_image_t * image,const uint8_t * bits,int offset,pixman_format_code_t format)335 fetch_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 
376 static force_inline void
convert_and_store_pixel(bits_image_t * image,uint8_t * dest,int offset,pixman_format_code_t format,uint32_t pixel)377 convert_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 
470 MAKE_ACCESSORS(a8r8g8b8);
471 MAKE_ACCESSORS(x8r8g8b8);
472 MAKE_ACCESSORS(a8b8g8r8);
473 MAKE_ACCESSORS(x8b8g8r8);
474 MAKE_ACCESSORS(x14r6g6b6);
475 MAKE_ACCESSORS(b8g8r8a8);
476 MAKE_ACCESSORS(b8g8r8x8);
477 MAKE_ACCESSORS(r8g8b8x8);
478 MAKE_ACCESSORS(r8g8b8a8);
479 MAKE_ACCESSORS(r8g8b8);
480 MAKE_ACCESSORS(b8g8r8);
481 MAKE_ACCESSORS(r5g6b5);
482 MAKE_ACCESSORS(b5g6r5);
483 MAKE_ACCESSORS(a1r5g5b5);
484 MAKE_ACCESSORS(x1r5g5b5);
485 MAKE_ACCESSORS(a1b5g5r5);
486 MAKE_ACCESSORS(x1b5g5r5);
487 MAKE_ACCESSORS(a4r4g4b4);
488 MAKE_ACCESSORS(x4r4g4b4);
489 MAKE_ACCESSORS(a4b4g4r4);
490 MAKE_ACCESSORS(x4b4g4r4);
491 MAKE_ACCESSORS(a8);
492 MAKE_ACCESSORS(c8);
493 MAKE_ACCESSORS(g8);
494 MAKE_ACCESSORS(r3g3b2);
495 MAKE_ACCESSORS(b2g3r3);
496 MAKE_ACCESSORS(a2r2g2b2);
497 MAKE_ACCESSORS(a2b2g2r2);
498 MAKE_ACCESSORS(x4a4);
499 MAKE_ACCESSORS(a4);
500 MAKE_ACCESSORS(g4);
501 MAKE_ACCESSORS(c4);
502 MAKE_ACCESSORS(r1g2b1);
503 MAKE_ACCESSORS(b1g2r1);
504 MAKE_ACCESSORS(a1r1g1b1);
505 MAKE_ACCESSORS(a1b1g1r1);
506 MAKE_ACCESSORS(a1);
507 MAKE_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  */
514 static 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 
561 static const float * const to_linear = (const float *)to_linear_u;
562 
563 static uint8_t
to_srgb(float f)564 to_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 
585 static void
fetch_scanline_a8r8g8b8_sRGB_float(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)586 fetch_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 */
614 static void
fetch_scanline_a2r10g10b10_float(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)615 fetch_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 */
645 static void
fetch_scanline_x2r10g10b10_float(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)646 fetch_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 */
675 static void
fetch_scanline_a2b10g10r10_float(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)676 fetch_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 */
706 static void
fetch_scanline_x2b10g10r10_float(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)707 fetch_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 
735 static void
fetch_scanline_yuy2(pixman_image_t * image,int x,int line,int width,uint32_t * buffer,const uint32_t * mask)736 fetch_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 
769 static void
fetch_scanline_yv12(pixman_image_t * image,int x,int line,int width,uint32_t * buffer,const uint32_t * mask)770 fetch_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 
808 static argb_t
fetch_pixel_x2r10g10b10_float(bits_image_t * image,int offset,int line)809 fetch_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 
828 static argb_t
fetch_pixel_a2r10g10b10_float(bits_image_t * image,int offset,int line)829 fetch_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 
849 static argb_t
fetch_pixel_a2b10g10r10_float(bits_image_t * image,int offset,int line)850 fetch_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 
870 static argb_t
fetch_pixel_x2b10g10r10_float(bits_image_t * image,int offset,int line)871 fetch_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 
890 static argb_t
fetch_pixel_a8r8g8b8_sRGB_float(bits_image_t * image,int offset,int line)891 fetch_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 
908 static uint32_t
fetch_pixel_yuy2(bits_image_t * image,int offset,int line)909 fetch_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 
937 static uint32_t
fetch_pixel_yv12(bits_image_t * image,int offset,int line)938 fetch_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 
965 static void
store_scanline_a2r10g10b10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)966 store_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 
991 static void
store_scanline_x2r10g10b10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)992 store_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 
1016 static void
store_scanline_a2b10g10r10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1017 store_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 
1042 static void
store_scanline_x2b10g10r10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1043 store_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 
1067 static void
store_scanline_a8r8g8b8_sRGB_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1068 store_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 static void
store_scanline_16(bits_image_t * image,int x,int y,int width,const uint32_t * v)1094 store_scanline_16 (bits_image_t *  image,
1095 		   int             x,
1096 		   int             y,
1097 		   int             width,
1098 		   const uint32_t *v)
1099 {
1100     uint16_t *bits = (uint16_t*)(image->bits + image->rowstride * y);
1101     uint16_t *values = (uint16_t *)v;
1102     uint16_t *pixel = bits + x;
1103     int i;
1104 
1105     for (i = 0; i < width; ++i)
1106     {
1107 	WRITE (image, pixel++, values[i]);
1108     }
1109 }
1110 
1111 static void
fetch_scanline_16(pixman_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)1112 fetch_scanline_16 (pixman_image_t *image,
1113                             int             x,
1114                             int             y,
1115                             int             width,
1116                             uint32_t *      b,
1117                             const uint32_t *mask)
1118 {
1119     const uint16_t *bits = (uint16_t*)(image->bits.bits + y * image->bits.rowstride);
1120     const uint16_t *pixel = bits + x;
1121     int i;
1122     uint16_t *buffer = (uint16_t *)b;
1123 
1124     for (i = 0; i < width; ++i)
1125     {
1126 	*buffer++ = READ (image, pixel++);
1127     }
1128 }
1129 
1130 
1131 /*
1132  * Contracts a floating point image to 32bpp and then stores it using a
1133  * regular 32-bit store proc. Despite the type, this function expects an
1134  * argb_t buffer.
1135  */
1136 static void
store_scanline_generic_float(bits_image_t * image,int x,int y,int width,const uint32_t * values)1137 store_scanline_generic_float (bits_image_t *  image,
1138 			      int             x,
1139 			      int             y,
1140 			      int             width,
1141 			      const uint32_t *values)
1142 {
1143     uint32_t *argb8_pixels;
1144 
1145     assert (image->common.type == BITS);
1146 
1147     argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1148     if (!argb8_pixels)
1149 	return;
1150 
1151     /* Contract the scanline.  We could do this in place if values weren't
1152      * const.
1153      */
1154     pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1155 
1156     image->store_scanline_32 (image, x, y, width, argb8_pixels);
1157 
1158     free (argb8_pixels);
1159 }
1160 
1161 static void
fetch_scanline_generic_float(pixman_image_t * image,int x,int y,int width,uint32_t * buffer,const uint32_t * mask)1162 fetch_scanline_generic_float (pixman_image_t *image,
1163 			      int	      x,
1164 			      int	      y,
1165 			      int	      width,
1166 			      uint32_t *      buffer,
1167 			      const uint32_t *mask)
1168 {
1169     image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
1170 
1171     pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
1172 }
1173 
1174 /* The 32_sRGB paths should be deleted after narrow processing
1175  * is no longer invoked for formats that are considered wide.
1176  * (Also see fetch_pixel_generic_lossy_32) */
1177 static void
fetch_scanline_a8r8g8b8_32_sRGB(pixman_image_t * image,int x,int y,int width,uint32_t * buffer,const uint32_t * mask)1178 fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
1179                                  int             x,
1180                                  int             y,
1181                                  int             width,
1182                                  uint32_t       *buffer,
1183                                  const uint32_t *mask)
1184 {
1185     const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
1186     const uint32_t *pixel = (uint32_t *)bits + x;
1187     const uint32_t *end = pixel + width;
1188     uint32_t tmp;
1189 
1190     while (pixel < end)
1191     {
1192 	uint8_t a, r, g, b;
1193 
1194 	tmp = READ (image, pixel++);
1195 
1196 	a = (tmp >> 24) & 0xff;
1197 	r = (tmp >> 16) & 0xff;
1198 	g = (tmp >> 8) & 0xff;
1199 	b = (tmp >> 0) & 0xff;
1200 
1201 	r = to_linear[r] * 255.0f + 0.5f;
1202 	g = to_linear[g] * 255.0f + 0.5f;
1203 	b = to_linear[b] * 255.0f + 0.5f;
1204 
1205 	*buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1206     }
1207 }
1208 
1209 static uint32_t
fetch_pixel_a8r8g8b8_32_sRGB(bits_image_t * image,int offset,int line)1210 fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1211 			      int           offset,
1212 			      int           line)
1213 {
1214     uint32_t *bits = image->bits + line * image->rowstride;
1215     uint32_t tmp = READ (image, bits + offset);
1216     uint8_t a, r, g, b;
1217 
1218     a = (tmp >> 24) & 0xff;
1219     r = (tmp >> 16) & 0xff;
1220     g = (tmp >> 8) & 0xff;
1221     b = (tmp >> 0) & 0xff;
1222 
1223     r = to_linear[r] * 255.0f + 0.5f;
1224     g = to_linear[g] * 255.0f + 0.5f;
1225     b = to_linear[b] * 255.0f + 0.5f;
1226 
1227     return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1228 }
1229 
1230 static void
store_scanline_a8r8g8b8_32_sRGB(bits_image_t * image,int x,int y,int width,const uint32_t * v)1231 store_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
1232                                  int             x,
1233                                  int             y,
1234                                  int             width,
1235                                  const uint32_t *v)
1236 {
1237     uint32_t *bits = image->bits + image->rowstride * y;
1238     uint64_t *values = (uint64_t *)v;
1239     uint32_t *pixel = bits + x;
1240     uint64_t tmp;
1241     int i;
1242 
1243     for (i = 0; i < width; ++i)
1244     {
1245 	uint8_t a, r, g, b;
1246 
1247 	tmp = values[i];
1248 
1249 	a = (tmp >> 24) & 0xff;
1250 	r = (tmp >> 16) & 0xff;
1251 	g = (tmp >> 8) & 0xff;
1252 	b = (tmp >> 0) & 0xff;
1253 
1254 	r = to_srgb (r * (1/255.0f));
1255 	g = to_srgb (g * (1/255.0f));
1256 	b = to_srgb (b * (1/255.0f));
1257 
1258 	WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1259     }
1260 }
1261 
1262 static argb_t
fetch_pixel_generic_float(bits_image_t * image,int offset,int line)1263 fetch_pixel_generic_float (bits_image_t *image,
1264 			   int		 offset,
1265 			   int           line)
1266 {
1267     uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1268     argb_t f;
1269 
1270     pixman_expand_to_float (&f, &pixel32, image->format, 1);
1271 
1272     return f;
1273 }
1274 
1275 /*
1276  * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1277  * paths have wide versions, this can be removed.
1278  *
1279  * WARNING: This function loses precision!
1280  */
1281 static uint32_t
fetch_pixel_generic_lossy_32(bits_image_t * image,int offset,int line)1282 fetch_pixel_generic_lossy_32 (bits_image_t *image,
1283 			      int           offset,
1284 			      int           line)
1285 {
1286     argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1287     uint32_t result;
1288 
1289     pixman_contract_from_float (&result, &pixel64, 1);
1290 
1291     return result;
1292 }
1293 
1294 typedef struct
1295 {
1296     pixman_format_code_t	format;
1297     fetch_scanline_t		fetch_scanline_16;
1298     fetch_scanline_t		fetch_scanline_32;
1299     fetch_scanline_t		fetch_scanline_float;
1300     fetch_pixel_32_t		fetch_pixel_32;
1301     fetch_pixel_float_t		fetch_pixel_float;
1302     store_scanline_t		store_scanline_16;
1303     store_scanline_t		store_scanline_32;
1304     store_scanline_t		store_scanline_float;
1305 } format_info_t;
1306 
1307 #define FORMAT_INFO(format) 						\
1308     {									\
1309 	PIXMAN_ ## format,						\
1310 	    NULL,							\
1311 	    fetch_scanline_ ## format,					\
1312 	    fetch_scanline_generic_float,				\
1313 	    fetch_pixel_ ## format,					\
1314 	    fetch_pixel_generic_float,					\
1315 	    NULL,							\
1316 	    store_scanline_ ## format,					\
1317 	    store_scanline_generic_float				\
1318     }
1319 #define FORMAT_INFO16(format) 						\
1320     {									\
1321 	PIXMAN_ ## format,						\
1322 	    fetch_scanline_16,						\
1323 	    fetch_scanline_ ## format,					\
1324 	    fetch_scanline_generic_float,				\
1325 	    fetch_pixel_ ## format,					\
1326 	    fetch_pixel_generic_float,					\
1327 	    store_scanline_16,						\
1328 	    store_scanline_ ## format,					\
1329 	    store_scanline_generic_float				\
1330     }
1331 
1332 
1333 static const format_info_t accessors[] =
1334 {
1335 /* 32 bpp formats */
1336     FORMAT_INFO (a8r8g8b8),
1337     FORMAT_INFO (x8r8g8b8),
1338     FORMAT_INFO (a8b8g8r8),
1339     FORMAT_INFO (x8b8g8r8),
1340     FORMAT_INFO (b8g8r8a8),
1341     FORMAT_INFO (b8g8r8x8),
1342     FORMAT_INFO (r8g8b8a8),
1343     FORMAT_INFO (r8g8b8x8),
1344     FORMAT_INFO (x14r6g6b6),
1345 
1346 /* sRGB formats */
1347   { PIXMAN_a8r8g8b8_sRGB,
1348     NULL,
1349     fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
1350     fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
1351     NULL,
1352     store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
1353   },
1354 
1355 /* 24bpp formats */
1356     FORMAT_INFO (r8g8b8),
1357     FORMAT_INFO (b8g8r8),
1358 
1359 /* 16bpp formats */
1360     FORMAT_INFO16 (r5g6b5),
1361     FORMAT_INFO16 (b5g6r5),
1362 
1363     FORMAT_INFO (a1r5g5b5),
1364     FORMAT_INFO (x1r5g5b5),
1365     FORMAT_INFO (a1b5g5r5),
1366     FORMAT_INFO (x1b5g5r5),
1367     FORMAT_INFO (a4r4g4b4),
1368     FORMAT_INFO (x4r4g4b4),
1369     FORMAT_INFO (a4b4g4r4),
1370     FORMAT_INFO (x4b4g4r4),
1371 
1372 /* 8bpp formats */
1373     FORMAT_INFO (a8),
1374     FORMAT_INFO (r3g3b2),
1375     FORMAT_INFO (b2g3r3),
1376     FORMAT_INFO (a2r2g2b2),
1377     FORMAT_INFO (a2b2g2r2),
1378 
1379     FORMAT_INFO (c8),
1380 
1381     FORMAT_INFO (g8),
1382 
1383 #define fetch_scanline_x4c4 fetch_scanline_c8
1384 #define fetch_pixel_x4c4 fetch_pixel_c8
1385 #define store_scanline_x4c4 store_scanline_c8
1386     FORMAT_INFO (x4c4),
1387 
1388 #define fetch_scanline_x4g4 fetch_scanline_g8
1389 #define fetch_pixel_x4g4 fetch_pixel_g8
1390 #define store_scanline_x4g4 store_scanline_g8
1391     FORMAT_INFO (x4g4),
1392 
1393     FORMAT_INFO (x4a4),
1394 
1395 /* 4bpp formats */
1396     FORMAT_INFO (a4),
1397     FORMAT_INFO (r1g2b1),
1398     FORMAT_INFO (b1g2r1),
1399     FORMAT_INFO (a1r1g1b1),
1400     FORMAT_INFO (a1b1g1r1),
1401 
1402     FORMAT_INFO (c4),
1403 
1404     FORMAT_INFO (g4),
1405 
1406 /* 1bpp formats */
1407     FORMAT_INFO (a1),
1408     FORMAT_INFO (g1),
1409 
1410 /* Wide formats */
1411 
1412     { PIXMAN_a2r10g10b10,
1413       NULL, NULL, fetch_scanline_a2r10g10b10_float,
1414       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
1415       NULL, NULL, store_scanline_a2r10g10b10_float },
1416 
1417     { PIXMAN_x2r10g10b10,
1418       NULL, NULL, fetch_scanline_x2r10g10b10_float,
1419       fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
1420       NULL, NULL, store_scanline_x2r10g10b10_float },
1421 
1422     { PIXMAN_a2b10g10r10,
1423       NULL, NULL, fetch_scanline_a2b10g10r10_float,
1424       fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
1425       NULL, NULL, store_scanline_a2b10g10r10_float },
1426 
1427     { PIXMAN_x2b10g10r10,
1428       NULL, NULL, fetch_scanline_x2b10g10r10_float,
1429       fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
1430       NULL, NULL, store_scanline_x2b10g10r10_float },
1431 
1432 /* YUV formats */
1433     { PIXMAN_yuy2,
1434       NULL, fetch_scanline_yuy2, fetch_scanline_generic_float,
1435       fetch_pixel_yuy2, fetch_pixel_generic_float,
1436       NULL, NULL, NULL },
1437 
1438     { PIXMAN_yv12,
1439       NULL, fetch_scanline_yv12, fetch_scanline_generic_float,
1440       fetch_pixel_yv12, fetch_pixel_generic_float,
1441       NULL, NULL, NULL },
1442 
1443     { PIXMAN_null },
1444 };
1445 
1446 static void
setup_accessors(bits_image_t * image)1447 setup_accessors (bits_image_t *image)
1448 {
1449     const format_info_t *info = accessors;
1450 
1451     while (info->format != PIXMAN_null)
1452     {
1453 	if (info->format == image->format)
1454 	{
1455 	    image->fetch_scanline_16 = info->fetch_scanline_16;
1456 	    image->fetch_scanline_32 = info->fetch_scanline_32;
1457 	    image->fetch_scanline_float = info->fetch_scanline_float;
1458 	    image->fetch_pixel_32 = info->fetch_pixel_32;
1459 	    image->fetch_pixel_float = info->fetch_pixel_float;
1460 	    image->store_scanline_16 = info->store_scanline_16;
1461 	    image->store_scanline_32 = info->store_scanline_32;
1462 	    image->store_scanline_float = info->store_scanline_float;
1463 
1464 	    return;
1465 	}
1466 
1467 	info++;
1468     }
1469 }
1470 
1471 #ifndef PIXMAN_FB_ACCESSORS
1472 void
1473 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1474 
1475 void
_pixman_bits_image_setup_accessors(bits_image_t * image)1476 _pixman_bits_image_setup_accessors (bits_image_t *image)
1477 {
1478     if (image->read_func || image->write_func)
1479 	_pixman_bits_image_setup_accessors_accessors (image);
1480     else
1481 	setup_accessors (image);
1482 }
1483 
1484 #else
1485 
1486 void
_pixman_bits_image_setup_accessors_accessors(bits_image_t * image)1487 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1488 {
1489     setup_accessors (image);
1490 }
1491 
1492 #endif
1493