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