1706f2543Smrg/* 2706f2543Smrg * Copyright © 1998 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that 7706f2543Smrg * copyright notice and this permission notice appear in supporting 8706f2543Smrg * documentation, and that the name of Keith Packard not be used in 9706f2543Smrg * advertising or publicity pertaining to distribution of the software without 10706f2543Smrg * specific, written prior permission. Keith Packard makes no 11706f2543Smrg * representations about the suitability of this software for any purpose. It 12706f2543Smrg * is provided "as is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 24706f2543Smrg#include <dix-config.h> 25706f2543Smrg#endif 26706f2543Smrg 27706f2543Smrg#include "fb.h" 28706f2543Smrg 29706f2543Smrg#ifndef FBNOPIXADDR 30706f2543Smrg/* 31706f2543Smrg * This is a slight abuse of the preprocessor to generate repetitive 32706f2543Smrg * code, the idea is to generate code for each case of a copy-mode 33706f2543Smrg * transparent stipple 34706f2543Smrg */ 35706f2543Smrg#define LaneCases1(c,a) case c: \ 36706f2543Smrg while (n--) { FbLaneCase(c,a); a++; } \ 37706f2543Smrg break 38706f2543Smrg#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) 39706f2543Smrg#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) 40706f2543Smrg#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) 41706f2543Smrg#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) 42706f2543Smrg#define LaneCases32(c,a) LaneCases16(c,a); LaneCases16(c+16,a) 43706f2543Smrg#define LaneCases64(c,a) LaneCases32(c,a); LaneCases32(c+32,a) 44706f2543Smrg#define LaneCases128(c,a) LaneCases64(c,a); LaneCases64(c+64,a) 45706f2543Smrg#define LaneCases256(c,a) LaneCases128(c,a); LaneCases128(c+128,a) 46706f2543Smrg 47706f2543Smrg#if FB_SHIFT == 6 48706f2543Smrg#define LaneCases(a) LaneCases256(0,a) 49706f2543Smrg#endif 50706f2543Smrg 51706f2543Smrg#if FB_SHIFT == 5 52706f2543Smrg#define LaneCases(a) LaneCases16(0,a) 53706f2543Smrg#endif 54706f2543Smrg 55706f2543Smrg/* 56706f2543Smrg * Repeat a transparent stipple across a scanline n times 57706f2543Smrg */ 58706f2543Smrg 59706f2543Smrgvoid 60706f2543SmrgfbTransparentSpan (FbBits *dst, 61706f2543Smrg FbBits stip, 62706f2543Smrg FbBits fgxor, 63706f2543Smrg int n) 64706f2543Smrg{ 65706f2543Smrg FbStip s; 66706f2543Smrg 67706f2543Smrg s = ((FbStip) (stip ) & 0x01); 68706f2543Smrg s |= ((FbStip) (stip >> 8) & 0x02); 69706f2543Smrg s |= ((FbStip) (stip >> 16) & 0x04); 70706f2543Smrg s |= ((FbStip) (stip >> 24) & 0x08); 71706f2543Smrg#if FB_SHIFT > 5 72706f2543Smrg s |= ((FbStip) (stip >> 32) & 0x10); 73706f2543Smrg s |= ((FbStip) (stip >> 40) & 0x20); 74706f2543Smrg s |= ((FbStip) (stip >> 48) & 0x40); 75706f2543Smrg s |= ((FbStip) (stip >> 56) & 0x80); 76706f2543Smrg#endif 77706f2543Smrg switch (s) { 78706f2543Smrg LaneCases(dst); 79706f2543Smrg } 80706f2543Smrg} 81706f2543Smrg#endif 82706f2543Smrg 83706f2543Smrgvoid 84706f2543SmrgfbEvenStipple (FbBits *dst, 85706f2543Smrg FbStride dstStride, 86706f2543Smrg int dstX, 87706f2543Smrg int dstBpp, 88706f2543Smrg 89706f2543Smrg int width, 90706f2543Smrg int height, 91706f2543Smrg 92706f2543Smrg FbStip *stip, 93706f2543Smrg FbStride stipStride, 94706f2543Smrg int stipHeight, 95706f2543Smrg 96706f2543Smrg FbBits fgand, 97706f2543Smrg FbBits fgxor, 98706f2543Smrg FbBits bgand, 99706f2543Smrg FbBits bgxor, 100706f2543Smrg 101706f2543Smrg int xRot, 102706f2543Smrg int yRot) 103706f2543Smrg{ 104706f2543Smrg FbBits startmask, endmask; 105706f2543Smrg FbBits mask, and, xor; 106706f2543Smrg int nmiddle, n; 107706f2543Smrg FbStip *s, *stipEnd, bits; 108706f2543Smrg int rot, stipX, stipY; 109706f2543Smrg int pixelsPerDst; 110706f2543Smrg const FbBits *fbBits; 111706f2543Smrg Bool transparent; 112706f2543Smrg int startbyte, endbyte; 113706f2543Smrg 114706f2543Smrg /* 115706f2543Smrg * Check for a transparent stipple (stencil) 116706f2543Smrg */ 117706f2543Smrg transparent = FALSE; 118706f2543Smrg if (dstBpp >= 8 && 119706f2543Smrg fgand == 0 && bgand == FB_ALLONES && bgxor == 0) 120706f2543Smrg transparent = TRUE; 121706f2543Smrg 122706f2543Smrg pixelsPerDst = FB_UNIT / dstBpp; 123706f2543Smrg /* 124706f2543Smrg * Adjust dest pointers 125706f2543Smrg */ 126706f2543Smrg dst += dstX >> FB_SHIFT; 127706f2543Smrg dstX &= FB_MASK; 128706f2543Smrg FbMaskBitsBytes (dstX, width, fgand == 0 && bgand == 0, 129706f2543Smrg startmask, startbyte, nmiddle, endmask, endbyte); 130706f2543Smrg 131706f2543Smrg if (startmask) 132706f2543Smrg dstStride--; 133706f2543Smrg dstStride -= nmiddle; 134706f2543Smrg 135706f2543Smrg xRot *= dstBpp; 136706f2543Smrg /* 137706f2543Smrg * Compute stip start scanline and rotation parameters 138706f2543Smrg */ 139706f2543Smrg stipEnd = stip + stipStride * stipHeight; 140706f2543Smrg modulus (- yRot, stipHeight, stipY); 141706f2543Smrg s = stip + stipStride * stipY; 142706f2543Smrg modulus (- xRot, FB_UNIT, stipX); 143706f2543Smrg rot = stipX; 144706f2543Smrg 145706f2543Smrg /* 146706f2543Smrg * Get pointer to stipple mask array for this depth 147706f2543Smrg */ 148706f2543Smrg /* fbStippleTable covers all valid bpp (4,8,16,32) */ 149706f2543Smrg fbBits = fbStippleTable[pixelsPerDst]; 150706f2543Smrg 151706f2543Smrg while (height--) 152706f2543Smrg { 153706f2543Smrg /* 154706f2543Smrg * Extract stipple bits for this scanline; 155706f2543Smrg */ 156706f2543Smrg bits = READ(s); 157706f2543Smrg s += stipStride; 158706f2543Smrg if (s == stipEnd) 159706f2543Smrg s = stip; 160706f2543Smrg#if FB_UNIT > 32 161706f2543Smrg if (pixelsPerDst == 16) 162706f2543Smrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 163706f2543Smrg else 164706f2543Smrg#endif 165706f2543Smrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 166706f2543Smrg /* 167706f2543Smrg * Rotate into position and compute reduced rop values 168706f2543Smrg */ 169706f2543Smrg mask = FbRotLeft(mask, rot); 170706f2543Smrg and = (fgand & mask) | (bgand & ~mask); 171706f2543Smrg xor = (fgxor & mask) | (bgxor & ~mask); 172706f2543Smrg 173706f2543Smrg#ifndef FBNOPIXADDR 174706f2543Smrg if (transparent) 175706f2543Smrg { 176706f2543Smrg if (startmask) 177706f2543Smrg { 178706f2543Smrg fbTransparentSpan(dst, mask&startmask, fgxor, 1); 179706f2543Smrg dst++; 180706f2543Smrg } 181706f2543Smrg fbTransparentSpan (dst, mask, fgxor, nmiddle); 182706f2543Smrg dst += nmiddle; 183706f2543Smrg if (endmask) 184706f2543Smrg fbTransparentSpan(dst, mask&endmask, fgxor, 1); 185706f2543Smrg } 186706f2543Smrg else 187706f2543Smrg#endif 188706f2543Smrg { 189706f2543Smrg /* 190706f2543Smrg * Fill scanline 191706f2543Smrg */ 192706f2543Smrg if (startmask) 193706f2543Smrg { 194706f2543Smrg FbDoLeftMaskByteRRop (dst, startbyte, startmask, and, xor); 195706f2543Smrg dst++; 196706f2543Smrg } 197706f2543Smrg n = nmiddle; 198706f2543Smrg if (!and) 199706f2543Smrg while (n--) 200706f2543Smrg WRITE(dst++, xor); 201706f2543Smrg else 202706f2543Smrg { 203706f2543Smrg while (n--) 204706f2543Smrg { 205706f2543Smrg WRITE(dst, FbDoRRop (READ(dst), and, xor)); 206706f2543Smrg dst++; 207706f2543Smrg } 208706f2543Smrg } 209706f2543Smrg if (endmask) 210706f2543Smrg FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); 211706f2543Smrg } 212706f2543Smrg dst += dstStride; 213706f2543Smrg } 214706f2543Smrg} 215706f2543Smrg 216706f2543Smrgvoid 217706f2543SmrgfbOddStipple (FbBits *dst, 218706f2543Smrg FbStride dstStride, 219706f2543Smrg int dstX, 220706f2543Smrg int dstBpp, 221706f2543Smrg 222706f2543Smrg int width, 223706f2543Smrg int height, 224706f2543Smrg 225706f2543Smrg FbStip *stip, 226706f2543Smrg FbStride stipStride, 227706f2543Smrg int stipWidth, 228706f2543Smrg int stipHeight, 229706f2543Smrg 230706f2543Smrg FbBits fgand, 231706f2543Smrg FbBits fgxor, 232706f2543Smrg FbBits bgand, 233706f2543Smrg FbBits bgxor, 234706f2543Smrg 235706f2543Smrg int xRot, 236706f2543Smrg int yRot) 237706f2543Smrg{ 238706f2543Smrg int stipX, stipY, sx; 239706f2543Smrg int widthTmp; 240706f2543Smrg int h, w; 241706f2543Smrg int x, y; 242706f2543Smrg 243706f2543Smrg modulus (- yRot, stipHeight, stipY); 244706f2543Smrg modulus (dstX / dstBpp - xRot, stipWidth, stipX); 245706f2543Smrg y = 0; 246706f2543Smrg while (height) 247706f2543Smrg { 248706f2543Smrg h = stipHeight - stipY; 249706f2543Smrg if (h > height) 250706f2543Smrg h = height; 251706f2543Smrg height -= h; 252706f2543Smrg widthTmp = width; 253706f2543Smrg x = dstX; 254706f2543Smrg sx = stipX; 255706f2543Smrg while (widthTmp) 256706f2543Smrg { 257706f2543Smrg w = (stipWidth - sx) * dstBpp; 258706f2543Smrg if (w > widthTmp) 259706f2543Smrg w = widthTmp; 260706f2543Smrg widthTmp -= w; 261706f2543Smrg fbBltOne (stip + stipY * stipStride, 262706f2543Smrg stipStride, 263706f2543Smrg sx, 264706f2543Smrg 265706f2543Smrg dst + y * dstStride, 266706f2543Smrg dstStride, 267706f2543Smrg x, 268706f2543Smrg dstBpp, 269706f2543Smrg 270706f2543Smrg w, h, 271706f2543Smrg 272706f2543Smrg fgand, fgxor, bgand, bgxor); 273706f2543Smrg x += w; 274706f2543Smrg sx = 0; 275706f2543Smrg } 276706f2543Smrg y += h; 277706f2543Smrg stipY = 0; 278706f2543Smrg } 279706f2543Smrg} 280706f2543Smrg 281706f2543Smrgvoid 282706f2543SmrgfbStipple (FbBits *dst, 283706f2543Smrg FbStride dstStride, 284706f2543Smrg int dstX, 285706f2543Smrg int dstBpp, 286706f2543Smrg 287706f2543Smrg int width, 288706f2543Smrg int height, 289706f2543Smrg 290706f2543Smrg FbStip *stip, 291706f2543Smrg FbStride stipStride, 292706f2543Smrg int stipWidth, 293706f2543Smrg int stipHeight, 294706f2543Smrg Bool even, 295706f2543Smrg 296706f2543Smrg FbBits fgand, 297706f2543Smrg FbBits fgxor, 298706f2543Smrg FbBits bgand, 299706f2543Smrg FbBits bgxor, 300706f2543Smrg 301706f2543Smrg int xRot, 302706f2543Smrg int yRot) 303706f2543Smrg{ 304706f2543Smrg if (even) 305706f2543Smrg fbEvenStipple (dst, dstStride, dstX, dstBpp, width, height, 306706f2543Smrg stip, stipStride, stipHeight, 307706f2543Smrg fgand, fgxor, bgand, bgxor, xRot, yRot); 308706f2543Smrg else 309706f2543Smrg fbOddStipple (dst, dstStride, dstX, dstBpp, width, height, 310706f2543Smrg stip, stipStride, stipWidth, stipHeight, 311706f2543Smrg fgand, fgxor, bgand, bgxor, xRot, yRot); 312706f2543Smrg} 313