1/*
2 * Copyright © 1998 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include <stdlib.h>
28
29#include "fb.h"
30
31const GCFuncs fbGCFuncs = {
32    fbValidateGC,
33    miChangeGC,
34    miCopyGC,
35    miDestroyGC,
36    miChangeClip,
37    miDestroyClip,
38    miCopyClip,
39};
40
41const GCOps fbGCOps = {
42    fbFillSpans,
43    fbSetSpans,
44    fbPutImage,
45    fbCopyArea,
46    fbCopyPlane,
47    fbPolyPoint,
48    fbPolyLine,
49    fbPolySegment,
50    fbPolyRectangle,
51    fbPolyArc,
52    miFillPolygon,
53    fbPolyFillRect,
54    fbPolyFillArc,
55    miPolyText8,
56    miPolyText16,
57    miImageText8,
58    miImageText16,
59    fbImageGlyphBlt,
60    fbPolyGlyphBlt,
61    fbPushPixels
62};
63
64Bool
65fbCreateGC(GCPtr pGC)
66{
67    pGC->ops = (GCOps *) &fbGCOps;
68    pGC->funcs = (GCFuncs *) &fbGCFuncs;
69
70    /* fb wants to translate before scan conversion */
71    pGC->miTranslate = 1;
72    pGC->fExpose = 1;
73
74    return TRUE;
75}
76
77/*
78 * Pad pixmap to FB_UNIT bits wide
79 */
80void
81fbPadPixmap(PixmapPtr pPixmap)
82{
83    int width;
84    FbBits *bits;
85    FbBits b;
86    FbBits mask;
87    int height;
88    int w;
89    int stride;
90    int bpp;
91    _X_UNUSED int xOff, yOff;
92
93    fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
94
95    width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
96    height = pPixmap->drawable.height;
97    mask = FbBitsMask(0, width);
98    while (height--) {
99        b = READ(bits) & mask;
100        w = width;
101        while (w < FB_UNIT) {
102            b = b | FbScrRight(b, w);
103            w <<= 1;
104        }
105        WRITE(bits, b);
106        bits += stride;
107    }
108
109    fbFinishAccess(&pPixmap->drawable);
110}
111
112void
113fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
114{
115    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
116    FbBits mask;
117
118    /*
119     * if the client clip is different or moved OR the subwindowMode has
120     * changed OR the window's clip has changed since the last validation
121     * we need to recompute the composite clip
122     */
123
124    if ((changes &
125         (GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode)) ||
126        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
127        ) {
128        miComputeCompositeClip(pGC, pDrawable);
129    }
130
131    if (changes & GCTile) {
132        if (!pGC->tileIsPixel &&
133            FbEvenTile(pGC->tile.pixmap->drawable.width *
134                       pDrawable->bitsPerPixel))
135            fbPadPixmap(pGC->tile.pixmap);
136    }
137    if (changes & GCStipple) {
138        if (pGC->stipple) {
139            if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel <
140                FB_UNIT)
141                fbPadPixmap(pGC->stipple);
142        }
143    }
144    /*
145     * Recompute reduced rop values
146     */
147    if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
148        int s;
149        FbBits depthMask;
150
151        mask = FbFullMask(pDrawable->bitsPerPixel);
152        depthMask = FbFullMask(pDrawable->depth);
153
154        pPriv->fg = pGC->fgPixel & mask;
155        pPriv->bg = pGC->bgPixel & mask;
156
157        if ((pGC->planemask & depthMask) == depthMask)
158            pPriv->pm = mask;
159        else
160            pPriv->pm = pGC->planemask & mask;
161
162        s = pDrawable->bitsPerPixel;
163        while (s < FB_UNIT) {
164            pPriv->fg |= pPriv->fg << s;
165            pPriv->bg |= pPriv->bg << s;
166            pPriv->pm |= pPriv->pm << s;
167            s <<= 1;
168        }
169        pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
170        pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
171        pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
172        pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
173    }
174    if (changes & GCDashList) {
175        unsigned short n = pGC->numInDashList;
176        unsigned char *dash = pGC->dash;
177        unsigned int dashLength = 0;
178
179        while (n--)
180            dashLength += (unsigned int) *dash++;
181        pPriv->dashLength = dashLength;
182    }
183}
184