/* * 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); } }