~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to fb/fbgc.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Id: fbgc.c,v 1.1 1999/11/02 03:54:45 keithp Exp $
 
3
 *
 
4
 * Copyright Ā© 1998 Keith Packard
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
/* $XdotOrg: xserver/xorg/fb/fbgc.c,v 1.6 2006/01/18 06:49:17 airlied Exp $ */
 
25
/* $XFree86: xc/programs/Xserver/fb/fbgc.c,v 1.14 2003/12/18 15:22:32 alanh Exp $ */
 
26
 
 
27
#ifdef HAVE_DIX_CONFIG_H
 
28
#include <dix-config.h>
 
29
#endif
 
30
 
 
31
#include "fb.h"
 
32
#ifdef IN_MODULE
 
33
#include "xf86_ansic.h"
 
34
#endif
 
35
 
 
36
const GCFuncs fbGCFuncs = {
 
37
    fbValidateGC,
 
38
    miChangeGC,
 
39
    miCopyGC,
 
40
    miDestroyGC,
 
41
    miChangeClip,
 
42
    miDestroyClip,
 
43
    miCopyClip,
 
44
};
 
45
 
 
46
const GCOps     fbGCOps = {
 
47
    fbFillSpans,
 
48
    fbSetSpans,
 
49
    fbPutImage,
 
50
    fbCopyArea,
 
51
    fbCopyPlane,
 
52
    fbPolyPoint,
 
53
    fbPolyLine,
 
54
    fbPolySegment,
 
55
    fbPolyRectangle,
 
56
    fbPolyArc,
 
57
    miFillPolygon,
 
58
    fbPolyFillRect,
 
59
    fbPolyFillArc,
 
60
    miPolyText8,
 
61
    miPolyText16,
 
62
    miImageText8,
 
63
    miImageText16,
 
64
    fbImageGlyphBlt,
 
65
    fbPolyGlyphBlt,
 
66
    fbPushPixels
 
67
#ifdef NEED_LINEHELPER
 
68
    ,NULL
 
69
#endif
 
70
};
 
71
 
 
72
Bool
 
73
fbCreateGC(GCPtr pGC)
 
74
{
 
75
    pGC->clientClip = NULL;
 
76
    pGC->clientClipType = CT_NONE;
 
77
 
 
78
    pGC->ops = (GCOps *) &fbGCOps;
 
79
    pGC->funcs = (GCFuncs *) &fbGCFuncs;
 
80
 
 
81
    /* fb wants to translate before scan conversion */
 
82
    pGC->miTranslate = 1;
 
83
 
 
84
    fbGetRotatedPixmap(pGC) = 0;
 
85
    fbGetExpose(pGC) = 1;
 
86
    fbGetFreeCompClip(pGC) = 0;
 
87
    fbGetCompositeClip(pGC) = 0;
 
88
    fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth);
 
89
    return TRUE;
 
90
}
 
91
 
 
92
/*
 
93
 * Pad pixmap to FB_UNIT bits wide
 
94
 */
 
95
void
 
96
fbPadPixmap (PixmapPtr pPixmap)
 
97
{
 
98
    int     width;
 
99
    FbBits  *bits;
 
100
    FbBits  b;
 
101
    FbBits  mask;
 
102
    int     height;
 
103
    int     w;
 
104
    int     stride;
 
105
    int     bpp;
 
106
    int     xOff, yOff;
 
107
 
 
108
    fbGetDrawable (&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
 
109
 
 
110
    width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
 
111
    height = pPixmap->drawable.height;
 
112
    mask = FbBitsMask (0, width);
 
113
    while (height--)
 
114
    {
 
115
        b = *bits & mask;
 
116
        w = width;
 
117
        while (w < FB_UNIT)
 
118
        {
 
119
            b = b | FbScrRight(b, w);
 
120
            w <<= 1;
 
121
        }
 
122
        *bits = b;
 
123
        bits += stride;
 
124
    }
 
125
}
 
126
 
 
127
/*
 
128
 * Verify that 'bits' repeats every 'len' bits
 
129
 */
 
130
static Bool
 
131
fbBitsRepeat (FbBits bits, int len, int width)
 
132
{
 
133
    FbBits  mask = FbBitsMask(0, len);
 
134
    FbBits  orig = bits & mask;
 
135
    int     i;
 
136
    
 
137
    if (width > FB_UNIT)
 
138
        width = FB_UNIT;
 
139
    for (i = 0; i < width / len; i++)
 
140
    {
 
141
        if ((bits & mask) != orig)
 
142
            return FALSE;
 
143
        bits = FbScrLeft(bits,len);
 
144
    }
 
145
    return TRUE;
 
146
}
 
147
 
 
148
/*
 
149
 * Check whether an entire bitmap line is a repetition of
 
150
 * the first 'len' bits
 
151
 */
 
152
static Bool
 
153
fbLineRepeat (FbBits *bits, int len, int width)
 
154
{
 
155
    FbBits  first = bits[0];
 
156
    
 
157
    if (!fbBitsRepeat (first, len, width))
 
158
        return FALSE;
 
159
    width = (width + FB_UNIT-1) >> FB_SHIFT;
 
160
    bits++;
 
161
    while (--width)
 
162
        if (*bits != first)
 
163
            return FALSE;
 
164
    return TRUE;
 
165
}
 
166
 
 
167
/*
 
168
 * The even stipple code wants the first FB_UNIT/bpp bits on
 
169
 * each scanline to represent the entire stipple
 
170
 */
 
171
static Bool
 
172
fbCanEvenStipple (PixmapPtr pStipple, int bpp)
 
173
{
 
174
    int     len = FB_UNIT / bpp;
 
175
    FbBits  *bits;
 
176
    int     stride;
 
177
    int     stip_bpp;
 
178
    int     stipXoff, stipYoff;
 
179
    int     h;
 
180
 
 
181
    /* can't even stipple 24bpp drawables */
 
182
    if ((bpp & (bpp-1)) != 0)
 
183
        return FALSE;
 
184
    /* make sure the stipple width is a multiple of the even stipple width */
 
185
    if (pStipple->drawable.width % len != 0)
 
186
        return FALSE;
 
187
    fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff);
 
188
    h = pStipple->drawable.height;
 
189
    /* check to see that the stipple repeats horizontally */
 
190
    while (h--)
 
191
    {
 
192
        if (!fbLineRepeat (bits, len, pStipple->drawable.width))
 
193
            return FALSE;
 
194
        bits += stride;
 
195
    }
 
196
    return TRUE;
 
197
}
 
198
 
 
199
void
 
200
fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 
201
{
 
202
    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
 
203
    FbBits      mask;
 
204
 
 
205
    pGC->lastWinOrg.x = pDrawable->x;
 
206
    pGC->lastWinOrg.y = pDrawable->y;
 
207
 
 
208
    /*
 
209
     * if the client clip is different or moved OR the subwindowMode has
 
210
     * changed OR the window's clip has changed since the last validation
 
211
     * we need to recompute the composite clip 
 
212
     */
 
213
 
 
214
    if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
 
215
        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
 
216
        )
 
217
    {
 
218
        miComputeCompositeClip (pGC, pDrawable);
 
219
        pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1;
 
220
    }
 
221
    
 
222
#ifdef FB_24_32BIT    
 
223
    if (pPriv->bpp != pDrawable->bitsPerPixel)
 
224
    {
 
225
        changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask;
 
226
        pPriv->bpp = pDrawable->bitsPerPixel;
 
227
    }
 
228
    if ((changes & GCTile) && fbGetRotatedPixmap(pGC))
 
229
    {
 
230
        (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
 
231
        fbGetRotatedPixmap(pGC) = 0;
 
232
    }
 
233
        
 
234
    if (pGC->fillStyle == FillTiled)
 
235
    {
 
236
        PixmapPtr       pOldTile, pNewTile;
 
237
 
 
238
        pOldTile = pGC->tile.pixmap;
 
239
        if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
 
240
        {
 
241
            pNewTile = fbGetRotatedPixmap(pGC);
 
242
            if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
 
243
            {
 
244
                if (pNewTile)
 
245
                    (*pGC->pScreen->DestroyPixmap) (pNewTile);
 
246
                pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel);
 
247
            }
 
248
            if (pNewTile)
 
249
            {
 
250
                fbGetRotatedPixmap(pGC) = pOldTile;
 
251
                pGC->tile.pixmap = pNewTile;
 
252
                changes |= GCTile;
 
253
            }
 
254
        }
 
255
    }
 
256
#endif
 
257
    if (changes & GCTile)
 
258
    {
 
259
        if (!pGC->tileIsPixel && 
 
260
            FbEvenTile (pGC->tile.pixmap->drawable.width *
 
261
                        pDrawable->bitsPerPixel))
 
262
            fbPadPixmap (pGC->tile.pixmap);
 
263
    }
 
264
    if (changes & GCStipple)
 
265
    {
 
266
        pPriv->evenStipple = FALSE;
 
267
 
 
268
        if (pGC->stipple) {
 
269
 
 
270
            /* can we do an even stipple ?? */
 
271
            if (FbEvenStip (pGC->stipple->drawable.width,
 
272
                                                pDrawable->bitsPerPixel) &&
 
273
               (fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel)))
 
274
                pPriv->evenStipple = TRUE;
 
275
 
 
276
            if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT)
 
277
                fbPadPixmap (pGC->stipple);
 
278
        }
 
279
    }
 
280
    /*
 
281
     * Recompute reduced rop values
 
282
     */
 
283
    if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction))
 
284
    {
 
285
        int     s;
 
286
        FbBits  depthMask;
 
287
        
 
288
        mask = FbFullMask(pDrawable->bitsPerPixel);
 
289
        depthMask = FbFullMask(pDrawable->depth);
 
290
        
 
291
        pPriv->fg = pGC->fgPixel & mask;
 
292
        pPriv->bg = pGC->bgPixel & mask;
 
293
        
 
294
        if ((pGC->planemask & depthMask) == depthMask)
 
295
            pPriv->pm = mask;
 
296
        else
 
297
            pPriv->pm = pGC->planemask & mask;    
 
298
        
 
299
        s = pDrawable->bitsPerPixel;
 
300
        while (s < FB_UNIT)
 
301
        {
 
302
            pPriv->fg |= pPriv->fg << s;
 
303
            pPriv->bg |= pPriv->bg << s;
 
304
            pPriv->pm |= pPriv->pm << s;
 
305
            s <<= 1;
 
306
        }
 
307
        pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
 
308
        pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
 
309
        pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
 
310
        pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
 
311
    }
 
312
    if (changes & GCDashList)
 
313
    {
 
314
        unsigned short  n = pGC->numInDashList;
 
315
        unsigned char   *dash = pGC->dash;
 
316
        unsigned int    dashLength = 0;
 
317
 
 
318
        while (n--)
 
319
            dashLength += (unsigned int ) *dash++;
 
320
        pPriv->dashLength = dashLength;
 
321
    }
 
322
}