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