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
7405b261ecSmrg    return TRUE;
7505b261ecSmrg}
7605b261ecSmrg
7705b261ecSmrg/*
7805b261ecSmrg * Pad pixmap to FB_UNIT bits wide
7905b261ecSmrg */
8005b261ecSmrgvoid
8135c4bbdfSmrgfbPadPixmap(PixmapPtr pPixmap)
8205b261ecSmrg{
8335c4bbdfSmrg    int width;
8435c4bbdfSmrg    FbBits *bits;
8535c4bbdfSmrg    FbBits b;
8635c4bbdfSmrg    FbBits mask;
8735c4bbdfSmrg    int height;
8835c4bbdfSmrg    int w;
8935c4bbdfSmrg    int stride;
9035c4bbdfSmrg    int bpp;
9135c4bbdfSmrg    _X_UNUSED int xOff, yOff;
9235c4bbdfSmrg
9335c4bbdfSmrg    fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
9405b261ecSmrg
9505b261ecSmrg    width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
9605b261ecSmrg    height = pPixmap->drawable.height;
9735c4bbdfSmrg    mask = FbBitsMask(0, width);
9835c4bbdfSmrg    while (height--) {
9935c4bbdfSmrg        b = READ(bits) & mask;
10035c4bbdfSmrg        w = width;
10135c4bbdfSmrg        while (w < FB_UNIT) {
10235c4bbdfSmrg            b = b | FbScrRight(b, w);
10335c4bbdfSmrg            w <<= 1;
10435c4bbdfSmrg        }
10535c4bbdfSmrg        WRITE(bits, b);
10635c4bbdfSmrg        bits += stride;
10705b261ecSmrg    }
10805b261ecSmrg
10935c4bbdfSmrg    fbFinishAccess(&pPixmap->drawable);
11005b261ecSmrg}
11105b261ecSmrg
11205b261ecSmrgvoid
11305b261ecSmrgfbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
11405b261ecSmrg{
11535c4bbdfSmrg    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
11635c4bbdfSmrg    FbBits mask;
11705b261ecSmrg
11805b261ecSmrg    /*
11905b261ecSmrg     * if the client clip is different or moved OR the subwindowMode has
12005b261ecSmrg     * changed OR the window's clip has changed since the last validation
12135c4bbdfSmrg     * we need to recompute the composite clip
12205b261ecSmrg     */
12305b261ecSmrg
12435c4bbdfSmrg    if ((changes &
12535c4bbdfSmrg         (GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode)) ||
12635c4bbdfSmrg        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
12735c4bbdfSmrg        ) {
12835c4bbdfSmrg        miComputeCompositeClip(pGC, pDrawable);
12905b261ecSmrg    }
13035c4bbdfSmrg
13135c4bbdfSmrg    if (changes & GCTile) {
13235c4bbdfSmrg        if (!pGC->tileIsPixel &&
13335c4bbdfSmrg            FbEvenTile(pGC->tile.pixmap->drawable.width *
13435c4bbdfSmrg                       pDrawable->bitsPerPixel))
13535c4bbdfSmrg            fbPadPixmap(pGC->tile.pixmap);
13605b261ecSmrg    }
13735c4bbdfSmrg    if (changes & GCStipple) {
13835c4bbdfSmrg        if (pGC->stipple) {
13935c4bbdfSmrg            if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel <
14035c4bbdfSmrg                FB_UNIT)
14135c4bbdfSmrg                fbPadPixmap(pGC->stipple);
14235c4bbdfSmrg        }
14305b261ecSmrg    }
14405b261ecSmrg    /*
14505b261ecSmrg     * Recompute reduced rop values
14605b261ecSmrg     */
14735c4bbdfSmrg    if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
14835c4bbdfSmrg        int s;
14935c4bbdfSmrg        FbBits depthMask;
15035c4bbdfSmrg
15135c4bbdfSmrg        mask = FbFullMask(pDrawable->bitsPerPixel);
15235c4bbdfSmrg        depthMask = FbFullMask(pDrawable->depth);
15335c4bbdfSmrg
15435c4bbdfSmrg        pPriv->fg = pGC->fgPixel & mask;
15535c4bbdfSmrg        pPriv->bg = pGC->bgPixel & mask;
15635c4bbdfSmrg
15735c4bbdfSmrg        if ((pGC->planemask & depthMask) == depthMask)
15835c4bbdfSmrg            pPriv->pm = mask;
15935c4bbdfSmrg        else
16035c4bbdfSmrg            pPriv->pm = pGC->planemask & mask;
16135c4bbdfSmrg
16235c4bbdfSmrg        s = pDrawable->bitsPerPixel;
16335c4bbdfSmrg        while (s < FB_UNIT) {
16435c4bbdfSmrg            pPriv->fg |= pPriv->fg << s;
16535c4bbdfSmrg            pPriv->bg |= pPriv->bg << s;
16635c4bbdfSmrg            pPriv->pm |= pPriv->pm << s;
16735c4bbdfSmrg            s <<= 1;
16835c4bbdfSmrg        }
16935c4bbdfSmrg        pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
17035c4bbdfSmrg        pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
17135c4bbdfSmrg        pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
17235c4bbdfSmrg        pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
17305b261ecSmrg    }
17435c4bbdfSmrg    if (changes & GCDashList) {
17535c4bbdfSmrg        unsigned short n = pGC->numInDashList;
17635c4bbdfSmrg        unsigned char *dash = pGC->dash;
17735c4bbdfSmrg        unsigned int dashLength = 0;
17835c4bbdfSmrg
17935c4bbdfSmrg        while (n--)
18035c4bbdfSmrg            dashLength += (unsigned int) *dash++;
18135c4bbdfSmrg        pPriv->dashLength = dashLength;
18205b261ecSmrg    }
18305b261ecSmrg}
184