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