First import
[xorg_rtime.git] / xorg-server-1.4 / fb / fbgc.c
blobfda391b14b644271037d60de0d64a74d20dd5b2c
1 /*
2 * Copyright © 1998 Keith Packard
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.
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include <stdlib.h>
29 #include "fb.h"
31 const GCFuncs fbGCFuncs = {
32 fbValidateGC,
33 miChangeGC,
34 miCopyGC,
35 miDestroyGC,
36 miChangeClip,
37 miDestroyClip,
38 miCopyClip,
41 const 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
64 Bool
65 fbCreateGC(GCPtr pGC)
67 pGC->clientClip = NULL;
68 pGC->clientClipType = CT_NONE;
70 pGC->ops = (GCOps *) &fbGCOps;
71 pGC->funcs = (GCFuncs *) &fbGCFuncs;
73 /* fb wants to translate before scan conversion */
74 pGC->miTranslate = 1;
76 fbGetRotatedPixmap(pGC) = 0;
77 fbGetExpose(pGC) = 1;
78 fbGetFreeCompClip(pGC) = 0;
79 fbGetCompositeClip(pGC) = 0;
80 fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth);
81 return TRUE;
85 * Pad pixmap to FB_UNIT bits wide
87 void
88 fbPadPixmap (PixmapPtr pPixmap)
90 int width;
91 FbBits *bits;
92 FbBits b;
93 FbBits mask;
94 int height;
95 int w;
96 int stride;
97 int bpp;
98 int xOff, yOff;
100 fbGetDrawable (&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
102 width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
103 height = pPixmap->drawable.height;
104 mask = FbBitsMask (0, width);
105 while (height--)
107 b = READ(bits) & mask;
108 w = width;
109 while (w < FB_UNIT)
111 b = b | FbScrRight(b, w);
112 w <<= 1;
114 WRITE(bits, b);
115 bits += stride;
118 fbFinishAccess (&pPixmap->drawable);
122 * Verify that 'bits' repeats every 'len' bits
124 static Bool
125 fbBitsRepeat (FbBits bits, int len, int width)
127 FbBits mask = FbBitsMask(0, len);
128 FbBits orig = bits & mask;
129 int i;
131 if (width > FB_UNIT)
132 width = FB_UNIT;
133 for (i = 0; i < width / len; i++)
135 if ((bits & mask) != orig)
136 return FALSE;
137 bits = FbScrLeft(bits,len);
139 return TRUE;
143 * Check whether an entire bitmap line is a repetition of
144 * the first 'len' bits
146 static Bool
147 fbLineRepeat (FbBits *bits, int len, int width)
149 FbBits first = bits[0];
151 if (!fbBitsRepeat (first, len, width))
152 return FALSE;
153 width = (width + FB_UNIT-1) >> FB_SHIFT;
154 bits++;
155 while (--width)
156 if (READ(bits) != first)
157 return FALSE;
158 return TRUE;
162 * The even stipple code wants the first FB_UNIT/bpp bits on
163 * each scanline to represent the entire stipple
165 static Bool
166 fbCanEvenStipple (PixmapPtr pStipple, int bpp)
168 int len = FB_UNIT / bpp;
169 FbBits *bits;
170 int stride;
171 int stip_bpp;
172 int stipXoff, stipYoff;
173 int h;
175 /* can't even stipple 24bpp drawables */
176 if ((bpp & (bpp-1)) != 0)
177 return FALSE;
178 /* make sure the stipple width is a multiple of the even stipple width */
179 if (pStipple->drawable.width % len != 0)
180 return FALSE;
181 fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff);
182 h = pStipple->drawable.height;
183 /* check to see that the stipple repeats horizontally */
184 while (h--)
186 if (!fbLineRepeat (bits, len, pStipple->drawable.width)) {
187 fbFinishAccess (&pStipple->drawable);
188 return FALSE;
190 bits += stride;
192 fbFinishAccess (&pStipple->drawable);
193 return TRUE;
196 void
197 fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
199 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
200 FbBits mask;
202 pGC->lastWinOrg.x = pDrawable->x;
203 pGC->lastWinOrg.y = pDrawable->y;
206 * if the client clip is different or moved OR the subwindowMode has
207 * changed OR the window's clip has changed since the last validation
208 * we need to recompute the composite clip
211 if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
212 (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
215 miComputeCompositeClip (pGC, pDrawable);
216 pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1;
219 #ifdef FB_24_32BIT
220 if (pPriv->bpp != pDrawable->bitsPerPixel)
222 changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask;
223 pPriv->bpp = pDrawable->bitsPerPixel;
225 if ((changes & GCTile) && fbGetRotatedPixmap(pGC))
227 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
228 fbGetRotatedPixmap(pGC) = 0;
231 if (pGC->fillStyle == FillTiled)
233 PixmapPtr pOldTile, pNewTile;
235 pOldTile = pGC->tile.pixmap;
236 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
238 pNewTile = fbGetRotatedPixmap(pGC);
239 if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
241 if (pNewTile)
242 (*pGC->pScreen->DestroyPixmap) (pNewTile);
243 pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel);
245 if (pNewTile)
247 fbGetRotatedPixmap(pGC) = pOldTile;
248 pGC->tile.pixmap = pNewTile;
249 changes |= GCTile;
253 #endif
254 if (changes & GCTile)
256 if (!pGC->tileIsPixel &&
257 FbEvenTile (pGC->tile.pixmap->drawable.width *
258 pDrawable->bitsPerPixel))
259 fbPadPixmap (pGC->tile.pixmap);
261 if (changes & GCStipple)
263 pPriv->evenStipple = FALSE;
265 if (pGC->stipple) {
267 /* can we do an even stipple ?? */
268 if (FbEvenStip (pGC->stipple->drawable.width,
269 pDrawable->bitsPerPixel) &&
270 (fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel)))
271 pPriv->evenStipple = TRUE;
273 if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT)
274 fbPadPixmap (pGC->stipple);
278 * Recompute reduced rop values
280 if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction))
282 int s;
283 FbBits depthMask;
285 mask = FbFullMask(pDrawable->bitsPerPixel);
286 depthMask = FbFullMask(pDrawable->depth);
288 pPriv->fg = pGC->fgPixel & mask;
289 pPriv->bg = pGC->bgPixel & mask;
291 if ((pGC->planemask & depthMask) == depthMask)
292 pPriv->pm = mask;
293 else
294 pPriv->pm = pGC->planemask & mask;
296 s = pDrawable->bitsPerPixel;
297 while (s < FB_UNIT)
299 pPriv->fg |= pPriv->fg << s;
300 pPriv->bg |= pPriv->bg << s;
301 pPriv->pm |= pPriv->pm << s;
302 s <<= 1;
304 pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
305 pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
306 pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
307 pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
309 if (changes & GCDashList)
311 unsigned short n = pGC->numInDashList;
312 unsigned char *dash = pGC->dash;
313 unsigned int dashLength = 0;
315 while (n--)
316 dashLength += (unsigned int ) *dash++;
317 pPriv->dashLength = dashLength;