Update vmx
[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
33 pixman_bool_t
34 pixman_transform_point_3d (pixman_transform_t *transform,
35                            pixman_vector_t *vector)
36 {
37     pixman_vector_t             result;
38     int                         i, j;
39     pixman_fixed_32_32_t        partial;
40     pixman_fixed_48_16_t        v;
41
42     for (j = 0; j < 3; j++)
43     {
44         v = 0;
45         for (i = 0; i < 3; i++)
46         {
47             partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
48                        (pixman_fixed_48_16_t) vector->vector[i]);
49             v += partial >> 16;
50         }
51
52         if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
53             return FALSE;
54
55         result.vector[j] = (pixman_fixed_48_16_t) v;
56     }
57
58     if (!result.vector[2])
59         return FALSE;
60
61     *vector = result;
62     return TRUE;
63 }
64
65 pixman_bool_t
66 pixman_blt (uint32_t *src_bits,
67             uint32_t *dst_bits,
68             int src_stride,
69             int dst_stride,
70             int src_bpp,
71             int dst_bpp,
72             int src_x, int src_y,
73             int dst_x, int dst_y,
74             int width, int height)
75 {
76 #ifdef USE_MMX
77     if (pixman_have_mmx())
78     {
79         return pixman_blt_mmx (src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
80                                src_x, src_y, dst_x, dst_y, width, height);
81     }
82     else
83 #endif
84         return FALSE;
85 }
86
87 static void
88 pixman_fill8 (uint32_t  *bits,
89               int       stride,
90               int       x,
91               int       y,
92               int       width,
93               int       height,
94               uint32_t  xor)
95 {
96     int byte_stride = stride * (int) sizeof (uint32_t);
97     uint8_t *dst = (uint8_t *) bits;
98     uint8_t v = xor & 0xff;
99     int i;
100
101     dst = dst + y * byte_stride + x;
102
103     while (height--)
104     {
105         for (i = 0; i < width; ++i)
106             dst[i] = v;
107
108         dst += byte_stride;
109     }
110 }
111
112 static void
113 pixman_fill16 (uint32_t *bits,
114                int       stride,
115                int       x,
116                int       y,
117                int       width,
118                int       height,
119                uint32_t  xor)
120 {
121     int short_stride = (stride * (int) sizeof (uint32_t)) / (int) sizeof (uint16_t);
122     uint16_t *dst = (uint16_t *)bits;
123     uint16_t v = xor & 0xffff;
124     int i;
125
126     dst = dst + y * short_stride + x;
127
128     while (height--)
129     {
130         for (i = 0; i < width; ++i)
131             dst[i] = v;
132
133         dst += short_stride;
134     }
135 }
136
137 static void
138 pixman_fill32 (uint32_t *bits,
139                int       stride,
140                int       x,
141                int       y,
142                int       width,
143                int       height,
144                uint32_t  xor)
145 {
146     int i;
147
148     bits = bits + y * stride + x;
149
150     while (height--)
151     {
152         for (i = 0; i < width; ++i)
153             bits[i] = xor;
154
155         bits += stride;
156     }
157 }
158
159 pixman_bool_t
160 pixman_fill (uint32_t *bits,
161              int stride,
162              int bpp,
163              int x,
164              int y,
165              int width,
166              int height,
167              uint32_t xor)
168 {
169 #if 0
170     printf ("filling: %d %d %d %d (stride: %d, bpp: %d)   pixel: %x\n",
171             x, y, width, height, stride, bpp, xor);
172 #endif
173
174 #ifdef USE_MMX
175     if (!pixman_have_mmx() || !pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
176 #endif
177     {
178         switch (bpp)
179         {
180         case 8:
181             pixman_fill8 (bits, stride, x, y, width, height, xor);
182             break;
183
184         case 16:
185             pixman_fill16 (bits, stride, x, y, width, height, xor);
186             break;
187
188         case 32:
189             pixman_fill32 (bits, stride, x, y, width, height, xor);
190             break;
191
192         default:
193             return FALSE;
194             break;
195         }
196     }
197
198     return TRUE;
199 }
200
201
202 /*
203  * Compute the smallest value no less than y which is on a
204  * grid row
205  */
206
207 pixman_fixed_t
208 pixman_sample_ceil_y (pixman_fixed_t y, int n)
209 {
210     pixman_fixed_t   f = pixman_fixed_frac(y);
211     pixman_fixed_t   i = pixman_fixed_floor(y);
212
213     f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
214     if (f > Y_FRAC_LAST(n))
215     {
216         f = Y_FRAC_FIRST(n);
217         i += pixman_fixed_1;
218     }
219     return (i | f);
220 }
221
222 #define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
223
224 /*
225  * Compute the largest value no greater than y which is on a
226  * grid row
227  */
228 pixman_fixed_t
229 pixman_sample_floor_y (pixman_fixed_t y, int n)
230 {
231     pixman_fixed_t   f = pixman_fixed_frac(y);
232     pixman_fixed_t   i = pixman_fixed_floor (y);
233
234     f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
235     if (f < Y_FRAC_FIRST(n))
236     {
237         f = Y_FRAC_LAST(n);
238         i -= pixman_fixed_1;
239     }
240     return (i | f);
241 }
242
243 /*
244  * Step an edge by any amount (including negative values)
245  */
246 void
247 pixman_edge_step (pixman_edge_t *e, int n)
248 {
249     pixman_fixed_48_16_t        ne;
250
251     e->x += n * e->stepx;
252
253     ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
254
255     if (n >= 0)
256     {
257         if (ne > 0)
258         {
259             int nx = (ne + e->dy - 1) / e->dy;
260             e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
261             e->x += nx * e->signdx;
262         }
263     }
264     else
265     {
266         if (ne <= -e->dy)
267         {
268             int nx = (-ne) / e->dy;
269             e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
270             e->x -= nx * e->signdx;
271         }
272     }
273 }
274
275 /*
276  * A private routine to initialize the multi-step
277  * elements of an edge structure
278  */
279 static void
280 _pixman_edge_tMultiInit (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
281 {
282     pixman_fixed_t      stepx;
283     pixman_fixed_48_16_t        ne;
284
285     ne = n * (pixman_fixed_48_16_t) e->dx;
286     stepx = n * e->stepx;
287     if (ne > 0)
288     {
289         int nx = ne / e->dy;
290         ne -= nx * e->dy;
291         stepx += nx * e->signdx;
292     }
293     *dx_p = ne;
294     *stepx_p = stepx;
295 }
296
297 /*
298  * Initialize one edge structure given the line endpoints and a
299  * starting y value
300  */
301 void
302 pixman_edge_init (pixman_edge_t *e,
303                   int           n,
304                   pixman_fixed_t                y_start,
305                   pixman_fixed_t                x_top,
306                   pixman_fixed_t                y_top,
307                   pixman_fixed_t                x_bot,
308                   pixman_fixed_t                y_bot)
309 {
310     pixman_fixed_t      dx, dy;
311
312     e->x = x_top;
313     e->e = 0;
314     dx = x_bot - x_top;
315     dy = y_bot - y_top;
316     e->dy = dy;
317     e->dx = 0;
318     if (dy)
319     {
320         if (dx >= 0)
321         {
322             e->signdx = 1;
323             e->stepx = dx / dy;
324             e->dx = dx % dy;
325             e->e = -dy;
326         }
327         else
328         {
329             e->signdx = -1;
330             e->stepx = -(-dx / dy);
331             e->dx = -dx % dy;
332             e->e = 0;
333         }
334
335         _pixman_edge_tMultiInit (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
336         _pixman_edge_tMultiInit (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
337     }
338     pixman_edge_step (e, y_start - y_top);
339 }
340
341 /*
342  * Initialize one edge structure given a line, starting y value
343  * and a pixel offset for the line
344  */
345 void
346 pixman_line_fixed_edge_init (pixman_edge_t *e,
347                              int            n,
348                              pixman_fixed_t         y,
349                              const pixman_line_fixed_t *line,
350                              int            x_off,
351                              int            y_off)
352 {
353     pixman_fixed_t      x_off_fixed = pixman_int_to_fixed(x_off);
354     pixman_fixed_t      y_off_fixed = pixman_int_to_fixed(y_off);
355     const pixman_point_fixed_t *top, *bot;
356
357     if (line->p1.y <= line->p2.y)
358     {
359         top = &line->p1;
360         bot = &line->p2;
361     }
362     else
363     {
364         top = &line->p2;
365         bot = &line->p1;
366     }
367     pixman_edge_init (e, n, y,
368                     top->x + x_off_fixed,
369                     top->y + y_off_fixed,
370                     bot->x + x_off_fixed,
371                     bot->y + y_off_fixed);
372 }
373
374 pixman_bool_t
375 pixman_multiply_overflows_int (unsigned int a,
376                                unsigned int b)
377 {
378     return a >= INT32_MAX / b;
379 }
380
381 pixman_bool_t
382 pixman_addition_overflows_int (unsigned int a,
383                                unsigned int b)
384 {
385     return a > INT32_MAX - b;
386 }
387
388 void *
389 pixman_malloc_ab(unsigned int a,
390                  unsigned int b)
391 {
392     if (a >= INT32_MAX / b)
393         return NULL;
394
395     return malloc (a * b);
396 }
397
398 void *
399 pixman_malloc_abc (unsigned int a,
400                    unsigned int b,
401                    unsigned int c)
402 {
403     if (a >= INT32_MAX / b)
404         return NULL;
405     else if (a * b >= INT32_MAX / c)
406         return NULL;
407     else
408         return malloc (a * b * c);
409 }