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 */
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include <string.h>
29 #include "fb.h"
31 void
32 fbPutImage (DrawablePtr pDrawable,
33 GCPtr pGC,
34 int depth,
35 int x,
36 int y,
37 int w,
38 int h,
39 int leftPad,
40 int format,
41 char *pImage)
42 {
43 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
44 unsigned long i;
45 FbStride srcStride;
46 FbStip *src = (FbStip *) pImage;
48 x += pDrawable->x;
49 y += pDrawable->y;
51 switch (format)
52 {
53 case XYBitmap:
54 srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
55 fbPutXYImage (pDrawable,
56 fbGetCompositeClip(pGC),
57 pPriv->fg,
58 pPriv->bg,
59 pPriv->pm,
60 pGC->alu,
61 TRUE,
62 x, y, w, h,
63 src,
64 srcStride,
65 leftPad);
66 break;
67 case XYPixmap:
68 srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
69 for (i = (unsigned long)1 << (pDrawable->depth - 1); i; i >>= 1)
70 {
71 if (i & pGC->planemask)
72 {
73 fbPutXYImage (pDrawable,
74 fbGetCompositeClip(pGC),
75 FB_ALLONES,
76 0,
77 fbReplicatePixel (i, pDrawable->bitsPerPixel),
78 pGC->alu,
79 TRUE,
80 x, y, w, h,
81 src,
82 srcStride,
83 leftPad);
84 src += srcStride * h;
85 }
86 }
87 break;
88 case ZPixmap:
89 if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth))
90 {
91 srcStride = PixmapBytePad(w, pDrawable->depth);
92 fb24_32PutZImage (pDrawable,
93 fbGetCompositeClip(pGC),
94 pGC->alu,
95 (FbBits) pGC->planemask,
96 x, y, w, h,
97 (CARD8 *) pImage,
98 srcStride);
99 }
100 else
101 {
102 srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip);
103 fbPutZImage (pDrawable,
104 fbGetCompositeClip(pGC),
105 pGC->alu,
106 pPriv->pm,
107 x, y, w, h,
108 src, srcStride);
109 }
110 }
111 }
113 void
114 fbPutZImage (DrawablePtr pDrawable,
115 RegionPtr pClip,
116 int alu,
117 FbBits pm,
118 int x,
119 int y,
120 int width,
121 int height,
122 FbStip *src,
123 FbStride srcStride)
124 {
125 FbStip *dst;
126 FbStride dstStride;
127 int dstBpp;
128 int dstXoff, dstYoff;
129 int nbox;
130 BoxPtr pbox;
131 int x1, y1, x2, y2;
133 fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
135 for (nbox = RegionNumRects (pClip),
136 pbox = RegionRects(pClip);
137 nbox--;
138 pbox++)
139 {
140 x1 = x;
141 y1 = y;
142 x2 = x + width;
143 y2 = y + height;
144 if (x1 < pbox->x1)
145 x1 = pbox->x1;
146 if (y1 < pbox->y1)
147 y1 = pbox->y1;
148 if (x2 > pbox->x2)
149 x2 = pbox->x2;
150 if (y2 > pbox->y2)
151 y2 = pbox->y2;
152 if (x1 >= x2 || y1 >= y2)
153 continue;
154 fbBltStip (src + (y1 - y) * srcStride,
155 srcStride,
156 (x1 - x) * dstBpp,
158 dst + (y1 + dstYoff) * dstStride,
159 dstStride,
160 (x1 + dstXoff) * dstBpp,
162 (x2 - x1) * dstBpp,
163 (y2 - y1),
165 alu,
166 pm,
167 dstBpp);
168 }
170 fbFinishAccess (pDrawable);
171 }
173 void
174 fbPutXYImage (DrawablePtr pDrawable,
175 RegionPtr pClip,
176 FbBits fg,
177 FbBits bg,
178 FbBits pm,
179 int alu,
180 Bool opaque,
182 int x,
183 int y,
184 int width,
185 int height,
187 FbStip *src,
188 FbStride srcStride,
189 int srcX)
190 {
191 FbBits *dst;
192 FbStride dstStride;
193 int dstBpp;
194 int dstXoff, dstYoff;
195 int nbox;
196 BoxPtr pbox;
197 int x1, y1, x2, y2;
198 FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
200 fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
202 if (dstBpp == 1)
203 {
204 if (opaque)
205 alu = FbOpaqueStipple1Rop(alu,fg,bg);
206 else
207 alu = FbStipple1Rop(alu,fg);
208 }
209 else
210 {
211 fgand = fbAnd(alu,fg,pm);
212 fgxor = fbXor(alu,fg,pm);
213 if (opaque)
214 {
215 bgand = fbAnd(alu,bg,pm);
216 bgxor = fbXor(alu,bg,pm);
217 }
218 else
219 {
220 bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES);
221 bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES);
222 }
223 }
225 for (nbox = RegionNumRects (pClip),
226 pbox = RegionRects(pClip);
227 nbox--;
228 pbox++)
229 {
230 x1 = x;
231 y1 = y;
232 x2 = x + width;
233 y2 = y + height;
234 if (x1 < pbox->x1)
235 x1 = pbox->x1;
236 if (y1 < pbox->y1)
237 y1 = pbox->y1;
238 if (x2 > pbox->x2)
239 x2 = pbox->x2;
240 if (y2 > pbox->y2)
241 y2 = pbox->y2;
242 if (x1 >= x2 || y1 >= y2)
243 continue;
244 if (dstBpp == 1)
245 {
246 fbBltStip (src + (y1 - y) * srcStride,
247 srcStride,
248 (x1 - x) + srcX,
250 (FbStip *) (dst + (y1 + dstYoff) * dstStride),
251 FbBitsStrideToStipStride(dstStride),
252 (x1 + dstXoff) * dstBpp,
254 (x2 - x1) * dstBpp,
255 (y2 - y1),
257 alu,
258 pm,
259 dstBpp);
260 }
261 else
262 {
263 fbBltOne (src + (y1 - y) * srcStride,
264 srcStride,
265 (x1 - x) + srcX,
267 dst + (y1 + dstYoff) * dstStride,
268 dstStride,
269 (x1 + dstXoff) * dstBpp,
270 dstBpp,
272 (x2 - x1) * dstBpp,
273 (y2 - y1),
275 fgand, fgxor, bgand, bgxor);
276 }
277 }
279 fbFinishAccess (pDrawable);
280 }
282 void
283 fbGetImage (DrawablePtr pDrawable,
284 int x,
285 int y,
286 int w,
287 int h,
288 unsigned int format,
289 unsigned long planeMask,
290 char *d)
291 {
292 FbBits *src;
293 FbStride srcStride;
294 int srcBpp;
295 int srcXoff, srcYoff;
296 FbStip *dst;
297 FbStride dstStride;
299 /*
300 * XFree86 DDX empties the root borderClip when the VT is
301 * switched away; this checks for that case
302 */
303 if (!fbDrawableEnabled(pDrawable))
304 return;
306 if (format == ZPixmap &&
307 pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth))
308 {
309 fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d);
310 return;
311 }
313 fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
315 x += pDrawable->x;
316 y += pDrawable->y;
318 dst = (FbStip *) d;
319 if (format == ZPixmap || srcBpp == 1)
320 {
321 FbBits pm;
323 pm = fbReplicatePixel (planeMask, srcBpp);
324 dstStride = PixmapBytePad(w, pDrawable->depth);
325 if (pm != FB_ALLONES)
326 memset (d, 0, dstStride * h);
327 dstStride /= sizeof (FbStip);
328 fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride),
329 FbBitsStrideToStipStride(srcStride),
330 (x + srcXoff) * srcBpp,
332 dst,
333 dstStride,
334 0,
336 w * srcBpp, h,
338 GXcopy,
339 pm,
340 srcBpp);
341 }
342 else
343 {
344 dstStride = BitmapBytePad(w) / sizeof (FbStip);
345 fbBltPlane (src + (y + srcYoff) * srcStride,
346 srcStride,
347 (x + srcXoff) * srcBpp,
348 srcBpp,
350 dst,
351 dstStride,
352 0,
354 w * srcBpp, h,
356 fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
357 fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
358 fbAndStip(GXcopy,0,FB_STIP_ALLONES),
359 fbXorStip(GXcopy,0,FB_STIP_ALLONES),
360 planeMask);
361 }
363 fbFinishAccess (pDrawable);
364 }