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 "fb.h"
2805b261ecSmrg
2935c4bbdfSmrgstatic void
3035c4bbdfSmrgfbStipple(FbBits * dst, FbStride dstStride,
3135c4bbdfSmrg          int dstX, int dstBpp,
3235c4bbdfSmrg          int width, int height,
3335c4bbdfSmrg          FbStip * stip, FbStride stipStride,
3435c4bbdfSmrg          int stipWidth, int stipHeight,
3535c4bbdfSmrg          FbBits fgand, FbBits fgxor,
3635c4bbdfSmrg          FbBits bgand, FbBits bgxor,
3735c4bbdfSmrg          int xRot, int yRot)
3835c4bbdfSmrg{
3935c4bbdfSmrg    int stipX, stipY, sx;
4035c4bbdfSmrg    int widthTmp;
4135c4bbdfSmrg    int h, w;
4235c4bbdfSmrg    int x, y;
4335c4bbdfSmrg
4435c4bbdfSmrg    modulus(-yRot, stipHeight, stipY);
4535c4bbdfSmrg    modulus(dstX / dstBpp - xRot, stipWidth, stipX);
4635c4bbdfSmrg    y = 0;
4735c4bbdfSmrg    while (height) {
4835c4bbdfSmrg        h = stipHeight - stipY;
4935c4bbdfSmrg        if (h > height)
5035c4bbdfSmrg            h = height;
5135c4bbdfSmrg        height -= h;
5235c4bbdfSmrg        widthTmp = width;
5335c4bbdfSmrg        x = dstX;
5435c4bbdfSmrg        sx = stipX;
5535c4bbdfSmrg        while (widthTmp) {
5635c4bbdfSmrg            w = (stipWidth - sx) * dstBpp;
5735c4bbdfSmrg            if (w > widthTmp)
5835c4bbdfSmrg                w = widthTmp;
5935c4bbdfSmrg            widthTmp -= w;
6035c4bbdfSmrg            fbBltOne(stip + stipY * stipStride,
6135c4bbdfSmrg                     stipStride,
6235c4bbdfSmrg                     sx,
6335c4bbdfSmrg                     dst + y * dstStride,
6435c4bbdfSmrg                     dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor);
6535c4bbdfSmrg            x += w;
6635c4bbdfSmrg            sx = 0;
6735c4bbdfSmrg        }
6835c4bbdfSmrg        y += h;
6935c4bbdfSmrg        stipY = 0;
7035c4bbdfSmrg    }
7135c4bbdfSmrg}
7235c4bbdfSmrg
7305b261ecSmrgvoid
7435c4bbdfSmrgfbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height)
7505b261ecSmrg{
7635c4bbdfSmrg    FbBits *dst;
7735c4bbdfSmrg    FbStride dstStride;
7835c4bbdfSmrg    int dstBpp;
7935c4bbdfSmrg    int dstXoff, dstYoff;
8035c4bbdfSmrg    FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
8135c4bbdfSmrg
8235c4bbdfSmrg    fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
8305b261ecSmrg
8405b261ecSmrg    switch (pGC->fillStyle) {
8505b261ecSmrg    case FillSolid:
8605b261ecSmrg#ifndef FB_ACCESS_WRAPPER
8735c4bbdfSmrg        if (pPriv->and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
8835c4bbdfSmrg                                       x + dstXoff, y + dstYoff,
8935c4bbdfSmrg                                       width, height, pPriv->xor))
9035c4bbdfSmrg#endif
9135c4bbdfSmrg            fbSolid(dst + (y + dstYoff) * dstStride,
9235c4bbdfSmrg                    dstStride,
9335c4bbdfSmrg                    (x + dstXoff) * dstBpp,
9435c4bbdfSmrg                    dstBpp, width * dstBpp, height, pPriv->and, pPriv->xor);
9535c4bbdfSmrg        break;
9605b261ecSmrg    case FillStippled:
9735c4bbdfSmrg    case FillOpaqueStippled:{
9835c4bbdfSmrg        PixmapPtr pStip = pGC->stipple;
9935c4bbdfSmrg        int stipWidth = pStip->drawable.width;
10035c4bbdfSmrg        int stipHeight = pStip->drawable.height;
10135c4bbdfSmrg
10235c4bbdfSmrg        if (dstBpp == 1) {
10335c4bbdfSmrg            int alu;
10435c4bbdfSmrg            FbBits *stip;
10535c4bbdfSmrg            FbStride stipStride;
10635c4bbdfSmrg            int stipBpp;
10735c4bbdfSmrg            _X_UNUSED int stipXoff, stipYoff;
10835c4bbdfSmrg
10935c4bbdfSmrg            if (pGC->fillStyle == FillStippled)
11035c4bbdfSmrg                alu = FbStipple1Rop(pGC->alu, pGC->fgPixel);
11135c4bbdfSmrg            else
11235c4bbdfSmrg                alu = FbOpaqueStipple1Rop(pGC->alu, pGC->fgPixel, pGC->bgPixel);
11335c4bbdfSmrg            fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff,
11435c4bbdfSmrg                          stipYoff);
11535c4bbdfSmrg            fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff,
11635c4bbdfSmrg                   width, height, stip, stipStride, stipWidth, stipHeight, alu,
11735c4bbdfSmrg                   pPriv->pm, dstBpp, (pGC->patOrg.x + pDrawable->x + dstXoff),
11835c4bbdfSmrg                   pGC->patOrg.y + pDrawable->y - y);
11935c4bbdfSmrg            fbFinishAccess(&pStip->drawable);
12035c4bbdfSmrg        }
12135c4bbdfSmrg        else {
12235c4bbdfSmrg            FbStip *stip;
12335c4bbdfSmrg            FbStride stipStride;
12435c4bbdfSmrg            int stipBpp;
12535c4bbdfSmrg            _X_UNUSED int stipXoff, stipYoff;
12635c4bbdfSmrg            FbBits fgand, fgxor, bgand, bgxor;
12735c4bbdfSmrg
12835c4bbdfSmrg            fgand = pPriv->and;
12935c4bbdfSmrg            fgxor = pPriv->xor;
13035c4bbdfSmrg            if (pGC->fillStyle == FillStippled) {
13135c4bbdfSmrg                bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
13235c4bbdfSmrg                bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
13335c4bbdfSmrg            }
13435c4bbdfSmrg            else {
13535c4bbdfSmrg                bgand = pPriv->bgand;
13635c4bbdfSmrg                bgxor = pPriv->bgxor;
13735c4bbdfSmrg            }
13835c4bbdfSmrg
13935c4bbdfSmrg            fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp,
14035c4bbdfSmrg                              stipXoff, stipYoff);
14135c4bbdfSmrg            fbStipple(dst + (y + dstYoff) * dstStride, dstStride,
14235c4bbdfSmrg                      (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height,
14335c4bbdfSmrg                      stip, stipStride, stipWidth, stipHeight,
14435c4bbdfSmrg                      fgand, fgxor, bgand, bgxor,
14535c4bbdfSmrg                      pGC->patOrg.x + pDrawable->x + dstXoff,
14635c4bbdfSmrg                      pGC->patOrg.y + pDrawable->y - y);
14735c4bbdfSmrg            fbFinishAccess(&pStip->drawable);
14835c4bbdfSmrg        }
14935c4bbdfSmrg        break;
15005b261ecSmrg    }
15135c4bbdfSmrg    case FillTiled:{
15235c4bbdfSmrg        PixmapPtr pTile = pGC->tile.pixmap;
15335c4bbdfSmrg        FbBits *tile;
15435c4bbdfSmrg        FbStride tileStride;
15535c4bbdfSmrg        int tileBpp;
15635c4bbdfSmrg        int tileWidth;
15735c4bbdfSmrg        int tileHeight;
15835c4bbdfSmrg        _X_UNUSED int tileXoff, tileYoff;
15935c4bbdfSmrg
16035c4bbdfSmrg        fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff,
16135c4bbdfSmrg                      tileYoff);
16235c4bbdfSmrg        tileWidth = pTile->drawable.width;
16335c4bbdfSmrg        tileHeight = pTile->drawable.height;
16435c4bbdfSmrg        fbTile(dst + (y + dstYoff) * dstStride,
16535c4bbdfSmrg               dstStride,
16635c4bbdfSmrg               (x + dstXoff) * dstBpp,
16735c4bbdfSmrg               width * dstBpp, height,
16835c4bbdfSmrg               tile,
16935c4bbdfSmrg               tileStride,
17035c4bbdfSmrg               tileWidth * tileBpp,
17135c4bbdfSmrg               tileHeight,
17235c4bbdfSmrg               pGC->alu,
17335c4bbdfSmrg               pPriv->pm,
17435c4bbdfSmrg               dstBpp,
17535c4bbdfSmrg               (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp,
17635c4bbdfSmrg               pGC->patOrg.y + pDrawable->y - y);
17735c4bbdfSmrg        fbFinishAccess(&pTile->drawable);
17835c4bbdfSmrg        break;
17905b261ecSmrg    }
18005b261ecSmrg    }
18135c4bbdfSmrg    fbValidateDrawable(pDrawable);
18235c4bbdfSmrg    fbFinishAccess(pDrawable);
18305b261ecSmrg}
18405b261ecSmrg
18505b261ecSmrgvoid
18635c4bbdfSmrgfbSolidBoxClipped(DrawablePtr pDrawable,
18735c4bbdfSmrg                  RegionPtr pClip,
18835c4bbdfSmrg                  int x1, int y1, int x2, int y2, FbBits and, FbBits xor)
18905b261ecSmrg{
19035c4bbdfSmrg    FbBits *dst;
19135c4bbdfSmrg    FbStride dstStride;
19235c4bbdfSmrg    int dstBpp;
19335c4bbdfSmrg    int dstXoff, dstYoff;
19435c4bbdfSmrg    BoxPtr pbox;
19535c4bbdfSmrg    int nbox;
19635c4bbdfSmrg    int partX1, partX2, partY1, partY2;
19735c4bbdfSmrg
19835c4bbdfSmrg    fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
19935c4bbdfSmrg
2006747b715Smrg    for (nbox = RegionNumRects(pClip), pbox = RegionRects(pClip);
20135c4bbdfSmrg         nbox--; pbox++) {
20235c4bbdfSmrg        partX1 = pbox->x1;
20335c4bbdfSmrg        if (partX1 < x1)
20435c4bbdfSmrg            partX1 = x1;
20535c4bbdfSmrg
20635c4bbdfSmrg        partX2 = pbox->x2;
20735c4bbdfSmrg        if (partX2 > x2)
20835c4bbdfSmrg            partX2 = x2;
20935c4bbdfSmrg
21035c4bbdfSmrg        if (partX2 <= partX1)
21135c4bbdfSmrg            continue;
21235c4bbdfSmrg
21335c4bbdfSmrg        partY1 = pbox->y1;
21435c4bbdfSmrg        if (partY1 < y1)
21535c4bbdfSmrg            partY1 = y1;
21635c4bbdfSmrg
21735c4bbdfSmrg        partY2 = pbox->y2;
21835c4bbdfSmrg        if (partY2 > y2)
21935c4bbdfSmrg            partY2 = y2;
22035c4bbdfSmrg
22135c4bbdfSmrg        if (partY2 <= partY1)
22235c4bbdfSmrg            continue;
22305b261ecSmrg
22405b261ecSmrg#ifndef FB_ACCESS_WRAPPER
22535c4bbdfSmrg        if (and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
22635c4bbdfSmrg                                partX1 + dstXoff, partY1 + dstYoff,
22735c4bbdfSmrg                                (partX2 - partX1), (partY2 - partY1), xor))
22805b261ecSmrg#endif
22935c4bbdfSmrg            fbSolid(dst + (partY1 + dstYoff) * dstStride,
23035c4bbdfSmrg                    dstStride,
23135c4bbdfSmrg                    (partX1 + dstXoff) * dstBpp,
23235c4bbdfSmrg                    dstBpp,
23335c4bbdfSmrg                    (partX2 - partX1) * dstBpp, (partY2 - partY1), and, xor);
23405b261ecSmrg    }
23535c4bbdfSmrg    fbFinishAccess(pDrawable);
23605b261ecSmrg}
237