Add pixman-trap with the trapezoid rasterization code from the X server.
authorSøren Sandmann <sandmann@redhat.com>
Wed, 23 May 2007 20:40:23 +0000 (16:40 -0400)
committerSøren Sandmann <sandmann@redhat.com>
Wed, 23 May 2007 20:40:48 +0000 (16:40 -0400)
Add two different trapezoid types that X makes use of.

pixman/Makefile.am
pixman/pixman-trap.c [new file with mode: 0644]
pixman/pixman.h

index f620def..71b70a9 100644 (file)
@@ -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 (file)
index 0000000..3e66e88
--- /dev/null
@@ -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 <config.h>
+#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
index fbc9518..e1c6ab2 100644 (file)
@@ -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,