Line data Source code
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
198 : get_shifts (pixman_format_code_t format,
199 : int *a,
200 : int *r,
201 : int *g,
202 : int *b)
203 : {
204 0 : switch (PIXMAN_FORMAT_TYPE (format))
205 : {
206 : case PIXMAN_TYPE_A:
207 0 : *b = 0;
208 0 : *g = 0;
209 0 : *r = 0;
210 0 : *a = 0;
211 : break;
212 :
213 : case PIXMAN_TYPE_ARGB:
214 : case PIXMAN_TYPE_ARGB_SRGB:
215 0 : *b = 0;
216 0 : *g = *b + PIXMAN_FORMAT_B (format);
217 0 : *r = *g + PIXMAN_FORMAT_G (format);
218 0 : *a = *r + PIXMAN_FORMAT_R (format);
219 : break;
220 :
221 : case PIXMAN_TYPE_ABGR:
222 0 : *r = 0;
223 0 : *g = *r + PIXMAN_FORMAT_R (format);
224 0 : *b = *g + PIXMAN_FORMAT_G (format);
225 0 : *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 0 : *b = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
231 0 : *g = *b - PIXMAN_FORMAT_B (format);
232 0 : *r = *g - PIXMAN_FORMAT_G (format);
233 0 : *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 0 : *r = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
239 0 : *g = *r - PIXMAN_FORMAT_R (format);
240 0 : *b = *g - PIXMAN_FORMAT_G (format);
241 0 : *a = *b - PIXMAN_FORMAT_B (format);
242 : break;
243 :
244 : default:
245 0 : assert (0);
246 : break;
247 : }
248 : }
249 :
250 : static force_inline uint32_t
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 0 : if (n_from_bits && n_to_bits)
258 0 : v = unorm_to_unorm (pixel >> from_shift, n_from_bits, n_to_bits);
259 0 : else if (n_to_bits)
260 0 : v = def_value;
261 : else
262 0 : v = 0;
263 :
264 0 : return (v & ((1 << n_to_bits) - 1)) << to_shift;
265 : }
266 :
267 : static force_inline uint32_t
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 0 : a = convert_channel (pixel, ~0,
278 0 : PIXMAN_FORMAT_A (from), a_from_shift,
279 0 : PIXMAN_FORMAT_A (to), a_to_shift);
280 :
281 0 : r = convert_channel (pixel, 0,
282 0 : PIXMAN_FORMAT_R (from), r_from_shift,
283 0 : PIXMAN_FORMAT_R (to), r_to_shift);
284 :
285 0 : g = convert_channel (pixel, 0,
286 0 : PIXMAN_FORMAT_G (from), g_from_shift,
287 0 : PIXMAN_FORMAT_G (to), g_to_shift);
288 :
289 0 : b = convert_channel (pixel, 0,
290 0 : PIXMAN_FORMAT_B (from), b_from_shift,
291 0 : PIXMAN_FORMAT_B (to), b_to_shift);
292 :
293 0 : return a | r | g | b;
294 : }
295 :
296 : static force_inline uint32_t
297 : convert_pixel_to_a8r8g8b8 (pixman_image_t *image,
298 : pixman_format_code_t format,
299 : uint32_t pixel)
300 : {
301 0 : if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY ||
302 0 : PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
303 : {
304 0 : return image->bits.indexed->rgba[pixel];
305 : }
306 : else
307 : {
308 0 : return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
309 : }
310 : }
311 :
312 : static force_inline uint32_t
313 : convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
314 : pixman_format_code_t format, uint32_t pixel)
315 : {
316 0 : if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
317 : {
318 0 : pixel = CONVERT_RGB24_TO_Y15 (pixel);
319 :
320 0 : return image->bits.indexed->ent[pixel & 0x7fff];
321 : }
322 0 : else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
323 : {
324 0 : pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel);
325 :
326 0 : return image->bits.indexed->ent[pixel & 0x7fff];
327 : }
328 : else
329 : {
330 0 : return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
331 : }
332 : }
333 :
334 : static force_inline uint32_t
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 0 : switch (PIXMAN_FORMAT_BPP (format))
343 : {
344 : case 1:
345 0 : pixel = FETCH_1 (image, bits, offset);
346 : break;
347 :
348 : case 4:
349 0 : pixel = FETCH_4 (image, bits, offset);
350 : break;
351 :
352 : case 8:
353 0 : pixel = READ (image, bits + offset);
354 : break;
355 :
356 : case 16:
357 0 : pixel = READ (image, ((uint16_t *)bits + offset));
358 : break;
359 :
360 : case 24:
361 0 : pixel = FETCH_24 (image, bits, offset);
362 : break;
363 :
364 : case 32:
365 0 : pixel = READ (image, ((uint32_t *)bits + offset));
366 : break;
367 :
368 : default:
369 0 : pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
370 : break;
371 : }
372 :
373 0 : return convert_pixel_to_a8r8g8b8 (image, format, pixel);
374 : }
375 :
376 : static force_inline void
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 0 : uint32_t converted = convert_pixel_from_a8r8g8b8 (
384 : (pixman_image_t *)image, format, pixel);
385 :
386 0 : switch (PIXMAN_FORMAT_BPP (format))
387 : {
388 : case 1:
389 0 : STORE_1 (image, dest, offset, converted & 0x01);
390 : break;
391 :
392 : case 4:
393 0 : STORE_4 (image, dest, offset, converted & 0xf);
394 : break;
395 :
396 : case 8:
397 0 : WRITE (image, (dest + offset), converted & 0xff);
398 : break;
399 :
400 : case 16:
401 0 : WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
402 : break;
403 :
404 : case 24:
405 0 : STORE_24 (image, dest, offset, converted);
406 : break;
407 :
408 : case 32:
409 0 : WRITE (image, ((uint32_t *)dest + offset), converted);
410 : break;
411 :
412 : default:
413 0 : *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 0 : MAKE_ACCESSORS(a8r8g8b8);
471 0 : MAKE_ACCESSORS(x8r8g8b8);
472 0 : MAKE_ACCESSORS(a8b8g8r8);
473 0 : MAKE_ACCESSORS(x8b8g8r8);
474 0 : MAKE_ACCESSORS(x14r6g6b6);
475 0 : MAKE_ACCESSORS(b8g8r8a8);
476 0 : MAKE_ACCESSORS(b8g8r8x8);
477 0 : MAKE_ACCESSORS(r8g8b8x8);
478 0 : MAKE_ACCESSORS(r8g8b8a8);
479 0 : MAKE_ACCESSORS(r8g8b8);
480 0 : MAKE_ACCESSORS(b8g8r8);
481 0 : MAKE_ACCESSORS(r5g6b5);
482 0 : MAKE_ACCESSORS(b5g6r5);
483 0 : MAKE_ACCESSORS(a1r5g5b5);
484 0 : MAKE_ACCESSORS(x1r5g5b5);
485 0 : MAKE_ACCESSORS(a1b5g5r5);
486 0 : MAKE_ACCESSORS(x1b5g5r5);
487 0 : MAKE_ACCESSORS(a4r4g4b4);
488 0 : MAKE_ACCESSORS(x4r4g4b4);
489 0 : MAKE_ACCESSORS(a4b4g4r4);
490 0 : MAKE_ACCESSORS(x4b4g4r4);
491 0 : MAKE_ACCESSORS(a8);
492 0 : MAKE_ACCESSORS(c8);
493 0 : MAKE_ACCESSORS(g8);
494 0 : MAKE_ACCESSORS(r3g3b2);
495 0 : MAKE_ACCESSORS(b2g3r3);
496 0 : MAKE_ACCESSORS(a2r2g2b2);
497 0 : MAKE_ACCESSORS(a2b2g2r2);
498 0 : MAKE_ACCESSORS(x4a4);
499 0 : MAKE_ACCESSORS(a4);
500 0 : MAKE_ACCESSORS(g4);
501 0 : MAKE_ACCESSORS(c4);
502 0 : MAKE_ACCESSORS(r1g2b1);
503 0 : MAKE_ACCESSORS(b1g2r1);
504 0 : MAKE_ACCESSORS(a1r1g1b1);
505 0 : MAKE_ACCESSORS(a1b1g1r1);
506 0 : MAKE_ACCESSORS(a1);
507 0 : 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
564 0 : to_srgb (float f)
565 : {
566 0 : uint8_t low = 0;
567 0 : uint8_t high = 255;
568 :
569 0 : while (high - low > 1)
570 : {
571 0 : uint8_t mid = (low + high) / 2;
572 :
573 0 : if (to_linear[mid] > f)
574 0 : high = mid;
575 : else
576 0 : low = mid;
577 : }
578 :
579 0 : if (to_linear[high] - f < f - to_linear[low])
580 0 : return high;
581 : else
582 0 : return low;
583 : }
584 :
585 : static void
586 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
594 0 : const uint32_t *pixel = bits + x;
595 0 : const uint32_t *end = pixel + width;
596 0 : argb_t *buffer = (argb_t *)b;
597 :
598 0 : while (pixel < end)
599 : {
600 0 : uint32_t p = READ (image, pixel++);
601 0 : argb_t *argb = buffer;
602 :
603 0 : argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
604 :
605 0 : argb->r = to_linear [(p >> 16) & 0xff];
606 0 : argb->g = to_linear [(p >> 8) & 0xff];
607 0 : argb->b = to_linear [(p >> 0) & 0xff];
608 :
609 0 : buffer++;
610 : }
611 0 : }
612 :
613 : /* Expects a float buffer */
614 : static void
615 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
623 0 : const uint32_t *pixel = bits + x;
624 0 : const uint32_t *end = pixel + width;
625 0 : argb_t *buffer = (argb_t *)b;
626 :
627 0 : while (pixel < end)
628 : {
629 0 : uint32_t p = READ (image, pixel++);
630 0 : uint64_t a = p >> 30;
631 0 : uint64_t r = (p >> 20) & 0x3ff;
632 0 : uint64_t g = (p >> 10) & 0x3ff;
633 0 : uint64_t b = p & 0x3ff;
634 :
635 0 : buffer->a = pixman_unorm_to_float (a, 2);
636 0 : buffer->r = pixman_unorm_to_float (r, 10);
637 0 : buffer->g = pixman_unorm_to_float (g, 10);
638 0 : buffer->b = pixman_unorm_to_float (b, 10);
639 :
640 0 : buffer++;
641 : }
642 0 : }
643 :
644 : /* Expects a float buffer */
645 : static void
646 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
654 0 : const uint32_t *pixel = (uint32_t *)bits + x;
655 0 : const uint32_t *end = pixel + width;
656 0 : argb_t *buffer = (argb_t *)b;
657 :
658 0 : while (pixel < end)
659 : {
660 0 : uint32_t p = READ (image, pixel++);
661 0 : uint64_t r = (p >> 20) & 0x3ff;
662 0 : uint64_t g = (p >> 10) & 0x3ff;
663 0 : uint64_t b = p & 0x3ff;
664 :
665 0 : buffer->a = 1.0;
666 0 : buffer->r = pixman_unorm_to_float (r, 10);
667 0 : buffer->g = pixman_unorm_to_float (g, 10);
668 0 : buffer->b = pixman_unorm_to_float (b, 10);
669 :
670 0 : buffer++;
671 : }
672 0 : }
673 :
674 : /* Expects a float buffer */
675 : static void
676 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
684 0 : const uint32_t *pixel = bits + x;
685 0 : const uint32_t *end = pixel + width;
686 0 : argb_t *buffer = (argb_t *)b;
687 :
688 0 : while (pixel < end)
689 : {
690 0 : uint32_t p = READ (image, pixel++);
691 0 : uint64_t a = p >> 30;
692 0 : uint64_t b = (p >> 20) & 0x3ff;
693 0 : uint64_t g = (p >> 10) & 0x3ff;
694 0 : uint64_t r = p & 0x3ff;
695 :
696 0 : buffer->a = pixman_unorm_to_float (a, 2);
697 0 : buffer->r = pixman_unorm_to_float (r, 10);
698 0 : buffer->g = pixman_unorm_to_float (g, 10);
699 0 : buffer->b = pixman_unorm_to_float (b, 10);
700 :
701 0 : buffer++;
702 : }
703 0 : }
704 :
705 : /* Expects a float buffer */
706 : static void
707 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
715 0 : const uint32_t *pixel = (uint32_t *)bits + x;
716 0 : const uint32_t *end = pixel + width;
717 0 : argb_t *buffer = (argb_t *)b;
718 :
719 0 : while (pixel < end)
720 : {
721 0 : uint32_t p = READ (image, pixel++);
722 0 : uint64_t b = (p >> 20) & 0x3ff;
723 0 : uint64_t g = (p >> 10) & 0x3ff;
724 0 : uint64_t r = p & 0x3ff;
725 :
726 0 : buffer->a = 1.0;
727 0 : buffer->r = pixman_unorm_to_float (r, 10);
728 0 : buffer->g = pixman_unorm_to_float (g, 10);
729 0 : buffer->b = pixman_unorm_to_float (b, 10);
730 :
731 0 : buffer++;
732 : }
733 0 : }
734 :
735 : static void
736 0 : 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 0 : const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
744 : int i;
745 :
746 0 : for (i = 0; i < width; i++)
747 : {
748 : int16_t y, u, v;
749 : int32_t r, g, b;
750 :
751 0 : y = ((uint8_t *) bits)[(x + i) << 1] - 16;
752 0 : u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128;
753 0 : v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128;
754 :
755 : /* R = 1.164(Y - 16) + 1.596(V - 128) */
756 0 : r = 0x012b27 * y + 0x019a2e * v;
757 : /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
758 0 : g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
759 : /* B = 1.164(Y - 16) + 2.018(U - 128) */
760 0 : b = 0x012b27 * y + 0x0206a2 * u;
761 :
762 0 : *buffer++ = 0xff000000 |
763 0 : (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
764 0 : (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
765 0 : (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
766 : }
767 0 : }
768 :
769 : static void
770 0 : 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 0 : YV12_SETUP (image);
778 0 : uint8_t *y_line = YV12_Y (line);
779 0 : uint8_t *u_line = YV12_U (line);
780 0 : uint8_t *v_line = YV12_V (line);
781 : int i;
782 :
783 0 : for (i = 0; i < width; i++)
784 : {
785 : int16_t y, u, v;
786 : int32_t r, g, b;
787 :
788 0 : y = y_line[x + i] - 16;
789 0 : u = u_line[(x + i) >> 1] - 128;
790 0 : v = v_line[(x + i) >> 1] - 128;
791 :
792 : /* R = 1.164(Y - 16) + 1.596(V - 128) */
793 0 : r = 0x012b27 * y + 0x019a2e * v;
794 : /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
795 0 : g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
796 : /* B = 1.164(Y - 16) + 2.018(U - 128) */
797 0 : b = 0x012b27 * y + 0x0206a2 * u;
798 :
799 0 : *buffer++ = 0xff000000 |
800 0 : (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
801 0 : (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
802 0 : (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
803 : }
804 0 : }
805 :
806 : /**************************** Pixel wise fetching *****************************/
807 :
808 : static argb_t
809 0 : fetch_pixel_x2r10g10b10_float (bits_image_t *image,
810 : int offset,
811 : int line)
812 : {
813 0 : uint32_t *bits = image->bits + line * image->rowstride;
814 0 : uint32_t p = READ (image, bits + offset);
815 0 : uint64_t r = (p >> 20) & 0x3ff;
816 0 : uint64_t g = (p >> 10) & 0x3ff;
817 0 : uint64_t b = p & 0x3ff;
818 : argb_t argb;
819 :
820 0 : argb.a = 1.0;
821 0 : argb.r = pixman_unorm_to_float (r, 10);
822 0 : argb.g = pixman_unorm_to_float (g, 10);
823 0 : argb.b = pixman_unorm_to_float (b, 10);
824 :
825 0 : return argb;
826 : }
827 :
828 : static argb_t
829 0 : fetch_pixel_a2r10g10b10_float (bits_image_t *image,
830 : int offset,
831 : int line)
832 : {
833 0 : uint32_t *bits = image->bits + line * image->rowstride;
834 0 : uint32_t p = READ (image, bits + offset);
835 0 : uint64_t a = p >> 30;
836 0 : uint64_t r = (p >> 20) & 0x3ff;
837 0 : uint64_t g = (p >> 10) & 0x3ff;
838 0 : uint64_t b = p & 0x3ff;
839 : argb_t argb;
840 :
841 0 : argb.a = pixman_unorm_to_float (a, 2);
842 0 : argb.r = pixman_unorm_to_float (r, 10);
843 0 : argb.g = pixman_unorm_to_float (g, 10);
844 0 : argb.b = pixman_unorm_to_float (b, 10);
845 :
846 0 : return argb;
847 : }
848 :
849 : static argb_t
850 0 : fetch_pixel_a2b10g10r10_float (bits_image_t *image,
851 : int offset,
852 : int line)
853 : {
854 0 : uint32_t *bits = image->bits + line * image->rowstride;
855 0 : uint32_t p = READ (image, bits + offset);
856 0 : uint64_t a = p >> 30;
857 0 : uint64_t b = (p >> 20) & 0x3ff;
858 0 : uint64_t g = (p >> 10) & 0x3ff;
859 0 : uint64_t r = p & 0x3ff;
860 : argb_t argb;
861 :
862 0 : argb.a = pixman_unorm_to_float (a, 2);
863 0 : argb.r = pixman_unorm_to_float (r, 10);
864 0 : argb.g = pixman_unorm_to_float (g, 10);
865 0 : argb.b = pixman_unorm_to_float (b, 10);
866 :
867 0 : return argb;
868 : }
869 :
870 : static argb_t
871 0 : fetch_pixel_x2b10g10r10_float (bits_image_t *image,
872 : int offset,
873 : int line)
874 : {
875 0 : uint32_t *bits = image->bits + line * image->rowstride;
876 0 : uint32_t p = READ (image, bits + offset);
877 0 : uint64_t b = (p >> 20) & 0x3ff;
878 0 : uint64_t g = (p >> 10) & 0x3ff;
879 0 : uint64_t r = p & 0x3ff;
880 : argb_t argb;
881 :
882 0 : argb.a = 1.0;
883 0 : argb.r = pixman_unorm_to_float (r, 10);
884 0 : argb.g = pixman_unorm_to_float (g, 10);
885 0 : argb.b = pixman_unorm_to_float (b, 10);
886 :
887 0 : return argb;
888 : }
889 :
890 : static argb_t
891 0 : fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
892 : int offset,
893 : int line)
894 : {
895 0 : uint32_t *bits = image->bits + line * image->rowstride;
896 0 : uint32_t p = READ (image, bits + offset);
897 : argb_t argb;
898 :
899 0 : argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
900 :
901 0 : argb.r = to_linear [(p >> 16) & 0xff];
902 0 : argb.g = to_linear [(p >> 8) & 0xff];
903 0 : argb.b = to_linear [(p >> 0) & 0xff];
904 :
905 0 : return argb;
906 : }
907 :
908 : static uint32_t
909 0 : fetch_pixel_yuy2 (bits_image_t *image,
910 : int offset,
911 : int line)
912 : {
913 0 : const uint32_t *bits = image->bits + image->rowstride * line;
914 :
915 : int16_t y, u, v;
916 : int32_t r, g, b;
917 :
918 0 : y = ((uint8_t *) bits)[offset << 1] - 16;
919 0 : u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128;
920 0 : v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128;
921 :
922 : /* R = 1.164(Y - 16) + 1.596(V - 128) */
923 0 : r = 0x012b27 * y + 0x019a2e * v;
924 :
925 : /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
926 0 : g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
927 :
928 : /* B = 1.164(Y - 16) + 2.018(U - 128) */
929 0 : b = 0x012b27 * y + 0x0206a2 * u;
930 :
931 0 : return 0xff000000 |
932 0 : (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
933 0 : (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
934 0 : (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
935 : }
936 :
937 : static uint32_t
938 0 : fetch_pixel_yv12 (bits_image_t *image,
939 : int offset,
940 : int line)
941 : {
942 0 : YV12_SETUP (image);
943 0 : int16_t y = YV12_Y (line)[offset] - 16;
944 0 : int16_t u = YV12_U (line)[offset >> 1] - 128;
945 0 : 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 0 : r = 0x012b27 * y + 0x019a2e * v;
950 :
951 : /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
952 0 : g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
953 :
954 : /* B = 1.164(Y - 16) + 2.018(U - 128) */
955 0 : b = 0x012b27 * y + 0x0206a2 * u;
956 :
957 0 : return 0xff000000 |
958 0 : (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) |
959 0 : (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) |
960 0 : (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0);
961 : }
962 :
963 : /*********************************** Store ************************************/
964 :
965 : static void
966 0 : store_scanline_a2r10g10b10_float (bits_image_t * image,
967 : int x,
968 : int y,
969 : int width,
970 : const uint32_t *v)
971 : {
972 0 : uint32_t *bits = image->bits + image->rowstride * y;
973 0 : uint32_t *pixel = bits + x;
974 0 : argb_t *values = (argb_t *)v;
975 : int i;
976 :
977 0 : for (i = 0; i < width; ++i)
978 : {
979 : uint16_t a, r, g, b;
980 :
981 0 : a = pixman_float_to_unorm (values[i].a, 2);
982 0 : r = pixman_float_to_unorm (values[i].r, 10);
983 0 : g = pixman_float_to_unorm (values[i].g, 10);
984 0 : b = pixman_float_to_unorm (values[i].b, 10);
985 :
986 0 : WRITE (image, pixel++,
987 : (a << 30) | (r << 20) | (g << 10) | b);
988 : }
989 0 : }
990 :
991 : static void
992 0 : store_scanline_x2r10g10b10_float (bits_image_t * image,
993 : int x,
994 : int y,
995 : int width,
996 : const uint32_t *v)
997 : {
998 0 : uint32_t *bits = image->bits + image->rowstride * y;
999 0 : uint32_t *pixel = bits + x;
1000 0 : argb_t *values = (argb_t *)v;
1001 : int i;
1002 :
1003 0 : for (i = 0; i < width; ++i)
1004 : {
1005 : uint16_t r, g, b;
1006 :
1007 0 : r = pixman_float_to_unorm (values[i].r, 10);
1008 0 : g = pixman_float_to_unorm (values[i].g, 10);
1009 0 : b = pixman_float_to_unorm (values[i].b, 10);
1010 :
1011 0 : WRITE (image, pixel++,
1012 : (r << 20) | (g << 10) | b);
1013 : }
1014 0 : }
1015 :
1016 : static void
1017 0 : store_scanline_a2b10g10r10_float (bits_image_t * image,
1018 : int x,
1019 : int y,
1020 : int width,
1021 : const uint32_t *v)
1022 : {
1023 0 : uint32_t *bits = image->bits + image->rowstride * y;
1024 0 : uint32_t *pixel = bits + x;
1025 0 : argb_t *values = (argb_t *)v;
1026 : int i;
1027 :
1028 0 : for (i = 0; i < width; ++i)
1029 : {
1030 : uint16_t a, r, g, b;
1031 :
1032 0 : a = pixman_float_to_unorm (values[i].a, 2);
1033 0 : r = pixman_float_to_unorm (values[i].r, 10);
1034 0 : g = pixman_float_to_unorm (values[i].g, 10);
1035 0 : b = pixman_float_to_unorm (values[i].b, 10);
1036 :
1037 0 : WRITE (image, pixel++,
1038 : (a << 30) | (b << 20) | (g << 10) | r);
1039 : }
1040 0 : }
1041 :
1042 : static void
1043 0 : store_scanline_x2b10g10r10_float (bits_image_t * image,
1044 : int x,
1045 : int y,
1046 : int width,
1047 : const uint32_t *v)
1048 : {
1049 0 : uint32_t *bits = image->bits + image->rowstride * y;
1050 0 : uint32_t *pixel = bits + x;
1051 0 : argb_t *values = (argb_t *)v;
1052 : int i;
1053 :
1054 0 : for (i = 0; i < width; ++i)
1055 : {
1056 : uint16_t r, g, b;
1057 :
1058 0 : r = pixman_float_to_unorm (values[i].r, 10);
1059 0 : g = pixman_float_to_unorm (values[i].g, 10);
1060 0 : b = pixman_float_to_unorm (values[i].b, 10);
1061 :
1062 0 : WRITE (image, pixel++,
1063 : (b << 20) | (g << 10) | r);
1064 : }
1065 0 : }
1066 :
1067 : static void
1068 0 : 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 0 : uint32_t *bits = image->bits + image->rowstride * y;
1075 0 : uint32_t *pixel = bits + x;
1076 0 : argb_t *values = (argb_t *)v;
1077 : int i;
1078 :
1079 0 : for (i = 0; i < width; ++i)
1080 : {
1081 : uint8_t a, r, g, b;
1082 :
1083 0 : a = pixman_float_to_unorm (values[i].a, 8);
1084 0 : r = to_srgb (values[i].r);
1085 0 : g = to_srgb (values[i].g);
1086 0 : b = to_srgb (values[i].b);
1087 :
1088 0 : WRITE (image, pixel++,
1089 : (a << 24) | (r << 16) | (g << 8) | b);
1090 : }
1091 0 : }
1092 :
1093 : static void
1094 0 : store_scanline_16 (bits_image_t * image,
1095 : int x,
1096 : int y,
1097 : int width,
1098 : const uint32_t *v)
1099 : {
1100 0 : uint16_t *bits = (uint16_t*)(image->bits + image->rowstride * y);
1101 0 : uint16_t *values = (uint16_t *)v;
1102 0 : uint16_t *pixel = bits + x;
1103 : int i;
1104 :
1105 0 : for (i = 0; i < width; ++i)
1106 : {
1107 0 : WRITE (image, pixel++, values[i]);
1108 : }
1109 0 : }
1110 :
1111 : static void
1112 0 : 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 0 : const uint16_t *bits = (uint16_t*)(image->bits.bits + y * image->bits.rowstride);
1120 0 : const uint16_t *pixel = bits + x;
1121 : int i;
1122 0 : uint16_t *buffer = (uint16_t *)b;
1123 :
1124 0 : for (i = 0; i < width; ++i)
1125 : {
1126 0 : *buffer++ = READ (image, pixel++);
1127 : }
1128 0 : }
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
1137 0 : 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 0 : assert (image->common.type == BITS);
1146 :
1147 0 : argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1148 0 : if (!argb8_pixels)
1149 0 : return;
1150 :
1151 : /* Contract the scanline. We could do this in place if values weren't
1152 : * const.
1153 : */
1154 0 : pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1155 :
1156 0 : image->store_scanline_32 (image, x, y, width, argb8_pixels);
1157 :
1158 0 : free (argb8_pixels);
1159 : }
1160 :
1161 : static void
1162 0 : 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 0 : image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
1170 :
1171 0 : pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
1172 0 : }
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
1178 0 : 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 0 : const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
1186 0 : const uint32_t *pixel = (uint32_t *)bits + x;
1187 0 : const uint32_t *end = pixel + width;
1188 : uint32_t tmp;
1189 :
1190 0 : while (pixel < end)
1191 : {
1192 : uint8_t a, r, g, b;
1193 :
1194 0 : tmp = READ (image, pixel++);
1195 :
1196 0 : a = (tmp >> 24) & 0xff;
1197 0 : r = (tmp >> 16) & 0xff;
1198 0 : g = (tmp >> 8) & 0xff;
1199 0 : b = (tmp >> 0) & 0xff;
1200 :
1201 0 : r = to_linear[r] * 255.0f + 0.5f;
1202 0 : g = to_linear[g] * 255.0f + 0.5f;
1203 0 : b = to_linear[b] * 255.0f + 0.5f;
1204 :
1205 0 : *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1206 : }
1207 0 : }
1208 :
1209 : static uint32_t
1210 0 : fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1211 : int offset,
1212 : int line)
1213 : {
1214 0 : uint32_t *bits = image->bits + line * image->rowstride;
1215 0 : uint32_t tmp = READ (image, bits + offset);
1216 : uint8_t a, r, g, b;
1217 :
1218 0 : a = (tmp >> 24) & 0xff;
1219 0 : r = (tmp >> 16) & 0xff;
1220 0 : g = (tmp >> 8) & 0xff;
1221 0 : b = (tmp >> 0) & 0xff;
1222 :
1223 0 : r = to_linear[r] * 255.0f + 0.5f;
1224 0 : g = to_linear[g] * 255.0f + 0.5f;
1225 0 : b = to_linear[b] * 255.0f + 0.5f;
1226 :
1227 0 : return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1228 : }
1229 :
1230 : static void
1231 0 : 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 0 : uint32_t *bits = image->bits + image->rowstride * y;
1238 0 : uint64_t *values = (uint64_t *)v;
1239 0 : uint32_t *pixel = bits + x;
1240 : uint64_t tmp;
1241 : int i;
1242 :
1243 0 : for (i = 0; i < width; ++i)
1244 : {
1245 : uint8_t a, r, g, b;
1246 :
1247 0 : tmp = values[i];
1248 :
1249 0 : a = (tmp >> 24) & 0xff;
1250 0 : r = (tmp >> 16) & 0xff;
1251 0 : g = (tmp >> 8) & 0xff;
1252 0 : b = (tmp >> 0) & 0xff;
1253 :
1254 0 : r = to_srgb (r * (1/255.0f));
1255 0 : g = to_srgb (g * (1/255.0f));
1256 0 : b = to_srgb (b * (1/255.0f));
1257 :
1258 0 : WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1259 : }
1260 0 : }
1261 :
1262 : static argb_t
1263 0 : fetch_pixel_generic_float (bits_image_t *image,
1264 : int offset,
1265 : int line)
1266 : {
1267 0 : uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
1268 : argb_t f;
1269 :
1270 0 : pixman_expand_to_float (&f, &pixel32, image->format, 1);
1271 :
1272 0 : 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
1282 0 : fetch_pixel_generic_lossy_32 (bits_image_t *image,
1283 : int offset,
1284 : int line)
1285 : {
1286 0 : argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1287 : uint32_t result;
1288 :
1289 0 : pixman_contract_from_float (&result, &pixel64, 1);
1290 :
1291 0 : 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
1447 44 : setup_accessors (bits_image_t *image)
1448 : {
1449 44 : const format_info_t *info = accessors;
1450 :
1451 88 : while (info->format != PIXMAN_null)
1452 : {
1453 44 : if (info->format == image->format)
1454 : {
1455 44 : image->fetch_scanline_16 = info->fetch_scanline_16;
1456 44 : image->fetch_scanline_32 = info->fetch_scanline_32;
1457 44 : image->fetch_scanline_float = info->fetch_scanline_float;
1458 44 : image->fetch_pixel_32 = info->fetch_pixel_32;
1459 44 : image->fetch_pixel_float = info->fetch_pixel_float;
1460 44 : image->store_scanline_16 = info->store_scanline_16;
1461 44 : image->store_scanline_32 = info->store_scanline_32;
1462 44 : image->store_scanline_float = info->store_scanline_float;
1463 :
1464 44 : return;
1465 : }
1466 :
1467 0 : 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
1476 44 : _pixman_bits_image_setup_accessors (bits_image_t *image)
1477 : {
1478 44 : if (image->read_func || image->write_func)
1479 0 : _pixman_bits_image_setup_accessors_accessors (image);
1480 : else
1481 44 : setup_accessors (image);
1482 44 : }
1483 :
1484 : #else
1485 :
1486 : void
1487 0 : _pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1488 : {
1489 0 : setup_accessors (image);
1490 0 : }
1491 :
1492 : #endif
|