diff options
Diffstat (limited to 'src/sna')
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 = ®ion->extents + 1; + return ®ion->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(¢er, 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(®ion, -dx, -dy); - if (!sna_gc_move_to_cpu(gc, drawable)) + if (!sna_gc_move_to_cpu(gc, drawable, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(dst, ®ion, MOVE_READ | MOVE_WRITE)) - goto out; + goto out_gc; RegionTranslate(®ion, src_x - dst_x - dst->x + src->x, src_y - dst_y - dst->y + src->y); if (!sna_drawable_move_region_to_cpu(src, ®ion, 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(®ion); 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(®ion)) return; - if (!sna_gc_move_to_cpu(gc, drawable)) + if (!sna_gc_move_to_cpu(gc, drawable, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -5339,16 +5364,18 @@ fallback: if (!RegionNotEmpty(®ion)) return; - if (!sna_gc_move_to_cpu(gc, drawable)) + if (!sna_gc_move_to_cpu(gc, drawable, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(dst, ®ion, 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(®ion); 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(®ion)) return; - if (!sna_gc_move_to_cpu(gc, drawable)) + if (!sna_gc_move_to_cpu(gc, drawable, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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(®ion)) return; - if (!sna_gc_move_to_cpu(gc, drawable)) + if (!sna_gc_move_to_cpu(gc, drawable, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(draw, ®ion, 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, ®ion.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(®ion); - 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion)) goto out; if (!sna_pixmap_move_to_cpu(bitmap, MOVE_READ)) - goto out; + goto out_gc; if (!sna_drawable_move_region_to_cpu(drawable, ®ion, 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(®ion); } @@ -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, ®ion.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 |