mmx: fix formats in commented code
[profile/ivi/pixman.git] / pixman / pixman-utils.c
1 /*
2  * Copyright © 2000 SuSE, Inc.
3  * Copyright © 1999 Keith Packard
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of SuSE not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  SuSE makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as is"
13  * without express or implied warranty.
14  *
15  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Author:  Keith Packard, SuSE, Inc.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include "pixman-private.h"
32
33 pixman_bool_t
34 _pixman_multiply_overflows_size (size_t a, size_t b)
35 {
36     return a >= SIZE_MAX / b;
37 }
38
39 pixman_bool_t
40 _pixman_multiply_overflows_int (unsigned int a, unsigned int b)
41 {
42     return a >= INT32_MAX / b;
43 }
44
45 pixman_bool_t
46 _pixman_addition_overflows_int (unsigned int a, unsigned int b)
47 {
48     return a > INT32_MAX - b;
49 }
50
51 void *
52 pixman_malloc_ab (unsigned int a,
53                   unsigned int b)
54 {
55     if (a >= INT32_MAX / b)
56         return NULL;
57
58     return malloc (a * b);
59 }
60
61 void *
62 pixman_malloc_abc (unsigned int a,
63                    unsigned int b,
64                    unsigned int c)
65 {
66     if (a >= INT32_MAX / b)
67         return NULL;
68     else if (a * b >= INT32_MAX / c)
69         return NULL;
70     else
71         return malloc (a * b * c);
72 }
73
74 /*
75  * This function expands images from ARGB8 format to ARGB16.  To preserve
76  * precision, it needs to know the original source format.  For example, if the
77  * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
78  * the expanded value is 12345123.  To correctly expand this to 16 bits, it
79  * should be 1234512345123451 and not 1234512312345123.
80  */
81 void
82 pixman_expand (uint64_t *           dst,
83                const uint32_t *     src,
84                pixman_format_code_t format,
85                int                  width)
86 {
87     /*
88      * Determine the sizes of each component and the masks and shifts
89      * required to extract them from the source pixel.
90      */
91     const int a_size = PIXMAN_FORMAT_A (format),
92               r_size = PIXMAN_FORMAT_R (format),
93               g_size = PIXMAN_FORMAT_G (format),
94               b_size = PIXMAN_FORMAT_B (format);
95     const int a_shift = 32 - a_size,
96               r_shift = 24 - r_size,
97               g_shift = 16 - g_size,
98               b_shift =  8 - b_size;
99     const uint8_t a_mask = ~(~0 << a_size),
100                   r_mask = ~(~0 << r_size),
101                   g_mask = ~(~0 << g_size),
102                   b_mask = ~(~0 << b_size);
103     int i;
104
105     /* Start at the end so that we can do the expansion in place
106      * when src == dst
107      */
108     for (i = width - 1; i >= 0; i--)
109     {
110         const uint32_t pixel = src[i];
111         const uint8_t a = (pixel >> a_shift) & a_mask,
112                       r = (pixel >> r_shift) & r_mask,
113                       g = (pixel >> g_shift) & g_mask,
114                       b = (pixel >> b_shift) & b_mask;
115         const uint64_t
116             a16 = a_size ? unorm_to_unorm (a, a_size, 16) : 0xffff,
117             r16 = unorm_to_unorm (r, r_size, 16),
118             g16 = unorm_to_unorm (g, g_size, 16),
119             b16 = unorm_to_unorm (b, b_size, 16);
120
121         dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
122     }
123 }
124
125 /*
126  * Contracting is easier than expanding.  We just need to truncate the
127  * components.
128  */
129 void
130 pixman_contract (uint32_t *      dst,
131                  const uint64_t *src,
132                  int             width)
133 {
134     int i;
135
136     /* Start at the beginning so that we can do the contraction in
137      * place when src == dst
138      */
139     for (i = 0; i < width; i++)
140     {
141         const uint8_t a = src[i] >> 56,
142                       r = src[i] >> 40,
143                       g = src[i] >> 24,
144                       b = src[i] >> 8;
145
146         dst[i] = a << 24 | r << 16 | g << 8 | b;
147     }
148 }
149
150 uint32_t *
151 _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
152 {
153     return iter->buffer;
154 }
155
156 #define N_TMP_BOXES (16)
157
158 pixman_bool_t
159 pixman_region16_copy_from_region32 (pixman_region16_t *dst,
160                                     pixman_region32_t *src)
161 {
162     int n_boxes, i;
163     pixman_box32_t *boxes32;
164     pixman_box16_t *boxes16;
165     pixman_bool_t retval;
166
167     boxes32 = pixman_region32_rectangles (src, &n_boxes);
168
169     boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
170
171     if (!boxes16)
172         return FALSE;
173
174     for (i = 0; i < n_boxes; ++i)
175     {
176         boxes16[i].x1 = boxes32[i].x1;
177         boxes16[i].y1 = boxes32[i].y1;
178         boxes16[i].x2 = boxes32[i].x2;
179         boxes16[i].y2 = boxes32[i].y2;
180     }
181
182     pixman_region_fini (dst);
183     retval = pixman_region_init_rects (dst, boxes16, n_boxes);
184     free (boxes16);
185     return retval;
186 }
187
188 pixman_bool_t
189 pixman_region32_copy_from_region16 (pixman_region32_t *dst,
190                                     pixman_region16_t *src)
191 {
192     int n_boxes, i;
193     pixman_box16_t *boxes16;
194     pixman_box32_t *boxes32;
195     pixman_box32_t tmp_boxes[N_TMP_BOXES];
196     pixman_bool_t retval;
197
198     boxes16 = pixman_region_rectangles (src, &n_boxes);
199
200     if (n_boxes > N_TMP_BOXES)
201         boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
202     else
203         boxes32 = tmp_boxes;
204
205     if (!boxes32)
206         return FALSE;
207
208     for (i = 0; i < n_boxes; ++i)
209     {
210         boxes32[i].x1 = boxes16[i].x1;
211         boxes32[i].y1 = boxes16[i].y1;
212         boxes32[i].x2 = boxes16[i].x2;
213         boxes32[i].y2 = boxes16[i].y2;
214     }
215
216     pixman_region32_fini (dst);
217     retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
218
219     if (boxes32 != tmp_boxes)
220         free (boxes32);
221
222     return retval;
223 }
224
225 #ifdef DEBUG
226
227 void
228 _pixman_log_error (const char *function, const char *message)
229 {
230     static int n_messages = 0;
231
232     if (n_messages < 10)
233     {
234         fprintf (stderr,
235                  "*** BUG ***\n"
236                  "In %s: %s\n"
237                  "Set a breakpoint on '_pixman_log_error' to debug\n\n",
238                  function, message);
239
240         n_messages++;
241     }
242 }
243
244 #endif