summaryrefslogtreecommitdiff
path: root/src/sna/fb
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-07-06 15:22:26 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-07-08 21:34:21 +0100
commite3e58123d36924c760ab6f58a7155a040422e91d (patch)
tree683b2db2d53d8abe790d34e431ddc7747d5639ff /src/sna/fb
parent5d2f88fd9972c62c87098ddc7fee7b6f0cea0fdb (diff)
sna: Fixup fb wrapper
To accommodate changes in the Xserver and avoid breakage; would have been much easier had the fb been exported in the first place.
Diffstat (limited to 'src/sna/fb')
-rw-r--r--src/sna/fb/Makefile.am37
-rw-r--r--src/sna/fb/README1
-rw-r--r--src/sna/fb/fb.h557
-rw-r--r--src/sna/fb/fbarc.c122
-rw-r--r--src/sna/fb/fbarcbits.h204
-rw-r--r--src/sna/fb/fbbitmap.c142
-rw-r--r--src/sna/fb/fbblt.c322
-rw-r--r--src/sna/fb/fbbltone.c413
-rw-r--r--src/sna/fb/fbclip.c111
-rw-r--r--src/sna/fb/fbclip.h80
-rw-r--r--src/sna/fb/fbcopy.c240
-rw-r--r--src/sna/fb/fbfill.c235
-rw-r--r--src/sna/fb/fbgc.c192
-rw-r--r--src/sna/fb/fbglyph.c277
-rw-r--r--src/sna/fb/fbglyphbits.h140
-rw-r--r--src/sna/fb/fbimage.c254
-rw-r--r--src/sna/fb/fbline.c179
-rw-r--r--src/sna/fb/fblinebits.h284
-rw-r--r--src/sna/fb/fbpict.c330
-rw-r--r--src/sna/fb/fbpict.h43
-rw-r--r--src/sna/fb/fbpoint.c120
-rw-r--r--src/sna/fb/fbpointbits.h110
-rw-r--r--src/sna/fb/fbpush.c177
-rw-r--r--src/sna/fb/fbrop.h111
-rw-r--r--src/sna/fb/fbseg.c563
-rw-r--r--src/sna/fb/fbsegbits.h212
-rw-r--r--src/sna/fb/fbspan.c131
-rw-r--r--src/sna/fb/fbstipple.c223
-rw-r--r--src/sna/fb/fbtile.c152
-rw-r--r--src/sna/fb/fbutil.c126
30 files changed, 6088 insertions, 0 deletions
diff --git a/src/sna/fb/Makefile.am b/src/sna/fb/Makefile.am
new file mode 100644
index 00000000..16f9b285
--- /dev/null
+++ b/src/sna/fb/Makefile.am
@@ -0,0 +1,37 @@
+noinst_LTLIBRARIES = libfb.la
+
+libfb_la_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@
+libfb_la_LIBADD = $(PIXMAN_LIBS)
+
+libfb_la_SOURCES = \
+ fb.h \
+ fbarc.c \
+ fbarcbits.h \
+ fbbitmap.c \
+ fbblt.c \
+ fbbltone.c \
+ fbclip.c \
+ fbclip.h \
+ fbcopy.c \
+ fbfill.c \
+ fbgc.c \
+ fbglyph.c \
+ fbglyphbits.h \
+ fbimage.c \
+ fbline.c \
+ fblinebits.h \
+ fbpict.c \
+ fbpict.h \
+ fbpoint.c \
+ fbpointbits.h \
+ fbpush.c \
+ fbrop.h \
+ fbseg.c \
+ fbsegbits.h \
+ fbspan.c \
+ fbstipple.c \
+ fbtile.c \
+ fbutil.c \
+ $(NULL)
+
+EXTRA_DIST = README
diff --git a/src/sna/fb/README b/src/sna/fb/README
new file mode 100644
index 00000000..15421240
--- /dev/null
+++ b/src/sna/fb/README
@@ -0,0 +1 @@
+Note this code is intended to live inside pixman in the long term.
diff --git a/src/sna/fb/fb.h b/src/sna/fb/fb.h
new file mode 100644
index 00000000..7847951f
--- /dev/null
+++ b/src/sna/fb/fb.h
@@ -0,0 +1,557 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef FB_H
+#define FB_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdbool.h>
+#include <pixman.h>
+
+#include <xorg-server.h>
+#include <servermd.h>
+#include <gcstruct.h>
+#include <colormap.h>
+#include <windowstr.h>
+
+#if HAS_DEBUG_FULL
+#define DBG(x) ErrorF x
+#else
+#define DBG(x)
+#endif
+
+#define WRITE(ptr, val) (*(ptr) = (val))
+#define READ(ptr) (*(ptr))
+
+/*
+ * This single define controls the basic size of data manipulated
+ * by this software; it must be log2(sizeof (FbBits) * 8)
+ */
+#define FB_SHIFT LOG2_BITMAP_PAD
+
+#define FB_UNIT (1 << FB_SHIFT)
+#define FB_HALFUNIT (1 << (FB_SHIFT-1))
+#define FB_MASK (FB_UNIT - 1)
+#define FB_ALLONES ((FbBits) -1)
+
+#if IMAGE_BYTE_ORDER != LSBFirst
+#error "IMAGE_BYTE_ORDER must be LSBFirst"
+#endif
+
+#if GLYPHPADBYTES != 4
+#error "GLYPHPADBYTES must be 4"
+#endif
+
+#if FB_SHIFT != 5
+#error "FB_SHIFT ala LOG2_BITMAP_PAD must be 5"
+#endif
+
+#define FB_STIP_SHIFT LOG2_BITMAP_PAD
+#define FB_STIP_UNIT (1 << FB_STIP_SHIFT)
+#define FB_STIP_MASK (FB_STIP_UNIT - 1)
+#define FB_STIP_ALLONES ((FbStip) -1)
+#define FbFullMask(n) ((n) == FB_UNIT ? FB_ALLONES : ((((FbBits) 1) << n) - 1))
+
+typedef uint32_t FbBits;
+typedef FbBits FbStip;
+typedef int FbStride;
+
+#include "fbrop.h"
+
+#define FbScrLeft(x,n) ((x) >> (n))
+#define FbScrRight(x,n) ((x) << (n))
+/* #define FbLeftBits(x,n) ((x) & ((((FbBits) 1) << (n)) - 1)) */
+#define FbLeftStipBits(x,n) ((x) & ((((FbStip) 1) << (n)) - 1))
+#define FbStipMoveLsb(x,s,n) (FbStipRight (x,(s)-(n)))
+#define FbPatternOffsetBits 0
+
+#define FbStipLeft(x,n) FbScrLeft(x,n)
+#define FbStipRight(x,n) FbScrRight(x,n)
+
+#define FbRotLeft(x,n) FbScrLeft(x,n) | (n ? FbScrRight(x,FB_UNIT-n) : 0)
+#define FbRotRight(x,n) FbScrRight(x,n) | (n ? FbScrLeft(x,FB_UNIT-n) : 0)
+
+#define FbRotStipLeft(x,n) FbStipLeft(x,n) | (n ? FbStipRight(x,FB_STIP_UNIT-n) : 0)
+#define FbRotStipRight(x,n) FbStipRight(x,n) | (n ? FbStipLeft(x,FB_STIP_UNIT-n) : 0)
+
+#define FbLeftMask(x) ( ((x) & FB_MASK) ? \
+ FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0)
+#define FbRightMask(x) ( ((FB_UNIT - (x)) & FB_MASK) ? \
+ FbScrLeft(FB_ALLONES,(FB_UNIT - (x)) & FB_MASK) : 0)
+
+#define FbLeftStipMask(x) ( ((x) & FB_STIP_MASK) ? \
+ FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) : 0)
+#define FbRightStipMask(x) ( ((FB_STIP_UNIT - (x)) & FB_STIP_MASK) ? \
+ FbScrLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - (x)) & FB_STIP_MASK) : 0)
+
+#define FbBitsMask(x,w) (FbScrRight(FB_ALLONES,(x) & FB_MASK) & \
+ FbScrLeft(FB_ALLONES,(FB_UNIT - ((x) + (w))) & FB_MASK))
+
+#define FbStipMask(x,w) (FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) & \
+ FbStipLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - ((x)+(w))) & FB_STIP_MASK))
+
+#define FbMaskBits(x,w,l,n,r) { \
+ n = (w); \
+ r = FbRightMask((x)+n); \
+ l = FbLeftMask(x); \
+ if (l) { \
+ n -= FB_UNIT - ((x) & FB_MASK); \
+ if (n < 0) { \
+ n = 0; \
+ l &= r; \
+ r = 0; \
+ } \
+ } \
+ n >>= FB_SHIFT; \
+}
+
+#define FbByteMaskInvalid 0x10
+
+#define FbPatternOffset(o,t) ((o) ^ (FbPatternOffsetBits & ~(sizeof (t) - 1)))
+
+#define FbPtrOffset(p,o,t) ((t *) ((CARD8 *) (p) + (o)))
+#define FbSelectPatternPart(xor,o,t) ((xor) >> (FbPatternOffset (o,t) << 3))
+#define FbStorePart(dst,off,t,xor) (WRITE(FbPtrOffset(dst,off,t), \
+ FbSelectPart(xor,off,t)))
+#ifndef FbSelectPart
+#define FbSelectPart(x,o,t) FbSelectPatternPart(x,o,t)
+#endif
+
+#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) { \
+ n = (w); \
+ lb = 0; \
+ rb = 0; \
+ r = FbRightMask((x)+n); \
+ if (r) { \
+ /* compute right byte length */ \
+ if ((copy) && (((x) + n) & 7) == 0) { \
+ rb = (((x) + n) & FB_MASK) >> 3; \
+ } else { \
+ rb = FbByteMaskInvalid; \
+ } \
+ } \
+ l = FbLeftMask(x); \
+ if (l) { \
+ /* compute left byte length */ \
+ if ((copy) && ((x) & 7) == 0) { \
+ lb = ((x) & FB_MASK) >> 3; \
+ } else { \
+ lb = FbByteMaskInvalid; \
+ } \
+ /* subtract out the portion painted by leftMask */ \
+ n -= FB_UNIT - ((x) & FB_MASK); \
+ if (n < 0) { \
+ if (lb != FbByteMaskInvalid) { \
+ if (rb == FbByteMaskInvalid) { \
+ lb = FbByteMaskInvalid; \
+ } else if (rb) { \
+ lb |= (rb - lb) << (FB_SHIFT - 3); \
+ rb = 0; \
+ } \
+ } \
+ n = 0; \
+ l &= r; \
+ r = 0; \
+ }\
+ } \
+ n >>= FB_SHIFT; \
+}
+
+#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \
+ switch (lb) { \
+ case (sizeof (FbBits) - 3) | (1 << (FB_SHIFT - 3)): \
+ FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
+ break; \
+ case (sizeof (FbBits) - 3) | (2 << (FB_SHIFT - 3)): \
+ FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
+ FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
+ break; \
+ case (sizeof (FbBits) - 2) | (1 << (FB_SHIFT - 3)): \
+ FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
+ break; \
+ case sizeof (FbBits) - 3: \
+ FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
+ case sizeof (FbBits) - 2: \
+ FbStorePart(dst,sizeof (FbBits) - 2,CARD16,xor); \
+ break; \
+ case sizeof (FbBits) - 1: \
+ FbStorePart(dst,sizeof (FbBits) - 1,CARD8,xor); \
+ break; \
+ default: \
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, l)); \
+ break; \
+ } \
+}
+
+#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \
+ switch (rb) { \
+ case 1: \
+ FbStorePart(dst,0,CARD8,xor); \
+ break; \
+ case 2: \
+ FbStorePart(dst,0,CARD16,xor); \
+ break; \
+ case 3: \
+ FbStorePart(dst,0,CARD16,xor); \
+ FbStorePart(dst,2,CARD8,xor); \
+ break; \
+ default: \
+ WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, r)); \
+ } \
+}
+
+#define FbMaskStip(x,w,l,n,r) { \
+ n = (w); \
+ r = FbRightStipMask((x)+n); \
+ l = FbLeftStipMask(x); \
+ if (l) { \
+ n -= FB_STIP_UNIT - ((x) & FB_STIP_MASK); \
+ if (n < 0) { \
+ n = 0; \
+ l &= r; \
+ r = 0; \
+ } \
+ } \
+ n >>= FB_STIP_SHIFT; \
+}
+
+/*
+ * These macros are used to transparently stipple
+ * in copy mode; the expected usage is with 'n' constant
+ * so all of the conditional parts collapse into a minimal
+ * sequence of partial word writes
+ *
+ * 'n' is the bytemask of which bytes to store, 'a' is the address
+ * of the FbBits base unit, 'o' is the offset within that unit
+ *
+ * The term "lane" comes from the hardware term "byte-lane" which
+ */
+
+#define FbLaneCase1(n,a,o) \
+ if ((n) == 0x01) { \
+ WRITE((CARD8 *) ((a)+FbPatternOffset(o,CARD8)), fgxor); \
+ }
+
+#define FbLaneCase2(n,a,o) \
+ if ((n) == 0x03) { \
+ WRITE((CARD16 *) ((a)+FbPatternOffset(o,CARD16)), fgxor); \
+ } else { \
+ FbLaneCase1((n)&1,a,o) \
+ FbLaneCase1((n)>>1,a,(o)+1) \
+ }
+
+#define FbLaneCase4(n,a,o) \
+ if ((n) == 0x0f) { \
+ WRITE((CARD32 *) ((a)+FbPatternOffset(o,CARD32)), fgxor); \
+ } else { \
+ FbLaneCase2((n)&3,a,o) \
+ FbLaneCase2((n)>>2,a,(o)+2) \
+ }
+
+#define FbLaneCase(n,a) FbLaneCase4(n,(CARD8 *) (a),0)
+
+typedef struct {
+ long changes;
+ long serial;
+ void *priv;
+
+ FbBits and, xor; /* reduced rop values */
+ FbBits bgand, bgxor; /* for stipples */
+ FbBits fg, bg, pm; /* expanded and filled */
+ unsigned int dashLength; /* total of all dash elements */
+ unsigned char evenStipple; /* stipple is even */
+ unsigned char bpp; /* current drawable bpp */
+} FbGCPrivate, *FbGCPrivPtr;
+
+static inline FbGCPrivate *fb_gc(GCPtr gc)
+{
+ return (FbGCPrivate *)gc->devPrivates;
+}
+static inline PixmapPtr fbGetWindowPixmap(WindowPtr window)
+{
+ return *(void **)window->devPrivates;
+}
+
+#ifdef ROOTLESS
+#define __fbPixDrawableX(p) ((p)->drawable.x)
+#define __fbPixDrawableY(p) ((p)->drawable.y)
+#else
+#define __fbPixDrawableX(p) 0
+#define __fbPixDrawableY(p) 0
+#endif
+
+#ifdef COMPOSITE
+#define __fbPixOffXWin(p) (__fbPixDrawableX(p) - (p)->screen_x)
+#define __fbPixOffYWin(p) (__fbPixDrawableY(p) - (p)->screen_y)
+#else
+#define __fbPixOffXWin(p) (__fbPixDrawableX(p))
+#define __fbPixOffYWin(p) (__fbPixDrawableY(p))
+#endif
+#define __fbPixOffXPix(p) (__fbPixDrawableX(p))
+#define __fbPixOffYPix(p) (__fbPixDrawableY(p))
+
+#define fbGetDrawablePixmap(drawable, pixmap, xoff, yoff) { \
+ if ((drawable)->type != DRAWABLE_PIXMAP) { \
+ (pixmap) = fbGetWindowPixmap((WindowPtr)drawable); \
+ (xoff) = __fbPixOffXWin(pixmap); \
+ (yoff) = __fbPixOffYWin(pixmap); \
+ } else { \
+ (pixmap) = (PixmapPtr) (drawable); \
+ (xoff) = __fbPixOffXPix(pixmap); \
+ (yoff) = __fbPixOffYPix(pixmap); \
+ } \
+}
+
+#define fbGetPixmapBitsData(pixmap, pointer, stride, bpp) { \
+ (pointer) = (FbBits *) (pixmap)->devPrivate.ptr; \
+ (stride) = ((int) (pixmap)->devKind) / sizeof (FbBits); (void)(stride);\
+ (bpp) = (pixmap)->drawable.bitsPerPixel; (void)(bpp); \
+}
+
+#define fbGetPixmapStipData(pixmap, pointer, stride, bpp) { \
+ (pointer) = (FbStip *) (pixmap)->devPrivate.ptr; \
+ (stride) = ((int) (pixmap)->devKind) / sizeof (FbStip); (void)(stride);\
+ (bpp) = (pixmap)->drawable.bitsPerPixel; (void)(bpp); \
+}
+
+#define fbGetDrawable(drawable, pointer, stride, bpp, xoff, yoff) { \
+ PixmapPtr _pPix; \
+ fbGetDrawablePixmap(drawable, _pPix, xoff, yoff); \
+ fbGetPixmapBitsData(_pPix, pointer, stride, bpp); \
+}
+
+#define fbGetStipDrawable(drawable, pointer, stride, bpp, xoff, yoff) { \
+ PixmapPtr _pPix; \
+ fbGetDrawablePixmap(drawable, _pPix, xoff, yoff); \
+ fbGetPixmapStipData(_pPix, pointer, stride, bpp); \
+}
+
+/*
+ * XFree86 empties the root BorderClip when the VT is inactive,
+ * here's a macro which uses that to disable GetImage and GetSpans
+ */
+#define fbWindowEnabled(pWin) \
+ RegionNotEmpty(&(pWin)->drawable.pScreen->root->borderClip)
+#define fbDrawableEnabled(drawable) \
+ ((drawable)->type == DRAWABLE_PIXMAP ? \
+ TRUE : fbWindowEnabled((WindowPtr) drawable))
+
+#define FbPowerOfTwo(w) (((w) & ((w) - 1)) == 0)
+/*
+ * Accelerated tiles are power of 2 width <= FB_UNIT
+ */
+#define FbEvenTile(w) ((w) <= FB_UNIT && FbPowerOfTwo(w))
+/*
+ * Accelerated stipples are power of 2 width and <= FB_UNIT/dstBpp
+ * with dstBpp a power of 2 as well
+ */
+#define FbEvenStip(w,bpp) ((w) * (bpp) <= FB_UNIT && FbPowerOfTwo(w) && FbPowerOfTwo(bpp))
+
+inline static int16_t fbBound(int16_t a, uint16_t b)
+{
+ int v = (int)a + (int)b;
+ if (v > MAXSHORT)
+ return MAXSHORT;
+ return v;
+}
+
+extern void
+fbPolyArc(DrawablePtr drawable, GCPtr gc, int narcs, xArc * parcs);
+
+extern void
+fbBlt(FbBits *src, FbStride srcStride, int srcX,
+ FbBits *dst, FbStride dstStride, int dstX,
+ int width, int height,
+ int alu, FbBits pm, int bpp,
+ Bool reverse, Bool upsidedown);
+
+#if FB_STIP_SHIFT == FB_SHIFT
+static inline void
+fbBltStip(FbStip *src, FbStride srcStride, int srcX,
+ FbStip *dst, FbStride dstStride, int dstX,
+ int width, int height, int alu, FbBits pm, int bpp)
+{
+ fbBlt((FbBits *)src, srcStride, srcX,
+ (FbBits *)dst, dstStride, dstX,
+ width, height, alu, pm, bpp,
+ FALSE, FALSE);
+}
+#else
+#error FB_STIP_SHIFT must equal FB_SHIFT
+#endif
+
+extern void
+fbBltOne(FbStip *src, FbStride srcStride, int srcX,
+ FbBits *dst, FbStride dstStride, int dstX,
+ int dstBpp, int width, int height,
+ FbBits fgand, FbBits fbxor, FbBits bgand, FbBits bgxor);
+
+extern void
+fbBltPlane(FbBits *src, FbStride srcStride, int srcX, int srcBpp,
+ FbStip *dst, FbStride dstStride, int dstX,
+ int width, int height,
+ FbStip fgand, FbStip fgxor, FbStip bgand, FbStip bgxor,
+ Pixel planeMask);
+
+extern void
+fbCopyNtoN(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ BoxPtr pbox, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
+
+extern void
+fbCopy1toN(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ BoxPtr pbox, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
+
+extern void
+fbCopyNto1(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ BoxPtr pbox, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
+
+extern RegionPtr
+fbCopyArea(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ int sx, int sy,
+ int width, int height,
+ int dx, int dy);
+
+extern RegionPtr
+fbCopyPlane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ int sx, int sy,
+ int width, int height,
+ int dx, int dy,
+ unsigned long bitplane);
+
+extern void
+fbFill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height);
+
+extern void
+fbSolidBoxClipped(DrawablePtr drawable, GCPtr gc,
+ int x1, int y1, int x2, int y2);
+
+extern void
+fbPolyFillRect(DrawablePtr drawable, GCPtr gc, int n, xRectangle *rec);
+
+extern void
+fbFillSpans(DrawablePtr drawable, GCPtr gc,
+ int n, DDXPointPtr pt, int *width, int fSorted);
+
+extern void
+fbPadPixmap(PixmapPtr pPixmap);
+
+extern void
+fbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable);
+
+extern void
+fbGetSpans(DrawablePtr drawable, int wMax,
+ DDXPointPtr pt, int *width, int n, char *dst);
+
+extern void
+fbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y,
+ unsigned int n, CharInfoPtr *info, pointer glyphs);
+
+extern void
+fbImageGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y,
+ unsigned int n, CharInfoPtr *info, pointer glyphs);
+
+extern void
+fbPutImage(DrawablePtr drawable, GCPtr gc, int depth,
+ int x, int y, int w, int h,
+ int leftPad, int format, char *image);
+
+extern void
+fbPutXYImage(DrawablePtr drawable, GCPtr gc,
+ FbBits fg, FbBits bg, FbBits pm,
+ int alu, Bool opaque,
+ int x, int y, int width, int height,
+ FbStip * src, FbStride srcStride, int srcX);
+
+extern void
+fbGetImage(DrawablePtr drawable,
+ int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d);
+
+extern void
+fbPolyLine(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt);
+
+extern void
+fbFixCoordModePrevious(int n, DDXPointPtr pt);
+
+extern void
+fbPolySegment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg);
+
+extern RegionPtr
+fbBitmapToRegion(PixmapPtr pixmap);
+
+extern void
+fbPolyPoint(DrawablePtr drawable, GCPtr gc, int mode, int n, xPoint *pt);
+
+extern void
+fbPushImage(DrawablePtr drawable, GCPtr gc,
+ FbStip *src, FbStride srcStride, int srcX,
+ int x, int y, int width, int height);
+
+extern void
+fbPushPixels(GCPtr gc, PixmapPtr pBitmap, DrawablePtr drawable,
+ int dx, int dy, int xOrg, int yOrg);
+
+extern void
+fbSetSpans(DrawablePtr drawable, GCPtr gc,
+ char *src, DDXPointPtr pt, int *width, int n, int fSorted);
+
+extern void
+fbSegment(DrawablePtr drawable, GCPtr gc,
+ int xa, int ya, int xb, int yb,
+ bool drawLast, int *dashOffset);
+
+extern void
+fbSegment1(DrawablePtr drawable, GCPtr gc, const BoxRec *clip,
+ int xa, int ya, int xb, int yb,
+ bool drawLast, int *dashOffset);
+
+extern void
+fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n);
+
+extern void
+fbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
+ int width, int height,
+ FbStip *stip, FbStride stipStride,
+ int stipWidth, int stipHeight,
+ Bool even,
+ FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
+ int xRot, int yRot);
+
+extern void
+fbTile(FbBits *dst, FbStride dstStride, int dstX, int width, int height,
+ FbBits *tile, FbStride tileStride, int tileWidth, int tileHeight,
+ int alu, FbBits pm, int bpp,
+ int xRot, int yRot);
+
+extern FbBits fbReplicatePixel(Pixel p, int bpp);
+
+#endif /* FB_H */
diff --git a/src/sna/fb/fbarc.c b/src/sna/fb/fbarc.c
new file mode 100644
index 00000000..2222d0b6
--- /dev/null
+++ b/src/sna/fb/fbarc.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include <mi.h>
+#include <mizerarc.h>
+#include <limits.h>
+
+#define ARC fbArc8
+#define BITS BYTE
+#define BITS2 CARD16
+#define BITS4 CARD32
+#include "fbarcbits.h"
+#undef BITS
+#undef BITS2
+#undef BITS4
+#undef ARC
+
+#define ARC fbArc16
+#define BITS CARD16
+#define BITS2 CARD32
+#include "fbarcbits.h"
+#undef BITS
+#undef BITS2
+#undef ARC
+
+#define ARC fbArc32
+#define BITS CARD32
+#include "fbarcbits.h"
+#undef BITS
+#undef ARC
+
+void
+fbPolyArc(DrawablePtr drawable, GCPtr gc, int n, xArc *arc)
+{
+ DBG(("%s x %d, width=%d, fill=%d, line=%d\n",
+ __FUNCTION__, n, gc->lineWidth, gc->lineStyle, gc->fillStyle));
+
+ if (gc->lineWidth == 0) {
+ void (*raster)(FbBits *dst, FbStride dstStride, int dstBpp,
+ xArc *arc, int dx, int dy,
+ FbBits and, FbBits xor);
+
+ raster = 0;
+ if (gc->lineStyle == LineSolid && gc->fillStyle == FillSolid) {
+ switch (drawable->bitsPerPixel) {
+ case 8:
+ raster = fbArc8;
+ break;
+ case 16:
+ raster = fbArc16;
+ break;
+ case 32:
+ raster = fbArc32;
+ break;
+ }
+ }
+ if (raster) {
+ FbGCPrivPtr pgc = fb_gc(gc);
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ BoxRec box;
+ int x2, y2;
+
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ while (n--) {
+ if (miCanZeroArc(arc)) {
+ box.x1 = arc->x + drawable->x;
+ box.y1 = arc->y + drawable->y;
+ /*
+ * Because box.x2 and box.y2 get truncated to 16 bits, and the
+ * RECT_IN_REGION test treats the resulting number as a signed
+ * integer, the RECT_IN_REGION test alone can go the wrong way.
+ * This can result in a server crash because the rendering
+ * routines in this file deal directly with cpu addresses
+ * of pixels to be stored, and do not clip or otherwise check
+ * that all such addresses are within their respective pixmaps.
+ * So we only allow the RECT_IN_REGION test to be used for
+ * values that can be expressed correctly in a signed short.
+ */
+ x2 = box.x1 + (int) arc->width + 1;
+ box.x2 = x2;
+ y2 = box.y1 + (int) arc->height + 1;
+ box.y2 = y2;
+ if ((x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
+ (RegionContainsRect(gc->pCompositeClip, &box) == rgnIN)) {
+ raster(dst, dstStride, dstBpp,
+ arc, drawable->x + dstXoff,
+ drawable->y + dstYoff, pgc->and, pgc->xor);
+ } else
+ miZeroPolyArc(drawable, gc, 1, arc);
+ } else
+ miPolyArc(drawable, gc, 1, arc);
+ arc++;
+ }
+ } else
+ miZeroPolyArc(drawable, gc, n, arc);
+ } else
+ miPolyArc(drawable, gc, n, arc);
+}
diff --git a/src/sna/fb/fbarcbits.h b/src/sna/fb/fbarcbits.h
new file mode 100644
index 00000000..a37206cd
--- /dev/null
+++ b/src/sna/fb/fbarcbits.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
+#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x)))
+
+#define ARCCOPY(d) WRITE(d,xorBits)
+#define ARCRROP(d) RROP(d,andBits,xorBits)
+
+static void
+ARC(FbBits * dst,
+ FbStride dstStride,
+ int dstBpp, xArc * arc, int drawX, int drawY, FbBits and, FbBits xor)
+{
+ BITS *bits;
+ FbStride bitsStride;
+ miZeroArcRec info;
+ Bool do360;
+ int x;
+ BITS *yorgp, *yorgop;
+ BITS andBits, xorBits;
+ int yoffset, dyoffset;
+ int y, a, b, d, mask;
+ int k1, k3, dx, dy;
+
+ bits = (BITS *) dst;
+ bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
+ andBits = (BITS) and;
+ xorBits = (BITS) xor;
+ do360 = miZeroArcSetup(arc, &info, TRUE);
+ yorgp = bits + ((info.yorg + drawY) * bitsStride);
+ yorgop = bits + ((info.yorgo + drawY) * bitsStride);
+ info.xorg = (info.xorg + drawX);
+ info.xorgo = (info.xorgo + drawX);
+ MIARCSETUP();
+ yoffset = y ? bitsStride : 0;
+ dyoffset = 0;
+ mask = info.initialMask;
+
+ if (!(arc->width & 1)) {
+ if (andBits == 0) {
+ if (mask & 2)
+ ARCCOPY(yorgp + info.xorgo);
+ if (mask & 8)
+ ARCCOPY(yorgop + info.xorgo);
+ } else {
+ if (mask & 2)
+ ARCRROP(yorgp + info.xorgo);
+ if (mask & 8)
+ ARCRROP(yorgop + info.xorgo);
+ }
+ }
+ if (!info.end.x || !info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
+ int xoffset = bitsStride;
+ BITS *yorghb = yorgp + (info.h * bitsStride) + info.xorg;
+ BITS *yorgohb = yorghb - info.h;
+
+ yorgp += info.xorg;
+ yorgop += info.xorg;
+ yorghb += info.h;
+ while (1) {
+ if (andBits == 0) {
+ ARCCOPY(yorgp + yoffset + x);
+ ARCCOPY(yorgp + yoffset - x);
+ ARCCOPY(yorgop - yoffset - x);
+ ARCCOPY(yorgop - yoffset + x);
+ } else {
+ ARCRROP(yorgp + yoffset + x);
+ ARCRROP(yorgp + yoffset - x);
+ ARCRROP(yorgop - yoffset - x);
+ ARCRROP(yorgop - yoffset + x);
+ }
+ if (a < 0)
+ break;
+ if (andBits == 0) {
+ ARCCOPY(yorghb - xoffset - y);
+ ARCCOPY(yorgohb - xoffset + y);
+ ARCCOPY(yorgohb + xoffset + y);
+ ARCCOPY(yorghb + xoffset - y);
+ } else {
+ ARCRROP(yorghb - xoffset - y);
+ ARCRROP(yorgohb - xoffset + y);
+ ARCRROP(yorgohb + xoffset + y);
+ ARCRROP(yorghb + xoffset - y);
+ }
+ xoffset += bitsStride;
+ MIARCCIRCLESTEP(yoffset += bitsStride;
+ );
+ }
+ yorgp -= info.xorg;
+ yorgop -= info.xorg;
+ x = info.w;
+ yoffset = info.h * bitsStride;
+ } else if (do360) {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(dyoffset = bitsStride;
+ );
+ if (andBits == 0) {
+ ARCCOPY(yorgp + yoffset + info.xorg + x);
+ ARCCOPY(yorgp + yoffset + info.xorgo - x);
+ ARCCOPY(yorgop - yoffset + info.xorgo - x);
+ ARCCOPY(yorgop - yoffset + info.xorg + x);
+ } else {
+ ARCRROP(yorgp + yoffset + info.xorg + x);
+ ARCRROP(yorgp + yoffset + info.xorgo - x);
+ ARCRROP(yorgop - yoffset + info.xorgo - x);
+ ARCRROP(yorgop - yoffset + info.xorg + x);
+ }
+ MIARCSTEP(yoffset += dyoffset;
+ , yoffset += bitsStride;
+ );
+ }
+ } else {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(dyoffset = bitsStride;
+ );
+ if ((x == info.start.x) || (y == info.start.y)) {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ if (andBits == 0) {
+ if (mask & 1)
+ ARCCOPY(yorgp + yoffset + info.xorg + x);
+ if (mask & 2)
+ ARCCOPY(yorgp + yoffset + info.xorgo - x);
+ if (mask & 4)
+ ARCCOPY(yorgop - yoffset + info.xorgo - x);
+ if (mask & 8)
+ ARCCOPY(yorgop - yoffset + info.xorg + x);
+ } else {
+ if (mask & 1)
+ ARCRROP(yorgp + yoffset + info.xorg + x);
+ if (mask & 2)
+ ARCRROP(yorgp + yoffset + info.xorgo - x);
+ if (mask & 4)
+ ARCRROP(yorgop - yoffset + info.xorgo - x);
+ if (mask & 8)
+ ARCRROP(yorgop - yoffset + info.xorg + x);
+ }
+ if ((x == info.end.x) || (y == info.end.y)) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(yoffset += dyoffset;
+ , yoffset += bitsStride;
+ );
+ }
+ }
+ if ((x == info.start.x) || (y == info.start.y))
+ mask = info.start.mask;
+ if (andBits == 0) {
+ if (mask & 1)
+ ARCCOPY(yorgp + yoffset + info.xorg + x);
+ if (mask & 4)
+ ARCCOPY(yorgop - yoffset + info.xorgo - x);
+ if (arc->height & 1) {
+ if (mask & 2)
+ ARCCOPY(yorgp + yoffset + info.xorgo - x);
+ if (mask & 8)
+ ARCCOPY(yorgop - yoffset + info.xorg + x);
+ }
+ } else {
+ if (mask & 1)
+ ARCRROP(yorgp + yoffset + info.xorg + x);
+ if (mask & 4)
+ ARCRROP(yorgop - yoffset + info.xorgo - x);
+ if (arc->height & 1) {
+ if (mask & 2)
+ ARCRROP(yorgp + yoffset + info.xorgo - x);
+ if (mask & 8)
+ ARCRROP(yorgop - yoffset + info.xorg + x);
+ }
+ }
+}
+
+#undef ARCCOPY
+#undef ARCRROP
+
+#undef RROP
+#undef isClipped
diff --git a/src/sna/fb/fbbitmap.c b/src/sna/fb/fbbitmap.c
new file mode 100644
index 00000000..075d6ccd
--- /dev/null
+++ b/src/sna/fb/fbbitmap.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <stdlib.h>
+
+#include "fb.h"
+
+static inline void add(RegionPtr region,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2)
+{
+ BoxPtr r;
+
+ if (region->data->numRects == region->data->size)
+ RegionRectAlloc(region, 1);
+
+ r = RegionBoxptr(region) + region->data->numRects++;
+ r->x1 = x1; r->y1 = y1;
+ r->x2 = x2; r->y2 = y2;
+
+ if (x1 < region->extents.x1)
+ region->extents.x1 = x1;
+ if (x2 > region->extents.x2)
+ region->extents.x2 = x2;
+}
+
+/* Convert bitmap clip mask into clipping region.
+ * First, goes through each line and makes boxes by noting the transitions
+ * from 0 to 1 and 1 to 0.
+ * Then it coalesces the current line with the previous if they have boxes
+ * at the same X coordinates.
+ */
+RegionPtr
+fbBitmapToRegion(PixmapPtr pixmap)
+{
+ const register FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1);
+ register RegionPtr region;
+ const FbBits *bits, *line, *end;
+ int width, y1, y2, base, x1;
+ int stride, i;
+
+ DBG(("%s bitmap=%dx%d\n", __FUNCTION__,
+ pixmap->drawable.width, pixmap->drawable.height));
+
+ region = RegionCreate(NULL, 1);
+ if (!region)
+ return NullRegion;
+
+ line = (FbBits *) pixmap->devPrivate.ptr;
+ stride = pixmap->devKind >> (FB_SHIFT - 3);
+
+ width = pixmap->drawable.width;
+ region->extents.x1 = width;
+ region->extents.x2 = 0;
+ y2 = 0;
+ while (y2 < pixmap->drawable.height) {
+ y1 = y2++;
+ bits = line;
+ line += stride;
+ while (y2 < pixmap->drawable.height &&
+ memcmp(bits, line, (width+7)>>3) == 0)
+ line += stride, y2++;
+
+ if (READ(bits) & mask0)
+ x1 = 0;
+ else
+ x1 =-1;
+
+ /* Process all words which are fully in the pixmap */
+ end = bits + (width >> FB_SHIFT);
+ for (base = 0; bits < end; base += FB_UNIT) {
+ FbBits w = READ(bits++);
+ if (x1 < 0) {
+ if (!~w)
+ continue;
+ } else {
+ if (!w)
+ continue;
+ }
+ for (i = 0; i < FB_UNIT; i++) {
+ if (w & mask0) {
+ if (x1 < 0)
+ x1 = base + i;
+ } else {
+ if (x1 >= 0) {
+ add(region, x1, y1, base + i, y2);
+ x1 = -1;
+ }
+ }
+ w = FbScrLeft(w, 1);
+ }
+ }
+ if (width & FB_MASK) {
+ FbBits w = READ(bits++);
+ for (i = 0; i < (width & FB_MASK); i++) {
+ if (w & mask0) {
+ if (x1 < 0)
+ x1 = base + i;
+ } else {
+ if (x1 >= 0) {
+ add(region, x1, y1, base + i, y2);
+ x1 = -1;
+ }
+ }
+ w = FbScrLeft(w, 1);
+ }
+ }
+ if (x1 >= 0)
+ add(region, x1, y1, width, y2);
+ }
+
+ if (region->data->numRects) {
+ region->extents.y1 = RegionBoxptr(region)->y1;
+ region->extents.y2 = RegionEnd(region)->y2;
+ if (region->data->numRects == 1) {
+ free(region->data);
+ region->data = NULL;
+ }
+ } else
+ region->extents.x1 = region->extents.x2 = 0;
+
+ return region;
+}
diff --git a/src/sna/fb/fbblt.c b/src/sna/fb/fbblt.c
new file mode 100644
index 00000000..247a331c
--- /dev/null
+++ b/src/sna/fb/fbblt.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <string.h>
+#include "fb.h"
+
+typedef struct _mergeRopBits {
+ FbBits ca1, cx1, ca2, cx2;
+} FbMergeRopRec, *FbMergeRopPtr;
+
+#define O 0
+#define I FB_ALLONES
+
+static const FbMergeRopRec FbMergeRopBits[16] = {
+ {O, O, O, O}, /* clear 0x0 0 */
+ {I, O, O, O}, /* and 0x1 src AND dst */
+ {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */
+ {O, O, I, O}, /* copy 0x3 src */
+ {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */
+ {O, I, O, O}, /* noop 0x5 dst */
+ {O, I, I, O}, /* xor 0x6 src XOR dst */
+ {I, I, I, O}, /* or 0x7 src OR dst */
+ {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */
+ {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */
+ {O, I, O, I}, /* invert 0xa NOT dst */
+ {I, I, O, I}, /* orReverse 0xb src OR NOT dst */
+ {O, O, I, I}, /* copyInverted 0xc NOT src */
+ {I, O, I, I}, /* orInverted 0xd NOT src OR dst */
+ {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */
+ {O, O, O, I}, /* set 0xf 1 */
+};
+
+#undef O
+#undef I
+
+#define FbDeclareMergeRop() FbBits _ca1, _cx1, _ca2, _cx2;
+#define FbDeclarePrebuiltMergeRop() FbBits _cca, _ccx;
+
+#define FbInitializeMergeRop(alu,pm) {\
+ const FbMergeRopRec *_bits; \
+ _bits = &FbMergeRopBits[alu]; \
+ _ca1 = _bits->ca1 & pm; \
+ _cx1 = _bits->cx1 | ~pm; \
+ _ca2 = _bits->ca2 & pm; \
+ _cx2 = _bits->cx2 & pm; \
+}
+
+#define InitializeShifts(sx,dx,ls,rs) { \
+ if (sx != dx) { \
+ if (sx > dx) { \
+ ls = sx - dx; \
+ rs = FB_UNIT - ls; \
+ } else { \
+ rs = dx - sx; \
+ ls = FB_UNIT - rs; \
+ } \
+ } \
+}
+
+static void
+fbBlt__rop(FbBits *srcLine, FbStride srcStride, int srcX,
+ FbBits *dstLine, FbStride dstStride, int dstX,
+ int width, int height,
+ int alu, FbBits pm, int bpp,
+ Bool reverse, Bool upsidedown)
+{
+ FbBits *src, *dst;
+ int leftShift, rightShift;
+ FbBits startmask, endmask;
+ FbBits bits, bits1;
+ int n, nmiddle;
+ Bool destInvarient;
+ int startbyte, endbyte;
+
+ FbDeclareMergeRop();
+
+ FbInitializeMergeRop(alu, pm);
+ destInvarient = FbDestInvarientMergeRop();
+ if (upsidedown) {
+ srcLine += (height - 1) * (srcStride);
+ dstLine += (height - 1) * (dstStride);
+ srcStride = -srcStride;
+ dstStride = -dstStride;
+ }
+ FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte,
+ nmiddle, endmask, endbyte);
+ if (reverse) {
+ srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
+ dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
+ srcX = (srcX + width - 1) & FB_MASK;
+ dstX = (dstX + width - 1) & FB_MASK;
+ } else {
+ srcLine += srcX >> FB_SHIFT;
+ dstLine += dstX >> FB_SHIFT;
+ srcX &= FB_MASK;
+ dstX &= FB_MASK;
+ }
+ if (srcX == dstX) {
+ while (height--) {
+ src = srcLine;
+ srcLine += srcStride;
+ dst = dstLine;
+ dstLine += dstStride;
+ if (reverse) {
+ if (endmask) {
+ bits = READ(--src);
+ --dst;
+ FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
+ }
+ n = nmiddle;
+ if (destInvarient) {
+ while (n--)
+ WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src)));
+ } else {
+ while (n--) {
+ bits = READ(--src);
+ --dst;
+ WRITE(dst, FbDoMergeRop(bits, READ(dst)));
+ }
+ }
+ if (startmask) {
+ bits = READ(--src);
+ --dst;
+ FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
+ }
+ } else {
+ if (startmask) {
+ bits = READ(src++);
+ FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (destInvarient) {
+ while (n--)
+ WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++)));
+ } else {
+ while (n--) {
+ bits = READ(src++);
+ WRITE(dst, FbDoMergeRop(bits, READ(dst)));
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = READ(src);
+ FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
+ }
+ }
+ }
+ } else {
+ if (srcX > dstX) {
+ leftShift = srcX - dstX;
+ rightShift = FB_UNIT - leftShift;
+ } else {
+ rightShift = dstX - srcX;
+ leftShift = FB_UNIT - rightShift;
+ }
+ while (height--) {
+ src = srcLine;
+ srcLine += srcStride;
+ dst = dstLine;
+ dstLine += dstStride;
+
+ bits1 = 0;
+ if (reverse) {
+ if (srcX < dstX)
+ bits1 = READ(--src);
+ if (endmask) {
+ bits = FbScrRight(bits1, rightShift);
+ if (FbScrRight(endmask, leftShift)) {
+ bits1 = READ(--src);
+ bits |= FbScrLeft(bits1, leftShift);
+ }
+ --dst;
+ FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
+ }
+ n = nmiddle;
+ if (destInvarient) {
+ while (n--) {
+ bits = FbScrRight(bits1, rightShift);
+ bits1 = READ(--src);
+ bits |= FbScrLeft(bits1, leftShift);
+ --dst;
+ WRITE(dst, FbDoDestInvarientMergeRop(bits));
+ }
+ } else {
+ while (n--) {
+ bits = FbScrRight(bits1, rightShift);
+ bits1 = READ(--src);
+ bits |= FbScrLeft(bits1, leftShift);
+ --dst;
+ WRITE(dst, FbDoMergeRop(bits, READ(dst)));
+ }
+ }
+ if (startmask) {
+ bits = FbScrRight(bits1, rightShift);
+ if (FbScrRight(startmask, leftShift)) {
+ bits1 = READ(--src);
+ bits |= FbScrLeft(bits1, leftShift);
+ }
+ --dst;
+ FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
+ }
+ } else {
+ if (srcX > dstX)
+ bits1 = READ(src++);
+ if (startmask) {
+ bits = FbScrLeft(bits1, leftShift);
+ if (FbScrLeft(startmask, rightShift)) {
+ bits1 = READ(src++);
+ bits |= FbScrRight(bits1, rightShift);
+ }
+ FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (destInvarient) {
+ while (n--) {
+ bits = FbScrLeft(bits1, leftShift);
+ bits1 = READ(src++);
+ bits |= FbScrRight(bits1, rightShift);
+ WRITE(dst, FbDoDestInvarientMergeRop(bits));
+ dst++;
+ }
+ } else {
+ while (n--) {
+ bits = FbScrLeft(bits1, leftShift);
+ bits1 = READ(src++);
+ bits |= FbScrRight(bits1, rightShift);
+ WRITE(dst, FbDoMergeRop(bits, READ(dst)));
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = FbScrLeft(bits1, leftShift);
+ if (FbScrLeft(endmask, rightShift)) {
+ bits1 = READ(src);
+ bits |= FbScrRight(bits1, rightShift);
+ }
+ FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
+ }
+ }
+ }
+ }
+}
+
+void
+fbBlt(FbBits *srcLine, FbStride srcStride, int srcX,
+ FbBits *dstLine, FbStride dstStride, int dstX,
+ int width, int height,
+ int alu, FbBits pm, int bpp,
+ Bool reverse, Bool upsidedown)
+{
+ DBG(("%s %dx%d, alu=%d, pm=%d, bpp=%d\n",
+ __FUNCTION__, width, height, alu, pm, bpp));
+
+ if (alu == GXcopy && pm == FB_ALLONES && ((srcX|dstX|width) & 7) == 0) {
+ CARD8 *s = (CARD8 *) srcLine;
+ CARD8 *d = (CARD8 *) dstLine;
+ int i;
+
+ srcStride *= sizeof(FbBits);
+ dstStride *= sizeof(FbBits);
+ width >>= 3;
+ s += srcX >> 3;
+ d += dstX >> 3;
+
+ DBG(("%s fast blt\n", __FUNCTION__));
+
+ if ((srcLine < dstLine && srcLine + width > dstLine) ||
+ (dstLine < srcLine && dstLine + width > srcLine)) {
+ if (!upsidedown)
+ for (i = 0; i < height; i++)
+ memmove(d + i * dstStride,
+ s + i * srcStride,
+ width);
+ else
+ for (i = height - 1; i >= 0; i--)
+ memmove(d + i * dstStride,
+ s + i * srcStride,
+ width);
+ } else {
+ if (!upsidedown)
+ for (i = 0; i < height; i++)
+ memcpy(d + i * dstStride,
+ s + i * srcStride,
+ width);
+ else
+ for (i = height - 1; i >= 0; i--)
+ memcpy(d + i * dstStride,
+ s + i * srcStride,
+ width);
+ }
+
+ return;
+ }
+
+ fbBlt__rop(srcLine, srcStride, srcX,
+ dstLine, dstStride, dstX,
+ width, height,
+ alu, pm, bpp,
+ reverse, upsidedown);
+}
diff --git a/src/sna/fb/fbbltone.c b/src/sna/fb/fbbltone.c
new file mode 100644
index 00000000..697d20b5
--- /dev/null
+++ b/src/sna/fb/fbbltone.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+
+#ifdef __clang__
+/* shift overflow is intentional */
+#pragma clang diagnostic ignored "-Wshift-overflow"
+#endif
+
+/*
+ * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8)
+ *
+ * **** **** **** **** **** **** **** ****
+ * ^
+ * ******** ******** ******** ********
+ * ^
+ * leftShift = 12
+ * rightShift = 20
+ *
+ * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8)
+ *
+ * **** **** **** **** **** **** **** ****
+ * ^
+ * ******** ******** ******** ********
+ * ^
+ *
+ * leftShift = 24
+ * rightShift = 8
+ */
+
+#define LoadBits {\
+ if (leftShift) { \
+ bitsRight = (src < srcEnd ? READ(src++) : 0); \
+ bits = (FbStipLeft (bitsLeft, leftShift) | \
+ FbStipRight(bitsRight, rightShift)); \
+ bitsLeft = bitsRight; \
+ } else \
+ bits = (src < srcEnd ? READ(src++) : 0); \
+}
+
+#define LaneCases1(n,a) case n: FbLaneCase(n,a); break
+#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a)
+#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a)
+#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a)
+#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a)
+#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a)
+#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a)
+#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a)
+#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a)
+
+#define LaneCases(a) LaneCases16(0,a)
+
+static const CARD8 fb8Lane[16] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static const CARD8 fb16Lane[16] = {
+ 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const CARD8 fb32Lane[16] = {
+ 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const CARD8 * const fbLaneTable[33] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ fb8Lane, 0, 0, 0, 0, 0, 0, 0,
+ fb16Lane, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ fb32Lane
+};
+
+void
+fbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */
+ int srcX, /* bit position of source */
+ FbBits * dst, FbStride dstStride, /* FbBits units per scanline */
+ int dstX, /* bit position of dest */
+ int dstBpp, /* bits per destination unit */
+ int width, /* width in bits of destination */
+ int height, /* height in scanlines */
+ FbBits fgand, /* rrop values */
+ FbBits fgxor, FbBits bgand, FbBits bgxor)
+{
+ const FbBits *fbBits;
+ FbBits *srcEnd;
+ int pixelsPerDst; /* dst pixels per FbBits */
+ int unitsPerSrc; /* src patterns per FbStip */
+ int leftShift, rightShift; /* align source with dest */
+ FbBits startmask, endmask; /* dest scanline masks */
+ FbStip bits = 0, bitsLeft, bitsRight; /* source bits */
+ FbStip left;
+ FbBits mask;
+ int nDst; /* dest longwords (w.o. end) */
+ int w;
+ int n, nmiddle;
+ int dstS; /* stipple-relative dst X coordinate */
+ Bool copy; /* accelerate dest-invariant */
+ Bool transparent; /* accelerate 0 nop */
+ int srcinc; /* source units consumed */
+ Bool endNeedsLoad = FALSE; /* need load for endmask */
+ const CARD8 *fbLane;
+ int startbyte, endbyte;
+
+ /*
+ * Do not read past the end of the buffer!
+ */
+ srcEnd = src + height * srcStride;
+
+ /*
+ * Number of destination units in FbBits == number of stipple pixels
+ * used each time
+ */
+ pixelsPerDst = FB_UNIT / dstBpp;
+
+ /*
+ * Number of source stipple patterns in FbStip
+ */
+ unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;
+
+ copy = FALSE;
+ transparent = FALSE;
+ if (bgand == 0 && fgand == 0)
+ copy = TRUE;
+ else if (bgand == FB_ALLONES && bgxor == 0)
+ transparent = TRUE;
+
+ /*
+ * Adjust source and dest to nearest FbBits boundary
+ */
+ src += srcX >> FB_STIP_SHIFT;
+ dst += dstX >> FB_SHIFT;
+ srcX &= FB_STIP_MASK;
+ dstX &= FB_MASK;
+
+ FbMaskBitsBytes(dstX, width, copy,
+ startmask, startbyte, nmiddle, endmask, endbyte);
+
+ /*
+ * Compute effective dest alignment requirement for
+ * source -- must align source to dest unit boundary
+ */
+ dstS = dstX / dstBpp;
+ /*
+ * Compute shift constants for effective alignement
+ */
+ if (srcX >= dstS) {
+ leftShift = srcX - dstS;
+ rightShift = FB_STIP_UNIT - leftShift;
+ } else {
+ rightShift = dstS - srcX;
+ leftShift = FB_STIP_UNIT - rightShift;
+ }
+ /*
+ * Get pointer to stipple mask array for this depth
+ */
+ fbBits = 0; /* unused */
+ if (pixelsPerDst <= 8)
+ fbBits = fbStippleTable[pixelsPerDst];
+ fbLane = 0;
+ if (transparent && fgand == 0 && dstBpp >= 8)
+ fbLane = fbLaneTable[dstBpp];
+
+ /*
+ * Compute total number of destination words written, but
+ * don't count endmask
+ */
+ nDst = nmiddle;
+ if (startmask)
+ nDst++;
+
+ dstStride -= nDst;
+
+ /*
+ * Compute total number of source words consumed
+ */
+
+ srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;
+
+ if (srcX > dstS)
+ srcinc++;
+ if (endmask) {
+ endNeedsLoad = nDst % unitsPerSrc == 0;
+ if (endNeedsLoad)
+ srcinc++;
+ }
+
+ srcStride -= srcinc;
+
+ /*
+ * Copy rectangle
+ */
+ while (height--) {
+ w = nDst; /* total units across scanline */
+ n = unitsPerSrc; /* units avail in single stipple */
+ if (n > w)
+ n = w;
+
+ bitsLeft = 0;
+ if (srcX > dstS)
+ bitsLeft = READ(src++);
+ if (n) {
+ /*
+ * Load first set of stipple bits
+ */
+ LoadBits;
+
+ /*
+ * Consume stipple bits for startmask
+ */
+ if (startmask) {
+ mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
+ if (fbLane) {
+ fbTransparentSpan(dst, mask & startmask, fgxor, 1);
+ } else {
+ if (mask || !transparent)
+ FbDoLeftMaskByteStippleRRop(dst, mask,
+ fgand, fgxor, bgand, bgxor,
+ startbyte, startmask);
+ }
+ bits = FbStipLeft(bits, pixelsPerDst);
+ dst++;
+ n--;
+ w--;
+ }
+ /*
+ * Consume stipple bits across scanline
+ */
+ for (;;) {
+ w -= n;
+ if (copy) {
+ while (n--) {
+#if FB_UNIT > 32
+ if (pixelsPerDst == 16)
+ mask = FbStipple16Bits(FbLeftStipBits(bits, 16));
+ else
+#endif
+ mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
+ WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor));
+ dst++;
+ bits = FbStipLeft(bits, pixelsPerDst);
+ }
+ }
+ else {
+ if (fbLane) {
+ while (bits && n) {
+ switch (fbLane[FbLeftStipBits(bits, pixelsPerDst)]) {
+ LaneCases((CARD8 *) dst);
+ }
+ bits = FbStipLeft(bits, pixelsPerDst);
+ dst++;
+ n--;
+ }
+ dst += n;
+ } else {
+ while (n--) {
+ left = FbLeftStipBits(bits, pixelsPerDst);
+ if (left || !transparent) {
+ mask = fbBits[left];
+ WRITE(dst, FbStippleRRop(READ(dst), mask,
+ fgand, fgxor, bgand,
+ bgxor));
+ }
+ dst++;
+ bits = FbStipLeft(bits, pixelsPerDst);
+ }
+ }
+ }
+ if (!w)
+ break;
+ /*
+ * Load another set and reset number of available units
+ */
+ LoadBits;
+ n = unitsPerSrc;
+ if (n > w)
+ n = w;
+ }
+ }
+ /*
+ * Consume stipple bits for endmask
+ */
+ if (endmask) {
+ if (endNeedsLoad) {
+ LoadBits;
+ }
+ mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
+ if (fbLane) {
+ fbTransparentSpan(dst, mask & endmask, fgxor, 1);
+ } else {
+ if (mask || !transparent)
+ FbDoRightMaskByteStippleRRop(dst, mask,
+ fgand, fgxor, bgand, bgxor,
+ endbyte, endmask);
+ }
+ }
+ dst += dstStride;
+ src += srcStride;
+ }
+}
+
+/*
+ * Not very efficient, but simple -- copy a single plane
+ * from an N bit image to a 1 bit image
+ */
+
+void
+fbBltPlane(FbBits * src,
+ FbStride srcStride,
+ int srcX,
+ int srcBpp,
+ FbStip * dst,
+ FbStride dstStride,
+ int dstX,
+ int width,
+ int height,
+ FbStip fgand,
+ FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask)
+{
+ FbBits *s;
+ FbBits pm;
+ FbBits srcMask;
+ FbBits srcMaskFirst;
+ FbBits srcMask0 = 0;
+ FbBits srcBits;
+
+ FbStip dstBits;
+ FbStip *d;
+ FbStip dstMask;
+ FbStip dstMaskFirst;
+ FbStip dstUnion;
+ int w;
+ int wt;
+
+ if (!width)
+ return;
+
+ src += srcX >> FB_SHIFT;
+ srcX &= FB_MASK;
+
+ dst += dstX >> FB_STIP_SHIFT;
+ dstX &= FB_STIP_MASK;
+
+ w = width / srcBpp;
+
+ pm = fbReplicatePixel(planeMask, srcBpp);
+ srcMaskFirst = pm & FbBitsMask(srcX, srcBpp);
+ srcMask0 = pm & FbBitsMask(0, srcBpp);
+
+ dstMaskFirst = FbStipMask(dstX, 1);
+ while (height--) {
+ d = dst;
+ dst += dstStride;
+ s = src;
+ src += srcStride;
+
+ srcMask = srcMaskFirst;
+ srcBits = READ(s++);
+
+ dstMask = dstMaskFirst;
+ dstUnion = 0;
+ dstBits = 0;
+
+ wt = w;
+
+ while (wt--) {
+ if (!srcMask) {
+ srcBits = READ(s++);
+ srcMask = srcMask0;
+ }
+ if (!dstMask) {
+ WRITE(d, FbStippleRRopMask(READ(d), dstBits,
+ fgand, fgxor, bgand, bgxor,
+ dstUnion));
+ d++;
+ dstMask = FbStipMask(0, 1);
+ dstUnion = 0;
+ dstBits = 0;
+ }
+ if (srcBits & srcMask)
+ dstBits |= dstMask;
+ dstUnion |= dstMask;
+ if (srcBpp == FB_UNIT)
+ srcMask = 0;
+ else
+ srcMask = FbScrRight(srcMask, srcBpp);
+ dstMask = FbStipRight(dstMask, 1);
+ }
+ if (dstUnion)
+ WRITE(d, FbStippleRRopMask(READ(d), dstBits,
+ fgand, fgxor, bgand, bgxor, dstUnion));
+ }
+}
diff --git a/src/sna/fb/fbclip.c b/src/sna/fb/fbclip.c
new file mode 100644
index 00000000..9b33e4ab
--- /dev/null
+++ b/src/sna/fb/fbclip.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include "fb.h"
+#include "fbclip.h"
+
+static const BoxRec *
+find_c0(const BoxRec *begin, const BoxRec *end, int16_t y)
+{
+ const BoxRec *mid;
+
+ if (end == begin)
+ return end;
+
+ if (end - begin == 1) {
+ if (begin->y2 > y)
+ return begin;
+ else
+ return end;
+ }
+
+ mid = begin + (end - begin) / 2;
+ if (mid->y2 > y)
+ return find_c0(begin, mid, y);
+ else
+ return find_c0(mid, end, y);
+}
+
+static const BoxRec *
+find_c1(const BoxRec *begin, const BoxRec *end, int16_t y)
+{
+ const BoxRec *mid;
+
+ if (end == begin)
+ return end;
+
+ if (end - begin == 1) {
+ if (begin->y1 > y)
+ return begin;
+ else
+ return end;
+ }
+
+ mid = begin + (end - begin) / 2;
+ if (mid->y1 > y)
+ return find_c1(begin, mid, y);
+ else
+ return find_c1(mid, end, y);
+}
+
+const BoxRec *
+fbClipBoxes(const RegionRec *region, const BoxRec *box, const BoxRec **end)
+{
+ const BoxRec *c0, *c1;
+
+ DBG(("%s: box=(%d, %d),(%d, %d); region=(%d, %d),(%d, %d) x %ld\n",
+ __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2,
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2,
+ region->data ? region->data->numRects : 1));
+
+ if (box->x1 >= region->extents.x2 || box->x2 <= region->extents.x1 ||
+ box->y1 >= region->extents.y2 || box->y2 <= region->extents.y1) {
+ DBG(("%s: no intersection\n", __FUNCTION__));
+ return *end = box;
+ }
+
+ if (region->data == NULL) {
+ *end = &region->extents + 1;
+ return &region->extents;
+ }
+
+ c0 = (const BoxRec *)region->data + 1;
+ c1 = c0 + region->data->numRects;
+
+ c0 = find_c0(c0, c1, box->y1);
+ c1 = find_c1(c0, c1, box->y2);
+
+ DBG(("%s: c0=(%d, %d),(%d, %d); c1=(%d, %d),(%d, %d)\n",
+ __FUNCTION__,
+ c0->x1, c0->y1, c0->x2, c0->y2,
+ c1[-1].x1, c1[-1].y1, c1[-1].x2, c1[-1].y2));
+
+ *end = c1;
+ return c0;
+}
diff --git a/src/sna/fb/fbclip.h b/src/sna/fb/fbclip.h
new file mode 100644
index 00000000..0436c408
--- /dev/null
+++ b/src/sna/fb/fbclip.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#ifndef FBCLIP_H
+#define FBCLIP_H
+
+extern const BoxRec *
+fbClipBoxes(const RegionRec *region, const BoxRec *box, const BoxRec **end);
+
+inline static bool
+box_intersect(BoxPtr a, const BoxRec *b)
+{
+ if (a->x1 < b->x1)
+ a->x1 = b->x1;
+ if (a->x2 > b->x2)
+ a->x2 = b->x2;
+ if (a->y1 < b->y1)
+ a->y1 = b->y1;
+ if (a->y2 > b->y2)
+ a->y2 = b->y2;
+
+ return a->x1 < a->x2 && a->y1 < a->y2;
+}
+
+static inline void
+fbDrawableRun(DrawablePtr d, GCPtr gc, const BoxRec *box,
+ void (*func)(DrawablePtr, GCPtr, const BoxRec *b, void *data),
+ void *data)
+{
+ const BoxRec *c, *end;
+ for (c = fbClipBoxes(gc->pCompositeClip, box, &end); c != end; c++) {
+ BoxRec b;
+
+ if (box->x2 <= c->x1 || box->x1 >= c->x2)
+ continue;
+
+ b = *box;
+ if (box_intersect(&b, c))
+ func(d, gc, &b, data);
+ }
+}
+
+static inline void
+fbDrawableRunUnclipped(DrawablePtr d, GCPtr gc, const BoxRec *box,
+ void (*func)(DrawablePtr, GCPtr, const BoxRec *b, void *data),
+ void *data)
+{
+ const BoxRec *c, *end;
+ for (c = fbClipBoxes(gc->pCompositeClip, box, &end); c != end; c++) {
+ if (box->x2 <= c->x1 || box->x1 >= c->x2)
+ continue;
+ func(d, gc, c, data);
+ }
+}
+
+#endif /* FBCLIP_H */
diff --git a/src/sna/fb/fbcopy.c b/src/sna/fb/fbcopy.c
new file mode 100644
index 00000000..a2b1deda
--- /dev/null
+++ b/src/sna/fb/fbcopy.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <stdlib.h>
+
+#include "fb.h"
+#include <mi.h>
+
+void
+fbCopyNtoN(DrawablePtr src_drawable, DrawablePtr dst_drawable, GCPtr gc,
+ BoxPtr box, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane,
+ void *closure)
+{
+ CARD8 alu = gc ? gc->alu : GXcopy;
+ FbBits pm = gc ? fb_gc(gc)->pm : FB_ALLONES;
+ FbBits *src;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ fbGetDrawable(src_drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+ fbGetDrawable(dst_drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+
+ while (nbox--) {
+ if (pm == FB_ALLONES && alu == GXcopy && !reverse && !upsidedown) {
+ if (!pixman_blt
+ ((uint32_t *) src, (uint32_t *) dst, srcStride, dstStride,
+ srcBpp, dstBpp, (box->x1 + dx + srcXoff),
+ (box->y1 + dy + srcYoff), (box->x1 + dstXoff),
+ (box->y1 + dstYoff), (box->x2 - box->x1),
+ (box->y2 - box->y1)))
+ goto fallback;
+ else
+ goto next;
+ }
+fallback:
+ fbBlt(src + (box->y1 + dy + srcYoff) * srcStride,
+ srcStride,
+ (box->x1 + dx + srcXoff) * srcBpp,
+ dst + (box->y1 + dstYoff) * dstStride,
+ dstStride,
+ (box->x1 + dstXoff) * dstBpp,
+ (box->x2 - box->x1) * dstBpp,
+ (box->y2 - box->y1), alu, pm, dstBpp, reverse, upsidedown);
+next:
+ box++;
+ }
+}
+
+void
+fbCopy1toN(DrawablePtr src_drawable, DrawablePtr dst_drawable, GCPtr gc,
+ BoxPtr box, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane,
+ void *closure)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ FbBits *src;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ fbGetDrawable(src_drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+ fbGetDrawable(dst_drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+
+ while (nbox--) {
+ if (dstBpp == 1) {
+ fbBlt(src + (box->y1 + dy + srcYoff) * srcStride,
+ srcStride,
+ (box->x1 + dx + srcXoff) * srcBpp,
+ dst + (box->y1 + dstYoff) * dstStride,
+ dstStride,
+ (box->x1 + dstXoff) * dstBpp,
+ (box->x2 - box->x1) * dstBpp,
+ (box->y2 - box->y1),
+ FbOpaqueStipple1Rop(gc->alu,
+ gc->fgPixel, gc->bgPixel),
+ pgc->pm, dstBpp, reverse, upsidedown);
+ } else {
+ fbBltOne((FbStip *) (src + (box->y1 + dy + srcYoff) * srcStride),
+ srcStride * (FB_UNIT / FB_STIP_UNIT),
+ (box->x1 + dx + srcXoff),
+ dst + (box->y1 + dstYoff) * dstStride,
+ dstStride,
+ (box->x1 + dstXoff) * dstBpp,
+ dstBpp,
+ (box->x2 - box->x1) * dstBpp,
+ (box->y2 - box->y1),
+ pgc->and, pgc->xor, pgc->bgand, pgc->bgxor);
+ }
+ box++;
+ }
+}
+
+void
+fbCopyNto1(DrawablePtr src_drawable, DrawablePtr dst_drawable, GCPtr gc,
+ BoxPtr box, int nbox,
+ int dx, int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+
+ while (nbox--) {
+ if (dst_drawable->bitsPerPixel == 1) {
+ FbBits *src;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+
+ FbStip *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ fbGetDrawable(src_drawable, src,
+ srcStride, srcBpp, srcXoff, srcYoff);
+ fbGetStipDrawable(dst_drawable,
+ dst, dstStride, dstBpp, dstXoff, dstYoff);
+ fbBltPlane(src + (box->y1 + dy + srcYoff) * srcStride, srcStride,
+ (box->x1 + dx + srcXoff) * srcBpp, srcBpp,
+ dst + (box->y1 + dstYoff) * dstStride, dstStride,
+ (box->x1 + dstXoff) * dstBpp,
+ (box->x2 - box->x1) * srcBpp, (box->y2 - box->y1),
+ (FbStip) pgc->and, (FbStip) pgc->xor,
+ (FbStip) pgc->bgand, (FbStip) pgc->bgxor, bitplane);
+ } else {
+ FbBits *src;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ FbStip *tmp;
+ FbStride tmpStride;
+ int width, height;
+
+ width = box->x2 - box->x1;
+ height = box->y2 - box->y1;
+
+ tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT);
+ tmp = malloc(tmpStride * height * sizeof(FbStip));
+ if (!tmp)
+ return;
+
+ fbGetDrawable(src_drawable, src,
+ srcStride, srcBpp, srcXoff, srcYoff);
+ fbGetDrawable(dst_drawable, dst,
+ dstStride, dstBpp, dstXoff, dstYoff);
+
+ fbBltPlane(src + (box->y1 + dy + srcYoff) * srcStride,
+ srcStride,
+ (box->x1 + dx + srcXoff) * srcBpp,
+ srcBpp,
+ tmp,
+ tmpStride,
+ 0,
+ width * srcBpp,
+ height,
+ fbAndStip(GXcopy, FB_ALLONES, FB_ALLONES),
+ fbXorStip(GXcopy, FB_ALLONES, FB_ALLONES),
+ fbAndStip(GXcopy, 0, FB_ALLONES),
+ fbXorStip(GXcopy, 0, FB_ALLONES), bitplane);
+ fbBltOne(tmp,
+ tmpStride,
+ 0,
+ dst + (box->y1 + dstYoff) * dstStride,
+ dstStride,
+ (box->x1 + dstXoff) * dstBpp,
+ dstBpp,
+ width * dstBpp,
+ height,
+ pgc->and, pgc->xor, pgc->bgand, pgc->bgxor);
+ free(tmp);
+ }
+ box++;
+ }
+}
+
+RegionPtr
+fbCopyArea(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ int sx, int sy,
+ int width, int height,
+ int dx, int dy)
+{
+ return miDoCopy(src, dst, gc, sx, sy, width, height, dx, dy,
+ fbCopyNtoN, 0, 0);
+}
+
+RegionPtr
+fbCopyPlane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+ int sx, int sy,
+ int width, int height,
+ int dx, int dy,
+ unsigned long bitplane)
+{
+ if (src->bitsPerPixel > 1)
+ return miDoCopy(src, dst, gc, sx, sy, width, height, dx, dy,
+ fbCopyNto1, (Pixel) bitplane, 0);
+ else if (bitplane & 1)
+ return miDoCopy(src, dst, gc, sx, sy, width, height, dx, dy,
+ fbCopy1toN, (Pixel) bitplane, 0);
+ else
+ return miHandleExposures(src, dst, gc,
+ sx, sy, width, height, dx, dy,
+ bitplane);
+}
diff --git a/src/sna/fb/fbfill.c b/src/sna/fb/fbfill.c
new file mode 100644
index 00000000..3df1f9c8
--- /dev/null
+++ b/src/sna/fb/fbfill.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include "fbclip.h"
+
+static void
+fbSolid(FbBits * dst,
+ FbStride dstStride,
+ int dstX, int bpp, int width, int height, FbBits and, FbBits xor)
+{
+ FbBits startmask, endmask;
+ int n, nmiddle;
+ int startbyte, endbyte;
+
+ dst += dstX >> FB_SHIFT;
+ dstX &= FB_MASK;
+ FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte,
+ nmiddle, endmask, endbyte);
+ if (startmask)
+ dstStride--;
+ dstStride -= nmiddle;
+ while (height--) {
+ if (startmask) {
+ FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
+ dst++;
+ }
+ n = nmiddle;
+ if (!and)
+ while (n--)
+ WRITE(dst++, xor);
+ else
+ while (n--) {
+ WRITE(dst, FbDoRRop(READ(dst), and, xor));
+ dst++;
+ }
+ if (endmask)
+ FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
+ dst += dstStride;
+ }
+}
+
+void
+fbFill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height)
+{
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ FbGCPrivPtr pgc = fb_gc(gc);
+
+ DBG(("%s (%d, %d)x(%d, %d), style=%d\n",
+ __FUNCTION__, x, y, width, height, gc->fillStyle));
+
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+
+ switch (gc->fillStyle) {
+ case FillSolid:
+ if (pgc->and ||
+ !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
+ x + dstXoff, y + dstYoff,
+ width, height, pgc->xor))
+ fbSolid(dst + (y + dstYoff) * dstStride,
+ dstStride,
+ (x + dstXoff) * dstBpp,
+ dstBpp, width * dstBpp, height, pgc->and, pgc->xor);
+ break;
+
+ case FillStippled:
+ case FillOpaqueStippled:
+ {
+ PixmapPtr pStip = gc->stipple;
+ int stipWidth = pStip->drawable.width;
+ int stipHeight = pStip->drawable.height;
+
+ if (dstBpp == 1) {
+ int alu;
+ FbBits *stip;
+ FbStride stipStride;
+ int stipBpp;
+ _X_UNUSED int stipXoff, stipYoff;
+
+ if (gc->fillStyle == FillStippled)
+ alu = FbStipple1Rop(gc->alu, gc->fgPixel);
+ else
+ alu = FbOpaqueStipple1Rop(gc->alu, gc->fgPixel, gc->bgPixel);
+ fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff,
+ stipYoff);
+ fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff,
+ width, height, stip, stipStride, stipWidth, stipHeight, alu,
+ pgc->pm, dstBpp, (gc->patOrg.x + drawable->x + dstXoff),
+ gc->patOrg.y + drawable->y - y);
+ } else {
+ FbStip *stip;
+ FbStride stipStride;
+ int stipBpp;
+ _X_UNUSED int stipXoff, stipYoff;
+ FbBits fgand, fgxor, bgand, bgxor;
+
+ fgand = pgc->and;
+ fgxor = pgc->xor;
+ if (gc->fillStyle == FillStippled) {
+ bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
+ bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
+ } else {
+ bgand = pgc->bgand;
+ bgxor = pgc->bgxor;
+ }
+
+ fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp,
+ stipXoff, stipYoff);
+ fbStipple(dst + (y + dstYoff) * dstStride, dstStride,
+ (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height,
+ stip, stipStride, stipWidth, stipHeight,
+ pgc->evenStipple, fgand, fgxor, bgand, bgxor,
+ gc->patOrg.x + drawable->x + dstXoff,
+ gc->patOrg.y + drawable->y - y);
+ }
+ break;
+ }
+
+ case FillTiled:
+ {
+ PixmapPtr pTile = gc->tile.pixmap;
+ FbBits *tile;
+ FbStride tileStride;
+ int tileBpp;
+ int tileWidth;
+ int tileHeight;
+ _X_UNUSED int tileXoff, tileYoff;
+
+ fbGetDrawable(&pTile->drawable, tile,
+ tileStride, tileBpp, tileXoff, tileYoff);
+ tileWidth = pTile->drawable.width;
+ tileHeight = pTile->drawable.height;
+ fbTile(dst + (y + dstYoff) * dstStride,
+ dstStride,
+ (x + dstXoff) * dstBpp,
+ width * dstBpp, height,
+ tile,
+ tileStride,
+ tileWidth * tileBpp,
+ tileHeight,
+ gc->alu, pgc->pm,
+ dstBpp,
+ (gc->patOrg.x + drawable->x + dstXoff) * dstBpp,
+ gc->patOrg.y + drawable->y - y);
+ break;
+ }
+ }
+}
+
+static void
+_fbSolidBox(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ FbBits *dst;
+ FbStride stride;
+ int dx, dy, bpp;
+ FbBits and = fbAnd(GXcopy, fb_gc(gc)->bg, fb_gc(gc)->pm);
+ FbBits xor = fbXor(GXcopy, fb_gc(gc)->bg, fb_gc(gc)->pm);
+
+ fbGetDrawable(drawable, dst, stride, bpp, dx, dy);
+
+ if (and ||
+ !pixman_fill((uint32_t *) dst, stride, bpp,
+ b->x1 + dx, b->y1 + dy,
+ (b->x2 - b->x1), (b->y2 - b->y1), xor))
+ fbSolid(dst + (b->y1 + dy) * stride, stride,
+ (b->x1 + dx) * bpp, bpp,
+ (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
+ and, xor);
+}
+
+void
+fbSolidBoxClipped(DrawablePtr drawable, GCPtr gc,
+ int x1, int y1, int x2, int y2)
+{
+ BoxRec box;
+
+ box.x1 = x1;
+ box.y1 = y1;
+ box.x2 = x2;
+ box.y2 = y2;
+
+ fbDrawableRun(drawable, gc, &box, _fbSolidBox, NULL);
+}
+
+inline static void
+fbFillBox(DrawablePtr drawable, GCPtr gc, const BoxRec *box, void *data)
+{
+ DBG(("%s box=(%d, %d), (%d, %d)\n", __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2));
+ fbFill(drawable, gc,
+ box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1);
+}
+
+void
+fbPolyFillRect(DrawablePtr drawable, GCPtr gc, int n, xRectangle *r)
+{
+ DBG(("%s x %d\n", __FUNCTION__, n));
+ while (n--) {
+ BoxRec b;
+
+ b.x1 = r->x + drawable->x;
+ b.y1 = r->y + drawable->y;
+ b.x2 = fbBound(b.x1, r->width);
+ b.y2 = fbBound(b.y1, r->height);
+ r++;
+
+ DBG(("%s: rectangle (%d, %d), (%d, %d)\n",
+ __FUNCTION__, b.x1, b.y1, b.x2, b.y2));
+ fbDrawableRun(drawable, gc, &b, fbFillBox, NULL);
+ }
+}
diff --git a/src/sna/fb/fbgc.c b/src/sna/fb/fbgc.c
new file mode 100644
index 00000000..0969040f
--- /dev/null
+++ b/src/sna/fb/fbgc.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include <gcstruct.h>
+#include <migc.h>
+#include <scrnintstr.h>
+
+/*
+ * Pad pixmap to FB_UNIT bits wide
+ */
+void
+fbPadPixmap(PixmapPtr pPixmap)
+{
+ int width;
+ FbBits *bits;
+ FbBits b;
+ FbBits mask;
+ int height;
+ int w;
+ int stride;
+ int bpp;
+ _X_UNUSED int xOff, yOff;
+
+ fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
+
+ width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
+ height = pPixmap->drawable.height;
+ mask = FbBitsMask(0, width);
+ while (height--) {
+ b = READ(bits) & mask;
+ w = width;
+ while (w < FB_UNIT) {
+ b = b | FbScrRight(b, w);
+ w <<= 1;
+ }
+ WRITE(bits, b);
+ bits += stride;
+ }
+}
+
+/*
+ * Verify that 'bits' repeats every 'len' bits
+ */
+static Bool
+fbBitsRepeat(FbBits bits, int len, int width)
+{
+ FbBits mask = FbBitsMask(0, len);
+ FbBits orig = bits & mask;
+ int i;
+
+ if (width > FB_UNIT)
+ width = FB_UNIT;
+ for (i = 0; i < width / len; i++) {
+ if ((bits & mask) != orig)
+ return FALSE;
+ bits = FbScrLeft(bits, len);
+ }
+ return TRUE;
+}
+
+/*
+ * Check whether an entire bitmap line is a repetition of
+ * the first 'len' bits
+ */
+static Bool
+fbLineRepeat(FbBits * bits, int len, int width)
+{
+ FbBits first = bits[0];
+
+ if (!fbBitsRepeat(first, len, width))
+ return FALSE;
+ width = (width + FB_UNIT - 1) >> FB_SHIFT;
+ bits++;
+ while (--width)
+ if (READ(bits) != first)
+ return FALSE;
+ return TRUE;
+}
+
+/*
+ * The even stipple code wants the first FB_UNIT/bpp bits on
+ * each scanline to represent the entire stipple
+ */
+static Bool
+fbCanEvenStipple(PixmapPtr pStipple, int bpp)
+{
+ int len = FB_UNIT / bpp;
+ FbBits *bits;
+ int stride;
+ int stip_bpp;
+ _X_UNUSED int stipXoff, stipYoff;
+ int h;
+
+ /* make sure the stipple width is a multiple of the even stipple width */
+ if (pStipple->drawable.width % len != 0)
+ return FALSE;
+
+ fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff,
+ stipYoff);
+ h = pStipple->drawable.height;
+ /* check to see that the stipple repeats horizontally */
+ while (h--) {
+ if (!fbLineRepeat(bits, len, pStipple->drawable.width))
+ return FALSE;
+
+ bits += stride;
+ }
+ return TRUE;
+}
+
+void
+fbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ FbBits mask;
+
+ DBG(("%s changes=%lx\n", __FUNCTION__, changes));
+
+ if (changes & GCStipple) {
+ pgc->evenStipple = FALSE;
+
+ if (gc->stipple) {
+ /* can we do an even stipple ?? */
+ if (FbEvenStip(gc->stipple->drawable.width,
+ drawable->bitsPerPixel) &&
+ (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel)))
+ pgc->evenStipple = TRUE;
+ }
+ }
+
+ /*
+ * Recompute reduced rop values
+ */
+ if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
+ int s;
+ FbBits depthMask;
+
+ mask = FbFullMask(drawable->bitsPerPixel);
+ depthMask = FbFullMask(drawable->depth);
+
+ pgc->fg = gc->fgPixel & mask;
+ pgc->bg = gc->bgPixel & mask;
+
+ if ((gc->planemask & depthMask) == depthMask)
+ pgc->pm = mask;
+ else
+ pgc->pm = gc->planemask & mask;
+
+ s = drawable->bitsPerPixel;
+ while (s < FB_UNIT) {
+ pgc->fg |= pgc->fg << s;
+ pgc->bg |= pgc->bg << s;
+ pgc->pm |= pgc->pm << s;
+ s <<= 1;
+ }
+ pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm);
+ pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm);
+ pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm);
+ pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm);
+ }
+
+ if (changes & GCDashList) {
+ unsigned short n = gc->numInDashList;
+ unsigned char *dash = gc->dash;
+ unsigned int dashLength = 0;
+
+ while (n--)
+ dashLength += (unsigned int) *dash++;
+ pgc->dashLength = dashLength;
+ }
+}
diff --git a/src/sna/fb/fbglyph.c b/src/sna/fb/fbglyph.c
new file mode 100644
index 00000000..789e5b84
--- /dev/null
+++ b/src/sna/fb/fbglyph.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include <X11/fonts/fontstruct.h>
+#include <dixfontstr.h>
+
+#define GLYPH fbGlyph8
+#define BITS BYTE
+#define BITS2 CARD16
+#define BITS4 CARD32
+#include "fbglyphbits.h"
+#undef BITS
+#undef BITS2
+#undef BITS4
+#undef GLYPH
+
+#define GLYPH fbGlyph16
+#define BITS CARD16
+#define BITS2 CARD32
+#include "fbglyphbits.h"
+#undef BITS
+#undef BITS2
+#undef GLYPH
+
+#define GLYPH fbGlyph32
+#define BITS CARD32
+#include "fbglyphbits.h"
+#undef BITS
+#undef GLYPH
+
+static bool
+fbGlyphIn(GCPtr gc, int x, int y, int width, int height)
+{
+ BoxRec box;
+ BoxPtr extents = RegionExtents(gc->pCompositeClip);
+
+ /*
+ * Check extents by hand to avoid 16 bit overflows
+ */
+ if (x < (int) extents->x1 || (int) extents->x2 < x + width)
+ return FALSE;
+ if (y < (int) extents->y1 || (int) extents->y2 < y + height)
+ return FALSE;
+
+ box.x1 = x;
+ box.x2 = x + width;
+ box.y1 = y;
+ box.y2 = y + height;
+ return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN;
+}
+
+#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg)
+#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg)
+#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg)
+
+/*
+ * This is a bit tricky, but it's brief. Write 12 bytes worth
+ * of dest, which is four pixels, at a time. This gives constant
+ * code for each pattern as they're always aligned the same
+ *
+ * a b c d a b c d a b c d bytes
+ * A B C A B C A B C A B C pixels
+ *
+ * f0 f1 f2
+ * A B C A B C A B C A B C pixels LSB
+ * C A B C A B C A B C A B pixels MSB
+ *
+ * LSB MSB
+ * A f0 f1
+ * B f1 f2
+ * C f2 f0
+ * A B f0 f2
+ * B C f1 f0
+ * C A f2 f1
+ * A B C A f0 f1
+ * B C A B f1 f2
+ * C A B C f2 f0
+ */
+
+#undef _A
+#undef _B
+#undef _C
+#undef _AB
+#undef _BC
+#undef _CA
+#undef _ABCA
+#undef _BCAB
+#undef _CABC
+
+#define _A f0
+#define _B f1
+#define _C f2
+#define _AB f0
+#define _BC f1
+#define _CA f2
+#define _ABCA f0
+#define _BCAB f1
+#define _CABC f2
+#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3))
+
+void
+fbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc,
+ int x, int y,
+ unsigned int nglyph, CharInfoPtr * ppci, pointer glyphs)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ CharInfoPtr pci;
+ unsigned char *pglyph; /* pointer bits in glyph */
+ int gx, gy;
+ int gWidth, gHeight; /* width and height of glyph */
+ FbStride gStride; /* stride of glyph */
+ void (*raster) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
+ FbBits *dst = 0;
+ FbStride dstStride = 0;
+ int dstBpp = 0;
+ int dstXoff = 0, dstYoff = 0;
+
+ DBG(("%s x %d\n", __FUNCTION__, nglyph));
+
+ raster = 0;
+ if (gc->fillStyle == FillSolid && pgc->and == 0) {
+ dstBpp = drawable->bitsPerPixel;
+ switch (dstBpp) {
+ case 8:
+ raster = fbGlyph8;
+ break;
+ case 16:
+ raster = fbGlyph16;
+ break;
+ case 32:
+ raster = fbGlyph32;
+ break;
+ }
+ }
+ x += drawable->x;
+ y += drawable->y;
+
+ while (nglyph--) {
+ pci = *ppci++;
+ pglyph = FONTGLYPHBITS(glyphs, pci);
+ gWidth = GLYPHWIDTHPIXELS(pci);
+ gHeight = GLYPHHEIGHTPIXELS(pci);
+ if (gWidth && gHeight) {
+ gx = x + pci->metrics.leftSideBearing;
+ gy = y - pci->metrics.ascent;
+ if (raster && gWidth <= sizeof(FbStip) * 8 &&
+ fbGlyphIn(gc, gx, gy, gWidth, gHeight)) {
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff,
+ dstYoff);
+ raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
+ (FbStip *) pglyph, pgc->xor, gx + dstXoff, gHeight);
+ } else {
+ gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
+ fbPushImage(drawable, gc,
+ (FbStip *)pglyph,
+ gStride, 0, gx, gy, gWidth, gHeight);
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+}
+
+void
+fbImageGlyphBlt(DrawablePtr drawable, GCPtr gc,
+ int x, int y,
+ unsigned int nglyph, CharInfoPtr * ppciInit, pointer glyphs)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ CharInfoPtr *ppci;
+ CharInfoPtr pci;
+ unsigned char *pglyph; /* pointer bits in glyph */
+ int gWidth, gHeight; /* width and height of glyph */
+ FbStride gStride; /* stride of glyph */
+ bool opaque;
+ int n;
+ int gx, gy;
+ void (*raster)(FbBits *, FbStride, int, FbStip *, FbBits, int, int);
+ FbBits *dst = 0;
+ FbStride dstStride = 0;
+ int dstBpp = 0;
+ int dstXoff = 0, dstYoff = 0;
+
+ DBG(("%s x %d\n", __FUNCTION__, nglyph));
+
+ raster = 0;
+ if (pgc->and == 0) {
+ dstBpp = drawable->bitsPerPixel;
+ switch (dstBpp) {
+ case 8:
+ raster = fbGlyph8;
+ break;
+ case 16:
+ raster = fbGlyph16;
+ break;
+ case 32:
+ raster = fbGlyph32;
+ break;
+ }
+ }
+
+ x += drawable->x;
+ y += drawable->y;
+
+ if (TERMINALFONT(gc->font) && !raster) {
+ opaque = TRUE;
+ } else {
+ int xBack, widthBack;
+ int yBack, heightBack;
+
+ ppci = ppciInit;
+ n = nglyph;
+ widthBack = 0;
+ while (n--)
+ widthBack += (*ppci++)->metrics.characterWidth;
+
+ xBack = x;
+ if (widthBack < 0) {
+ xBack += widthBack;
+ widthBack = -widthBack;
+ }
+ yBack = y - FONTASCENT(gc->font);
+ heightBack = FONTASCENT(gc->font) + FONTDESCENT(gc->font);
+ fbSolidBoxClipped(drawable, gc,
+ xBack, yBack,
+ xBack + widthBack,
+ yBack + heightBack);
+ opaque = FALSE;
+ }
+
+ ppci = ppciInit;
+ while (nglyph--) {
+ pci = *ppci++;
+ pglyph = FONTGLYPHBITS(glyphs, pci);
+ gWidth = GLYPHWIDTHPIXELS(pci);
+ gHeight = GLYPHHEIGHTPIXELS(pci);
+ if (gWidth && gHeight) {
+ gx = x + pci->metrics.leftSideBearing;
+ gy = y - pci->metrics.ascent;
+ if (raster && gWidth <= sizeof(FbStip) * 8 &&
+ fbGlyphIn(gc, gx, gy, gWidth, gHeight)) {
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff,
+ dstYoff);
+ raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
+ (FbStip *) pglyph, pgc->fg, gx + dstXoff, gHeight);
+ } else {
+ gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
+ fbPutXYImage(drawable, gc,
+ pgc->fg, pgc->bg, pgc->pm,
+ GXcopy, opaque,
+ gx, gy, gWidth, gHeight,
+ (FbStip *) pglyph, gStride, 0);
+ }
+ }
+ x += pci->metrics.characterWidth;
+ }
+}
diff --git a/src/sna/fb/fbglyphbits.h b/src/sna/fb/fbglyphbits.h
new file mode 100644
index 00000000..af0f00ff
--- /dev/null
+++ b/src/sna/fb/fbglyphbits.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
+#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x)))
+
+#define WRITE_ADDR1(n) (n)
+#define WRITE_ADDR2(n) (n)
+#define WRITE_ADDR4(n) (n)
+
+#define WRITE1(d,n,fg) WRITE(d + WRITE_ADDR1(n), (BITS) (fg))
+
+#ifdef BITS2
+#define WRITE2(d,n,fg) WRITE((BITS2 *) &((d)[WRITE_ADDR2(n)]), (BITS2) (fg))
+#else
+#define WRITE2(d,n,fg) (WRITE1(d,n,fg), WRITE1(d,(n)+1,fg))
+#endif
+
+#ifdef BITS4
+#define WRITE4(d,n,fg) WRITE((BITS4 *) &((d)[WRITE_ADDR4(n)]), (BITS4) (fg))
+#else
+#define WRITE4(d,n,fg) (WRITE2(d,n,fg), WRITE2(d,(n)+2,fg))
+#endif
+
+static void
+GLYPH(FbBits * dstBits,
+ FbStride dstStride,
+ int dstBpp, FbStip * stipple, FbBits fg, int x, int height)
+{
+ int lshift;
+ FbStip bits;
+ BITS *dstLine;
+ BITS *dst;
+ int n;
+ int shift;
+
+ dstLine = (BITS *) dstBits;
+ dstLine += x & ~3;
+ dstStride *= (sizeof(FbBits) / sizeof(BITS));
+ shift = x & 3;
+ lshift = 4 - shift;
+ while (height--) {
+ bits = *stipple++;
+ dst = (BITS *) dstLine;
+ n = lshift;
+ while (bits) {
+ switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) {
+ case 0:
+ break;
+ case 1:
+ WRITE1(dst, 0, fg);
+ break;
+ case 2:
+ WRITE1(dst, 1, fg);
+ break;
+ case 3:
+ WRITE2(dst, 0, fg);
+ break;
+ case 4:
+ WRITE1(dst, 2, fg);
+ break;
+ case 5:
+ WRITE1(dst, 0, fg);
+ WRITE1(dst, 2, fg);
+ break;
+ case 6:
+ WRITE1(dst, 1, fg);
+ WRITE1(dst, 2, fg);
+ break;
+ case 7:
+ WRITE2(dst, 0, fg);
+ WRITE1(dst, 2, fg);
+ break;
+ case 8:
+ WRITE1(dst, 3, fg);
+ break;
+ case 9:
+ WRITE1(dst, 0, fg);
+ WRITE1(dst, 3, fg);
+ break;
+ case 10:
+ WRITE1(dst, 1, fg);
+ WRITE1(dst, 3, fg);
+ break;
+ case 11:
+ WRITE2(dst, 0, fg);
+ WRITE1(dst, 3, fg);
+ break;
+ case 12:
+ WRITE2(dst, 2, fg);
+ break;
+ case 13:
+ WRITE1(dst, 0, fg);
+ WRITE2(dst, 2, fg);
+ break;
+ case 14:
+ WRITE1(dst, 1, fg);
+ WRITE2(dst, 2, fg);
+ break;
+ case 15:
+ WRITE4(dst, 0, fg);
+ break;
+ }
+ bits = FbStipLeft(bits, n);
+ n = 4;
+ dst += 4;
+ }
+ dstLine += dstStride;
+ }
+}
+
+#undef WRITE_ADDR1
+#undef WRITE_ADDR2
+#undef WRITE_ADDR4
+#undef WRITE1
+#undef WRITE2
+#undef WRITE4
+
+#undef RROP
+#undef isClipped
diff --git a/src/sna/fb/fbimage.c b/src/sna/fb/fbimage.c
new file mode 100644
index 00000000..5af23890
--- /dev/null
+++ b/src/sna/fb/fbimage.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <string.h>
+
+#include "fb.h"
+#include "fbclip.h"
+
+struct fbPutZImage {
+ FbStip *src, *dst;
+ FbStride src_stride, dst_stride;
+
+ int dst_x, dst_y;
+ int x0, y0;
+};
+
+inline static void
+_fbPutZImage(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbPutZImage *data = _data;
+ int bpp = drawable->bitsPerPixel;
+
+ fbBltStip(data->src + (b->y1 - data->y0) * data->src_stride, data->src_stride,
+ (b->x1 - data->x0) * bpp,
+ data->dst + (b->y1 + data->dst_y) * data->dst_stride,
+ data->dst_stride,
+ (b->x1 + data->dst_x) * bpp,
+ (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
+ gc->alu, fb_gc(gc)->pm, bpp);
+}
+
+static void
+fbPutZImage(DrawablePtr drawable, GCPtr gc,
+ int x, int y, int width, int height,
+ FbStip *src, FbStride srcStride)
+{
+ PixmapPtr pixmap;
+ struct fbPutZImage data;
+ BoxRec box;
+
+ box.x1 = data.x0 = x;
+ box.y1 = data.y0 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ data.src = src;
+ data.src_stride = srcStride;
+
+ fbGetDrawablePixmap(drawable, pixmap, data.dst_x, data.dst_y);
+ data.dst = pixmap->devPrivate.ptr;
+ data.dst_stride = pixmap->devKind / sizeof(FbStip);
+
+ fbDrawableRun(drawable, gc, &box, _fbPutZImage, &data);
+}
+
+struct fbPutXYImage {
+ FbStip *src, *dst;
+ FbStride src_stride, dst_stride;
+
+ int dst_x, dst_y, src_x;
+ int x0, y0;
+
+ int alu, pm;
+ FbBits fgand, fgxor, bgand, bgxor;
+};
+
+inline static void
+_fbPutXYImage1(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbPutXYImage *data = _data;
+ int bpp = drawable->bitsPerPixel;
+
+ fbBltStip(data->src + (b->y1 - data->y0) * data->src_stride, data->src_stride,
+ (b->x1 - data->x0) + data->src_x,
+ (FbStip *) (data->dst + (b->y1 + data->dst_y) * data->dst_stride),
+ data->dst_stride,
+ (b->x1 + data->dst_x) * bpp,
+ (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
+ data->alu, data->pm, bpp);
+}
+
+inline static void
+_fbPutXYImageN(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbPutXYImage *data = _data;
+ int bpp = drawable->bitsPerPixel;
+
+ fbBltOne(data->src + (b->y1 - data->y0) * data->src_stride,
+ data->src_stride,
+ (b->x1 - data->x0) + data->src_x,
+ data->dst + (b->y1 + data->dst_y) * data->dst_stride,
+ data->dst_stride,
+ (b->x1 + data->dst_x) * bpp, bpp,
+ (b->x2 - b->x1) * bpp, (b->y2 - b->y1),
+ data->fgand, data->fgxor,
+ data->bgand, data->bgxor);
+}
+
+void
+fbPutXYImage(DrawablePtr drawable, GCPtr gc,
+ FbBits fg, FbBits bg, FbBits pm, int alu, Bool opaque,
+ int x, int y, int width, int height,
+ FbStip *src, FbStride srcStride, int srcX)
+{
+ PixmapPtr pixmap;
+ struct fbPutXYImage data;
+ BoxRec box;
+
+ box.x1 = data.x0 = x;
+ box.y1 = data.y0 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ data.src = src;
+ data.src_stride = srcStride;
+ data.src_x = srcX;
+
+ fbGetDrawablePixmap(drawable, pixmap, data.dst_x, data.dst_y);
+ data.dst = pixmap->devPrivate.ptr;
+ data.dst_stride = pixmap->devKind / sizeof(FbStip);
+
+ if (drawable->bitsPerPixel == 1) {
+ if (opaque)
+ data.alu = FbOpaqueStipple1Rop(alu, fg, bg);
+ else
+ data.alu = FbStipple1Rop(alu, fg);
+ data.pm = pm;
+
+ fbDrawableRun(drawable, gc, &box, _fbPutXYImage1, &data);
+ } else {
+ data.fgand = fbAnd(alu, fg, pm);
+ data.fgxor = fbXor(alu, fg, pm);
+ if (opaque) {
+ data.bgand = fbAnd(alu, bg, pm);
+ data.bgxor = fbXor(alu, bg, pm);
+ } else {
+ data.bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
+ data.bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
+ }
+
+ fbDrawableRun(drawable, gc, &box, _fbPutXYImageN, &data);
+ }
+}
+
+void
+fbPutImage(DrawablePtr drawable, GCPtr gc, int depth,
+ int x, int y, int w, int h,
+ int leftPad, int format, char *image)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ unsigned long i;
+ FbStride srcStride;
+ FbStip *src = (FbStip *)image;
+
+ DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
+
+ x += drawable->x;
+ y += drawable->y;
+
+ switch (format) {
+ case XYBitmap:
+ srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
+ fbPutXYImage(drawable, gc,
+ pgc->fg, pgc->bg, pgc->pm,
+ gc->alu, TRUE,
+ x, y, w, h,
+ src, srcStride, leftPad);
+ break;
+ case XYPixmap:
+ srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
+ for (i = (unsigned long) 1 << (drawable->depth - 1); i; i >>= 1) {
+ if (i & gc->planemask) {
+ fbPutXYImage(drawable, gc,
+ FB_ALLONES,
+ 0,
+ fbReplicatePixel(i, drawable->bitsPerPixel),
+ gc->alu,
+ TRUE, x, y, w, h, src, srcStride, leftPad);
+ src += srcStride * h;
+ }
+ }
+ break;
+ case ZPixmap:
+ srcStride = PixmapBytePad(w, drawable->depth) / sizeof(FbStip);
+ fbPutZImage(drawable, gc,
+ x, y, w, h, src, srcStride);
+ }
+}
+
+void
+fbGetImage(DrawablePtr drawable,
+ int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ FbBits *src;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+ FbStip *dst;
+ FbStride dstStride;
+
+ DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
+
+ fbGetDrawable(drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+
+ x += drawable->x;
+ y += drawable->y;
+
+ dst = (FbStip *) d;
+ if (format == ZPixmap || srcBpp == 1) {
+ FbBits pm;
+
+ pm = fbReplicatePixel(planeMask, srcBpp);
+ dstStride = PixmapBytePad(w, drawable->depth);
+ if (pm != FB_ALLONES)
+ memset(d, 0, dstStride * h);
+ dstStride /= sizeof(FbStip);
+ fbBltStip((FbStip *)(src + (y + srcYoff) * srcStride), srcStride,
+ (x + srcXoff) * srcBpp,
+ dst, dstStride, 0, w * srcBpp, h, GXcopy, pm, srcBpp);
+ } else {
+ dstStride = BitmapBytePad(w) / sizeof(FbStip);
+ fbBltPlane(src + (y + srcYoff) * srcStride,
+ srcStride,
+ (x + srcXoff) * srcBpp,
+ srcBpp,
+ dst,
+ dstStride,
+ 0,
+ w * srcBpp, h,
+ fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
+ fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
+ fbAndStip(GXcopy, 0, FB_STIP_ALLONES),
+ fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask);
+ }
+}
diff --git a/src/sna/fb/fbline.c b/src/sna/fb/fbline.c
new file mode 100644
index 00000000..04d5343c
--- /dev/null
+++ b/src/sna/fb/fbline.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include <mi.h>
+#include <micoord.h>
+#include <miline.h>
+#include <scrnintstr.h>
+
+#define POLYLINE fbPolyline8
+#define POLYSEGMENT fbPolySegment8
+#define BITS BYTE
+#define BITS2 CARD16
+#define BITS4 CARD32
+#include "fblinebits.h"
+#undef BITS
+#undef BITS2
+#undef BITS4
+#undef POLYSEGMENT
+#undef POLYLINE
+
+#define POLYLINE fbPolyline16
+#define POLYSEGMENT fbPolySegment16
+#define BITS CARD16
+#define BITS2 CARD32
+#include "fblinebits.h"
+#undef BITS
+#undef BITS2
+#undef POLYSEGMENT
+#undef POLYLINE
+
+#define POLYLINE fbPolyline32
+#define POLYSEGMENT fbPolySegment32
+#define BITS CARD32
+#include "fblinebits.h"
+#undef BITS
+#undef POLYSEGMENT
+#undef POLYLINE
+
+static void
+fbZeroLine(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt)
+{
+ int x1, y1, x2, y2;
+ int x, y;
+ int dashOffset;
+
+ x = drawable->x;
+ y = drawable->y;
+ x1 = pt->x;
+ y1 = pt->y;
+ dashOffset = gc->dashOffset;
+ while (--n) {
+ ++pt;
+ x2 = pt->x;
+ y2 = pt->y;
+ if (mode == CoordModePrevious) {
+ x2 += x1;
+ y2 += y1;
+ }
+ fbSegment(drawable, gc,
+ x1 + x, y1 + y,
+ x2 + x, y2 + y,
+ n == 1 && gc->capStyle != CapNotLast, &dashOffset);
+ x1 = x2;
+ y1 = y2;
+ }
+}
+
+static void
+fbZeroSegment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg)
+{
+ int dashOffset;
+ int16_t x, y;
+ Bool drawLast = gc->capStyle != CapNotLast;
+
+ x = drawable->x;
+ y = drawable->y;
+ while (n--) {
+ dashOffset = gc->dashOffset;
+ fbSegment(drawable, gc,
+ seg->x1 + x, seg->y1 + y,
+ seg->x2 + x, seg->y2 + y,
+ drawLast, &dashOffset);
+ seg++;
+ }
+}
+
+void
+fbFixCoordModePrevious(int n, DDXPointPtr pt)
+{
+ int16_t x = pt->x;
+ int16_t y = pt->y;
+ while (--n) {
+ pt++;
+ x = (pt->x += x);
+ y = (pt->y += y);
+ }
+}
+
+void
+fbPolyLine(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt)
+{
+ void (*raster)(DrawablePtr, GCPtr, int mode, int n, DDXPointPtr pt);
+
+ DBG(("%s x %d, width=%d, fill=%d, line=%d\n",
+ __FUNCTION__, n, gc->lineWidth, gc->fillStyle, gc->lineStyle));
+
+ if (gc->lineWidth == 0) {
+ raster = fbZeroLine;
+ if (gc->fillStyle == FillSolid && gc->lineStyle == LineSolid) {
+ switch (drawable->bitsPerPixel) {
+ case 8:
+ raster = fbPolyline8;
+ break;
+ case 16:
+ raster = fbPolyline16;
+ break;
+ case 32:
+ raster = fbPolyline32;
+ break;
+ }
+ }
+ } else {
+ if (gc->lineStyle != LineSolid)
+ raster = miWideDash;
+ else
+ raster = miWideLine;
+ }
+ raster(drawable, gc, mode, n, pt);
+}
+
+void
+fbPolySegment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg)
+{
+ void (*raster)(DrawablePtr drawable, GCPtr gc, int n, xSegment * seg);
+
+ DBG(("%s x %d, width=%d, fill=%d, line=%d\n",
+ __FUNCTION__, n, gc->lineWidth, gc->fillStyle, gc->lineStyle));
+
+ if (gc->lineWidth == 0) {
+ raster = fbZeroSegment;
+ if (gc->fillStyle == FillSolid && gc->lineStyle == LineSolid) {
+ switch (drawable->bitsPerPixel) {
+ case 8:
+ raster = fbPolySegment8;
+ break;
+ case 16:
+ raster = fbPolySegment16;
+ break;
+ case 32:
+ raster = fbPolySegment32;
+ break;
+ }
+ }
+ } else
+ raster = miPolySegment;
+
+ raster(drawable, gc, n, seg);
+}
diff --git a/src/sna/fb/fblinebits.h b/src/sna/fb/fblinebits.h
new file mode 100644
index 00000000..db315d81
--- /dev/null
+++ b/src/sna/fb/fblinebits.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
+#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x)))
+
+static void
+POLYLINE(DrawablePtr drawable, GCPtr gc, int mode, int n_0, DDXPointPtr pt_0)
+{
+ int xoff = drawable->x;
+ int yoff = drawable->y;
+ unsigned int bias = miGetZeroLineBias(drawable->pScreen);
+ const BoxRec *clip = RegionRects(gc->pCompositeClip);
+ const BoxRec *const last_clip = clip + RegionNumRects(gc->pCompositeClip);
+
+ FbBits *dst;
+ int dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ BITS *bits, *bitsBase;
+ FbStride bitsStride;
+ BITS xor = fb_gc(gc)->xor;
+ BITS and = fb_gc(gc)->and;
+
+
+ int e, e1, e3, len;
+ int stepmajor, stepminor;
+ int octant;
+
+ if (mode == CoordModePrevious)
+ fbFixCoordModePrevious(n_0, pt_0);
+
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
+ bitsBase =
+ ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
+ do {
+ INT32 *pt = (INT32 *)pt_0;
+ int n = n_0;
+ INT32 pt1, pt2;
+
+ INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff);
+ INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1);
+
+ pt1 = *pt++; n--;
+ pt2 = *pt++; n--;
+ for (;;) {
+ if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) {
+ int dashoffset = 0;
+ fbSegment1(drawable, gc, clip,
+ intToX(pt1) + xoff, intToY(pt1) + yoff,
+ intToX(pt2) + xoff, intToY(pt2) + yoff,
+ n == 0 && gc->capStyle != CapNotLast, &dashoffset);
+ if (!n)
+ return;
+
+ pt1 = pt2;
+ pt2 = *pt++;
+ n--;
+ } else {
+ bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1);
+ for (;;) {
+ CalcLineDeltas(intToX(pt1), intToY(pt1),
+ intToX(pt2), intToY(pt2),
+ len, e1, stepmajor, stepminor, 1, bitsStride,
+ octant);
+ if (len < e1) {
+ e3 = len;
+ len = e1;
+ e1 = e3;
+
+ e3 = stepminor;
+ stepminor = stepmajor;
+ stepmajor = e3;
+ SetYMajorOctant(octant);
+ }
+ e = -len;
+ e1 <<= 1;
+ e3 = e << 1;
+ FIXUP_ERROR(e, octant, bias);
+ if (and == 0) {
+ while (len--) {
+ WRITE(bits, xor);
+ bits += stepmajor;
+ e += e1;
+ if (e >= 0) {
+ bits += stepminor;
+ e += e3;
+ }
+ }
+ } else {
+ while (len--) {
+ RROP(bits, and, xor);
+ bits += stepmajor;
+ e += e1;
+ if (e >= 0) {
+ bits += stepminor;
+ e += e3;
+ }
+ }
+ }
+ if (!n) {
+ if (gc->capStyle != CapNotLast &&
+ pt2 != *((INT32 *)pt_0)) {
+ RROP(bits, and, xor);
+ }
+ return;
+ }
+ pt1 = pt2;
+ pt2 = *pt++;
+ --n;
+ if (isClipped(pt2, ul, lr))
+ break;
+ }
+ }
+ }
+ } while (++clip != last_clip);
+}
+
+static void
+POLYSEGMENT(DrawablePtr drawable, GCPtr gc, int n_0, xSegment *seg_0)
+{
+ int xoff = drawable->x;
+ int yoff = drawable->y;
+ unsigned int bias = miGetZeroLineBias(drawable->pScreen);
+ const BoxRec *clip = RegionRects(gc->pCompositeClip);
+ const BoxRec *const last_clip = clip + RegionNumRects(gc->pCompositeClip);
+
+ FbBits *dst;
+ int dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+
+ BITS *bits, *bitsBase;
+ FbStride bitsStride;
+ FbBits xor = fb_gc(gc)->xor;
+ FbBits and = fb_gc(gc)->and;
+
+ int e, e1, e3, len;
+ int stepmajor, stepminor;
+ int octant;
+ bool capNotLast = gc->capStyle == CapNotLast;
+
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
+ bitsBase =
+ ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
+
+ do {
+ INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff);
+ INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1);
+ uint64_t *pt = (uint64_t *)seg_0;
+ int n = n_0;
+
+ while (n--) {
+ union {
+ int32_t pt32[2];
+ uint64_t pt64;
+ } u;
+
+ u.pt64 = *pt++;
+ if (isClipped(u.pt32[0], ul, lr) | isClipped(u.pt32[1], ul, lr)) {
+ int dashoffset = 0;
+ fbSegment1(drawable, gc, clip,
+ intToX(u.pt32[0]) + xoff, intToY(u.pt32[0]) + yoff,
+ intToX(u.pt32[1]) + xoff, intToY(u.pt32[1]) + yoff,
+ !capNotLast, &dashoffset);
+ } else {
+ CalcLineDeltas(intToX(u.pt32[0]), intToY(u.pt32[0]),
+ intToX(u.pt32[1]), intToY(u.pt32[1]),
+ len, e1, stepmajor, stepminor, 1, bitsStride,
+ octant);
+ if (e1 == 0 && len > 3) {
+ int x1, x2;
+ FbBits *dstLine;
+ int dstX, width;
+ FbBits startmask, endmask;
+ int nmiddle;
+
+ if (stepmajor < 0) {
+ x1 = intToX(u.pt32[1]);
+ x2 = intToX(u.pt32[0]) + 1;
+ if (capNotLast)
+ x1++;
+ } else {
+ x1 = intToX(u.pt32[0]);
+ x2 = intToX(u.pt32[1]);
+ if (!capNotLast)
+ x2++;
+ }
+ dstX = (x1 + xoff + dstXoff) * (sizeof(BITS) * 8);
+ width = (x2 - x1) * (sizeof(BITS) * 8);
+
+ dstLine = dst + (intToY(u.pt32[0]) + yoff + dstYoff) * dstStride;
+ dstLine += dstX >> FB_SHIFT;
+ dstX &= FB_MASK;
+ FbMaskBits(dstX, width, startmask, nmiddle, endmask);
+ if (startmask) {
+ WRITE(dstLine,
+ FbDoMaskRRop(READ(dstLine), and, xor,
+ startmask));
+ dstLine++;
+ }
+ if (!and)
+ while (nmiddle--)
+ WRITE(dstLine++, xor);
+ else
+ while (nmiddle--) {
+ WRITE(dstLine,
+ FbDoRRop(READ(dstLine), and, xor));
+ dstLine++;
+ }
+ if (endmask)
+ WRITE(dstLine,
+ FbDoMaskRRop(READ(dstLine), and, xor,
+ endmask));
+ } else {
+ bits = bitsBase + intToY(u.pt32[0]) * bitsStride + intToX(u.pt32[0]);
+ if (len < e1) {
+ e3 = len;
+ len = e1;
+ e1 = e3;
+
+ e3 = stepminor;
+ stepminor = stepmajor;
+ stepmajor = e3;
+ SetYMajorOctant(octant);
+ }
+ e = -len;
+ e1 <<= 1;
+ e3 = e << 1;
+ FIXUP_ERROR(e, octant, bias);
+ if (!capNotLast)
+ len++;
+ if (and == 0) {
+ while (len--) {
+ WRITE(bits, xor);
+ bits += stepmajor;
+ e += e1;
+ if (e >= 0) {
+ bits += stepminor;
+ e += e3;
+ }
+ }
+ } else {
+ while (len--) {
+ RROP(bits, and, xor);
+ bits += stepmajor;
+ e += e1;
+ if (e >= 0) {
+ bits += stepminor;
+ e += e3;
+ }
+ }
+ }
+ }
+ }
+ }
+ } while (++clip != last_clip);
+}
+
+#undef RROP
+#undef isClipped
diff --git a/src/sna/fb/fbpict.c b/src/sna/fb/fbpict.c
new file mode 100644
index 00000000..f6bcb645
--- /dev/null
+++ b/src/sna/fb/fbpict.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright © 2000 SuSE, Inc.
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#include <string.h>
+
+#include "fb.h"
+
+#include <picturestr.h>
+#include <mipict.h>
+#include "fbpict.h"
+
+void
+fbComposite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ pixman_image_t *src, *mask, *dest;
+ int src_xoff, src_yoff;
+ int msk_xoff, msk_yoff;
+ int dst_xoff, dst_yoff;
+
+ miCompositeSourceValidate(pSrc);
+ if (pMask)
+ miCompositeSourceValidate(pMask);
+
+ src = image_from_pict(pSrc, FALSE, &src_xoff, &src_yoff);
+ mask = image_from_pict(pMask, FALSE, &msk_xoff, &msk_yoff);
+ dest = image_from_pict(pDst, TRUE, &dst_xoff, &dst_yoff);
+
+ if (src && dest && !(pMask && !mask)) {
+ pixman_image_composite(op, src, mask, dest,
+ xSrc + src_xoff, ySrc + src_yoff,
+ xMask + msk_xoff, yMask + msk_yoff,
+ xDst + dst_xoff, yDst + dst_yoff, width, height);
+ }
+
+ free_pixman_pict(pSrc, src);
+ free_pixman_pict(pMask, mask);
+ free_pixman_pict(pDst, dest);
+}
+
+static pixman_image_t *
+create_solid_fill_image(PicturePtr pict)
+{
+ PictSolidFill *solid = &pict->pSourcePict->solidFill;
+ pixman_color_t color;
+ CARD32 a, r, g, b;
+
+ a = (solid->color & 0xff000000) >> 24;
+ r = (solid->color & 0x00ff0000) >> 16;
+ g = (solid->color & 0x0000ff00) >> 8;
+ b = (solid->color & 0x000000ff) >> 0;
+
+ color.alpha = (a << 8) | a;
+ color.red = (r << 8) | r;
+ color.green = (g << 8) | g;
+ color.blue = (b << 8) | b;
+
+ return pixman_image_create_solid_fill(&color);
+}
+
+static pixman_image_t *
+create_linear_gradient_image(PictGradient * gradient)
+{
+ PictLinearGradient *linear = (PictLinearGradient *) gradient;
+ pixman_point_fixed_t p1;
+ pixman_point_fixed_t p2;
+
+ p1.x = linear->p1.x;
+ p1.y = linear->p1.y;
+ p2.x = linear->p2.x;
+ p2.y = linear->p2.y;
+
+ return pixman_image_create_linear_gradient(&p1, &p2,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_radial_gradient_image(PictGradient * gradient)
+{
+ PictRadialGradient *radial = (PictRadialGradient *) gradient;
+ pixman_point_fixed_t c1;
+ pixman_point_fixed_t c2;
+
+ c1.x = radial->c1.x;
+ c1.y = radial->c1.y;
+ c2.x = radial->c2.x;
+ c2.y = radial->c2.y;
+
+ return pixman_image_create_radial_gradient(&c1, &c2, radial->c1.radius,
+ radial->c2.radius,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_conical_gradient_image(PictGradient * gradient)
+{
+ PictConicalGradient *conical = (PictConicalGradient *) gradient;
+ pixman_point_fixed_t center;
+
+ center.x = conical->center.x;
+ center.y = conical->center.y;
+
+ return pixman_image_create_conical_gradient(&center, conical->angle,
+ (pixman_gradient_stop_t *)
+ gradient->stops,
+ gradient->nstops);
+}
+
+static pixman_image_t *
+create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+{
+ PixmapPtr pixmap;
+ FbBits *bits;
+ FbStride stride;
+ int bpp;
+ pixman_image_t *image;
+
+ fbGetDrawablePixmap(pict->pDrawable, pixmap, *xoff, *yoff);
+ fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+
+ image = pixman_image_create_bits((pixman_format_code_t) pict->format,
+ pixmap->drawable.width,
+ pixmap->drawable.height, (uint32_t *) bits,
+ stride * sizeof(FbStride));
+
+ if (!image)
+ return NULL;
+
+ /* pCompositeClip is undefined for source pictures, so
+ * only set the clip region for pictures with drawables
+ */
+ if (has_clip) {
+ if (pict->clientClipType != CT_NONE)
+ pixman_image_set_has_client_clip(image, TRUE);
+
+ if (*xoff || *yoff)
+ pixman_region_translate(pict->pCompositeClip, *xoff, *yoff);
+
+ pixman_image_set_clip_region(image, pict->pCompositeClip);
+
+ if (*xoff || *yoff)
+ pixman_region_translate(pict->pCompositeClip, -*xoff, -*yoff);
+ }
+
+ /* Indexed table */
+ if (pict->pFormat->index.devPrivate)
+ pixman_image_set_indexed(image, pict->pFormat->index.devPrivate);
+
+ /* Add in drawable origin to position within the image */
+ *xoff += pict->pDrawable->x;
+ *yoff += pict->pDrawable->y;
+
+ return image;
+}
+
+static pixman_image_t *image_from_pict_internal(PicturePtr pict, Bool has_clip,
+ int *xoff, int *yoff,
+ Bool is_alpha_map);
+
+static void
+set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
+ int *xoff, int *yoff, Bool is_alpha_map)
+{
+ pixman_repeat_t repeat;
+ pixman_filter_t filter;
+
+ if (pict->transform) {
+ /* For source images, adjust the transform to account
+ * for the drawable offset within the pixman image,
+ * then set the offset to 0 as it will be used
+ * to compute positions within the transformed image.
+ */
+ if (!has_clip) {
+ struct pixman_transform adjusted;
+
+ adjusted = *pict->transform;
+ pixman_transform_translate(&adjusted,
+ NULL,
+ pixman_int_to_fixed(*xoff),
+ pixman_int_to_fixed(*yoff));
+ pixman_image_set_transform(image, &adjusted);
+ *xoff = 0;
+ *yoff = 0;
+ }
+ else
+ pixman_image_set_transform(image, pict->transform);
+ }
+
+ switch (pict->repeatType) {
+ default:
+ case RepeatNone:
+ repeat = PIXMAN_REPEAT_NONE;
+ break;
+
+ case RepeatPad:
+ repeat = PIXMAN_REPEAT_PAD;
+ break;
+
+ case RepeatNormal:
+ repeat = PIXMAN_REPEAT_NORMAL;
+ break;
+
+ case RepeatReflect:
+ repeat = PIXMAN_REPEAT_REFLECT;
+ break;
+ }
+
+ pixman_image_set_repeat(image, repeat);
+
+ /* Fetch alpha map unless 'pict' is being used
+ * as the alpha map for this operation
+ */
+ if (pict->alphaMap && !is_alpha_map) {
+ int alpha_xoff, alpha_yoff;
+ pixman_image_t *alpha_map =
+ image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff,
+ &alpha_yoff, TRUE);
+
+ pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
+ pict->alphaOrigin.y);
+
+ free_pixman_pict(pict->alphaMap, alpha_map);
+ }
+
+ pixman_image_set_component_alpha(image, pict->componentAlpha);
+
+ switch (pict->filter) {
+ default:
+ case PictFilterNearest:
+ case PictFilterFast:
+ filter = PIXMAN_FILTER_NEAREST;
+ break;
+
+ case PictFilterBilinear:
+ case PictFilterGood:
+ filter = PIXMAN_FILTER_BILINEAR;
+ break;
+
+ case PictFilterConvolution:
+ filter = PIXMAN_FILTER_CONVOLUTION;
+ break;
+ }
+
+ pixman_image_set_filter(image, filter,
+ (pixman_fixed_t *) pict->filter_params,
+ pict->filter_nparams);
+ pixman_image_set_source_clipping(image, TRUE);
+}
+
+static pixman_image_t *
+image_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
+ Bool is_alpha_map)
+{
+ pixman_image_t *image = NULL;
+
+ if (!pict)
+ return NULL;
+
+ if (pict->pDrawable) {
+ image = create_bits_picture(pict, has_clip, xoff, yoff);
+ }
+ else if (pict->pSourcePict) {
+ SourcePict *sp = pict->pSourcePict;
+
+ if (sp->type == SourcePictTypeSolidFill) {
+ image = create_solid_fill_image(pict);
+ }
+ else {
+ PictGradient *gradient = &pict->pSourcePict->gradient;
+
+ if (sp->type == SourcePictTypeLinear)
+ image = create_linear_gradient_image(gradient);
+ else if (sp->type == SourcePictTypeRadial)
+ image = create_radial_gradient_image(gradient);
+ else if (sp->type == SourcePictTypeConical)
+ image = create_conical_gradient_image(gradient);
+ }
+ *xoff = *yoff = 0;
+ }
+
+ if (image)
+ set_image_properties(image, pict, has_clip, xoff, yoff, is_alpha_map);
+
+ return image;
+}
+
+pixman_image_t *
+image_from_pict(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+{
+ return image_from_pict_internal(pict, has_clip, xoff, yoff, FALSE);
+}
+
+void
+free_pixman_pict(PicturePtr pict, pixman_image_t * image)
+{
+ if (image)
+ pixman_image_unref(image);
+}
diff --git a/src/sna/fb/fbpict.h b/src/sna/fb/fbpict.h
new file mode 100644
index 00000000..6bcee34b
--- /dev/null
+++ b/src/sna/fb/fbpict.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef FBPICT_H
+#define FBPICT_H
+
+extern void
+fbComposite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+
+extern pixman_image_t *image_from_pict(PicturePtr pict,
+ Bool has_clip,
+ int *xoff, int *yoff);
+
+extern void free_pixman_pict(PicturePtr, pixman_image_t *);
+
+#endif /* FBPICT_H */
diff --git a/src/sna/fb/fbpoint.c b/src/sna/fb/fbpoint.c
new file mode 100644
index 00000000..d3f796e6
--- /dev/null
+++ b/src/sna/fb/fbpoint.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include <micoord.h>
+
+#define DOTS fbDots8
+#define BITS BYTE
+#define BITS2 CARD16
+#define BITS4 CARD32
+#include "fbpointbits.h"
+#undef BITS
+#undef BITS2
+#undef BITS4
+#undef DOTS
+
+#define DOTS fbDots16
+#define BITS CARD16
+#define BITS2 CARD32
+#include "fbpointbits.h"
+#undef BITS
+#undef BITS2
+#undef DOTS
+
+#define DOTS fbDots32
+#define BITS CARD32
+#include "fbpointbits.h"
+#undef ARC
+#undef BITS
+#undef DOTS
+
+static void
+fbDots(FbBits *dstOrig, FbStride dstStride, int dstBpp,
+ RegionPtr clip,
+ xPoint *pts, int n,
+ int xorg, int yorg,
+ int xoff, int yoff,
+ FbBits andOrig, FbBits xorOrig)
+{
+ FbStip *dst = (FbStip *) dstOrig;
+ FbStip and = andOrig;
+ FbStip xor = xorOrig;
+
+ while (n--) {
+ int x = pts->x + xorg;
+ int y = pts->y + yorg;
+ pts++;
+ if (RegionContainsPoint(clip, x, y, NULL)) {
+ FbStip mask;
+ FbStip *d;
+
+ x = (x + xoff) * dstBpp;
+ d = dst + ((y + yoff) * dstStride) + (x >> FB_STIP_SHIFT);
+ x &= FB_STIP_MASK;
+
+ mask = FbStipMask(x, dstBpp);
+ WRITE(d, FbDoMaskRRop(READ(d), and, xor, mask));
+ }
+ }
+}
+
+void
+fbPolyPoint(DrawablePtr drawable, GCPtr gc,
+ int mode, int n, xPoint *pt)
+{
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ void (*dots)(FbBits *dst, FbStride dstStride, int dstBpp,
+ RegionPtr clip,
+ xPoint *pts, int n,
+ int xorg, int yorg,
+ int xoff, int yoff,
+ FbBits and, FbBits xor);
+ FbBits and, xor;
+
+ DBG(("%s x %d\n", __FUNCTION__, n));
+
+ if (mode == CoordModePrevious)
+ fbFixCoordModePrevious(n, pt);
+
+ fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ and = fb_gc(gc)->and;
+ xor = fb_gc(gc)->xor;
+ dots = fbDots;
+ switch (dstBpp) {
+ case 8:
+ dots = fbDots8;
+ break;
+ case 16:
+ dots = fbDots16;
+ break;
+ case 32:
+ dots = fbDots32;
+ break;
+ }
+ dots(dst, dstStride, dstBpp, gc->pCompositeClip, pt, n,
+ drawable->x, drawable->y, dstXoff, dstYoff, and, xor);
+}
diff --git a/src/sna/fb/fbpointbits.h b/src/sna/fb/fbpointbits.h
new file mode 100644
index 00000000..40a25c68
--- /dev/null
+++ b/src/sna/fb/fbpointbits.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x)))
+#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
+
+static void
+DOTS(FbBits * dst,
+ FbStride dstStride,
+ int dstBpp,
+ RegionPtr region,
+ xPoint * ptsOrig,
+ int npt, int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor)
+{
+ uint32_t *pts = (uint32_t *) ptsOrig;
+ BITS *bits = (BITS *) dst;
+ BITS bxor = (BITS) xor;
+ BITS band = (BITS) and;
+ FbStride bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
+
+ bits += bitsStride * (yorg + yoff) + (xorg + xoff);
+
+ if (region->data == NULL) {
+ INT32 ul = coordToInt(region->extents.x1 - xorg,
+ region->extents.y1 - yorg);
+ INT32 lr = coordToInt(region->extents.x2 - xorg - 1,
+ region->extents.y2 - yorg - 1);
+
+ if (and == 0) {
+ while (npt >= 2) {
+ union {
+ uint32_t pt32[2];
+ uint64_t pt64;
+ } pt;
+ pt.pt64 = *(uint64_t *)pts;
+ if (!isClipped(pt.pt32[0], ul, lr)) {
+ BITS *point = bits + intToY(pt.pt32[0]) * bitsStride + intToX(pt.pt32[0]);
+ WRITE(point, bxor);
+ }
+ if (!isClipped(pt.pt32[1], ul, lr)) {
+ BITS *point = bits + intToY(pt.pt32[1]) * bitsStride + intToX(pt.pt32[1]);
+ WRITE(point, bxor);
+ }
+
+ pts += 2;
+ npt -= 2;
+ }
+ if (npt) {
+ uint32_t pt = *pts;
+ if (!isClipped(pt, ul, lr)) {
+ BITS *point = bits + intToY(pt) * bitsStride + intToX(pt);
+ WRITE(point, bxor);
+ }
+ }
+ } else {
+ while (npt--) {
+ uint32_t pt = *pts++;
+ if (!isClipped(pt, ul, lr)) {
+ BITS *point = bits + intToY(pt) * bitsStride + intToX(pt);
+ RROP(point, band, bxor);
+ }
+ }
+ }
+ } else {
+ if (and == 0) {
+ while (npt--) {
+ uint32_t pt = *pts++;
+ if (RegionContainsPoint(region,
+ intToX(pt), intToY(pt),
+ NULL)) {
+ BITS *point = bits + intToY(pt) * bitsStride + intToX(pt);
+ WRITE(point, bxor);
+ }
+ }
+ } else {
+ while (npt--) {
+ uint32_t pt = *pts++;
+ if (RegionContainsPoint(region,
+ intToX(pt), intToY(pt),
+ NULL)) {
+ BITS *point = bits + intToY(pt) * bitsStride + intToX(pt);
+ RROP(point, band, bxor);
+ }
+ }
+ }
+ }
+}
+
+#undef RROP
+#undef isClipped
diff --git a/src/sna/fb/fbpush.c b/src/sna/fb/fbpush.c
new file mode 100644
index 00000000..c53f0adf
--- /dev/null
+++ b/src/sna/fb/fbpush.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include "fbclip.h"
+
+static void
+fbPushPattern(DrawablePtr drawable, GCPtr gc,
+ FbStip *src, FbStride srcStride, int srcX,
+ int x, int y, int width, int height)
+{
+ FbStip *s, bitsMask, bitsMask0, bits;
+ int xspan;
+ int w;
+ int lenspan;
+
+ src += srcX >> FB_STIP_SHIFT;
+ srcX &= FB_STIP_MASK;
+
+ bitsMask0 = FbStipMask(srcX, 1);
+
+ while (height--) {
+ bitsMask = bitsMask0;
+ w = width;
+ s = src;
+ src += srcStride;
+ bits = READ(s++);
+ xspan = x;
+ while (w) {
+ if (bits & bitsMask) {
+ lenspan = 0;
+ do {
+ if (++lenspan == w)
+ break;
+
+ bitsMask = FbStipRight(bitsMask, 1);
+ if (!bitsMask) {
+ bits = READ(s++);
+ bitsMask = FbBitsMask(0, 1);
+ }
+ } while (bits & bitsMask);
+ fbFill(drawable, gc, xspan, y, lenspan, 1);
+ xspan += lenspan;
+ w -= lenspan;
+ } else {
+ do {
+ xspan++;
+ if (!--w)
+ break;
+
+ bitsMask = FbStipRight(bitsMask, 1);
+ if (!bitsMask) {
+ bits = READ(s++);
+ bitsMask = FbBitsMask(0, 1);
+ }
+ } while (!(bits & bitsMask));
+ }
+ }
+ y++;
+ }
+}
+
+static void
+fbPushFill(DrawablePtr drawable, GCPtr gc,
+ FbStip *src, FbStride srcStride, int srcX,
+ int x, int y, int width, int height)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+
+ if (gc->fillStyle == FillSolid) {
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ int dstX;
+ int dstWidth;
+
+ fbGetDrawable(drawable, dst,
+ dstStride, dstBpp, dstXoff, dstYoff);
+ dst = dst + (y + dstYoff) * dstStride;
+ dstX = (x + dstXoff) * dstBpp;
+ dstWidth = width * dstBpp;
+ if (dstBpp == 1) {
+ fbBltStip(src, srcStride, srcX,
+ (FbStip *)dst, dstStride, dstX,
+ dstWidth, height,
+ FbStipple1Rop(gc->alu, gc->fgPixel), pgc->pm, dstBpp);
+ } else {
+ fbBltOne(src, srcStride, srcX,
+ dst, dstStride, dstX, dstBpp,
+ dstWidth, height,
+ pgc->and, pgc->xor,
+ fbAnd(GXnoop, (FbBits) 0, FB_ALLONES),
+ fbXor(GXnoop, (FbBits) 0, FB_ALLONES));
+ }
+ } else
+ fbPushPattern(drawable, gc, src, srcStride, srcX,
+ x, y, width, height);
+}
+
+struct fbPushImage {
+ FbStip *src;
+ FbStride stride;
+ int x0, y0;
+};
+
+inline static void
+_fbPushImage(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbPushImage *data = _data;
+
+ fbPushFill(drawable, gc,
+ data->src + (b->y1 - data->y0) * data->stride, data->stride,
+ b->x1 - data->x0,
+ b->x1, b->y1,
+ b->x2 - b->x1, b->y2 - b->y1);
+}
+
+void
+fbPushImage(DrawablePtr drawable, GCPtr gc,
+ FbStip *src, FbStride stride, int dx,
+ int x, int y, int width, int height)
+{
+ struct fbPushImage data;
+ BoxRec box;
+
+ DBG(("%s (%d, %d)x(%d, %d)", __FUNCTION__, x, y, width, height));
+
+ data.src = src;
+ data.stride = stride;
+ data.y0 = y;
+ data.x0 = x - dx;
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ fbDrawableRun(drawable, gc, &box, _fbPushImage, &data);
+}
+
+void
+fbPushPixels(GCPtr gc, PixmapPtr bitmap, DrawablePtr drawable,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ FbStip *stip;
+ FbStride stipStride;
+ int stipBpp;
+ _X_UNUSED int stipXoff, stipYoff;
+
+ DBG(("%s bitmap=%x%d\n", __FUNCTION__,
+ bitmap->drawable.width, bitmap->drawable.height));
+
+ fbGetStipDrawable(&bitmap->drawable, stip,
+ stipStride, stipBpp, stipXoff, stipYoff);
+
+ fbPushImage(drawable, gc, stip, stipStride, 0, xOrg, yOrg, dx, dy);
+}
diff --git a/src/sna/fb/fbrop.h b/src/sna/fb/fbrop.h
new file mode 100644
index 00000000..9eb1fc38
--- /dev/null
+++ b/src/sna/fb/fbrop.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef _FBROP_H_
+#define _FBROP_H_
+
+#define FbDestInvarientRop(alu,pm) ((pm) == FB_ALLONES && \
+ (((alu) >> 1 & 5) == ((alu) & 5)))
+
+#define FbDestInvarientMergeRop() (_ca1 == 0 && _cx1 == 0)
+
+/* AND has higher precedence than XOR */
+
+#define FbDoMergeRop(src, dst) \
+ (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2))
+
+#define FbDoDestInvarientMergeRop(src) (((src) & _ca2) ^ _cx2)
+
+#define FbDoMaskMergeRop(src, dst, mask) \
+ (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask)))
+
+#define FbDoLeftMaskByteMergeRop(dst, src, lb, l) { \
+ FbBits __xor = ((src) & _ca2) ^ _cx2; \
+ FbDoLeftMaskByteRRop(dst,lb,l,((src) & _ca1) ^ _cx1,__xor); \
+}
+
+#define FbDoRightMaskByteMergeRop(dst, src, rb, r) { \
+ FbBits __xor = ((src) & _ca2) ^ _cx2; \
+ FbDoRightMaskByteRRop(dst,rb,r,((src) & _ca1) ^ _cx1,__xor); \
+}
+
+#define FbDoRRop(dst, and, xor) (((dst) & (and)) ^ (xor))
+
+#define FbDoMaskRRop(dst, and, xor, mask) \
+ (((dst) & ((and) | ~(mask))) ^ (xor & mask))
+
+/*
+ * Take a single bit (0 or 1) and generate a full mask
+ */
+#define fbFillFromBit(b,t) (~((t) ((b) & 1)-1))
+
+#define fbXorT(rop,fg,pm,t) ((((fg) & fbFillFromBit((rop) >> 1,t)) | \
+ (~(fg) & fbFillFromBit((rop) >> 3,t))) & (pm))
+
+#define fbAndT(rop,fg,pm,t) ((((fg) & fbFillFromBit (rop ^ (rop>>1),t)) | \
+ (~(fg) & fbFillFromBit((rop>>2) ^ (rop>>3),t))) | \
+ ~(pm))
+
+#define fbXor(rop,fg,pm) fbXorT(rop,fg,pm,FbBits)
+
+#define fbAnd(rop,fg,pm) fbAndT(rop,fg,pm,FbBits)
+
+#define fbXorStip(rop,fg,pm) fbXorT(rop,fg,pm,FbStip)
+
+#define fbAndStip(rop,fg,pm) fbAndT(rop,fg,pm,FbStip)
+
+/*
+ * Stippling operations;
+ */
+extern const FbBits *const fbStippleTable[];
+
+#define FbStippleRRop(dst, b, fa, fx, ba, bx) \
+ (FbDoRRop(dst, fa, fx) & b) | (FbDoRRop(dst, ba, bx) & ~b)
+
+#define FbStippleRRopMask(dst, b, fa, fx, ba, bx, m) \
+ (FbDoMaskRRop(dst, fa, fx, m) & (b)) | (FbDoMaskRRop(dst, ba, bx, m) & ~(b))
+
+#define FbDoLeftMaskByteStippleRRop(dst, b, fa, fx, ba, bx, lb, l) { \
+ FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \
+ FbDoLeftMaskByteRRop(dst, lb, l, ((fa) & (b)) | ((ba) & ~(b)), __xor); \
+}
+
+#define FbDoRightMaskByteStippleRRop(dst, b, fa, fx, ba, bx, rb, r) { \
+ FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \
+ FbDoRightMaskByteRRop(dst, rb, r, ((fa) & (b)) | ((ba) & ~(b)), __xor); \
+}
+
+#define FbOpaqueStipple(b, fg, bg) (((fg) & (b)) | ((bg) & ~(b)))
+
+/*
+ * Compute rop for using tile code for 1-bit dest stipples; modifies
+ * existing rop to flip depending on pixel values
+ */
+#define FbStipple1RopPick(alu,b) (((alu) >> (2 - (((b) & 1) << 1))) & 3)
+
+#define FbOpaqueStipple1Rop(alu,fg,bg) (FbStipple1RopPick(alu,fg) | \
+ (FbStipple1RopPick(alu,bg) << 2))
+
+#define FbStipple1Rop(alu,fg) (FbStipple1RopPick(alu,fg) | 4)
+
+#endif
diff --git a/src/sna/fb/fbseg.c b/src/sna/fb/fbseg.c
new file mode 100644
index 00000000..5b8173f0
--- /dev/null
+++ b/src/sna/fb/fbseg.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <stdlib.h>
+
+#include "fb.h"
+#include "fbclip.h"
+#include <mi.h>
+#include <miline.h>
+#include <scrnintstr.h>
+
+#define FbDashDeclare \
+ unsigned char *__dash, *__firstDash, *__lastDash
+
+#define FbDashInit(gc,pgc,dashOffset,dashlen,even) { \
+ (even) = TRUE; \
+ __firstDash = (gc)->dash; \
+ __lastDash = __firstDash + (gc)->numInDashList; \
+ (dashOffset) %= (pgc)->dashLength; \
+ \
+ __dash = __firstDash; \
+ while ((dashOffset) >= ((dashlen) = *__dash)) { \
+ (dashOffset) -= (dashlen); \
+ (even) = 1-(even); \
+ if (++__dash == __lastDash) \
+ __dash = __firstDash; \
+ } \
+ (dashlen) -= (dashOffset); \
+}
+
+#define FbDashNext(dashlen) { \
+ if (++__dash == __lastDash) \
+ __dash = __firstDash; \
+ (dashlen) = *__dash; \
+}
+
+/* as numInDashList is always even, this case can skip a test */
+
+#define FbDashNextEven(dashlen) { \
+ (dashlen) = *++__dash; \
+}
+
+#define FbDashNextOdd(dashlen) FbDashNext(dashlen)
+
+#define FbDashStep(dashlen,even) { \
+ if (!--(dashlen)) { \
+ FbDashNext(dashlen); \
+ (even) = 1-(even); \
+ } \
+}
+
+#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \
+ ((dir < 0) ? FbStipLeft(mask,bpp) : \
+ FbStipRight(mask,bpp)))
+
+typedef void FbBres(DrawablePtr drawable,
+ GCPtr gc,
+ int dashOffset,
+ int sdx,
+ int sdy,
+ int axis, int x, int y, int e, int e1, int e3, int len);
+
+#define BRESSOLID fbBresSolid8
+#define BRESSOLIDR fbBresSolidR8
+#define BRESDASH fbBresDash8
+#define BITS BYTE
+#define BITS2 CARD16
+#define BITS4 CARD32
+#include "fbsegbits.h"
+#undef BRESSOLID
+#undef BRESSOLIDR
+#undef BRESDASH
+#undef BITS
+#undef BITS2
+#undef BITS4
+
+#define BRESSOLID fbBresSolid16
+#define BRESSOLIDR fbBresSolidR16
+#define BRESDASH fbBresDash16
+#define BITS CARD16
+#define BITS2 CARD32
+#include "fbsegbits.h"
+#undef BRESSOLID
+#undef BRESSOLIDR
+#undef BRESDASH
+#undef BITS
+#undef BITS2
+
+#define BRESSOLID fbBresSolid32
+#define BRESSOLIDR fbBresSolidR32
+#define BRESDASH fbBresDash32
+#define BITS CARD32
+#include "fbsegbits.h"
+#undef BRESSOLID
+#undef BRESSOLIDR
+#undef BRESDASH
+#undef BITS
+
+static void
+fbBresSolid(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1,
+ int e, int e1, int e3, int len)
+{
+ FbStip *dst;
+ FbStride stride;
+ int bpp;
+ int dx, dy;
+ FbGCPrivPtr pgc = fb_gc(gc);
+ FbStip and = (FbStip) pgc->and;
+ FbStip xor = (FbStip) pgc->xor;
+ FbStip mask, mask0;
+ FbStip bits;
+
+ fbGetStipDrawable(drawable, dst, stride, bpp, dx, dy);
+ dst += ((y1 + dy) * stride);
+ x1 = (x1 + dx) * bpp;
+ dst += x1 >> FB_STIP_SHIFT;
+ x1 &= FB_STIP_MASK;
+ mask0 = FbStipMask(0, bpp);
+ mask = FbStipRight(mask0, x1);
+ if (sdx < 0)
+ mask0 = FbStipRight(mask0, FB_STIP_UNIT - bpp);
+ if (sdy < 0)
+ stride = -stride;
+ if (axis == X_AXIS) {
+ bits = 0;
+ while (len--) {
+ bits |= mask;
+ mask = fbBresShiftMask(mask, sdx, bpp);
+ if (!mask) {
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
+ bits = 0;
+ dst += sdx;
+ mask = mask0;
+ }
+ e += e1;
+ if (e >= 0) {
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
+ bits = 0;
+ dst += stride;
+ e += e3;
+ }
+ }
+ if (bits)
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits));
+ } else {
+ while (len--) {
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
+ dst += stride;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ mask = fbBresShiftMask(mask, sdx, bpp);
+ if (!mask) {
+ dst += sdx;
+ mask = mask0;
+ }
+ }
+ }
+ }
+}
+
+static void
+fbBresDash(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1,
+ int e, int e1, int e3, int len)
+{
+ FbStip *dst;
+ FbStride stride;
+ int bpp;
+ int dx, dy;
+ FbGCPrivPtr pgc = fb_gc(gc);
+ FbStip and = (FbStip) pgc->and;
+ FbStip xor = (FbStip) pgc->xor;
+ FbStip bgand = (FbStip) pgc->bgand;
+ FbStip bgxor = (FbStip) pgc->bgxor;
+ FbStip mask, mask0;
+
+ FbDashDeclare;
+ int dashlen;
+ bool even;
+ bool doOdd;
+
+ fbGetStipDrawable(drawable, dst, stride, bpp, dx, dy);
+ doOdd = gc->lineStyle == LineDoubleDash;
+
+ FbDashInit(gc, pgc, dashOffset, dashlen, even);
+
+ dst += ((y1 + dy) * stride);
+ x1 = (x1 + dx) * bpp;
+ dst += x1 >> FB_STIP_SHIFT;
+ x1 &= FB_STIP_MASK;
+ mask0 = FbStipMask(0, bpp);
+ mask = FbStipRight(mask0, x1);
+ if (sdx < 0)
+ mask0 = FbStipRight(mask0, FB_STIP_UNIT - bpp);
+ if (sdy < 0)
+ stride = -stride;
+ while (len--) {
+ if (even)
+ WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask));
+ else if (doOdd)
+ WRITE(dst, FbDoMaskRRop(READ(dst), bgand, bgxor, mask));
+ if (axis == X_AXIS) {
+ mask = fbBresShiftMask(mask, sdx, bpp);
+ if (!mask) {
+ dst += sdx;
+ mask = mask0;
+ }
+ e += e1;
+ if (e >= 0) {
+ dst += stride;
+ e += e3;
+ }
+ } else {
+ dst += stride;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ mask = fbBresShiftMask(mask, sdx, bpp);
+ if (!mask) {
+ dst += sdx;
+ mask = mask0;
+ }
+ }
+ }
+ FbDashStep(dashlen, even);
+ }
+}
+
+static void
+fbBresFill(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1,
+ int e, int e1, int e3, int len)
+{
+ while (len--) {
+ fbFill(drawable, gc, x1, y1, 1, 1);
+ if (axis == X_AXIS) {
+ x1 += sdx;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ y1 += sdy;
+ }
+ } else {
+ y1 += sdy;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ x1 += sdx;
+ }
+ }
+ }
+}
+
+static void
+fbSetFg(DrawablePtr drawable, GCPtr gc, Pixel fg)
+{
+ if (fg != gc->fgPixel) {
+ gc->fgPixel = fg;
+ fbValidateGC(gc, GCForeground, drawable);
+ }
+}
+
+static void
+fbBresFillDash(DrawablePtr drawable,
+ GCPtr gc,
+ int dashOffset,
+ int sdx,
+ int sdy,
+ int axis, int x1, int y1, int e, int e1, int e3, int len)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+
+ FbDashDeclare;
+ int dashlen;
+ bool even;
+ bool doOdd;
+ bool doBg;
+ Pixel fg, bg;
+
+ fg = gc->fgPixel;
+ bg = gc->bgPixel;
+
+ /* whether to fill the odd dashes */
+ doOdd = gc->lineStyle == LineDoubleDash;
+ /* whether to switch fg to bg when filling odd dashes */
+ doBg = doOdd && (gc->fillStyle == FillSolid ||
+ gc->fillStyle == FillStippled);
+
+ /* compute current dash position */
+ FbDashInit(gc, pgc, dashOffset, dashlen, even);
+
+ while (len--) {
+ if (even || doOdd) {
+ if (doBg) {
+ if (even)
+ fbSetFg(drawable, gc, fg);
+ else
+ fbSetFg(drawable, gc, bg);
+ }
+ fbFill(drawable, gc, x1, y1, 1, 1);
+ }
+ if (axis == X_AXIS) {
+ x1 += sdx;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ y1 += sdy;
+ }
+ } else {
+ y1 += sdy;
+ e += e1;
+ if (e >= 0) {
+ e += e3;
+ x1 += sdx;
+ }
+ }
+ FbDashStep(dashlen, even);
+ }
+ if (doBg)
+ fbSetFg(drawable, gc, fg);
+}
+
+static FbBres *
+fbSelectBres(DrawablePtr drawable, GCPtr gc)
+{
+ FbGCPrivPtr pgc = fb_gc(gc);
+ int bpp = drawable->bitsPerPixel;
+ FbBres *bres;
+
+ DBG(("%s: line=%d, fill=%d, and=%lx, bgand=%lx\n",
+ __FUNCTION__, gc->lineStyle, gc->fillStyle, pgc->and, pgc->bgand));
+ assert(gc->lineWidth == 0);
+
+ if (gc->lineStyle == LineSolid) {
+ bres = fbBresFill;
+ if (gc->fillStyle == FillSolid) {
+ bres = fbBresSolid;
+ if (pgc->and == 0) {
+ switch (bpp) {
+ case 8:
+ bres = fbBresSolid8;
+ break;
+ case 16:
+ bres = fbBresSolid16;
+ break;
+ case 32:
+ bres = fbBresSolid32;
+ break;
+ }
+ } else {
+ switch (bpp) {
+ case 8:
+ bres = fbBresSolidR8;
+ break;
+ case 16:
+ bres = fbBresSolidR16;
+ break;
+ case 32:
+ bres = fbBresSolidR32;
+ break;
+ }
+ }
+ }
+ } else {
+ bres = fbBresFillDash;
+ if (gc->fillStyle == FillSolid) {
+ bres = fbBresDash;
+ if (pgc->and == 0 &&
+ (gc->lineStyle == LineOnOffDash || pgc->bgand == 0)) {
+ switch (bpp) {
+ case 8:
+ bres = fbBresDash8;
+ break;
+ case 16:
+ bres = fbBresDash16;
+ break;
+ case 32:
+ bres = fbBresDash32;
+ break;
+ }
+ }
+ }
+ }
+ return bres;
+}
+
+struct fbSegment {
+ FbBres *bres;
+ bool drawLast;
+ int *dashOffset;
+ int x1, y1, x2, y2;
+};
+
+static void
+_fbSegment(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbSegment *data = _data;
+ const unsigned int bias = miGetZeroLineBias(drawable->pScreen);
+ int adx, ady; /* abs values of dx and dy */
+ int sdx, sdy; /* sign of dx and dy */
+ int e, e1, e2, e3; /* bresenham error and increments */
+ int len, axis, octant;
+ int dashoff, doff;
+ unsigned int oc1, oc2;
+
+ DBG(("%s box=(%d, %d),(%d, %d)\n",
+ __FUNCTION__, b->x1, b->y1, b->x2, b->y2));
+
+ CalcLineDeltas(data->x1, data->y1, data->x2, data->y2,
+ adx, ady, sdx, sdy, 1, 1, octant);
+
+ if (adx > ady) {
+ axis = X_AXIS;
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ len = adx;
+ } else {
+ axis = Y_AXIS;
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ SetYMajorOctant(octant);
+ len = ady;
+ }
+
+ FIXUP_ERROR(e, octant, bias);
+
+ /*
+ * Adjust error terms to compare against zero
+ */
+ e3 = e2 - e1;
+ e = e - e1;
+
+ if (data->drawLast)
+ len++;
+ dashoff = *data->dashOffset;
+ *data->dashOffset = dashoff + len;
+
+ oc1 = 0;
+ oc2 = 0;
+ OUTCODES(oc1, data->x1, data->y1, b);
+ OUTCODES(oc2, data->x2, data->y2, b);
+ if ((oc1 | oc2) == 0) {
+ data->bres(drawable, gc, dashoff,
+ sdx, sdy, axis, data->x1, data->y1, e, e1, e3, len);
+ } else if (oc1 & oc2) {
+ } else {
+ int new_x1 = data->x1, new_y1 = data->y1;
+ int new_x2 = data->x2, new_y2 = data->y2;
+ int clip1 = 0, clip2 = 0;
+ int clipdx, clipdy;
+ int err;
+
+ if (miZeroClipLine(b->x1, b->y1, b->x2-1, b->y2-1,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady, &clip1, &clip2,
+ octant, bias, oc1, oc2) == -1)
+ return;
+
+ if (axis == X_AXIS)
+ len = abs(new_x2 - new_x1);
+ else
+ len = abs(new_y2 - new_y1);
+ if (clip2 != 0 || data->drawLast)
+ len++;
+ if (len) {
+ /* unwind bresenham error term to first point */
+ doff = dashoff;
+ err = e;
+ if (clip1) {
+ clipdx = abs(new_x1 - data->x1);
+ clipdy = abs(new_y1 - data->y1);
+ if (axis == X_AXIS) {
+ doff += clipdx;
+ err += e3 * clipdy + e1 * clipdx;
+ } else {
+ doff += clipdy;
+ err += e3 * clipdx + e1 * clipdy;
+ }
+ }
+ data->bres(drawable, gc, doff,
+ sdx, sdy, axis, new_x1, new_y1,
+ err, e1, e3, len);
+ }
+ }
+}
+
+void
+fbSegment(DrawablePtr drawable, GCPtr gc,
+ int x1, int y1, int x2, int y2,
+ bool drawLast, int *dashOffset)
+{
+ struct fbSegment data;
+ BoxRec box;
+
+ DBG(("%s (%d, %d), (%d, %d), drawLast?=%d\n",
+ __FUNCTION__, x1, y1, x2, y2, drawLast));
+
+ /* simple overestimate of line extents for clipping */
+ box.x1 = x1 - 1;
+ box.y1 = y1 - 1;
+ box.x2 = x2 + 1;
+ box.y2 = y2 + 1;
+
+ data.x1 = x1;
+ data.y1 = y1;
+ data.x2 = x2;
+ data.y2 = y2;
+
+ data.dashOffset = dashOffset;
+ data.drawLast = drawLast;
+ data.bres = fbSelectBres(drawable, gc);
+
+ fbDrawableRunUnclipped(drawable, gc, &box, _fbSegment, &data);
+}
+
+void
+fbSegment1(DrawablePtr drawable, GCPtr gc, const BoxRec *b,
+ int x1, int y1, int x2, int y2,
+ bool drawLast, int *dashOffset)
+{
+ struct fbSegment data;
+
+ DBG(("%s (%d, %d), (%d, %d), drawLast?=%d\n",
+ __FUNCTION__, x1, y1, x2, y2, drawLast));
+
+ data.x1 = x1;
+ data.y1 = y1;
+ data.x2 = x2;
+ data.y2 = y2;
+
+ data.dashOffset = dashOffset;
+ data.drawLast = drawLast;
+ data.bres = fbSelectBres(drawable, gc);
+
+ _fbSegment(drawable, gc, b, &data);
+}
diff --git a/src/sna/fb/fbsegbits.h b/src/sna/fb/fbsegbits.h
new file mode 100644
index 00000000..590ad300
--- /dev/null
+++ b/src/sna/fb/fbsegbits.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
+#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x)))
+
+static void
+BRESSOLID(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1, int e, int e1, int e3, int len)
+{
+ FbBits *dst;
+ FbStride stride;
+ int bpp, dx, dy;
+ BITS *bits;
+ FbStride major, minor;
+ BITS xor = fb_gc(gc)->xor;
+
+ fbGetDrawable(drawable, dst, stride, bpp, dx, dy);
+ bits = (BITS *)(dst + (y1 + dy) * stride) + (x1 + dx);
+ stride = stride * (sizeof(FbBits) / sizeof(BITS));
+ if (sdy < 0)
+ stride = -stride;
+ if (axis == X_AXIS) {
+ major = sdx;
+ minor = stride;
+ } else {
+ major = stride;
+ minor = sdx;
+ }
+ while (len--) {
+ WRITE(bits, xor);
+ bits += major;
+ e += e1;
+ if (e >= 0) {
+ bits += minor;
+ e += e3;
+ }
+ }
+}
+
+static void
+BRESSOLIDR(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1, int e, int e1, int e3, int len)
+{
+ FbBits *dst;
+ FbStride stride;
+ int bpp, dx, dy;
+ BITS *bits;
+ FbStride major, minor;
+ BITS and = fb_gc(gc)->and;
+ BITS xor = fb_gc(gc)->xor;
+
+ fbGetDrawable(drawable, dst, stride, bpp, dx, dy);
+ bits = (BITS *)(dst + (y1 + dy) * stride) + (x1 + dx);
+ stride = stride * (sizeof(FbBits) / sizeof(BITS));
+ if (sdy < 0)
+ stride = -stride;
+ if (axis == X_AXIS) {
+ major = sdx;
+ minor = stride;
+ } else {
+ major = stride;
+ minor = sdx;
+ }
+ while (len--) {
+ RROP(bits, and, xor);
+ bits += major;
+ e += e1;
+ if (e >= 0) {
+ bits += minor;
+ e += e3;
+ }
+ }
+}
+
+static void
+BRESDASH(DrawablePtr drawable, GCPtr gc, int dashOffset,
+ int sdx, int sdy, int axis,
+ int x1, int y1, int e, int e1, int e3, int len)
+{
+ FbBits *dst;
+ FbStride stride;
+ int bpp, dx, dy;
+ BITS *bits;
+ FbStride major, minor;
+
+ FbDashDeclare;
+ int dashlen;
+ bool even;
+ bool doOdd = gc->lineStyle == LineDoubleDash;
+ BITS xorfg = fb_gc(gc)->xor;
+ BITS xorbg = fb_gc(gc)->bgxor;
+
+ fbGetDrawable(drawable, dst, stride, bpp, dx, dy);
+
+ FbDashInit(gc, fb_gc(gc), dashOffset, dashlen, even);
+
+ bits = ((BITS *) (dst + ((y1 + dy) * stride))) + (x1 + dx);
+ stride = stride * (sizeof(FbBits) / sizeof(BITS));
+ if (sdy < 0)
+ stride = -stride;
+ if (axis == X_AXIS) {
+ major = sdx;
+ minor = stride;
+ } else {
+ major = stride;
+ minor = sdx;
+ }
+ if (dashlen >= len)
+ dashlen = len;
+ if (doOdd) {
+ if (!even)
+ goto doubleOdd;
+ for (;;) {
+ len -= dashlen;
+ while (dashlen--) {
+ WRITE(bits, xorfg);
+ bits += major;
+ if ((e += e1) >= 0) {
+ e += e3;
+ bits += minor;
+ }
+ }
+ if (!len)
+ break;
+
+ FbDashNextEven(dashlen);
+
+ if (dashlen >= len)
+ dashlen = len;
+doubleOdd:
+ len -= dashlen;
+ while (dashlen--) {
+ WRITE(bits, xorbg);
+ bits += major;
+ if ((e += e1) >= 0) {
+ e += e3;
+ bits += minor;
+ }
+ }
+ if (!len)
+ break;
+
+ FbDashNextOdd(dashlen);
+
+ if (dashlen >= len)
+ dashlen = len;
+ }
+ } else {
+ if (!even)
+ goto onOffOdd;
+ for (;;) {
+ len -= dashlen;
+ while (dashlen--) {
+ WRITE(bits, xorfg);
+ bits += major;
+ if ((e += e1) >= 0) {
+ e += e3;
+ bits += minor;
+ }
+ }
+ if (!len)
+ break;
+
+ FbDashNextEven(dashlen);
+
+ if (dashlen >= len)
+ dashlen = len;
+onOffOdd:
+ len -= dashlen;
+ while (dashlen--) {
+ bits += major;
+ if ((e += e1) >= 0) {
+ e += e3;
+ bits += minor;
+ }
+ }
+ if (!len)
+ break;
+
+ FbDashNextOdd(dashlen);
+
+ if (dashlen >= len)
+ dashlen = len;
+ }
+ }
+}
+
+#undef RROP
+#undef isClipped
diff --git a/src/sna/fb/fbspan.c b/src/sna/fb/fbspan.c
new file mode 100644
index 00000000..45cb7cc7
--- /dev/null
+++ b/src/sna/fb/fbspan.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+#include "fbclip.h"
+
+inline static void
+fbFillSpan(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *data)
+{
+ DBG(("%s (%d,%d)+%d\n", __FUNCTION__, b->x1, b->y1, b->x2-b->x1));
+ fbFill(drawable, gc, b->x1, b->y1, b->x2 - b->x1, 1);
+}
+
+void
+fbFillSpans(DrawablePtr drawable, GCPtr gc,
+ int n, DDXPointPtr pt, int *width, int fSorted)
+{
+ DBG(("%s x %d\n", __FUNCTION__, n));
+ while (n--) {
+ BoxRec box;
+
+ *(DDXPointPtr)&box = *pt++;
+ box.x2 = box.x1 + *width++;
+ box.y2 = box.y1 + 1;
+
+ /* XXX fSorted */
+ fbDrawableRun(drawable, gc, &box, fbFillSpan, NULL);
+ }
+}
+
+struct fbSetSpan {
+ char *src;
+ DDXPointRec pt;
+ FbStride stride;
+ FbBits *dst;
+ int dx, dy;
+};
+
+inline static void
+fbSetSpan(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
+{
+ struct fbSetSpan *data = _data;
+ int xoff, bpp;
+
+ xoff = (int) (((long)data->src) & (FB_MASK >> 3));
+ bpp = drawable->bitsPerPixel;
+
+ fbBlt((FbBits *)(data->src - xoff), 0,
+ (b->x1 - data->pt.x) * bpp + (xoff << 3),
+ data->dst + (b->y1 + data->dy) * data->stride, data->stride,
+ (b->x1 + data->dx) * bpp,
+ (b->x2 - b->x1) * bpp, 1,
+ gc->alu, fb_gc(gc)->pm, bpp,
+ FALSE, FALSE);
+}
+
+void
+fbSetSpans(DrawablePtr drawable, GCPtr gc,
+ char *src, DDXPointPtr pt, int *width, int n, int fSorted)
+{
+ struct fbSetSpan data;
+ PixmapPtr pixmap;
+
+ DBG(("%s x %d\n", __FUNCTION__, n));
+
+ fbGetDrawablePixmap(drawable, pixmap, data.dx, data.dy);
+ data.dst = pixmap->devPrivate.ptr;
+ data.stride = pixmap->devKind / sizeof(FbStip);
+
+ data.src = src;
+ while (n--) {
+ BoxRec box;
+
+ *(DDXPointPtr)&box = data.pt = *pt;
+ box.x2 = box.x1 + *width;
+ box.y2 = box.y1 + 1;
+
+ fbDrawableRun(drawable, gc, &box, fbSetSpan, &data);
+
+ data.src += PixmapBytePad(*width, drawable->depth);
+ width++;
+ pt++;
+ }
+}
+
+void
+fbGetSpans(DrawablePtr drawable, int wMax,
+ DDXPointPtr pt, int *width, int n, char *dst)
+{
+ FbBits *src, *d;
+ FbStride srcStride;
+ int srcBpp;
+ int srcXoff, srcYoff;
+ int xoff;
+
+ fbGetDrawable(drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+
+ DBG(("%s x %d\n", __FUNCTION__, n));
+ while (n--) {
+ xoff = (int) (((long) dst) & (FB_MASK >> 3));
+ d = (FbBits *) (dst - xoff);
+ fbBlt(src + (pt->y + srcYoff) * srcStride, srcStride,
+ (pt->x + srcXoff) * srcBpp,
+ d, 1, xoff << 3, *width * srcBpp,
+ 1, GXcopy, FB_ALLONES, srcBpp,
+ FALSE, FALSE);
+ dst += PixmapBytePad(*width, drawable->depth);
+ pt++;
+ width++;
+ }
+}
diff --git a/src/sna/fb/fbstipple.c b/src/sna/fb/fbstipple.c
new file mode 100644
index 00000000..d02970a0
--- /dev/null
+++ b/src/sna/fb/fbstipple.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+
+/*
+ * This is a slight abuse of the preprocessor to generate repetitive
+ * code, the idea is to generate code for each case of a copy-mode
+ * transparent stipple
+ */
+#define LaneCases1(c,a) \
+ case c: while (n--) { FbLaneCase(c,a); a++; } break
+#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a)
+#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a)
+#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a)
+#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a)
+
+#define LaneCases(a) LaneCases16(0,a)
+
+/*
+ * Repeat a transparent stipple across a scanline n times
+ */
+
+void
+fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n)
+{
+ FbStip s;
+
+ s = ((FbStip) (stip) & 0x01);
+ s |= ((FbStip) (stip >> 8) & 0x02);
+ s |= ((FbStip) (stip >> 16) & 0x04);
+ s |= ((FbStip) (stip >> 24) & 0x08);
+ switch (s) {
+ LaneCases(dst);
+ }
+}
+
+static void
+fbEvenStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
+ int width, int height,
+ FbStip *stip, FbStride stipStride,
+ int stipHeight,
+ FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
+ int xRot, int yRot)
+{
+ FbBits startmask, endmask;
+ FbBits mask, and, xor;
+ int nmiddle, n;
+ FbStip *s, *stipEnd, bits;
+ int rot, stipX, stipY;
+ int pixelsPerDst;
+ const FbBits *fbBits;
+ Bool transparent;
+ int startbyte, endbyte;
+
+ /*
+ * Check for a transparent stipple (stencil)
+ */
+ transparent = FALSE;
+ if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0)
+ transparent = TRUE;
+
+ pixelsPerDst = FB_UNIT / dstBpp;
+ /*
+ * Adjust dest pointers
+ */
+ dst += dstX >> FB_SHIFT;
+ dstX &= FB_MASK;
+ FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0,
+ startmask, startbyte, nmiddle, endmask, endbyte);
+
+ if (startmask)
+ dstStride--;
+ dstStride -= nmiddle;
+
+ xRot *= dstBpp;
+ /*
+ * Compute stip start scanline and rotation parameters
+ */
+ stipEnd = stip + stipStride * stipHeight;
+ modulus(-yRot, stipHeight, stipY);
+ s = stip + stipStride * stipY;
+ modulus(-xRot, FB_UNIT, stipX);
+ rot = stipX;
+
+ /*
+ * Get pointer to stipple mask array for this depth
+ */
+ /* fbStippleTable covers all valid bpp (4,8,16,32) */
+ fbBits = fbStippleTable[pixelsPerDst];
+
+ while (height--) {
+ /*
+ * Extract stipple bits for this scanline;
+ */
+ bits = READ(s);
+ s += stipStride;
+ if (s == stipEnd)
+ s = stip;
+ mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
+ /*
+ * Rotate into position and compute reduced rop values
+ */
+ mask = FbRotLeft(mask, rot);
+ and = (fgand & mask) | (bgand & ~mask);
+ xor = (fgxor & mask) | (bgxor & ~mask);
+
+ if (transparent) {
+ if (startmask) {
+ fbTransparentSpan(dst, mask & startmask, fgxor, 1);
+ dst++;
+ }
+ fbTransparentSpan(dst, mask, fgxor, nmiddle);
+ dst += nmiddle;
+ if (endmask)
+ fbTransparentSpan(dst, mask & endmask, fgxor, 1);
+ } else {
+ /*
+ * Fill scanline
+ */
+ if (startmask) {
+ FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
+ dst++;
+ }
+ n = nmiddle;
+ if (!and)
+ while (n--)
+ WRITE(dst++, xor);
+ else {
+ while (n--) {
+ WRITE(dst, FbDoRRop(READ(dst), and, xor));
+ dst++;
+ }
+ }
+ if (endmask)
+ FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
+ }
+ dst += dstStride;
+ }
+}
+
+static void
+fbOddStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
+ int width, int height,
+ FbStip *stip, FbStride stipStride,
+ int stipWidth, int stipHeight,
+ FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
+ int xRot, int yRot)
+{
+ int stipX, stipY, sx;
+ int widthTmp;
+ int h, w;
+ int x, y;
+
+ modulus(-yRot, stipHeight, stipY);
+ modulus(dstX / dstBpp - xRot, stipWidth, stipX);
+ y = 0;
+ while (height) {
+ h = stipHeight - stipY;
+ if (h > height)
+ h = height;
+ height -= h;
+ widthTmp = width;
+ x = dstX;
+ sx = stipX;
+ while (widthTmp) {
+ w = (stipWidth - sx) * dstBpp;
+ if (w > widthTmp)
+ w = widthTmp;
+ widthTmp -= w;
+ fbBltOne(stip + stipY * stipStride,
+ stipStride,
+ sx,
+ dst + y * dstStride,
+ dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor);
+ x += w;
+ sx = 0;
+ }
+ y += h;
+ stipY = 0;
+ }
+}
+
+void
+fbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
+ int width, int height,
+ FbStip *stip, FbStride stipStride,
+ int stipWidth, int stipHeight, Bool even,
+ FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
+ int xRot, int yRot)
+{
+ DBG(("%s stipple=%dx%d, size=%dx%d\n",
+ __FUNCTION__, stipWidth, stipHeight, width, height));
+
+ if (even)
+ fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height,
+ stip, stipStride, stipHeight,
+ fgand, fgxor, bgand, bgxor, xRot, yRot);
+ else
+ fbOddStipple(dst, dstStride, dstX, dstBpp, width, height,
+ stip, stipStride, stipWidth, stipHeight,
+ fgand, fgxor, bgand, bgxor, xRot, yRot);
+}
diff --git a/src/sna/fb/fbtile.c b/src/sna/fb/fbtile.c
new file mode 100644
index 00000000..5586553e
--- /dev/null
+++ b/src/sna/fb/fbtile.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+
+/*
+ * Accelerated tile fill -- tile width is a power of two not greater
+ * than FB_UNIT
+ */
+
+static void
+fbEvenTile(FbBits *dst, FbStride dstStride, int dstX, int width, int height,
+ FbBits *tile, FbStride tileStride, int tileHeight,
+ int alu, FbBits pm,
+ int xRot, int yRot)
+{
+ FbBits *t, *tileEnd, bits;
+ FbBits startmask, endmask;
+ FbBits and, xor;
+ int n, nmiddle;
+ int tileX, tileY;
+ int rot;
+ int startbyte, endbyte;
+
+ dst += dstX >> FB_SHIFT;
+ dstX &= FB_MASK;
+ FbMaskBitsBytes(dstX, width, FbDestInvarientRop(alu, pm),
+ startmask, startbyte, nmiddle, endmask, endbyte);
+ if (startmask)
+ dstStride--;
+ dstStride -= nmiddle;
+
+ /*
+ * Compute tile start scanline and rotation parameters
+ */
+ tileEnd = tile + tileHeight * tileStride;
+ modulus(-yRot, tileHeight, tileY);
+ t = tile + tileY * tileStride;
+ modulus(-xRot, FB_UNIT, tileX);
+ rot = tileX;
+
+ while (height--) {
+ /*
+ * Pick up bits for this scanline
+ */
+ bits = READ(t);
+ t += tileStride;
+ if (t >= tileEnd)
+ t = tile;
+ bits = FbRotLeft(bits, rot);
+ and = fbAnd(alu, bits, pm);
+ xor = fbXor(alu, bits, pm);
+
+ if (startmask) {
+ FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
+ dst++;
+ }
+ n = nmiddle;
+ if (!and)
+ while (n--)
+ WRITE(dst++, xor);
+ else
+ while (n--) {
+ WRITE(dst, FbDoRRop(READ(dst), and, xor));
+ dst++;
+ }
+ if (endmask)
+ FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
+ dst += dstStride;
+ }
+}
+
+static void
+fbOddTile(FbBits *dst, FbStride dstStride, int dstX,
+ int width, int height,
+ FbBits *tile, FbStride tileStride,
+ int tileWidth, int tileHeight,
+ int alu, FbBits pm, int bpp,
+ int xRot, int yRot)
+{
+ int tileX, tileY;
+ int widthTmp;
+ int h, w;
+ int x, y;
+
+ modulus(-yRot, tileHeight, tileY);
+ y = 0;
+ while (height) {
+ h = tileHeight - tileY;
+ if (h > height)
+ h = height;
+ height -= h;
+ widthTmp = width;
+ x = dstX;
+ modulus(dstX - xRot, tileWidth, tileX);
+ while (widthTmp) {
+ w = tileWidth - tileX;
+ if (w > widthTmp)
+ w = widthTmp;
+ widthTmp -= w;
+ fbBlt(tile + tileY * tileStride,
+ tileStride,
+ tileX,
+ dst + y * dstStride,
+ dstStride, x, w, h, alu, pm, bpp, FALSE, FALSE);
+ x += w;
+ tileX = 0;
+ }
+ y += h;
+ tileY = 0;
+ }
+}
+
+void
+fbTile(FbBits *dst, FbStride dstStride, int dstX,
+ int width, int height,
+ FbBits *tile, FbStride tileStride,
+ int tileWidth, int tileHeight,
+ int alu, FbBits pm, int bpp,
+ int xRot, int yRot)
+{
+ DBG(("%s tile=%dx%d, size=%dx%d\n", __FUNCTION__,
+ tileWidth, tileHeight, width, height));
+
+ if (FbEvenTile(tileWidth))
+ fbEvenTile(dst, dstStride, dstX, width, height,
+ tile, tileStride, tileHeight, alu, pm, xRot, yRot);
+ else
+ fbOddTile(dst, dstStride, dstX, width, height,
+ tile, tileStride, tileWidth, tileHeight,
+ alu, pm, bpp, xRot, yRot);
+}
diff --git a/src/sna/fb/fbutil.c b/src/sna/fb/fbutil.c
new file mode 100644
index 00000000..61b63ad5
--- /dev/null
+++ b/src/sna/fb/fbutil.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 1998 Keith Packard
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "fb.h"
+
+FbBits
+fbReplicatePixel(Pixel p, int bpp)
+{
+ FbBits b = p;
+
+ b &= FbFullMask(bpp);
+ while (bpp < FB_UNIT) {
+ b |= b << bpp;
+ bpp <<= 1;
+ }
+ return b;
+}
+
+/*
+ * Stipple masks are independent of bit/byte order as long
+ * as bitorder == byteorder. FB doesn't handle the case
+ * where these differ
+ */
+#define __mask(x,w) ((FB_ALLONES << ((x) & FB_MASK)) & \
+ (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK)))
+#define _mask(x,w) __mask((x)*(w),(w))
+#define mask(b,n,w) ((((b) >> (n)) & 1) * _mask(n,w))
+
+#define _C1(b,n,w) mask(b,n,w)
+#define _C2(b,n,w) (_C1(b,n,w) | _C1(b,n+1,w))
+#define _C4(b,n,w) (_C2(b,n,w) | _C2(b,n+2,w))
+#define C8(b,w) (_C4(b,0,w) | _C4(b,4,w))
+#define C4(b,w) _C4(b,0,w)
+#define C2(b,w) _C2(b,0,w)
+#define C1(b,w) _C1(b,0,w)
+
+static const FbBits fbStipple8Bits[256] = {
+ C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4),
+ C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4),
+ C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4),
+ C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4),
+ C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4),
+ C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4),
+ C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4),
+ C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4),
+ C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4),
+ C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4),
+ C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4),
+ C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4),
+ C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4),
+ C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4),
+ C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4),
+ C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4),
+ C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4),
+ C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4),
+ C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4),
+ C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4),
+ C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4),
+ C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4),
+ C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4),
+ C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4),
+ C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4),
+ C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4),
+ C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4),
+ C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4),
+ C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4),
+ C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4),
+ C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4),
+ C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4),
+ C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4),
+ C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4),
+ C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4),
+ C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4),
+ C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4),
+ C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4),
+ C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4),
+ C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4),
+ C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4),
+ C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4),
+ C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4),
+};
+
+static const FbBits fbStipple4Bits[16] = {
+ C4(0, 8), C4(1, 8), C4(2, 8), C4(3, 8), C4(4, 8), C4(5, 8),
+ C4(6, 8), C4(7, 8), C4(8, 8), C4(9, 8), C4(10, 8), C4(11, 8),
+ C4(12, 8), C4(13, 8), C4(14, 8), C4(15, 8),
+};
+
+static const FbBits fbStipple2Bits[4] = {
+ C2(0, 16), C2(1, 16), C2(2, 16), C2(3, 16),
+};
+
+static const FbBits fbStipple1Bits[2] = {
+ C1(0, 32), C1(1, 32),
+};
+const FbBits *const fbStippleTable[] = {
+ 0,
+ fbStipple1Bits,
+ fbStipple2Bits,
+ 0,
+ fbStipple4Bits,
+ 0,
+ 0,
+ 0,
+ fbStipple8Bits,
+};