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