1/* 2 * Copyright © 1998 Keith Packard 3 * Copyright © 2012 Intel Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000) 25#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x))) 26 27static void 28POLYLINE(DrawablePtr drawable, GCPtr gc, int mode, int n_0, DDXPointPtr pt_0) 29{ 30 int xoff = drawable->x; 31 int yoff = drawable->y; 32 unsigned int bias = miGetZeroLineBias(drawable->pScreen); 33 const BoxRec *clip = region_rects(gc->pCompositeClip); 34 const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip); 35 36 FbBits *dst; 37 int dstStride; 38 int dstBpp; 39 int dstXoff, dstYoff; 40 41 BITS *bits, *bitsBase; 42 FbStride bitsStride; 43 BITS xor = fb_gc(gc)->xor; 44 BITS and = fb_gc(gc)->and; 45 46 47 int e, e1, e3, len; 48 int stepmajor, stepminor; 49 int octant; 50 51 if (mode == CoordModePrevious) 52 fbFixCoordModePrevious(n_0, pt_0); 53 54 fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 55 bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); 56 bitsBase = ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); 57 58 DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip))); 59 do { 60 INT32 *pt = (INT32 *)pt_0; 61 int n = n_0; 62 INT32 pt1, pt2; 63 64 INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); 65 INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); 66 67 DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2)); 68 69 pt1 = *pt++; n--; 70 pt2 = *pt++; n--; 71 for (;;) { 72 if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) { 73 int dashoffset = 0; 74 fbSegment1(drawable, gc, clip, 75 intToX(pt1) + xoff, intToY(pt1) + yoff, 76 intToX(pt2) + xoff, intToY(pt2) + yoff, 77 n == 0 && gc->capStyle != CapNotLast, &dashoffset); 78 if (!n) 79 goto next_clip; 80 81 pt1 = pt2; 82 pt2 = *pt++; 83 n--; 84 } else { 85 bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1); 86 for (;;) { 87 CalcLineDeltas(intToX(pt1), intToY(pt1), 88 intToX(pt2), intToY(pt2), 89 len, e1, stepmajor, stepminor, 1, bitsStride, 90 octant); 91 if (len < e1) { 92 e3 = len; 93 len = e1; 94 e1 = e3; 95 96 e3 = stepminor; 97 stepminor = stepmajor; 98 stepmajor = e3; 99 SetYMajorOctant(octant); 100 } 101 e = -len; 102 e1 <<= 1; 103 e3 = e << 1; 104 FIXUP_ERROR(e, octant, bias); 105 if (and == 0) { 106 while (len--) { 107 WRITE(bits, xor); 108 bits += stepmajor; 109 e += e1; 110 if (e >= 0) { 111 bits += stepminor; 112 e += e3; 113 } 114 } 115 } else { 116 while (len--) { 117 RROP(bits, and, xor); 118 bits += stepmajor; 119 e += e1; 120 if (e >= 0) { 121 bits += stepminor; 122 e += e3; 123 } 124 } 125 } 126 if (!n) { 127 if (gc->capStyle != CapNotLast && 128 pt2 != *((INT32 *)pt_0)) { 129 RROP(bits, and, xor); 130 } 131 goto next_clip; 132 } 133 pt1 = pt2; 134 pt2 = *pt++; 135 --n; 136 if (isClipped(pt2, ul, lr)) 137 break; 138 } 139 } 140 } 141next_clip: (void)clip; 142 } while (++clip != last_clip); 143} 144 145static void 146POLYSEGMENT(DrawablePtr drawable, GCPtr gc, int n_0, xSegment *seg_0) 147{ 148 int xoff = drawable->x; 149 int yoff = drawable->y; 150 unsigned int bias = miGetZeroLineBias(drawable->pScreen); 151 const BoxRec *clip = region_rects(gc->pCompositeClip); 152 const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip); 153 154 FbBits *dst; 155 int dstStride; 156 int dstBpp; 157 int dstXoff, dstYoff; 158 159 BITS *bits, *bitsBase; 160 FbStride bitsStride; 161 FbBits xor = fb_gc(gc)->xor; 162 FbBits and = fb_gc(gc)->and; 163 164 int e, e1, e3, len; 165 int stepmajor, stepminor; 166 int octant; 167 bool capNotLast = gc->capStyle == CapNotLast; 168 169 fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 170 bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); 171 bitsBase = 172 ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); 173 174 DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip))); 175 do { 176 INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); 177 INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); 178 uint64_t *pt = (uint64_t *)seg_0; 179 int n = n_0; 180 181 DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2)); 182 183 while (n--) { 184 union { 185 int32_t pt32[2]; 186 uint64_t pt64; 187 } u; 188 189 u.pt64 = *pt++; 190 if (isClipped(u.pt32[0], ul, lr) | isClipped(u.pt32[1], ul, lr)) { 191 int dashoffset = 0; 192 fbSegment1(drawable, gc, clip, 193 intToX(u.pt32[0]) + xoff, intToY(u.pt32[0]) + yoff, 194 intToX(u.pt32[1]) + xoff, intToY(u.pt32[1]) + yoff, 195 !capNotLast, &dashoffset); 196 } else { 197 CalcLineDeltas(intToX(u.pt32[0]), intToY(u.pt32[0]), 198 intToX(u.pt32[1]), intToY(u.pt32[1]), 199 len, e1, stepmajor, stepminor, 1, bitsStride, 200 octant); 201 if (e1 == 0 && len > 3) { 202 int x1, x2; 203 FbBits *dstLine; 204 int dstX, width; 205 FbBits startmask, endmask; 206 int nmiddle; 207 208 if (stepmajor < 0) { 209 x1 = intToX(u.pt32[1]); 210 x2 = intToX(u.pt32[0]) + 1; 211 if (capNotLast) 212 x1++; 213 } else { 214 x1 = intToX(u.pt32[0]); 215 x2 = intToX(u.pt32[1]); 216 if (!capNotLast) 217 x2++; 218 } 219 dstX = (x1 + xoff + dstXoff) * (sizeof(BITS) * 8); 220 width = (x2 - x1) * (sizeof(BITS) * 8); 221 222 dstLine = dst + (intToY(u.pt32[0]) + yoff + dstYoff) * dstStride; 223 dstLine += dstX >> FB_SHIFT; 224 dstX &= FB_MASK; 225 FbMaskBits(dstX, width, startmask, nmiddle, endmask); 226 if (startmask) { 227 WRITE(dstLine, 228 FbDoMaskRRop(READ(dstLine), and, xor, 229 startmask)); 230 dstLine++; 231 } 232 if (!and) 233 while (nmiddle--) 234 WRITE(dstLine++, xor); 235 else 236 while (nmiddle--) { 237 WRITE(dstLine, 238 FbDoRRop(READ(dstLine), and, xor)); 239 dstLine++; 240 } 241 if (endmask) 242 WRITE(dstLine, 243 FbDoMaskRRop(READ(dstLine), and, xor, 244 endmask)); 245 } else { 246 bits = bitsBase + intToY(u.pt32[0]) * bitsStride + intToX(u.pt32[0]); 247 if (len < e1) { 248 e3 = len; 249 len = e1; 250 e1 = e3; 251 252 e3 = stepminor; 253 stepminor = stepmajor; 254 stepmajor = e3; 255 SetYMajorOctant(octant); 256 } 257 e = -len; 258 e1 <<= 1; 259 e3 = e << 1; 260 FIXUP_ERROR(e, octant, bias); 261 if (!capNotLast) 262 len++; 263 if (and == 0) { 264 while (len--) { 265 WRITE(bits, xor); 266 bits += stepmajor; 267 e += e1; 268 if (e >= 0) { 269 bits += stepminor; 270 e += e3; 271 } 272 } 273 } else { 274 while (len--) { 275 RROP(bits, and, xor); 276 bits += stepmajor; 277 e += e1; 278 if (e >= 0) { 279 bits += stepminor; 280 e += e3; 281 } 282 } 283 } 284 } 285 } 286 } 287 } while (++clip != last_clip); 288} 289 290#undef RROP 291#undef isClipped 292