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
31void
32fbPutImage(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
77void
78fbPutZImage(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
123void
124fbPutXYImage(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
205void
206fbGetImage(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