fbfill.c revision 35c4bbdf
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 29static void 30fbTile(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 67static void 68fbStipple(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 111void 112fbFill(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 223void 224fbSolidBoxClipped(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