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 "fb.h"
28
29/*
30 * Accelerated tile fill -- tile width is a power of two not greater
31 * than FB_UNIT
32 */
33
34void
35fbEvenTile(FbBits * dst,
36           FbStride dstStride,
37           int dstX,
38           int width,
39           int height,
40           FbBits * tile,
41           FbStride tileStride,
42           int tileHeight, int alu, FbBits pm, int xRot, int yRot)
43{
44    FbBits *t, *tileEnd, bits;
45    FbBits startmask, endmask;
46    FbBits and, xor;
47    int n, nmiddle;
48    int tileX, tileY;
49    int rot;
50    int startbyte, endbyte;
51
52    dst += dstX >> FB_SHIFT;
53    dstX &= FB_MASK;
54    FbMaskBitsBytes(dstX, width, FbDestInvarientRop(alu, pm),
55                    startmask, startbyte, nmiddle, endmask, endbyte);
56    if (startmask)
57        dstStride--;
58    dstStride -= nmiddle;
59
60    /*
61     * Compute tile start scanline and rotation parameters
62     */
63    tileEnd = tile + tileHeight * tileStride;
64    modulus(-yRot, tileHeight, tileY);
65    t = tile + tileY * tileStride;
66    modulus(-xRot, FB_UNIT, tileX);
67    rot = tileX;
68
69    while (height--) {
70
71        /*
72         * Pick up bits for this scanline
73         */
74        bits = READ(t);
75        t += tileStride;
76        if (t >= tileEnd)
77            t = tile;
78        bits = FbRotLeft(bits, rot);
79        and = fbAnd(alu, bits, pm);
80        xor = fbXor(alu, bits, pm);
81
82        if (startmask) {
83            FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
84            dst++;
85        }
86        n = nmiddle;
87        if (!and)
88            while (n--)
89                WRITE(dst++, xor);
90        else
91            while (n--) {
92                WRITE(dst, FbDoRRop(READ(dst), and, xor));
93                dst++;
94            }
95        if (endmask)
96            FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
97        dst += dstStride;
98    }
99}
100
101void
102fbOddTile(FbBits * dst,
103          FbStride dstStride,
104          int dstX,
105          int width,
106          int height,
107          FbBits * tile,
108          FbStride tileStride,
109          int tileWidth,
110          int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot)
111{
112    int tileX, tileY;
113    int widthTmp;
114    int h, w;
115    int x, y;
116
117    modulus(-yRot, tileHeight, tileY);
118    y = 0;
119    while (height) {
120        h = tileHeight - tileY;
121        if (h > height)
122            h = height;
123        height -= h;
124        widthTmp = width;
125        x = dstX;
126        modulus(dstX - xRot, tileWidth, tileX);
127        while (widthTmp) {
128            w = tileWidth - tileX;
129            if (w > widthTmp)
130                w = widthTmp;
131            widthTmp -= w;
132            fbBlt(tile + tileY * tileStride,
133                  tileStride,
134                  tileX,
135                  dst + y * dstStride,
136                  dstStride, x, w, h, alu, pm, bpp, FALSE, FALSE);
137            x += w;
138            tileX = 0;
139        }
140        y += h;
141        tileY = 0;
142    }
143}
144
145void
146fbTile(FbBits * dst,
147       FbStride dstStride,
148       int dstX,
149       int width,
150       int height,
151       FbBits * tile,
152       FbStride tileStride,
153       int tileWidth,
154       int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot)
155{
156    if (FbEvenTile(tileWidth))
157        fbEvenTile(dst, dstStride, dstX, width, height,
158                   tile, tileStride, tileHeight, alu, pm, xRot, yRot);
159    else
160        fbOddTile(dst, dstStride, dstX, width, height,
161                  tile, tileStride, tileWidth, tileHeight,
162                  alu, pm, bpp, xRot, yRot);
163}
164