pixman-utils.c revision 27693ee9
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
33PIXMAN_EXPORT pixman_bool_t
34pixman_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
65PIXMAN_EXPORT pixman_bool_t
66pixman_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
87static void
88pixman_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
112static void
113pixman_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
137static void
138pixman_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
159PIXMAN_EXPORT pixman_bool_t
160pixman_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
207PIXMAN_EXPORT pixman_fixed_t
208pixman_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 */
228PIXMAN_EXPORT pixman_fixed_t
229pixman_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 */
246PIXMAN_EXPORT void
247pixman_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 */
279static 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 */
301PIXMAN_EXPORT void
302pixman_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 */
345PIXMAN_EXPORT void
346pixman_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
374pixman_bool_t
375pixman_multiply_overflows_int (unsigned int a,
376		               unsigned int b)
377{
378    return a >= INT32_MAX / b;
379}
380
381pixman_bool_t
382pixman_addition_overflows_int (unsigned int a,
383		               unsigned int b)
384{
385    return a > INT32_MAX - b;
386}
387
388void *
389pixman_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
398void *
399pixman_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}
410
411
412/**
413 * pixman_version:
414 *
415 * Returns the version of the pixman library encoded in a single
416 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
417 * later versions compare greater than earlier versions.
418 *
419 * A run-time comparison to check that pixman's version is greater than
420 * or equal to version X.Y.Z could be performed as follows:
421 *
422 * <informalexample><programlisting>
423 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
424 * </programlisting></informalexample>
425 *
426 * See also pixman_version_string() as well as the compile-time
427 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
428 *
429 * Return value: the encoded version.
430 **/
431PIXMAN_EXPORT int
432pixman_version (void)
433{
434    return PIXMAN_VERSION;
435}
436
437/**
438 * pixman_version_string:
439 *
440 * Returns the version of the pixman library as a human-readable string
441 * of the form "X.Y.Z".
442 *
443 * See also pixman_version() as well as the compile-time equivalents
444 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
445 *
446 * Return value: a string containing the version.
447 **/
448PIXMAN_EXPORT const char*
449pixman_version_string (void)
450{
451    return PIXMAN_VERSION_STRING;
452}
453
454/**
455 * pixman_format_supported_destination:
456 * @format: A pixman_format_code_t format
457 *
458 * Return value: whether the provided format code is a supported
459 * format for a pixman surface used as a destination in
460 * rendering.
461 *
462 * Currently, all pixman_format_code_t values are supported
463 * except for the YUV formats.
464 **/
465PIXMAN_EXPORT pixman_bool_t
466pixman_format_supported_destination (pixman_format_code_t format)
467{
468    switch (format) {
469    /* 32 bpp formats */
470    case PIXMAN_a2b10g10r10:
471    case PIXMAN_x2b10g10r10:
472    case PIXMAN_a8r8g8b8:
473    case PIXMAN_x8r8g8b8:
474    case PIXMAN_a8b8g8r8:
475    case PIXMAN_x8b8g8r8:
476    case PIXMAN_r8g8b8:
477    case PIXMAN_b8g8r8:
478    case PIXMAN_r5g6b5:
479    case PIXMAN_b5g6r5:
480    /* 16 bpp formats */
481    case PIXMAN_a1r5g5b5:
482    case PIXMAN_x1r5g5b5:
483    case PIXMAN_a1b5g5r5:
484    case PIXMAN_x1b5g5r5:
485    case PIXMAN_a4r4g4b4:
486    case PIXMAN_x4r4g4b4:
487    case PIXMAN_a4b4g4r4:
488    case PIXMAN_x4b4g4r4:
489    /* 8bpp formats */
490    case PIXMAN_a8:
491    case PIXMAN_r3g3b2:
492    case PIXMAN_b2g3r3:
493    case PIXMAN_a2r2g2b2:
494    case PIXMAN_a2b2g2r2:
495    case PIXMAN_c8:
496    case PIXMAN_g8:
497    case PIXMAN_x4a4:
498    /* Collides with PIXMAN_c8
499    case PIXMAN_x4c4:
500    */
501    /* Collides with PIXMAN_g8
502    case PIXMAN_x4g4:
503    */
504    /* 4bpp formats */
505    case PIXMAN_a4:
506    case PIXMAN_r1g2b1:
507    case PIXMAN_b1g2r1:
508    case PIXMAN_a1r1g1b1:
509    case PIXMAN_a1b1g1r1:
510    case PIXMAN_c4:
511    case PIXMAN_g4:
512    /* 1bpp formats */
513    case PIXMAN_a1:
514    case PIXMAN_g1:
515	return TRUE;
516
517    /* YUV formats */
518    case PIXMAN_yuy2:
519    case PIXMAN_yv12:
520    default:
521	return FALSE;
522    }
523}
524
525/**
526 * pixman_format_supported_source:
527 * @format: A pixman_format_code_t format
528 *
529 * Return value: whether the provided format code is a supported
530 * format for a pixman surface used as a source in
531 * rendering.
532 *
533 * Currently, all pixman_format_code_t values are supported.
534 **/
535PIXMAN_EXPORT pixman_bool_t
536pixman_format_supported_source (pixman_format_code_t format)
537{
538    switch (format) {
539    /* 32 bpp formats */
540    case PIXMAN_a2b10g10r10:
541    case PIXMAN_x2b10g10r10:
542    case PIXMAN_a8r8g8b8:
543    case PIXMAN_x8r8g8b8:
544    case PIXMAN_a8b8g8r8:
545    case PIXMAN_x8b8g8r8:
546    case PIXMAN_r8g8b8:
547    case PIXMAN_b8g8r8:
548    case PIXMAN_r5g6b5:
549    case PIXMAN_b5g6r5:
550    /* 16 bpp formats */
551    case PIXMAN_a1r5g5b5:
552    case PIXMAN_x1r5g5b5:
553    case PIXMAN_a1b5g5r5:
554    case PIXMAN_x1b5g5r5:
555    case PIXMAN_a4r4g4b4:
556    case PIXMAN_x4r4g4b4:
557    case PIXMAN_a4b4g4r4:
558    case PIXMAN_x4b4g4r4:
559    /* 8bpp formats */
560    case PIXMAN_a8:
561    case PIXMAN_r3g3b2:
562    case PIXMAN_b2g3r3:
563    case PIXMAN_a2r2g2b2:
564    case PIXMAN_a2b2g2r2:
565    case PIXMAN_c8:
566    case PIXMAN_g8:
567    case PIXMAN_x4a4:
568    /* Collides with PIXMAN_c8
569    case PIXMAN_x4c4:
570    */
571    /* Collides with PIXMAN_g8
572    case PIXMAN_x4g4:
573    */
574    /* 4bpp formats */
575    case PIXMAN_a4:
576    case PIXMAN_r1g2b1:
577    case PIXMAN_b1g2r1:
578    case PIXMAN_a1r1g1b1:
579    case PIXMAN_a1b1g1r1:
580    case PIXMAN_c4:
581    case PIXMAN_g4:
582    /* 1bpp formats */
583    case PIXMAN_a1:
584    case PIXMAN_g1:
585    /* YUV formats */
586    case PIXMAN_yuy2:
587    case PIXMAN_yv12:
588	return TRUE;
589
590    default:
591	return FALSE;
592    }
593}
594