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 <string.h>
28
29 #include "fb.h"
30
31 void
fbPutImage(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pImage)32 fbPutImage(DrawablePtr pDrawable,
33 GCPtr pGC,
34 int depth,
35 int x, int y, int w, int h, int leftPad, int format, char *pImage)
36 {
37 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
38 unsigned long i;
39 FbStride srcStride;
40 FbStip *src = (FbStip *) pImage;
41
42 x += pDrawable->x;
43 y += pDrawable->y;
44
45 switch (format) {
46 case XYBitmap:
47 srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
48 fbPutXYImage(pDrawable,
49 fbGetCompositeClip(pGC),
50 pPriv->fg,
51 pPriv->bg,
52 pPriv->pm,
53 pGC->alu, TRUE, x, y, w, h, src, srcStride, leftPad);
54 break;
55 case XYPixmap:
56 srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
57 for (i = (unsigned long) 1 << (pDrawable->depth - 1); i; i >>= 1) {
58 if (i & pGC->planemask) {
59 fbPutXYImage(pDrawable,
60 fbGetCompositeClip(pGC),
61 FB_ALLONES,
62 0,
63 fbReplicatePixel(i, pDrawable->bitsPerPixel),
64 pGC->alu,
65 TRUE, x, y, w, h, src, srcStride, leftPad);
66 }
67 src += srcStride * h;
68 }
69 break;
70 case ZPixmap:
71 srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip);
72 fbPutZImage(pDrawable, fbGetCompositeClip(pGC),
73 pGC->alu, pPriv->pm, x, y, w, h, src, srcStride);
74 }
75 }
76
77 void
fbPutZImage(DrawablePtr pDrawable,RegionPtr pClip,int alu,FbBits pm,int x,int y,int width,int height,FbStip * src,FbStride srcStride)78 fbPutZImage(DrawablePtr pDrawable,
79 RegionPtr pClip,
80 int alu,
81 FbBits pm,
82 int x,
83 int y, int width, int height, FbStip * src, FbStride srcStride)
84 {
85 FbStip *dst;
86 FbStride dstStride;
87 int dstBpp;
88 int dstXoff, dstYoff;
89 int nbox;
90 BoxPtr pbox;
91 int x1, y1, x2, y2;
92
93 fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
94
95 for (nbox = RegionNumRects(pClip),
96 pbox = RegionRects(pClip); nbox--; pbox++) {
97 x1 = x;
98 y1 = y;
99 x2 = x + width;
100 y2 = y + height;
101 if (x1 < pbox->x1)
102 x1 = pbox->x1;
103 if (y1 < pbox->y1)
104 y1 = pbox->y1;
105 if (x2 > pbox->x2)
106 x2 = pbox->x2;
107 if (y2 > pbox->y2)
108 y2 = pbox->y2;
109 if (x1 >= x2 || y1 >= y2)
110 continue;
111 fbBltStip(src + (y1 - y) * srcStride,
112 srcStride,
113 (x1 - x) * dstBpp,
114 dst + (y1 + dstYoff) * dstStride,
115 dstStride,
116 (x1 + dstXoff) * dstBpp,
117 (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
118 }
119
120 fbFinishAccess(pDrawable);
121 }
122
123 void
fbPutXYImage(DrawablePtr pDrawable,RegionPtr pClip,FbBits fg,FbBits bg,FbBits pm,int alu,Bool opaque,int x,int y,int width,int height,FbStip * src,FbStride srcStride,int srcX)124 fbPutXYImage(DrawablePtr pDrawable,
125 RegionPtr pClip,
126 FbBits fg,
127 FbBits bg,
128 FbBits pm,
129 int alu,
130 Bool opaque,
131 int x,
132 int y,
133 int width, int height, FbStip * src, FbStride srcStride, int srcX)
134 {
135 FbBits *dst;
136 FbStride dstStride;
137 int dstBpp;
138 int dstXoff, dstYoff;
139 int nbox;
140 BoxPtr pbox;
141 int x1, y1, x2, y2;
142 FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
143
144 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
145
146 if (dstBpp == 1) {
147 if (opaque)
148 alu = FbOpaqueStipple1Rop(alu, fg, bg);
149 else
150 alu = FbStipple1Rop(alu, fg);
151 }
152 else {
153 fgand = fbAnd(alu, fg, pm);
154 fgxor = fbXor(alu, fg, pm);
155 if (opaque) {
156 bgand = fbAnd(alu, bg, pm);
157 bgxor = fbXor(alu, bg, pm);
158 }
159 else {
160 bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
161 bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
162 }
163 }
164
165 for (nbox = RegionNumRects(pClip),
166 pbox = RegionRects(pClip); nbox--; pbox++) {
167 x1 = x;
168 y1 = y;
169 x2 = x + width;
170 y2 = y + height;
171 if (x1 < pbox->x1)
172 x1 = pbox->x1;
173 if (y1 < pbox->y1)
174 y1 = pbox->y1;
175 if (x2 > pbox->x2)
176 x2 = pbox->x2;
177 if (y2 > pbox->y2)
178 y2 = pbox->y2;
179 if (x1 >= x2 || y1 >= y2)
180 continue;
181 if (dstBpp == 1) {
182 fbBltStip(src + (y1 - y) * srcStride,
183 srcStride,
184 (x1 - x) + srcX,
185 (FbStip *) (dst + (y1 + dstYoff) * dstStride),
186 FbBitsStrideToStipStride(dstStride),
187 (x1 + dstXoff) * dstBpp,
188 (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
189 }
190 else {
191 fbBltOne(src + (y1 - y) * srcStride,
192 srcStride,
193 (x1 - x) + srcX,
194 dst + (y1 + dstYoff) * dstStride,
195 dstStride,
196 (x1 + dstXoff) * dstBpp,
197 dstBpp,
198 (x2 - x1) * dstBpp, (y2 - y1), fgand, fgxor, bgand, bgxor);
199 }
200 }
201
202 fbFinishAccess(pDrawable);
203 }
204
205 void
fbGetImage(DrawablePtr pDrawable,int x,int y,int w,int h,unsigned int format,unsigned long planeMask,char * d)206 fbGetImage(DrawablePtr pDrawable,
207 int x,
208 int y,
209 int w, int h, unsigned int format, unsigned long planeMask, char *d)
210 {
211 FbBits *src;
212 FbStride srcStride;
213 int srcBpp;
214 int srcXoff, srcYoff;
215 FbStip *dst;
216 FbStride dstStride;
217
218 /*
219 * XFree86 DDX empties the root borderClip when the VT is
220 * switched away; this checks for that case
221 */
222 if (!fbDrawableEnabled(pDrawable))
223 return;
224
225 fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
226
227 x += pDrawable->x;
228 y += pDrawable->y;
229
230 dst = (FbStip *) d;
231 if (format == ZPixmap || srcBpp == 1) {
232 FbBits pm;
233
234 pm = fbReplicatePixel(planeMask, srcBpp);
235 dstStride = PixmapBytePad(w, pDrawable->depth);
236 dstStride /= sizeof(FbStip);
237 fbBltStip((FbStip *) (src + (y + srcYoff) * srcStride),
238 FbBitsStrideToStipStride(srcStride),
239 (x + srcXoff) * srcBpp,
240 dst, dstStride, 0, w * srcBpp, h, GXcopy, FB_ALLONES, srcBpp);
241
242 if (pm != FB_ALLONES) {
243 for (int i = 0; i < dstStride * h; i++)
244 dst[i] &= pm;
245 }
246 }
247 else {
248 dstStride = BitmapBytePad(w) / sizeof(FbStip);
249 fbBltPlane(src + (y + srcYoff) * srcStride,
250 srcStride,
251 (x + srcXoff) * srcBpp,
252 srcBpp,
253 dst,
254 dstStride,
255 0,
256 w * srcBpp, h,
257 fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
258 fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
259 fbAndStip(GXcopy, 0, FB_STIP_ALLONES),
260 fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask);
261 }
262
263 fbFinishAccess(pDrawable);
264 }
265