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