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
31 const GCFuncs fbGCFuncs = {
32 fbValidateGC,
33 miChangeGC,
34 miCopyGC,
35 miDestroyGC,
36 miChangeClip,
37 miDestroyClip,
38 miCopyClip,
39 };
40
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
62 };
63
64 Bool
fbCreateGC(GCPtr pGC)65 fbCreateGC(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 */
80 void
fbPadPixmap(PixmapPtr pPixmap)81 fbPadPixmap(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
112 void
fbValidateGC(GCPtr pGC,unsigned long changes,DrawablePtr pDrawable)113 fbValidateGC(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