diff options
Diffstat (limited to 'src/sna/fb/fbfill.c')
-rw-r--r-- | src/sna/fb/fbfill.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/sna/fb/fbfill.c b/src/sna/fb/fbfill.c new file mode 100644 index 000000000..a9ae2bcd7 --- /dev/null +++ b/src/sna/fb/fbfill.c @@ -0,0 +1,221 @@ +/* + * 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 tile = gc->tile.pixmap; + + fbTile(dst + (y + dstYoff) * dstStride, dstStride, + (x + dstXoff) * dstBpp, width * dstBpp, height, + tile->devPrivate.ptr, tile->devKind / sizeof(FbBits), + tile->drawable.width * tile->drawable.bitsPerPixel, + tile->drawable.height, + 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); + } +} |