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