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