fbimage.c revision 35c4bbdf
105b261ecSmrg/*
205b261ecSmrg * Copyright © 1998 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2405b261ecSmrg#include <dix-config.h>
2505b261ecSmrg#endif
2605b261ecSmrg
2705b261ecSmrg#include <string.h>
2805b261ecSmrg
2905b261ecSmrg#include "fb.h"
3005b261ecSmrg
3105b261ecSmrgvoid
3235c4bbdfSmrgfbPutImage(DrawablePtr pDrawable,
3335c4bbdfSmrg           GCPtr pGC,
3435c4bbdfSmrg           int depth,
3535c4bbdfSmrg           int x, int y, int w, int h, int leftPad, int format, char *pImage)
3605b261ecSmrg{
3735c4bbdfSmrg    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
3835c4bbdfSmrg    unsigned long i;
3935c4bbdfSmrg    FbStride srcStride;
4035c4bbdfSmrg    FbStip *src = (FbStip *) pImage;
4135c4bbdfSmrg
4205b261ecSmrg    x += pDrawable->x;
4305b261ecSmrg    y += pDrawable->y;
4435c4bbdfSmrg
4535c4bbdfSmrg    switch (format) {
4605b261ecSmrg    case XYBitmap:
4735c4bbdfSmrg        srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
4835c4bbdfSmrg        fbPutXYImage(pDrawable,
4935c4bbdfSmrg                     fbGetCompositeClip(pGC),
5035c4bbdfSmrg                     pPriv->fg,
5135c4bbdfSmrg                     pPriv->bg,
5235c4bbdfSmrg                     pPriv->pm,
5335c4bbdfSmrg                     pGC->alu, TRUE, x, y, w, h, src, srcStride, leftPad);
5435c4bbdfSmrg        break;
5505b261ecSmrg    case XYPixmap:
5635c4bbdfSmrg        srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip);
5735c4bbdfSmrg        for (i = (unsigned long) 1 << (pDrawable->depth - 1); i; i >>= 1) {
5835c4bbdfSmrg            if (i & pGC->planemask) {
5935c4bbdfSmrg                fbPutXYImage(pDrawable,
6035c4bbdfSmrg                             fbGetCompositeClip(pGC),
6135c4bbdfSmrg                             FB_ALLONES,
6235c4bbdfSmrg                             0,
6335c4bbdfSmrg                             fbReplicatePixel(i, pDrawable->bitsPerPixel),
6435c4bbdfSmrg                             pGC->alu,
6535c4bbdfSmrg                             TRUE, x, y, w, h, src, srcStride, leftPad);
6635c4bbdfSmrg                src += srcStride * h;
6735c4bbdfSmrg            }
6835c4bbdfSmrg        }
6935c4bbdfSmrg        break;
7005b261ecSmrg    case ZPixmap:
7135c4bbdfSmrg        if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) {
7235c4bbdfSmrg            srcStride = PixmapBytePad(w, pDrawable->depth);
7335c4bbdfSmrg            fb24_32PutZImage(pDrawable,
7435c4bbdfSmrg                             fbGetCompositeClip(pGC),
7535c4bbdfSmrg                             pGC->alu,
7635c4bbdfSmrg                             (FbBits) pGC->planemask,
7735c4bbdfSmrg                             x, y, w, h, (CARD8 *) pImage, srcStride);
7835c4bbdfSmrg        }
7935c4bbdfSmrg        else {
8035c4bbdfSmrg            srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip);
8135c4bbdfSmrg            fbPutZImage(pDrawable,
8235c4bbdfSmrg                        fbGetCompositeClip(pGC),
8335c4bbdfSmrg                        pGC->alu, pPriv->pm, x, y, w, h, src, srcStride);
8435c4bbdfSmrg        }
8505b261ecSmrg    }
8605b261ecSmrg}
8705b261ecSmrg
8805b261ecSmrgvoid
8935c4bbdfSmrgfbPutZImage(DrawablePtr pDrawable,
9035c4bbdfSmrg            RegionPtr pClip,
9135c4bbdfSmrg            int alu,
9235c4bbdfSmrg            FbBits pm,
9335c4bbdfSmrg            int x,
9435c4bbdfSmrg            int y, int width, int height, FbStip * src, FbStride srcStride)
9505b261ecSmrg{
9635c4bbdfSmrg    FbStip *dst;
9735c4bbdfSmrg    FbStride dstStride;
9835c4bbdfSmrg    int dstBpp;
9935c4bbdfSmrg    int dstXoff, dstYoff;
10035c4bbdfSmrg    int nbox;
10135c4bbdfSmrg    BoxPtr pbox;
10235c4bbdfSmrg    int x1, y1, x2, y2;
10305b261ecSmrg
10435c4bbdfSmrg    fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
10505b261ecSmrg
10635c4bbdfSmrg    for (nbox = RegionNumRects(pClip),
10735c4bbdfSmrg         pbox = RegionRects(pClip); nbox--; pbox++) {
10835c4bbdfSmrg        x1 = x;
10935c4bbdfSmrg        y1 = y;
11035c4bbdfSmrg        x2 = x + width;
11135c4bbdfSmrg        y2 = y + height;
11235c4bbdfSmrg        if (x1 < pbox->x1)
11335c4bbdfSmrg            x1 = pbox->x1;
11435c4bbdfSmrg        if (y1 < pbox->y1)
11535c4bbdfSmrg            y1 = pbox->y1;
11635c4bbdfSmrg        if (x2 > pbox->x2)
11735c4bbdfSmrg            x2 = pbox->x2;
11835c4bbdfSmrg        if (y2 > pbox->y2)
11935c4bbdfSmrg            y2 = pbox->y2;
12035c4bbdfSmrg        if (x1 >= x2 || y1 >= y2)
12135c4bbdfSmrg            continue;
12235c4bbdfSmrg        fbBltStip(src + (y1 - y) * srcStride,
12335c4bbdfSmrg                  srcStride,
12435c4bbdfSmrg                  (x1 - x) * dstBpp,
12535c4bbdfSmrg                  dst + (y1 + dstYoff) * dstStride,
12635c4bbdfSmrg                  dstStride,
12735c4bbdfSmrg                  (x1 + dstXoff) * dstBpp,
12835c4bbdfSmrg                  (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
12905b261ecSmrg    }
13005b261ecSmrg
13135c4bbdfSmrg    fbFinishAccess(pDrawable);
13205b261ecSmrg}
13305b261ecSmrg
13435c4bbdfSmrgvoid
13535c4bbdfSmrgfbPutXYImage(DrawablePtr pDrawable,
13635c4bbdfSmrg             RegionPtr pClip,
13735c4bbdfSmrg             FbBits fg,
13835c4bbdfSmrg             FbBits bg,
13935c4bbdfSmrg             FbBits pm,
14035c4bbdfSmrg             int alu,
14135c4bbdfSmrg             Bool opaque,
14235c4bbdfSmrg             int x,
14335c4bbdfSmrg             int y,
14435c4bbdfSmrg             int width, int height, FbStip * src, FbStride srcStride, int srcX)
14505b261ecSmrg{
14635c4bbdfSmrg    FbBits *dst;
14735c4bbdfSmrg    FbStride dstStride;
14835c4bbdfSmrg    int dstBpp;
14935c4bbdfSmrg    int dstXoff, dstYoff;
15035c4bbdfSmrg    int nbox;
15135c4bbdfSmrg    BoxPtr pbox;
15235c4bbdfSmrg    int x1, y1, x2, y2;
15335c4bbdfSmrg    FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
15405b261ecSmrg
15535c4bbdfSmrg    fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
15605b261ecSmrg
15735c4bbdfSmrg    if (dstBpp == 1) {
15835c4bbdfSmrg        if (opaque)
15935c4bbdfSmrg            alu = FbOpaqueStipple1Rop(alu, fg, bg);
16035c4bbdfSmrg        else
16135c4bbdfSmrg            alu = FbStipple1Rop(alu, fg);
16205b261ecSmrg    }
16335c4bbdfSmrg    else {
16435c4bbdfSmrg        fgand = fbAnd(alu, fg, pm);
16535c4bbdfSmrg        fgxor = fbXor(alu, fg, pm);
16635c4bbdfSmrg        if (opaque) {
16735c4bbdfSmrg            bgand = fbAnd(alu, bg, pm);
16835c4bbdfSmrg            bgxor = fbXor(alu, bg, pm);
16935c4bbdfSmrg        }
17035c4bbdfSmrg        else {
17135c4bbdfSmrg            bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
17235c4bbdfSmrg            bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
17335c4bbdfSmrg        }
17405b261ecSmrg    }
17505b261ecSmrg
17635c4bbdfSmrg    for (nbox = RegionNumRects(pClip),
17735c4bbdfSmrg         pbox = RegionRects(pClip); nbox--; pbox++) {
17835c4bbdfSmrg        x1 = x;
17935c4bbdfSmrg        y1 = y;
18035c4bbdfSmrg        x2 = x + width;
18135c4bbdfSmrg        y2 = y + height;
18235c4bbdfSmrg        if (x1 < pbox->x1)
18335c4bbdfSmrg            x1 = pbox->x1;
18435c4bbdfSmrg        if (y1 < pbox->y1)
18535c4bbdfSmrg            y1 = pbox->y1;
18635c4bbdfSmrg        if (x2 > pbox->x2)
18735c4bbdfSmrg            x2 = pbox->x2;
18835c4bbdfSmrg        if (y2 > pbox->y2)
18935c4bbdfSmrg            y2 = pbox->y2;
19035c4bbdfSmrg        if (x1 >= x2 || y1 >= y2)
19135c4bbdfSmrg            continue;
19235c4bbdfSmrg        if (dstBpp == 1) {
19335c4bbdfSmrg            fbBltStip(src + (y1 - y) * srcStride,
19435c4bbdfSmrg                      srcStride,
19535c4bbdfSmrg                      (x1 - x) + srcX,
19635c4bbdfSmrg                      (FbStip *) (dst + (y1 + dstYoff) * dstStride),
19735c4bbdfSmrg                      FbBitsStrideToStipStride(dstStride),
19835c4bbdfSmrg                      (x1 + dstXoff) * dstBpp,
19935c4bbdfSmrg                      (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
20035c4bbdfSmrg        }
20135c4bbdfSmrg        else {
20235c4bbdfSmrg            fbBltOne(src + (y1 - y) * srcStride,
20335c4bbdfSmrg                     srcStride,
20435c4bbdfSmrg                     (x1 - x) + srcX,
20535c4bbdfSmrg                     dst + (y1 + dstYoff) * dstStride,
20635c4bbdfSmrg                     dstStride,
20735c4bbdfSmrg                     (x1 + dstXoff) * dstBpp,
20835c4bbdfSmrg                     dstBpp,
20935c4bbdfSmrg                     (x2 - x1) * dstBpp, (y2 - y1), fgand, fgxor, bgand, bgxor);
21035c4bbdfSmrg        }
21105b261ecSmrg    }
21205b261ecSmrg
21335c4bbdfSmrg    fbFinishAccess(pDrawable);
21405b261ecSmrg}
21505b261ecSmrg
21605b261ecSmrgvoid
21735c4bbdfSmrgfbGetImage(DrawablePtr pDrawable,
21835c4bbdfSmrg           int x,
21935c4bbdfSmrg           int y,
22035c4bbdfSmrg           int w, int h, unsigned int format, unsigned long planeMask, char *d)
22105b261ecSmrg{
22235c4bbdfSmrg    FbBits *src;
22335c4bbdfSmrg    FbStride srcStride;
22435c4bbdfSmrg    int srcBpp;
22535c4bbdfSmrg    int srcXoff, srcYoff;
22635c4bbdfSmrg    FbStip *dst;
22735c4bbdfSmrg    FbStride dstStride;
22835c4bbdfSmrg
22905b261ecSmrg    /*
23005b261ecSmrg     * XFree86 DDX empties the root borderClip when the VT is
23105b261ecSmrg     * switched away; this checks for that case
23205b261ecSmrg     */
23305b261ecSmrg    if (!fbDrawableEnabled(pDrawable))
23435c4bbdfSmrg        return;
23535c4bbdfSmrg
23605b261ecSmrg    if (format == ZPixmap &&
23735c4bbdfSmrg        pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) {
23835c4bbdfSmrg        fb24_32GetImage(pDrawable, x, y, w, h, format, planeMask, d);
23935c4bbdfSmrg        return;
24005b261ecSmrg    }
24135c4bbdfSmrg
24235c4bbdfSmrg    fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
24335c4bbdfSmrg
24405b261ecSmrg    x += pDrawable->x;
24505b261ecSmrg    y += pDrawable->y;
24605b261ecSmrg
24735c4bbdfSmrg    dst = (FbStip *) d;
24835c4bbdfSmrg    if (format == ZPixmap || srcBpp == 1) {
24935c4bbdfSmrg        FbBits pm;
25005b261ecSmrg
25135c4bbdfSmrg        pm = fbReplicatePixel(planeMask, srcBpp);
25235c4bbdfSmrg        dstStride = PixmapBytePad(w, pDrawable->depth);
25335c4bbdfSmrg        if (pm != FB_ALLONES)
25435c4bbdfSmrg            memset(d, 0, dstStride * h);
25535c4bbdfSmrg        dstStride /= sizeof(FbStip);
25635c4bbdfSmrg        fbBltStip((FbStip *) (src + (y + srcYoff) * srcStride),
25735c4bbdfSmrg                  FbBitsStrideToStipStride(srcStride),
25835c4bbdfSmrg                  (x + srcXoff) * srcBpp,
25935c4bbdfSmrg                  dst, dstStride, 0, w * srcBpp, h, GXcopy, pm, srcBpp);
26005b261ecSmrg    }
26135c4bbdfSmrg    else {
26235c4bbdfSmrg        dstStride = BitmapBytePad(w) / sizeof(FbStip);
26335c4bbdfSmrg        fbBltPlane(src + (y + srcYoff) * srcStride,
26435c4bbdfSmrg                   srcStride,
26535c4bbdfSmrg                   (x + srcXoff) * srcBpp,
26635c4bbdfSmrg                   srcBpp,
26735c4bbdfSmrg                   dst,
26835c4bbdfSmrg                   dstStride,
26935c4bbdfSmrg                   0,
27035c4bbdfSmrg                   w * srcBpp, h,
27135c4bbdfSmrg                   fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
27235c4bbdfSmrg                   fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
27335c4bbdfSmrg                   fbAndStip(GXcopy, 0, FB_STIP_ALLONES),
27435c4bbdfSmrg                   fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask);
27505b261ecSmrg    }
27605b261ecSmrg
27735c4bbdfSmrg    fbFinishAccess(pDrawable);
27805b261ecSmrg}
279