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            }
671b5d61b8Smrg            src += srcStride * h;
6835c4bbdfSmrg        }
6935c4bbdfSmrg        break;
7005b261ecSmrg    case ZPixmap:
711b5d61b8Smrg        srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip);
721b5d61b8Smrg        fbPutZImage(pDrawable, fbGetCompositeClip(pGC),
731b5d61b8Smrg                    pGC->alu, pPriv->pm, x, y, w, h, src, srcStride);
7405b261ecSmrg    }
7505b261ecSmrg}
7605b261ecSmrg
7705b261ecSmrgvoid
7835c4bbdfSmrgfbPutZImage(DrawablePtr pDrawable,
7935c4bbdfSmrg            RegionPtr pClip,
8035c4bbdfSmrg            int alu,
8135c4bbdfSmrg            FbBits pm,
8235c4bbdfSmrg            int x,
8335c4bbdfSmrg            int y, int width, int height, FbStip * src, FbStride srcStride)
8405b261ecSmrg{
8535c4bbdfSmrg    FbStip *dst;
8635c4bbdfSmrg    FbStride dstStride;
8735c4bbdfSmrg    int dstBpp;
8835c4bbdfSmrg    int dstXoff, dstYoff;
8935c4bbdfSmrg    int nbox;
9035c4bbdfSmrg    BoxPtr pbox;
9135c4bbdfSmrg    int x1, y1, x2, y2;
9205b261ecSmrg
9335c4bbdfSmrg    fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
9405b261ecSmrg
9535c4bbdfSmrg    for (nbox = RegionNumRects(pClip),
9635c4bbdfSmrg         pbox = RegionRects(pClip); nbox--; pbox++) {
9735c4bbdfSmrg        x1 = x;
9835c4bbdfSmrg        y1 = y;
9935c4bbdfSmrg        x2 = x + width;
10035c4bbdfSmrg        y2 = y + height;
10135c4bbdfSmrg        if (x1 < pbox->x1)
10235c4bbdfSmrg            x1 = pbox->x1;
10335c4bbdfSmrg        if (y1 < pbox->y1)
10435c4bbdfSmrg            y1 = pbox->y1;
10535c4bbdfSmrg        if (x2 > pbox->x2)
10635c4bbdfSmrg            x2 = pbox->x2;
10735c4bbdfSmrg        if (y2 > pbox->y2)
10835c4bbdfSmrg            y2 = pbox->y2;
10935c4bbdfSmrg        if (x1 >= x2 || y1 >= y2)
11035c4bbdfSmrg            continue;
11135c4bbdfSmrg        fbBltStip(src + (y1 - y) * srcStride,
11235c4bbdfSmrg                  srcStride,
11335c4bbdfSmrg                  (x1 - x) * dstBpp,
11435c4bbdfSmrg                  dst + (y1 + dstYoff) * dstStride,
11535c4bbdfSmrg                  dstStride,
11635c4bbdfSmrg                  (x1 + dstXoff) * dstBpp,
11735c4bbdfSmrg                  (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
11805b261ecSmrg    }
11905b261ecSmrg
12035c4bbdfSmrg    fbFinishAccess(pDrawable);
12105b261ecSmrg}
12205b261ecSmrg
12335c4bbdfSmrgvoid
12435c4bbdfSmrgfbPutXYImage(DrawablePtr pDrawable,
12535c4bbdfSmrg             RegionPtr pClip,
12635c4bbdfSmrg             FbBits fg,
12735c4bbdfSmrg             FbBits bg,
12835c4bbdfSmrg             FbBits pm,
12935c4bbdfSmrg             int alu,
13035c4bbdfSmrg             Bool opaque,
13135c4bbdfSmrg             int x,
13235c4bbdfSmrg             int y,
13335c4bbdfSmrg             int width, int height, FbStip * src, FbStride srcStride, int srcX)
13405b261ecSmrg{
13535c4bbdfSmrg    FbBits *dst;
13635c4bbdfSmrg    FbStride dstStride;
13735c4bbdfSmrg    int dstBpp;
13835c4bbdfSmrg    int dstXoff, dstYoff;
13935c4bbdfSmrg    int nbox;
14035c4bbdfSmrg    BoxPtr pbox;
14135c4bbdfSmrg    int x1, y1, x2, y2;
14235c4bbdfSmrg    FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
14305b261ecSmrg
14435c4bbdfSmrg    fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
14505b261ecSmrg
14635c4bbdfSmrg    if (dstBpp == 1) {
14735c4bbdfSmrg        if (opaque)
14835c4bbdfSmrg            alu = FbOpaqueStipple1Rop(alu, fg, bg);
14935c4bbdfSmrg        else
15035c4bbdfSmrg            alu = FbStipple1Rop(alu, fg);
15105b261ecSmrg    }
15235c4bbdfSmrg    else {
15335c4bbdfSmrg        fgand = fbAnd(alu, fg, pm);
15435c4bbdfSmrg        fgxor = fbXor(alu, fg, pm);
15535c4bbdfSmrg        if (opaque) {
15635c4bbdfSmrg            bgand = fbAnd(alu, bg, pm);
15735c4bbdfSmrg            bgxor = fbXor(alu, bg, pm);
15835c4bbdfSmrg        }
15935c4bbdfSmrg        else {
16035c4bbdfSmrg            bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
16135c4bbdfSmrg            bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
16235c4bbdfSmrg        }
16305b261ecSmrg    }
16405b261ecSmrg
16535c4bbdfSmrg    for (nbox = RegionNumRects(pClip),
16635c4bbdfSmrg         pbox = RegionRects(pClip); nbox--; pbox++) {
16735c4bbdfSmrg        x1 = x;
16835c4bbdfSmrg        y1 = y;
16935c4bbdfSmrg        x2 = x + width;
17035c4bbdfSmrg        y2 = y + height;
17135c4bbdfSmrg        if (x1 < pbox->x1)
17235c4bbdfSmrg            x1 = pbox->x1;
17335c4bbdfSmrg        if (y1 < pbox->y1)
17435c4bbdfSmrg            y1 = pbox->y1;
17535c4bbdfSmrg        if (x2 > pbox->x2)
17635c4bbdfSmrg            x2 = pbox->x2;
17735c4bbdfSmrg        if (y2 > pbox->y2)
17835c4bbdfSmrg            y2 = pbox->y2;
17935c4bbdfSmrg        if (x1 >= x2 || y1 >= y2)
18035c4bbdfSmrg            continue;
18135c4bbdfSmrg        if (dstBpp == 1) {
18235c4bbdfSmrg            fbBltStip(src + (y1 - y) * srcStride,
18335c4bbdfSmrg                      srcStride,
18435c4bbdfSmrg                      (x1 - x) + srcX,
18535c4bbdfSmrg                      (FbStip *) (dst + (y1 + dstYoff) * dstStride),
18635c4bbdfSmrg                      FbBitsStrideToStipStride(dstStride),
18735c4bbdfSmrg                      (x1 + dstXoff) * dstBpp,
18835c4bbdfSmrg                      (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp);
18935c4bbdfSmrg        }
19035c4bbdfSmrg        else {
19135c4bbdfSmrg            fbBltOne(src + (y1 - y) * srcStride,
19235c4bbdfSmrg                     srcStride,
19335c4bbdfSmrg                     (x1 - x) + srcX,
19435c4bbdfSmrg                     dst + (y1 + dstYoff) * dstStride,
19535c4bbdfSmrg                     dstStride,
19635c4bbdfSmrg                     (x1 + dstXoff) * dstBpp,
19735c4bbdfSmrg                     dstBpp,
19835c4bbdfSmrg                     (x2 - x1) * dstBpp, (y2 - y1), fgand, fgxor, bgand, bgxor);
19935c4bbdfSmrg        }
20005b261ecSmrg    }
20105b261ecSmrg
20235c4bbdfSmrg    fbFinishAccess(pDrawable);
20305b261ecSmrg}
20405b261ecSmrg
20505b261ecSmrgvoid
20635c4bbdfSmrgfbGetImage(DrawablePtr pDrawable,
20735c4bbdfSmrg           int x,
20835c4bbdfSmrg           int y,
20935c4bbdfSmrg           int w, int h, unsigned int format, unsigned long planeMask, char *d)
21005b261ecSmrg{
21135c4bbdfSmrg    FbBits *src;
21235c4bbdfSmrg    FbStride srcStride;
21335c4bbdfSmrg    int srcBpp;
21435c4bbdfSmrg    int srcXoff, srcYoff;
21535c4bbdfSmrg    FbStip *dst;
21635c4bbdfSmrg    FbStride dstStride;
21735c4bbdfSmrg
21805b261ecSmrg    /*
21905b261ecSmrg     * XFree86 DDX empties the root borderClip when the VT is
22005b261ecSmrg     * switched away; this checks for that case
22105b261ecSmrg     */
22205b261ecSmrg    if (!fbDrawableEnabled(pDrawable))
22335c4bbdfSmrg        return;
22435c4bbdfSmrg
22535c4bbdfSmrg    fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
22635c4bbdfSmrg
22705b261ecSmrg    x += pDrawable->x;
22805b261ecSmrg    y += pDrawable->y;
22905b261ecSmrg
23035c4bbdfSmrg    dst = (FbStip *) d;
23135c4bbdfSmrg    if (format == ZPixmap || srcBpp == 1) {
23235c4bbdfSmrg        FbBits pm;
23305b261ecSmrg
23435c4bbdfSmrg        pm = fbReplicatePixel(planeMask, srcBpp);
23535c4bbdfSmrg        dstStride = PixmapBytePad(w, pDrawable->depth);
23635c4bbdfSmrg        dstStride /= sizeof(FbStip);
23735c4bbdfSmrg        fbBltStip((FbStip *) (src + (y + srcYoff) * srcStride),
23835c4bbdfSmrg                  FbBitsStrideToStipStride(srcStride),
23935c4bbdfSmrg                  (x + srcXoff) * srcBpp,
2401b5d61b8Smrg                  dst, dstStride, 0, w * srcBpp, h, GXcopy, FB_ALLONES, srcBpp);
2411b5d61b8Smrg
2421b5d61b8Smrg        if (pm != FB_ALLONES) {
2431b5d61b8Smrg            for (int i = 0; i < dstStride * h; i++)
2441b5d61b8Smrg                dst[i] &= pm;
2451b5d61b8Smrg        }
24605b261ecSmrg    }
24735c4bbdfSmrg    else {
24835c4bbdfSmrg        dstStride = BitmapBytePad(w) / sizeof(FbStip);
24935c4bbdfSmrg        fbBltPlane(src + (y + srcYoff) * srcStride,
25035c4bbdfSmrg                   srcStride,
25135c4bbdfSmrg                   (x + srcXoff) * srcBpp,
25235c4bbdfSmrg                   srcBpp,
25335c4bbdfSmrg                   dst,
25435c4bbdfSmrg                   dstStride,
25535c4bbdfSmrg                   0,
25635c4bbdfSmrg                   w * srcBpp, h,
25735c4bbdfSmrg                   fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
25835c4bbdfSmrg                   fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES),
25935c4bbdfSmrg                   fbAndStip(GXcopy, 0, FB_STIP_ALLONES),
26035c4bbdfSmrg                   fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask);
26105b261ecSmrg    }
26205b261ecSmrg
26335c4bbdfSmrg    fbFinishAccess(pDrawable);
26405b261ecSmrg}
265