1706f2543Smrg 2706f2543Smrg 3706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 4706f2543Smrg#include <xorg-config.h> 5706f2543Smrg#endif 6706f2543Smrg 7706f2543Smrg#include "xaa.h" 8706f2543Smrg#include "xaalocal.h" 9706f2543Smrg#include "xaacexp.h" 10706f2543Smrg#include "xf86.h" 11706f2543Smrg 12706f2543Smrg 13706f2543Smrg/********** byte swapping ***************/ 14706f2543Smrg 15706f2543Smrg 16706f2543Smrg#ifdef FIXEDBASE 17706f2543Smrg# define DEST(i) *dest 18706f2543Smrg# define RETURN(i) return(dest) 19706f2543Smrg#else 20706f2543Smrg# define DEST(i) dest[i] 21706f2543Smrg# define RETURN(i) return(dest + i) 22706f2543Smrg#endif 23706f2543Smrg 24706f2543Smrg#ifdef MSBFIRST 25706f2543Smrg# define SOURCE(i) SWAP_BITS_IN_BYTES(src[i]) 26706f2543Smrg#else 27706f2543Smrg# define SOURCE(i) src[i] 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg 31706f2543Smrgtypedef CARD32 *(* BitmapScanlineProcPtr)(CARD32 *, CARD32 *, int, int); 32706f2543Smrg 33706f2543Smrg#ifdef TRIPLE_BITS 34706f2543Smrgstatic CARD32* 35706f2543SmrgBitmapScanline( 36706f2543Smrg CARD32 *src, CARD32 *base, 37706f2543Smrg int count, int skipleft ) 38706f2543Smrg{ 39706f2543Smrg CARD32 bits; 40706f2543Smrg 41706f2543Smrg while(count >= 3) { 42706f2543Smrg bits = *src; 43706f2543Smrg WRITE_BITS3(bits); 44706f2543Smrg src++; 45706f2543Smrg count -= 3; 46706f2543Smrg } 47706f2543Smrg if (count == 2) { 48706f2543Smrg bits = *src; 49706f2543Smrg WRITE_BITS2(bits); 50706f2543Smrg } else if (count == 1) { 51706f2543Smrg bits = *src; 52706f2543Smrg WRITE_BITS1(bits); 53706f2543Smrg } 54706f2543Smrg 55706f2543Smrg return base; 56706f2543Smrg} 57706f2543Smrg 58706f2543Smrgstatic CARD32* 59706f2543SmrgBitmapScanline_Inverted( 60706f2543Smrg CARD32 *src, CARD32 *base, 61706f2543Smrg int count, int skipleft ) 62706f2543Smrg{ 63706f2543Smrg CARD32 bits; 64706f2543Smrg 65706f2543Smrg while(count >= 3) { 66706f2543Smrg bits = ~(*src); 67706f2543Smrg WRITE_BITS3(bits); 68706f2543Smrg src++; 69706f2543Smrg count -= 3; 70706f2543Smrg } 71706f2543Smrg if (count == 2) { 72706f2543Smrg bits = ~(*src); 73706f2543Smrg WRITE_BITS2(bits); 74706f2543Smrg } else if (count == 1) { 75706f2543Smrg bits = ~(*src); 76706f2543Smrg WRITE_BITS1(bits); 77706f2543Smrg } 78706f2543Smrg 79706f2543Smrg return base; 80706f2543Smrg} 81706f2543Smrg 82706f2543Smrg 83706f2543Smrgstatic CARD32* 84706f2543SmrgBitmapScanline_Shifted( 85706f2543Smrg CARD32 *src, CARD32 *base, 86706f2543Smrg int count, int skipleft ) 87706f2543Smrg{ 88706f2543Smrg CARD32 bits; 89706f2543Smrg 90706f2543Smrg while(count >= 3) { 91706f2543Smrg bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)); 92706f2543Smrg WRITE_BITS3(bits); 93706f2543Smrg src++; 94706f2543Smrg count -= 3; 95706f2543Smrg } 96706f2543Smrg if (count == 2) { 97706f2543Smrg bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)); 98706f2543Smrg WRITE_BITS2(bits); 99706f2543Smrg } else if (count == 1) { 100706f2543Smrg bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)); 101706f2543Smrg WRITE_BITS1(bits); 102706f2543Smrg } 103706f2543Smrg 104706f2543Smrg return base; 105706f2543Smrg} 106706f2543Smrg 107706f2543Smrgstatic CARD32* 108706f2543SmrgBitmapScanline_Shifted_Inverted( 109706f2543Smrg CARD32 *src, CARD32 *base, 110706f2543Smrg int count, int skipleft ) 111706f2543Smrg{ 112706f2543Smrg CARD32 bits; 113706f2543Smrg 114706f2543Smrg while(count >= 3) { 115706f2543Smrg bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft))); 116706f2543Smrg WRITE_BITS3(bits); 117706f2543Smrg src++; 118706f2543Smrg count -= 3; 119706f2543Smrg } 120706f2543Smrg if (count == 2) { 121706f2543Smrg bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft))); 122706f2543Smrg WRITE_BITS2(bits); 123706f2543Smrg } else if (count == 1) { 124706f2543Smrg bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft))); 125706f2543Smrg WRITE_BITS1(bits); 126706f2543Smrg } 127706f2543Smrg 128706f2543Smrg return base; 129706f2543Smrg} 130706f2543Smrg 131706f2543Smrg#define BitmapScanline_Shifted_Careful BitmapScanline_Shifted 132706f2543Smrg#define BitmapScanline_Shifted_Inverted_Careful BitmapScanline_Shifted_Inverted 133706f2543Smrg 134706f2543Smrg#else 135706f2543Smrgstatic CARD32* 136706f2543SmrgBitmapScanline( 137706f2543Smrg CARD32 *src, CARD32 *dest, 138706f2543Smrg int count, int skipleft ) 139706f2543Smrg{ 140706f2543Smrg while(count >= 4) { 141706f2543Smrg DEST(0) = SOURCE(0); 142706f2543Smrg DEST(1) = SOURCE(1); 143706f2543Smrg DEST(2) = SOURCE(2); 144706f2543Smrg DEST(3) = SOURCE(3); 145706f2543Smrg count -= 4; 146706f2543Smrg src += 4; 147706f2543Smrg#ifndef FIXEDBASE 148706f2543Smrg dest += 4; 149706f2543Smrg#endif 150706f2543Smrg } 151706f2543Smrg 152706f2543Smrg if(!count) return dest; 153706f2543Smrg DEST(0) = SOURCE(0); 154706f2543Smrg if(count == 1) RETURN(1); 155706f2543Smrg DEST(1) = SOURCE(1); 156706f2543Smrg if(count == 2) RETURN(2); 157706f2543Smrg DEST(2) = SOURCE(2); 158706f2543Smrg RETURN(3); 159706f2543Smrg} 160706f2543Smrg 161706f2543Smrgstatic CARD32* 162706f2543SmrgBitmapScanline_Inverted( 163706f2543Smrg CARD32 *src, CARD32 *dest, 164706f2543Smrg int count, int skipleft ) 165706f2543Smrg{ 166706f2543Smrg while(count >= 4) { 167706f2543Smrg DEST(0) = ~SOURCE(0); 168706f2543Smrg DEST(1) = ~SOURCE(1); 169706f2543Smrg DEST(2) = ~SOURCE(2); 170706f2543Smrg DEST(3) = ~SOURCE(3); 171706f2543Smrg count -= 4; 172706f2543Smrg src += 4; 173706f2543Smrg#ifndef FIXEDBASE 174706f2543Smrg dest += 4; 175706f2543Smrg#endif 176706f2543Smrg } 177706f2543Smrg 178706f2543Smrg if(!count) return dest; 179706f2543Smrg DEST(0) = ~SOURCE(0); 180706f2543Smrg if(count == 1) RETURN(1); 181706f2543Smrg DEST(1) = ~SOURCE(1); 182706f2543Smrg if(count == 2) RETURN(2); 183706f2543Smrg DEST(2) = ~SOURCE(2); 184706f2543Smrg RETURN(3); 185706f2543Smrg} 186706f2543Smrg 187706f2543Smrg 188706f2543Smrgstatic CARD32* 189706f2543SmrgBitmapScanline_Shifted( 190706f2543Smrg CARD32 *bits, CARD32 *base, 191706f2543Smrg int count, int skipleft ) 192706f2543Smrg{ 193706f2543Smrg while(count--) { 194706f2543Smrg register CARD32 tmp = SHIFT_R(*bits,skipleft) | 195706f2543Smrg SHIFT_L(*(bits + 1),(32 - skipleft)); 196706f2543Smrg WRITE_BITS(tmp); 197706f2543Smrg bits++; 198706f2543Smrg } 199706f2543Smrg return base; 200706f2543Smrg} 201706f2543Smrg 202706f2543Smrgstatic CARD32* 203706f2543SmrgBitmapScanline_Shifted_Inverted( 204706f2543Smrg CARD32 *bits, CARD32 *base, 205706f2543Smrg int count, int skipleft ) 206706f2543Smrg{ 207706f2543Smrg while(count--) { 208706f2543Smrg register CARD32 tmp = ~(SHIFT_R(*bits,skipleft) | 209706f2543Smrg SHIFT_L(*(bits + 1),(32 - skipleft))); 210706f2543Smrg WRITE_BITS(tmp); 211706f2543Smrg bits++; 212706f2543Smrg } 213706f2543Smrg return base; 214706f2543Smrg} 215706f2543Smrg 216706f2543Smrgstatic CARD32* 217706f2543SmrgBitmapScanline_Shifted_Careful( 218706f2543Smrg CARD32 *bits, CARD32 *base, 219706f2543Smrg int count, int skipleft ) 220706f2543Smrg{ 221706f2543Smrg register CARD32 tmp; 222706f2543Smrg while(--count) { 223706f2543Smrg tmp = SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft)); 224706f2543Smrg WRITE_BITS(tmp); 225706f2543Smrg bits++; 226706f2543Smrg } 227706f2543Smrg tmp = SHIFT_R(*bits,skipleft); 228706f2543Smrg WRITE_BITS(tmp); 229706f2543Smrg 230706f2543Smrg return base; 231706f2543Smrg} 232706f2543Smrg 233706f2543Smrgstatic CARD32* 234706f2543SmrgBitmapScanline_Shifted_Inverted_Careful( 235706f2543Smrg CARD32 *bits, CARD32 *base, 236706f2543Smrg int count, int skipleft ) 237706f2543Smrg{ 238706f2543Smrg register CARD32 tmp; 239706f2543Smrg while(--count) { 240706f2543Smrg tmp = ~(SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft))); 241706f2543Smrg WRITE_BITS(tmp); 242706f2543Smrg bits++; 243706f2543Smrg } 244706f2543Smrg tmp = ~(SHIFT_R(*bits,skipleft)); 245706f2543Smrg WRITE_BITS(tmp); 246706f2543Smrg return base; 247706f2543Smrg} 248706f2543Smrg 249706f2543Smrg#endif 250706f2543Smrg 251706f2543Smrg/* 252706f2543Smrg When the accelerator is TRANSPARENCY_ONLY, WriteBitmap can do 253706f2543Smrg the fill in two passes, inverting the source on the second pass. 254706f2543Smrg For GXcopy we can fill the backing rectangle as a solid rect and 255706f2543Smrg avoid the invert. 256706f2543Smrg*/ 257706f2543Smrg 258706f2543Smrgvoid 259706f2543Smrg#ifdef TRIPLE_BITS 260706f2543SmrgEXPNAME(XAAWriteBitmapColorExpand3)( 261706f2543Smrg#else 262706f2543SmrgEXPNAME(XAAWriteBitmapColorExpand)( 263706f2543Smrg#endif 264706f2543Smrg ScrnInfoPtr pScrn, 265706f2543Smrg int x, int y, int w, int H, 266706f2543Smrg unsigned char *src, 267706f2543Smrg int srcwidth, 268706f2543Smrg int skipleft, 269706f2543Smrg int fg, int bg, 270706f2543Smrg int rop, 271706f2543Smrg unsigned int planemask 272706f2543Smrg) 273706f2543Smrg{ 274706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 275706f2543Smrg CARD32* base; 276706f2543Smrg unsigned char *srcp = src; 277706f2543Smrg int SecondPassColor = -1; 278706f2543Smrg int shift = 0, dwords; 279706f2543Smrg BitmapScanlineProcPtr firstFunc; 280706f2543Smrg BitmapScanlineProcPtr secondFunc; 281706f2543Smrg int flag; 282706f2543Smrg int h = H; 283706f2543Smrg 284706f2543Smrg#ifdef TRIPLE_BITS 285706f2543Smrg if((bg != -1) && 286706f2543Smrg ((infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) || 287706f2543Smrg ((infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) && 288706f2543Smrg (!CHECK_RGB_EQUAL(bg))))) { 289706f2543Smrg#else 290706f2543Smrg if((bg != -1) && 291706f2543Smrg (infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { 292706f2543Smrg#endif 293706f2543Smrg if((rop == GXcopy) && infoRec->SetupForSolidFill) { 294706f2543Smrg (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); 295706f2543Smrg (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 296706f2543Smrg } else SecondPassColor = bg; 297706f2543Smrg bg = -1; 298706f2543Smrg } 299706f2543Smrg 300706f2543Smrg#ifdef TRIPLE_BITS 301706f2543Smrg if(skipleft) { 302706f2543Smrg#else 303706f2543Smrg if(skipleft && 304706f2543Smrg (!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING) || 305706f2543Smrg (!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && 306706f2543Smrg (skipleft > x)))) { 307706f2543Smrg#endif 308706f2543Smrg if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) { 309706f2543Smrg /* don't read past the end */ 310706f2543Smrg firstFunc = BitmapScanline_Shifted_Careful; 311706f2543Smrg secondFunc = BitmapScanline_Shifted_Inverted_Careful; 312706f2543Smrg } else { 313706f2543Smrg firstFunc = BitmapScanline_Shifted; 314706f2543Smrg secondFunc = BitmapScanline_Shifted_Inverted; 315706f2543Smrg } 316706f2543Smrg shift = skipleft; 317706f2543Smrg skipleft = 0; 318706f2543Smrg } else { 319706f2543Smrg firstFunc = BitmapScanline; 320706f2543Smrg secondFunc = BitmapScanline_Inverted; 321706f2543Smrg w += skipleft; 322706f2543Smrg x -= skipleft; 323706f2543Smrg } 324706f2543Smrg 325706f2543Smrg#ifdef TRIPLE_BITS 326706f2543Smrg dwords = (3 * w + 31) >> 5; 327706f2543Smrg#else 328706f2543Smrg dwords = (w + 31) >> 5; 329706f2543Smrg#endif 330706f2543Smrg 331706f2543SmrgSECOND_PASS: 332706f2543Smrg 333706f2543Smrg flag = (infoRec->CPUToScreenColorExpandFillFlags 334706f2543Smrg & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01); 335706f2543Smrg (*infoRec->SetupForCPUToScreenColorExpandFill)( 336706f2543Smrg pScrn, fg, bg, rop, planemask); 337706f2543Smrg (*infoRec->SubsequentCPUToScreenColorExpandFill)( 338706f2543Smrg pScrn, x, y, w, h, skipleft); 339706f2543Smrg 340706f2543Smrg base = (CARD32*)infoRec->ColorExpandBase; 341706f2543Smrg 342706f2543Smrg#ifndef FIXEDBASE 343706f2543Smrg if((dwords * h) <= infoRec->ColorExpandRange) 344706f2543Smrg while(h--) { 345706f2543Smrg base = (*firstFunc)((CARD32*)srcp, base, dwords, shift); 346706f2543Smrg srcp += srcwidth; 347706f2543Smrg } 348706f2543Smrg else 349706f2543Smrg#endif 350706f2543Smrg while(h--) { 351706f2543Smrg (*firstFunc)((CARD32*)srcp, base, dwords, shift); 352706f2543Smrg srcp += srcwidth; 353706f2543Smrg } 354706f2543Smrg 355706f2543Smrg if(flag){ 356706f2543Smrg base = (CARD32*)infoRec->ColorExpandBase; 357706f2543Smrg base[0] = 0x00000000; 358706f2543Smrg } 359706f2543Smrg 360706f2543Smrg if(SecondPassColor != -1) { 361706f2543Smrg h = H; /* Reset height */ 362706f2543Smrg fg = SecondPassColor; 363706f2543Smrg SecondPassColor = -1; 364706f2543Smrg firstFunc = secondFunc; 365706f2543Smrg srcp = src; 366706f2543Smrg goto SECOND_PASS; 367706f2543Smrg } 368706f2543Smrg 369706f2543Smrg if(infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND) 370706f2543Smrg (*infoRec->Sync)(pScrn); 371706f2543Smrg else SET_SYNC_FLAG(infoRec); 372706f2543Smrg} 373706f2543Smrg 374706f2543Smrg#ifndef FIXEDBASE 375706f2543Smrg 376706f2543Smrgvoid 377706f2543Smrg#ifdef TRIPLE_BITS 378706f2543SmrgEXPNAME(XAAWriteBitmapScanlineColorExpand3)( 379706f2543Smrg#else 380706f2543SmrgEXPNAME(XAAWriteBitmapScanlineColorExpand)( 381706f2543Smrg#endif 382706f2543Smrg ScrnInfoPtr pScrn, 383706f2543Smrg int x, int y, int w, int h, 384706f2543Smrg unsigned char *src, 385706f2543Smrg int srcwidth, 386706f2543Smrg int skipleft, 387706f2543Smrg int fg, int bg, 388706f2543Smrg int rop, 389706f2543Smrg unsigned int planemask 390706f2543Smrg) 391706f2543Smrg{ 392706f2543Smrg XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 393706f2543Smrg CARD32* base; 394706f2543Smrg unsigned char *srcp = src; 395706f2543Smrg int SecondPassColor = -1; 396706f2543Smrg int shift = 0, dwords, bufferNo; 397706f2543Smrg BitmapScanlineProcPtr firstFunc; 398706f2543Smrg BitmapScanlineProcPtr secondFunc; 399706f2543Smrg 400706f2543Smrg#ifdef TRIPLE_BITS 401706f2543Smrg if((bg != -1) && 402706f2543Smrg ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) 403706f2543Smrg || ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) && 404706f2543Smrg (!CHECK_RGB_EQUAL(bg))))) { 405706f2543Smrg#else 406706f2543Smrg if((bg != -1) && 407706f2543Smrg (infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)){ 408706f2543Smrg#endif 409706f2543Smrg if((rop == GXcopy) && infoRec->SetupForSolidFill) { 410706f2543Smrg (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); 411706f2543Smrg (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 412706f2543Smrg } else SecondPassColor = bg; 413706f2543Smrg bg = -1; 414706f2543Smrg } 415706f2543Smrg 416706f2543Smrg#ifdef TRIPLE_BITS 417706f2543Smrg if(skipleft) { 418706f2543Smrg#else 419706f2543Smrg if(skipleft && 420706f2543Smrg (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & 421706f2543Smrg LEFT_EDGE_CLIPPING) || 422706f2543Smrg (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & 423706f2543Smrg LEFT_EDGE_CLIPPING_NEGATIVE_X) && (skipleft > x)))) { 424706f2543Smrg#endif 425706f2543Smrg if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) { 426706f2543Smrg /* don't read past the end */ 427706f2543Smrg firstFunc = BitmapScanline_Shifted_Careful; 428706f2543Smrg secondFunc = BitmapScanline_Shifted_Inverted_Careful; 429706f2543Smrg } else { 430706f2543Smrg firstFunc = BitmapScanline_Shifted; 431706f2543Smrg secondFunc = BitmapScanline_Shifted_Inverted; 432706f2543Smrg } 433706f2543Smrg shift = skipleft; 434706f2543Smrg skipleft = 0; 435706f2543Smrg } else { 436706f2543Smrg firstFunc = BitmapScanline; 437706f2543Smrg secondFunc = BitmapScanline_Inverted; 438706f2543Smrg w += skipleft; 439706f2543Smrg x -= skipleft; 440706f2543Smrg } 441706f2543Smrg 442706f2543Smrg#ifdef TRIPLE_BITS 443706f2543Smrg dwords = (3 * w + 31) >> 5; 444706f2543Smrg#else 445706f2543Smrg dwords = (w + 31) >> 5; 446706f2543Smrg#endif 447706f2543Smrg 448706f2543SmrgSECOND_PASS: 449706f2543Smrg 450706f2543Smrg (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); 451706f2543Smrg (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( 452706f2543Smrg pScrn, x, y, w, h, skipleft); 453706f2543Smrg 454706f2543Smrg bufferNo = 0; 455706f2543Smrg 456706f2543Smrg while(h--) { 457706f2543Smrg base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; 458706f2543Smrg (*firstFunc)((CARD32*)srcp, base, dwords, shift); 459706f2543Smrg (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); 460706f2543Smrg srcp += srcwidth; 461706f2543Smrg if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) 462706f2543Smrg bufferNo = 0; 463706f2543Smrg } 464706f2543Smrg 465706f2543Smrg if(SecondPassColor != -1) { 466706f2543Smrg fg = SecondPassColor; 467706f2543Smrg SecondPassColor = -1; 468706f2543Smrg firstFunc = secondFunc; 469706f2543Smrg srcp = src; 470706f2543Smrg goto SECOND_PASS; 471706f2543Smrg } 472706f2543Smrg 473706f2543Smrg SET_SYNC_FLAG(infoRec); 474706f2543Smrg} 475706f2543Smrg 476706f2543Smrg#endif 477