105b261ecSmrg/* 205b261ecSmrg * Copyright © 1998 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that 705b261ecSmrg * copyright notice and this permission notice appear in supporting 805b261ecSmrg * documentation, and that the name of Keith Packard not be used in 905b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1005b261ecSmrg * specific, written prior permission. Keith Packard makes no 1105b261ecSmrg * representations about the suitability of this software for any purpose. It 1205b261ecSmrg * is provided "as is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2405b261ecSmrg#include <dix-config.h> 2505b261ecSmrg#endif 2605b261ecSmrg 2705b261ecSmrg#include "fb.h" 2805b261ecSmrg 2935c4bbdfSmrgstatic void 3035c4bbdfSmrgfbStipple(FbBits * dst, FbStride dstStride, 3135c4bbdfSmrg int dstX, int dstBpp, 3235c4bbdfSmrg int width, int height, 3335c4bbdfSmrg FbStip * stip, FbStride stipStride, 3435c4bbdfSmrg int stipWidth, int stipHeight, 3535c4bbdfSmrg FbBits fgand, FbBits fgxor, 3635c4bbdfSmrg FbBits bgand, FbBits bgxor, 3735c4bbdfSmrg int xRot, int yRot) 3835c4bbdfSmrg{ 3935c4bbdfSmrg int stipX, stipY, sx; 4035c4bbdfSmrg int widthTmp; 4135c4bbdfSmrg int h, w; 4235c4bbdfSmrg int x, y; 4335c4bbdfSmrg 4435c4bbdfSmrg modulus(-yRot, stipHeight, stipY); 4535c4bbdfSmrg modulus(dstX / dstBpp - xRot, stipWidth, stipX); 4635c4bbdfSmrg y = 0; 4735c4bbdfSmrg while (height) { 4835c4bbdfSmrg h = stipHeight - stipY; 4935c4bbdfSmrg if (h > height) 5035c4bbdfSmrg h = height; 5135c4bbdfSmrg height -= h; 5235c4bbdfSmrg widthTmp = width; 5335c4bbdfSmrg x = dstX; 5435c4bbdfSmrg sx = stipX; 5535c4bbdfSmrg while (widthTmp) { 5635c4bbdfSmrg w = (stipWidth - sx) * dstBpp; 5735c4bbdfSmrg if (w > widthTmp) 5835c4bbdfSmrg w = widthTmp; 5935c4bbdfSmrg widthTmp -= w; 6035c4bbdfSmrg fbBltOne(stip + stipY * stipStride, 6135c4bbdfSmrg stipStride, 6235c4bbdfSmrg sx, 6335c4bbdfSmrg dst + y * dstStride, 6435c4bbdfSmrg dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); 6535c4bbdfSmrg x += w; 6635c4bbdfSmrg sx = 0; 6735c4bbdfSmrg } 6835c4bbdfSmrg y += h; 6935c4bbdfSmrg stipY = 0; 7035c4bbdfSmrg } 7135c4bbdfSmrg} 7235c4bbdfSmrg 7305b261ecSmrgvoid 7435c4bbdfSmrgfbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height) 7505b261ecSmrg{ 7635c4bbdfSmrg FbBits *dst; 7735c4bbdfSmrg FbStride dstStride; 7835c4bbdfSmrg int dstBpp; 7935c4bbdfSmrg int dstXoff, dstYoff; 8035c4bbdfSmrg FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 8135c4bbdfSmrg 8235c4bbdfSmrg fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 8305b261ecSmrg 8405b261ecSmrg switch (pGC->fillStyle) { 8505b261ecSmrg case FillSolid: 8605b261ecSmrg#ifndef FB_ACCESS_WRAPPER 8735c4bbdfSmrg if (pPriv->and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp, 8835c4bbdfSmrg x + dstXoff, y + dstYoff, 8935c4bbdfSmrg width, height, pPriv->xor)) 9035c4bbdfSmrg#endif 9135c4bbdfSmrg fbSolid(dst + (y + dstYoff) * dstStride, 9235c4bbdfSmrg dstStride, 9335c4bbdfSmrg (x + dstXoff) * dstBpp, 9435c4bbdfSmrg dstBpp, width * dstBpp, height, pPriv->and, pPriv->xor); 9535c4bbdfSmrg break; 9605b261ecSmrg case FillStippled: 9735c4bbdfSmrg case FillOpaqueStippled:{ 9835c4bbdfSmrg PixmapPtr pStip = pGC->stipple; 9935c4bbdfSmrg int stipWidth = pStip->drawable.width; 10035c4bbdfSmrg int stipHeight = pStip->drawable.height; 10135c4bbdfSmrg 10235c4bbdfSmrg if (dstBpp == 1) { 10335c4bbdfSmrg int alu; 10435c4bbdfSmrg FbBits *stip; 10535c4bbdfSmrg FbStride stipStride; 10635c4bbdfSmrg int stipBpp; 10735c4bbdfSmrg _X_UNUSED int stipXoff, stipYoff; 10835c4bbdfSmrg 10935c4bbdfSmrg if (pGC->fillStyle == FillStippled) 11035c4bbdfSmrg alu = FbStipple1Rop(pGC->alu, pGC->fgPixel); 11135c4bbdfSmrg else 11235c4bbdfSmrg alu = FbOpaqueStipple1Rop(pGC->alu, pGC->fgPixel, pGC->bgPixel); 11335c4bbdfSmrg fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff, 11435c4bbdfSmrg stipYoff); 11535c4bbdfSmrg fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff, 11635c4bbdfSmrg width, height, stip, stipStride, stipWidth, stipHeight, alu, 11735c4bbdfSmrg pPriv->pm, dstBpp, (pGC->patOrg.x + pDrawable->x + dstXoff), 11835c4bbdfSmrg pGC->patOrg.y + pDrawable->y - y); 11935c4bbdfSmrg fbFinishAccess(&pStip->drawable); 12035c4bbdfSmrg } 12135c4bbdfSmrg else { 12235c4bbdfSmrg FbStip *stip; 12335c4bbdfSmrg FbStride stipStride; 12435c4bbdfSmrg int stipBpp; 12535c4bbdfSmrg _X_UNUSED int stipXoff, stipYoff; 12635c4bbdfSmrg FbBits fgand, fgxor, bgand, bgxor; 12735c4bbdfSmrg 12835c4bbdfSmrg fgand = pPriv->and; 12935c4bbdfSmrg fgxor = pPriv->xor; 13035c4bbdfSmrg if (pGC->fillStyle == FillStippled) { 13135c4bbdfSmrg bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES); 13235c4bbdfSmrg bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES); 13335c4bbdfSmrg } 13435c4bbdfSmrg else { 13535c4bbdfSmrg bgand = pPriv->bgand; 13635c4bbdfSmrg bgxor = pPriv->bgxor; 13735c4bbdfSmrg } 13835c4bbdfSmrg 13935c4bbdfSmrg fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp, 14035c4bbdfSmrg stipXoff, stipYoff); 14135c4bbdfSmrg fbStipple(dst + (y + dstYoff) * dstStride, dstStride, 14235c4bbdfSmrg (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height, 14335c4bbdfSmrg stip, stipStride, stipWidth, stipHeight, 14435c4bbdfSmrg fgand, fgxor, bgand, bgxor, 14535c4bbdfSmrg pGC->patOrg.x + pDrawable->x + dstXoff, 14635c4bbdfSmrg pGC->patOrg.y + pDrawable->y - y); 14735c4bbdfSmrg fbFinishAccess(&pStip->drawable); 14835c4bbdfSmrg } 14935c4bbdfSmrg break; 15005b261ecSmrg } 15135c4bbdfSmrg case FillTiled:{ 15235c4bbdfSmrg PixmapPtr pTile = pGC->tile.pixmap; 15335c4bbdfSmrg FbBits *tile; 15435c4bbdfSmrg FbStride tileStride; 15535c4bbdfSmrg int tileBpp; 15635c4bbdfSmrg int tileWidth; 15735c4bbdfSmrg int tileHeight; 15835c4bbdfSmrg _X_UNUSED int tileXoff, tileYoff; 15935c4bbdfSmrg 16035c4bbdfSmrg fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff, 16135c4bbdfSmrg tileYoff); 16235c4bbdfSmrg tileWidth = pTile->drawable.width; 16335c4bbdfSmrg tileHeight = pTile->drawable.height; 16435c4bbdfSmrg fbTile(dst + (y + dstYoff) * dstStride, 16535c4bbdfSmrg dstStride, 16635c4bbdfSmrg (x + dstXoff) * dstBpp, 16735c4bbdfSmrg width * dstBpp, height, 16835c4bbdfSmrg tile, 16935c4bbdfSmrg tileStride, 17035c4bbdfSmrg tileWidth * tileBpp, 17135c4bbdfSmrg tileHeight, 17235c4bbdfSmrg pGC->alu, 17335c4bbdfSmrg pPriv->pm, 17435c4bbdfSmrg dstBpp, 17535c4bbdfSmrg (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp, 17635c4bbdfSmrg pGC->patOrg.y + pDrawable->y - y); 17735c4bbdfSmrg fbFinishAccess(&pTile->drawable); 17835c4bbdfSmrg break; 17905b261ecSmrg } 18005b261ecSmrg } 18135c4bbdfSmrg fbValidateDrawable(pDrawable); 18235c4bbdfSmrg fbFinishAccess(pDrawable); 18305b261ecSmrg} 18405b261ecSmrg 18505b261ecSmrgvoid 18635c4bbdfSmrgfbSolidBoxClipped(DrawablePtr pDrawable, 18735c4bbdfSmrg RegionPtr pClip, 18835c4bbdfSmrg int x1, int y1, int x2, int y2, FbBits and, FbBits xor) 18905b261ecSmrg{ 19035c4bbdfSmrg FbBits *dst; 19135c4bbdfSmrg FbStride dstStride; 19235c4bbdfSmrg int dstBpp; 19335c4bbdfSmrg int dstXoff, dstYoff; 19435c4bbdfSmrg BoxPtr pbox; 19535c4bbdfSmrg int nbox; 19635c4bbdfSmrg int partX1, partX2, partY1, partY2; 19735c4bbdfSmrg 19835c4bbdfSmrg fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 19935c4bbdfSmrg 2006747b715Smrg for (nbox = RegionNumRects(pClip), pbox = RegionRects(pClip); 20135c4bbdfSmrg nbox--; pbox++) { 20235c4bbdfSmrg partX1 = pbox->x1; 20335c4bbdfSmrg if (partX1 < x1) 20435c4bbdfSmrg partX1 = x1; 20535c4bbdfSmrg 20635c4bbdfSmrg partX2 = pbox->x2; 20735c4bbdfSmrg if (partX2 > x2) 20835c4bbdfSmrg partX2 = x2; 20935c4bbdfSmrg 21035c4bbdfSmrg if (partX2 <= partX1) 21135c4bbdfSmrg continue; 21235c4bbdfSmrg 21335c4bbdfSmrg partY1 = pbox->y1; 21435c4bbdfSmrg if (partY1 < y1) 21535c4bbdfSmrg partY1 = y1; 21635c4bbdfSmrg 21735c4bbdfSmrg partY2 = pbox->y2; 21835c4bbdfSmrg if (partY2 > y2) 21935c4bbdfSmrg partY2 = y2; 22035c4bbdfSmrg 22135c4bbdfSmrg if (partY2 <= partY1) 22235c4bbdfSmrg continue; 22305b261ecSmrg 22405b261ecSmrg#ifndef FB_ACCESS_WRAPPER 22535c4bbdfSmrg if (and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp, 22635c4bbdfSmrg partX1 + dstXoff, partY1 + dstYoff, 22735c4bbdfSmrg (partX2 - partX1), (partY2 - partY1), xor)) 22805b261ecSmrg#endif 22935c4bbdfSmrg fbSolid(dst + (partY1 + dstYoff) * dstStride, 23035c4bbdfSmrg dstStride, 23135c4bbdfSmrg (partX1 + dstXoff) * dstBpp, 23235c4bbdfSmrg dstBpp, 23335c4bbdfSmrg (partX2 - partX1) * dstBpp, (partY2 - partY1), and, xor); 23405b261ecSmrg } 23535c4bbdfSmrg fbFinishAccess(pDrawable); 23605b261ecSmrg} 237