summaryrefslogtreecommitdiff
path: root/src/sna
diff options
context:
space:
mode:
Diffstat (limited to 'src/sna')
-rw-r--r--src/sna/Makefile.am4
-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
-rw-r--r--src/sna/sna.h22
-rw-r--r--src/sna/sna_accel.c745
-rw-r--r--src/sna/sna_blt.c3
-rw-r--r--src/sna/sna_composite.c2
-rw-r--r--src/sna/sna_display.c7
-rw-r--r--src/sna/sna_driver.c74
-rw-r--r--src/sna/sna_glyphs.c3
-rw-r--r--src/sna/sna_render.c5
-rw-r--r--src/sna/sna_tiling.c3
-rw-r--r--src/sna/sna_trapezoids.c21
41 files changed, 6585 insertions, 392 deletions
diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
index 911a857e..8cd3c451 100644
--- a/src/sna/Makefile.am
+++ b/src/sna/Makefile.am
@@ -18,6 +18,8 @@
# 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.
+SUBDIRS = fb
+
AM_CFLAGS = \
@CWARNFLAGS@ \
-I$(top_srcdir)/src \
@@ -29,7 +31,7 @@ AM_CFLAGS = \
$(NULL)
noinst_LTLIBRARIES = libsna.la
-libsna_la_LIBADD = @UDEV_LIBS@ -lm @DRM_LIBS@
+libsna_la_LIBADD = @UDEV_LIBS@ -lm @DRM_LIBS@ fb/libfb.la
libsna_la_SOURCES = \
blt.c \
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,
+};
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 3219e151..7f4c0bfb 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -42,9 +42,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#include <stdint.h>
-
#include "compiler.h"
+#include <xorg-server.h>
+
#include <xf86Crtc.h>
#include <xf86str.h>
#include <windowstr.h>
@@ -52,7 +53,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <picturestr.h>
#include <gcstruct.h>
-#include <xorg-server.h>
#include <pciaccess.h>
#include <xf86drmMode.h>
@@ -67,8 +67,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <libudev.h>
#endif
-#include "compiler.h"
-
#define DBG(x)
#define DEBUG_ALL (HAS_DEBUG_FULL || 0)
@@ -114,6 +112,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "kgem.h"
#include "sna_damage.h"
#include "sna_render.h"
+#include "fb/fb.h"
#define SNA_CURSOR_X 64
#define SNA_CURSOR_Y SNA_CURSOR_X
@@ -150,18 +149,9 @@ struct sna_glyph {
uint16_t size, pos;
};
-extern DevPrivateKeyRec sna_private_index;
-extern DevPrivateKeyRec sna_pixmap_index;
-extern DevPrivateKeyRec sna_gc_index;
-extern DevPrivateKeyRec sna_glyph_key;
-
static inline PixmapPtr get_window_pixmap(WindowPtr window)
{
-#if 0
- return window->drawable.pScreen->GetWindowPixmap(window)
-#else
- return *(void **)window->devPrivates;
-#endif
+ return fbGetWindowPixmap(window);
}
static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
@@ -259,7 +249,6 @@ struct sna {
ScreenBlockHandlerProcPtr BlockHandler;
ScreenWakeupHandlerProcPtr WakeupHandler;
- CloseScreenProcPtr CloseScreen;
PicturePtr clear;
struct {
@@ -565,8 +554,7 @@ static inline uint32_t pixmap_size(PixmapPtr pixmap)
pixmap->drawable.width * pixmap->drawable.bitsPerPixel/8;
}
-Bool sna_accel_pre_init(struct sna *sna);
-Bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
+bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
void sna_accel_wakeup_handler(struct sna *sna);
void sna_accel_watch_flush(struct sna *sna, int enable);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e553baf4..099075bd 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -36,14 +36,15 @@
#include <X11/fonts/font.h>
#include <X11/fonts/fontstruct.h>
-#include <fb.h>
#include <dixfontstr.h>
+#include <mi.h>
+#include <migc.h>
+#include <miline.h>
+#include <micmap.h>
#ifdef RENDER
#include <mipict.h>
-#include <fbpict.h>
#endif
-#include <miline.h>
#include <shmint.h>
#include <sys/time.h>
@@ -113,11 +114,11 @@ static void __sna_fallback_flush(DrawablePtr d)
box.x2 = pixmap->drawable.width;
box.y2 = pixmap->drawable.height;
- tmp = fbCreatePixmap(pixmap->drawable.pScreen,
- pixmap->drawable.width,
- pixmap->drawable.height,
- pixmap->drawable.depth,
- 0);
+ tmp = sna_pixmap_create_unattached(pixmap->drawable.pScreen,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->drawable.depth,
+ 0);
DBG(("%s: comparing with direct read...\n", __FUNCTION__));
sna_read_boxes(sna,
@@ -138,7 +139,7 @@ static void __sna_fallback_flush(DrawablePtr d)
src += pixmap->devKind;
dst += tmp->devKind;
}
- fbDestroyPixmap(tmp);
+ tmp->drawable.pScreen->DestroyPixmap(tmp);
}
#define FALLBACK_FLUSH(d) __sna_fallback_flush(d)
#else
@@ -187,6 +188,8 @@ static const uint8_t fill_ROP[] = {
static const GCOps sna_gc_ops;
static const GCOps sna_gc_ops__cpu;
static GCOps sna_gc_ops__tmp;
+static const GCFuncs sna_gc_funcs;
+static const GCFuncs sna_gc_funcs__cpu;
static inline void region_set(RegionRec *r, const BoxRec *b)
{
@@ -471,9 +474,13 @@ static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
priv->pixmap->devPrivate.ptr = NULL;
}
-static Bool sna_destroy_private(PixmapPtr pixmap, struct sna_pixmap *priv)
+static bool sna_destroy_private(PixmapPtr pixmap)
{
struct sna *sna = to_sna_from_pixmap(pixmap);
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+
+ if (priv == NULL)
+ return true;
list_del(&priv->list);
list_del(&priv->inactive);
@@ -612,7 +619,11 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna)
{
- dixSetPrivate(&pixmap->devPrivates, &sna_pixmap_index, sna);
+#if 0
+ dixSetPrivate(&pixmap->devPrivates, &sna_private_index, sna);
+#else
+ ((void **)pixmap->devPrivates)[1] = sna;
+#endif
assert(sna_pixmap(pixmap) == sna);
}
@@ -672,17 +683,74 @@ bool sna_pixmap_attach_to_bo(PixmapPtr pixmap, struct kgem_bo *bo)
return true;
}
-static inline PixmapPtr
+static int bits_per_pixel(int depth)
+{
+ switch (depth) {
+ case 1: return 1;
+ case 4:
+ case 8: return 8;
+ case 15:
+ case 16: return 16;
+ case 24:
+ case 30:
+ case 32: return 32;
+ default: return 0;
+ }
+}
+static PixmapPtr
create_pixmap(struct sna *sna, ScreenPtr screen,
int width, int height, int depth,
- unsigned usage)
+ unsigned usage_hint)
{
PixmapPtr pixmap;
+ size_t datasize;
+ size_t stride;
+ int base, bpp;
+
+ bpp = bits_per_pixel(depth);
+ if (bpp == 0)
+ return NullPixmap;
+
+ stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (stride / 4 > 32767 || height > 32767)
+ return NullPixmap;
+
+ datasize = height * stride;
+ base = screen->totalPixmapSize;
+ if (base & 15) {
+ int adjust = 16 - (base & 15);
+ base += adjust;
+ datasize += adjust;
+ }
- pixmap = fbCreatePixmap(screen, width, height, depth, usage);
- if (pixmap == NullPixmap)
+ pixmap = AllocatePixmap(screen, datasize);
+ if (!pixmap)
return NullPixmap;
+ ((void **)pixmap->devPrivates)[0] = sna;
+
+ pixmap->drawable.type = DRAWABLE_PIXMAP;
+ pixmap->drawable.class = 0;
+ pixmap->drawable.pScreen = screen;
+ pixmap->drawable.depth = depth;
+ pixmap->drawable.bitsPerPixel = bpp;
+ pixmap->drawable.id = 0;
+ pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pixmap->drawable.x = 0;
+ pixmap->drawable.y = 0;
+ pixmap->drawable.width = width;
+ pixmap->drawable.height = height;
+ pixmap->devKind = stride;
+ pixmap->refcnt = 1;
+ pixmap->devPrivate.ptr = (char *)pixmap + base;
+
+#ifdef COMPOSITE
+ pixmap->screen_x = 0;
+ pixmap->screen_y = 0;
+#endif
+
+ pixmap->usage_hint = usage_hint;
+
DBG(("%s: serial=%ld, usage=%d, %dx%d\n",
__FUNCTION__,
pixmap->drawable.serialNumber,
@@ -690,8 +758,6 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
pixmap->drawable.width,
pixmap->drawable.height));
- assert(sna_private_index.offset == 0);
- dixSetPrivate(&pixmap->devPrivates, &sna_private_index, sna);
return pixmap;
}
@@ -701,7 +767,7 @@ sna_pixmap_create_shm(ScreenPtr screen,
char *addr)
{
struct sna *sna = to_sna_from_screen(screen);
- int bpp = BitsPerPixel(depth);
+ int bpp = bits_per_pixel(depth);
int pitch = PixmapBytePad(width, depth);
struct sna_pixmap *priv;
PixmapPtr pixmap;
@@ -741,7 +807,7 @@ sna_pixmap_create_shm(ScreenPtr screen,
priv = sna_pixmap_attach(pixmap);
if (!priv) {
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return NullPixmap;
}
}
@@ -749,7 +815,7 @@ sna_pixmap_create_shm(ScreenPtr screen,
priv->cpu_bo = kgem_create_map(&sna->kgem, addr, pitch*height, false);
if (priv->cpu_bo == NULL) {
free(priv);
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return GetScratchPixmapHeader(screen, width, height, depth,
bpp, pitch, addr);
}
@@ -787,7 +853,7 @@ sna_pixmap_create_scratch(ScreenPtr screen,
DBG(("%s(%d, %d, %d, tiling=%d)\n", __FUNCTION__,
width, height, depth, tiling));
- bpp = BitsPerPixel(depth);
+ bpp = bits_per_pixel(depth);
if (tiling == I915_TILING_Y && !sna->have_render)
tiling = I915_TILING_X;
@@ -833,7 +899,7 @@ sna_pixmap_create_scratch(ScreenPtr screen,
priv = sna_pixmap_attach(pixmap);
if (!priv) {
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return NullPixmap;
}
}
@@ -846,7 +912,7 @@ sna_pixmap_create_scratch(ScreenPtr screen,
CREATE_TEMPORARY);
if (priv->gpu_bo == NULL) {
free(priv);
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return NullPixmap;
}
@@ -956,15 +1022,14 @@ fallback:
static Bool sna_destroy_pixmap(PixmapPtr pixmap)
{
- if (pixmap->refcnt == 1) {
- struct sna_pixmap *priv = sna_pixmap(pixmap);
- if (priv) {
- if (!sna_destroy_private(pixmap, priv))
- return TRUE;
- }
- }
+ if (--pixmap->refcnt)
+ return TRUE;
- return fbDestroyPixmap(pixmap);
+ if (!sna_destroy_private(pixmap))
+ return TRUE;
+
+ FreePixmap(pixmap);
+ return TRUE;
}
static inline bool pixmap_inplace(struct sna *sna,
@@ -1991,9 +2056,9 @@ inline static unsigned drawable_gc_flags(DrawablePtr draw,
return MOVE_READ | MOVE_WRITE;
}
- if (fbGetGCPrivate(gc)->and) {
+ if (fb_gc(gc)->and) {
DBG(("%s: read due to rop %d:%x\n",
- __FUNCTION__, gc->alu, (unsigned)fbGetGCPrivate(gc)->and));
+ __FUNCTION__, gc->alu, (unsigned)fb_gc(gc)->and));
return MOVE_READ | MOVE_WRITE;
}
@@ -2425,7 +2490,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
struct sna *sna = to_sna_from_screen(screen);
PixmapPtr pixmap;
struct sna_pixmap *priv;
- int bpp = BitsPerPixel(depth);
+ int bpp = bits_per_pixel(depth);
void *ptr;
DBG(("%s(%d, %d, %d, flags=%x)\n", __FUNCTION__,
@@ -2446,7 +2511,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
priv = malloc(sizeof(*priv));
if (!priv) {
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return NullPixmap;
}
@@ -2461,7 +2526,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
flags, &ptr);
if (!priv->gpu_bo) {
free(priv);
- fbDestroyPixmap(pixmap);
+ FreePixmap(pixmap);
return NullPixmap;
}
@@ -2699,25 +2764,35 @@ active:
static bool must_check sna_validate_pixmap(DrawablePtr draw, PixmapPtr pixmap)
{
- bool ret = true;
-
if (draw->bitsPerPixel == pixmap->drawable.bitsPerPixel &&
FbEvenTile(pixmap->drawable.width *
pixmap->drawable.bitsPerPixel)) {
DBG(("%s: flushing pixmap\n", __FUNCTION__));
- ret = sna_pixmap_move_to_cpu(pixmap, MOVE_READ | MOVE_WRITE);
+ if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ | MOVE_WRITE))
+ return false;
+
+ fbPadPixmap(pixmap);
}
- return ret;
+ return true;
}
-static bool must_check sna_gc_move_to_cpu(GCPtr gc, DrawablePtr drawable)
+static bool must_check sna_gc_move_to_cpu(GCPtr gc,
+ DrawablePtr drawable,
+ RegionPtr region)
{
struct sna_gc *sgc = sna_gc(gc);
long changes = sgc->changes;
DBG(("%s, changes=%lx\n", __FUNCTION__, changes));
+ assert(gc->ops == (GCOps *)&sna_gc_ops);
+ assert(gc->funcs == (GCFuncs *)&sna_gc_funcs);
+
+ sgc->priv = region;
+ gc->ops = (GCOps *)&sna_gc_ops__cpu;
+ gc->funcs = (GCFuncs *)&sna_gc_funcs__cpu;
+
if (gc->clientClipType == CT_PIXMAP) {
PixmapPtr clip = gc->clientClip;
gc->clientClip = BitmapToRegion(gc->pScreen, clip);
@@ -2730,6 +2805,11 @@ static bool must_check sna_gc_move_to_cpu(GCPtr gc, DrawablePtr drawable)
if (changes || drawable->serialNumber != sgc->serial) {
gc->serialNumber = sgc->serial;
+ if (fb_gc(gc)->bpp != drawable->bitsPerPixel) {
+ changes |= GCStipple | GCForeground | GCBackground | GCPlaneMask;
+ fb_gc(gc)->bpp = drawable->bitsPerPixel;
+ }
+
if (changes & GCTile && !gc->tileIsPixel) {
DBG(("%s: flushing tile pixmap\n", __FUNCTION__));
if (!sna_validate_pixmap(drawable, gc->tile.pixmap))
@@ -2738,7 +2818,7 @@ static bool must_check sna_gc_move_to_cpu(GCPtr gc, DrawablePtr drawable)
if (changes & GCStipple && gc->stipple) {
DBG(("%s: flushing stipple pixmap\n", __FUNCTION__));
- if (!sna_pixmap_move_to_cpu(gc->stipple, MOVE_READ))
+ if (!sna_validate_pixmap(drawable, gc->stipple))
return false;
}
@@ -2760,6 +2840,15 @@ static bool must_check sna_gc_move_to_cpu(GCPtr gc, DrawablePtr drawable)
}
}
+static void sna_gc_move_to_gpu(GCPtr gc)
+{
+ assert(gc->ops == (GCOps *)&sna_gc_ops__cpu);
+ assert(gc->funcs == (GCFuncs *)&sna_gc_funcs__cpu);
+
+ gc->ops = (GCOps *)&sna_gc_ops;
+ gc->funcs = (GCFuncs *)&sna_gc_funcs;
+}
+
static inline bool clip_box(BoxPtr box, GCPtr gc)
{
const BoxRec *clip;
@@ -3491,10 +3580,12 @@ sna_put_image(DrawablePtr drawable, GCPtr gc, int depth,
if (priv == NULL) {
DBG(("%s: fbPutImage, unattached(%d, %d, %d, %d)\n",
__FUNCTION__, x, y, w, h));
- if (sna_gc_move_to_cpu(gc, drawable))
+ if (sna_gc_move_to_cpu(gc, drawable, NULL)) {
fbPutImage(drawable, gc, depth,
x, y, w, h, left,
format, bits);
+ sna_gc_move_to_gpu(gc);
+ }
return;
}
@@ -3563,17 +3654,19 @@ fallback:
DBG(("%s: fallback\n", __FUNCTION__));
RegionTranslate(&region, -dx, -dy);
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable, gc,
true)))
- goto out;
+ goto out_gc;
DBG(("%s: fbPutImage(%d, %d, %d, %d)\n",
__FUNCTION__, x, y, w, h));
fbPutImage(drawable, gc, depth, x, y, w, h, left, format, bits);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -4284,23 +4377,26 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
return NULL;
ret = NULL;
- if (!sna_gc_move_to_cpu(gc, dst))
+ if (!sna_gc_move_to_cpu(gc, dst, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(dst, &region, MOVE_READ | MOVE_WRITE))
- goto out;
+ goto out_gc;
RegionTranslate(&region,
src_x - dst_x - dst->x + src->x,
src_y - dst_y - dst->y + src->y);
if (!sna_drawable_move_region_to_cpu(src, &region, MOVE_READ))
- goto out;
+ goto out_gc;
- ret = fbCopyArea(src, dst, gc,
- src_x, src_y,
- width, height,
- dst_x, dst_y);
+ ret = miDoCopy(src, dst, gc,
+ src_x, src_y,
+ width, height,
+ dst_x, dst_y,
+ fbCopyNtoN, 0, 0);
FALLBACK_FLUSH(dst);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
return ret;
@@ -4355,79 +4451,6 @@ find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
return find_clip_box_for_y(mid, end, y);
}
-static void
-sna_fill_spans__cpu(DrawablePtr drawable,
- GCPtr gc, int n,
- DDXPointPtr pt, int *width, int sorted)
-{
- RegionRec *clip = sna_gc(gc)->priv;
-
- DBG(("%s x %d\n", __FUNCTION__, n));
-
- while (n--) {
- BoxRec b;
-
- DBG(("%s: (%d, %d) + %d\n",
- __FUNCTION__, pt->x, pt->y, *width));
-
- *(DDXPointRec *)&b = *pt++;
- b.x2 = b.x1 + *width++;
- b.y2 = b.y1 + 1;
-
- if (!box_intersect(&b, &clip->extents))
- continue;
-
- if (region_is_singular(clip)) {
- DBG(("%s: singular fill: (%d, %d) x %d\n",
- __FUNCTION__, b.x1, b.y1, b.x2 - b.x1));
- fbFill(drawable, gc, b.x1, b.y1, b.x2 - b.x1, 1);
- } else {
- const BoxRec * const clip_start = RegionBoxptr(clip);
- const BoxRec * const clip_end = clip_start + clip->data->numRects;
- const BoxRec *c;
-
- DBG(("%s: multiple fills: (%d, %d) x %d, clip start((%d, %d), (%d,%d)), end((%d, %d), (%d, %d))\n",
- __FUNCTION__, b.x1, b.y1, b.x2 - b.x1,
- clip_start->x1, clip_start->y1,
- clip_start->x2, clip_start->y2,
- clip_end[-1].x1, clip_end[-1].y1,
- clip_end[-1].x2, clip_end[-1].y2));
-
- c = find_clip_box_for_y(clip_start, clip_end, b.y1);
- while (c != clip_end) {
- int16_t x1, x2;
-
- DBG(("%s: clip box? (%d, %d), (%d, %d)\n",
- __FUNCTION__,
- c->x1, c->y1, c->x2, c->y2));
-
- if (b.y2 <= c->y1 || b.x2 <= c->x1)
- break;
-
- if (b.x1 > c->x2) {
- c++;
- continue;
- }
-
- x1 = c->x1;
- x2 = c->x2;
- c++;
-
- if (x1 < b.x1)
- x1 = b.x1;
- if (x2 > b.x2)
- x2 = b.x2;
- if (x2 > x1) {
- DBG(("%s: fbFill(%d, %d) x %d\n",
- __FUNCTION__, x1, b.y1, x2 - x1));
- fbFill(drawable, gc,
- x1, b.y1, x2 - x1, 1);
- }
- }
- }
- }
-}
-
struct sna_fill_spans {
struct sna *sna;
PixmapPtr pixmap;
@@ -5300,16 +5323,18 @@ fallback:
if (!RegionNotEmpty(&region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fbFillSpans\n", __FUNCTION__));
fbFillSpans(drawable, gc, n, pt, width, sorted);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -5339,16 +5364,18 @@ fallback:
if (!RegionNotEmpty(&region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, true)))
- goto out;
+ goto out_gc;
DBG(("%s: fbSetSpans\n", __FUNCTION__));
fbSetSpans(drawable, gc, src, pt, width, n, sorted);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -5822,16 +5849,21 @@ sna_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
fallback:
DBG(("%s: fallback\n", __FUNCTION__));
- if (!sna_gc_move_to_cpu(gc, dst))
+ if (!sna_gc_move_to_cpu(gc, dst, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(dst, &region,
MOVE_READ | MOVE_WRITE))
- goto out;
+ goto out_gc;
DBG(("%s: fbCopyPlane(%d, %d, %d, %d, %d,%d) %x\n",
__FUNCTION__, src_x, src_y, w, h, dst_x, dst_y, (unsigned)bit));
- ret = fbCopyPlane(src, dst, gc, src_x, src_y, w, h, dst_x, dst_y, bit);
+ ret = miDoCopy(src, dst, gc,
+ src_x, src_y, w, h, dst_x, dst_y,
+ src->bitsPerPixel > 1 ? fbCopyNto1 : fbCopy1toN,
+ bit, 0);
FALLBACK_FLUSH(dst);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
return ret;
@@ -5894,7 +5926,7 @@ sna_poly_point_blt(DrawablePtr drawable,
b = box;
} while (n);
} else {
- RegionPtr clip = fbGetCompositeClip(gc);
+ RegionPtr clip = gc->pCompositeClip;
while (n--) {
int x, y;
@@ -5976,13 +6008,6 @@ sna_poly_point_extents(DrawablePtr drawable, GCPtr gc,
}
static void
-sna_poly_point__cpu(DrawablePtr drawable, GCPtr gc,
- int mode, int n, DDXPointPtr pt)
-{
- fbPolyPoint(drawable, gc, mode, n, pt);
-}
-
-static void
sna_poly_point(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr pt)
{
@@ -6035,16 +6060,18 @@ fallback:
if (!RegionNotEmpty(&region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable, gc,
n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fbPolyPoint\n", __FUNCTION__));
fbPolyPoint(drawable, gc, mode, n, pt);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -7058,34 +7085,23 @@ fallback:
if (!RegionNotEmpty(&data.region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &data.region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &data.region,
drawable_gc_flags(drawable, gc,
!(data.flags & 4 && n == 2))))
- goto out;
-
- /* Install FillSpans in case we hit a fallback path in fbPolyLine */
- sna_gc(gc)->priv = &data.region;
- assert(gc->ops == (GCOps *)&sna_gc_ops);
- gc->ops = (GCOps *)&sna_gc_ops__cpu;
+ goto out_gc;
DBG(("%s: fbPolyLine\n", __FUNCTION__));
fbPolyLine(drawable, gc, mode, n, pt);
FALLBACK_FLUSH(drawable);
- gc->ops = (GCOps *)&sna_gc_ops;
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&data.region);
}
-static void
-sna_poly_line__cpu(DrawablePtr drawable, GCPtr gc,
- int mode, int n, DDXPointPtr pt)
-{
- fbPolyLine(drawable, gc, mode, n, pt);
-}
-
static inline void box_from_seg(BoxPtr b, xSegment *seg, GCPtr gc)
{
if (seg->x1 == seg->x2) {
@@ -7913,23 +7929,19 @@ fallback:
if (!RegionNotEmpty(&data.region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &data.region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &data.region,
drawable_gc_flags(drawable, gc,
!(data.flags & 4 && n == 1))))
- goto out;
-
- /* Install FillSpans in case we hit a fallback path in fbPolySegment */
- sna_gc(gc)->priv = &data.region;
- assert(gc->ops == (GCOps *)&sna_gc_ops);
- gc->ops = (GCOps *)&sna_gc_ops__cpu;
+ goto out_gc;
DBG(("%s: fbPolySegment\n", __FUNCTION__));
fbPolySegment(drawable, gc, n, seg);
FALLBACK_FLUSH(drawable);
- gc->ops = (GCOps *)&sna_gc_ops;
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&data.region);
}
@@ -8519,16 +8531,18 @@ fallback:
if (!RegionNotEmpty(&region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, true)))
goto out;
- DBG(("%s: fbPolyRectangle\n", __FUNCTION__));
- fbPolyRectangle(drawable, gc, n, r);
+ DBG(("%s: miPolyRectangle\n", __FUNCTION__));
+ miPolyRectangle(drawable, gc, n, r);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -8698,23 +8712,19 @@ fallback:
if (!RegionNotEmpty(&data.region))
return;
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &data.region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &data.region,
drawable_gc_flags(drawable,
gc, true)))
- goto out;
-
- /* Install FillSpans in case we hit a fallback path in fbPolyArc */
- sna_gc(gc)->priv = &data.region;
- assert(gc->ops == (GCOps *)&sna_gc_ops);
- gc->ops = (GCOps *)&sna_gc_ops__cpu;
+ goto out_gc;
DBG(("%s -- fbPolyArc\n", __FUNCTION__));
fbPolyArc(drawable, gc, n, arc);
FALLBACK_FLUSH(drawable);
- gc->ops = (GCOps *)&sna_gc_ops;
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&data.region);
}
@@ -9050,21 +9060,18 @@ fallback:
return;
}
- if (!sna_gc_move_to_cpu(gc, draw))
+ if (!sna_gc_move_to_cpu(gc, draw, &data.region))
goto out;
if (!sna_drawable_move_region_to_cpu(draw, &data.region,
drawable_gc_flags(draw, gc,
true)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n",
__FUNCTION__));
- sna_gc(gc)->priv = &data.region;
- assert(gc->ops == (GCOps *)&sna_gc_ops);
- gc->ops = (GCOps *)&sna_gc_ops__cpu;
-
miFillPolygon(draw, gc, shape, mode, n, pt);
- gc->ops = (GCOps *)&sna_gc_ops;
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&data.region);
}
@@ -10465,72 +10472,18 @@ fallback:
return;
}
- if (!sna_gc_move_to_cpu(gc, draw))
+ if (!sna_gc_move_to_cpu(gc, draw, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(draw, &region,
drawable_gc_flags(draw, gc,
n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback - fbPolyFillRect\n", __FUNCTION__));
- if (region.data == NULL) {
- do {
- BoxRec box;
-
- box.x1 = rect->x + draw->x;
- box.y1 = rect->y + draw->y;
- box.x2 = bound(box.x1, rect->width);
- box.y2 = bound(box.y1, rect->height);
- rect++;
-
- if (box_intersect(&box, &region.extents)) {
- DBG(("%s: fallback - fbFill((%d, %d), (%d, %d))\n",
- __FUNCTION__,
- box.x1, box.y1,
- box.x2-box.x1, box.y2-box.y1));
- fbFill(draw, gc,
- box.x1, box.y1,
- box.x2-box.x1, box.y2-box.y1);
- }
- } while (--n);
- } else {
- const BoxRec * const clip_start = RegionBoxptr(&region);
- const BoxRec * const clip_end = clip_start + region.data->numRects;
- const BoxRec *c;
-
- do {
- BoxRec box;
-
- box.x1 = rect->x + draw->x;
- box.y1 = rect->y + draw->y;
- box.x2 = bound(box.x1, rect->width);
- box.y2 = bound(box.y1, rect->height);
- rect++;
-
- c = find_clip_box_for_y(clip_start,
- clip_end,
- box.y1);
-
- while (c != clip_end) {
- BoxRec b;
-
- if (box.y2 <= c->y1)
- break;
-
- b = box;
- if (box_intersect(&b, c++)) {
- DBG(("%s: fallback - fbFill((%d, %d), (%d, %d))\n",
- __FUNCTION__,
- b.x1, b.y1,
- b.x2-b.x1, b.y2-b.y1));
- fbFill(draw, gc,
- b.x1, b.y1,
- b.x2-b.x1, b.y2-b.y1);
- }
- }
- } while (--n);
- }
+ fbPolyFillRect(draw, gc, n, rect);
FALLBACK_FLUSH(draw);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -10650,21 +10603,19 @@ fallback:
return;
}
- if (!sna_gc_move_to_cpu(gc, draw))
+ if (!sna_gc_move_to_cpu(gc, draw, &data.region))
goto out;
if (!sna_drawable_move_region_to_cpu(draw, &data.region,
drawable_gc_flags(draw, gc,
true)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- miPolyFillArc -> sna_fill_spans__cpu\n",
__FUNCTION__));
- sna_gc(gc)->priv = &data.region;
- assert(gc->ops == (GCOps *)&sna_gc_ops);
- gc->ops = (GCOps *)&sna_gc_ops__cpu;
miPolyFillArc(draw, gc, n, arc);
- gc->ops = (GCOps *)&sna_gc_ops;
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&data.region);
}
@@ -10682,6 +10633,8 @@ sna_realize_font(ScreenPtr screen, FontPtr font)
{
struct sna_font *priv;
+ DBG(("%s (key=%d)\n", __FUNCTION__, sna_font_key));
+
priv = calloc(1, sizeof(struct sna_font));
if (priv == NULL)
return FALSE;
@@ -10700,6 +10653,8 @@ sna_unrealize_font(ScreenPtr screen, FontPtr font)
struct sna_font *priv = FontGetPrivate(font, sna_font_key);
int i, j;
+ DBG(("%s (key=%d)\n", __FUNCTION__, sna_font_key));
+
if (priv == NULL)
return TRUE;
@@ -11110,17 +11065,19 @@ force_fallback:
gc->font->get_glyphs(gc->font, count, (unsigned char *)chars,
Linear8Bit, &n, info);
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, true)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbPolyGlyphBlt\n", __FUNCTION__));
fbPolyGlyphBlt(drawable, gc, x, y, n,
info, FONTGLYPHS(gc->font));
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
}
out:
RegionUninit(&region);
@@ -11203,16 +11160,18 @@ force_fallback:
FONTLASTROW(gc->font) ? TwoD16Bit : Linear16Bit,
&n, info);
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable, gc, true)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbPolyGlyphBlt\n", __FUNCTION__));
fbPolyGlyphBlt(drawable, gc, x, y, n,
info, FONTGLYPHS(gc->font));
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
}
out:
RegionUninit(&region);
@@ -11304,17 +11263,19 @@ force_fallback:
gc->font->get_glyphs(gc->font, count, (unsigned char *)chars,
Linear8Bit, &n, info);
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbImageGlyphBlt\n", __FUNCTION__));
fbImageGlyphBlt(drawable, gc, x, y, n,
info, FONTGLYPHS(gc->font));
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
}
out:
RegionUninit(&region);
@@ -11399,17 +11360,19 @@ force_fallback:
FONTLASTROW(gc->font) ? TwoD16Bit : Linear16Bit,
&n, info);
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbImageGlyphBlt\n", __FUNCTION__));
fbImageGlyphBlt(drawable, gc, x, y, n,
info, FONTGLYPHS(gc->font));
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
}
out:
RegionUninit(&region);
@@ -11695,17 +11658,19 @@ sna_image_glyph(DrawablePtr drawable, GCPtr gc,
fallback:
DBG(("%s: fallback\n", __FUNCTION__));
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, n > 1)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbImageGlyphBlt\n", __FUNCTION__));
fbImageGlyphBlt(drawable, gc, x, y, n, info, base);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -11774,17 +11739,19 @@ sna_poly_glyph(DrawablePtr drawable, GCPtr gc,
fallback:
DBG(("%s: fallback\n", __FUNCTION__));
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, true)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback -- fbPolyGlyphBlt\n", __FUNCTION__));
fbPolyGlyphBlt(drawable, gc, x, y, n, info, base);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -11956,19 +11923,21 @@ sna_push_pixels(GCPtr gc, PixmapPtr bitmap, DrawablePtr drawable,
}
DBG(("%s: fallback\n", __FUNCTION__));
- if (!sna_gc_move_to_cpu(gc, drawable))
+ if (!sna_gc_move_to_cpu(gc, drawable, &region))
goto out;
if (!sna_pixmap_move_to_cpu(bitmap, MOVE_READ))
- goto out;
+ goto out_gc;
if (!sna_drawable_move_region_to_cpu(drawable, &region,
drawable_gc_flags(drawable,
gc, false)))
- goto out;
+ goto out_gc;
DBG(("%s: fallback, fbPushPixels(%d, %d, %d %d)\n",
__FUNCTION__, w, h, x, y));
fbPushPixels(gc, bitmap, drawable, w, h, x, y);
FALLBACK_FLUSH(drawable);
+out_gc:
+ sna_gc_move_to_gpu(gc);
out:
RegionUninit(&region);
}
@@ -11997,26 +11966,26 @@ static const GCOps sna_gc_ops = {
};
static const GCOps sna_gc_ops__cpu = {
- sna_fill_spans__cpu,
- sna_set_spans,
- sna_put_image,
- sna_copy_area,
- sna_copy_plane,
- sna_poly_point__cpu,
- sna_poly_line__cpu,
- sna_poly_segment,
- sna_poly_rectangle,
- sna_poly_arc,
- sna_poly_fill_polygon,
- sna_poly_fill_rect,
- sna_poly_fill_arc,
- sna_poly_text8,
- sna_poly_text16,
- sna_image_text8,
- sna_image_text16,
- sna_image_glyph,
- sna_poly_glyph,
- sna_push_pixels,
+ fbFillSpans,
+ fbSetSpans,
+ fbPutImage,
+ fbCopyArea,
+ fbCopyPlane,
+ fbPolyPoint,
+ fbPolyLine,
+ fbPolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ fbPolyFillRect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ fbImageGlyphBlt,
+ fbPolyGlyphBlt,
+ fbPushPixels
};
static GCOps sna_gc_ops__tmp = {
@@ -12065,10 +12034,22 @@ static const GCFuncs sna_gc_funcs = {
miCopyClip
};
+static const GCFuncs sna_gc_funcs__cpu = {
+ fbValidateGC,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
static int sna_create_gc(GCPtr gc)
{
- if (!fbCreateGC(gc))
- return FALSE;
+ gc->miTranslate = 1;
+ gc->fExpose = 1;
+
+ fb_gc(gc)->bpp = bits_per_pixel(gc->depth);
gc->funcs = (GCFuncs *)&sna_gc_funcs;
gc->ops = (GCOps *)&sna_gc_ops;
@@ -12084,6 +12065,9 @@ sna_get_image(DrawablePtr drawable,
RegionRec region;
unsigned int flags;
+ if (!fbDrawableEnabled(drawable))
+ return;
+
DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
region.extents.x1 = x + drawable->x;
@@ -12126,6 +12110,9 @@ sna_get_spans(DrawablePtr drawable, int wMax,
{
RegionRec region;
+ if (!fbDrawableEnabled(drawable))
+ return;
+
if (sna_spans_extents(drawable, NULL, n, pt, width, &region.extents) == 0)
return;
@@ -12145,13 +12132,8 @@ sna_copy_window(WindowPtr win, DDXPointRec origin, RegionPtr src)
int dx, dy;
DBG(("%s origin=(%d, %d)\n", __FUNCTION__, origin.x, origin.y));
-
- if (wedged(sna)) {
- DBG(("%s: fallback -- wedged\n", __FUNCTION__));
- if (sna_pixmap_move_to_cpu(pixmap, MOVE_READ | MOVE_WRITE))
- fbCopyWindow(win, origin, src);
+ if (!fbWindowEnabled(win))
return;
- }
dx = origin.x - win->drawable.x;
dy = origin.y - win->drawable.y;
@@ -12164,8 +12146,17 @@ sna_copy_window(WindowPtr win, DDXPointRec origin, RegionPtr src)
RegionTranslate(&dst, -pixmap->screen_x, -pixmap->screen_y);
#endif
- miCopyRegion(&pixmap->drawable, &pixmap->drawable,
- NULL, &dst, dx, dy, sna_self_copy_boxes, 0, NULL);
+ if (wedged(sna)) {
+ DBG(("%s: fallback -- wedged\n", __FUNCTION__));
+ if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ | MOVE_WRITE))
+ return;
+
+ miCopyRegion(&pixmap->drawable, &pixmap->drawable,
+ 0, &dst, dx, dy, fbCopyNtoN, 0, NULL);
+ } else {
+ miCopyRegion(&pixmap->drawable, &pixmap->drawable,
+ NULL, &dst, dx, dy, sna_self_copy_boxes, 0, NULL);
+ }
RegionUninit(&dst);
}
@@ -12189,7 +12180,7 @@ static Bool sna_change_window_attributes(WindowPtr win, unsigned long mask)
ret &= sna_validate_pixmap(&win->drawable, win->border.pixmap);
}
- return ret && fbChangeWindowAttributes(win, mask);
+ return ret;
}
static void
@@ -12585,20 +12576,112 @@ static void sna_accel_debug_memory(struct sna *sna)
static void sna_accel_debug_memory(struct sna *sna) { }
#endif
-Bool sna_accel_pre_init(struct sna *sna)
+static ShmFuncs shm_funcs = { sna_pixmap_create_shm, NULL };
+
+static PixmapPtr
+sna_get_window_pixmap(WindowPtr window)
+{
+ return get_window_pixmap(window);
+}
+
+static void
+sna_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
+{
+ *(PixmapPtr *)window->devPrivates = pixmap;
+}
+
+static Bool
+sna_create_window(WindowPtr win)
{
+ sna_set_window_pixmap(win, win->drawable.pScreen->devPrivate);
return TRUE;
}
-static ShmFuncs shm_funcs = { sna_pixmap_create_shm, NULL };
+static Bool
+sna_map_window(WindowPtr win)
+{
+ return TRUE;
+}
+
+static Bool
+sna_position_window(WindowPtr win, int x, int y)
+{
+ return TRUE;
+}
-Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
+static Bool
+sna_unmap_window(WindowPtr win)
+{
+ return TRUE;
+}
+
+static Bool
+sna_destroy_window(WindowPtr win)
+{
+ return TRUE;
+}
+
+static void
+sna_query_best_size(int class,
+ unsigned short *width, unsigned short *height,
+ ScreenPtr screen)
+{
+ unsigned short w;
+
+ switch (class) {
+ case CursorShape:
+ if (*width > screen->width)
+ *width = screen->width;
+ if (*height > screen->height)
+ *height = screen->height;
+ break;
+
+ case TileShape:
+ case StippleShape:
+ w = *width;
+ if ((w & (w - 1)) && w < FB_UNIT) {
+ for (w = 1; w < *width; w <<= 1)
+ ;
+ *width = w;
+ }
+ break;
+ }
+}
+
+static void sna_store_colors(ColormapPtr cmap, int n, xColorItem *def)
+{
+}
+
+static bool sna_picture_init(ScreenPtr screen)
+{
+ PictureScreenPtr ps;
+
+ if (!miPictureInit(screen, NULL, 0))
+ return false;
+
+ ps = GetPictureScreen(screen);
+ assert(ps != NULL);
+
+ ps->Composite = sna_composite;
+ ps->CompositeRects = sna_composite_rectangles;
+ ps->Glyphs = sna_glyphs;
+ ps->UnrealizeGlyph = sna_glyph_unrealize;
+ ps->AddTraps = sna_add_traps;
+ ps->Trapezoids = sna_composite_trapezoids;
+ ps->Triangles = sna_composite_triangles;
+#if PICTURE_SCREEN_VERSION >= 2
+ ps->TriStrip = sna_composite_tristrip;
+ ps->TriFan = sna_composite_trifan;
+#endif
+
+ return true;
+}
+
+bool sna_accel_init(ScreenPtr screen, struct sna *sna)
{
const char *backend;
sna_font_key = AllocateFontPrivateIndex();
- screen->RealizeFont = sna_realize_font;
- screen->UnrealizeFont = sna_unrealize_font;
list_init(&sna->dirty_pixmaps);
list_init(&sna->active_pixmaps);
@@ -12611,35 +12694,53 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
sna->timer_expire[DEBUG_MEMORY_TIMER] = GetTimeInMillis()+ 10 * 1000;
#endif
- screen->CreateGC = sna_create_gc;
+ screen->defColormap = FakeClientID(0);
+ /* let CreateDefColormap do whatever it wants for pixels */
+ screen->blackPixel = screen->whitePixel = (Pixel) 0;
+ screen->QueryBestSize = sna_query_best_size;
+ assert(screen->GetImage == NULL);
screen->GetImage = sna_get_image;
+ assert(screen->GetSpans == NULL);
screen->GetSpans = sna_get_spans;
- screen->CopyWindow = sna_copy_window;
+ assert(screen->CreateWindow == NULL);
+ screen->CreateWindow = sna_create_window;
+ assert(screen->DestroyWindow == NULL);
+ screen->DestroyWindow = sna_destroy_window;
+ screen->PositionWindow = sna_position_window;
screen->ChangeWindowAttributes = sna_change_window_attributes;
+ screen->RealizeWindow = sna_map_window;
+ screen->UnrealizeWindow = sna_unmap_window;
+ screen->CopyWindow = sna_copy_window;
+ assert(screen->CreatePixmap == NULL);
screen->CreatePixmap = sna_create_pixmap;
+ assert(screen->DestroyPixmap == NULL);
screen->DestroyPixmap = sna_destroy_pixmap;
-
-#ifdef RENDER
- {
- PictureScreenPtr ps = GetPictureScreenIfSet(screen);
- if (ps) {
- ps->Composite = sna_composite;
- ps->CompositeRects = sna_composite_rectangles;
- ps->Glyphs = sna_glyphs;
- ps->UnrealizeGlyph = sna_glyph_unrealize;
- ps->AddTraps = sna_add_traps;
- ps->Trapezoids = sna_composite_trapezoids;
- ps->Triangles = sna_composite_triangles;
-#if PICTURE_SCREEN_VERSION >= 2
- ps->TriStrip = sna_composite_tristrip;
- ps->TriFan = sna_composite_trifan;
-#endif
- }
- }
-#endif
+ screen->RealizeFont = sna_realize_font;
+ screen->UnrealizeFont = sna_unrealize_font;
+ assert(screen->CreateGC == NULL);
+ screen->CreateGC = sna_create_gc;
+ screen->CreateColormap = miInitializeColormap;
+ screen->DestroyColormap = (void (*)(ColormapPtr)) NoopDDA;
+ screen->InstallColormap = miInstallColormap;
+ screen->UninstallColormap = miUninstallColormap;
+ screen->ListInstalledColormaps = miListInstalledColormaps;
+ screen->ResolveColor = miResolveColor;
+ assert(screen->StoreColors = PictureStoreColors);
+ screen->StoreColors = sna_store_colors;
+ screen->BitmapToRegion = fbBitmapToRegion;
+
+ assert(screen->GetWindowPixmap == NULL);
+ screen->GetWindowPixmap = sna_get_window_pixmap;
+ assert(screen->SetWindowPixmap == NULL);
+ screen->SetWindowPixmap = sna_set_window_pixmap;
if (USE_SHM_VMAP && sna->kgem.has_vmap)
ShmRegisterFuncs(screen, &shm_funcs);
+ else
+ ShmRegisterFbFuncs(screen);
+
+ if (!sna_picture_init(screen))
+ return false;
backend = "no";
sna->have_render = false;
@@ -12718,9 +12819,9 @@ void sna_accel_close(struct sna *sna)
sna_glyphs_close(sna);
if (sna->freed_pixmap) {
- assert(sna->freed_pixmap->refcnt == 1);
+ assert(sna->freed_pixmap->refcnt == 0);
free(sna_pixmap(sna->freed_pixmap));
- fbDestroyPixmap(sna->freed_pixmap);
+ FreePixmap(sna->freed_pixmap);
sna->freed_pixmap = NULL;
}
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 7690afed..0b0471ec 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -38,9 +38,6 @@
#include "sna_reg.h"
#include "rop.h"
-#include <mipict.h>
-#include <fbpict.h>
-
#if DEBUG_BLT
#undef DBG
#define DBG(x) ErrorF x
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 49414770..606acb64 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -32,9 +32,9 @@
#include "sna.h"
#include "sna_render.h"
#include "sna_render_inline.h"
+#include "fb/fbpict.h"
#include <mipict.h>
-#include <fbpict.h>
#if DEBUG_COMPOSITE
#undef DBG
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 0b1a4948..7c1d3bce 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -45,11 +45,9 @@
#include <xf86drm.h>
#include <xf86DDC.h> /* for xf86InterpretEDID */
-#include <fb.h>
-#include <fbpict.h>
-
#include "sna.h"
#include "sna_reg.h"
+#include "fb/fbpict.h"
#include "intel_options.h"
@@ -2651,7 +2649,8 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region)
if (ptr == NULL)
return;
- pixmap = fbCreatePixmap(screen, 0, 0, sna->front->drawable.depth, 0);
+ pixmap = sna_pixmap_create_unattached(screen,
+ 0, 0, sna->front->drawable.depth);
if (pixmap == NullPixmap)
return;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index eb4776b4..d12c2b0e 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -48,8 +48,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <xf86cmap.h>
#include <xf86drm.h>
#include <xf86RandR12.h>
+#include <mi.h>
#include <micmap.h>
-#include <fb.h>
+#include <mipict.h>
+#include <mibstore.h>
#include "compiler.h"
#include "sna.h"
@@ -78,11 +80,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define DBG(x) ErrorF x
#endif
-DevPrivateKeyRec sna_private_index;
-DevPrivateKeyRec sna_pixmap_index;
-DevPrivateKeyRec sna_gc_index;
-DevPrivateKeyRec sna_glyph_key;
-DevPrivateKeyRec sna_glyph_image_key;
+static DevPrivateKeyRec sna_private_index;
+static DevPrivateKeyRec sna_pixmap_index;
+static DevPrivateKeyRec sna_gc_index;
+static DevPrivateKeyRec sna_glyph_key;
+static DevPrivateKeyRec sna_window_key;
static Bool sna_enter_vt(VT_FUNC_ARGS_DECL);
@@ -556,16 +558,10 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
/* Set display resolution */
xf86SetDpi(scrn, 0, 0);
- /* Load the required sub modules */
- if (!xf86LoadSubModule(scrn, "fb")) {
- PreInitCleanup(scrn);
- return FALSE;
- }
-
/* Load the dri2 module if requested. */
xf86LoadSubModule(scrn, "dri2");
- return sna_accel_pre_init(sna);
+ return TRUE;
}
static void
@@ -753,6 +749,8 @@ static Bool sna_close_screen(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
struct sna *sna = to_sna(scrn);
+ DepthPtr depths;
+ int d;
DBG(("%s\n", __FUNCTION__));
@@ -771,11 +769,12 @@ static Bool sna_close_screen(CLOSE_SCREEN_ARGS_DECL)
xf86_cursors_fini(screen);
- /* XXX unhook devPrivate otherwise fbCloseScreen frees it! */
- screen->devPrivate = NULL;
+ depths = screen->allowedDepths;
+ for (d = 0; d < screen->numDepths; d++)
+ free(depths[d].vids);
+ free(depths);
- screen->CloseScreen = sna->CloseScreen;
- (*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
+ free(screen->visuals);
if (sna->directRenderingOpen) {
sna_dri_close(sna, screen);
@@ -812,7 +811,7 @@ sna_register_all_privates(void)
assert(sna_pixmap_index.offset == sizeof(void*));
if (!dixRegisterPrivateKey(&sna_gc_index, PRIVATE_GC,
- sizeof(struct sna_gc)))
+ sizeof(FbGCPrivate)))
return FALSE;
assert(sna_gc_index.offset == 0);
@@ -821,6 +820,11 @@ sna_register_all_privates(void)
return FALSE;
assert(sna_glyph_key.offset == 0);
+ if (!dixRegisterPrivateKey(&sna_window_key,
+ PRIVATE_WINDOW, 0))
+ return FALSE;
+ assert(sna_window_key.offset == 0);
+
return TRUE;
}
@@ -835,7 +839,12 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
struct sna *sna = to_sna(scrn);
- VisualPtr visual;
+ VisualPtr visuals;
+ DepthPtr depths;
+ int nvisuals;
+ int ndepths;
+ int rootdepth;
+ VisualID defaultVisual;
DBG(("%s\n", __FUNCTION__));
@@ -852,16 +861,23 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
if (!miSetPixmapDepths())
return FALSE;
- if (!fbScreenInit(screen, NULL,
+ rootdepth = 0;
+ if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth,
+ &defaultVisual,
+ ((unsigned long)1 << (scrn->bitsPerPixel - 1)),
+ 8, -1))
+ return FALSE;
+
+ if (!miScreenInit(screen, NULL,
scrn->virtualX, scrn->virtualY,
- scrn->xDpi, scrn->yDpi,
- scrn->displayWidth, scrn->bitsPerPixel))
+ scrn->xDpi, scrn->yDpi, 0,
+ rootdepth, ndepths, depths,
+ defaultVisual, nvisuals, visuals))
return FALSE;
- assert(fbGetWinPrivateKey()->offset == 0);
if (scrn->bitsPerPixel > 8) {
/* Fixup RGB ordering */
- visual = screen->visuals + screen->numVisuals;
+ VisualPtr visual = screen->visuals + screen->numVisuals;
while (--visual >= screen->visuals) {
if ((visual->class | DynamicClass) == DirectColor) {
visual->offsetRed = scrn->offset.red;
@@ -874,16 +890,16 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
}
}
- fbPictureInit(screen, NULL, 0);
-
- xf86SetBlackWhitePixels(screen);
-
+ assert(screen->CloseScreen == NULL);
+ screen->CloseScreen = sna_close_screen;
if (!sna_accel_init(screen, sna)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Hardware acceleration initialization failed\n");
return FALSE;
}
+ xf86SetBlackWhitePixels(screen);
+
miInitializeBackingStore(screen);
xf86SetBackingStore(screen);
xf86SetSilkenMouse(screen);
@@ -914,8 +930,6 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
screen->WakeupHandler = sna_wakeup_handler;
screen->SaveScreen = xf86SaveScreen;
- sna->CloseScreen = screen->CloseScreen;
- screen->CloseScreen = sna_close_screen;
screen->CreateScreenResources = sna_create_screen_resources;
if (!xf86CrtcScreenInit(screen))
diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
index d9a3dcf6..01795207 100644
--- a/src/sna/sna_glyphs.c
+++ b/src/sna/sna_glyphs.c
@@ -65,10 +65,9 @@
#include "sna.h"
#include "sna_render.h"
#include "sna_render_inline.h"
+#include "fb/fbpict.h"
#include <mipict.h>
-#include <fbpict.h>
-#include <fb.h>
#if DEBUG_GLYPHS
#undef DBG
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index c22965c7..f6a562b0 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -28,8 +28,7 @@
#include "sna.h"
#include "sna_render.h"
#include "sna_render_inline.h"
-
-#include <fb.h>
+#include "fb/fbpict.h"
#if DEBUG_RENDER
#undef DBG
@@ -108,7 +107,7 @@ static Bool
no_render_copy_boxes(struct sna *sna, uint8_t alu,
PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
- const BoxRec *box, int n)
+ const BoxRec *box, int n, unsigned flags)
{
DBG(("%s (n=%d)\n", __FUNCTION__, n));
diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c
index b20eceb8..ae14d796 100644
--- a/src/sna/sna_tiling.c
+++ b/src/sna/sna_tiling.c
@@ -31,8 +31,7 @@
#include "sna.h"
#include "sna_render.h"
-
-#include <fbpict.h>
+#include "fb/fbpict.h"
#if DEBUG_RENDER
#undef DBG
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index d83c083c..56c6a3e9 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -34,10 +34,9 @@
#include "sna.h"
#include "sna_render.h"
#include "sna_render_inline.h"
+#include "fb/fbpict.h"
-#include <fb.h>
#include <mipict.h>
-#include <fbpict.h>
#if DEBUG_TRAPEZOIDS
#undef DBG
@@ -5213,9 +5212,8 @@ trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
DBG(("%s: mask (%dx%d), dx=(%d, %d)\n",
__FUNCTION__, extents.x2, extents.y2, dx, dy));
- scratch = fbCreatePixmap(screen,
- extents.x2, extents.y2, 8,
- CREATE_PIXMAP_USAGE_SCRATCH);
+ scratch = sna_pixmap_create_unattached(screen,
+ extents.x2, extents.y2, 8);
if (!scratch)
return true;
@@ -5882,8 +5880,17 @@ sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
DBG(("%s -- fallback\n", __FUNCTION__));
if (sna_drawable_move_to_cpu(picture->pDrawable,
- MOVE_READ | MOVE_WRITE))
- fbAddTraps(picture, x, y, n, t);
+ MOVE_READ | MOVE_WRITE)) {
+ pixman_image_t *image;
+ int dx, dy;
+
+ if (!(image = image_from_pict(picture, FALSE, &dx, &dy)))
+ return;
+
+ pixman_add_traps(image, x + dx, y + dy, n, (pixman_trap_t *)t);
+
+ free_pixman_pict(picture, image);
+ }
}
static inline void