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>
31 const GCFuncs fbGCFuncs
= {
41 const GCOps fbGCOps
= {
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 */
76 fbGetRotatedPixmap(pGC
) = 0;
78 fbGetFreeCompClip(pGC
) = 0;
79 fbGetCompositeClip(pGC
) = 0;
80 fbGetGCPrivate(pGC
)->bpp
= BitsPerPixel (pGC
->depth
);
85 * Pad pixmap to FB_UNIT bits wide
88 fbPadPixmap (PixmapPtr pPixmap
)
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
);
107 b
= READ(bits
) & mask
;
111 b
= b
| FbScrRight(b
, w
);
118 fbFinishAccess (&pPixmap
->drawable
);
122 * Verify that 'bits' repeats every 'len' bits
125 fbBitsRepeat (FbBits bits
, int len
, int width
)
127 FbBits mask
= FbBitsMask(0, len
);
128 FbBits orig
= bits
& mask
;
133 for (i
= 0; i
< width
/ len
; i
++)
135 if ((bits
& mask
) != orig
)
137 bits
= FbScrLeft(bits
,len
);
143 * Check whether an entire bitmap line is a repetition of
144 * the first 'len' bits
147 fbLineRepeat (FbBits
*bits
, int len
, int width
)
149 FbBits first
= bits
[0];
151 if (!fbBitsRepeat (first
, len
, width
))
153 width
= (width
+ FB_UNIT
-1) >> FB_SHIFT
;
156 if (READ(bits
) != first
)
162 * The even stipple code wants the first FB_UNIT/bpp bits on
163 * each scanline to represent the entire stipple
166 fbCanEvenStipple (PixmapPtr pStipple
, int bpp
)
168 int len
= FB_UNIT
/ bpp
;
172 int stipXoff
, stipYoff
;
175 /* can't even stipple 24bpp drawables */
176 if ((bpp
& (bpp
-1)) != 0)
178 /* make sure the stipple width is a multiple of the even stipple width */
179 if (pStipple
->drawable
.width
% len
!= 0)
181 fbGetDrawable (&pStipple
->drawable
, bits
, stride
, stip_bpp
, stipXoff
, stipYoff
);
182 h
= pStipple
->drawable
.height
;
183 /* check to see that the stipple repeats horizontally */
186 if (!fbLineRepeat (bits
, len
, pStipple
->drawable
.width
)) {
187 fbFinishAccess (&pStipple
->drawable
);
192 fbFinishAccess (&pStipple
->drawable
);
197 fbValidateGC(GCPtr pGC
, unsigned long changes
, DrawablePtr pDrawable
)
199 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
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;
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
)
242 (*pGC
->pScreen
->DestroyPixmap
) (pNewTile
);
243 pNewTile
= fb24_32ReformatTile (pOldTile
, pDrawable
->bitsPerPixel
);
247 fbGetRotatedPixmap(pGC
) = pOldTile
;
248 pGC
->tile
.pixmap
= pNewTile
;
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
;
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
))
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
)
294 pPriv
->pm
= pGC
->planemask
& mask
;
296 s
= pDrawable
->bitsPerPixel
;
299 pPriv
->fg
|= pPriv
->fg
<< s
;
300 pPriv
->bg
|= pPriv
->bg
<< s
;
301 pPriv
->pm
|= pPriv
->pm
<< s
;
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;
316 dashLength
+= (unsigned int ) *dash
++;
317 pPriv
->dashLength
= dashLength
;