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     ((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 16)    |       \
72      (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)     |       \
73      (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 2)) << 0))
74 #else
75 #define FETCH_24(img,l,o)						\
76     ((uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 0)) << 0)	|	\
77      (uint32_t)(READ (img, (((uint8_t *)(l)) + ((o) * 3) + 1)) << 8)	|	\
78      (uint32_t)(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 = 1U << (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 = 1U << ((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(bits_image_t * image,pixman_format_code_t format,uint32_t pixel)297 convert_pixel_to_a8r8g8b8 (bits_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->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(bits_image_t * image,const uint8_t * bits,int offset,pixman_format_code_t format)335 fetch_and_convert_pixel (bits_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 (bits_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 + y * image->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 (				\
465 	    image, 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(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)586 fetch_scanline_a8r8g8b8_sRGB_float (bits_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 + y * image->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(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)615 fetch_scanline_a2r10g10b10_float (bits_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 + y * image->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 #ifndef PIXMAN_FB_ACCESSORS
646 static void
fetch_scanline_rgbf_float(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)647 fetch_scanline_rgbf_float (bits_image_t   *image,
648 			   int             x,
649 			   int             y,
650 			   int             width,
651 			   uint32_t *      b,
652 			   const uint32_t *mask)
653 {
654     const float *bits = (float *)image->bits + y * image->rowstride;
655     const float *pixel = bits + x * 3;
656     argb_t *buffer = (argb_t *)b;
657 
658     for (; width--; buffer++) {
659 	buffer->r = *pixel++;
660 	buffer->g = *pixel++;
661 	buffer->b = *pixel++;
662 	buffer->a = 1.f;
663     }
664 }
665 
666 static void
fetch_scanline_rgbaf_float(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)667 fetch_scanline_rgbaf_float (bits_image_t   *image,
668 			    int             x,
669 			    int             y,
670 			    int             width,
671 			    uint32_t *      b,
672 			    const uint32_t *mask)
673 {
674     const float *bits = (float *)image->bits + y * image->rowstride;
675     const float *pixel = bits + x * 4;
676     argb_t *buffer = (argb_t *)b;
677 
678     for (; width--; buffer++) {
679 	buffer->r = *pixel++;
680 	buffer->g = *pixel++;
681 	buffer->b = *pixel++;
682 	buffer->a = *pixel++;
683     }
684 }
685 #endif
686 
687 static void
fetch_scanline_x2r10g10b10_float(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)688 fetch_scanline_x2r10g10b10_float (bits_image_t   *image,
689 				  int             x,
690 				  int             y,
691 				  int             width,
692 				  uint32_t *      b,
693 				  const uint32_t *mask)
694 {
695     const uint32_t *bits = image->bits + y * image->rowstride;
696     const uint32_t *pixel = (uint32_t *)bits + x;
697     const uint32_t *end = pixel + width;
698     argb_t *buffer = (argb_t *)b;
699 
700     while (pixel < end)
701     {
702 	uint32_t p = READ (image, pixel++);
703 	uint64_t r = (p >> 20) & 0x3ff;
704 	uint64_t g = (p >> 10) & 0x3ff;
705 	uint64_t b = p & 0x3ff;
706 
707 	buffer->a = 1.0;
708 	buffer->r = pixman_unorm_to_float (r, 10);
709 	buffer->g = pixman_unorm_to_float (g, 10);
710 	buffer->b = pixman_unorm_to_float (b, 10);
711 
712 	buffer++;
713     }
714 }
715 
716 /* Expects a float buffer */
717 static void
fetch_scanline_a2b10g10r10_float(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)718 fetch_scanline_a2b10g10r10_float (bits_image_t   *image,
719 				  int             x,
720 				  int             y,
721 				  int             width,
722 				  uint32_t *      b,
723 				  const uint32_t *mask)
724 {
725     const uint32_t *bits = image->bits + y * image->rowstride;
726     const uint32_t *pixel = bits + x;
727     const uint32_t *end = pixel + width;
728     argb_t *buffer = (argb_t *)b;
729 
730     while (pixel < end)
731     {
732 	uint32_t p = READ (image, pixel++);
733 	uint64_t a = p >> 30;
734 	uint64_t b = (p >> 20) & 0x3ff;
735 	uint64_t g = (p >> 10) & 0x3ff;
736 	uint64_t r = p & 0x3ff;
737 
738 	buffer->a = pixman_unorm_to_float (a, 2);
739 	buffer->r = pixman_unorm_to_float (r, 10);
740 	buffer->g = pixman_unorm_to_float (g, 10);
741 	buffer->b = pixman_unorm_to_float (b, 10);
742 
743 	buffer++;
744     }
745 }
746 
747 /* Expects a float buffer */
748 static void
fetch_scanline_x2b10g10r10_float(bits_image_t * image,int x,int y,int width,uint32_t * b,const uint32_t * mask)749 fetch_scanline_x2b10g10r10_float (bits_image_t   *image,
750 				  int             x,
751 				  int             y,
752 				  int             width,
753 				  uint32_t *      b,
754 				  const uint32_t *mask)
755 {
756     const uint32_t *bits = image->bits + y * image->rowstride;
757     const uint32_t *pixel = (uint32_t *)bits + x;
758     const uint32_t *end = pixel + width;
759     argb_t *buffer = (argb_t *)b;
760 
761     while (pixel < end)
762     {
763 	uint32_t p = READ (image, pixel++);
764 	uint64_t b = (p >> 20) & 0x3ff;
765 	uint64_t g = (p >> 10) & 0x3ff;
766 	uint64_t r = p & 0x3ff;
767 
768 	buffer->a = 1.0;
769 	buffer->r = pixman_unorm_to_float (r, 10);
770 	buffer->g = pixman_unorm_to_float (g, 10);
771 	buffer->b = pixman_unorm_to_float (b, 10);
772 
773 	buffer++;
774     }
775 }
776 
777 static void
fetch_scanline_yuy2(bits_image_t * image,int x,int line,int width,uint32_t * buffer,const uint32_t * mask)778 fetch_scanline_yuy2 (bits_image_t   *image,
779                      int             x,
780                      int             line,
781                      int             width,
782                      uint32_t *      buffer,
783                      const uint32_t *mask)
784 {
785     const uint32_t *bits = image->bits + image->rowstride * line;
786     int i;
787 
788     for (i = 0; i < width; i++)
789     {
790 	int16_t y, u, v;
791 	int32_t r, g, b;
792 
793 	y = ((uint8_t *) bits)[(x + i) << 1] - 16;
794 	u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
795 	v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
796 
797 	/* R = 1.164(Y - 16) + 1.596(V - 128) */
798 	r = 0x012b27 * y + 0x019a2e * v;
799 	/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
800 	g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
801 	/* B = 1.164(Y - 16) + 2.018(U - 128) */
802 	b = 0x012b27 * y + 0x0206a2 * u;
803 
804 	*buffer++ = 0xff000000 |
805 	    (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
806 	    (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
807 	    (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
808     }
809 }
810 
811 static void
fetch_scanline_yv12(bits_image_t * image,int x,int line,int width,uint32_t * buffer,const uint32_t * mask)812 fetch_scanline_yv12 (bits_image_t   *image,
813                      int             x,
814                      int             line,
815                      int             width,
816                      uint32_t *      buffer,
817                      const uint32_t *mask)
818 {
819     YV12_SETUP (image);
820     uint8_t *y_line = YV12_Y (line);
821     uint8_t *u_line = YV12_U (line);
822     uint8_t *v_line = YV12_V (line);
823     int i;
824 
825     for (i = 0; i < width; i++)
826     {
827 	int16_t y, u, v;
828 	int32_t r, g, b;
829 
830 	y = y_line[x + i] - 16;
831 	u = u_line[(x + i) >> 1] - 128;
832 	v = v_line[(x + i) >> 1] - 128;
833 
834 	/* R = 1.164(Y - 16) + 1.596(V - 128) */
835 	r = 0x012b27 * y + 0x019a2e * v;
836 	/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
837 	g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
838 	/* B = 1.164(Y - 16) + 2.018(U - 128) */
839 	b = 0x012b27 * y + 0x0206a2 * u;
840 
841 	*buffer++ = 0xff000000 |
842 	    (r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
843 	    (g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
844 	    (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
845     }
846 }
847 
848 /**************************** Pixel wise fetching *****************************/
849 
850 #ifndef PIXMAN_FB_ACCESSORS
851 static argb_t
fetch_pixel_rgbf_float(bits_image_t * image,int offset,int line)852 fetch_pixel_rgbf_float (bits_image_t *image,
853 			int	    offset,
854 			int	    line)
855 {
856     float *bits = (float *)image->bits + line * image->rowstride;
857     argb_t argb;
858 
859     argb.r = bits[offset * 3];
860     argb.g = bits[offset * 3 + 1];
861     argb.b = bits[offset * 3 + 2];
862     argb.a = 1.f;
863 
864     return argb;
865 }
866 
867 static argb_t
fetch_pixel_rgbaf_float(bits_image_t * image,int offset,int line)868 fetch_pixel_rgbaf_float (bits_image_t *image,
869 			 int	    offset,
870 			 int	    line)
871 {
872     float *bits = (float *)image->bits + line * image->rowstride;
873     argb_t argb;
874 
875     argb.r = bits[offset * 4];
876     argb.g = bits[offset * 4 + 1];
877     argb.b = bits[offset * 4 + 2];
878     argb.a = bits[offset * 4 + 3];
879 
880     return argb;
881 }
882 #endif
883 
884 static argb_t
fetch_pixel_x2r10g10b10_float(bits_image_t * image,int offset,int line)885 fetch_pixel_x2r10g10b10_float (bits_image_t *image,
886 			       int	   offset,
887 			       int           line)
888 {
889     uint32_t *bits = image->bits + line * image->rowstride;
890     uint32_t p = READ (image, bits + offset);
891     uint64_t r = (p >> 20) & 0x3ff;
892     uint64_t g = (p >> 10) & 0x3ff;
893     uint64_t b = p & 0x3ff;
894     argb_t argb;
895 
896     argb.a = 1.0;
897     argb.r = pixman_unorm_to_float (r, 10);
898     argb.g = pixman_unorm_to_float (g, 10);
899     argb.b = pixman_unorm_to_float (b, 10);
900 
901     return argb;
902 }
903 
904 static argb_t
fetch_pixel_a2r10g10b10_float(bits_image_t * image,int offset,int line)905 fetch_pixel_a2r10g10b10_float (bits_image_t *image,
906 			       int	     offset,
907 			       int           line)
908 {
909     uint32_t *bits = image->bits + line * image->rowstride;
910     uint32_t p = READ (image, bits + offset);
911     uint64_t a = p >> 30;
912     uint64_t r = (p >> 20) & 0x3ff;
913     uint64_t g = (p >> 10) & 0x3ff;
914     uint64_t b = p & 0x3ff;
915     argb_t argb;
916 
917     argb.a = pixman_unorm_to_float (a, 2);
918     argb.r = pixman_unorm_to_float (r, 10);
919     argb.g = pixman_unorm_to_float (g, 10);
920     argb.b = pixman_unorm_to_float (b, 10);
921 
922     return argb;
923 }
924 
925 static argb_t
fetch_pixel_a2b10g10r10_float(bits_image_t * image,int offset,int line)926 fetch_pixel_a2b10g10r10_float (bits_image_t *image,
927 			       int           offset,
928 			       int           line)
929 {
930     uint32_t *bits = image->bits + line * image->rowstride;
931     uint32_t p = READ (image, bits + offset);
932     uint64_t a = p >> 30;
933     uint64_t b = (p >> 20) & 0x3ff;
934     uint64_t g = (p >> 10) & 0x3ff;
935     uint64_t r = p & 0x3ff;
936     argb_t argb;
937 
938     argb.a = pixman_unorm_to_float (a, 2);
939     argb.r = pixman_unorm_to_float (r, 10);
940     argb.g = pixman_unorm_to_float (g, 10);
941     argb.b = pixman_unorm_to_float (b, 10);
942 
943     return argb;
944 }
945 
946 static argb_t
fetch_pixel_x2b10g10r10_float(bits_image_t * image,int offset,int line)947 fetch_pixel_x2b10g10r10_float (bits_image_t *image,
948 			       int           offset,
949 			       int           line)
950 {
951     uint32_t *bits = image->bits + line * image->rowstride;
952     uint32_t p = READ (image, bits + offset);
953     uint64_t b = (p >> 20) & 0x3ff;
954     uint64_t g = (p >> 10) & 0x3ff;
955     uint64_t r = p & 0x3ff;
956     argb_t argb;
957 
958     argb.a = 1.0;
959     argb.r = pixman_unorm_to_float (r, 10);
960     argb.g = pixman_unorm_to_float (g, 10);
961     argb.b = pixman_unorm_to_float (b, 10);
962 
963     return argb;
964 }
965 
966 static argb_t
fetch_pixel_a8r8g8b8_sRGB_float(bits_image_t * image,int offset,int line)967 fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
968 				 int	       offset,
969 				 int           line)
970 {
971     uint32_t *bits = image->bits + line * image->rowstride;
972     uint32_t p = READ (image, bits + offset);
973     argb_t argb;
974 
975     argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
976 
977     argb.r = to_linear [(p >> 16) & 0xff];
978     argb.g = to_linear [(p >>  8) & 0xff];
979     argb.b = to_linear [(p >>  0) & 0xff];
980 
981     return argb;
982 }
983 
984 static uint32_t
fetch_pixel_yuy2(bits_image_t * image,int offset,int line)985 fetch_pixel_yuy2 (bits_image_t *image,
986 		  int           offset,
987 		  int           line)
988 {
989     const uint32_t *bits = image->bits + image->rowstride * line;
990 
991     int16_t y, u, v;
992     int32_t r, g, b;
993 
994     y = ((uint8_t *) bits)[offset << 1] - 16;
995     u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
996     v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
997 
998     /* R = 1.164(Y - 16) + 1.596(V - 128) */
999     r = 0x012b27 * y + 0x019a2e * v;
1000 
1001     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
1002     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
1003 
1004     /* B = 1.164(Y - 16) + 2.018(U - 128) */
1005     b = 0x012b27 * y + 0x0206a2 * u;
1006 
1007     return 0xff000000 |
1008 	(r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
1009 	(g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
1010 	(b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
1011 }
1012 
1013 static uint32_t
fetch_pixel_yv12(bits_image_t * image,int offset,int line)1014 fetch_pixel_yv12 (bits_image_t *image,
1015 		  int           offset,
1016 		  int           line)
1017 {
1018     YV12_SETUP (image);
1019     int16_t y = YV12_Y (line)[offset] - 16;
1020     int16_t u = YV12_U (line)[offset >> 1] - 128;
1021     int16_t v = YV12_V (line)[offset >> 1] - 128;
1022     int32_t r, g, b;
1023 
1024     /* R = 1.164(Y - 16) + 1.596(V - 128) */
1025     r = 0x012b27 * y + 0x019a2e * v;
1026 
1027     /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
1028     g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
1029 
1030     /* B = 1.164(Y - 16) + 2.018(U - 128) */
1031     b = 0x012b27 * y + 0x0206a2 * u;
1032 
1033     return 0xff000000 |
1034 	(r >= 0 ? r < 0x1000000 ? r         & 0xff0000 : 0xff0000 : 0) |
1035 	(g >= 0 ? g < 0x1000000 ? (g >> 8)  & 0x00ff00 : 0x00ff00 : 0) |
1036 	(b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
1037 }
1038 
1039 /*********************************** Store ************************************/
1040 
1041 #ifndef PIXMAN_FB_ACCESSORS
1042 static void
store_scanline_rgbaf_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1043 store_scanline_rgbaf_float (bits_image_t *  image,
1044 			    int             x,
1045 			    int             y,
1046 			    int             width,
1047 			    const uint32_t *v)
1048 {
1049     float *bits = (float *)image->bits + image->rowstride * y + 4 * x;
1050     const argb_t *values = (argb_t *)v;
1051 
1052     for (; width; width--, values++)
1053     {
1054 	*bits++ = values->r;
1055 	*bits++ = values->g;
1056 	*bits++ = values->b;
1057 	*bits++ = values->a;
1058     }
1059 }
1060 
1061 static void
store_scanline_rgbf_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1062 store_scanline_rgbf_float (bits_image_t *  image,
1063 			   int             x,
1064 			   int             y,
1065 			   int             width,
1066 			   const uint32_t *v)
1067 {
1068     float *bits = (float *)image->bits + image->rowstride * y + 3 * x;
1069     const argb_t *values = (argb_t *)v;
1070 
1071     for (; width; width--, values++)
1072     {
1073 	*bits++ = values->r;
1074 	*bits++ = values->g;
1075 	*bits++ = values->b;
1076     }
1077 }
1078 #endif
1079 
1080 static void
store_scanline_a2r10g10b10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1081 store_scanline_a2r10g10b10_float (bits_image_t *  image,
1082 				  int             x,
1083 				  int             y,
1084 				  int             width,
1085 				  const uint32_t *v)
1086 {
1087     uint32_t *bits = image->bits + image->rowstride * y;
1088     uint32_t *pixel = bits + x;
1089     argb_t *values = (argb_t *)v;
1090     int i;
1091 
1092     for (i = 0; i < width; ++i)
1093     {
1094 	uint32_t a, r, g, b;
1095 
1096 	a = pixman_float_to_unorm (values[i].a, 2);
1097 	r = pixman_float_to_unorm (values[i].r, 10);
1098 	g = pixman_float_to_unorm (values[i].g, 10);
1099 	b = pixman_float_to_unorm (values[i].b, 10);
1100 
1101 	WRITE (image, pixel++,
1102 	       (a << 30) | (r << 20) | (g << 10) | b);
1103     }
1104 }
1105 
1106 static void
store_scanline_x2r10g10b10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1107 store_scanline_x2r10g10b10_float (bits_image_t *  image,
1108 				  int             x,
1109 				  int             y,
1110 				  int             width,
1111 				  const uint32_t *v)
1112 {
1113     uint32_t *bits = image->bits + image->rowstride * y;
1114     uint32_t *pixel = bits + x;
1115     argb_t *values = (argb_t *)v;
1116     int i;
1117 
1118     for (i = 0; i < width; ++i)
1119     {
1120 	uint32_t r, g, b;
1121 
1122 	r = pixman_float_to_unorm (values[i].r, 10);
1123 	g = pixman_float_to_unorm (values[i].g, 10);
1124 	b = pixman_float_to_unorm (values[i].b, 10);
1125 
1126 	WRITE (image, pixel++,
1127 	       (r << 20) | (g << 10) | b);
1128     }
1129 }
1130 
1131 static void
store_scanline_a2b10g10r10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1132 store_scanline_a2b10g10r10_float (bits_image_t *  image,
1133 				  int             x,
1134 				  int             y,
1135 				  int             width,
1136 				  const uint32_t *v)
1137 {
1138     uint32_t *bits = image->bits + image->rowstride * y;
1139     uint32_t *pixel = bits + x;
1140     argb_t *values = (argb_t *)v;
1141     int i;
1142 
1143     for (i = 0; i < width; ++i)
1144     {
1145 	uint32_t a, r, g, b;
1146 
1147 	a = pixman_float_to_unorm (values[i].a, 2);
1148 	r = pixman_float_to_unorm (values[i].r, 10);
1149 	g = pixman_float_to_unorm (values[i].g, 10);
1150 	b = pixman_float_to_unorm (values[i].b, 10);
1151 
1152 	WRITE (image, pixel++,
1153 	       (a << 30) | (b << 20) | (g << 10) | r);
1154     }
1155 }
1156 
1157 static void
store_scanline_x2b10g10r10_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1158 store_scanline_x2b10g10r10_float (bits_image_t *  image,
1159 				  int             x,
1160 				  int             y,
1161 				  int             width,
1162 				  const uint32_t *v)
1163 {
1164     uint32_t *bits = image->bits + image->rowstride * y;
1165     uint32_t *pixel = bits + x;
1166     argb_t *values = (argb_t *)v;
1167     int i;
1168 
1169     for (i = 0; i < width; ++i)
1170     {
1171 	uint32_t r, g, b;
1172 
1173 	r = pixman_float_to_unorm (values[i].r, 10);
1174 	g = pixman_float_to_unorm (values[i].g, 10);
1175 	b = pixman_float_to_unorm (values[i].b, 10);
1176 
1177 	WRITE (image, pixel++,
1178 	       (b << 20) | (g << 10) | r);
1179     }
1180 }
1181 
1182 static void
store_scanline_a8r8g8b8_sRGB_float(bits_image_t * image,int x,int y,int width,const uint32_t * v)1183 store_scanline_a8r8g8b8_sRGB_float (bits_image_t *  image,
1184 				    int             x,
1185 				    int             y,
1186 				    int             width,
1187 				    const uint32_t *v)
1188 {
1189     uint32_t *bits = image->bits + image->rowstride * y;
1190     uint32_t *pixel = bits + x;
1191     argb_t *values = (argb_t *)v;
1192     int i;
1193 
1194     for (i = 0; i < width; ++i)
1195     {
1196 	uint32_t a, r, g, b;
1197 
1198 	a = pixman_float_to_unorm (values[i].a, 8);
1199 	r = to_srgb (values[i].r);
1200 	g = to_srgb (values[i].g);
1201 	b = to_srgb (values[i].b);
1202 
1203 	WRITE (image, pixel++,
1204 	       (a << 24) | (r << 16) | (g << 8) | b);
1205     }
1206 }
1207 
1208 /*
1209  * Contracts a floating point image to 32bpp and then stores it using a
1210  * regular 32-bit store proc. Despite the type, this function expects an
1211  * argb_t buffer.
1212  */
1213 static void
store_scanline_generic_float(bits_image_t * image,int x,int y,int width,const uint32_t * values)1214 store_scanline_generic_float (bits_image_t *  image,
1215 			      int             x,
1216 			      int             y,
1217 			      int             width,
1218 			      const uint32_t *values)
1219 {
1220     uint32_t *argb8_pixels;
1221 
1222     assert (image->common.type == BITS);
1223 
1224     argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1225     if (!argb8_pixels)
1226 	return;
1227 
1228     /* Contract the scanline.  We could do this in place if values weren't
1229      * const.
1230      */
1231     pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1232 
1233     image->store_scanline_32 (image, x, y, width, argb8_pixels);
1234 
1235     free (argb8_pixels);
1236 }
1237 
1238 static void
fetch_scanline_generic_float(bits_image_t * image,int x,int y,int width,uint32_t * buffer,const uint32_t * mask)1239 fetch_scanline_generic_float (bits_image_t *  image,
1240 			      int	      x,
1241 			      int	      y,
1242 			      int	      width,
1243 			      uint32_t *      buffer,
1244 			      const uint32_t *mask)
1245 {
1246     image->fetch_scanline_32 (image, x, y, width, buffer, NULL);
1247 
1248     pixman_expand_to_float ((argb_t *)buffer, buffer, image->format, width);
1249 }
1250 
1251 /* The 32_sRGB paths should be deleted after narrow processing
1252  * is no longer invoked for formats that are considered wide.
1253  * (Also see fetch_pixel_generic_lossy_32) */
1254 static void
fetch_scanline_a8r8g8b8_32_sRGB(bits_image_t * image,int x,int y,int width,uint32_t * buffer,const uint32_t * mask)1255 fetch_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
1256                                  int             x,
1257                                  int             y,
1258                                  int             width,
1259                                  uint32_t       *buffer,
1260                                  const uint32_t *mask)
1261 {
1262     const uint32_t *bits = image->bits + y * image->rowstride;
1263     const uint32_t *pixel = (uint32_t *)bits + x;
1264     const uint32_t *end = pixel + width;
1265     uint32_t tmp;
1266 
1267     while (pixel < end)
1268     {
1269 	uint32_t a, r, g, b;
1270 
1271 	tmp = READ (image, pixel++);
1272 
1273 	a = (tmp >> 24) & 0xff;
1274 	r = (tmp >> 16) & 0xff;
1275 	g = (tmp >> 8) & 0xff;
1276 	b = (tmp >> 0) & 0xff;
1277 
1278 	r = to_linear[r] * 255.0f + 0.5f;
1279 	g = to_linear[g] * 255.0f + 0.5f;
1280 	b = to_linear[b] * 255.0f + 0.5f;
1281 
1282 	*buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1283     }
1284 }
1285 
1286 static uint32_t
fetch_pixel_a8r8g8b8_32_sRGB(bits_image_t * image,int offset,int line)1287 fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1288 			      int           offset,
1289 			      int           line)
1290 {
1291     uint32_t *bits = image->bits + line * image->rowstride;
1292     uint32_t tmp = READ (image, bits + offset);
1293     uint32_t a, r, g, b;
1294 
1295     a = (tmp >> 24) & 0xff;
1296     r = (tmp >> 16) & 0xff;
1297     g = (tmp >> 8) & 0xff;
1298     b = (tmp >> 0) & 0xff;
1299 
1300     r = to_linear[r] * 255.0f + 0.5f;
1301     g = to_linear[g] * 255.0f + 0.5f;
1302     b = to_linear[b] * 255.0f + 0.5f;
1303 
1304     return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1305 }
1306 
1307 static void
store_scanline_a8r8g8b8_32_sRGB(bits_image_t * image,int x,int y,int width,const uint32_t * v)1308 store_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
1309                                  int             x,
1310                                  int             y,
1311                                  int             width,
1312                                  const uint32_t *v)
1313 {
1314     uint32_t *bits = image->bits + image->rowstride * y;
1315     uint64_t *values = (uint64_t *)v;
1316     uint32_t *pixel = bits + x;
1317     uint64_t tmp;
1318     int i;
1319 
1320     for (i = 0; i < width; ++i)
1321     {
1322 	uint32_t a, r, g, b;
1323 
1324 	tmp = values[i];
1325 
1326 	a = (tmp >> 24) & 0xff;
1327 	r = (tmp >> 16) & 0xff;
1328 	g = (tmp >> 8) & 0xff;
1329 	b = (tmp >> 0) & 0xff;
1330 
1331 	r = to_srgb (r * (1/255.0f));
1332 	g = to_srgb (g * (1/255.0f));
1333 	b = to_srgb (b * (1/255.0f));
1334 
1335 	WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1336     }
1337 }
1338 
1339 static argb_t
fetch_pixel_generic_float(bits_image_t * image,int offset,int line)1340 fetch_pixel_generic_float (bits_image_t *image,
1341 			   int		 offset,
1342 			   int           line)
1343 {
1344     uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1345     argb_t f;
1346 
1347     pixman_expand_to_float (&f, &pixel32, image->format, 1);
1348 
1349     return f;
1350 }
1351 
1352 /*
1353  * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1354  * paths have wide versions, this can be removed.
1355  *
1356  * WARNING: This function loses precision!
1357  */
1358 static uint32_t
fetch_pixel_generic_lossy_32(bits_image_t * image,int offset,int line)1359 fetch_pixel_generic_lossy_32 (bits_image_t *image,
1360 			      int           offset,
1361 			      int           line)
1362 {
1363     argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1364     uint32_t result;
1365 
1366     pixman_contract_from_float (&result, &pixel64, 1);
1367 
1368     return result;
1369 }
1370 
1371 typedef struct
1372 {
1373     pixman_format_code_t	format;
1374     fetch_scanline_t		fetch_scanline_32;
1375     fetch_scanline_t		fetch_scanline_float;
1376     fetch_pixel_32_t		fetch_pixel_32;
1377     fetch_pixel_float_t		fetch_pixel_float;
1378     store_scanline_t		store_scanline_32;
1379     store_scanline_t		store_scanline_float;
1380 } format_info_t;
1381 
1382 #define FORMAT_INFO(format) 						\
1383     {									\
1384 	PIXMAN_ ## format,						\
1385 	    fetch_scanline_ ## format,					\
1386 	    fetch_scanline_generic_float,				\
1387 	    fetch_pixel_ ## format,					\
1388 	    fetch_pixel_generic_float,					\
1389 	    store_scanline_ ## format,					\
1390 	    store_scanline_generic_float				\
1391     }
1392 
1393 static const format_info_t accessors[] =
1394 {
1395 /* 32 bpp formats */
1396     FORMAT_INFO (a8r8g8b8),
1397     FORMAT_INFO (x8r8g8b8),
1398     FORMAT_INFO (a8b8g8r8),
1399     FORMAT_INFO (x8b8g8r8),
1400     FORMAT_INFO (b8g8r8a8),
1401     FORMAT_INFO (b8g8r8x8),
1402     FORMAT_INFO (r8g8b8a8),
1403     FORMAT_INFO (r8g8b8x8),
1404     FORMAT_INFO (x14r6g6b6),
1405 
1406 /* sRGB formats */
1407   { PIXMAN_a8r8g8b8_sRGB,
1408     fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
1409     fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
1410     store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
1411   },
1412 
1413 /* 24bpp formats */
1414     FORMAT_INFO (r8g8b8),
1415     FORMAT_INFO (b8g8r8),
1416 
1417 /* 16bpp formats */
1418     FORMAT_INFO (r5g6b5),
1419     FORMAT_INFO (b5g6r5),
1420 
1421     FORMAT_INFO (a1r5g5b5),
1422     FORMAT_INFO (x1r5g5b5),
1423     FORMAT_INFO (a1b5g5r5),
1424     FORMAT_INFO (x1b5g5r5),
1425     FORMAT_INFO (a4r4g4b4),
1426     FORMAT_INFO (x4r4g4b4),
1427     FORMAT_INFO (a4b4g4r4),
1428     FORMAT_INFO (x4b4g4r4),
1429 
1430 /* 8bpp formats */
1431     FORMAT_INFO (a8),
1432     FORMAT_INFO (r3g3b2),
1433     FORMAT_INFO (b2g3r3),
1434     FORMAT_INFO (a2r2g2b2),
1435     FORMAT_INFO (a2b2g2r2),
1436 
1437     FORMAT_INFO (c8),
1438 
1439     FORMAT_INFO (g8),
1440 
1441 #define fetch_scanline_x4c4 fetch_scanline_c8
1442 #define fetch_pixel_x4c4 fetch_pixel_c8
1443 #define store_scanline_x4c4 store_scanline_c8
1444     FORMAT_INFO (x4c4),
1445 
1446 #define fetch_scanline_x4g4 fetch_scanline_g8
1447 #define fetch_pixel_x4g4 fetch_pixel_g8
1448 #define store_scanline_x4g4 store_scanline_g8
1449     FORMAT_INFO (x4g4),
1450 
1451     FORMAT_INFO (x4a4),
1452 
1453 /* 4bpp formats */
1454     FORMAT_INFO (a4),
1455     FORMAT_INFO (r1g2b1),
1456     FORMAT_INFO (b1g2r1),
1457     FORMAT_INFO (a1r1g1b1),
1458     FORMAT_INFO (a1b1g1r1),
1459 
1460     FORMAT_INFO (c4),
1461 
1462     FORMAT_INFO (g4),
1463 
1464 /* 1bpp formats */
1465     FORMAT_INFO (a1),
1466     FORMAT_INFO (g1),
1467 
1468 /* Wide formats */
1469 #ifndef PIXMAN_FB_ACCESSORS
1470     { PIXMAN_rgba_float,
1471       NULL, fetch_scanline_rgbaf_float,
1472       fetch_pixel_generic_lossy_32, fetch_pixel_rgbaf_float,
1473       NULL, store_scanline_rgbaf_float },
1474 
1475     { PIXMAN_rgb_float,
1476       NULL, fetch_scanline_rgbf_float,
1477       fetch_pixel_generic_lossy_32, fetch_pixel_rgbf_float,
1478       NULL, store_scanline_rgbf_float },
1479 #endif
1480 
1481     { PIXMAN_a2r10g10b10,
1482       NULL, fetch_scanline_a2r10g10b10_float,
1483       fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
1484       NULL, store_scanline_a2r10g10b10_float },
1485 
1486     { PIXMAN_x2r10g10b10,
1487       NULL, fetch_scanline_x2r10g10b10_float,
1488       fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
1489       NULL, store_scanline_x2r10g10b10_float },
1490 
1491     { PIXMAN_a2b10g10r10,
1492       NULL, fetch_scanline_a2b10g10r10_float,
1493       fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
1494       NULL, store_scanline_a2b10g10r10_float },
1495 
1496     { PIXMAN_x2b10g10r10,
1497       NULL, fetch_scanline_x2b10g10r10_float,
1498       fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
1499       NULL, store_scanline_x2b10g10r10_float },
1500 
1501 /* YUV formats */
1502     { PIXMAN_yuy2,
1503       fetch_scanline_yuy2, fetch_scanline_generic_float,
1504       fetch_pixel_yuy2, fetch_pixel_generic_float,
1505       NULL, NULL },
1506 
1507     { PIXMAN_yv12,
1508       fetch_scanline_yv12, fetch_scanline_generic_float,
1509       fetch_pixel_yv12, fetch_pixel_generic_float,
1510       NULL, NULL },
1511 
1512     { PIXMAN_null },
1513 };
1514 
1515 static void
setup_accessors(bits_image_t * image)1516 setup_accessors (bits_image_t *image)
1517 {
1518     const format_info_t *info = accessors;
1519 
1520     while (info->format != PIXMAN_null)
1521     {
1522 	if (info->format == image->format)
1523 	{
1524 	    image->fetch_scanline_32 = info->fetch_scanline_32;
1525 	    image->fetch_scanline_float = info->fetch_scanline_float;
1526 	    image->fetch_pixel_32 = info->fetch_pixel_32;
1527 	    image->fetch_pixel_float = info->fetch_pixel_float;
1528 	    image->store_scanline_32 = info->store_scanline_32;
1529 	    image->store_scanline_float = info->store_scanline_float;
1530 
1531 	    return;
1532 	}
1533 
1534 	info++;
1535     }
1536 }
1537 
1538 #ifndef PIXMAN_FB_ACCESSORS
1539 void
1540 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1541 
1542 void
_pixman_bits_image_setup_accessors(bits_image_t * image)1543 _pixman_bits_image_setup_accessors (bits_image_t *image)
1544 {
1545     if (image->read_func || image->write_func)
1546 	_pixman_bits_image_setup_accessors_accessors (image);
1547     else
1548 	setup_accessors (image);
1549 }
1550 
1551 #else
1552 
1553 void
_pixman_bits_image_setup_accessors_accessors(bits_image_t * image)1554 _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1555 {
1556     setup_accessors (image);
1557 }
1558 
1559 #endif
1560