From 4355cc5c57f3e402af9a508762c8ed3a5ac9f2ca Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann?= Date: Wed, 23 May 2007 16:40:23 -0400 Subject: [PATCH] Add pixman-trap with the trapezoid rasterization code from the X server. Add two different trapezoid types that X makes use of. --- pixman/Makefile.am | 21 ++--- pixman/pixman-trap.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++ pixman/pixman.h | 26 ++++++ 3 files changed, 261 insertions(+), 10 deletions(-) create mode 100644 pixman/pixman-trap.c diff --git a/pixman/Makefile.am b/pixman/Makefile.am index f620def..71b70a9 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -2,16 +2,17 @@ lib_LTLIBRARIES = libpixman.la libpixman_la_LIBADD = @DEP_LIBS@ -lm -libpixman_la_SOURCES = \ - pixman.h \ - pixman-region.c \ - pixman-private.h \ - pixman-image.c \ - pixman-compose.c \ - pixman-pict.c \ - pixman-utils.c \ - pixman-edge.c \ - pixman-edge-imp.h +libpixman_la_SOURCES = \ + pixman.h \ + pixman-region.c \ + pixman-private.h \ + pixman-image.c \ + pixman-compose.c \ + pixman-pict.c \ + pixman-utils.c \ + pixman-edge.c \ + pixman-edge-imp.h \ + pixman-trap.c if USE_MMX diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c new file mode 100644 index 0000000..3e66e88 --- /dev/null +++ b/pixman/pixman-trap.c @@ -0,0 +1,224 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "pixman-private.h" + +typedef uint32_t FbBits; + +void +pixman_add_traps (pixman_image_t * image, + int16_t x_off, + int16_t y_off, + int ntrap, + pixman_trap_t *traps) +{ + int bpp; + int width; + int height; + + pixman_fixed_t x_off_fixed; + pixman_fixed_t y_off_fixed; + pixman_edge_t l, r; + pixman_fixed_t t, b; + + width = image->bits.width; + height = image->bits.height; + bpp = PIXMAN_FORMAT_BPP (image->bits.format); + + x_off_fixed = pixman_int_to_fixed(y_off); + y_off_fixed = pixman_int_to_fixed(y_off); + + while (ntrap--) + { + t = traps->top.y + y_off_fixed; + if (t < 0) + t = 0; + t = pixman_sample_ceil_y (t, bpp); + + b = traps->bot.y + y_off_fixed; + if (pixman_fixed_to_int (b) >= height) + b = pixman_int_to_fixed (height) - 1; + b = pixman_sample_floor_y (b, bpp); + + if (b >= t) + { + /* initialize edge walkers */ + pixman_edge_init (&l, bpp, t, + traps->top.l + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.l + x_off_fixed, + traps->bot.y + y_off_fixed); + + pixman_edge_init (&r, bpp, t, + traps->top.r + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.r + x_off_fixed, + traps->bot.y + y_off_fixed); + + pixman_rasterize_edges (image, &l, &r, t, b); + } + traps++; + } + + fbFinishAccess (pPicture->pDrawable); +} + +void +pixman_rasterize_trapezoid (pixman_image_t * image, + pixman_trapezoid_t *trap, + int x_off, + int y_off) +{ + int bpp; + int width; + int height; + + pixman_fixed_t x_off_fixed; + pixman_fixed_t y_off_fixed; + pixman_edge_t l, r; + pixman_fixed_t t, b; + + if (!pixman_trapezoid_valid (trap)) + return; + + width = image->bits.width; + height = image->bits.height; + bpp = PIXMAN_FORMAT_BPP (image->bits.format); + + x_off_fixed = pixman_int_to_fixed(x_off); + y_off_fixed = pixman_int_to_fixed(y_off); + t = trap->top + y_off_fixed; + if (t < 0) + t = 0; + t = pixman_sample_ceil_y (t, bpp); + + b = trap->bottom + y_off_fixed; + if (pixman_fixed_to_int (b) >= height) + b = pixman_int_to_fixed (height) - 1; + b = pixman_sample_floor_y (b, bpp); + + if (b >= t) + { + /* initialize edge walkers */ + pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off); + pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); + + pixman_rasterize_edges (image, &l, &r, t, b); + } +} + +#if 0 +static int +_GreaterY (pixman_point_fixed_t *a, pixman_point_fixed_t *b) +{ + if (a->y == b->y) + return a->x > b->x; + return a->y > b->y; +} + +/* + * Note that the definition of this function is a bit odd because + * of the X coordinate space (y increasing downwards). + */ +static int +_Clockwise (pixman_point_fixed_t *ref, pixman_point_fixed_t *a, pixman_point_fixed_t *b) +{ + pixman_point_fixed_t ad, bd; + + ad.x = a->x - ref->x; + ad.y = a->y - ref->y; + bd.x = b->x - ref->x; + bd.y = b->y - ref->y; + + return ((pixman_fixed_32_32_t) bd.y * ad.x - (pixman_fixed_32_32_t) ad.y * bd.x) < 0; +} + +/* FIXME -- this could be made more efficient */ +void +fbAddTriangles (pixman_image_t * pPicture, + int16_t x_off, + int16_t y_off, + int ntri, + xTriangle *tris) +{ + pixman_point_fixed_t *top, *left, *right, *tmp; + xTrapezoid trap; + + for (; ntri; ntri--, tris++) + { + top = &tris->p1; + left = &tris->p2; + right = &tris->p3; + if (_GreaterY (top, left)) { + tmp = left; left = top; top = tmp; + } + if (_GreaterY (top, right)) { + tmp = right; right = top; top = tmp; + } + if (_Clockwise (top, right, left)) { + tmp = right; right = left; left = tmp; + } + + /* + * Two cases: + * + * + + + * / \ / \ + * / \ / \ + * / + + \ + * / -- -- \ + * / -- -- \ + * / --- --- \ + * +-- --+ + */ + + trap.top = top->y; + trap.left.p1 = *top; + trap.left.p2 = *left; + trap.right.p1 = *top; + trap.right.p2 = *right; + if (right->y < left->y) + trap.bottom = right->y; + else + trap.bottom = left->y; + fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); + if (right->y < left->y) + { + trap.top = right->y; + trap.bottom = left->y; + trap.right.p1 = *right; + trap.right.p2 = *left; + } + else + { + trap.top = left->y; + trap.bottom = right->y; + trap.left.p1 = *left; + trap.left.p2 = *right; + } + fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); + } +} +#endif diff --git a/pixman/pixman.h b/pixman/pixman.h index fbc9518..e1c6ab2 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -490,6 +490,9 @@ void pixman_image_composite_rect (pixman_op_t * Trapezoids */ typedef struct pixman_edge pixman_edge_t; +typedef struct pixman_trapezoid pixman_trapezoid_t; +typedef struct pixman_trap pixman_trap_t; +typedef struct pixman_span_fix pixman_span_fix_t; /* * An edge structure. This represents a single polygon edge @@ -511,6 +514,29 @@ struct pixman_edge pixman_fixed_t dx_big; }; +struct pixman_trapezoid +{ + pixman_fixed_t top, bottom; + pixman_line_fixed_t left, right; +}; + + +/* whether 't' is a well defined not obviously empty trapezoid */ +#define pixman_trapezoid_valid(t) \ + ((t)->left.p1.y != (t)->left.p2.y && \ + (t)->right.p1.y != (t)->right.p2.y && \ + (int) ((t)->bottom - (t)->top) > 0) + +struct pixman_span_fix +{ + pixman_fixed_t l, r, y; +}; + +struct pixman_trap +{ + pixman_span_fix_t top, bot; +}; + pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y, int bpp); pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y, -- 2.7.4