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/* 30706f2543Smrg * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) 31706f2543Smrg * 32706f2543Smrg * **** **** **** **** **** **** **** **** 33706f2543Smrg * ^ 34706f2543Smrg * ******** ******** ******** ******** 35706f2543Smrg * ^ 36706f2543Smrg * leftShift = 12 37706f2543Smrg * rightShift = 20 38706f2543Smrg * 39706f2543Smrg * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) 40706f2543Smrg * 41706f2543Smrg * **** **** **** **** **** **** **** **** 42706f2543Smrg * ^ 43706f2543Smrg * ******** ******** ******** ******** 44706f2543Smrg * ^ 45706f2543Smrg * 46706f2543Smrg * leftShift = 24 47706f2543Smrg * rightShift = 8 48706f2543Smrg */ 49706f2543Smrg 50706f2543Smrg#define LoadBits {\ 51706f2543Smrg if (leftShift) { \ 52706f2543Smrg bitsRight = (src < srcEnd ? READ(src++) : 0); \ 53706f2543Smrg bits = (FbStipLeft (bitsLeft, leftShift) | \ 54706f2543Smrg FbStipRight(bitsRight, rightShift)); \ 55706f2543Smrg bitsLeft = bitsRight; \ 56706f2543Smrg } else \ 57706f2543Smrg bits = (src < srcEnd ? READ(src++) : 0); \ 58706f2543Smrg} 59706f2543Smrg 60706f2543Smrg#ifndef FBNOPIXADDR 61706f2543Smrg 62706f2543Smrg#define LaneCases1(n,a) case n: FbLaneCase(n,a); break 63706f2543Smrg#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a) 64706f2543Smrg#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a) 65706f2543Smrg#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a) 66706f2543Smrg#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a) 67706f2543Smrg#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a) 68706f2543Smrg#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a) 69706f2543Smrg#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a) 70706f2543Smrg#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a) 71706f2543Smrg 72706f2543Smrg#if FB_SHIFT == 6 73706f2543Smrg#define LaneCases(a) LaneCases256(0,a) 74706f2543Smrg#endif 75706f2543Smrg 76706f2543Smrg#if FB_SHIFT == 5 77706f2543Smrg#define LaneCases(a) LaneCases16(0,a) 78706f2543Smrg#endif 79706f2543Smrg 80706f2543Smrg#if FB_SHIFT == 6 81706f2543SmrgCARD8 fb8Lane[256] = { 82706f2543Smrg0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 83706f2543Smrg22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 84706f2543Smrg41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 85706f2543Smrg60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 86706f2543Smrg79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 87706f2543Smrg98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115, 88706f2543Smrg116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, 89706f2543Smrg134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, 90706f2543Smrg152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169, 91706f2543Smrg170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, 92706f2543Smrg188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, 93706f2543Smrg206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 94706f2543Smrg224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241, 95706f2543Smrg242, 243, 244,245,246,247,248,249,250,251,252,253,254,255, 96706f2543Smrg}; 97706f2543Smrg 98706f2543SmrgCARD8 fb16Lane[256] = { 99706f2543Smrg 0x00, 0x03, 0x0c, 0x0f, 100706f2543Smrg 0x30, 0x33, 0x3c, 0x3f, 101706f2543Smrg 0xc0, 0xc3, 0xcc, 0xcf, 102706f2543Smrg 0xf0, 0xf3, 0xfc, 0xff, 103706f2543Smrg}; 104706f2543Smrg 105706f2543SmrgCARD8 fb32Lane[16] = { 106706f2543Smrg 0x00, 0x0f, 0xf0, 0xff, 107706f2543Smrg}; 108706f2543Smrg#endif 109706f2543Smrg 110706f2543Smrg#if FB_SHIFT == 5 111706f2543SmrgCARD8 fb8Lane[16] = { 112706f2543Smrg 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 113706f2543Smrg}; 114706f2543Smrg 115706f2543SmrgCARD8 fb16Lane[16] = { 116706f2543Smrg 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117706f2543Smrg}; 118706f2543Smrg 119706f2543SmrgCARD8 fb32Lane[16] = { 120706f2543Smrg 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121706f2543Smrg}; 122706f2543Smrg#endif 123706f2543Smrg 124706f2543SmrgCARD8 *fbLaneTable[33] = { 125706f2543Smrg 0, 0, 0, 0, 0, 0, 0, 0, 126706f2543Smrg fb8Lane, 0, 0, 0, 0, 0, 0, 0, 127706f2543Smrg fb16Lane, 0, 0, 0, 0, 0, 0, 0, 128706f2543Smrg 0, 0, 0, 0, 0, 0, 0, 0, 129706f2543Smrg fb32Lane 130706f2543Smrg}; 131706f2543Smrg#endif 132706f2543Smrg 133706f2543Smrgvoid 134706f2543SmrgfbBltOne (FbStip *src, 135706f2543Smrg FbStride srcStride, /* FbStip units per scanline */ 136706f2543Smrg int srcX, /* bit position of source */ 137706f2543Smrg FbBits *dst, 138706f2543Smrg FbStride dstStride, /* FbBits units per scanline */ 139706f2543Smrg int dstX, /* bit position of dest */ 140706f2543Smrg int dstBpp, /* bits per destination unit */ 141706f2543Smrg 142706f2543Smrg int width, /* width in bits of destination */ 143706f2543Smrg int height, /* height in scanlines */ 144706f2543Smrg 145706f2543Smrg FbBits fgand, /* rrop values */ 146706f2543Smrg FbBits fgxor, 147706f2543Smrg FbBits bgand, 148706f2543Smrg FbBits bgxor) 149706f2543Smrg{ 150706f2543Smrg const FbBits *fbBits; 151706f2543Smrg FbBits *srcEnd; 152706f2543Smrg int pixelsPerDst; /* dst pixels per FbBits */ 153706f2543Smrg int unitsPerSrc; /* src patterns per FbStip */ 154706f2543Smrg int leftShift, rightShift; /* align source with dest */ 155706f2543Smrg FbBits startmask, endmask; /* dest scanline masks */ 156706f2543Smrg FbStip bits=0, bitsLeft, bitsRight;/* source bits */ 157706f2543Smrg FbStip left; 158706f2543Smrg FbBits mask; 159706f2543Smrg int nDst; /* dest longwords (w.o. end) */ 160706f2543Smrg int w; 161706f2543Smrg int n, nmiddle; 162706f2543Smrg int dstS; /* stipple-relative dst X coordinate */ 163706f2543Smrg Bool copy; /* accelerate dest-invariant */ 164706f2543Smrg Bool transparent; /* accelerate 0 nop */ 165706f2543Smrg int srcinc; /* source units consumed */ 166706f2543Smrg Bool endNeedsLoad = FALSE; /* need load for endmask */ 167706f2543Smrg#ifndef FBNOPIXADDR 168706f2543Smrg CARD8 *fbLane; 169706f2543Smrg#endif 170706f2543Smrg int startbyte, endbyte; 171706f2543Smrg 172706f2543Smrg#ifdef FB_24BIT 173706f2543Smrg if (dstBpp == 24) 174706f2543Smrg { 175706f2543Smrg fbBltOne24 (src, srcStride, srcX, 176706f2543Smrg dst, dstStride, dstX, dstBpp, 177706f2543Smrg width, height, 178706f2543Smrg fgand, fgxor, bgand, bgxor); 179706f2543Smrg return; 180706f2543Smrg } 181706f2543Smrg#endif 182706f2543Smrg 183706f2543Smrg /* 184706f2543Smrg * Do not read past the end of the buffer! 185706f2543Smrg */ 186706f2543Smrg srcEnd = src + height * srcStride; 187706f2543Smrg 188706f2543Smrg /* 189706f2543Smrg * Number of destination units in FbBits == number of stipple pixels 190706f2543Smrg * used each time 191706f2543Smrg */ 192706f2543Smrg pixelsPerDst = FB_UNIT / dstBpp; 193706f2543Smrg 194706f2543Smrg /* 195706f2543Smrg * Number of source stipple patterns in FbStip 196706f2543Smrg */ 197706f2543Smrg unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 198706f2543Smrg 199706f2543Smrg copy = FALSE; 200706f2543Smrg transparent = FALSE; 201706f2543Smrg if (bgand == 0 && fgand == 0) 202706f2543Smrg copy = TRUE; 203706f2543Smrg else if (bgand == FB_ALLONES && bgxor == 0) 204706f2543Smrg transparent = TRUE; 205706f2543Smrg 206706f2543Smrg /* 207706f2543Smrg * Adjust source and dest to nearest FbBits boundary 208706f2543Smrg */ 209706f2543Smrg src += srcX >> FB_STIP_SHIFT; 210706f2543Smrg dst += dstX >> FB_SHIFT; 211706f2543Smrg srcX &= FB_STIP_MASK; 212706f2543Smrg dstX &= FB_MASK; 213706f2543Smrg 214706f2543Smrg FbMaskBitsBytes(dstX, width, copy, 215706f2543Smrg startmask, startbyte, nmiddle, endmask, endbyte); 216706f2543Smrg 217706f2543Smrg /* 218706f2543Smrg * Compute effective dest alignment requirement for 219706f2543Smrg * source -- must align source to dest unit boundary 220706f2543Smrg */ 221706f2543Smrg dstS = dstX / dstBpp; 222706f2543Smrg /* 223706f2543Smrg * Compute shift constants for effective alignement 224706f2543Smrg */ 225706f2543Smrg if (srcX >= dstS) 226706f2543Smrg { 227706f2543Smrg leftShift = srcX - dstS; 228706f2543Smrg rightShift = FB_STIP_UNIT - leftShift; 229706f2543Smrg } 230706f2543Smrg else 231706f2543Smrg { 232706f2543Smrg rightShift = dstS - srcX; 233706f2543Smrg leftShift = FB_STIP_UNIT - rightShift; 234706f2543Smrg } 235706f2543Smrg /* 236706f2543Smrg * Get pointer to stipple mask array for this depth 237706f2543Smrg */ 238706f2543Smrg fbBits = 0; /* unused */ 239706f2543Smrg if (pixelsPerDst <= 8) 240706f2543Smrg fbBits = fbStippleTable[pixelsPerDst]; 241706f2543Smrg#ifndef FBNOPIXADDR 242706f2543Smrg fbLane = 0; 243706f2543Smrg if (transparent && fgand == 0 && dstBpp >= 8) 244706f2543Smrg fbLane = fbLaneTable[dstBpp]; 245706f2543Smrg#endif 246706f2543Smrg 247706f2543Smrg /* 248706f2543Smrg * Compute total number of destination words written, but 249706f2543Smrg * don't count endmask 250706f2543Smrg */ 251706f2543Smrg nDst = nmiddle; 252706f2543Smrg if (startmask) 253706f2543Smrg nDst++; 254706f2543Smrg 255706f2543Smrg dstStride -= nDst; 256706f2543Smrg 257706f2543Smrg /* 258706f2543Smrg * Compute total number of source words consumed 259706f2543Smrg */ 260706f2543Smrg 261706f2543Smrg srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 262706f2543Smrg 263706f2543Smrg if (srcX > dstS) 264706f2543Smrg srcinc++; 265706f2543Smrg if (endmask) 266706f2543Smrg { 267706f2543Smrg endNeedsLoad = nDst % unitsPerSrc == 0; 268706f2543Smrg if (endNeedsLoad) 269706f2543Smrg srcinc++; 270706f2543Smrg } 271706f2543Smrg 272706f2543Smrg srcStride -= srcinc; 273706f2543Smrg 274706f2543Smrg /* 275706f2543Smrg * Copy rectangle 276706f2543Smrg */ 277706f2543Smrg while (height--) 278706f2543Smrg { 279706f2543Smrg w = nDst; /* total units across scanline */ 280706f2543Smrg n = unitsPerSrc; /* units avail in single stipple */ 281706f2543Smrg if (n > w) 282706f2543Smrg n = w; 283706f2543Smrg 284706f2543Smrg bitsLeft = 0; 285706f2543Smrg if (srcX > dstS) 286706f2543Smrg bitsLeft = READ(src++); 287706f2543Smrg if (n) 288706f2543Smrg { 289706f2543Smrg /* 290706f2543Smrg * Load first set of stipple bits 291706f2543Smrg */ 292706f2543Smrg LoadBits; 293706f2543Smrg 294706f2543Smrg /* 295706f2543Smrg * Consume stipple bits for startmask 296706f2543Smrg */ 297706f2543Smrg if (startmask) 298706f2543Smrg { 299706f2543Smrg#if FB_UNIT > 32 300706f2543Smrg if (pixelsPerDst == 16) 301706f2543Smrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 302706f2543Smrg else 303706f2543Smrg#endif 304706f2543Smrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 305706f2543Smrg#ifndef FBNOPIXADDR 306706f2543Smrg if (fbLane) 307706f2543Smrg { 308706f2543Smrg fbTransparentSpan (dst, mask & startmask, fgxor, 1); 309706f2543Smrg } 310706f2543Smrg else 311706f2543Smrg#endif 312706f2543Smrg { 313706f2543Smrg if (mask || !transparent) 314706f2543Smrg FbDoLeftMaskByteStippleRRop (dst, mask, 315706f2543Smrg fgand, fgxor, bgand, bgxor, 316706f2543Smrg startbyte, startmask); 317706f2543Smrg } 318706f2543Smrg bits = FbStipLeft (bits, pixelsPerDst); 319706f2543Smrg dst++; 320706f2543Smrg n--; 321706f2543Smrg w--; 322706f2543Smrg } 323706f2543Smrg /* 324706f2543Smrg * Consume stipple bits across scanline 325706f2543Smrg */ 326706f2543Smrg for (;;) 327706f2543Smrg { 328706f2543Smrg w -= n; 329706f2543Smrg if (copy) 330706f2543Smrg { 331706f2543Smrg while (n--) 332706f2543Smrg { 333706f2543Smrg#if FB_UNIT > 32 334706f2543Smrg if (pixelsPerDst == 16) 335706f2543Smrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 336706f2543Smrg else 337706f2543Smrg#endif 338706f2543Smrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 339706f2543Smrg WRITE(dst, FbOpaqueStipple (mask, fgxor, bgxor)); 340706f2543Smrg dst++; 341706f2543Smrg bits = FbStipLeft(bits, pixelsPerDst); 342706f2543Smrg } 343706f2543Smrg } 344706f2543Smrg else 345706f2543Smrg { 346706f2543Smrg#ifndef FBNOPIXADDR 347706f2543Smrg if (fbLane) 348706f2543Smrg { 349706f2543Smrg while (bits && n) 350706f2543Smrg { 351706f2543Smrg switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) { 352706f2543Smrg LaneCases((CARD8 *) dst); 353706f2543Smrg } 354706f2543Smrg bits = FbStipLeft(bits,pixelsPerDst); 355706f2543Smrg dst++; 356706f2543Smrg n--; 357706f2543Smrg } 358706f2543Smrg dst += n; 359706f2543Smrg } 360706f2543Smrg else 361706f2543Smrg#endif 362706f2543Smrg { 363706f2543Smrg while (n--) 364706f2543Smrg { 365706f2543Smrg left = FbLeftStipBits(bits,pixelsPerDst); 366706f2543Smrg if (left || !transparent) 367706f2543Smrg { 368706f2543Smrg mask = fbBits[left]; 369706f2543Smrg WRITE(dst, FbStippleRRop (READ(dst), mask, 370706f2543Smrg fgand, fgxor, bgand, bgxor)); 371706f2543Smrg } 372706f2543Smrg dst++; 373706f2543Smrg bits = FbStipLeft(bits, pixelsPerDst); 374706f2543Smrg } 375706f2543Smrg } 376706f2543Smrg } 377706f2543Smrg if (!w) 378706f2543Smrg break; 379706f2543Smrg /* 380706f2543Smrg * Load another set and reset number of available units 381706f2543Smrg */ 382706f2543Smrg LoadBits; 383706f2543Smrg n = unitsPerSrc; 384706f2543Smrg if (n > w) 385706f2543Smrg n = w; 386706f2543Smrg } 387706f2543Smrg } 388706f2543Smrg /* 389706f2543Smrg * Consume stipple bits for endmask 390706f2543Smrg */ 391706f2543Smrg if (endmask) 392706f2543Smrg { 393706f2543Smrg if (endNeedsLoad) 394706f2543Smrg { 395706f2543Smrg LoadBits; 396706f2543Smrg } 397706f2543Smrg#if FB_UNIT > 32 398706f2543Smrg if (pixelsPerDst == 16) 399706f2543Smrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 400706f2543Smrg else 401706f2543Smrg#endif 402706f2543Smrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 403706f2543Smrg#ifndef FBNOPIXADDR 404706f2543Smrg if (fbLane) 405706f2543Smrg { 406706f2543Smrg fbTransparentSpan (dst, mask & endmask, fgxor, 1); 407706f2543Smrg } 408706f2543Smrg else 409706f2543Smrg#endif 410706f2543Smrg { 411706f2543Smrg if (mask || !transparent) 412706f2543Smrg FbDoRightMaskByteStippleRRop (dst, mask, 413706f2543Smrg fgand, fgxor, bgand, bgxor, 414706f2543Smrg endbyte, endmask); 415706f2543Smrg } 416706f2543Smrg } 417706f2543Smrg dst += dstStride; 418706f2543Smrg src += srcStride; 419706f2543Smrg } 420706f2543Smrg} 421706f2543Smrg 422706f2543Smrg#ifdef FB_24BIT 423706f2543Smrg 424706f2543Smrg/* 425706f2543Smrg * Crufty macros to initialize the mask array, most of this 426706f2543Smrg * is to avoid compile-time warnings about shift overflow 427706f2543Smrg */ 428706f2543Smrg 429706f2543Smrg#if BITMAP_BIT_ORDER == MSBFirst 430706f2543Smrg#define Mask24Pos(x,r) ((x)*24-(r)) 431706f2543Smrg#else 432706f2543Smrg#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) 433706f2543Smrg#endif 434706f2543Smrg 435706f2543Smrg#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) 436706f2543Smrg#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ 437706f2543Smrg Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) 438706f2543Smrg 439706f2543Smrg#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ 440706f2543Smrg (Mask24Pos(x,r) < 0 ? \ 441706f2543Smrg 0xffffffU >> Mask24Neg (x,r) : \ 442706f2543Smrg 0xffffffU << Mask24Check(x,r)) : 0) 443706f2543Smrg 444706f2543Smrg#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) 445706f2543Smrg 446706f2543Smrg/* 447706f2543Smrg * Untested for MSBFirst or FB_UNIT == 32 448706f2543Smrg */ 449706f2543Smrg 450706f2543Smrg#if FB_UNIT == 64 451706f2543Smrg#define C4_24(b,r) \ 452706f2543Smrg (SelMask24(b,0,r) | \ 453706f2543Smrg SelMask24(b,1,r) | \ 454706f2543Smrg SelMask24(b,2,r) | \ 455706f2543Smrg SelMask24(b,3,r)) 456706f2543Smrg 457706f2543Smrg#define FbStip24New(rot) (2 + (rot != 0)) 458706f2543Smrg#define FbStip24Len 4 459706f2543Smrg 460706f2543Smrgconst FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 461706f2543Smrg /* rotate 0 */ 462706f2543Smrg { 463706f2543Smrg C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0), 464706f2543Smrg C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0), 465706f2543Smrg C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0), 466706f2543Smrg C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0), 467706f2543Smrg }, 468706f2543Smrg /* rotate 8 */ 469706f2543Smrg { 470706f2543Smrg C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8), 471706f2543Smrg C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8), 472706f2543Smrg C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8), 473706f2543Smrg C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8), 474706f2543Smrg }, 475706f2543Smrg /* rotate 16 */ 476706f2543Smrg { 477706f2543Smrg C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16), 478706f2543Smrg C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16), 479706f2543Smrg C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16), 480706f2543Smrg C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16), 481706f2543Smrg } 482706f2543Smrg}; 483706f2543Smrg 484706f2543Smrg#endif 485706f2543Smrg 486706f2543Smrg#if FB_UNIT == 32 487706f2543Smrg#define C2_24(b,r) \ 488706f2543Smrg (SelMask24(b,0,r) | \ 489706f2543Smrg SelMask24(b,1,r)) 490706f2543Smrg 491706f2543Smrg#define FbStip24Len 2 492706f2543Smrg#if BITMAP_BIT_ORDER == MSBFirst 493706f2543Smrg#define FbStip24New(rot) (1 + (rot == 0)) 494706f2543Smrg#else 495706f2543Smrg#define FbStip24New(rot) (1 + (rot == 8)) 496706f2543Smrg#endif 497706f2543Smrg 498706f2543Smrgconst FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 499706f2543Smrg /* rotate 0 */ 500706f2543Smrg { 501706f2543Smrg C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0), 502706f2543Smrg }, 503706f2543Smrg /* rotate 8 */ 504706f2543Smrg { 505706f2543Smrg C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8), 506706f2543Smrg }, 507706f2543Smrg /* rotate 16 */ 508706f2543Smrg { 509706f2543Smrg C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16), 510706f2543Smrg } 511706f2543Smrg}; 512706f2543Smrg#endif 513706f2543Smrg 514706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst 515706f2543Smrg 516706f2543Smrg#define FbMergeStip24Bits(left, right, new) \ 517706f2543Smrg (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) 518706f2543Smrg 519706f2543Smrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 520706f2543Smrg (left | FbStipRight(right, llen)) 521706f2543Smrg 522706f2543Smrg#else 523706f2543Smrg 524706f2543Smrg#define FbMergeStip24Bits(left, right, new) \ 525706f2543Smrg ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) 526706f2543Smrg 527706f2543Smrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 528706f2543Smrg (FbStipLeft(left, rlen) | right) 529706f2543Smrg 530706f2543Smrg#endif 531706f2543Smrg 532706f2543Smrg#define fbFirstStipBits(len,stip) {\ 533706f2543Smrg int __len = (len); \ 534706f2543Smrg if (len <= remain) { \ 535706f2543Smrg stip = FbLeftStipBits(bits, len); \ 536706f2543Smrg } else { \ 537706f2543Smrg stip = FbLeftStipBits(bits, remain); \ 538706f2543Smrg bits = (src < srcEnd ? READ(src++) : 0); \ 539706f2543Smrg __len = (len) - remain; \ 540706f2543Smrg stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ 541706f2543Smrg remain, __len); \ 542706f2543Smrg remain = FB_STIP_UNIT; \ 543706f2543Smrg } \ 544706f2543Smrg bits = FbStipLeft (bits, __len); \ 545706f2543Smrg remain -= __len; \ 546706f2543Smrg} 547706f2543Smrg 548706f2543Smrg#define fbInitStipBits(offset,len,stip) {\ 549706f2543Smrg bits = FbStipLeft (READ(src++),offset); \ 550706f2543Smrg remain = FB_STIP_UNIT - offset; \ 551706f2543Smrg fbFirstStipBits(len,stip); \ 552706f2543Smrg stip = FbMergeStip24Bits (0, stip, len); \ 553706f2543Smrg} 554706f2543Smrg 555706f2543Smrg#define fbNextStipBits(rot,stip) {\ 556706f2543Smrg int __new = FbStip24New(rot); \ 557706f2543Smrg FbStip __right; \ 558706f2543Smrg fbFirstStipBits(__new, __right); \ 559706f2543Smrg stip = FbMergeStip24Bits (stip, __right, __new); \ 560706f2543Smrg rot = FbNext24Rot (rot); \ 561706f2543Smrg} 562706f2543Smrg 563706f2543Smrg/* 564706f2543Smrg * Use deep mask tables that incorporate rotation, pull 565706f2543Smrg * a variable number of bits out of the stipple and 566706f2543Smrg * reuse the right bits as needed for the next write 567706f2543Smrg * 568706f2543Smrg * Yes, this is probably too much code, but most 24-bpp screens 569706f2543Smrg * have no acceleration so this code is used for stipples, copyplane 570706f2543Smrg * and text 571706f2543Smrg */ 572706f2543Smrgvoid 573706f2543SmrgfbBltOne24 (FbStip *srcLine, 574706f2543Smrg FbStride srcStride, /* FbStip units per scanline */ 575706f2543Smrg int srcX, /* bit position of source */ 576706f2543Smrg FbBits *dst, 577706f2543Smrg FbStride dstStride, /* FbBits units per scanline */ 578706f2543Smrg int dstX, /* bit position of dest */ 579706f2543Smrg int dstBpp, /* bits per destination unit */ 580706f2543Smrg 581706f2543Smrg int width, /* width in bits of destination */ 582706f2543Smrg int height, /* height in scanlines */ 583706f2543Smrg 584706f2543Smrg FbBits fgand, /* rrop values */ 585706f2543Smrg FbBits fgxor, 586706f2543Smrg FbBits bgand, 587706f2543Smrg FbBits bgxor) 588706f2543Smrg{ 589706f2543Smrg FbStip *src, *srcEnd; 590706f2543Smrg FbBits leftMask, rightMask, mask; 591706f2543Smrg int nlMiddle, nl; 592706f2543Smrg FbStip stip, bits; 593706f2543Smrg int remain; 594706f2543Smrg int dstS; 595706f2543Smrg int firstlen; 596706f2543Smrg int rot0, rot; 597706f2543Smrg int nDst; 598706f2543Smrg 599706f2543Smrg /* 600706f2543Smrg * Do not read past the end of the buffer! 601706f2543Smrg */ 602706f2543Smrg srcEnd = srcLine + height * srcStride; 603706f2543Smrg 604706f2543Smrg srcLine += srcX >> FB_STIP_SHIFT; 605706f2543Smrg dst += dstX >> FB_SHIFT; 606706f2543Smrg srcX &= FB_STIP_MASK; 607706f2543Smrg dstX &= FB_MASK; 608706f2543Smrg rot0 = FbFirst24Rot (dstX); 609706f2543Smrg 610706f2543Smrg FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask); 611706f2543Smrg 612706f2543Smrg dstS = (dstX + 23) / 24; 613706f2543Smrg firstlen = FbStip24Len - dstS; 614706f2543Smrg 615706f2543Smrg nDst = nlMiddle; 616706f2543Smrg if (leftMask) 617706f2543Smrg nDst++; 618706f2543Smrg dstStride -= nDst; 619706f2543Smrg 620706f2543Smrg /* opaque copy */ 621706f2543Smrg if (bgand == 0 && fgand == 0) 622706f2543Smrg { 623706f2543Smrg while (height--) 624706f2543Smrg { 625706f2543Smrg rot = rot0; 626706f2543Smrg src = srcLine; 627706f2543Smrg srcLine += srcStride; 628706f2543Smrg fbInitStipBits (srcX,firstlen, stip); 629706f2543Smrg if (leftMask) 630706f2543Smrg { 631706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip]; 632706f2543Smrg WRITE(dst, (READ(dst) & ~leftMask) | 633706f2543Smrg (FbOpaqueStipple (mask, 634706f2543Smrg FbRot24(fgxor, rot), 635706f2543Smrg FbRot24(bgxor, rot)) 636706f2543Smrg & leftMask)); 637706f2543Smrg dst++; 638706f2543Smrg fbNextStipBits(rot,stip); 639706f2543Smrg } 640706f2543Smrg nl = nlMiddle; 641706f2543Smrg while (nl--) 642706f2543Smrg { 643706f2543Smrg mask = fbStipple24Bits[rot>>3][stip]; 644706f2543Smrg WRITE(dst, FbOpaqueStipple (mask, 645706f2543Smrg FbRot24(fgxor, rot), 646706f2543Smrg FbRot24(bgxor, rot))); 647706f2543Smrg dst++; 648706f2543Smrg fbNextStipBits(rot,stip); 649706f2543Smrg } 650706f2543Smrg if (rightMask) 651706f2543Smrg { 652706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip]; 653706f2543Smrg WRITE(dst, (READ(dst) & ~rightMask) | 654706f2543Smrg (FbOpaqueStipple (mask, 655706f2543Smrg FbRot24(fgxor, rot), 656706f2543Smrg FbRot24(bgxor, rot)) 657706f2543Smrg & rightMask)); 658706f2543Smrg } 659706f2543Smrg dst += dstStride; 660706f2543Smrg src += srcStride; 661706f2543Smrg } 662706f2543Smrg } 663706f2543Smrg /* transparent copy */ 664706f2543Smrg else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) 665706f2543Smrg { 666706f2543Smrg while (height--) 667706f2543Smrg { 668706f2543Smrg rot = rot0; 669706f2543Smrg src = srcLine; 670706f2543Smrg srcLine += srcStride; 671706f2543Smrg fbInitStipBits (srcX, firstlen, stip); 672706f2543Smrg if (leftMask) 673706f2543Smrg { 674706f2543Smrg if (stip) 675706f2543Smrg { 676706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip] & leftMask; 677706f2543Smrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 678706f2543Smrg } 679706f2543Smrg dst++; 680706f2543Smrg fbNextStipBits (rot, stip); 681706f2543Smrg } 682706f2543Smrg nl = nlMiddle; 683706f2543Smrg while (nl--) 684706f2543Smrg { 685706f2543Smrg if (stip) 686706f2543Smrg { 687706f2543Smrg mask = fbStipple24Bits[rot>>3][stip]; 688706f2543Smrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor,rot) & mask)); 689706f2543Smrg } 690706f2543Smrg dst++; 691706f2543Smrg fbNextStipBits (rot, stip); 692706f2543Smrg } 693706f2543Smrg if (rightMask) 694706f2543Smrg { 695706f2543Smrg if (stip) 696706f2543Smrg { 697706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip] & rightMask; 698706f2543Smrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 699706f2543Smrg } 700706f2543Smrg } 701706f2543Smrg dst += dstStride; 702706f2543Smrg } 703706f2543Smrg } 704706f2543Smrg else 705706f2543Smrg { 706706f2543Smrg while (height--) 707706f2543Smrg { 708706f2543Smrg rot = rot0; 709706f2543Smrg src = srcLine; 710706f2543Smrg srcLine += srcStride; 711706f2543Smrg fbInitStipBits (srcX, firstlen, stip); 712706f2543Smrg if (leftMask) 713706f2543Smrg { 714706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip]; 715706f2543Smrg WRITE(dst, FbStippleRRopMask (READ(dst), mask, 716706f2543Smrg FbRot24(fgand, rot), 717706f2543Smrg FbRot24(fgxor, rot), 718706f2543Smrg FbRot24(bgand, rot), 719706f2543Smrg FbRot24(bgxor, rot), 720706f2543Smrg leftMask)); 721706f2543Smrg dst++; 722706f2543Smrg fbNextStipBits(rot,stip); 723706f2543Smrg } 724706f2543Smrg nl = nlMiddle; 725706f2543Smrg while (nl--) 726706f2543Smrg { 727706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip]; 728706f2543Smrg WRITE(dst, FbStippleRRop (READ(dst), mask, 729706f2543Smrg FbRot24(fgand, rot), 730706f2543Smrg FbRot24(fgxor, rot), 731706f2543Smrg FbRot24(bgand, rot), 732706f2543Smrg FbRot24(bgxor, rot))); 733706f2543Smrg dst++; 734706f2543Smrg fbNextStipBits(rot,stip); 735706f2543Smrg } 736706f2543Smrg if (rightMask) 737706f2543Smrg { 738706f2543Smrg mask = fbStipple24Bits[rot >> 3][stip]; 739706f2543Smrg WRITE(dst, FbStippleRRopMask (READ(dst), mask, 740706f2543Smrg FbRot24(fgand, rot), 741706f2543Smrg FbRot24(fgxor, rot), 742706f2543Smrg FbRot24(bgand, rot), 743706f2543Smrg FbRot24(bgxor, rot), 744706f2543Smrg rightMask)); 745706f2543Smrg } 746706f2543Smrg dst += dstStride; 747706f2543Smrg } 748706f2543Smrg } 749706f2543Smrg} 750706f2543Smrg#endif 751706f2543Smrg 752706f2543Smrg/* 753706f2543Smrg * Not very efficient, but simple -- copy a single plane 754706f2543Smrg * from an N bit image to a 1 bit image 755706f2543Smrg */ 756706f2543Smrg 757706f2543Smrgvoid 758706f2543SmrgfbBltPlane (FbBits *src, 759706f2543Smrg FbStride srcStride, 760706f2543Smrg int srcX, 761706f2543Smrg int srcBpp, 762706f2543Smrg 763706f2543Smrg FbStip *dst, 764706f2543Smrg FbStride dstStride, 765706f2543Smrg int dstX, 766706f2543Smrg 767706f2543Smrg int width, 768706f2543Smrg int height, 769706f2543Smrg 770706f2543Smrg FbStip fgand, 771706f2543Smrg FbStip fgxor, 772706f2543Smrg FbStip bgand, 773706f2543Smrg FbStip bgxor, 774706f2543Smrg Pixel planeMask) 775706f2543Smrg{ 776706f2543Smrg FbBits *s; 777706f2543Smrg FbBits pm; 778706f2543Smrg FbBits srcMask; 779706f2543Smrg FbBits srcMaskFirst; 780706f2543Smrg FbBits srcMask0 = 0; 781706f2543Smrg FbBits srcBits; 782706f2543Smrg 783706f2543Smrg FbStip dstBits; 784706f2543Smrg FbStip *d; 785706f2543Smrg FbStip dstMask; 786706f2543Smrg FbStip dstMaskFirst; 787706f2543Smrg FbStip dstUnion; 788706f2543Smrg int w; 789706f2543Smrg int wt; 790706f2543Smrg int rot0; 791706f2543Smrg 792706f2543Smrg if (!width) 793706f2543Smrg return; 794706f2543Smrg 795706f2543Smrg src += srcX >> FB_SHIFT; 796706f2543Smrg srcX &= FB_MASK; 797706f2543Smrg 798706f2543Smrg dst += dstX >> FB_STIP_SHIFT; 799706f2543Smrg dstX &= FB_STIP_MASK; 800706f2543Smrg 801706f2543Smrg w = width / srcBpp; 802706f2543Smrg 803706f2543Smrg pm = fbReplicatePixel (planeMask, srcBpp); 804706f2543Smrg#ifdef FB_24BIT 805706f2543Smrg if (srcBpp == 24) 806706f2543Smrg { 807706f2543Smrg int w = 24; 808706f2543Smrg 809706f2543Smrg rot0 = FbFirst24Rot (srcX); 810706f2543Smrg if (srcX + w > FB_UNIT) 811706f2543Smrg w = FB_UNIT - srcX; 812706f2543Smrg srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w); 813706f2543Smrg } 814706f2543Smrg else 815706f2543Smrg#endif 816706f2543Smrg { 817706f2543Smrg rot0 = 0; 818706f2543Smrg srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 819706f2543Smrg srcMask0 = pm & FbBitsMask(0, srcBpp); 820706f2543Smrg } 821706f2543Smrg 822706f2543Smrg dstMaskFirst = FbStipMask(dstX,1); 823706f2543Smrg while (height--) 824706f2543Smrg { 825706f2543Smrg d = dst; 826706f2543Smrg dst += dstStride; 827706f2543Smrg s = src; 828706f2543Smrg src += srcStride; 829706f2543Smrg 830706f2543Smrg srcMask = srcMaskFirst; 831706f2543Smrg#ifdef FB_24BIT 832706f2543Smrg if (srcBpp == 24) 833706f2543Smrg srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp); 834706f2543Smrg#endif 835706f2543Smrg srcBits = READ(s++); 836706f2543Smrg 837706f2543Smrg dstMask = dstMaskFirst; 838706f2543Smrg dstUnion = 0; 839706f2543Smrg dstBits = 0; 840706f2543Smrg 841706f2543Smrg wt = w; 842706f2543Smrg 843706f2543Smrg while (wt--) 844706f2543Smrg { 845706f2543Smrg if (!srcMask) 846706f2543Smrg { 847706f2543Smrg srcBits = READ(s++); 848706f2543Smrg#ifdef FB_24BIT 849706f2543Smrg if (srcBpp == 24) 850706f2543Smrg srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24); 851706f2543Smrg#endif 852706f2543Smrg srcMask = srcMask0; 853706f2543Smrg } 854706f2543Smrg if (!dstMask) 855706f2543Smrg { 856706f2543Smrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 857706f2543Smrg fgand, fgxor, bgand, bgxor, 858706f2543Smrg dstUnion)); 859706f2543Smrg d++; 860706f2543Smrg dstMask = FbStipMask(0,1); 861706f2543Smrg dstUnion = 0; 862706f2543Smrg dstBits = 0; 863706f2543Smrg } 864706f2543Smrg if (srcBits & srcMask) 865706f2543Smrg dstBits |= dstMask; 866706f2543Smrg dstUnion |= dstMask; 867706f2543Smrg if (srcBpp == FB_UNIT) 868706f2543Smrg srcMask = 0; 869706f2543Smrg else 870706f2543Smrg srcMask = FbScrRight(srcMask,srcBpp); 871706f2543Smrg dstMask = FbStipRight(dstMask,1); 872706f2543Smrg } 873706f2543Smrg if (dstUnion) 874706f2543Smrg WRITE(d, FbStippleRRopMask(READ(d),dstBits, 875706f2543Smrg fgand, fgxor, bgand, bgxor, 876706f2543Smrg dstUnion)); 877706f2543Smrg } 878706f2543Smrg} 879706f2543Smrg 880