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