xref: /OK3568_Linux_fs/external/xserver/fb/fbfill.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 static void
fbTile(FbBits * dst,FbStride dstStride,int dstX,int width,int height,FbBits * tile,FbStride tileStride,int tileWidth,int tileHeight,int alu,FbBits pm,int bpp,int xRot,int yRot)30 fbTile(FbBits * dst, FbStride dstStride, int dstX, int width, int height,
31        FbBits * tile, FbStride tileStride, int tileWidth, int tileHeight,
32        int alu, FbBits pm, int bpp, int xRot, int yRot)
33 {
34     int tileX, tileY;
35     int widthTmp;
36     int h, w;
37     int x, y;
38 
39     modulus(-yRot, tileHeight, tileY);
40     y = 0;
41     while (height) {
42         h = tileHeight - tileY;
43         if (h > height)
44             h = height;
45         height -= h;
46         widthTmp = width;
47         x = dstX;
48         modulus(dstX - xRot, tileWidth, tileX);
49         while (widthTmp) {
50             w = tileWidth - tileX;
51             if (w > widthTmp)
52                 w = widthTmp;
53             widthTmp -= w;
54             fbBlt(tile + tileY * tileStride,
55                   tileStride,
56                   tileX,
57                   dst + y * dstStride,
58                   dstStride, x, w, h, alu, pm, bpp, FALSE, FALSE);
59             x += w;
60             tileX = 0;
61         }
62         y += h;
63         tileY = 0;
64     }
65 }
66 
67 static void
fbStipple(FbBits * dst,FbStride dstStride,int dstX,int dstBpp,int width,int height,FbStip * stip,FbStride stipStride,int stipWidth,int stipHeight,FbBits fgand,FbBits fgxor,FbBits bgand,FbBits bgxor,int xRot,int yRot)68 fbStipple(FbBits * dst, FbStride dstStride,
69           int dstX, int dstBpp,
70           int width, int height,
71           FbStip * stip, FbStride stipStride,
72           int stipWidth, int stipHeight,
73           FbBits fgand, FbBits fgxor,
74           FbBits bgand, FbBits bgxor,
75           int xRot, int yRot)
76 {
77     int stipX, stipY, sx;
78     int widthTmp;
79     int h, w;
80     int x, y;
81 
82     modulus(-yRot, stipHeight, stipY);
83     modulus(dstX / dstBpp - xRot, stipWidth, stipX);
84     y = 0;
85     while (height) {
86         h = stipHeight - stipY;
87         if (h > height)
88             h = height;
89         height -= h;
90         widthTmp = width;
91         x = dstX;
92         sx = stipX;
93         while (widthTmp) {
94             w = (stipWidth - sx) * dstBpp;
95             if (w > widthTmp)
96                 w = widthTmp;
97             widthTmp -= w;
98             fbBltOne(stip + stipY * stipStride,
99                      stipStride,
100                      sx,
101                      dst + y * dstStride,
102                      dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor);
103             x += w;
104             sx = 0;
105         }
106         y += h;
107         stipY = 0;
108     }
109 }
110 
111 void
fbFill(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int width,int height)112 fbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height)
113 {
114     FbBits *dst;
115     FbStride dstStride;
116     int dstBpp;
117     int dstXoff, dstYoff;
118     FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
119 
120     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
121 
122     switch (pGC->fillStyle) {
123     case FillSolid:
124 #ifndef FB_ACCESS_WRAPPER
125         if (pPriv->and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
126                                        x + dstXoff, y + dstYoff,
127                                        width, height, pPriv->xor))
128 #endif
129             fbSolid(dst + (y + dstYoff) * dstStride,
130                     dstStride,
131                     (x + dstXoff) * dstBpp,
132                     dstBpp, width * dstBpp, height, pPriv->and, pPriv->xor);
133         break;
134     case FillStippled:
135     case FillOpaqueStippled:{
136         PixmapPtr pStip = pGC->stipple;
137         int stipWidth = pStip->drawable.width;
138         int stipHeight = pStip->drawable.height;
139 
140         if (dstBpp == 1) {
141             int alu;
142             FbBits *stip;
143             FbStride stipStride;
144             int stipBpp;
145             _X_UNUSED int stipXoff, stipYoff;
146 
147             if (pGC->fillStyle == FillStippled)
148                 alu = FbStipple1Rop(pGC->alu, pGC->fgPixel);
149             else
150                 alu = FbOpaqueStipple1Rop(pGC->alu, pGC->fgPixel, pGC->bgPixel);
151             fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff,
152                           stipYoff);
153             fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff,
154                    width, height, stip, stipStride, stipWidth, stipHeight, alu,
155                    pPriv->pm, dstBpp, (pGC->patOrg.x + pDrawable->x + dstXoff),
156                    pGC->patOrg.y + pDrawable->y - y);
157             fbFinishAccess(&pStip->drawable);
158         }
159         else {
160             FbStip *stip;
161             FbStride stipStride;
162             int stipBpp;
163             _X_UNUSED int stipXoff, stipYoff;
164             FbBits fgand, fgxor, bgand, bgxor;
165 
166             fgand = pPriv->and;
167             fgxor = pPriv->xor;
168             if (pGC->fillStyle == FillStippled) {
169                 bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
170                 bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
171             }
172             else {
173                 bgand = pPriv->bgand;
174                 bgxor = pPriv->bgxor;
175             }
176 
177             fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp,
178                               stipXoff, stipYoff);
179             fbStipple(dst + (y + dstYoff) * dstStride, dstStride,
180                       (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height,
181                       stip, stipStride, stipWidth, stipHeight,
182                       fgand, fgxor, bgand, bgxor,
183                       pGC->patOrg.x + pDrawable->x + dstXoff,
184                       pGC->patOrg.y + pDrawable->y - y);
185             fbFinishAccess(&pStip->drawable);
186         }
187         break;
188     }
189     case FillTiled:{
190         PixmapPtr pTile = pGC->tile.pixmap;
191         FbBits *tile;
192         FbStride tileStride;
193         int tileBpp;
194         int tileWidth;
195         int tileHeight;
196         _X_UNUSED int tileXoff, tileYoff;
197 
198         fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff,
199                       tileYoff);
200         tileWidth = pTile->drawable.width;
201         tileHeight = pTile->drawable.height;
202         fbTile(dst + (y + dstYoff) * dstStride,
203                dstStride,
204                (x + dstXoff) * dstBpp,
205                width * dstBpp, height,
206                tile,
207                tileStride,
208                tileWidth * tileBpp,
209                tileHeight,
210                pGC->alu,
211                pPriv->pm,
212                dstBpp,
213                (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp,
214                pGC->patOrg.y + pDrawable->y - y);
215         fbFinishAccess(&pTile->drawable);
216         break;
217     }
218     }
219     fbValidateDrawable(pDrawable);
220     fbFinishAccess(pDrawable);
221 }
222 
223 void
fbSolidBoxClipped(DrawablePtr pDrawable,RegionPtr pClip,int x1,int y1,int x2,int y2,FbBits and,FbBits xor)224 fbSolidBoxClipped(DrawablePtr pDrawable,
225                   RegionPtr pClip,
226                   int x1, int y1, int x2, int y2, FbBits and, FbBits xor)
227 {
228     FbBits *dst;
229     FbStride dstStride;
230     int dstBpp;
231     int dstXoff, dstYoff;
232     BoxPtr pbox;
233     int nbox;
234     int partX1, partX2, partY1, partY2;
235 
236     fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
237 
238     for (nbox = RegionNumRects(pClip), pbox = RegionRects(pClip);
239          nbox--; pbox++) {
240         partX1 = pbox->x1;
241         if (partX1 < x1)
242             partX1 = x1;
243 
244         partX2 = pbox->x2;
245         if (partX2 > x2)
246             partX2 = x2;
247 
248         if (partX2 <= partX1)
249             continue;
250 
251         partY1 = pbox->y1;
252         if (partY1 < y1)
253             partY1 = y1;
254 
255         partY2 = pbox->y2;
256         if (partY2 > y2)
257             partY2 = y2;
258 
259         if (partY2 <= partY1)
260             continue;
261 
262 #ifndef FB_ACCESS_WRAPPER
263         if (and || !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
264                                 partX1 + dstXoff, partY1 + dstYoff,
265                                 (partX2 - partX1), (partY2 - partY1), xor))
266 #endif
267             fbSolid(dst + (partY1 + dstYoff) * dstStride,
268                     dstStride,
269                     (partX1 + dstXoff) * dstBpp,
270                     dstBpp,
271                     (partX2 - partX1) * dstBpp, (partY2 - partY1), and, xor);
272     }
273     fbFinishAccess(pDrawable);
274 }
275