Subversion Repositories Kolibri OS

Rev

Rev 1891 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1891 serge 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 
29
#endif
30
 
31
#include 
32
#include 
33
#include 
3931 Serge 34
#include 
1891 serge 35
 
3931 Serge 36
#include "pixman-accessor.h"
1891 serge 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
 
3931 Serge 49
/* Fetch macros */
1891 serge 50
 
3931 Serge 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
1891 serge 58
 
3931 Serge 59
#define FETCH_8(img,l,o)    (READ (img, (((uint8_t *)(l)) + ((o) >> 3))))
1891 serge 60
 
3931 Serge 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
 
1891 serge 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
 
3931 Serge 195
/* Misc. helpers */
1891 serge 196
 
3931 Serge 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)
1891 serge 203
{
3931 Serge 204
    switch (PIXMAN_FORMAT_TYPE (format))
1891 serge 205
    {
3931 Serge 206
    case PIXMAN_TYPE_A:
207
	*b = 0;
208
	*g = 0;
209
	*r = 0;
210
	*a = 0;
211
	break;
1891 serge 212
 
3931 Serge 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;
1891 serge 220
 
3931 Serge 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;
1891 serge 227
 
3931 Serge 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;
1891 serge 235
 
3931 Serge 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;
1891 serge 243
 
3931 Serge 244
    default:
245
	assert (0);
246
	break;
1891 serge 247
    }
248
}
249
 
3931 Serge 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)
1891 serge 254
{
3931 Serge 255
    uint32_t v;
1891 serge 256
 
3931 Serge 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;
1891 serge 263
 
3931 Serge 264
    return (v & ((1 << n_to_bits) - 1)) << to_shift;
1891 serge 265
}
266
 
3931 Serge 267
static force_inline uint32_t
268
convert_pixel (pixman_format_code_t from, pixman_format_code_t to, uint32_t pixel)
1891 serge 269
{
3931 Serge 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;
1891 serge 273
 
3931 Serge 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);
1891 serge 276
 
3931 Serge 277
    a = convert_channel (pixel, ~0,
278
			 PIXMAN_FORMAT_A (from), a_from_shift,
279
			 PIXMAN_FORMAT_A (to), a_to_shift);
1891 serge 280
 
3931 Serge 281
    r = convert_channel (pixel, 0,
282
			 PIXMAN_FORMAT_R (from), r_from_shift,
283
			 PIXMAN_FORMAT_R (to), r_to_shift);
1891 serge 284
 
3931 Serge 285
    g = convert_channel (pixel, 0,
286
			 PIXMAN_FORMAT_G (from), g_from_shift,
287
			 PIXMAN_FORMAT_G (to), g_to_shift);
1891 serge 288
 
3931 Serge 289
    b = convert_channel (pixel, 0,
290
			 PIXMAN_FORMAT_B (from), b_from_shift,
291
			 PIXMAN_FORMAT_B (to), b_to_shift);
1891 serge 292
 
3931 Serge 293
    return a | r | g | b;
1891 serge 294
}
295
 
3931 Serge 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)
1891 serge 300
{
3931 Serge 301
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY		||
302
	PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
1891 serge 303
    {
3931 Serge 304
	return image->bits.indexed->rgba[pixel];
1891 serge 305
    }
3931 Serge 306
    else
1891 serge 307
    {
3931 Serge 308
	return convert_pixel (format, PIXMAN_a8r8g8b8, pixel);
1891 serge 309
    }
310
}
311
 
3931 Serge 312
static force_inline uint32_t
313
convert_pixel_from_a8r8g8b8 (pixman_image_t *image,
314
			     pixman_format_code_t format, uint32_t pixel)
1891 serge 315
{
3931 Serge 316
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
1891 serge 317
    {
3931 Serge 318
	pixel = CONVERT_RGB24_TO_Y15 (pixel);
1891 serge 319
 
3931 Serge 320
	return image->bits.indexed->ent[pixel & 0x7fff];
1891 serge 321
    }
3931 Serge 322
    else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
1891 serge 323
    {
3931 Serge 324
	pixel = convert_pixel (PIXMAN_a8r8g8b8, PIXMAN_x1r5g5b5, pixel);
1891 serge 325
 
3931 Serge 326
	return image->bits.indexed->ent[pixel & 0x7fff];
1891 serge 327
    }
3931 Serge 328
    else
1891 serge 329
    {
3931 Serge 330
	return convert_pixel (PIXMAN_a8r8g8b8, format, pixel);
1891 serge 331
    }
332
}
333
 
3931 Serge 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)
1891 serge 339
{
3931 Serge 340
    uint32_t pixel;
1891 serge 341
 
3931 Serge 342
    switch (PIXMAN_FORMAT_BPP (format))
1891 serge 343
    {
3931 Serge 344
    case 1:
345
	pixel = FETCH_1 (image, bits, offset);
346
	break;
1891 serge 347
 
3931 Serge 348
    case 4:
349
	pixel = FETCH_4 (image, bits, offset);
350
	break;
1891 serge 351
 
3931 Serge 352
    case 8:
353
	pixel = READ (image, bits + offset);
354
	break;
1891 serge 355
 
3931 Serge 356
    case 16:
357
	pixel = READ (image, ((uint16_t *)bits + offset));
358
	break;
1891 serge 359
 
3931 Serge 360
    case 24:
361
	pixel = FETCH_24 (image, bits, offset);
362
	break;
1891 serge 363
 
3931 Serge 364
    case 32:
365
	pixel = READ (image, ((uint32_t *)bits + offset));
366
	break;
1891 serge 367
 
3931 Serge 368
    default:
369
	pixel = 0xffff00ff; /* As ugly as possible to detect the bug */
370
	break;
1891 serge 371
    }
3931 Serge 372
 
373
    return convert_pixel_to_a8r8g8b8 (image, format, pixel);
1891 serge 374
}
375
 
3931 Serge 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)
1891 serge 382
{
3931 Serge 383
    uint32_t converted = convert_pixel_from_a8r8g8b8 (
384
	(pixman_image_t *)image, format, pixel);
1891 serge 385
 
3931 Serge 386
    switch (PIXMAN_FORMAT_BPP (format))
1891 serge 387
    {
3931 Serge 388
    case 1:
389
	STORE_1 (image, dest, offset, converted & 0x01);
390
	break;
1891 serge 391
 
3931 Serge 392
    case 4:
393
	STORE_4 (image, dest, offset, converted & 0xf);
394
	break;
1891 serge 395
 
3931 Serge 396
    case 8:
397
	WRITE (image, (dest + offset), converted & 0xff);
398
	break;
1891 serge 399
 
3931 Serge 400
    case 16:
401
	WRITE (image, ((uint16_t *)dest + offset), converted & 0xffff);
402
	break;
1891 serge 403
 
3931 Serge 404
    case 24:
405
	STORE_24 (image, dest, offset, converted);
406
	break;
1891 serge 407
 
3931 Serge 408
    case 32:
409
	WRITE (image, ((uint32_t *)dest + offset), converted);
410
	break;
411
 
412
    default:
413
	*dest = 0x0;
414
	break;
1891 serge 415
    }
416
}
417
 
3931 Serge 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] =
1891 serge 515
{
3931 Serge 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
};
1891 serge 560
 
3931 Serge 561
static const float * const to_linear = (const float *)to_linear_u;
562
 
563
static uint8_t
564
to_srgb (float f)
1891 serge 565
{
3931 Serge 566
    uint8_t low = 0;
567
    uint8_t high = 255;
1891 serge 568
 
3931 Serge 569
    while (high - low > 1)
1891 serge 570
    {
3931 Serge 571
	uint8_t mid = (low + high) / 2;
1891 serge 572
 
3931 Serge 573
	if (to_linear[mid] > f)
574
	    high = mid;
575
	else
576
	    low = mid;
1891 serge 577
    }
3931 Serge 578
 
579
    if (to_linear[high] - f < f - to_linear[low])
580
	return high;
581
    else
582
	return low;
1891 serge 583
}
584
 
585
static void
3931 Serge 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)
1891 serge 592
{
593
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
3931 Serge 594
    const uint32_t *pixel = bits + x;
595
    const uint32_t *end = pixel + width;
596
    argb_t *buffer = (argb_t *)b;
1891 serge 597
 
3931 Serge 598
    while (pixel < end)
1891 serge 599
    {
3931 Serge 600
	uint32_t p = READ (image, pixel++);
601
	argb_t *argb = buffer;
1891 serge 602
 
3931 Serge 603
	argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
1891 serge 604
 
3931 Serge 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++;
1891 serge 610
    }
611
}
612
 
3931 Serge 613
/* Expects a float buffer */
1891 serge 614
static void
3931 Serge 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)
1891 serge 621
{
622
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
3931 Serge 623
    const uint32_t *pixel = bits + x;
624
    const uint32_t *end = pixel + width;
625
    argb_t *buffer = (argb_t *)b;
1891 serge 626
 
3931 Serge 627
    while (pixel < end)
1891 serge 628
    {
3931 Serge 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;
1891 serge 634
 
3931 Serge 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++;
1891 serge 641
    }
642
}
643
 
3931 Serge 644
/* Expects a float buffer */
1891 serge 645
static void
3931 Serge 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)
1891 serge 652
{
653
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
3931 Serge 654
    const uint32_t *pixel = (uint32_t *)bits + x;
655
    const uint32_t *end = pixel + width;
656
    argb_t *buffer = (argb_t *)b;
1891 serge 657
 
3931 Serge 658
    while (pixel < end)
1891 serge 659
    {
3931 Serge 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;
1891 serge 664
 
3931 Serge 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);
1891 serge 669
 
3931 Serge 670
	buffer++;
1891 serge 671
    }
672
}
673
 
3931 Serge 674
/* Expects a float buffer */
1891 serge 675
static void
3931 Serge 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)
1891 serge 682
{
683
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
3931 Serge 684
    const uint32_t *pixel = bits + x;
685
    const uint32_t *end = pixel + width;
686
    argb_t *buffer = (argb_t *)b;
1891 serge 687
 
3931 Serge 688
    while (pixel < end)
1891 serge 689
    {
3931 Serge 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;
1891 serge 695
 
3931 Serge 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);
1891 serge 700
 
3931 Serge 701
	buffer++;
1891 serge 702
    }
703
}
704
 
3931 Serge 705
/* Expects a float buffer */
1891 serge 706
static void
3931 Serge 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)
1891 serge 713
{
714
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
3931 Serge 715
    const uint32_t *pixel = (uint32_t *)bits + x;
716
    const uint32_t *end = pixel + width;
717
    argb_t *buffer = (argb_t *)b;
1891 serge 718
 
3931 Serge 719
    while (pixel < end)
1891 serge 720
    {
3931 Serge 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;
1891 serge 725
 
3931 Serge 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++;
1891 serge 732
    }
733
}
734
 
735
static void
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
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
 
3931 Serge 808
static argb_t
809
fetch_pixel_x2r10g10b10_float (bits_image_t *image,
810
			       int	   offset,
811
			       int           line)
1891 serge 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;
3931 Serge 818
    argb_t argb;
1891 serge 819
 
3931 Serge 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);
1891 serge 824
 
3931 Serge 825
    return argb;
1891 serge 826
}
827
 
3931 Serge 828
static argb_t
829
fetch_pixel_a2r10g10b10_float (bits_image_t *image,
830
			       int	     offset,
831
			       int           line)
1891 serge 832
{
833
    uint32_t *bits = image->bits + line * image->rowstride;
834
    uint32_t p = READ (image, bits + offset);
3931 Serge 835
    uint64_t a = p >> 30;
1891 serge 836
    uint64_t r = (p >> 20) & 0x3ff;
837
    uint64_t g = (p >> 10) & 0x3ff;
838
    uint64_t b = p & 0x3ff;
3931 Serge 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;
1891 serge 847
}
848
 
3931 Serge 849
static argb_t
850
fetch_pixel_a2b10g10r10_float (bits_image_t *image,
851
			       int           offset,
852
			       int           line)
1891 serge 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;
3931 Serge 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;
1891 serge 868
}
869
 
3931 Serge 870
static argb_t
871
fetch_pixel_x2b10g10r10_float (bits_image_t *image,
872
			       int           offset,
873
			       int           line)
1891 serge 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;
3931 Serge 880
    argb_t argb;
1891 serge 881
 
3931 Serge 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);
1891 serge 886
 
3931 Serge 887
    return argb;
1891 serge 888
}
889
 
3931 Serge 890
static argb_t
891
fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image,
892
				 int	       offset,
893
				 int           line)
1891 serge 894
{
895
    uint32_t *bits = image->bits + line * image->rowstride;
3931 Serge 896
    uint32_t p = READ (image, bits + offset);
897
    argb_t argb;
1891 serge 898
 
3931 Serge 899
    argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8);
1891 serge 900
 
3931 Serge 901
    argb.r = to_linear [(p >> 16) & 0xff];
902
    argb.g = to_linear [(p >>  8) & 0xff];
903
    argb.b = to_linear [(p >>  0) & 0xff];
1891 serge 904
 
3931 Serge 905
    return argb;
1891 serge 906
}
907
 
908
static uint32_t
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
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
3931 Serge 966
store_scanline_a2r10g10b10_float (bits_image_t *  image,
967
				  int             x,
968
				  int             y,
969
				  int             width,
970
				  const uint32_t *v)
1891 serge 971
{
972
    uint32_t *bits = image->bits + image->rowstride * y;
973
    uint32_t *pixel = bits + x;
3931 Serge 974
    argb_t *values = (argb_t *)v;
1891 serge 975
    int i;
976
 
977
    for (i = 0; i < width; ++i)
978
    {
3931 Serge 979
	uint16_t a, r, g, b;
1891 serge 980
 
3931 Serge 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
 
1891 serge 986
	WRITE (image, pixel++,
3931 Serge 987
	       (a << 30) | (r << 20) | (g << 10) | b);
1891 serge 988
    }
989
}
990
 
991
static void
3931 Serge 992
store_scanline_x2r10g10b10_float (bits_image_t *  image,
993
				  int             x,
994
				  int             y,
995
				  int             width,
996
				  const uint32_t *v)
1891 serge 997
{
998
    uint32_t *bits = image->bits + image->rowstride * y;
999
    uint32_t *pixel = bits + x;
3931 Serge 1000
    argb_t *values = (argb_t *)v;
1891 serge 1001
    int i;
1002
 
1003
    for (i = 0; i < width; ++i)
1004
    {
3931 Serge 1005
	uint16_t r, g, b;
1891 serge 1006
 
3931 Serge 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);
1891 serge 1010
 
1011
	WRITE (image, pixel++,
3931 Serge 1012
	       (r << 20) | (g << 10) | b);
1891 serge 1013
    }
1014
}
1015
 
1016
static void
3931 Serge 1017
store_scanline_a2b10g10r10_float (bits_image_t *  image,
1018
				  int             x,
1019
				  int             y,
1020
				  int             width,
1021
				  const uint32_t *v)
1891 serge 1022
{
1023
    uint32_t *bits = image->bits + image->rowstride * y;
3931 Serge 1024
    uint32_t *pixel = bits + x;
1025
    argb_t *values = (argb_t *)v;
1891 serge 1026
    int i;
1027
 
1028
    for (i = 0; i < width; ++i)
1029
    {
3931 Serge 1030
	uint16_t a, r, g, b;
1891 serge 1031
 
3931 Serge 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);
1891 serge 1036
 
3931 Serge 1037
	WRITE (image, pixel++,
1038
	       (a << 30) | (b << 20) | (g << 10) | r);
1891 serge 1039
    }
1040
}
1041
 
1042
static void
3931 Serge 1043
store_scanline_x2b10g10r10_float (bits_image_t *  image,
1044
				  int             x,
1045
				  int             y,
1046
				  int             width,
1047
				  const uint32_t *v)
1891 serge 1048
{
1049
    uint32_t *bits = image->bits + image->rowstride * y;
3931 Serge 1050
    uint32_t *pixel = bits + x;
1051
    argb_t *values = (argb_t *)v;
1891 serge 1052
    int i;
1053
 
1054
    for (i = 0; i < width; ++i)
1055
    {
3931 Serge 1056
	uint16_t r, g, b;
1891 serge 1057
 
3931 Serge 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);
1891 serge 1061
 
1062
	WRITE (image, pixel++,
3931 Serge 1063
	       (b << 20) | (g << 10) | r);
1891 serge 1064
    }
1065
}
1066
 
1067
static void
3931 Serge 1068
store_scanline_a8r8g8b8_sRGB_float (bits_image_t *  image,
1069
				    int             x,
1070
				    int             y,
1071
				    int             width,
1072
				    const uint32_t *v)
1891 serge 1073
{
1074
    uint32_t *bits = image->bits + image->rowstride * y;
3931 Serge 1075
    uint32_t *pixel = bits + x;
1076
    argb_t *values = (argb_t *)v;
1891 serge 1077
    int i;
1078
 
1079
    for (i = 0; i < width; ++i)
1080
    {
3931 Serge 1081
	uint8_t a, r, g, b;
1891 serge 1082
 
3931 Serge 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);
1891 serge 1087
 
1088
	WRITE (image, pixel++,
3931 Serge 1089
	       (a << 24) | (r << 16) | (g << 8) | b);
1891 serge 1090
    }
1091
}
1092
 
3931 Serge 1093
/*
1094
 * Contracts a floating point image to 32bpp and then stores it using a
1095
 * regular 32-bit store proc. Despite the type, this function expects an
1096
 * argb_t buffer.
1097
 */
1891 serge 1098
static void
3931 Serge 1099
store_scanline_generic_float (bits_image_t *  image,
1100
			      int             x,
1101
			      int             y,
1102
			      int             width,
1103
			      const uint32_t *values)
1891 serge 1104
{
3931 Serge 1105
    uint32_t *argb8_pixels;
1891 serge 1106
 
3931 Serge 1107
    assert (image->common.type == BITS);
1891 serge 1108
 
3931 Serge 1109
    argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t));
1110
    if (!argb8_pixels)
1111
	return;
1891 serge 1112
 
3931 Serge 1113
    /* Contract the scanline.  We could do this in place if values weren't
1114
     * const.
1115
     */
1116
    pixman_contract_from_float (argb8_pixels, (argb_t *)values, width);
1891 serge 1117
 
3931 Serge 1118
    image->store_scanline_32 (image, x, y, width, argb8_pixels);
1891 serge 1119
 
3931 Serge 1120
    free (argb8_pixels);
1891 serge 1121
}
1122
 
1123
static void
3931 Serge 1124
fetch_scanline_generic_float (pixman_image_t *image,
1125
			      int	      x,
1126
			      int	      y,
1127
			      int	      width,
1128
			      uint32_t *      buffer,
1129
			      const uint32_t *mask)
1891 serge 1130
{
3931 Serge 1131
    image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
1891 serge 1132
 
3931 Serge 1133
    pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width);
1891 serge 1134
}
1135
 
3931 Serge 1136
/* The 32_sRGB paths should be deleted after narrow processing
1137
 * is no longer invoked for formats that are considered wide.
1138
 * (Also see fetch_pixel_generic_lossy_32) */
1891 serge 1139
static void
3931 Serge 1140
fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image,
1141
                                 int             x,
1142
                                 int             y,
1143
                                 int             width,
1144
                                 uint32_t       *buffer,
1145
                                 const uint32_t *mask)
1891 serge 1146
{
3931 Serge 1147
    const uint32_t *bits = image->bits.bits + y * image->bits.rowstride;
1148
    const uint32_t *pixel = (uint32_t *)bits + x;
1149
    const uint32_t *end = pixel + width;
1150
    uint32_t tmp;
1891 serge 1151
 
3931 Serge 1152
    while (pixel < end)
1891 serge 1153
    {
3931 Serge 1154
	uint8_t a, r, g, b;
1891 serge 1155
 
3931 Serge 1156
	tmp = READ (image, pixel++);
1891 serge 1157
 
3931 Serge 1158
	a = (tmp >> 24) & 0xff;
1159
	r = (tmp >> 16) & 0xff;
1160
	g = (tmp >> 8) & 0xff;
1161
	b = (tmp >> 0) & 0xff;
1891 serge 1162
 
3931 Serge 1163
	r = to_linear[r] * 255.0f + 0.5f;
1164
	g = to_linear[g] * 255.0f + 0.5f;
1165
	b = to_linear[b] * 255.0f + 0.5f;
1891 serge 1166
 
3931 Serge 1167
	*buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0);
1891 serge 1168
    }
1169
}
1170
 
3931 Serge 1171
static uint32_t
1172
fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image,
1173
			      int           offset,
1174
			      int           line)
1891 serge 1175
{
3931 Serge 1176
    uint32_t *bits = image->bits + line * image->rowstride;
1177
    uint32_t tmp = READ (image, bits + offset);
1178
    uint8_t a, r, g, b;
1891 serge 1179
 
3931 Serge 1180
    a = (tmp >> 24) & 0xff;
1181
    r = (tmp >> 16) & 0xff;
1182
    g = (tmp >> 8) & 0xff;
1183
    b = (tmp >> 0) & 0xff;
1891 serge 1184
 
3931 Serge 1185
    r = to_linear[r] * 255.0f + 0.5f;
1186
    g = to_linear[g] * 255.0f + 0.5f;
1187
    b = to_linear[b] * 255.0f + 0.5f;
1891 serge 1188
 
3931 Serge 1189
    return (a << 24) | (r << 16) | (g << 8) | (b << 0);
1891 serge 1190
}
1191
 
1192
static void
3931 Serge 1193
store_scanline_a8r8g8b8_32_sRGB (bits_image_t   *image,
1194
                                 int             x,
1195
                                 int             y,
1196
                                 int             width,
1197
                                 const uint32_t *v)
1891 serge 1198
{
1199
    uint32_t *bits = image->bits + image->rowstride * y;
3931 Serge 1200
    uint64_t *values = (uint64_t *)v;
1201
    uint32_t *pixel = bits + x;
1202
    uint64_t tmp;
1891 serge 1203
    int i;
1204
 
1205
    for (i = 0; i < width; ++i)
1206
    {
3931 Serge 1207
	uint8_t a, r, g, b;
1891 serge 1208
 
3931 Serge 1209
	tmp = values[i];
1891 serge 1210
 
3931 Serge 1211
	a = (tmp >> 24) & 0xff;
1212
	r = (tmp >> 16) & 0xff;
1213
	g = (tmp >> 8) & 0xff;
1214
	b = (tmp >> 0) & 0xff;
1891 serge 1215
 
3931 Serge 1216
	r = to_srgb (r * (1/255.0f));
1217
	g = to_srgb (g * (1/255.0f));
1218
	b = to_srgb (b * (1/255.0f));
1891 serge 1219
 
3931 Serge 1220
	WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0));
1891 serge 1221
    }
1222
}
1223
 
3931 Serge 1224
static argb_t
1225
fetch_pixel_generic_float (bits_image_t *image,
1226
			   int		 offset,
1227
			   int           line)
1891 serge 1228
{
1229
    uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
3931 Serge 1230
    argb_t f;
1891 serge 1231
 
3931 Serge 1232
    pixman_expand_to_float (&f, &pixel32, image->format, 1);
1891 serge 1233
 
3931 Serge 1234
    return f;
1891 serge 1235
}
1236
 
1237
/*
1238
 * XXX: The transformed fetch path only works at 32-bpp so far.  When all
1239
 * paths have wide versions, this can be removed.
1240
 *
1241
 * WARNING: This function loses precision!
1242
 */
1243
static uint32_t
1244
fetch_pixel_generic_lossy_32 (bits_image_t *image,
1245
			      int           offset,
1246
			      int           line)
1247
{
3931 Serge 1248
    argb_t pixel64 = image->fetch_pixel_float (image, offset, line);
1891 serge 1249
    uint32_t result;
1250
 
3931 Serge 1251
    pixman_contract_from_float (&result, &pixel64, 1);
1252
 
1891 serge 1253
    return result;
1254
}
1255
 
1256
typedef struct
1257
{
1258
    pixman_format_code_t	format;
1259
    fetch_scanline_t		fetch_scanline_32;
3931 Serge 1260
    fetch_scanline_t		fetch_scanline_float;
1891 serge 1261
    fetch_pixel_32_t		fetch_pixel_32;
3931 Serge 1262
    fetch_pixel_float_t		fetch_pixel_float;
1891 serge 1263
    store_scanline_t		store_scanline_32;
3931 Serge 1264
    store_scanline_t		store_scanline_float;
1891 serge 1265
} format_info_t;
1266
 
1267
#define FORMAT_INFO(format) 						\
1268
    {									\
1269
	PIXMAN_ ## format,						\
1270
	    fetch_scanline_ ## format,					\
3931 Serge 1271
	    fetch_scanline_generic_float,				\
1272
	    fetch_pixel_ ## format,					\
1273
	    fetch_pixel_generic_float,					\
1274
	    store_scanline_ ## format,					\
1275
	    store_scanline_generic_float				\
1891 serge 1276
    }
1277
 
1278
static const format_info_t accessors[] =
1279
{
1280
/* 32 bpp formats */
1281
    FORMAT_INFO (a8r8g8b8),
1282
    FORMAT_INFO (x8r8g8b8),
1283
    FORMAT_INFO (a8b8g8r8),
1284
    FORMAT_INFO (x8b8g8r8),
1285
    FORMAT_INFO (b8g8r8a8),
1286
    FORMAT_INFO (b8g8r8x8),
3931 Serge 1287
    FORMAT_INFO (r8g8b8a8),
1288
    FORMAT_INFO (r8g8b8x8),
1891 serge 1289
    FORMAT_INFO (x14r6g6b6),
1290
 
3931 Serge 1291
/* sRGB formats */
1292
  { PIXMAN_a8r8g8b8_sRGB,
1293
    fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_sRGB_float,
1294
    fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float,
1295
    store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float,
1296
  },
1297
 
1891 serge 1298
/* 24bpp formats */
1299
    FORMAT_INFO (r8g8b8),
1300
    FORMAT_INFO (b8g8r8),
1301
 
1302
/* 16bpp formats */
1303
    FORMAT_INFO (r5g6b5),
1304
    FORMAT_INFO (b5g6r5),
1305
 
1306
    FORMAT_INFO (a1r5g5b5),
1307
    FORMAT_INFO (x1r5g5b5),
1308
    FORMAT_INFO (a1b5g5r5),
1309
    FORMAT_INFO (x1b5g5r5),
1310
    FORMAT_INFO (a4r4g4b4),
1311
    FORMAT_INFO (x4r4g4b4),
1312
    FORMAT_INFO (a4b4g4r4),
1313
    FORMAT_INFO (x4b4g4r4),
1314
 
1315
/* 8bpp formats */
1316
    FORMAT_INFO (a8),
1317
    FORMAT_INFO (r3g3b2),
1318
    FORMAT_INFO (b2g3r3),
1319
    FORMAT_INFO (a2r2g2b2),
1320
    FORMAT_INFO (a2b2g2r2),
1321
 
1322
    FORMAT_INFO (c8),
1323
 
1324
    FORMAT_INFO (g8),
1325
 
1326
#define fetch_scanline_x4c4 fetch_scanline_c8
1327
#define fetch_pixel_x4c4 fetch_pixel_c8
1328
#define store_scanline_x4c4 store_scanline_c8
1329
    FORMAT_INFO (x4c4),
1330
 
3931 Serge 1331
#define fetch_scanline_x4g4 fetch_scanline_g8
1332
#define fetch_pixel_x4g4 fetch_pixel_g8
1891 serge 1333
#define store_scanline_x4g4 store_scanline_g8
1334
    FORMAT_INFO (x4g4),
1335
 
1336
    FORMAT_INFO (x4a4),
1337
 
1338
/* 4bpp formats */
1339
    FORMAT_INFO (a4),
1340
    FORMAT_INFO (r1g2b1),
1341
    FORMAT_INFO (b1g2r1),
1342
    FORMAT_INFO (a1r1g1b1),
1343
    FORMAT_INFO (a1b1g1r1),
1344
 
1345
    FORMAT_INFO (c4),
1346
 
1347
    FORMAT_INFO (g4),
1348
 
1349
/* 1bpp formats */
1350
    FORMAT_INFO (a1),
1351
    FORMAT_INFO (g1),
1352
 
1353
/* Wide formats */
1354
 
1355
    { PIXMAN_a2r10g10b10,
3931 Serge 1356
      NULL, fetch_scanline_a2r10g10b10_float,
1357
      fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10_float,
1358
      NULL, store_scanline_a2r10g10b10_float },
1359
 
1891 serge 1360
    { PIXMAN_x2r10g10b10,
3931 Serge 1361
      NULL, fetch_scanline_x2r10g10b10_float,
1362
      fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10_float,
1363
      NULL, store_scanline_x2r10g10b10_float },
1364
 
1891 serge 1365
    { PIXMAN_a2b10g10r10,
3931 Serge 1366
      NULL, fetch_scanline_a2b10g10r10_float,
1367
      fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10_float,
1368
      NULL, store_scanline_a2b10g10r10_float },
1369
 
1891 serge 1370
    { PIXMAN_x2b10g10r10,
3931 Serge 1371
      NULL, fetch_scanline_x2b10g10r10_float,
1372
      fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10_float,
1373
      NULL, store_scanline_x2b10g10r10_float },
1374
 
1891 serge 1375
/* YUV formats */
1376
    { PIXMAN_yuy2,
3931 Serge 1377
      fetch_scanline_yuy2, fetch_scanline_generic_float,
1378
      fetch_pixel_yuy2, fetch_pixel_generic_float,
1891 serge 1379
      NULL, NULL },
3931 Serge 1380
 
1891 serge 1381
    { PIXMAN_yv12,
3931 Serge 1382
      fetch_scanline_yv12, fetch_scanline_generic_float,
1383
      fetch_pixel_yv12, fetch_pixel_generic_float,
1891 serge 1384
      NULL, NULL },
1385
 
1386
    { PIXMAN_null },
1387
};
1388
 
1389
static void
1390
setup_accessors (bits_image_t *image)
1391
{
1392
    const format_info_t *info = accessors;
1393
 
1394
    while (info->format != PIXMAN_null)
1395
    {
1396
	if (info->format == image->format)
1397
	{
1398
	    image->fetch_scanline_32 = info->fetch_scanline_32;
3931 Serge 1399
	    image->fetch_scanline_float = info->fetch_scanline_float;
1891 serge 1400
	    image->fetch_pixel_32 = info->fetch_pixel_32;
3931 Serge 1401
	    image->fetch_pixel_float = info->fetch_pixel_float;
1891 serge 1402
	    image->store_scanline_32 = info->store_scanline_32;
3931 Serge 1403
	    image->store_scanline_float = info->store_scanline_float;
1891 serge 1404
 
1405
	    return;
1406
	}
1407
 
1408
	info++;
1409
    }
1410
}
1411
 
1412
#ifndef PIXMAN_FB_ACCESSORS
1413
void
1414
_pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
1415
 
1416
void
1417
_pixman_bits_image_setup_accessors (bits_image_t *image)
1418
{
1419
    if (image->read_func || image->write_func)
1420
	_pixman_bits_image_setup_accessors_accessors (image);
1421
    else
1422
	setup_accessors (image);
1423
}
1424
 
1425
#else
1426
 
1427
void
1428
_pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
1429
{
1430
    setup_accessors (image);
1431
}
1432
 
1433
#endif