fbgc.c revision 05b261ec
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 <stdlib.h> 2805b261ecSmrg 2905b261ecSmrg#include "fb.h" 3005b261ecSmrg 3105b261ecSmrgconst GCFuncs fbGCFuncs = { 3205b261ecSmrg fbValidateGC, 3305b261ecSmrg miChangeGC, 3405b261ecSmrg miCopyGC, 3505b261ecSmrg miDestroyGC, 3605b261ecSmrg miChangeClip, 3705b261ecSmrg miDestroyClip, 3805b261ecSmrg miCopyClip, 3905b261ecSmrg}; 4005b261ecSmrg 4105b261ecSmrgconst GCOps fbGCOps = { 4205b261ecSmrg fbFillSpans, 4305b261ecSmrg fbSetSpans, 4405b261ecSmrg fbPutImage, 4505b261ecSmrg fbCopyArea, 4605b261ecSmrg fbCopyPlane, 4705b261ecSmrg fbPolyPoint, 4805b261ecSmrg fbPolyLine, 4905b261ecSmrg fbPolySegment, 5005b261ecSmrg fbPolyRectangle, 5105b261ecSmrg fbPolyArc, 5205b261ecSmrg miFillPolygon, 5305b261ecSmrg fbPolyFillRect, 5405b261ecSmrg fbPolyFillArc, 5505b261ecSmrg miPolyText8, 5605b261ecSmrg miPolyText16, 5705b261ecSmrg miImageText8, 5805b261ecSmrg miImageText16, 5905b261ecSmrg fbImageGlyphBlt, 6005b261ecSmrg fbPolyGlyphBlt, 6105b261ecSmrg fbPushPixels 6205b261ecSmrg}; 6305b261ecSmrg 6405b261ecSmrgBool 6505b261ecSmrgfbCreateGC(GCPtr pGC) 6605b261ecSmrg{ 6705b261ecSmrg pGC->clientClip = NULL; 6805b261ecSmrg pGC->clientClipType = CT_NONE; 6905b261ecSmrg 7005b261ecSmrg pGC->ops = (GCOps *) &fbGCOps; 7105b261ecSmrg pGC->funcs = (GCFuncs *) &fbGCFuncs; 7205b261ecSmrg 7305b261ecSmrg /* fb wants to translate before scan conversion */ 7405b261ecSmrg pGC->miTranslate = 1; 7505b261ecSmrg 7605b261ecSmrg fbGetRotatedPixmap(pGC) = 0; 7705b261ecSmrg fbGetExpose(pGC) = 1; 7805b261ecSmrg fbGetFreeCompClip(pGC) = 0; 7905b261ecSmrg fbGetCompositeClip(pGC) = 0; 8005b261ecSmrg fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth); 8105b261ecSmrg return TRUE; 8205b261ecSmrg} 8305b261ecSmrg 8405b261ecSmrg/* 8505b261ecSmrg * Pad pixmap to FB_UNIT bits wide 8605b261ecSmrg */ 8705b261ecSmrgvoid 8805b261ecSmrgfbPadPixmap (PixmapPtr pPixmap) 8905b261ecSmrg{ 9005b261ecSmrg int width; 9105b261ecSmrg FbBits *bits; 9205b261ecSmrg FbBits b; 9305b261ecSmrg FbBits mask; 9405b261ecSmrg int height; 9505b261ecSmrg int w; 9605b261ecSmrg int stride; 9705b261ecSmrg int bpp; 9805b261ecSmrg int xOff, yOff; 9905b261ecSmrg 10005b261ecSmrg fbGetDrawable (&pPixmap->drawable, bits, stride, bpp, xOff, yOff); 10105b261ecSmrg 10205b261ecSmrg width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; 10305b261ecSmrg height = pPixmap->drawable.height; 10405b261ecSmrg mask = FbBitsMask (0, width); 10505b261ecSmrg while (height--) 10605b261ecSmrg { 10705b261ecSmrg b = READ(bits) & mask; 10805b261ecSmrg w = width; 10905b261ecSmrg while (w < FB_UNIT) 11005b261ecSmrg { 11105b261ecSmrg b = b | FbScrRight(b, w); 11205b261ecSmrg w <<= 1; 11305b261ecSmrg } 11405b261ecSmrg WRITE(bits, b); 11505b261ecSmrg bits += stride; 11605b261ecSmrg } 11705b261ecSmrg 11805b261ecSmrg fbFinishAccess (&pPixmap->drawable); 11905b261ecSmrg} 12005b261ecSmrg 12105b261ecSmrg/* 12205b261ecSmrg * Verify that 'bits' repeats every 'len' bits 12305b261ecSmrg */ 12405b261ecSmrgstatic Bool 12505b261ecSmrgfbBitsRepeat (FbBits bits, int len, int width) 12605b261ecSmrg{ 12705b261ecSmrg FbBits mask = FbBitsMask(0, len); 12805b261ecSmrg FbBits orig = bits & mask; 12905b261ecSmrg int i; 13005b261ecSmrg 13105b261ecSmrg if (width > FB_UNIT) 13205b261ecSmrg width = FB_UNIT; 13305b261ecSmrg for (i = 0; i < width / len; i++) 13405b261ecSmrg { 13505b261ecSmrg if ((bits & mask) != orig) 13605b261ecSmrg return FALSE; 13705b261ecSmrg bits = FbScrLeft(bits,len); 13805b261ecSmrg } 13905b261ecSmrg return TRUE; 14005b261ecSmrg} 14105b261ecSmrg 14205b261ecSmrg/* 14305b261ecSmrg * Check whether an entire bitmap line is a repetition of 14405b261ecSmrg * the first 'len' bits 14505b261ecSmrg */ 14605b261ecSmrgstatic Bool 14705b261ecSmrgfbLineRepeat (FbBits *bits, int len, int width) 14805b261ecSmrg{ 14905b261ecSmrg FbBits first = bits[0]; 15005b261ecSmrg 15105b261ecSmrg if (!fbBitsRepeat (first, len, width)) 15205b261ecSmrg return FALSE; 15305b261ecSmrg width = (width + FB_UNIT-1) >> FB_SHIFT; 15405b261ecSmrg bits++; 15505b261ecSmrg while (--width) 15605b261ecSmrg if (READ(bits) != first) 15705b261ecSmrg return FALSE; 15805b261ecSmrg return TRUE; 15905b261ecSmrg} 16005b261ecSmrg 16105b261ecSmrg/* 16205b261ecSmrg * The even stipple code wants the first FB_UNIT/bpp bits on 16305b261ecSmrg * each scanline to represent the entire stipple 16405b261ecSmrg */ 16505b261ecSmrgstatic Bool 16605b261ecSmrgfbCanEvenStipple (PixmapPtr pStipple, int bpp) 16705b261ecSmrg{ 16805b261ecSmrg int len = FB_UNIT / bpp; 16905b261ecSmrg FbBits *bits; 17005b261ecSmrg int stride; 17105b261ecSmrg int stip_bpp; 17205b261ecSmrg int stipXoff, stipYoff; 17305b261ecSmrg int h; 17405b261ecSmrg 17505b261ecSmrg /* can't even stipple 24bpp drawables */ 17605b261ecSmrg if ((bpp & (bpp-1)) != 0) 17705b261ecSmrg return FALSE; 17805b261ecSmrg /* make sure the stipple width is a multiple of the even stipple width */ 17905b261ecSmrg if (pStipple->drawable.width % len != 0) 18005b261ecSmrg return FALSE; 18105b261ecSmrg fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff); 18205b261ecSmrg h = pStipple->drawable.height; 18305b261ecSmrg /* check to see that the stipple repeats horizontally */ 18405b261ecSmrg while (h--) 18505b261ecSmrg { 18605b261ecSmrg if (!fbLineRepeat (bits, len, pStipple->drawable.width)) { 18705b261ecSmrg fbFinishAccess (&pStipple->drawable); 18805b261ecSmrg return FALSE; 18905b261ecSmrg } 19005b261ecSmrg bits += stride; 19105b261ecSmrg } 19205b261ecSmrg fbFinishAccess (&pStipple->drawable); 19305b261ecSmrg return TRUE; 19405b261ecSmrg} 19505b261ecSmrg 19605b261ecSmrgvoid 19705b261ecSmrgfbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 19805b261ecSmrg{ 19905b261ecSmrg FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 20005b261ecSmrg FbBits mask; 20105b261ecSmrg 20205b261ecSmrg pGC->lastWinOrg.x = pDrawable->x; 20305b261ecSmrg pGC->lastWinOrg.y = pDrawable->y; 20405b261ecSmrg 20505b261ecSmrg /* 20605b261ecSmrg * if the client clip is different or moved OR the subwindowMode has 20705b261ecSmrg * changed OR the window's clip has changed since the last validation 20805b261ecSmrg * we need to recompute the composite clip 20905b261ecSmrg */ 21005b261ecSmrg 21105b261ecSmrg if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || 21205b261ecSmrg (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) 21305b261ecSmrg ) 21405b261ecSmrg { 21505b261ecSmrg miComputeCompositeClip (pGC, pDrawable); 21605b261ecSmrg pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1; 21705b261ecSmrg } 21805b261ecSmrg 21905b261ecSmrg#ifdef FB_24_32BIT 22005b261ecSmrg if (pPriv->bpp != pDrawable->bitsPerPixel) 22105b261ecSmrg { 22205b261ecSmrg changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask; 22305b261ecSmrg pPriv->bpp = pDrawable->bitsPerPixel; 22405b261ecSmrg } 22505b261ecSmrg if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) 22605b261ecSmrg { 22705b261ecSmrg (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 22805b261ecSmrg fbGetRotatedPixmap(pGC) = 0; 22905b261ecSmrg } 23005b261ecSmrg 23105b261ecSmrg if (pGC->fillStyle == FillTiled) 23205b261ecSmrg { 23305b261ecSmrg PixmapPtr pOldTile, pNewTile; 23405b261ecSmrg 23505b261ecSmrg pOldTile = pGC->tile.pixmap; 23605b261ecSmrg if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 23705b261ecSmrg { 23805b261ecSmrg pNewTile = fbGetRotatedPixmap(pGC); 23905b261ecSmrg if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 24005b261ecSmrg { 24105b261ecSmrg if (pNewTile) 24205b261ecSmrg (*pGC->pScreen->DestroyPixmap) (pNewTile); 24305b261ecSmrg pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel); 24405b261ecSmrg } 24505b261ecSmrg if (pNewTile) 24605b261ecSmrg { 24705b261ecSmrg fbGetRotatedPixmap(pGC) = pOldTile; 24805b261ecSmrg pGC->tile.pixmap = pNewTile; 24905b261ecSmrg changes |= GCTile; 25005b261ecSmrg } 25105b261ecSmrg } 25205b261ecSmrg } 25305b261ecSmrg#endif 25405b261ecSmrg if (changes & GCTile) 25505b261ecSmrg { 25605b261ecSmrg if (!pGC->tileIsPixel && 25705b261ecSmrg FbEvenTile (pGC->tile.pixmap->drawable.width * 25805b261ecSmrg pDrawable->bitsPerPixel)) 25905b261ecSmrg fbPadPixmap (pGC->tile.pixmap); 26005b261ecSmrg } 26105b261ecSmrg if (changes & GCStipple) 26205b261ecSmrg { 26305b261ecSmrg pPriv->evenStipple = FALSE; 26405b261ecSmrg 26505b261ecSmrg if (pGC->stipple) { 26605b261ecSmrg 26705b261ecSmrg /* can we do an even stipple ?? */ 26805b261ecSmrg if (FbEvenStip (pGC->stipple->drawable.width, 26905b261ecSmrg pDrawable->bitsPerPixel) && 27005b261ecSmrg (fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel))) 27105b261ecSmrg pPriv->evenStipple = TRUE; 27205b261ecSmrg 27305b261ecSmrg if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT) 27405b261ecSmrg fbPadPixmap (pGC->stipple); 27505b261ecSmrg } 27605b261ecSmrg } 27705b261ecSmrg /* 27805b261ecSmrg * Recompute reduced rop values 27905b261ecSmrg */ 28005b261ecSmrg if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction)) 28105b261ecSmrg { 28205b261ecSmrg int s; 28305b261ecSmrg FbBits depthMask; 28405b261ecSmrg 28505b261ecSmrg mask = FbFullMask(pDrawable->bitsPerPixel); 28605b261ecSmrg depthMask = FbFullMask(pDrawable->depth); 28705b261ecSmrg 28805b261ecSmrg pPriv->fg = pGC->fgPixel & mask; 28905b261ecSmrg pPriv->bg = pGC->bgPixel & mask; 29005b261ecSmrg 29105b261ecSmrg if ((pGC->planemask & depthMask) == depthMask) 29205b261ecSmrg pPriv->pm = mask; 29305b261ecSmrg else 29405b261ecSmrg pPriv->pm = pGC->planemask & mask; 29505b261ecSmrg 29605b261ecSmrg s = pDrawable->bitsPerPixel; 29705b261ecSmrg while (s < FB_UNIT) 29805b261ecSmrg { 29905b261ecSmrg pPriv->fg |= pPriv->fg << s; 30005b261ecSmrg pPriv->bg |= pPriv->bg << s; 30105b261ecSmrg pPriv->pm |= pPriv->pm << s; 30205b261ecSmrg s <<= 1; 30305b261ecSmrg } 30405b261ecSmrg pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm); 30505b261ecSmrg pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm); 30605b261ecSmrg pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm); 30705b261ecSmrg pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm); 30805b261ecSmrg } 30905b261ecSmrg if (changes & GCDashList) 31005b261ecSmrg { 31105b261ecSmrg unsigned short n = pGC->numInDashList; 31205b261ecSmrg unsigned char *dash = pGC->dash; 31305b261ecSmrg unsigned int dashLength = 0; 31405b261ecSmrg 31505b261ecSmrg while (n--) 31605b261ecSmrg dashLength += (unsigned int ) *dash++; 31705b261ecSmrg pPriv->dashLength = dashLength; 31805b261ecSmrg } 31905b261ecSmrg} 320