Split fill implementations out in the implementations
[profile/ivi/pixman.git] / pixman / pixman-utils.c
1 /*
2  * Copyright © 2000 SuSE, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of SuSE not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  SuSE makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
16  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Author:  Keith Packard, SuSE, Inc.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29
30 #include "pixman-private.h"
31 #include "pixman-mmx.h"
32 #include "pixman-sse2.h"
33
34 /*
35  * Compute the smallest value no less than y which is on a
36  * grid row
37  */
38
39 PIXMAN_EXPORT pixman_fixed_t
40 pixman_sample_ceil_y (pixman_fixed_t y, int n)
41 {
42     pixman_fixed_t   f = pixman_fixed_frac(y);
43     pixman_fixed_t   i = pixman_fixed_floor(y);
44
45     f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
46     if (f > Y_FRAC_LAST(n))
47     {
48         if (pixman_fixed_to_int(i) == 0x7fff)
49         {
50             f = 0xffff; /* saturate */
51         } else {
52             f = Y_FRAC_FIRST(n);
53             i += pixman_fixed_1;
54         }
55     }
56     return (i | f);
57 }
58
59 #define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
60
61 /*
62  * Compute the largest value no greater than y which is on a
63  * grid row
64  */
65 PIXMAN_EXPORT pixman_fixed_t
66 pixman_sample_floor_y (pixman_fixed_t y, int n)
67 {
68     pixman_fixed_t   f = pixman_fixed_frac(y);
69     pixman_fixed_t   i = pixman_fixed_floor (y);
70
71     f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
72     if (f < Y_FRAC_FIRST(n))
73     {
74         if (pixman_fixed_to_int(i) == 0x8000)
75         {
76             f = 0; /* saturate */
77         } else {
78             f = Y_FRAC_LAST(n);
79             i -= pixman_fixed_1;
80         }
81     }
82     return (i | f);
83 }
84
85 /*
86  * Step an edge by any amount (including negative values)
87  */
88 PIXMAN_EXPORT void
89 pixman_edge_step (pixman_edge_t *e, int n)
90 {
91     pixman_fixed_48_16_t        ne;
92
93     e->x += n * e->stepx;
94
95     ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
96
97     if (n >= 0)
98     {
99         if (ne > 0)
100         {
101             int nx = (ne + e->dy - 1) / e->dy;
102             e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
103             e->x += nx * e->signdx;
104         }
105     }
106     else
107     {
108         if (ne <= -e->dy)
109         {
110             int nx = (-ne) / e->dy;
111             e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
112             e->x -= nx * e->signdx;
113         }
114     }
115 }
116
117 /*
118  * A private routine to initialize the multi-step
119  * elements of an edge structure
120  */
121 static void
122 _pixman_edge_multi_init (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
123 {
124     pixman_fixed_t      stepx;
125     pixman_fixed_48_16_t        ne;
126
127     ne = n * (pixman_fixed_48_16_t) e->dx;
128     stepx = n * e->stepx;
129     if (ne > 0)
130     {
131         int nx = ne / e->dy;
132         ne -= nx * e->dy;
133         stepx += nx * e->signdx;
134     }
135     *dx_p = ne;
136     *stepx_p = stepx;
137 }
138
139 /*
140  * Initialize one edge structure given the line endpoints and a
141  * starting y value
142  */
143 PIXMAN_EXPORT void
144 pixman_edge_init (pixman_edge_t *e,
145                   int           n,
146                   pixman_fixed_t                y_start,
147                   pixman_fixed_t                x_top,
148                   pixman_fixed_t                y_top,
149                   pixman_fixed_t                x_bot,
150                   pixman_fixed_t                y_bot)
151 {
152     pixman_fixed_t      dx, dy;
153
154     e->x = x_top;
155     e->e = 0;
156     dx = x_bot - x_top;
157     dy = y_bot - y_top;
158     e->dy = dy;
159     e->dx = 0;
160     if (dy)
161     {
162         if (dx >= 0)
163         {
164             e->signdx = 1;
165             e->stepx = dx / dy;
166             e->dx = dx % dy;
167             e->e = -dy;
168         }
169         else
170         {
171             e->signdx = -1;
172             e->stepx = -(-dx / dy);
173             e->dx = -dx % dy;
174             e->e = 0;
175         }
176
177         _pixman_edge_multi_init (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
178         _pixman_edge_multi_init (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
179     }
180     pixman_edge_step (e, y_start - y_top);
181 }
182
183 /*
184  * Initialize one edge structure given a line, starting y value
185  * and a pixel offset for the line
186  */
187 PIXMAN_EXPORT void
188 pixman_line_fixed_edge_init (pixman_edge_t *e,
189                              int            n,
190                              pixman_fixed_t         y,
191                              const pixman_line_fixed_t *line,
192                              int            x_off,
193                              int            y_off)
194 {
195     pixman_fixed_t      x_off_fixed = pixman_int_to_fixed(x_off);
196     pixman_fixed_t      y_off_fixed = pixman_int_to_fixed(y_off);
197     const pixman_point_fixed_t *top, *bot;
198
199     if (line->p1.y <= line->p2.y)
200     {
201         top = &line->p1;
202         bot = &line->p2;
203     }
204     else
205     {
206         top = &line->p2;
207         bot = &line->p1;
208     }
209     pixman_edge_init (e, n, y,
210                     top->x + x_off_fixed,
211                     top->y + y_off_fixed,
212                     bot->x + x_off_fixed,
213                     bot->y + y_off_fixed);
214 }
215
216 pixman_bool_t
217 pixman_multiply_overflows_int (unsigned int a,
218                                unsigned int b)
219 {
220     return a >= INT32_MAX / b;
221 }
222
223 pixman_bool_t
224 pixman_addition_overflows_int (unsigned int a,
225                                unsigned int b)
226 {
227     return a > INT32_MAX - b;
228 }
229
230 void *
231 pixman_malloc_ab(unsigned int a,
232                  unsigned int b)
233 {
234     if (a >= INT32_MAX / b)
235         return NULL;
236
237     return malloc (a * b);
238 }
239
240 void *
241 pixman_malloc_abc (unsigned int a,
242                    unsigned int b,
243                    unsigned int c)
244 {
245     if (a >= INT32_MAX / b)
246         return NULL;
247     else if (a * b >= INT32_MAX / c)
248         return NULL;
249     else
250         return malloc (a * b * c);
251 }
252
253
254 /**
255  * pixman_version:
256  *
257  * Returns the version of the pixman library encoded in a single
258  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
259  * later versions compare greater than earlier versions.
260  *
261  * A run-time comparison to check that pixman's version is greater than
262  * or equal to version X.Y.Z could be performed as follows:
263  *
264  * <informalexample><programlisting>
265  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
266  * </programlisting></informalexample>
267  *
268  * See also pixman_version_string() as well as the compile-time
269  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
270  *
271  * Return value: the encoded version.
272  **/
273 PIXMAN_EXPORT int
274 pixman_version (void)
275 {
276     return PIXMAN_VERSION;
277 }
278
279 /**
280  * pixman_version_string:
281  *
282  * Returns the version of the pixman library as a human-readable string
283  * of the form "X.Y.Z".
284  *
285  * See also pixman_version() as well as the compile-time equivalents
286  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
287  *
288  * Return value: a string containing the version.
289  **/
290 PIXMAN_EXPORT const char*
291 pixman_version_string (void)
292 {
293     return PIXMAN_VERSION_STRING;
294 }
295
296 /**
297  * pixman_format_supported_destination:
298  * @format: A pixman_format_code_t format
299  * 
300  * Return value: whether the provided format code is a supported
301  * format for a pixman surface used as a destination in
302  * rendering.
303  *
304  * Currently, all pixman_format_code_t values are supported
305  * except for the YUV formats.
306  **/
307 PIXMAN_EXPORT pixman_bool_t
308 pixman_format_supported_destination (pixman_format_code_t format)
309 {
310     switch (format) {
311     /* 32 bpp formats */
312     case PIXMAN_a2b10g10r10:
313     case PIXMAN_x2b10g10r10:
314     case PIXMAN_a8r8g8b8:
315     case PIXMAN_x8r8g8b8:
316     case PIXMAN_a8b8g8r8:
317     case PIXMAN_x8b8g8r8:
318     case PIXMAN_b8g8r8a8:
319     case PIXMAN_b8g8r8x8:
320     case PIXMAN_r8g8b8:
321     case PIXMAN_b8g8r8:
322     case PIXMAN_r5g6b5:
323     case PIXMAN_b5g6r5:
324     /* 16 bpp formats */
325     case PIXMAN_a1r5g5b5:
326     case PIXMAN_x1r5g5b5:
327     case PIXMAN_a1b5g5r5:
328     case PIXMAN_x1b5g5r5:
329     case PIXMAN_a4r4g4b4:
330     case PIXMAN_x4r4g4b4:
331     case PIXMAN_a4b4g4r4:
332     case PIXMAN_x4b4g4r4:
333     /* 8bpp formats */
334     case PIXMAN_a8:
335     case PIXMAN_r3g3b2:
336     case PIXMAN_b2g3r3:
337     case PIXMAN_a2r2g2b2:
338     case PIXMAN_a2b2g2r2:
339     case PIXMAN_c8:
340     case PIXMAN_g8:
341     case PIXMAN_x4a4:
342     /* Collides with PIXMAN_c8
343     case PIXMAN_x4c4:
344     */
345     /* Collides with PIXMAN_g8
346     case PIXMAN_x4g4:
347     */
348     /* 4bpp formats */
349     case PIXMAN_a4:
350     case PIXMAN_r1g2b1:
351     case PIXMAN_b1g2r1:
352     case PIXMAN_a1r1g1b1:
353     case PIXMAN_a1b1g1r1:
354     case PIXMAN_c4:
355     case PIXMAN_g4:
356     /* 1bpp formats */
357     case PIXMAN_a1:
358     case PIXMAN_g1:
359         return TRUE;
360         
361     /* YUV formats */
362     case PIXMAN_yuy2:
363     case PIXMAN_yv12:
364     default:
365         return FALSE;
366     }
367 }
368
369 /**
370  * pixman_format_supported_source:
371  * @format: A pixman_format_code_t format
372  * 
373  * Return value: whether the provided format code is a supported
374  * format for a pixman surface used as a source in
375  * rendering.
376  *
377  * Currently, all pixman_format_code_t values are supported.
378  **/
379 PIXMAN_EXPORT pixman_bool_t
380 pixman_format_supported_source (pixman_format_code_t format)
381 {
382     switch (format) {
383     /* 32 bpp formats */
384     case PIXMAN_a2b10g10r10:
385     case PIXMAN_x2b10g10r10:
386     case PIXMAN_a8r8g8b8:
387     case PIXMAN_x8r8g8b8:
388     case PIXMAN_a8b8g8r8:
389     case PIXMAN_x8b8g8r8:
390     case PIXMAN_b8g8r8a8:
391     case PIXMAN_b8g8r8x8:
392     case PIXMAN_r8g8b8:
393     case PIXMAN_b8g8r8:
394     case PIXMAN_r5g6b5:
395     case PIXMAN_b5g6r5:
396     /* 16 bpp formats */
397     case PIXMAN_a1r5g5b5:
398     case PIXMAN_x1r5g5b5:
399     case PIXMAN_a1b5g5r5:
400     case PIXMAN_x1b5g5r5:
401     case PIXMAN_a4r4g4b4:
402     case PIXMAN_x4r4g4b4:
403     case PIXMAN_a4b4g4r4:
404     case PIXMAN_x4b4g4r4:
405     /* 8bpp formats */
406     case PIXMAN_a8:
407     case PIXMAN_r3g3b2:
408     case PIXMAN_b2g3r3:
409     case PIXMAN_a2r2g2b2:
410     case PIXMAN_a2b2g2r2:
411     case PIXMAN_c8:
412     case PIXMAN_g8:
413     case PIXMAN_x4a4:
414     /* Collides with PIXMAN_c8
415     case PIXMAN_x4c4:
416     */
417     /* Collides with PIXMAN_g8
418     case PIXMAN_x4g4:
419     */
420     /* 4bpp formats */
421     case PIXMAN_a4:
422     case PIXMAN_r1g2b1:
423     case PIXMAN_b1g2r1:
424     case PIXMAN_a1r1g1b1:
425     case PIXMAN_a1b1g1r1:
426     case PIXMAN_c4:
427     case PIXMAN_g4:
428     /* 1bpp formats */
429     case PIXMAN_a1:
430     case PIXMAN_g1:
431     /* YUV formats */
432     case PIXMAN_yuy2:
433     case PIXMAN_yv12:
434         return TRUE;
435
436     default:
437         return FALSE;
438     }
439 }
440
441 void
442 _pixman_walk_composite_region (pixman_implementation_t *imp,
443                               pixman_op_t op,
444                               pixman_image_t * pSrc,
445                               pixman_image_t * pMask,
446                               pixman_image_t * pDst,
447                               int16_t xSrc,
448                               int16_t ySrc,
449                               int16_t xMask,
450                               int16_t yMask,
451                               int16_t xDst,
452                               int16_t yDst,
453                               uint16_t width,
454                               uint16_t height,
455                               pixman_bool_t srcRepeat,
456                               pixman_bool_t maskRepeat,
457                               pixman_composite_func_t compositeRect)
458 {
459     int             n;
460     const pixman_box32_t *pbox;
461     int             w, h, w_this, h_this;
462     int             x_msk, y_msk, x_src, y_src, x_dst, y_dst;
463     pixman_region32_t reg;
464     pixman_region32_t *region;
465
466     pixman_region32_init (&reg);
467     if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
468                                             xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
469     {
470         return;
471     }
472
473     region = &reg;
474
475     pbox = pixman_region32_rectangles (region, &n);
476     while (n--)
477     {
478         h = pbox->y2 - pbox->y1;
479         y_src = pbox->y1 - yDst + ySrc;
480         y_msk = pbox->y1 - yDst + yMask;
481         y_dst = pbox->y1;
482         while (h)
483         {
484             h_this = h;
485             w = pbox->x2 - pbox->x1;
486             x_src = pbox->x1 - xDst + xSrc;
487             x_msk = pbox->x1 - xDst + xMask;
488             x_dst = pbox->x1;
489             if (maskRepeat)
490             {
491                 y_msk = MOD (y_msk, pMask->bits.height);
492                 if (h_this > pMask->bits.height - y_msk)
493                     h_this = pMask->bits.height - y_msk;
494             }
495             if (srcRepeat)
496             {
497                 y_src = MOD (y_src, pSrc->bits.height);
498                 if (h_this > pSrc->bits.height - y_src)
499                     h_this = pSrc->bits.height - y_src;
500             }
501             while (w)
502             {
503                 w_this = w;
504                 if (maskRepeat)
505                 {
506                     x_msk = MOD (x_msk, pMask->bits.width);
507                     if (w_this > pMask->bits.width - x_msk)
508                         w_this = pMask->bits.width - x_msk;
509                 }
510                 if (srcRepeat)
511                 {
512                     x_src = MOD (x_src, pSrc->bits.width);
513                     if (w_this > pSrc->bits.width - x_src)
514                         w_this = pSrc->bits.width - x_src;
515                 }
516                 (*compositeRect) (imp,
517                                   op, pSrc, pMask, pDst,
518                                   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
519                                   w_this, h_this);
520                 w -= w_this;
521                 x_src += w_this;
522                 x_msk += w_this;
523                 x_dst += w_this;
524             }
525             h -= h_this;
526             y_src += h_this;
527             y_msk += h_this;
528             y_dst += h_this;
529         }
530         pbox++;
531     }
532     pixman_region32_fini (&reg);
533 }
534
535 static pixman_bool_t
536 mask_is_solid (pixman_image_t *mask)
537 {
538     if (mask->type == SOLID)
539         return TRUE;
540
541     if (mask->type == BITS &&
542         mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
543         mask->bits.width == 1 &&
544         mask->bits.height == 1)
545     {
546         return TRUE;
547     }
548
549     return FALSE;
550 }
551
552 static const FastPathInfo *
553 get_fast_path (const FastPathInfo *fast_paths,
554                pixman_op_t         op,
555                pixman_image_t     *pSrc,
556                pixman_image_t     *pMask,
557                pixman_image_t     *pDst,
558                pixman_bool_t       is_pixbuf)
559 {
560     const FastPathInfo *info;
561
562     for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
563     {
564         pixman_bool_t valid_src         = FALSE;
565         pixman_bool_t valid_mask        = FALSE;
566
567         if (info->op != op)
568             continue;
569
570         if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))             ||
571             (pSrc->type == BITS && info->src_format == pSrc->bits.format))
572         {
573             valid_src = TRUE;
574         }
575
576         if (!valid_src)
577             continue;
578
579         if ((info->mask_format == PIXMAN_null && !pMask)                        ||
580             (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
581         {
582             valid_mask = TRUE;
583
584             if (info->flags & NEED_SOLID_MASK)
585             {
586                 if (!pMask || !mask_is_solid (pMask))
587                     valid_mask = FALSE;
588             }
589
590             if (info->flags & NEED_COMPONENT_ALPHA)
591             {
592                 if (!pMask || !pMask->common.component_alpha)
593                     valid_mask = FALSE;
594             }
595         }
596
597         if (!valid_mask)
598             continue;
599         
600         if (info->dest_format != pDst->bits.format)
601             continue;
602
603         if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
604             continue;
605
606         return info;
607     }
608
609     return NULL;
610 }
611
612 pixman_bool_t
613 _pixman_run_fast_path (const FastPathInfo *paths,
614                        pixman_implementation_t *imp,
615                        pixman_op_t op,
616                        pixman_image_t *src,
617                        pixman_image_t *mask,
618                        pixman_image_t *dest,
619                        int32_t src_x,
620                        int32_t src_y,
621                        int32_t mask_x,
622                        int32_t mask_y,
623                        int32_t dest_x,
624                        int32_t dest_y,
625                        int32_t width,
626                        int32_t height)
627 {
628     pixman_composite_func_t func = NULL;
629     pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL;
630     pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
631     
632     if ((src->type == BITS || pixman_image_can_get_solid (src)) &&
633         (!mask || mask->type == BITS)
634         && !src->common.transform && !(mask && mask->common.transform)
635         && !(mask && mask->common.alpha_map) && !src->common.alpha_map && !dest->common.alpha_map
636         && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
637         && (src->common.repeat != PIXMAN_REPEAT_PAD)
638         && (src->common.repeat != PIXMAN_REPEAT_REFLECT)
639         && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
640                       mask->common.repeat != PIXMAN_REPEAT_PAD &&
641                       mask->common.repeat != PIXMAN_REPEAT_REFLECT))
642         && !src->common.read_func && !src->common.write_func
643         && !(mask && mask->common.read_func)
644         && !(mask && mask->common.write_func)
645         && !dest->common.read_func
646         && !dest->common.write_func)
647     {
648         const FastPathInfo *info;       
649         pixman_bool_t pixbuf;
650
651         pixbuf =
652             src && src->type == BITS            &&
653             mask && mask->type == BITS          &&
654             src->bits.bits == mask->bits.bits   &&
655             src_x == mask_x                     &&
656             src_y == mask_y                     &&
657             !mask->common.component_alpha       &&
658             !mask_repeat;
659         
660         info = get_fast_path (paths, op, src, mask, dest, pixbuf);
661
662         if (info)
663         {
664             func = info->func;
665                 
666             if (info->src_format == PIXMAN_solid)
667                 src_repeat = FALSE;
668
669             if (info->mask_format == PIXMAN_solid || info->flags & NEED_SOLID_MASK)
670                 mask_repeat = FALSE;
671
672             if ((src_repeat                     &&
673                  src->bits.width == 1           &&
674                  src->bits.height == 1) ||
675                 (mask_repeat                    &&
676                  mask->bits.width == 1          &&
677                  mask->bits.height == 1))
678             {
679                 /* If src or mask are repeating 1x1 images and src_repeat or
680                  * mask_repeat are still TRUE, it means the fast path we
681                  * selected does not actually handle repeating images.
682                  *
683                  * So rather than call the "fast path" with a zillion
684                  * 1x1 requests, we just fall back to the general code (which
685                  * does do something sensible with 1x1 repeating images).
686                  */
687                 func = NULL;
688             }
689         }
690     }
691
692     if (func)
693     {
694         _pixman_walk_composite_region (imp, op,
695                                        src, mask, dest,
696                                        src_x, src_y, mask_x, mask_y,
697                                        dest_x, dest_y,
698                                        width, height,
699                                        src_repeat, mask_repeat,
700                                        func);
701         return TRUE;
702     }
703     
704     return FALSE;
705 }