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 "fb.h"
28
29 static void
fbTile(FbBits * dst,FbStride dstStride,int dstX,int width,int height,FbBits * tile,FbStride tileStride,int tileWidth,int tileHeight,int alu,FbBits pm,int bpp,int xRot,int yRot)30 fbTile(FbBits * dst, FbStride dstStride, int dstX, int width, int height,
31 FbBits * tile, FbStride tileStride, int tileWidth, int tileHeight,
32 int alu, FbBits pm, int bpp, int xRot, int yRot)
33 {
34 int tileX, tileY;
35 int widthTmp;
36 int h, w;
37 int x, y;
38
39 modulus(-yRot, tileHeight, tileY);
40 y = 0;
41 while (height) {
42 h = tileHeight - tileY;
43 if (h > height)
44 h = height;
45 height -= h;
46 widthTmp = width;
47 x = dstX;
48 modulus(dstX - xRot, tileWidth, tileX);
49 while (widthTmp) {
50 w = tileWidth - tileX;
51 if (w > widthTmp)
52 w = widthTmp;
53 widthTmp -= w;
54 fbBlt(tile + tileY * tileStride,
55 tileStride,
56 tileX,
57 dst + y * dstStride,
58 dstStride, x, w, h, alu, pm, bpp, FALSE, FALSE);
59 x += w;
60 tileX = 0;
61 }
62 y += h;
63 tileY = 0;
64 }
65 }
66
67 static void
fbStipple(FbBits * dst,FbStride dstStride,int dstX,int dstBpp,int width,int height,FbStip * stip,FbStride stipStride,int stipWidth,int stipHeight,FbBits fgand,FbBits fgxor,FbBits bgand,FbBits bgxor,int xRot,int yRot)68 fbStipple(FbBits * dst, FbStride dstStride,
69 int dstX, int dstBpp,
70 int width, int height,
71 FbStip * stip, FbStride stipStride,
72 int stipWidth, int stipHeight,
73 FbBits fgand, FbBits fgxor,
74 FbBits bgand, FbBits bgxor,
75 int xRot, int yRot)
76 {
77 int stipX, stipY, sx;
78 int widthTmp;
79 int h, w;
80 int x, y;
81
82 modulus(-yRot, stipHeight, stipY);
83 modulus(dstX / dstBpp - xRot, stipWidth, stipX);
84 y = 0;
85 while (height) {
86 h = stipHeight - stipY;
87 if (h > height)
88 h = height;
89 height -= h;
90 widthTmp = width;
91 x = dstX;
92 sx = stipX;
93 while (widthTmp) {
94 w = (stipWidth - sx) * dstBpp;
95 if (w > widthTmp)
96 w = widthTmp;
97 widthTmp -= w;
98 fbBltOne(stip + stipY * stipStride,
99 stipStride,
100 sx,
101 dst + y * dstStride,
102 dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor);
103 x += w;
104 sx = 0;
105 }
106 y += h;
107 stipY = 0;
108 }
109 }
110
111 void
fbFill(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int width,int height)112 fbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height)
113 {
114 FbBits *dst;
115 FbStride dstStride;
116 int dstBpp;
117 int dstXoff, dstYoff;
118 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
119
120 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
121
122 switch (pGC->fillStyle) {
123 case FillSolid:
124 #ifndef FB_ACCESS_WRAPPER
125 if (pPriv->and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
126 x + dstXoff, y + dstYoff,
127 width, height, pPriv->xor))
128 #endif
129 fbSolid(dst + (y + dstYoff) * dstStride,
130 dstStride,
131 (x + dstXoff) * dstBpp,
132 dstBpp, width * dstBpp, height, pPriv->and, pPriv->xor);
133 break;
134 case FillStippled:
135 case FillOpaqueStippled:{
136 PixmapPtr pStip = pGC->stipple;
137 int stipWidth = pStip->drawable.width;
138 int stipHeight = pStip->drawable.height;
139
140 if (dstBpp == 1) {
141 int alu;
142 FbBits *stip;
143 FbStride stipStride;
144 int stipBpp;
145 _X_UNUSED int stipXoff, stipYoff;
146
147 if (pGC->fillStyle == FillStippled)
148 alu = FbStipple1Rop(pGC->alu, pGC->fgPixel);
149 else
150 alu = FbOpaqueStipple1Rop(pGC->alu, pGC->fgPixel, pGC->bgPixel);
151 fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff,
152 stipYoff);
153 fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff,
154 width, height, stip, stipStride, stipWidth, stipHeight, alu,
155 pPriv->pm, dstBpp, (pGC->patOrg.x + pDrawable->x + dstXoff),
156 pGC->patOrg.y + pDrawable->y - y);
157 fbFinishAccess(&pStip->drawable);
158 }
159 else {
160 FbStip *stip;
161 FbStride stipStride;
162 int stipBpp;
163 _X_UNUSED int stipXoff, stipYoff;
164 FbBits fgand, fgxor, bgand, bgxor;
165
166 fgand = pPriv->and;
167 fgxor = pPriv->xor;
168 if (pGC->fillStyle == FillStippled) {
169 bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
170 bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
171 }
172 else {
173 bgand = pPriv->bgand;
174 bgxor = pPriv->bgxor;
175 }
176
177 fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp,
178 stipXoff, stipYoff);
179 fbStipple(dst + (y + dstYoff) * dstStride, dstStride,
180 (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height,
181 stip, stipStride, stipWidth, stipHeight,
182 fgand, fgxor, bgand, bgxor,
183 pGC->patOrg.x + pDrawable->x + dstXoff,
184 pGC->patOrg.y + pDrawable->y - y);
185 fbFinishAccess(&pStip->drawable);
186 }
187 break;
188 }
189 case FillTiled:{
190 PixmapPtr pTile = pGC->tile.pixmap;
191 FbBits *tile;
192 FbStride tileStride;
193 int tileBpp;
194 int tileWidth;
195 int tileHeight;
196 _X_UNUSED int tileXoff, tileYoff;
197
198 fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff,
199 tileYoff);
200 tileWidth = pTile->drawable.width;
201 tileHeight = pTile->drawable.height;
202 fbTile(dst + (y + dstYoff) * dstStride,
203 dstStride,
204 (x + dstXoff) * dstBpp,
205 width * dstBpp, height,
206 tile,
207 tileStride,
208 tileWidth * tileBpp,
209 tileHeight,
210 pGC->alu,
211 pPriv->pm,
212 dstBpp,
213 (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp,
214 pGC->patOrg.y + pDrawable->y - y);
215 fbFinishAccess(&pTile->drawable);
216 break;
217 }
218 }
219 fbValidateDrawable(pDrawable);
220 fbFinishAccess(pDrawable);
221 }
222
223 void
fbSolidBoxClipped(DrawablePtr pDrawable,RegionPtr pClip,int x1,int y1,int x2,int y2,FbBits and,FbBits xor)224 fbSolidBoxClipped(DrawablePtr pDrawable,
225 RegionPtr pClip,
226 int x1, int y1, int x2, int y2, FbBits and, FbBits xor)
227 {
228 FbBits *dst;
229 FbStride dstStride;
230 int dstBpp;
231 int dstXoff, dstYoff;
232 BoxPtr pbox;
233 int nbox;
234 int partX1, partX2, partY1, partY2;
235
236 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
237
238 for (nbox = RegionNumRects(pClip), pbox = RegionRects(pClip);
239 nbox--; pbox++) {
240 partX1 = pbox->x1;
241 if (partX1 < x1)
242 partX1 = x1;
243
244 partX2 = pbox->x2;
245 if (partX2 > x2)
246 partX2 = x2;
247
248 if (partX2 <= partX1)
249 continue;
250
251 partY1 = pbox->y1;
252 if (partY1 < y1)
253 partY1 = y1;
254
255 partY2 = pbox->y2;
256 if (partY2 > y2)
257 partY2 = y2;
258
259 if (partY2 <= partY1)
260 continue;
261
262 #ifndef FB_ACCESS_WRAPPER
263 if (and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
264 partX1 + dstXoff, partY1 + dstYoff,
265 (partX2 - partX1), (partY2 - partY1), xor))
266 #endif
267 fbSolid(dst + (partY1 + dstYoff) * dstStride,
268 dstStride,
269 (partX1 + dstXoff) * dstBpp,
270 dstBpp,
271 (partX2 - partX1) * dstBpp, (partY2 - partY1), and, xor);
272 }
273 fbFinishAccess(pDrawable);
274 }
275