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
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2
/*
3
 * Copyright © 2000 SuSE, Inc.
4
 * Copyright © 2007 Red Hat, Inc.
5
 *
6
 * Permission to use, copy, modify, distribute, and sell this software and its
7
 * documentation for any purpose is hereby granted without fee, provided that
8
 * the above copyright notice appear in all copies and that both that
9
 * copyright notice and this permission notice appear in supporting
10
 * documentation, and that the name of SuSE not be used in advertising or
11
 * publicity pertaining to distribution of the software without specific,
12
 * written prior permission.  SuSE makes no representations about the
13
 * suitability of this software for any purpose.  It is provided "as is"
14
 * without express or implied warranty.
15
 *
16
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 *
23
 * Author:  Keith Packard, SuSE, Inc.
24
 */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include 
28
#endif
29
#include 
30
#include 
31
#include "pixman-private.h"
32
#include "pixman-combine32.h"
3931 Serge 33
#include "pixman-inlines.h"
1891 serge 34
 
35
static force_inline uint32_t
36
fetch_24 (uint8_t *a)
37
{
3931 Serge 38
    if (((uintptr_t)a) & 1)
1891 serge 39
    {
40
#ifdef WORDS_BIGENDIAN
41
	return (*a << 16) | (*(uint16_t *)(a + 1));
42
#else
43
	return *a | (*(uint16_t *)(a + 1) << 8);
44
#endif
45
    }
46
    else
47
    {
48
#ifdef WORDS_BIGENDIAN
49
	return (*(uint16_t *)a << 8) | *(a + 2);
50
#else
51
	return *(uint16_t *)a | (*(a + 2) << 16);
52
#endif
53
    }
54
}
55
 
56
static force_inline void
57
store_24 (uint8_t *a,
58
          uint32_t v)
59
{
3931 Serge 60
    if (((uintptr_t)a) & 1)
1891 serge 61
    {
62
#ifdef WORDS_BIGENDIAN
63
	*a = (uint8_t) (v >> 16);
64
	*(uint16_t *)(a + 1) = (uint16_t) (v);
65
#else
66
	*a = (uint8_t) (v);
67
	*(uint16_t *)(a + 1) = (uint16_t) (v >> 8);
68
#endif
69
    }
70
    else
71
    {
72
#ifdef WORDS_BIGENDIAN
73
	*(uint16_t *)a = (uint16_t)(v >> 8);
74
	*(a + 2) = (uint8_t)v;
75
#else
76
	*(uint16_t *)a = (uint16_t)v;
77
	*(a + 2) = (uint8_t)(v >> 16);
78
#endif
79
    }
80
}
81
 
82
static force_inline uint32_t
83
over (uint32_t src,
84
      uint32_t dest)
85
{
86
    uint32_t a = ~src >> 24;
87
 
88
    UN8x4_MUL_UN8_ADD_UN8x4 (dest, a, src);
89
 
90
    return dest;
91
}
92
 
3931 Serge 93
static force_inline uint32_t
1891 serge 94
in (uint32_t x,
95
    uint8_t  y)
96
{
97
    uint16_t a = y;
98
 
99
    UN8x4_MUL_UN8 (x, a);
100
 
101
    return x;
102
}
103
 
104
/*
105
 * Naming convention:
106
 *
107
 *  op_src_mask_dest
108
 */
109
static void
110
fast_composite_over_x888_8_8888 (pixman_implementation_t *imp,
3931 Serge 111
                                 pixman_composite_info_t *info)
1891 serge 112
{
3931 Serge 113
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 114
    uint32_t    *src, *src_line;
115
    uint32_t    *dst, *dst_line;
116
    uint8_t     *mask, *mask_line;
117
    int src_stride, mask_stride, dst_stride;
118
    uint8_t m;
119
    uint32_t s, d;
120
    int32_t w;
121
 
3931 Serge 122
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 123
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
124
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
125
 
126
    while (height--)
127
    {
128
	src = src_line;
129
	src_line += src_stride;
130
	dst = dst_line;
131
	dst_line += dst_stride;
132
	mask = mask_line;
133
	mask_line += mask_stride;
134
 
135
	w = width;
136
	while (w--)
137
	{
138
	    m = *mask++;
139
	    if (m)
140
	    {
141
		s = *src | 0xff000000;
142
 
143
		if (m == 0xff)
144
		{
145
		    *dst = s;
146
		}
147
		else
148
		{
149
		    d = in (s, m);
150
		    *dst = over (d, *dst);
151
		}
152
	    }
153
	    src++;
154
	    dst++;
155
	}
156
    }
157
}
158
 
159
static void
160
fast_composite_in_n_8_8 (pixman_implementation_t *imp,
3931 Serge 161
                         pixman_composite_info_t *info)
1891 serge 162
{
3931 Serge 163
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 164
    uint32_t src, srca;
165
    uint8_t     *dst_line, *dst;
166
    uint8_t     *mask_line, *mask, m;
167
    int dst_stride, mask_stride;
168
    int32_t w;
169
    uint16_t t;
170
 
3931 Serge 171
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 172
 
173
    srca = src >> 24;
174
 
175
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
176
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
177
 
178
    if (srca == 0xff)
179
    {
180
	while (height--)
181
	{
182
	    dst = dst_line;
183
	    dst_line += dst_stride;
184
	    mask = mask_line;
185
	    mask_line += mask_stride;
186
	    w = width;
187
 
188
	    while (w--)
189
	    {
190
		m = *mask++;
191
 
192
		if (m == 0)
193
		    *dst = 0;
194
		else if (m != 0xff)
195
		    *dst = MUL_UN8 (m, *dst, t);
196
 
197
		dst++;
198
	    }
199
	}
200
    }
201
    else
202
    {
203
	while (height--)
204
	{
205
	    dst = dst_line;
206
	    dst_line += dst_stride;
207
	    mask = mask_line;
208
	    mask_line += mask_stride;
209
	    w = width;
210
 
211
	    while (w--)
212
	    {
213
		m = *mask++;
214
		m = MUL_UN8 (m, srca, t);
215
 
216
		if (m == 0)
217
		    *dst = 0;
218
		else if (m != 0xff)
219
		    *dst = MUL_UN8 (m, *dst, t);
220
 
221
		dst++;
222
	    }
223
	}
224
    }
225
}
226
 
227
static void
228
fast_composite_in_8_8 (pixman_implementation_t *imp,
3931 Serge 229
                       pixman_composite_info_t *info)
1891 serge 230
{
3931 Serge 231
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 232
    uint8_t     *dst_line, *dst;
233
    uint8_t     *src_line, *src;
234
    int dst_stride, src_stride;
235
    int32_t w;
236
    uint8_t s;
237
    uint16_t t;
238
 
239
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
240
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
241
 
242
    while (height--)
243
    {
244
	dst = dst_line;
245
	dst_line += dst_stride;
246
	src = src_line;
247
	src_line += src_stride;
248
	w = width;
249
 
250
	while (w--)
251
	{
252
	    s = *src++;
253
 
254
	    if (s == 0)
255
		*dst = 0;
256
	    else if (s != 0xff)
257
		*dst = MUL_UN8 (s, *dst, t);
258
 
259
	    dst++;
260
	}
261
    }
262
}
263
 
264
static void
265
fast_composite_over_n_8_8888 (pixman_implementation_t *imp,
3931 Serge 266
                              pixman_composite_info_t *info)
1891 serge 267
{
3931 Serge 268
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 269
    uint32_t src, srca;
270
    uint32_t    *dst_line, *dst, d;
271
    uint8_t     *mask_line, *mask, m;
272
    int dst_stride, mask_stride;
273
    int32_t w;
274
 
3931 Serge 275
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 276
 
277
    srca = src >> 24;
278
    if (src == 0)
279
	return;
280
 
3931 Serge 281
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 282
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
283
 
284
    while (height--)
285
    {
286
	dst = dst_line;
287
	dst_line += dst_stride;
288
	mask = mask_line;
289
	mask_line += mask_stride;
290
	w = width;
291
 
292
	while (w--)
293
	{
294
	    m = *mask++;
295
	    if (m == 0xff)
296
	    {
297
		if (srca == 0xff)
298
		    *dst = src;
299
		else
300
		    *dst = over (src, *dst);
301
	    }
302
	    else if (m)
303
	    {
304
		d = in (src, m);
305
		*dst = over (d, *dst);
306
	    }
307
	    dst++;
308
	}
309
    }
310
}
311
 
312
static void
313
fast_composite_add_n_8888_8888_ca (pixman_implementation_t *imp,
3931 Serge 314
				   pixman_composite_info_t *info)
1891 serge 315
{
3931 Serge 316
    PIXMAN_COMPOSITE_ARGS (info);
317
    uint32_t src, s;
1891 serge 318
    uint32_t    *dst_line, *dst, d;
319
    uint32_t    *mask_line, *mask, ma;
320
    int dst_stride, mask_stride;
321
    int32_t w;
322
 
3931 Serge 323
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 324
 
325
    if (src == 0)
326
	return;
327
 
3931 Serge 328
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 329
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
330
 
331
    while (height--)
332
    {
333
	dst = dst_line;
334
	dst_line += dst_stride;
335
	mask = mask_line;
336
	mask_line += mask_stride;
337
	w = width;
338
 
339
	while (w--)
340
	{
341
	    ma = *mask++;
342
 
343
	    if (ma)
344
	    {
345
		d = *dst;
346
		s = src;
347
 
348
		UN8x4_MUL_UN8x4_ADD_UN8x4 (s, ma, d);
349
 
350
		*dst = s;
351
	    }
352
 
353
	    dst++;
354
	}
355
    }
356
}
357
 
358
static void
359
fast_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
3931 Serge 360
                                    pixman_composite_info_t *info)
1891 serge 361
{
3931 Serge 362
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 363
    uint32_t src, srca, s;
364
    uint32_t    *dst_line, *dst, d;
365
    uint32_t    *mask_line, *mask, ma;
366
    int dst_stride, mask_stride;
367
    int32_t w;
368
 
3931 Serge 369
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 370
 
371
    srca = src >> 24;
372
    if (src == 0)
373
	return;
374
 
3931 Serge 375
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 376
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
377
 
378
    while (height--)
379
    {
380
	dst = dst_line;
381
	dst_line += dst_stride;
382
	mask = mask_line;
383
	mask_line += mask_stride;
384
	w = width;
385
 
386
	while (w--)
387
	{
388
	    ma = *mask++;
389
	    if (ma == 0xffffffff)
390
	    {
391
		if (srca == 0xff)
392
		    *dst = src;
393
		else
394
		    *dst = over (src, *dst);
395
	    }
396
	    else if (ma)
397
	    {
398
		d = *dst;
399
		s = src;
400
 
401
		UN8x4_MUL_UN8x4 (s, ma);
402
		UN8x4_MUL_UN8 (ma, srca);
403
		ma = ~ma;
404
		UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
405
 
406
		*dst = d;
407
	    }
408
 
409
	    dst++;
410
	}
411
    }
412
}
413
 
414
static void
415
fast_composite_over_n_8_0888 (pixman_implementation_t *imp,
3931 Serge 416
                              pixman_composite_info_t *info)
1891 serge 417
{
3931 Serge 418
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 419
    uint32_t src, srca;
420
    uint8_t     *dst_line, *dst;
421
    uint32_t d;
422
    uint8_t     *mask_line, *mask, m;
423
    int dst_stride, mask_stride;
424
    int32_t w;
425
 
3931 Serge 426
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 427
 
428
    srca = src >> 24;
429
    if (src == 0)
430
	return;
431
 
3931 Serge 432
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
1891 serge 433
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
434
 
435
    while (height--)
436
    {
437
	dst = dst_line;
438
	dst_line += dst_stride;
439
	mask = mask_line;
440
	mask_line += mask_stride;
441
	w = width;
442
 
443
	while (w--)
444
	{
445
	    m = *mask++;
446
	    if (m == 0xff)
447
	    {
448
		if (srca == 0xff)
449
		{
450
		    d = src;
451
		}
452
		else
453
		{
454
		    d = fetch_24 (dst);
455
		    d = over (src, d);
456
		}
457
		store_24 (dst, d);
458
	    }
459
	    else if (m)
460
	    {
461
		d = over (in (src, m), fetch_24 (dst));
462
		store_24 (dst, d);
463
	    }
464
	    dst += 3;
465
	}
466
    }
467
}
468
 
469
static void
470
fast_composite_over_n_8_0565 (pixman_implementation_t *imp,
3931 Serge 471
                              pixman_composite_info_t *info)
1891 serge 472
{
3931 Serge 473
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 474
    uint32_t src, srca;
475
    uint16_t    *dst_line, *dst;
476
    uint32_t d;
477
    uint8_t     *mask_line, *mask, m;
478
    int dst_stride, mask_stride;
479
    int32_t w;
480
 
3931 Serge 481
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 482
 
483
    srca = src >> 24;
484
    if (src == 0)
485
	return;
486
 
3931 Serge 487
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1891 serge 488
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
489
 
490
    while (height--)
491
    {
492
	dst = dst_line;
493
	dst_line += dst_stride;
494
	mask = mask_line;
495
	mask_line += mask_stride;
496
	w = width;
497
 
498
	while (w--)
499
	{
500
	    m = *mask++;
501
	    if (m == 0xff)
502
	    {
503
		if (srca == 0xff)
504
		{
505
		    d = src;
506
		}
507
		else
508
		{
509
		    d = *dst;
3931 Serge 510
		    d = over (src, convert_0565_to_0888 (d));
1891 serge 511
		}
3931 Serge 512
		*dst = convert_8888_to_0565 (d);
1891 serge 513
	    }
514
	    else if (m)
515
	    {
516
		d = *dst;
3931 Serge 517
		d = over (in (src, m), convert_0565_to_0888 (d));
518
		*dst = convert_8888_to_0565 (d);
1891 serge 519
	    }
520
	    dst++;
521
	}
522
    }
523
}
524
 
525
static void
526
fast_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
3931 Serge 527
                                    pixman_composite_info_t *info)
1891 serge 528
{
3931 Serge 529
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 530
    uint32_t  src, srca, s;
531
    uint16_t  src16;
532
    uint16_t *dst_line, *dst;
533
    uint32_t  d;
534
    uint32_t *mask_line, *mask, ma;
535
    int dst_stride, mask_stride;
536
    int32_t w;
537
 
3931 Serge 538
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 539
 
540
    srca = src >> 24;
541
    if (src == 0)
542
	return;
543
 
3931 Serge 544
    src16 = convert_8888_to_0565 (src);
1891 serge 545
 
3931 Serge 546
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1891 serge 547
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
548
 
549
    while (height--)
550
    {
551
	dst = dst_line;
552
	dst_line += dst_stride;
553
	mask = mask_line;
554
	mask_line += mask_stride;
555
	w = width;
556
 
557
	while (w--)
558
	{
559
	    ma = *mask++;
560
	    if (ma == 0xffffffff)
561
	    {
562
		if (srca == 0xff)
563
		{
564
		    *dst = src16;
565
		}
566
		else
567
		{
568
		    d = *dst;
3931 Serge 569
		    d = over (src, convert_0565_to_0888 (d));
570
		    *dst = convert_8888_to_0565 (d);
1891 serge 571
		}
572
	    }
573
	    else if (ma)
574
	    {
575
		d = *dst;
3931 Serge 576
		d = convert_0565_to_0888 (d);
1891 serge 577
 
578
		s = src;
579
 
580
		UN8x4_MUL_UN8x4 (s, ma);
581
		UN8x4_MUL_UN8 (ma, srca);
582
		ma = ~ma;
583
		UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ma, s);
584
 
3931 Serge 585
		*dst = convert_8888_to_0565 (d);
1891 serge 586
	    }
587
	    dst++;
588
	}
589
    }
590
}
591
 
592
static void
593
fast_composite_over_8888_8888 (pixman_implementation_t *imp,
3931 Serge 594
                               pixman_composite_info_t *info)
1891 serge 595
{
3931 Serge 596
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 597
    uint32_t    *dst_line, *dst;
598
    uint32_t    *src_line, *src, s;
599
    int dst_stride, src_stride;
600
    uint8_t a;
601
    int32_t w;
602
 
3931 Serge 603
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 604
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
605
 
606
    while (height--)
607
    {
608
	dst = dst_line;
609
	dst_line += dst_stride;
610
	src = src_line;
611
	src_line += src_stride;
612
	w = width;
613
 
614
	while (w--)
615
	{
616
	    s = *src++;
617
	    a = s >> 24;
618
	    if (a == 0xff)
619
		*dst = s;
620
	    else if (s)
621
		*dst = over (s, *dst);
622
	    dst++;
623
	}
624
    }
625
}
626
 
627
static void
628
fast_composite_src_x888_8888 (pixman_implementation_t *imp,
3931 Serge 629
			      pixman_composite_info_t *info)
1891 serge 630
{
3931 Serge 631
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 632
    uint32_t    *dst_line, *dst;
633
    uint32_t    *src_line, *src;
634
    int dst_stride, src_stride;
635
    int32_t w;
636
 
3931 Serge 637
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 638
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
639
 
640
    while (height--)
641
    {
642
	dst = dst_line;
643
	dst_line += dst_stride;
644
	src = src_line;
645
	src_line += src_stride;
646
	w = width;
647
 
648
	while (w--)
649
	    *dst++ = (*src++) | 0xff000000;
650
    }
651
}
652
 
653
#if 0
654
static void
655
fast_composite_over_8888_0888 (pixman_implementation_t *imp,
3931 Serge 656
			       pixman_composite_info_t *info)
1891 serge 657
{
3931 Serge 658
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 659
    uint8_t     *dst_line, *dst;
660
    uint32_t d;
661
    uint32_t    *src_line, *src, s;
662
    uint8_t a;
663
    int dst_stride, src_stride;
664
    int32_t w;
665
 
3931 Serge 666
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 3);
1891 serge 667
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
668
 
669
    while (height--)
670
    {
671
	dst = dst_line;
672
	dst_line += dst_stride;
673
	src = src_line;
674
	src_line += src_stride;
675
	w = width;
676
 
677
	while (w--)
678
	{
679
	    s = *src++;
680
	    a = s >> 24;
681
	    if (a)
682
	    {
683
		if (a == 0xff)
684
		    d = s;
685
		else
686
		    d = over (s, fetch_24 (dst));
687
 
688
		store_24 (dst, d);
689
	    }
690
	    dst += 3;
691
	}
692
    }
693
}
694
#endif
695
 
696
static void
697
fast_composite_over_8888_0565 (pixman_implementation_t *imp,
3931 Serge 698
                               pixman_composite_info_t *info)
1891 serge 699
{
3931 Serge 700
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 701
    uint16_t    *dst_line, *dst;
702
    uint32_t d;
703
    uint32_t    *src_line, *src, s;
704
    uint8_t a;
705
    int dst_stride, src_stride;
706
    int32_t w;
707
 
708
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
3931 Serge 709
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1891 serge 710
 
711
    while (height--)
712
    {
713
	dst = dst_line;
714
	dst_line += dst_stride;
715
	src = src_line;
716
	src_line += src_stride;
717
	w = width;
718
 
719
	while (w--)
720
	{
721
	    s = *src++;
722
	    a = s >> 24;
723
	    if (s)
724
	    {
725
		if (a == 0xff)
726
		{
727
		    d = s;
728
		}
729
		else
730
		{
731
		    d = *dst;
3931 Serge 732
		    d = over (s, convert_0565_to_0888 (d));
1891 serge 733
		}
3931 Serge 734
		*dst = convert_8888_to_0565 (d);
1891 serge 735
	    }
736
	    dst++;
737
	}
738
    }
739
}
740
 
741
static void
3931 Serge 742
fast_composite_add_8_8 (pixman_implementation_t *imp,
743
			pixman_composite_info_t *info)
1891 serge 744
{
3931 Serge 745
    PIXMAN_COMPOSITE_ARGS (info);
746
    uint8_t     *dst_line, *dst;
747
    uint8_t     *src_line, *src;
1891 serge 748
    int dst_stride, src_stride;
749
    int32_t w;
3931 Serge 750
    uint8_t s, d;
751
    uint16_t t;
1891 serge 752
 
3931 Serge 753
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
754
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
1891 serge 755
 
756
    while (height--)
757
    {
758
	dst = dst_line;
759
	dst_line += dst_stride;
760
	src = src_line;
761
	src_line += src_stride;
762
	w = width;
763
 
764
	while (w--)
765
	{
766
	    s = *src++;
3931 Serge 767
	    if (s)
768
	    {
769
		if (s != 0xff)
770
		{
771
		    d = *dst;
772
		    t = d + s;
773
		    s = t | (0 - (t >> 8));
774
		}
775
		*dst = s;
776
	    }
1891 serge 777
	    dst++;
778
	}
779
    }
780
}
781
 
782
static void
3931 Serge 783
fast_composite_add_0565_0565 (pixman_implementation_t *imp,
784
                              pixman_composite_info_t *info)
1891 serge 785
{
3931 Serge 786
    PIXMAN_COMPOSITE_ARGS (info);
787
    uint16_t    *dst_line, *dst;
788
    uint32_t	d;
789
    uint16_t    *src_line, *src;
790
    uint32_t	s;
1891 serge 791
    int dst_stride, src_stride;
792
    int32_t w;
793
 
3931 Serge 794
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1);
795
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1891 serge 796
 
797
    while (height--)
798
    {
799
	dst = dst_line;
800
	dst_line += dst_stride;
801
	src = src_line;
802
	src_line += src_stride;
803
	w = width;
804
 
805
	while (w--)
806
	{
807
	    s = *src++;
808
	    if (s)
809
	    {
3931 Serge 810
		d = *dst;
811
		s = convert_0565_to_8888 (s);
812
		if (d)
1891 serge 813
		{
3931 Serge 814
		    d = convert_0565_to_8888 (d);
815
		    UN8x4_ADD_UN8x4 (s, d);
1891 serge 816
		}
3931 Serge 817
		*dst = convert_8888_to_0565 (s);
1891 serge 818
	    }
819
	    dst++;
820
	}
821
    }
822
}
823
 
824
static void
825
fast_composite_add_8888_8888 (pixman_implementation_t *imp,
3931 Serge 826
                              pixman_composite_info_t *info)
1891 serge 827
{
3931 Serge 828
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 829
    uint32_t    *dst_line, *dst;
830
    uint32_t    *src_line, *src;
831
    int dst_stride, src_stride;
832
    int32_t w;
833
    uint32_t s, d;
834
 
835
    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
3931 Serge 836
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 837
 
838
    while (height--)
839
    {
840
	dst = dst_line;
841
	dst_line += dst_stride;
842
	src = src_line;
843
	src_line += src_stride;
844
	w = width;
845
 
846
	while (w--)
847
	{
848
	    s = *src++;
849
	    if (s)
850
	    {
851
		if (s != 0xffffffff)
852
		{
853
		    d = *dst;
854
		    if (d)
855
			UN8x4_ADD_UN8x4 (s, d);
856
		}
857
		*dst = s;
858
	    }
859
	    dst++;
860
	}
861
    }
862
}
863
 
864
static void
865
fast_composite_add_n_8_8 (pixman_implementation_t *imp,
3931 Serge 866
			  pixman_composite_info_t *info)
1891 serge 867
{
3931 Serge 868
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 869
    uint8_t     *dst_line, *dst;
870
    uint8_t     *mask_line, *mask;
871
    int dst_stride, mask_stride;
872
    int32_t w;
873
    uint32_t src;
874
    uint8_t sa;
875
 
3931 Serge 876
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
1891 serge 877
    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
3931 Serge 878
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 879
    sa = (src >> 24);
880
 
881
    while (height--)
882
    {
883
	dst = dst_line;
884
	dst_line += dst_stride;
885
	mask = mask_line;
886
	mask_line += mask_stride;
887
	w = width;
888
 
889
	while (w--)
890
	{
891
	    uint16_t tmp;
892
	    uint16_t a;
893
	    uint32_t m, d;
894
	    uint32_t r;
895
 
896
	    a = *mask++;
897
	    d = *dst;
898
 
899
	    m = MUL_UN8 (sa, a, tmp);
900
	    r = ADD_UN8 (m, d, tmp);
901
 
902
	    *dst++ = r;
903
	}
904
    }
905
}
906
 
907
#ifdef WORDS_BIGENDIAN
908
#define CREATE_BITMASK(n) (0x80000000 >> (n))
909
#define UPDATE_BITMASK(n) ((n) >> 1)
910
#else
911
#define CREATE_BITMASK(n) (1 << (n))
912
#define UPDATE_BITMASK(n) ((n) << 1)
913
#endif
914
 
915
#define TEST_BIT(p, n)					\
916
    (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31))
917
#define SET_BIT(p, n)							\
918
    do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0);
919
 
920
static void
3931 Serge 921
fast_composite_add_1_1 (pixman_implementation_t *imp,
922
			pixman_composite_info_t *info)
1891 serge 923
{
3931 Serge 924
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 925
    uint32_t     *dst_line, *dst;
926
    uint32_t     *src_line, *src;
927
    int           dst_stride, src_stride;
928
    int32_t       w;
929
 
930
    PIXMAN_IMAGE_GET_LINE (src_image, 0, src_y, uint32_t,
931
                           src_stride, src_line, 1);
3931 Serge 932
    PIXMAN_IMAGE_GET_LINE (dest_image, 0, dest_y, uint32_t,
1891 serge 933
                           dst_stride, dst_line, 1);
934
 
935
    while (height--)
936
    {
937
	dst = dst_line;
938
	dst_line += dst_stride;
939
	src = src_line;
940
	src_line += src_stride;
941
	w = width;
942
 
943
	while (w--)
944
	{
945
	    /*
946
	     * TODO: improve performance by processing uint32_t data instead
947
	     *       of individual bits
948
	     */
949
	    if (TEST_BIT (src, src_x + w))
950
		SET_BIT (dst, dest_x + w);
951
	}
952
    }
953
}
954
 
955
static void
956
fast_composite_over_n_1_8888 (pixman_implementation_t *imp,
3931 Serge 957
                              pixman_composite_info_t *info)
1891 serge 958
{
3931 Serge 959
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 960
    uint32_t     src, srca;
961
    uint32_t    *dst, *dst_line;
962
    uint32_t    *mask, *mask_line;
963
    int          mask_stride, dst_stride;
964
    uint32_t     bitcache, bitmask;
965
    int32_t      w;
966
 
967
    if (width <= 0)
968
	return;
969
 
3931 Serge 970
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 971
    srca = src >> 24;
972
    if (src == 0)
973
	return;
974
 
3931 Serge 975
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t,
1891 serge 976
                           dst_stride, dst_line, 1);
977
    PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
978
                           mask_stride, mask_line, 1);
979
    mask_line += mask_x >> 5;
980
 
981
    if (srca == 0xff)
982
    {
983
	while (height--)
984
	{
985
	    dst = dst_line;
986
	    dst_line += dst_stride;
987
	    mask = mask_line;
988
	    mask_line += mask_stride;
989
	    w = width;
990
 
991
	    bitcache = *mask++;
992
	    bitmask = CREATE_BITMASK (mask_x & 31);
993
 
994
	    while (w--)
995
	    {
996
		if (bitmask == 0)
997
		{
998
		    bitcache = *mask++;
999
		    bitmask = CREATE_BITMASK (0);
1000
		}
1001
		if (bitcache & bitmask)
1002
		    *dst = src;
1003
		bitmask = UPDATE_BITMASK (bitmask);
1004
		dst++;
1005
	    }
1006
	}
1007
    }
1008
    else
1009
    {
1010
	while (height--)
1011
	{
1012
	    dst = dst_line;
1013
	    dst_line += dst_stride;
1014
	    mask = mask_line;
1015
	    mask_line += mask_stride;
1016
	    w = width;
1017
 
1018
	    bitcache = *mask++;
1019
	    bitmask = CREATE_BITMASK (mask_x & 31);
1020
 
1021
	    while (w--)
1022
	    {
1023
		if (bitmask == 0)
1024
		{
1025
		    bitcache = *mask++;
1026
		    bitmask = CREATE_BITMASK (0);
1027
		}
1028
		if (bitcache & bitmask)
1029
		    *dst = over (src, *dst);
1030
		bitmask = UPDATE_BITMASK (bitmask);
1031
		dst++;
1032
	    }
1033
	}
1034
    }
1035
}
1036
 
1037
static void
1038
fast_composite_over_n_1_0565 (pixman_implementation_t *imp,
3931 Serge 1039
                              pixman_composite_info_t *info)
1891 serge 1040
{
3931 Serge 1041
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 1042
    uint32_t     src, srca;
1043
    uint16_t    *dst, *dst_line;
1044
    uint32_t    *mask, *mask_line;
1045
    int          mask_stride, dst_stride;
1046
    uint32_t     bitcache, bitmask;
1047
    int32_t      w;
1048
    uint32_t     d;
1049
    uint16_t     src565;
1050
 
1051
    if (width <= 0)
1052
	return;
1053
 
3931 Serge 1054
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 1055
    srca = src >> 24;
1056
    if (src == 0)
1057
	return;
1058
 
3931 Serge 1059
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t,
1891 serge 1060
                           dst_stride, dst_line, 1);
1061
    PIXMAN_IMAGE_GET_LINE (mask_image, 0, mask_y, uint32_t,
1062
                           mask_stride, mask_line, 1);
1063
    mask_line += mask_x >> 5;
1064
 
1065
    if (srca == 0xff)
1066
    {
3931 Serge 1067
	src565 = convert_8888_to_0565 (src);
1891 serge 1068
	while (height--)
1069
	{
1070
	    dst = dst_line;
1071
	    dst_line += dst_stride;
1072
	    mask = mask_line;
1073
	    mask_line += mask_stride;
1074
	    w = width;
1075
 
1076
	    bitcache = *mask++;
1077
	    bitmask = CREATE_BITMASK (mask_x & 31);
1078
 
1079
	    while (w--)
1080
	    {
1081
		if (bitmask == 0)
1082
		{
1083
		    bitcache = *mask++;
1084
		    bitmask = CREATE_BITMASK (0);
1085
		}
1086
		if (bitcache & bitmask)
1087
		    *dst = src565;
1088
		bitmask = UPDATE_BITMASK (bitmask);
1089
		dst++;
1090
	    }
1091
	}
1092
    }
1093
    else
1094
    {
1095
	while (height--)
1096
	{
1097
	    dst = dst_line;
1098
	    dst_line += dst_stride;
1099
	    mask = mask_line;
1100
	    mask_line += mask_stride;
1101
	    w = width;
1102
 
1103
	    bitcache = *mask++;
1104
	    bitmask = CREATE_BITMASK (mask_x & 31);
1105
 
1106
	    while (w--)
1107
	    {
1108
		if (bitmask == 0)
1109
		{
1110
		    bitcache = *mask++;
1111
		    bitmask = CREATE_BITMASK (0);
1112
		}
1113
		if (bitcache & bitmask)
1114
		{
3931 Serge 1115
		    d = over (src, convert_0565_to_0888 (*dst));
1116
		    *dst = convert_8888_to_0565 (d);
1891 serge 1117
		}
1118
		bitmask = UPDATE_BITMASK (bitmask);
1119
		dst++;
1120
	    }
1121
	}
1122
    }
1123
}
1124
 
1125
/*
1126
 * Simple bitblt
1127
 */
1128
 
1129
static void
1130
fast_composite_solid_fill (pixman_implementation_t *imp,
3931 Serge 1131
                           pixman_composite_info_t *info)
1891 serge 1132
{
3931 Serge 1133
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 1134
    uint32_t src;
1135
 
3931 Serge 1136
    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1891 serge 1137
 
3931 Serge 1138
    if (dest_image->bits.format == PIXMAN_a1)
1891 serge 1139
    {
3931 Serge 1140
	src = src >> 31;
1141
    }
1142
    else if (dest_image->bits.format == PIXMAN_a8)
1143
    {
1891 serge 1144
	src = src >> 24;
1145
    }
3931 Serge 1146
    else if (dest_image->bits.format == PIXMAN_r5g6b5 ||
1147
             dest_image->bits.format == PIXMAN_b5g6r5)
1891 serge 1148
    {
3931 Serge 1149
	src = convert_8888_to_0565 (src);
1891 serge 1150
    }
1151
 
3931 Serge 1152
    pixman_fill (dest_image->bits.bits, dest_image->bits.rowstride,
1153
                 PIXMAN_FORMAT_BPP (dest_image->bits.format),
1891 serge 1154
                 dest_x, dest_y,
1155
                 width, height,
1156
                 src);
1157
}
1158
 
1159
static void
1160
fast_composite_src_memcpy (pixman_implementation_t *imp,
3931 Serge 1161
			   pixman_composite_info_t *info)
1891 serge 1162
{
3931 Serge 1163
    PIXMAN_COMPOSITE_ARGS (info);
1164
    int bpp = PIXMAN_FORMAT_BPP (dest_image->bits.format) / 8;
1891 serge 1165
    uint32_t n_bytes = width * bpp;
1166
    int dst_stride, src_stride;
1167
    uint8_t    *dst;
1168
    uint8_t    *src;
1169
 
1170
    src_stride = src_image->bits.rowstride * 4;
3931 Serge 1171
    dst_stride = dest_image->bits.rowstride * 4;
1891 serge 1172
 
1173
    src = (uint8_t *)src_image->bits.bits + src_y * src_stride + src_x * bpp;
3931 Serge 1174
    dst = (uint8_t *)dest_image->bits.bits + dest_y * dst_stride + dest_x * bpp;
1891 serge 1175
 
1176
    while (height--)
1177
    {
1178
	memcpy (dst, src, n_bytes);
1179
 
1180
	dst += dst_stride;
1181
	src += src_stride;
1182
    }
1183
}
1184
 
3931 Serge 1185
FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, SRC, COVER)
1186
FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, SRC, NONE)
1187
FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, SRC, PAD)
1188
FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, SRC, NORMAL)
1189
FAST_NEAREST (x888_8888_cover, x888, 8888, uint32_t, uint32_t, SRC, COVER)
1190
FAST_NEAREST (x888_8888_pad, x888, 8888, uint32_t, uint32_t, SRC, PAD)
1191
FAST_NEAREST (x888_8888_normal, x888, 8888, uint32_t, uint32_t, SRC, NORMAL)
1192
FAST_NEAREST (8888_8888_cover, 8888, 8888, uint32_t, uint32_t, OVER, COVER)
1193
FAST_NEAREST (8888_8888_none, 8888, 8888, uint32_t, uint32_t, OVER, NONE)
1194
FAST_NEAREST (8888_8888_pad, 8888, 8888, uint32_t, uint32_t, OVER, PAD)
1195
FAST_NEAREST (8888_8888_normal, 8888, 8888, uint32_t, uint32_t, OVER, NORMAL)
1196
FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, SRC, COVER)
1197
FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, SRC, NONE)
1198
FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, SRC, PAD)
1199
FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, SRC, NORMAL)
1200
FAST_NEAREST (565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL)
1201
FAST_NEAREST (8888_565_cover, 8888, 0565, uint32_t, uint16_t, OVER, COVER)
1202
FAST_NEAREST (8888_565_none, 8888, 0565, uint32_t, uint16_t, OVER, NONE)
1203
FAST_NEAREST (8888_565_pad, 8888, 0565, uint32_t, uint16_t, OVER, PAD)
1204
FAST_NEAREST (8888_565_normal, 8888, 0565, uint32_t, uint16_t, OVER, NORMAL)
1891 serge 1205
 
3931 Serge 1206
#define REPEAT_MIN_WIDTH    32
1207
 
1208
static void
1209
fast_composite_tiled_repeat (pixman_implementation_t *imp,
1210
			     pixman_composite_info_t *info)
1211
{
1212
    PIXMAN_COMPOSITE_ARGS (info);
1213
    pixman_composite_func_t func;
1214
    pixman_format_code_t mask_format;
1215
    uint32_t src_flags, mask_flags;
1216
    int32_t sx, sy;
1217
    int32_t width_remain;
1218
    int32_t num_pixels;
1219
    int32_t src_width;
1220
    int32_t i, j;
1221
    pixman_image_t extended_src_image;
1222
    uint32_t extended_src[REPEAT_MIN_WIDTH * 2];
1223
    pixman_bool_t need_src_extension;
1224
    uint32_t *src_line;
1225
    int32_t src_stride;
1226
    int32_t src_bpp;
1227
    pixman_composite_info_t info2 = *info;
1228
 
1229
    src_flags = (info->src_flags & ~FAST_PATH_NORMAL_REPEAT) |
1230
		    FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
1231
 
1232
    if (mask_image)
1233
    {
1234
	mask_format = mask_image->common.extended_format_code;
1235
	mask_flags = info->mask_flags;
1236
    }
1237
    else
1238
    {
1239
	mask_format = PIXMAN_null;
1240
	mask_flags = FAST_PATH_IS_OPAQUE;
1241
    }
1242
 
1243
    _pixman_implementation_lookup_composite (
1244
	imp->toplevel, info->op,
1245
	src_image->common.extended_format_code, src_flags,
1246
	mask_format, mask_flags,
1247
	dest_image->common.extended_format_code, info->dest_flags,
1248
	&imp, &func);
1249
 
1250
    src_bpp = PIXMAN_FORMAT_BPP (src_image->bits.format);
1251
 
1252
    if (src_image->bits.width < REPEAT_MIN_WIDTH		&&
1253
	(src_bpp == 32 || src_bpp == 16 || src_bpp == 8)	&&
1254
	!src_image->bits.indexed)
1255
    {
1256
	sx = src_x;
1257
	sx = MOD (sx, src_image->bits.width);
1258
	sx += width;
1259
	src_width = 0;
1260
 
1261
	while (src_width < REPEAT_MIN_WIDTH && src_width <= sx)
1262
	    src_width += src_image->bits.width;
1263
 
1264
	src_stride = (src_width * (src_bpp >> 3) + 3) / (int) sizeof (uint32_t);
1265
 
1266
	/* Initialize/validate stack-allocated temporary image */
1267
	_pixman_bits_image_init (&extended_src_image, src_image->bits.format,
1268
				 src_width, 1, &extended_src[0], src_stride,
1269
				 FALSE);
1270
	_pixman_image_validate (&extended_src_image);
1271
 
1272
	info2.src_image = &extended_src_image;
1273
	need_src_extension = TRUE;
1274
    }
1275
    else
1276
    {
1277
	src_width = src_image->bits.width;
1278
	need_src_extension = FALSE;
1279
    }
1280
 
1281
    sx = src_x;
1282
    sy = src_y;
1283
 
1284
    while (--height >= 0)
1285
    {
1286
	sx = MOD (sx, src_width);
1287
	sy = MOD (sy, src_image->bits.height);
1288
 
1289
	if (need_src_extension)
1290
	{
1291
	    if (src_bpp == 32)
1292
	    {
1293
		PIXMAN_IMAGE_GET_LINE (src_image, 0, sy, uint32_t, src_stride, src_line, 1);
1294
 
1295
		for (i = 0; i < src_width; )
1296
		{
1297
		    for (j = 0; j < src_image->bits.width; j++, i++)
1298
			extended_src[i] = src_line[j];
1299
		}
1300
	    }
1301
	    else if (src_bpp == 16)
1302
	    {
1303
		uint16_t *src_line_16;
1304
 
1305
		PIXMAN_IMAGE_GET_LINE (src_image, 0, sy, uint16_t, src_stride,
1306
				       src_line_16, 1);
1307
		src_line = (uint32_t*)src_line_16;
1308
 
1309
		for (i = 0; i < src_width; )
1310
		{
1311
		    for (j = 0; j < src_image->bits.width; j++, i++)
1312
			((uint16_t*)extended_src)[i] = ((uint16_t*)src_line)[j];
1313
		}
1314
	    }
1315
	    else if (src_bpp == 8)
1316
	    {
1317
		uint8_t *src_line_8;
1318
 
1319
		PIXMAN_IMAGE_GET_LINE (src_image, 0, sy, uint8_t, src_stride,
1320
				       src_line_8, 1);
1321
		src_line = (uint32_t*)src_line_8;
1322
 
1323
		for (i = 0; i < src_width; )
1324
		{
1325
		    for (j = 0; j < src_image->bits.width; j++, i++)
1326
			((uint8_t*)extended_src)[i] = ((uint8_t*)src_line)[j];
1327
		}
1328
	    }
1329
 
1330
	    info2.src_y = 0;
1331
	}
1332
	else
1333
	{
1334
	    info2.src_y = sy;
1335
	}
1336
 
1337
	width_remain = width;
1338
 
1339
	while (width_remain > 0)
1340
	{
1341
	    num_pixels = src_width - sx;
1342
 
1343
	    if (num_pixels > width_remain)
1344
		num_pixels = width_remain;
1345
 
1346
	    info2.src_x = sx;
1347
	    info2.width = num_pixels;
1348
	    info2.height = 1;
1349
 
1350
	    func (imp, &info2);
1351
 
1352
	    width_remain -= num_pixels;
1353
	    info2.mask_x += num_pixels;
1354
	    info2.dest_x += num_pixels;
1355
	    sx = 0;
1356
	}
1357
 
1358
	sx = src_x;
1359
	sy++;
1360
	info2.mask_x = info->mask_x;
1361
	info2.mask_y++;
1362
	info2.dest_x = info->dest_x;
1363
	info2.dest_y++;
1364
    }
1365
 
1366
    if (need_src_extension)
1367
	_pixman_image_fini (&extended_src_image);
1368
}
1369
 
1891 serge 1370
/* Use more unrolling for src_0565_0565 because it is typically CPU bound */
1371
static force_inline void
3931 Serge 1372
scaled_nearest_scanline_565_565_SRC (uint16_t *       dst,
1373
				     const uint16_t * src,
1374
				     int32_t          w,
1375
				     pixman_fixed_t   vx,
1376
				     pixman_fixed_t   unit_x,
1377
				     pixman_fixed_t   max_vx,
1378
				     pixman_bool_t    fully_transparent_src)
1891 serge 1379
{
1380
    uint16_t tmp1, tmp2, tmp3, tmp4;
1381
    while ((w -= 4) >= 0)
1382
    {
3931 Serge 1383
	tmp1 = *(src + pixman_fixed_to_int (vx));
1891 serge 1384
	vx += unit_x;
3931 Serge 1385
	tmp2 = *(src + pixman_fixed_to_int (vx));
1891 serge 1386
	vx += unit_x;
3931 Serge 1387
	tmp3 = *(src + pixman_fixed_to_int (vx));
1891 serge 1388
	vx += unit_x;
3931 Serge 1389
	tmp4 = *(src + pixman_fixed_to_int (vx));
1891 serge 1390
	vx += unit_x;
1391
	*dst++ = tmp1;
1392
	*dst++ = tmp2;
1393
	*dst++ = tmp3;
1394
	*dst++ = tmp4;
1395
    }
1396
    if (w & 2)
1397
    {
3931 Serge 1398
	tmp1 = *(src + pixman_fixed_to_int (vx));
1891 serge 1399
	vx += unit_x;
3931 Serge 1400
	tmp2 = *(src + pixman_fixed_to_int (vx));
1891 serge 1401
	vx += unit_x;
1402
	*dst++ = tmp1;
1403
	*dst++ = tmp2;
1404
    }
1405
    if (w & 1)
3931 Serge 1406
	*dst = *(src + pixman_fixed_to_int (vx));
1891 serge 1407
}
1408
 
1409
FAST_NEAREST_MAINLOOP (565_565_cover_SRC,
1410
		       scaled_nearest_scanline_565_565_SRC,
3931 Serge 1411
		       uint16_t, uint16_t, COVER)
1891 serge 1412
FAST_NEAREST_MAINLOOP (565_565_none_SRC,
1413
		       scaled_nearest_scanline_565_565_SRC,
3931 Serge 1414
		       uint16_t, uint16_t, NONE)
1891 serge 1415
FAST_NEAREST_MAINLOOP (565_565_pad_SRC,
1416
		       scaled_nearest_scanline_565_565_SRC,
3931 Serge 1417
		       uint16_t, uint16_t, PAD)
1891 serge 1418
 
1419
static force_inline uint32_t
1420
fetch_nearest (pixman_repeat_t src_repeat,
1421
	       pixman_format_code_t format,
1422
	       uint32_t *src, int x, int src_width)
1423
{
1424
    if (repeat (src_repeat, &x, src_width))
1425
    {
3931 Serge 1426
	if (format == PIXMAN_x8r8g8b8 || format == PIXMAN_x8b8g8r8)
1891 serge 1427
	    return *(src + x) | 0xff000000;
1428
	else
1429
	    return *(src + x);
1430
    }
1431
    else
1432
    {
1433
	return 0;
1434
    }
1435
}
1436
 
1437
static force_inline void
1438
combine_over (uint32_t s, uint32_t *dst)
1439
{
1440
    if (s)
1441
    {
1442
	uint8_t ia = 0xff - (s >> 24);
1443
 
1444
	if (ia)
1445
	    UN8x4_MUL_UN8_ADD_UN8x4 (*dst, ia, s);
1446
	else
1447
	    *dst = s;
1448
    }
1449
}
1450
 
1451
static force_inline void
1452
combine_src (uint32_t s, uint32_t *dst)
1453
{
1454
    *dst = s;
1455
}
1456
 
1457
static void
1458
fast_composite_scaled_nearest (pixman_implementation_t *imp,
3931 Serge 1459
			       pixman_composite_info_t *info)
1891 serge 1460
{
3931 Serge 1461
    PIXMAN_COMPOSITE_ARGS (info);
1891 serge 1462
    uint32_t       *dst_line;
1463
    uint32_t       *src_line;
1464
    int             dst_stride, src_stride;
1465
    int		    src_width, src_height;
1466
    pixman_repeat_t src_repeat;
1467
    pixman_fixed_t unit_x, unit_y;
1468
    pixman_format_code_t src_format;
1469
    pixman_vector_t v;
1470
    pixman_fixed_t vy;
1471
 
3931 Serge 1472
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1891 serge 1473
    /* pass in 0 instead of src_x and src_y because src_x and src_y need to be
1474
     * transformed from destination space to source space
1475
     */
1476
    PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, uint32_t, src_stride, src_line, 1);
1477
 
1478
    /* reference point is the center of the pixel */
1479
    v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2;
1480
    v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2;
1481
    v.vector[2] = pixman_fixed_1;
1482
 
1483
    if (!pixman_transform_point_3d (src_image->common.transform, &v))
1484
	return;
1485
 
1486
    unit_x = src_image->common.transform->matrix[0][0];
1487
    unit_y = src_image->common.transform->matrix[1][1];
1488
 
1489
    /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
1490
    v.vector[0] -= pixman_fixed_e;
1491
    v.vector[1] -= pixman_fixed_e;
1492
 
1493
    src_height = src_image->bits.height;
1494
    src_width = src_image->bits.width;
1495
    src_repeat = src_image->common.repeat;
1496
    src_format = src_image->bits.format;
1497
 
1498
    vy = v.vector[1];
1499
    while (height--)
1500
    {
1501
        pixman_fixed_t vx = v.vector[0];
1502
	int y = pixman_fixed_to_int (vy);
1503
	uint32_t *dst = dst_line;
1504
 
1505
	dst_line += dst_stride;
1506
 
1507
        /* adjust the y location by a unit vector in the y direction
1508
         * this is equivalent to transforming y+1 of the destination point to source space */
1509
        vy += unit_y;
1510
 
1511
	if (!repeat (src_repeat, &y, src_height))
1512
	{
1513
	    if (op == PIXMAN_OP_SRC)
1514
		memset (dst, 0, sizeof (*dst) * width);
1515
	}
1516
	else
1517
	{
1518
	    int w = width;
1519
 
1520
	    uint32_t *src = src_line + y * src_stride;
1521
 
1522
	    while (w >= 2)
1523
	    {
1524
		uint32_t s1, s2;
1525
		int x1, x2;
1526
 
1527
		x1 = pixman_fixed_to_int (vx);
1528
		vx += unit_x;
1529
 
1530
		x2 = pixman_fixed_to_int (vx);
1531
		vx += unit_x;
1532
 
1533
		w -= 2;
1534
 
1535
		s1 = fetch_nearest (src_repeat, src_format, src, x1, src_width);
1536
		s2 = fetch_nearest (src_repeat, src_format, src, x2, src_width);
1537
 
1538
		if (op == PIXMAN_OP_OVER)
1539
		{
1540
		    combine_over (s1, dst++);
1541
		    combine_over (s2, dst++);
1542
		}
1543
		else
1544
		{
1545
		    combine_src (s1, dst++);
1546
		    combine_src (s2, dst++);
1547
		}
1548
	    }
1549
 
1550
	    while (w--)
1551
	    {
1552
		uint32_t s;
1553
		int x;
1554
 
1555
		x = pixman_fixed_to_int (vx);
1556
		vx += unit_x;
1557
 
1558
		s = fetch_nearest (src_repeat, src_format, src, x, src_width);
1559
 
1560
		if (op == PIXMAN_OP_OVER)
1561
		    combine_over (s, dst++);
1562
		else
1563
		    combine_src (s, dst++);
1564
	    }
1565
	}
1566
    }
1567
}
1568
 
3931 Serge 1569
#define CACHE_LINE_SIZE 64
1570
 
1571
#define FAST_SIMPLE_ROTATE(suffix, pix_type)                                  \
1572
                                                                              \
1573
static void                                                                   \
1574
blt_rotated_90_trivial_##suffix (pix_type       *dst,                         \
1575
				 int             dst_stride,                  \
1576
				 const pix_type *src,                         \
1577
				 int             src_stride,                  \
1578
				 int             w,                           \
1579
				 int             h)                           \
1580
{                                                                             \
1581
    int x, y;                                                                 \
1582
    for (y = 0; y < h; y++)                                                   \
1583
    {                                                                         \
1584
	const pix_type *s = src + (h - y - 1);                                \
1585
	pix_type *d = dst + dst_stride * y;                                   \
1586
	for (x = 0; x < w; x++)                                               \
1587
	{                                                                     \
1588
	    *d++ = *s;                                                        \
1589
	    s += src_stride;                                                  \
1590
	}                                                                     \
1591
    }                                                                         \
1592
}                                                                             \
1593
                                                                              \
1594
static void                                                                   \
1595
blt_rotated_270_trivial_##suffix (pix_type       *dst,                        \
1596
				  int             dst_stride,                 \
1597
				  const pix_type *src,                        \
1598
				  int             src_stride,                 \
1599
				  int             w,                          \
1600
				  int             h)                          \
1601
{                                                                             \
1602
    int x, y;                                                                 \
1603
    for (y = 0; y < h; y++)                                                   \
1604
    {                                                                         \
1605
	const pix_type *s = src + src_stride * (w - 1) + y;                   \
1606
	pix_type *d = dst + dst_stride * y;                                   \
1607
	for (x = 0; x < w; x++)                                               \
1608
	{                                                                     \
1609
	    *d++ = *s;                                                        \
1610
	    s -= src_stride;                                                  \
1611
	}                                                                     \
1612
    }                                                                         \
1613
}                                                                             \
1614
                                                                              \
1615
static void                                                                   \
1616
blt_rotated_90_##suffix (pix_type       *dst,                                 \
1617
			 int             dst_stride,                          \
1618
			 const pix_type *src,                                 \
1619
			 int             src_stride,                          \
1620
			 int             W,                                   \
1621
			 int             H)                                   \
1622
{                                                                             \
1623
    int x;                                                                    \
1624
    int leading_pixels = 0, trailing_pixels = 0;                              \
1625
    const int TILE_SIZE = CACHE_LINE_SIZE / sizeof(pix_type);                 \
1626
                                                                              \
1627
    /*                                                                        \
1628
     * split processing into handling destination as TILE_SIZExH cache line   \
1629
     * aligned vertical stripes (optimistically assuming that destination     \
1630
     * stride is a multiple of cache line, if not - it will be just a bit     \
1631
     * slower)                                                                \
1632
     */                                                                       \
1633
                                                                              \
1634
    if ((uintptr_t)dst & (CACHE_LINE_SIZE - 1))                               \
1635
    {                                                                         \
1636
	leading_pixels = TILE_SIZE - (((uintptr_t)dst &                       \
1637
			    (CACHE_LINE_SIZE - 1)) / sizeof(pix_type));       \
1638
	if (leading_pixels > W)                                               \
1639
	    leading_pixels = W;                                               \
1640
                                                                              \
1641
	/* unaligned leading part NxH (where N < TILE_SIZE) */                \
1642
	blt_rotated_90_trivial_##suffix (                                     \
1643
	    dst,                                                              \
1644
	    dst_stride,                                                       \
1645
	    src,                                                              \
1646
	    src_stride,                                                       \
1647
	    leading_pixels,                                                   \
1648
	    H);                                                               \
1649
	                                                                      \
1650
	dst += leading_pixels;                                                \
1651
	src += leading_pixels * src_stride;                                   \
1652
	W -= leading_pixels;                                                  \
1653
    }                                                                         \
1654
                                                                              \
1655
    if ((uintptr_t)(dst + W) & (CACHE_LINE_SIZE - 1))                         \
1656
    {                                                                         \
1657
	trailing_pixels = (((uintptr_t)(dst + W) &                            \
1658
			    (CACHE_LINE_SIZE - 1)) / sizeof(pix_type));       \
1659
	if (trailing_pixels > W)                                              \
1660
	    trailing_pixels = W;                                              \
1661
	W -= trailing_pixels;                                                 \
1662
    }                                                                         \
1663
                                                                              \
1664
    for (x = 0; x < W; x += TILE_SIZE)                                        \
1665
    {                                                                         \
1666
	/* aligned middle part TILE_SIZExH */                                 \
1667
	blt_rotated_90_trivial_##suffix (                                     \
1668
	    dst + x,                                                          \
1669
	    dst_stride,                                                       \
1670
	    src + src_stride * x,                                             \
1671
	    src_stride,                                                       \
1672
	    TILE_SIZE,                                                        \
1673
	    H);                                                               \
1674
    }                                                                         \
1675
                                                                              \
1676
    if (trailing_pixels)                                                      \
1677
    {                                                                         \
1678
	/* unaligned trailing part NxH (where N < TILE_SIZE) */               \
1679
	blt_rotated_90_trivial_##suffix (                                     \
1680
	    dst + W,                                                          \
1681
	    dst_stride,                                                       \
1682
	    src + W * src_stride,                                             \
1683
	    src_stride,                                                       \
1684
	    trailing_pixels,                                                  \
1685
	    H);                                                               \
1686
    }                                                                         \
1687
}                                                                             \
1688
                                                                              \
1689
static void                                                                   \
1690
blt_rotated_270_##suffix (pix_type       *dst,                                \
1691
			  int             dst_stride,                         \
1692
			  const pix_type *src,                                \
1693
			  int             src_stride,                         \
1694
			  int             W,                                  \
1695
			  int             H)                                  \
1696
{                                                                             \
1697
    int x;                                                                    \
1698
    int leading_pixels = 0, trailing_pixels = 0;                              \
1699
    const int TILE_SIZE = CACHE_LINE_SIZE / sizeof(pix_type);                 \
1700
                                                                              \
1701
    /*                                                                        \
1702
     * split processing into handling destination as TILE_SIZExH cache line   \
1703
     * aligned vertical stripes (optimistically assuming that destination     \
1704
     * stride is a multiple of cache line, if not - it will be just a bit     \
1705
     * slower)                                                                \
1706
     */                                                                       \
1707
                                                                              \
1708
    if ((uintptr_t)dst & (CACHE_LINE_SIZE - 1))                               \
1709
    {                                                                         \
1710
	leading_pixels = TILE_SIZE - (((uintptr_t)dst &                       \
1711
			    (CACHE_LINE_SIZE - 1)) / sizeof(pix_type));       \
1712
	if (leading_pixels > W)                                               \
1713
	    leading_pixels = W;                                               \
1714
                                                                              \
1715
	/* unaligned leading part NxH (where N < TILE_SIZE) */                \
1716
	blt_rotated_270_trivial_##suffix (                                    \
1717
	    dst,                                                              \
1718
	    dst_stride,                                                       \
1719
	    src + src_stride * (W - leading_pixels),                          \
1720
	    src_stride,                                                       \
1721
	    leading_pixels,                                                   \
1722
	    H);                                                               \
1723
	                                                                      \
1724
	dst += leading_pixels;                                                \
1725
	W -= leading_pixels;                                                  \
1726
    }                                                                         \
1727
                                                                              \
1728
    if ((uintptr_t)(dst + W) & (CACHE_LINE_SIZE - 1))                         \
1729
    {                                                                         \
1730
	trailing_pixels = (((uintptr_t)(dst + W) &                            \
1731
			    (CACHE_LINE_SIZE - 1)) / sizeof(pix_type));       \
1732
	if (trailing_pixels > W)                                              \
1733
	    trailing_pixels = W;                                              \
1734
	W -= trailing_pixels;                                                 \
1735
	src += trailing_pixels * src_stride;                                  \
1736
    }                                                                         \
1737
                                                                              \
1738
    for (x = 0; x < W; x += TILE_SIZE)                                        \
1739
    {                                                                         \
1740
	/* aligned middle part TILE_SIZExH */                                 \
1741
	blt_rotated_270_trivial_##suffix (                                    \
1742
	    dst + x,                                                          \
1743
	    dst_stride,                                                       \
1744
	    src + src_stride * (W - x - TILE_SIZE),                           \
1745
	    src_stride,                                                       \
1746
	    TILE_SIZE,                                                        \
1747
	    H);                                                               \
1748
    }                                                                         \
1749
                                                                              \
1750
    if (trailing_pixels)                                                      \
1751
    {                                                                         \
1752
	/* unaligned trailing part NxH (where N < TILE_SIZE) */               \
1753
	blt_rotated_270_trivial_##suffix (                                    \
1754
	    dst + W,                                                          \
1755
	    dst_stride,                                                       \
1756
	    src - trailing_pixels * src_stride,                               \
1757
	    src_stride,                                                       \
1758
	    trailing_pixels,                                                  \
1759
	    H);                                                               \
1760
    }                                                                         \
1761
}                                                                             \
1762
                                                                              \
1763
static void                                                                   \
1764
fast_composite_rotate_90_##suffix (pixman_implementation_t *imp,              \
1765
				   pixman_composite_info_t *info)	      \
1766
{									      \
1767
    PIXMAN_COMPOSITE_ARGS (info);					      \
1768
    pix_type       *dst_line;						      \
1769
    pix_type       *src_line;                                                 \
1770
    int             dst_stride, src_stride;                                   \
1771
    int             src_x_t, src_y_t;                                         \
1772
                                                                              \
1773
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, pix_type,              \
1774
			   dst_stride, dst_line, 1);                          \
1775
    src_x_t = -src_y + pixman_fixed_to_int (                                  \
1776
				src_image->common.transform->matrix[0][2] +   \
1777
				pixman_fixed_1 / 2 - pixman_fixed_e) - height;\
1778
    src_y_t = src_x + pixman_fixed_to_int (                                   \
1779
				src_image->common.transform->matrix[1][2] +   \
1780
				pixman_fixed_1 / 2 - pixman_fixed_e);         \
1781
    PIXMAN_IMAGE_GET_LINE (src_image, src_x_t, src_y_t, pix_type,             \
1782
			   src_stride, src_line, 1);                          \
1783
    blt_rotated_90_##suffix (dst_line, dst_stride, src_line, src_stride,      \
1784
			     width, height);                                  \
1785
}                                                                             \
1786
                                                                              \
1787
static void                                                                   \
1788
fast_composite_rotate_270_##suffix (pixman_implementation_t *imp,             \
1789
				    pixman_composite_info_t *info)            \
1790
{                                                                             \
1791
    PIXMAN_COMPOSITE_ARGS (info);					      \
1792
    pix_type       *dst_line;						      \
1793
    pix_type       *src_line;                                                 \
1794
    int             dst_stride, src_stride;                                   \
1795
    int             src_x_t, src_y_t;                                         \
1796
                                                                              \
1797
    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, pix_type,              \
1798
			   dst_stride, dst_line, 1);                          \
1799
    src_x_t = src_y + pixman_fixed_to_int (                                   \
1800
				src_image->common.transform->matrix[0][2] +   \
1801
				pixman_fixed_1 / 2 - pixman_fixed_e);         \
1802
    src_y_t = -src_x + pixman_fixed_to_int (                                  \
1803
				src_image->common.transform->matrix[1][2] +   \
1804
				pixman_fixed_1 / 2 - pixman_fixed_e) - width; \
1805
    PIXMAN_IMAGE_GET_LINE (src_image, src_x_t, src_y_t, pix_type,             \
1806
			   src_stride, src_line, 1);                          \
1807
    blt_rotated_270_##suffix (dst_line, dst_stride, src_line, src_stride,     \
1808
			      width, height);                                 \
1809
}
1810
 
1811
FAST_SIMPLE_ROTATE (8, uint8_t)
1812
FAST_SIMPLE_ROTATE (565, uint16_t)
1813
FAST_SIMPLE_ROTATE (8888, uint32_t)
1814
 
1891 serge 1815
static const pixman_fast_path_t c_fast_paths[] =
1816
{
1817
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565),
1818
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565),
1819
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888),
1820
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888),
1821
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888),
1822
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888),
1823
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888),
1824
    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888),
1825
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888),
1826
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888),
1827
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888),
1828
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888),
1829
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5,   fast_composite_over_n_1_0565),
1830
    PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5,   fast_composite_over_n_1_0565),
1831
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca),
1832
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca),
1833
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca),
1834
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca),
1835
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca),
1836
    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca),
1837
    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888),
1838
    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888),
1839
    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888),
1840
    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888),
1841
    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888),
1842
    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888),
1843
    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565),
1844
    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888),
1845
    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888),
1846
    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565),
3931 Serge 1847
    PIXMAN_STD_FAST_PATH (ADD, r5g6b5, null, r5g6b5, fast_composite_add_0565_0565),
1848
    PIXMAN_STD_FAST_PATH (ADD, b5g6r5, null, b5g6r5, fast_composite_add_0565_0565),
1891 serge 1849
    PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888),
1850
    PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888),
1851
    PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8_8),
3931 Serge 1852
    PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1_1),
1891 serge 1853
    PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca),
1854
    PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8),
1855
    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill),
1856
    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill),
1857
    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill),
1858
    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill),
3931 Serge 1859
    PIXMAN_STD_FAST_PATH (SRC, solid, null, a1, fast_composite_solid_fill),
1891 serge 1860
    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill),
1861
    PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill),
1862
    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, fast_composite_src_x888_8888),
1863
    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, fast_composite_src_x888_8888),
1864
    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
1865
    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, fast_composite_src_memcpy),
1866
    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy),
1867
    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
1868
    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, fast_composite_src_memcpy),
1869
    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy),
1870
    PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8x8, fast_composite_src_memcpy),
1871
    PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8a8, fast_composite_src_memcpy),
1872
    PIXMAN_STD_FAST_PATH (SRC, b8g8r8x8, null, b8g8r8x8, fast_composite_src_memcpy),
1873
    PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, fast_composite_src_memcpy),
1874
    PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, fast_composite_src_memcpy),
1875
    PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, fast_composite_src_memcpy),
1876
    PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, b8g8r8, fast_composite_src_memcpy),
1877
    PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
1878
    PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy),
1879
    PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, fast_composite_src_memcpy),
1880
    PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8),
1881
    PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8),
1882
 
1883
    SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, 8888_8888),
1884
    SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, 8888_8888),
1885
    SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, 8888_8888),
1886
    SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, 8888_8888),
1887
 
1888
    SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, 8888_8888),
1889
    SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, 8888_8888),
1890
 
1891
    SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, 8888_565),
1892
    SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, 8888_565),
1893
 
1894
    SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, 565_565),
1895
 
3931 Serge 1896
    SIMPLE_NEAREST_FAST_PATH_COVER (SRC, x8r8g8b8, a8r8g8b8, x888_8888),
1897
    SIMPLE_NEAREST_FAST_PATH_COVER (SRC, x8b8g8r8, a8b8g8r8, x888_8888),
1898
    SIMPLE_NEAREST_FAST_PATH_PAD (SRC, x8r8g8b8, a8r8g8b8, x888_8888),
1899
    SIMPLE_NEAREST_FAST_PATH_PAD (SRC, x8b8g8r8, a8b8g8r8, x888_8888),
1900
    SIMPLE_NEAREST_FAST_PATH_NORMAL (SRC, x8r8g8b8, a8r8g8b8, x888_8888),
1901
    SIMPLE_NEAREST_FAST_PATH_NORMAL (SRC, x8b8g8r8, a8b8g8r8, x888_8888),
1902
 
1891 serge 1903
    SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, 8888_8888),
1904
    SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, 8888_8888),
1905
    SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, 8888_8888),
1906
    SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, 8888_8888),
1907
 
1908
    SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, 8888_565),
1909
 
1910
#define NEAREST_FAST_PATH(op,s,d)		\
1911
    {   PIXMAN_OP_ ## op,			\
1912
	PIXMAN_ ## s, SCALED_NEAREST_FLAGS,	\
1913
	PIXMAN_null, 0,				\
1914
	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,	\
1915
	fast_composite_scaled_nearest,		\
1916
    }
1917
 
1918
    NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8),
1919
    NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8),
1920
    NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8),
1921
    NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8),
1922
 
1923
    NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8),
1924
    NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8),
1925
    NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8),
1926
    NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8),
1927
 
1928
    NEAREST_FAST_PATH (OVER, x8r8g8b8, x8r8g8b8),
1929
    NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8),
1930
    NEAREST_FAST_PATH (OVER, x8b8g8r8, x8b8g8r8),
1931
    NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8),
1932
 
1933
    NEAREST_FAST_PATH (OVER, x8r8g8b8, a8r8g8b8),
1934
    NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8),
1935
    NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8),
1936
    NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8),
1937
 
3931 Serge 1938
#define SIMPLE_ROTATE_FLAGS(angle)					  \
1939
    (FAST_PATH_ROTATE_ ## angle ## _TRANSFORM	|			  \
1940
     FAST_PATH_NEAREST_FILTER			|			  \
1941
     FAST_PATH_SAMPLES_COVER_CLIP_NEAREST	|			  \
1942
     FAST_PATH_STANDARD_FLAGS)
1943
 
1944
#define SIMPLE_ROTATE_FAST_PATH(op,s,d,suffix)				  \
1945
    {   PIXMAN_OP_ ## op,						  \
1946
	PIXMAN_ ## s, SIMPLE_ROTATE_FLAGS (90),				  \
1947
	PIXMAN_null, 0,							  \
1948
	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				  \
1949
	fast_composite_rotate_90_##suffix,				  \
1950
    },									  \
1951
    {   PIXMAN_OP_ ## op,						  \
1952
	PIXMAN_ ## s, SIMPLE_ROTATE_FLAGS (270),			  \
1953
	PIXMAN_null, 0,							  \
1954
	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				  \
1955
	fast_composite_rotate_270_##suffix,				  \
1956
    }
1957
 
1958
    SIMPLE_ROTATE_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, 8888),
1959
    SIMPLE_ROTATE_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, 8888),
1960
    SIMPLE_ROTATE_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, 8888),
1961
    SIMPLE_ROTATE_FAST_PATH (SRC, r5g6b5, r5g6b5, 565),
1962
    SIMPLE_ROTATE_FAST_PATH (SRC, a8, a8, 8),
1963
 
1964
    /* Simple repeat fast path entry. */
1965
    {	PIXMAN_OP_any,
1966
	PIXMAN_any,
1967
	(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | FAST_PATH_BITS_IMAGE |
1968
	 FAST_PATH_NORMAL_REPEAT),
1969
	PIXMAN_any, 0,
1970
	PIXMAN_any, FAST_PATH_STD_DEST_FLAGS,
1971
	fast_composite_tiled_repeat
1972
    },
1973
 
1891 serge 1974
    {   PIXMAN_OP_NONE	},
1975
};
1976
 
3931 Serge 1977
#ifdef WORDS_BIGENDIAN
1978
#define A1_FILL_MASK(n, offs) (((1U << (n)) - 1) << (32 - (offs) - (n)))
1979
#else
1980
#define A1_FILL_MASK(n, offs) (((1U << (n)) - 1) << (offs))
1981
#endif
1982
 
1983
static force_inline void
1984
pixman_fill1_line (uint32_t *dst, int offs, int width, int v)
1985
{
1986
    if (offs)
1987
    {
1988
	int leading_pixels = 32 - offs;
1989
	if (leading_pixels >= width)
1990
	{
1991
	    if (v)
1992
		*dst |= A1_FILL_MASK (width, offs);
1993
	    else
1994
		*dst &= ~A1_FILL_MASK (width, offs);
1995
	    return;
1996
	}
1997
	else
1998
	{
1999
	    if (v)
2000
		*dst++ |= A1_FILL_MASK (leading_pixels, offs);
2001
	    else
2002
		*dst++ &= ~A1_FILL_MASK (leading_pixels, offs);
2003
	    width -= leading_pixels;
2004
	}
2005
    }
2006
    while (width >= 32)
2007
    {
2008
	if (v)
2009
	    *dst++ = 0xFFFFFFFF;
2010
	else
2011
	    *dst++ = 0;
2012
	width -= 32;
2013
    }
2014
    if (width > 0)
2015
    {
2016
	if (v)
2017
	    *dst |= A1_FILL_MASK (width, 0);
2018
	else
2019
	    *dst &= ~A1_FILL_MASK (width, 0);
2020
    }
2021
}
2022
 
1891 serge 2023
static void
3931 Serge 2024
pixman_fill1 (uint32_t *bits,
2025
              int       stride,
2026
              int       x,
2027
              int       y,
2028
              int       width,
2029
              int       height,
2030
              uint32_t  filler)
2031
{
2032
    uint32_t *dst = bits + y * stride + (x >> 5);
2033
    int offs = x & 31;
2034
 
2035
    if (filler & 1)
2036
    {
2037
	while (height--)
2038
	{
2039
	    pixman_fill1_line (dst, offs, width, 1);
2040
	    dst += stride;
2041
	}
2042
    }
2043
    else
2044
    {
2045
	while (height--)
2046
	{
2047
	    pixman_fill1_line (dst, offs, width, 0);
2048
	    dst += stride;
2049
	}
2050
    }
2051
}
2052
 
2053
static void
1891 serge 2054
pixman_fill8 (uint32_t *bits,
2055
              int       stride,
2056
              int       x,
2057
              int       y,
2058
              int       width,
2059
              int       height,
3931 Serge 2060
              uint32_t  filler)
1891 serge 2061
{
2062
    int byte_stride = stride * (int) sizeof (uint32_t);
2063
    uint8_t *dst = (uint8_t *) bits;
3931 Serge 2064
    uint8_t v = filler & 0xff;
1891 serge 2065
    int i;
2066
 
2067
    dst = dst + y * byte_stride + x;
2068
 
2069
    while (height--)
2070
    {
2071
	for (i = 0; i < width; ++i)
2072
	    dst[i] = v;
2073
 
2074
	dst += byte_stride;
2075
    }
2076
}
2077
 
2078
static void
2079
pixman_fill16 (uint32_t *bits,
2080
               int       stride,
2081
               int       x,
2082
               int       y,
2083
               int       width,
2084
               int       height,
3931 Serge 2085
               uint32_t  filler)
1891 serge 2086
{
2087
    int short_stride =
2088
	(stride * (int)sizeof (uint32_t)) / (int)sizeof (uint16_t);
2089
    uint16_t *dst = (uint16_t *)bits;
3931 Serge 2090
    uint16_t v = filler & 0xffff;
1891 serge 2091
    int i;
2092
 
2093
    dst = dst + y * short_stride + x;
2094
 
2095
    while (height--)
2096
    {
2097
	for (i = 0; i < width; ++i)
2098
	    dst[i] = v;
2099
 
2100
	dst += short_stride;
2101
    }
2102
}
2103
 
2104
static void
2105
pixman_fill32 (uint32_t *bits,
2106
               int       stride,
2107
               int       x,
2108
               int       y,
2109
               int       width,
2110
               int       height,
3931 Serge 2111
               uint32_t  filler)
1891 serge 2112
{
2113
    int i;
2114
 
2115
    bits = bits + y * stride + x;
2116
 
2117
    while (height--)
2118
    {
2119
	for (i = 0; i < width; ++i)
3931 Serge 2120
	    bits[i] = filler;
1891 serge 2121
 
2122
	bits += stride;
2123
    }
2124
}
2125
 
2126
static pixman_bool_t
2127
fast_path_fill (pixman_implementation_t *imp,
2128
                uint32_t *               bits,
2129
                int                      stride,
2130
                int                      bpp,
2131
                int                      x,
2132
                int                      y,
2133
                int                      width,
2134
                int                      height,
3931 Serge 2135
                uint32_t		 filler)
1891 serge 2136
{
2137
    switch (bpp)
2138
    {
3931 Serge 2139
    case 1:
2140
	pixman_fill1 (bits, stride, x, y, width, height, filler);
2141
	break;
2142
 
1891 serge 2143
    case 8:
3931 Serge 2144
	pixman_fill8 (bits, stride, x, y, width, height, filler);
1891 serge 2145
	break;
2146
 
2147
    case 16:
3931 Serge 2148
	pixman_fill16 (bits, stride, x, y, width, height, filler);
1891 serge 2149
	break;
2150
 
2151
    case 32:
3931 Serge 2152
	pixman_fill32 (bits, stride, x, y, width, height, filler);
1891 serge 2153
	break;
2154
 
2155
    default:
3931 Serge 2156
	return FALSE;
1891 serge 2157
    }
2158
 
2159
    return TRUE;
2160
}
2161
 
3931 Serge 2162
/*****************************************************************************/
2163
 
2164
static uint32_t *
2165
fast_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask)
2166
{
2167
    int32_t w = iter->width;
2168
    uint32_t *dst = iter->buffer;
2169
    const uint16_t *src = (const uint16_t *)iter->bits;
2170
 
2171
    iter->bits += iter->stride;
2172
 
2173
    /* Align the source buffer at 4 bytes boundary */
2174
    if (w > 0 && ((uintptr_t)src & 3))
2175
    {
2176
	*dst++ = convert_0565_to_8888 (*src++);
2177
	w--;
2178
    }
2179
    /* Process two pixels per iteration */
2180
    while ((w -= 2) >= 0)
2181
    {
2182
	uint32_t sr, sb, sg, t0, t1;
2183
	uint32_t s = *(const uint32_t *)src;
2184
	src += 2;
2185
	sr = (s >> 8) & 0x00F800F8;
2186
	sb = (s << 3) & 0x00F800F8;
2187
	sg = (s >> 3) & 0x00FC00FC;
2188
	sr |= sr >> 5;
2189
	sb |= sb >> 5;
2190
	sg |= sg >> 6;
2191
	t0 = ((sr << 16) & 0x00FF0000) | ((sg << 8) & 0x0000FF00) |
2192
	     (sb & 0xFF) | 0xFF000000;
2193
	t1 = (sr & 0x00FF0000) | ((sg >> 8) & 0x0000FF00) |
2194
	     (sb >> 16) | 0xFF000000;
2195
#ifdef WORDS_BIGENDIAN
2196
	*dst++ = t1;
2197
	*dst++ = t0;
2198
#else
2199
	*dst++ = t0;
2200
	*dst++ = t1;
2201
#endif
2202
    }
2203
    if (w & 1)
2204
    {
2205
	*dst = convert_0565_to_8888 (*src);
2206
    }
2207
 
2208
    return iter->buffer;
2209
}
2210
 
2211
static uint32_t *
2212
fast_dest_fetch_noop (pixman_iter_t *iter, const uint32_t *mask)
2213
{
2214
    iter->bits += iter->stride;
2215
    return iter->buffer;
2216
}
2217
 
2218
/* Helper function for a workaround, which tries to ensure that 0x1F001F
2219
 * constant is always allocated in a register on RISC architectures.
2220
 */
2221
static force_inline uint32_t
2222
convert_8888_to_0565_workaround (uint32_t s, uint32_t x1F001F)
2223
{
2224
    uint32_t a, b;
2225
    a = (s >> 3) & x1F001F;
2226
    b = s & 0xFC00;
2227
    a |= a >> 5;
2228
    a |= b >> 5;
2229
    return a;
2230
}
2231
 
2232
static void
2233
fast_write_back_r5g6b5 (pixman_iter_t *iter)
2234
{
2235
    int32_t w = iter->width;
2236
    uint16_t *dst = (uint16_t *)(iter->bits - iter->stride);
2237
    const uint32_t *src = iter->buffer;
2238
    /* Workaround to ensure that x1F001F variable is allocated in a register */
2239
    static volatile uint32_t volatile_x1F001F = 0x1F001F;
2240
    uint32_t x1F001F = volatile_x1F001F;
2241
 
2242
    while ((w -= 4) >= 0)
2243
    {
2244
	uint32_t s1 = *src++;
2245
	uint32_t s2 = *src++;
2246
	uint32_t s3 = *src++;
2247
	uint32_t s4 = *src++;
2248
	*dst++ = convert_8888_to_0565_workaround (s1, x1F001F);
2249
	*dst++ = convert_8888_to_0565_workaround (s2, x1F001F);
2250
	*dst++ = convert_8888_to_0565_workaround (s3, x1F001F);
2251
	*dst++ = convert_8888_to_0565_workaround (s4, x1F001F);
2252
    }
2253
    if (w & 2)
2254
    {
2255
	*dst++ = convert_8888_to_0565_workaround (*src++, x1F001F);
2256
	*dst++ = convert_8888_to_0565_workaround (*src++, x1F001F);
2257
    }
2258
    if (w & 1)
2259
    {
2260
	*dst = convert_8888_to_0565_workaround (*src, x1F001F);
2261
    }
2262
}
2263
 
2264
typedef struct
2265
{
2266
    pixman_format_code_t	format;
2267
    pixman_iter_get_scanline_t	get_scanline;
2268
    pixman_iter_write_back_t	write_back;
2269
} fetcher_info_t;
2270
 
2271
static const fetcher_info_t fetchers[] =
2272
{
2273
    { PIXMAN_r5g6b5, fast_fetch_r5g6b5, fast_write_back_r5g6b5 },
2274
    { PIXMAN_null }
2275
};
2276
 
2277
static pixman_bool_t
2278
fast_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
2279
{
2280
    pixman_image_t *image = iter->image;
2281
 
2282
#define FLAGS								\
2283
    (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |		\
2284
     FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
2285
 
2286
    if ((iter->iter_flags & ITER_NARROW)			&&
2287
	(iter->image_flags & FLAGS) == FLAGS)
2288
    {
2289
	const fetcher_info_t *f;
2290
 
2291
	for (f = &fetchers[0]; f->format != PIXMAN_null; f++)
2292
	{
2293
	    if (image->common.extended_format_code == f->format)
2294
	    {
2295
		uint8_t *b = (uint8_t *)image->bits.bits;
2296
		int s = image->bits.rowstride * 4;
2297
 
2298
		iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8;
2299
		iter->stride = s;
2300
 
2301
		iter->get_scanline = f->get_scanline;
2302
		return TRUE;
2303
	    }
2304
	}
2305
    }
2306
 
2307
    return FALSE;
2308
}
2309
 
2310
static pixman_bool_t
2311
fast_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
2312
{
2313
    pixman_image_t *image = iter->image;
2314
 
2315
    if ((iter->iter_flags & ITER_NARROW)		&&
2316
	(iter->image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS)
2317
    {
2318
	const fetcher_info_t *f;
2319
 
2320
	for (f = &fetchers[0]; f->format != PIXMAN_null; f++)
2321
	{
2322
	    if (image->common.extended_format_code == f->format)
2323
	    {
2324
		uint8_t *b = (uint8_t *)image->bits.bits;
2325
		int s = image->bits.rowstride * 4;
2326
 
2327
		iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8;
2328
		iter->stride = s;
2329
 
2330
		if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
2331
		    (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
2332
		{
2333
		    iter->get_scanline = fast_dest_fetch_noop;
2334
		}
2335
		else
2336
		{
2337
		    iter->get_scanline = f->get_scanline;
2338
		}
2339
		iter->write_back = f->write_back;
2340
		return TRUE;
2341
	    }
2342
	}
2343
    }
2344
    return FALSE;
2345
}
2346
 
2347
 
1891 serge 2348
pixman_implementation_t *
3931 Serge 2349
_pixman_implementation_create_fast_path (pixman_implementation_t *fallback)
1891 serge 2350
{
3931 Serge 2351
    pixman_implementation_t *imp = _pixman_implementation_create (fallback, c_fast_paths);
1891 serge 2352
 
2353
    imp->fill = fast_path_fill;
3931 Serge 2354
    imp->src_iter_init = fast_src_iter_init;
2355
    imp->dest_iter_init = fast_dest_iter_init;
1891 serge 2356
 
2357
    return imp;
2358
}