2 * Copyright © 2000 SuSE, Inc.
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.
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.
21 * Author: Keith Packard, SuSE, Inc.
30 #include "pixman-private.h"
31 #include "pixman-mmx.h"
32 #include "pixman-sse2.h"
35 * Compute the smallest value no less than y which is on a
39 PIXMAN_EXPORT pixman_fixed_t
40 pixman_sample_ceil_y (pixman_fixed_t y, int n)
42 pixman_fixed_t f = pixman_fixed_frac(y);
43 pixman_fixed_t i = pixman_fixed_floor(y);
45 f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
46 if (f > Y_FRAC_LAST(n))
48 if (pixman_fixed_to_int(i) == 0x7fff)
50 f = 0xffff; /* saturate */
59 #define _div(a,b) ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
62 * Compute the largest value no greater than y which is on a
65 PIXMAN_EXPORT pixman_fixed_t
66 pixman_sample_floor_y (pixman_fixed_t y, int n)
68 pixman_fixed_t f = pixman_fixed_frac(y);
69 pixman_fixed_t i = pixman_fixed_floor (y);
71 f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
72 if (f < Y_FRAC_FIRST(n))
74 if (pixman_fixed_to_int(i) == 0x8000)
86 * Step an edge by any amount (including negative values)
89 pixman_edge_step (pixman_edge_t *e, int n)
91 pixman_fixed_48_16_t ne;
95 ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
101 int nx = (ne + e->dy - 1) / e->dy;
102 e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
103 e->x += nx * e->signdx;
110 int nx = (-ne) / e->dy;
111 e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
112 e->x -= nx * e->signdx;
118 * A private routine to initialize the multi-step
119 * elements of an edge structure
122 _pixman_edge_multi_init (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
124 pixman_fixed_t stepx;
125 pixman_fixed_48_16_t ne;
127 ne = n * (pixman_fixed_48_16_t) e->dx;
128 stepx = n * e->stepx;
133 stepx += nx * e->signdx;
140 * Initialize one edge structure given the line endpoints and a
144 pixman_edge_init (pixman_edge_t *e,
146 pixman_fixed_t y_start,
147 pixman_fixed_t x_top,
148 pixman_fixed_t y_top,
149 pixman_fixed_t x_bot,
150 pixman_fixed_t y_bot)
152 pixman_fixed_t dx, dy;
172 e->stepx = -(-dx / dy);
177 _pixman_edge_multi_init (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
178 _pixman_edge_multi_init (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
180 pixman_edge_step (e, y_start - y_top);
184 * Initialize one edge structure given a line, starting y value
185 * and a pixel offset for the line
188 pixman_line_fixed_edge_init (pixman_edge_t *e,
191 const pixman_line_fixed_t *line,
195 pixman_fixed_t x_off_fixed = pixman_int_to_fixed(x_off);
196 pixman_fixed_t y_off_fixed = pixman_int_to_fixed(y_off);
197 const pixman_point_fixed_t *top, *bot;
199 if (line->p1.y <= line->p2.y)
209 pixman_edge_init (e, n, y,
210 top->x + x_off_fixed,
211 top->y + y_off_fixed,
212 bot->x + x_off_fixed,
213 bot->y + y_off_fixed);
217 pixman_multiply_overflows_int (unsigned int a,
220 return a >= INT32_MAX / b;
224 pixman_addition_overflows_int (unsigned int a,
227 return a > INT32_MAX - b;
231 pixman_malloc_ab(unsigned int a,
234 if (a >= INT32_MAX / b)
237 return malloc (a * b);
241 pixman_malloc_abc (unsigned int a,
245 if (a >= INT32_MAX / b)
247 else if (a * b >= INT32_MAX / c)
250 return malloc (a * b * c);
257 * Returns the version of the pixman library encoded in a single
258 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
259 * later versions compare greater than earlier versions.
261 * A run-time comparison to check that pixman's version is greater than
262 * or equal to version X.Y.Z could be performed as follows:
264 * <informalexample><programlisting>
265 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
266 * </programlisting></informalexample>
268 * See also pixman_version_string() as well as the compile-time
269 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
271 * Return value: the encoded version.
274 pixman_version (void)
276 return PIXMAN_VERSION;
280 * pixman_version_string:
282 * Returns the version of the pixman library as a human-readable string
283 * of the form "X.Y.Z".
285 * See also pixman_version() as well as the compile-time equivalents
286 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
288 * Return value: a string containing the version.
290 PIXMAN_EXPORT const char*
291 pixman_version_string (void)
293 return PIXMAN_VERSION_STRING;
297 * pixman_format_supported_destination:
298 * @format: A pixman_format_code_t format
300 * Return value: whether the provided format code is a supported
301 * format for a pixman surface used as a destination in
304 * Currently, all pixman_format_code_t values are supported
305 * except for the YUV formats.
307 PIXMAN_EXPORT pixman_bool_t
308 pixman_format_supported_destination (pixman_format_code_t format)
312 case PIXMAN_a2b10g10r10:
313 case PIXMAN_x2b10g10r10:
314 case PIXMAN_a8r8g8b8:
315 case PIXMAN_x8r8g8b8:
316 case PIXMAN_a8b8g8r8:
317 case PIXMAN_x8b8g8r8:
318 case PIXMAN_b8g8r8a8:
319 case PIXMAN_b8g8r8x8:
325 case PIXMAN_a1r5g5b5:
326 case PIXMAN_x1r5g5b5:
327 case PIXMAN_a1b5g5r5:
328 case PIXMAN_x1b5g5r5:
329 case PIXMAN_a4r4g4b4:
330 case PIXMAN_x4r4g4b4:
331 case PIXMAN_a4b4g4r4:
332 case PIXMAN_x4b4g4r4:
337 case PIXMAN_a2r2g2b2:
338 case PIXMAN_a2b2g2r2:
342 /* Collides with PIXMAN_c8
345 /* Collides with PIXMAN_g8
352 case PIXMAN_a1r1g1b1:
353 case PIXMAN_a1b1g1r1:
370 * pixman_format_supported_source:
371 * @format: A pixman_format_code_t format
373 * Return value: whether the provided format code is a supported
374 * format for a pixman surface used as a source in
377 * Currently, all pixman_format_code_t values are supported.
379 PIXMAN_EXPORT pixman_bool_t
380 pixman_format_supported_source (pixman_format_code_t format)
384 case PIXMAN_a2b10g10r10:
385 case PIXMAN_x2b10g10r10:
386 case PIXMAN_a8r8g8b8:
387 case PIXMAN_x8r8g8b8:
388 case PIXMAN_a8b8g8r8:
389 case PIXMAN_x8b8g8r8:
390 case PIXMAN_b8g8r8a8:
391 case PIXMAN_b8g8r8x8:
397 case PIXMAN_a1r5g5b5:
398 case PIXMAN_x1r5g5b5:
399 case PIXMAN_a1b5g5r5:
400 case PIXMAN_x1b5g5r5:
401 case PIXMAN_a4r4g4b4:
402 case PIXMAN_x4r4g4b4:
403 case PIXMAN_a4b4g4r4:
404 case PIXMAN_x4b4g4r4:
409 case PIXMAN_a2r2g2b2:
410 case PIXMAN_a2b2g2r2:
414 /* Collides with PIXMAN_c8
417 /* Collides with PIXMAN_g8
424 case PIXMAN_a1r1g1b1:
425 case PIXMAN_a1b1g1r1:
442 _pixman_walk_composite_region (pixman_implementation_t *imp,
444 pixman_image_t * pSrc,
445 pixman_image_t * pMask,
446 pixman_image_t * pDst,
455 pixman_bool_t srcRepeat,
456 pixman_bool_t maskRepeat,
457 pixman_composite_func_t compositeRect)
460 const pixman_box32_t *pbox;
461 int w, h, w_this, h_this;
462 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
463 pixman_region32_t reg;
464 pixman_region32_t *region;
466 pixman_region32_init (®);
467 if (!pixman_compute_composite_region32 (®, pSrc, pMask, pDst,
468 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
475 pbox = pixman_region32_rectangles (region, &n);
478 h = pbox->y2 - pbox->y1;
479 y_src = pbox->y1 - yDst + ySrc;
480 y_msk = pbox->y1 - yDst + yMask;
485 w = pbox->x2 - pbox->x1;
486 x_src = pbox->x1 - xDst + xSrc;
487 x_msk = pbox->x1 - xDst + xMask;
491 y_msk = MOD (y_msk, pMask->bits.height);
492 if (h_this > pMask->bits.height - y_msk)
493 h_this = pMask->bits.height - y_msk;
497 y_src = MOD (y_src, pSrc->bits.height);
498 if (h_this > pSrc->bits.height - y_src)
499 h_this = pSrc->bits.height - y_src;
506 x_msk = MOD (x_msk, pMask->bits.width);
507 if (w_this > pMask->bits.width - x_msk)
508 w_this = pMask->bits.width - x_msk;
512 x_src = MOD (x_src, pSrc->bits.width);
513 if (w_this > pSrc->bits.width - x_src)
514 w_this = pSrc->bits.width - x_src;
516 (*compositeRect) (imp,
517 op, pSrc, pMask, pDst,
518 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
532 pixman_region32_fini (®);
536 mask_is_solid (pixman_image_t *mask)
538 if (mask->type == SOLID)
541 if (mask->type == BITS &&
542 mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
543 mask->bits.width == 1 &&
544 mask->bits.height == 1)
552 static const FastPathInfo *
553 get_fast_path (const FastPathInfo *fast_paths,
555 pixman_image_t *pSrc,
556 pixman_image_t *pMask,
557 pixman_image_t *pDst,
558 pixman_bool_t is_pixbuf)
560 const FastPathInfo *info;
562 for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
564 pixman_bool_t valid_src = FALSE;
565 pixman_bool_t valid_mask = FALSE;
570 if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc)) ||
571 (pSrc->type == BITS && info->src_format == pSrc->bits.format))
579 if ((info->mask_format == PIXMAN_null && !pMask) ||
580 (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
584 if (info->flags & NEED_SOLID_MASK)
586 if (!pMask || !mask_is_solid (pMask))
590 if (info->flags & NEED_COMPONENT_ALPHA)
592 if (!pMask || !pMask->common.component_alpha)
600 if (info->dest_format != pDst->bits.format)
603 if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
613 _pixman_run_fast_path (const FastPathInfo *paths,
614 pixman_implementation_t *imp,
617 pixman_image_t *mask,
618 pixman_image_t *dest,
628 pixman_composite_func_t func = NULL;
629 pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL;
630 pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
632 if ((src->type == BITS || pixman_image_can_get_solid (src)) &&
633 (!mask || mask->type == BITS)
634 && !src->common.transform && !(mask && mask->common.transform)
635 && !(mask && mask->common.alpha_map) && !src->common.alpha_map && !dest->common.alpha_map
636 && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
637 && (src->common.repeat != PIXMAN_REPEAT_PAD)
638 && (src->common.repeat != PIXMAN_REPEAT_REFLECT)
639 && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
640 mask->common.repeat != PIXMAN_REPEAT_PAD &&
641 mask->common.repeat != PIXMAN_REPEAT_REFLECT))
642 && !src->common.read_func && !src->common.write_func
643 && !(mask && mask->common.read_func)
644 && !(mask && mask->common.write_func)
645 && !dest->common.read_func
646 && !dest->common.write_func)
648 const FastPathInfo *info;
649 pixman_bool_t pixbuf;
652 src && src->type == BITS &&
653 mask && mask->type == BITS &&
654 src->bits.bits == mask->bits.bits &&
657 !mask->common.component_alpha &&
660 info = get_fast_path (paths, op, src, mask, dest, pixbuf);
666 if (info->src_format == PIXMAN_solid)
669 if (info->mask_format == PIXMAN_solid || info->flags & NEED_SOLID_MASK)
673 src->bits.width == 1 &&
674 src->bits.height == 1) ||
676 mask->bits.width == 1 &&
677 mask->bits.height == 1))
679 /* If src or mask are repeating 1x1 images and src_repeat or
680 * mask_repeat are still TRUE, it means the fast path we
681 * selected does not actually handle repeating images.
683 * So rather than call the "fast path" with a zillion
684 * 1x1 requests, we just fall back to the general code (which
685 * does do something sensible with 1x1 repeating images).
694 _pixman_walk_composite_region (imp, op,
696 src_x, src_y, mask_x, mask_y,
699 src_repeat, mask_repeat,