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