1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 1998 Keith Packard 3428d7b3dSmrg * Copyright © 2012 Intel Corporation 4428d7b3dSmrg * 5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that 7428d7b3dSmrg * the above copyright notice appear in all copies and that both that 8428d7b3dSmrg * copyright notice and this permission notice appear in supporting 9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in 10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without 11428d7b3dSmrg * specific, written prior permission. Keith Packard makes no 12428d7b3dSmrg * representations about the suitability of this software for any purpose. It 13428d7b3dSmrg * is provided "as is" without express or implied warranty. 14428d7b3dSmrg * 15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE. 22428d7b3dSmrg */ 23428d7b3dSmrg 24428d7b3dSmrg#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000) 25428d7b3dSmrg#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x))) 26428d7b3dSmrg 27428d7b3dSmrgstatic void 28428d7b3dSmrgPOLYLINE(DrawablePtr drawable, GCPtr gc, int mode, int n_0, DDXPointPtr pt_0) 29428d7b3dSmrg{ 30428d7b3dSmrg int xoff = drawable->x; 31428d7b3dSmrg int yoff = drawable->y; 32428d7b3dSmrg unsigned int bias = miGetZeroLineBias(drawable->pScreen); 33428d7b3dSmrg const BoxRec *clip = region_rects(gc->pCompositeClip); 34428d7b3dSmrg const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip); 35428d7b3dSmrg 36428d7b3dSmrg FbBits *dst; 37428d7b3dSmrg int dstStride; 38428d7b3dSmrg int dstBpp; 39428d7b3dSmrg int dstXoff, dstYoff; 40428d7b3dSmrg 41428d7b3dSmrg BITS *bits, *bitsBase; 42428d7b3dSmrg FbStride bitsStride; 43428d7b3dSmrg BITS xor = fb_gc(gc)->xor; 44428d7b3dSmrg BITS and = fb_gc(gc)->and; 45428d7b3dSmrg 46428d7b3dSmrg 47428d7b3dSmrg int e, e1, e3, len; 48428d7b3dSmrg int stepmajor, stepminor; 49428d7b3dSmrg int octant; 50428d7b3dSmrg 51428d7b3dSmrg if (mode == CoordModePrevious) 52428d7b3dSmrg fbFixCoordModePrevious(n_0, pt_0); 53428d7b3dSmrg 54428d7b3dSmrg fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 55428d7b3dSmrg bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); 56428d7b3dSmrg bitsBase = ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); 57428d7b3dSmrg 58428d7b3dSmrg DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip))); 59428d7b3dSmrg do { 60428d7b3dSmrg INT32 *pt = (INT32 *)pt_0; 61428d7b3dSmrg int n = n_0; 62428d7b3dSmrg INT32 pt1, pt2; 63428d7b3dSmrg 64428d7b3dSmrg INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); 65428d7b3dSmrg INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); 66428d7b3dSmrg 67428d7b3dSmrg DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2)); 68428d7b3dSmrg 69428d7b3dSmrg pt1 = *pt++; n--; 70428d7b3dSmrg pt2 = *pt++; n--; 71428d7b3dSmrg for (;;) { 72428d7b3dSmrg if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) { 73428d7b3dSmrg int dashoffset = 0; 74428d7b3dSmrg fbSegment1(drawable, gc, clip, 75428d7b3dSmrg intToX(pt1) + xoff, intToY(pt1) + yoff, 76428d7b3dSmrg intToX(pt2) + xoff, intToY(pt2) + yoff, 77428d7b3dSmrg n == 0 && gc->capStyle != CapNotLast, &dashoffset); 78428d7b3dSmrg if (!n) 79428d7b3dSmrg goto next_clip; 80428d7b3dSmrg 81428d7b3dSmrg pt1 = pt2; 82428d7b3dSmrg pt2 = *pt++; 83428d7b3dSmrg n--; 84428d7b3dSmrg } else { 85428d7b3dSmrg bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1); 86428d7b3dSmrg for (;;) { 87428d7b3dSmrg CalcLineDeltas(intToX(pt1), intToY(pt1), 88428d7b3dSmrg intToX(pt2), intToY(pt2), 89428d7b3dSmrg len, e1, stepmajor, stepminor, 1, bitsStride, 90428d7b3dSmrg octant); 91428d7b3dSmrg if (len < e1) { 92428d7b3dSmrg e3 = len; 93428d7b3dSmrg len = e1; 94428d7b3dSmrg e1 = e3; 95428d7b3dSmrg 96428d7b3dSmrg e3 = stepminor; 97428d7b3dSmrg stepminor = stepmajor; 98428d7b3dSmrg stepmajor = e3; 99428d7b3dSmrg SetYMajorOctant(octant); 100428d7b3dSmrg } 101428d7b3dSmrg e = -len; 102428d7b3dSmrg e1 <<= 1; 103428d7b3dSmrg e3 = e << 1; 104428d7b3dSmrg FIXUP_ERROR(e, octant, bias); 105428d7b3dSmrg if (and == 0) { 106428d7b3dSmrg while (len--) { 107428d7b3dSmrg WRITE(bits, xor); 108428d7b3dSmrg bits += stepmajor; 109428d7b3dSmrg e += e1; 110428d7b3dSmrg if (e >= 0) { 111428d7b3dSmrg bits += stepminor; 112428d7b3dSmrg e += e3; 113428d7b3dSmrg } 114428d7b3dSmrg } 115428d7b3dSmrg } else { 116428d7b3dSmrg while (len--) { 117428d7b3dSmrg RROP(bits, and, xor); 118428d7b3dSmrg bits += stepmajor; 119428d7b3dSmrg e += e1; 120428d7b3dSmrg if (e >= 0) { 121428d7b3dSmrg bits += stepminor; 122428d7b3dSmrg e += e3; 123428d7b3dSmrg } 124428d7b3dSmrg } 125428d7b3dSmrg } 126428d7b3dSmrg if (!n) { 127428d7b3dSmrg if (gc->capStyle != CapNotLast && 128428d7b3dSmrg pt2 != *((INT32 *)pt_0)) { 129428d7b3dSmrg RROP(bits, and, xor); 130428d7b3dSmrg } 131428d7b3dSmrg goto next_clip; 132428d7b3dSmrg } 133428d7b3dSmrg pt1 = pt2; 134428d7b3dSmrg pt2 = *pt++; 135428d7b3dSmrg --n; 136428d7b3dSmrg if (isClipped(pt2, ul, lr)) 137428d7b3dSmrg break; 138428d7b3dSmrg } 139428d7b3dSmrg } 140428d7b3dSmrg } 141428d7b3dSmrgnext_clip: (void)clip; 142428d7b3dSmrg } while (++clip != last_clip); 143428d7b3dSmrg} 144428d7b3dSmrg 145428d7b3dSmrgstatic void 146428d7b3dSmrgPOLYSEGMENT(DrawablePtr drawable, GCPtr gc, int n_0, xSegment *seg_0) 147428d7b3dSmrg{ 148428d7b3dSmrg int xoff = drawable->x; 149428d7b3dSmrg int yoff = drawable->y; 150428d7b3dSmrg unsigned int bias = miGetZeroLineBias(drawable->pScreen); 151428d7b3dSmrg const BoxRec *clip = region_rects(gc->pCompositeClip); 152428d7b3dSmrg const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip); 153428d7b3dSmrg 154428d7b3dSmrg FbBits *dst; 155428d7b3dSmrg int dstStride; 156428d7b3dSmrg int dstBpp; 157428d7b3dSmrg int dstXoff, dstYoff; 158428d7b3dSmrg 159428d7b3dSmrg BITS *bits, *bitsBase; 160428d7b3dSmrg FbStride bitsStride; 161428d7b3dSmrg FbBits xor = fb_gc(gc)->xor; 162428d7b3dSmrg FbBits and = fb_gc(gc)->and; 163428d7b3dSmrg 164428d7b3dSmrg int e, e1, e3, len; 165428d7b3dSmrg int stepmajor, stepminor; 166428d7b3dSmrg int octant; 167428d7b3dSmrg bool capNotLast = gc->capStyle == CapNotLast; 168428d7b3dSmrg 169428d7b3dSmrg fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 170428d7b3dSmrg bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); 171428d7b3dSmrg bitsBase = 172428d7b3dSmrg ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); 173428d7b3dSmrg 174428d7b3dSmrg DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip))); 175428d7b3dSmrg do { 176428d7b3dSmrg INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); 177428d7b3dSmrg INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); 178428d7b3dSmrg uint64_t *pt = (uint64_t *)seg_0; 179428d7b3dSmrg int n = n_0; 180428d7b3dSmrg 181428d7b3dSmrg DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2)); 182428d7b3dSmrg 183428d7b3dSmrg while (n--) { 184428d7b3dSmrg union { 185428d7b3dSmrg int32_t pt32[2]; 186428d7b3dSmrg uint64_t pt64; 187428d7b3dSmrg } u; 188428d7b3dSmrg 189428d7b3dSmrg u.pt64 = *pt++; 190428d7b3dSmrg if (isClipped(u.pt32[0], ul, lr) | isClipped(u.pt32[1], ul, lr)) { 191428d7b3dSmrg int dashoffset = 0; 192428d7b3dSmrg fbSegment1(drawable, gc, clip, 193428d7b3dSmrg intToX(u.pt32[0]) + xoff, intToY(u.pt32[0]) + yoff, 194428d7b3dSmrg intToX(u.pt32[1]) + xoff, intToY(u.pt32[1]) + yoff, 195428d7b3dSmrg !capNotLast, &dashoffset); 196428d7b3dSmrg } else { 197428d7b3dSmrg CalcLineDeltas(intToX(u.pt32[0]), intToY(u.pt32[0]), 198428d7b3dSmrg intToX(u.pt32[1]), intToY(u.pt32[1]), 199428d7b3dSmrg len, e1, stepmajor, stepminor, 1, bitsStride, 200428d7b3dSmrg octant); 201428d7b3dSmrg if (e1 == 0 && len > 3) { 202428d7b3dSmrg int x1, x2; 203428d7b3dSmrg FbBits *dstLine; 204428d7b3dSmrg int dstX, width; 205428d7b3dSmrg FbBits startmask, endmask; 206428d7b3dSmrg int nmiddle; 207428d7b3dSmrg 208428d7b3dSmrg if (stepmajor < 0) { 209428d7b3dSmrg x1 = intToX(u.pt32[1]); 210428d7b3dSmrg x2 = intToX(u.pt32[0]) + 1; 211428d7b3dSmrg if (capNotLast) 212428d7b3dSmrg x1++; 213428d7b3dSmrg } else { 214428d7b3dSmrg x1 = intToX(u.pt32[0]); 215428d7b3dSmrg x2 = intToX(u.pt32[1]); 216428d7b3dSmrg if (!capNotLast) 217428d7b3dSmrg x2++; 218428d7b3dSmrg } 219428d7b3dSmrg dstX = (x1 + xoff + dstXoff) * (sizeof(BITS) * 8); 220428d7b3dSmrg width = (x2 - x1) * (sizeof(BITS) * 8); 221428d7b3dSmrg 222428d7b3dSmrg dstLine = dst + (intToY(u.pt32[0]) + yoff + dstYoff) * dstStride; 223428d7b3dSmrg dstLine += dstX >> FB_SHIFT; 224428d7b3dSmrg dstX &= FB_MASK; 225428d7b3dSmrg FbMaskBits(dstX, width, startmask, nmiddle, endmask); 226428d7b3dSmrg if (startmask) { 227428d7b3dSmrg WRITE(dstLine, 228428d7b3dSmrg FbDoMaskRRop(READ(dstLine), and, xor, 229428d7b3dSmrg startmask)); 230428d7b3dSmrg dstLine++; 231428d7b3dSmrg } 232428d7b3dSmrg if (!and) 233428d7b3dSmrg while (nmiddle--) 234428d7b3dSmrg WRITE(dstLine++, xor); 235428d7b3dSmrg else 236428d7b3dSmrg while (nmiddle--) { 237428d7b3dSmrg WRITE(dstLine, 238428d7b3dSmrg FbDoRRop(READ(dstLine), and, xor)); 239428d7b3dSmrg dstLine++; 240428d7b3dSmrg } 241428d7b3dSmrg if (endmask) 242428d7b3dSmrg WRITE(dstLine, 243428d7b3dSmrg FbDoMaskRRop(READ(dstLine), and, xor, 244428d7b3dSmrg endmask)); 245428d7b3dSmrg } else { 246428d7b3dSmrg bits = bitsBase + intToY(u.pt32[0]) * bitsStride + intToX(u.pt32[0]); 247428d7b3dSmrg if (len < e1) { 248428d7b3dSmrg e3 = len; 249428d7b3dSmrg len = e1; 250428d7b3dSmrg e1 = e3; 251428d7b3dSmrg 252428d7b3dSmrg e3 = stepminor; 253428d7b3dSmrg stepminor = stepmajor; 254428d7b3dSmrg stepmajor = e3; 255428d7b3dSmrg SetYMajorOctant(octant); 256428d7b3dSmrg } 257428d7b3dSmrg e = -len; 258428d7b3dSmrg e1 <<= 1; 259428d7b3dSmrg e3 = e << 1; 260428d7b3dSmrg FIXUP_ERROR(e, octant, bias); 261428d7b3dSmrg if (!capNotLast) 262428d7b3dSmrg len++; 263428d7b3dSmrg if (and == 0) { 264428d7b3dSmrg while (len--) { 265428d7b3dSmrg WRITE(bits, xor); 266428d7b3dSmrg bits += stepmajor; 267428d7b3dSmrg e += e1; 268428d7b3dSmrg if (e >= 0) { 269428d7b3dSmrg bits += stepminor; 270428d7b3dSmrg e += e3; 271428d7b3dSmrg } 272428d7b3dSmrg } 273428d7b3dSmrg } else { 274428d7b3dSmrg while (len--) { 275428d7b3dSmrg RROP(bits, and, xor); 276428d7b3dSmrg bits += stepmajor; 277428d7b3dSmrg e += e1; 278428d7b3dSmrg if (e >= 0) { 279428d7b3dSmrg bits += stepminor; 280428d7b3dSmrg e += e3; 281428d7b3dSmrg } 282428d7b3dSmrg } 283428d7b3dSmrg } 284428d7b3dSmrg } 285428d7b3dSmrg } 286428d7b3dSmrg } 287428d7b3dSmrg } while (++clip != last_clip); 288428d7b3dSmrg} 289428d7b3dSmrg 290428d7b3dSmrg#undef RROP 291428d7b3dSmrg#undef isClipped 292