diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-06 15:22:26 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-08 21:34:21 +0100 |
commit | e3e58123d36924c760ab6f58a7155a040422e91d (patch) | |
tree | 683b2db2d53d8abe790d34e431ddc7747d5639ff /src/sna/fb/fblinebits.h | |
parent | 5d2f88fd9972c62c87098ddc7fee7b6f0cea0fdb (diff) |
sna: Fixup fb wrapper
To accommodate changes in the Xserver and avoid breakage; would have been
much easier had the fb been exported in the first place.
Diffstat (limited to 'src/sna/fb/fblinebits.h')
-rw-r--r-- | src/sna/fb/fblinebits.h | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/sna/fb/fblinebits.h b/src/sna/fb/fblinebits.h new file mode 100644 index 00000000..db315d81 --- /dev/null +++ b/src/sna/fb/fblinebits.h @@ -0,0 +1,284 @@ +/* + * Copyright © 1998 Keith Packard + * Copyright © 2012 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#define isClipped(c,ul,lr) (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000) +#define RROP(b,a,x) WRITE((b), FbDoRRop (READ(b), (a), (x))) + +static void +POLYLINE(DrawablePtr drawable, GCPtr gc, int mode, int n_0, DDXPointPtr pt_0) +{ + int xoff = drawable->x; + int yoff = drawable->y; + unsigned int bias = miGetZeroLineBias(drawable->pScreen); + const BoxRec *clip = RegionRects(gc->pCompositeClip); + const BoxRec *const last_clip = clip + RegionNumRects(gc->pCompositeClip); + + FbBits *dst; + int dstStride; + int dstBpp; + int dstXoff, dstYoff; + + BITS *bits, *bitsBase; + FbStride bitsStride; + BITS xor = fb_gc(gc)->xor; + BITS and = fb_gc(gc)->and; + + + int e, e1, e3, len; + int stepmajor, stepminor; + int octant; + + if (mode == CoordModePrevious) + fbFixCoordModePrevious(n_0, pt_0); + + fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); + bitsBase = + ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); + do { + INT32 *pt = (INT32 *)pt_0; + int n = n_0; + INT32 pt1, pt2; + + INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); + INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); + + pt1 = *pt++; n--; + pt2 = *pt++; n--; + for (;;) { + if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) { + int dashoffset = 0; + fbSegment1(drawable, gc, clip, + intToX(pt1) + xoff, intToY(pt1) + yoff, + intToX(pt2) + xoff, intToY(pt2) + yoff, + n == 0 && gc->capStyle != CapNotLast, &dashoffset); + if (!n) + return; + + pt1 = pt2; + pt2 = *pt++; + n--; + } else { + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1); + for (;;) { + CalcLineDeltas(intToX(pt1), intToY(pt1), + intToX(pt2), intToY(pt2), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + if (len < e1) { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR(e, octant, bias); + if (and == 0) { + while (len--) { + WRITE(bits, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } else { + while (len--) { + RROP(bits, and, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + if (!n) { + if (gc->capStyle != CapNotLast && + pt2 != *((INT32 *)pt_0)) { + RROP(bits, and, xor); + } + return; + } + pt1 = pt2; + pt2 = *pt++; + --n; + if (isClipped(pt2, ul, lr)) + break; + } + } + } + } while (++clip != last_clip); +} + +static void +POLYSEGMENT(DrawablePtr drawable, GCPtr gc, int n_0, xSegment *seg_0) +{ + int xoff = drawable->x; + int yoff = drawable->y; + unsigned int bias = miGetZeroLineBias(drawable->pScreen); + const BoxRec *clip = RegionRects(gc->pCompositeClip); + const BoxRec *const last_clip = clip + RegionNumRects(gc->pCompositeClip); + + FbBits *dst; + int dstStride; + int dstBpp; + int dstXoff, dstYoff; + + BITS *bits, *bitsBase; + FbStride bitsStride; + FbBits xor = fb_gc(gc)->xor; + FbBits and = fb_gc(gc)->and; + + int e, e1, e3, len; + int stepmajor, stepminor; + int octant; + bool capNotLast = gc->capStyle == CapNotLast; + + fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS)); + bitsBase = + ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); + + do { + INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff); + INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1); + uint64_t *pt = (uint64_t *)seg_0; + int n = n_0; + + while (n--) { + union { + int32_t pt32[2]; + uint64_t pt64; + } u; + + u.pt64 = *pt++; + if (isClipped(u.pt32[0], ul, lr) | isClipped(u.pt32[1], ul, lr)) { + int dashoffset = 0; + fbSegment1(drawable, gc, clip, + intToX(u.pt32[0]) + xoff, intToY(u.pt32[0]) + yoff, + intToX(u.pt32[1]) + xoff, intToY(u.pt32[1]) + yoff, + !capNotLast, &dashoffset); + } else { + CalcLineDeltas(intToX(u.pt32[0]), intToY(u.pt32[0]), + intToX(u.pt32[1]), intToY(u.pt32[1]), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + if (e1 == 0 && len > 3) { + int x1, x2; + FbBits *dstLine; + int dstX, width; + FbBits startmask, endmask; + int nmiddle; + + if (stepmajor < 0) { + x1 = intToX(u.pt32[1]); + x2 = intToX(u.pt32[0]) + 1; + if (capNotLast) + x1++; + } else { + x1 = intToX(u.pt32[0]); + x2 = intToX(u.pt32[1]); + if (!capNotLast) + x2++; + } + dstX = (x1 + xoff + dstXoff) * (sizeof(BITS) * 8); + width = (x2 - x1) * (sizeof(BITS) * 8); + + dstLine = dst + (intToY(u.pt32[0]) + yoff + dstYoff) * dstStride; + dstLine += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBits(dstX, width, startmask, nmiddle, endmask); + if (startmask) { + WRITE(dstLine, + FbDoMaskRRop(READ(dstLine), and, xor, + startmask)); + dstLine++; + } + if (!and) + while (nmiddle--) + WRITE(dstLine++, xor); + else + while (nmiddle--) { + WRITE(dstLine, + FbDoRRop(READ(dstLine), and, xor)); + dstLine++; + } + if (endmask) + WRITE(dstLine, + FbDoMaskRRop(READ(dstLine), and, xor, + endmask)); + } else { + bits = bitsBase + intToY(u.pt32[0]) * bitsStride + intToX(u.pt32[0]); + if (len < e1) { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR(e, octant, bias); + if (!capNotLast) + len++; + if (and == 0) { + while (len--) { + WRITE(bits, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } else { + while (len--) { + RROP(bits, and, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + } + } + } + } while (++clip != last_clip); +} + +#undef RROP +#undef isClipped |