fbgc.c revision 35c4bbdf
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
4135c4bbdfSmrgconst 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
7435c4bbdfSmrg    fbGetGCPrivate(pGC)->bpp = BitsPerPixel(pGC->depth);
7505b261ecSmrg    return TRUE;
7605b261ecSmrg}
7705b261ecSmrg
7805b261ecSmrg/*
7905b261ecSmrg * Pad pixmap to FB_UNIT bits wide
8005b261ecSmrg */
8105b261ecSmrgvoid
8235c4bbdfSmrgfbPadPixmap(PixmapPtr pPixmap)
8305b261ecSmrg{
8435c4bbdfSmrg    int width;
8535c4bbdfSmrg    FbBits *bits;
8635c4bbdfSmrg    FbBits b;
8735c4bbdfSmrg    FbBits mask;
8835c4bbdfSmrg    int height;
8935c4bbdfSmrg    int w;
9035c4bbdfSmrg    int stride;
9135c4bbdfSmrg    int bpp;
9235c4bbdfSmrg    _X_UNUSED int xOff, yOff;
9335c4bbdfSmrg
9435c4bbdfSmrg    fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
9505b261ecSmrg
9605b261ecSmrg    width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
9705b261ecSmrg    height = pPixmap->drawable.height;
9835c4bbdfSmrg    mask = FbBitsMask(0, width);
9935c4bbdfSmrg    while (height--) {
10035c4bbdfSmrg        b = READ(bits) & mask;
10135c4bbdfSmrg        w = width;
10235c4bbdfSmrg        while (w < FB_UNIT) {
10335c4bbdfSmrg            b = b | FbScrRight(b, w);
10435c4bbdfSmrg            w <<= 1;
10535c4bbdfSmrg        }
10635c4bbdfSmrg        WRITE(bits, b);
10735c4bbdfSmrg        bits += stride;
10805b261ecSmrg    }
10905b261ecSmrg
11035c4bbdfSmrg    fbFinishAccess(&pPixmap->drawable);
11105b261ecSmrg}
11205b261ecSmrg
11305b261ecSmrgvoid
11405b261ecSmrgfbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
11505b261ecSmrg{
11635c4bbdfSmrg    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
11735c4bbdfSmrg    FbBits mask;
11805b261ecSmrg
11905b261ecSmrg    /*
12005b261ecSmrg     * if the client clip is different or moved OR the subwindowMode has
12105b261ecSmrg     * changed OR the window's clip has changed since the last validation
12235c4bbdfSmrg     * we need to recompute the composite clip
12305b261ecSmrg     */
12405b261ecSmrg
12535c4bbdfSmrg    if ((changes &
12635c4bbdfSmrg         (GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode)) ||
12735c4bbdfSmrg        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
12835c4bbdfSmrg        ) {
12935c4bbdfSmrg        miComputeCompositeClip(pGC, pDrawable);
13005b261ecSmrg    }
13135c4bbdfSmrg
13235c4bbdfSmrg    if (pPriv->bpp != pDrawable->bitsPerPixel) {
13335c4bbdfSmrg        changes |= GCStipple | GCForeground | GCBackground | GCPlaneMask;
13435c4bbdfSmrg        pPriv->bpp = pDrawable->bitsPerPixel;
13505b261ecSmrg    }
13635c4bbdfSmrg    if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
13735c4bbdfSmrg        (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
13835c4bbdfSmrg        fbGetRotatedPixmap(pGC) = 0;
13905b261ecSmrg    }
14005b261ecSmrg
14135c4bbdfSmrg    if (pGC->fillStyle == FillTiled) {
14235c4bbdfSmrg        PixmapPtr pOldTile, pNewTile;
14335c4bbdfSmrg
14435c4bbdfSmrg        pOldTile = pGC->tile.pixmap;
14535c4bbdfSmrg        if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
14635c4bbdfSmrg            pNewTile = fbGetRotatedPixmap(pGC);
14735c4bbdfSmrg            if (!pNewTile ||
14835c4bbdfSmrg                pNewTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
14935c4bbdfSmrg                if (pNewTile)
15035c4bbdfSmrg                    (*pGC->pScreen->DestroyPixmap) (pNewTile);
15135c4bbdfSmrg                pNewTile =
15235c4bbdfSmrg                    fb24_32ReformatTile(pOldTile, pDrawable->bitsPerPixel);
15335c4bbdfSmrg            }
15435c4bbdfSmrg            if (pNewTile) {
15535c4bbdfSmrg                fbGetRotatedPixmap(pGC) = pOldTile;
15635c4bbdfSmrg                pGC->tile.pixmap = pNewTile;
15735c4bbdfSmrg                changes |= GCTile;
15835c4bbdfSmrg            }
15935c4bbdfSmrg        }
16005b261ecSmrg    }
16135c4bbdfSmrg    if (changes & GCTile) {
16235c4bbdfSmrg        if (!pGC->tileIsPixel &&
16335c4bbdfSmrg            FbEvenTile(pGC->tile.pixmap->drawable.width *
16435c4bbdfSmrg                       pDrawable->bitsPerPixel))
16535c4bbdfSmrg            fbPadPixmap(pGC->tile.pixmap);
16605b261ecSmrg    }
16735c4bbdfSmrg    if (changes & GCStipple) {
16835c4bbdfSmrg        if (pGC->stipple) {
16935c4bbdfSmrg            if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel <
17035c4bbdfSmrg                FB_UNIT)
17135c4bbdfSmrg                fbPadPixmap(pGC->stipple);
17235c4bbdfSmrg        }
17305b261ecSmrg    }
17405b261ecSmrg    /*
17505b261ecSmrg     * Recompute reduced rop values
17605b261ecSmrg     */
17735c4bbdfSmrg    if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
17835c4bbdfSmrg        int s;
17935c4bbdfSmrg        FbBits depthMask;
18035c4bbdfSmrg
18135c4bbdfSmrg        mask = FbFullMask(pDrawable->bitsPerPixel);
18235c4bbdfSmrg        depthMask = FbFullMask(pDrawable->depth);
18335c4bbdfSmrg
18435c4bbdfSmrg        pPriv->fg = pGC->fgPixel & mask;
18535c4bbdfSmrg        pPriv->bg = pGC->bgPixel & mask;
18635c4bbdfSmrg
18735c4bbdfSmrg        if ((pGC->planemask & depthMask) == depthMask)
18835c4bbdfSmrg            pPriv->pm = mask;
18935c4bbdfSmrg        else
19035c4bbdfSmrg            pPriv->pm = pGC->planemask & mask;
19135c4bbdfSmrg
19235c4bbdfSmrg        s = pDrawable->bitsPerPixel;
19335c4bbdfSmrg        while (s < FB_UNIT) {
19435c4bbdfSmrg            pPriv->fg |= pPriv->fg << s;
19535c4bbdfSmrg            pPriv->bg |= pPriv->bg << s;
19635c4bbdfSmrg            pPriv->pm |= pPriv->pm << s;
19735c4bbdfSmrg            s <<= 1;
19835c4bbdfSmrg        }
19935c4bbdfSmrg        pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
20035c4bbdfSmrg        pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
20135c4bbdfSmrg        pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
20235c4bbdfSmrg        pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
20305b261ecSmrg    }
20435c4bbdfSmrg    if (changes & GCDashList) {
20535c4bbdfSmrg        unsigned short n = pGC->numInDashList;
20635c4bbdfSmrg        unsigned char *dash = pGC->dash;
20735c4bbdfSmrg        unsigned int dashLength = 0;
20835c4bbdfSmrg
20935c4bbdfSmrg        while (n--)
21035c4bbdfSmrg            dashLength += (unsigned int) *dash++;
21135c4bbdfSmrg        pPriv->dashLength = dashLength;
21205b261ecSmrg    }
21305b261ecSmrg}
214