1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#define FASTER 7#ifndef PSZ 8#define PSZ 8 9#endif 10 11#if PSZ == 24 12# define APM_SUFF_24 "24" 13# define A(s) Apm##s##24 14#else 15# define APM_SUFF_24 "" 16# define A(s) Apm##s 17#endif 18#define DPRINTNAME(s) do { xf86DrvMsgVerb(pScrn->pScreen->myNum, X_NOTICE, 6, "Apm" #s APM_SUFF_24 "\n"); } while (0) 19 20#if PSZ == 24 21#undef SETSOURCEXY 22#undef SETDESTXY 23#undef SETWIDTH 24#undef SETWIDTHHEIGHT 25#undef UPDATEDEST 26#define SETSOURCEXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1) 27#define SETDESTXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETDESTOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1) 28#define SETWIDTH(w) WRXW(0x58, ((w) & 0x3FFF) * 3) 29#define SETWIDTHHEIGHT(w,h) WRXL(0x58, ((h) << 16) | (((w) & 0x3FFF) * 3)) 30#define UPDATEDEST(x,y) (void)(curr32[0x54 / 4] = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0xFFFF)) * 3)) 31#endif 32 33/* Defines */ 34#define MAXLOOP 1000000 35 36 37/* Local functions */ 38static void A(Sync)(ScrnInfoPtr pScrn); 39static void A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, 40 unsigned int planemask); 41static void A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, 42 int w, int h); 43static void A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, 44 int rop, unsigned int planemask, 45 int transparency_color); 46static void A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1, 47 int x2, int y2, int w, int h); 48#if PSZ != 24 49static void A(Sync6422)(ScrnInfoPtr pScrn); 50static void A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 51 unsigned char *src, int srcwidth, int skipleft, 52 int fg, int bg, int rop, unsigned int planemask); 53static void A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 54 int skipleft, int startline, 55 unsigned int **glyphs, int glyphWidth, 56 int fg, int bg, int rop, unsigned planemask); 57static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, 58 int fg, int bg, int rop, 59 unsigned int planemask); 60static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, 61 int paty, int x, int y, 62 int w, int h); 63#if 0 64static void A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int bg, int fg, int rop, unsigned int planemask); 65static void A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft); 66#endif 67static void A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, 68 int fg, int bg, int rop, 69 unsigned int planemask); 70static void A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, 71 unsigned int planemask, int trans_color, 72 int bpp, int depth); 73static void A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, 74 int w, int h, int skipleft); 75static void A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, 76 int x, int y, 77 int w, int h, 78 int srcx, int srcy, 79 int offset); 80static void A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length); 81static void A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length); 82static void A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2); 83static void A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 84 unsigned char *src, int srcwidth, int rop, 85 unsigned int planemask, int trans, int bpp, 86 int depth); 87static void A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, 88 unsigned int planemask, 89 int nBox, BoxPtr pBox, int xorg, int yorg, 90 PixmapPtr pPix); 91static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty, 92 int rop, unsigned int planemask, 93 int transparency_color); 94static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, 95 int paty, int x, int y, 96 int w, int h); 97#endif 98 99/* Inline functions */ 100static __inline__ void 101A(WaitForFifo)(ApmPtr pApm, int slots) 102{ 103 if (!pApm->UsePCIRetry) { 104 volatile int i; 105 106 for(i = 0; i < MAXLOOP; i++) { 107 if ((STATUS() & STATUS_FIFO) >= slots) 108 break; 109 } 110 if (i == MAXLOOP) { 111 unsigned int status = STATUS(); 112 113 WRXB(0x1FF, 0); 114 if (!xf86ServerIsExiting()) 115 FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status); 116 } 117 } 118} 119 120 121static void 122A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, 123 unsigned int planemask) 124{ 125 APMDECL(pScrn); 126 127 DPRINTNAME(SetupForSolidFill); 128#ifdef FASTER 129 A(WaitForFifo)(pApm, 3 + pApm->apmClip); 130 SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER | 131 pApm->CurrentLayout.Setup_DEC); 132#else 133 A(WaitForFifo)(pApm, 2 + pApm->apmClip); 134#endif 135#if PSZ == 2 136 pApm->color = ((color & 0xFF0000) << 8) | ((color & 0xFF0000) >> 16) | 137 ((color & 0xFF00) << 8) | ((color & 0xFF) << 16); 138#else 139 SETFOREGROUNDCOLOR(color); 140#endif 141 142 if (pApm->apmClip) { 143 SETCLIP_CTRL(0); 144 pApm->apmClip = FALSE; 145 } 146 147 SETROP(apmROP[rop]); 148} 149 150static void 151A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h) 152{ 153 APMDECL(pScrn); 154 155 DPRINTNAME(SubsequentSolidFillRect); 156#if PSZ == 24 157# ifndef FASTER 158 A(WaitForFifo)(pApm, 5); 159# else 160 A(WaitForFifo)(pApm, 4); 161# endif 162 SETOFFSET(3*(pApm->CurrentLayout.displayWidth - w)); 163#if 0 164 switch ((((y * pApm->CurrentLayout.displayWidth + x)* 3) / 8) % 3) { 165 case 0: 166 SETFOREGROUNDCOLOR(pApm->color); 167 break; 168 case 1: 169 SETFOREGROUNDCOLOR((pApm->color << 8) | (pApm->color >> 16)); 170 break; 171 case 2: 172 SETFOREGROUNDCOLOR(pApm->color >> 8); 173 break; 174 } 175#endif 176#else 177# ifndef FASTER 178 A(WaitForFifo)(pApm, 3); 179# else 180 A(WaitForFifo)(pApm, 2); 181# endif 182#endif 183 SETDESTXY(x, y); 184 SETWIDTHHEIGHT(w, h); 185 UPDATEDEST(x + w + 1, y); 186#ifndef FASTER 187 SETDEC(DEC_START | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC); 188#endif 189} 190 191static void 192A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, 193 unsigned int planemask, int transparency_color) 194{ 195 unsigned char tmp; 196 197 APMDECL(pScrn); 198 199 DPRINTNAME(SetupForScreenToScreenCopy); 200 201 if (pApm->apmLock) { 202 /* 203 * This is just an attempt, because Daryll is tampering with MY registers. 204 */ 205 tmp = (RDXB(0xDB) & 0xF4) | 0x0A; 206 WRXB(0xDB, tmp); 207 ApmWriteSeq(0x1B, 0x20); 208 ApmWriteSeq(0x1C, 0x2F); 209 pApm->apmLock = FALSE; 210 } 211 212 pApm->blitxdir = xdir; 213 pApm->blitydir = ydir; 214 215 pApm->apmTransparency = (transparency_color != -1); 216 217#ifdef FASTER 218 A(WaitForFifo)(pApm, 2 + (transparency_color != -1)); 219 SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | 220 (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | pApm->CurrentLayout.Setup_DEC | 221 ((xdir < 0) ? DEC_DIR_X_NEG : DEC_DIR_X_POS) | 222 ((ydir < 0) ? DEC_DIR_Y_NEG : DEC_DIR_Y_POS)); 223#else 224 A(WaitForFifo)(pApm, 1 + (transparency_color != -1)); 225#endif 226 227 if (transparency_color != -1) 228 SETBACKGROUNDCOLOR(transparency_color); 229 230 SETROP(apmROP[rop]); 231} 232 233static void 234A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1, 235 int x2, int y2, int w, int h) 236{ 237 APMDECL(pScrn); 238#ifndef FASTER 239 u32 c = pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0; 240#endif 241 u32 sx, dx, sy, dy; 242 int i = y1 / pApm->CurrentLayout.Scanlines; 243 244 DPRINTNAME(SubsequentScreenToScreenCopy); 245 if (i && pApm->pixelStride) { 246#ifdef FASTER 247 A(WaitForFifo)(pApm, 1); 248 SETDEC(curr32[0x40 / 4] | (DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR)); 249#else 250 c |= DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG; 251#endif 252 pApm->apmClip = TRUE; 253 A(WaitForFifo)(pApm, 3); 254 SETCLIP_LEFTTOP(x2, y2); 255 SETCLIP_RIGHTBOT(x2 + w - 1, y2 + h - 1); 256 SETCLIP_CTRL(1); 257 w = (pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel; 258 } 259 else { 260#ifdef FASTER 261 A(WaitForFifo)(pApm, 1 + pApm->apmClip); 262 SETDEC(curr32[0x40 / 4] & ~(DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR)); 263 if (pApm->apmClip) 264 SETCLIP_CTRL(0); 265 pApm->apmClip = FALSE; 266#else 267 if (pApm->apmClip) { 268 A(WaitForFifo)(pApm, 1); 269 SETCLIP_CTRL(0); 270 pApm->apmClip = FALSE; 271 } 272#endif 273 } 274 if (i) { 275 if (pApm->pixelStride) { 276 x1 += (((y1 % pApm->CurrentLayout.Scanlines) - pApm->RushY[i - 1]) * pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel; 277 y1 = pApm->RushY[i - 1]; 278 } 279 else 280 y1 -= i * pApm->CurrentLayout.Scanlines; 281 } 282 if (pApm->blitxdir < 0) 283 { 284#ifndef FASTER 285 c |= DEC_DIR_X_NEG; 286#endif 287 sx = x1+w-1; 288 dx = x2+w-1; 289 } 290 else 291 { 292#ifndef FASTER 293 c |= DEC_DIR_X_POS; 294#endif 295 sx = x1; 296 dx = x2; 297 } 298 299 if (pApm->blitydir < 0) 300 { 301#ifndef FASTER 302 c |= DEC_DIR_Y_NEG | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | 303 pApm->CurrentLayout.Setup_DEC; 304#endif 305 sy = y1+h-1; 306 dy = y2+h-1; 307 } 308 else 309 { 310#ifndef FASTER 311 c |= DEC_DIR_Y_POS | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | 312 pApm->CurrentLayout.Setup_DEC; 313#endif 314 sy = y1; 315 dy = y2; 316 } 317 318#if PSZ == 24 319# ifndef FASTER 320 A(WaitForFifo)(pApm, 5); 321# else 322 A(WaitForFifo)(pApm, 4); 323# endif 324 if (pApm->blitxdir == pApm->blitydir) 325 SETOFFSET(3 * (pApm->CurrentLayout.displayWidth - w)); 326 else 327 SETOFFSET(3 * (pApm->CurrentLayout.displayWidth + w)); 328#else 329# ifndef FASTER 330 A(WaitForFifo)(pApm, 4); 331# else 332 A(WaitForFifo)(pApm, 3); 333# endif 334#endif 335 336 if (i && pApm->pixelStride) { 337 register unsigned int off = sx + sy * pApm->CurrentLayout.displayWidth; 338 339 SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); 340 } 341 else 342 SETSOURCEXY(sx,sy); 343 SETDESTXY(dx,dy); 344 SETWIDTHHEIGHT(w,h); 345 UPDATEDEST(dx + (w + 1)*pApm->blitxdir, dy); 346 347#ifndef FASTER 348 SETDEC(c); 349#endif 350 if (i) A(Sync)(pScrn); /* Only for AT3D */ 351} 352 353 354#if PSZ != 24 355static void 356A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg, 357 int rop, unsigned int planemask) 358{ 359 APMDECL(pScrn); 360 361 DPRINTNAME(SetupForScreenToScreenColorExpandFill); 362 A(WaitForFifo)(pApm, 3 + pApm->apmClip); 363 if (bg == -1) 364 { 365 SETFOREGROUNDCOLOR(fg); 366 SETBACKGROUNDCOLOR(fg+1); 367 pApm->apmTransparency = TRUE; 368 } 369 else 370 { 371 SETFOREGROUNDCOLOR(fg); 372 SETBACKGROUNDCOLOR(bg); 373 pApm->apmTransparency = FALSE; 374 } 375 376 SETROP(apmROP[rop]); 377} 378 379static void 380A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 381 unsigned char *src, int srcwidth, int skipleft, 382 int fg, int bg, int rop, unsigned int planemask) 383{ 384 APMDECL(pScrn); 385 Bool beCareful, apmClip = FALSE; 386 int wc, n, nc, wr, wrd; 387 CARD32 *dstPtr; 388#ifndef FASTER 389 int c; 390#endif 391 392 DPRINTNAME(WriteBitmap); 393 394 if (w <= 0 && h <= 0) 395 return; 396 397 /* 398 * The function is a bit long, but the spirit is simple : put the monochrome 399 * data in scratch memory and color-expand it using the 400 * ScreenToScreenColorExpand techniques. 401 */ 402 403 w += skipleft; 404 x -= skipleft; 405 wc = pApm->ScratchMemSize * 8; 406 wrd = (w + 31) >> 5; 407 wr = wrd << 5; 408 nc = wc / wr; 409 if (nc > h) 410 nc = h; 411 if (wr / 8 > srcwidth) 412 beCareful = TRUE; 413 else 414 beCareful = FALSE; 415 srcwidth -= wr / 8; 416 417 if (skipleft || w != wr) { 418 apmClip = TRUE; 419 A(WaitForFifo)(pApm, 3); 420 SETCLIP_LEFTTOP(x + skipleft, y); 421 SETCLIP_RIGHTBOT(x + w - 1, y + h - 1); 422 SETCLIP_CTRL(1); 423 } 424 else if (pApm->apmClip) { 425 A(WaitForFifo)(pApm, 1); 426 SETCLIP_CTRL(0); 427 } 428 pApm->apmClip = FALSE; 429 430 A(SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); 431#ifdef FASTER 432 A(WaitForFifo)(pApm, 2); 433 if (pApm->apmTransparency) 434 SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | 435 DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | 436 DEC_SOURCE_CONTIG | DEC_SOURCE_TRANSPARENCY | pApm->CurrentLayout.Setup_DEC); 437 else 438 SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | 439 DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | 440 DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC); 441#else 442 A(WaitForFifo)(pApm, 1); 443 c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | 444 DEC_START | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | 445 DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC; 446 if (pApm->apmTransparency) 447 c |= DEC_SOURCE_TRANSPARENCY; 448#endif 449 450 SETDESTXY(x, y); 451 452 if (!beCareful || h % nc > 3 || (w > 16 && h % nc)) { 453#ifndef FASTER 454 if (h / nc) 455 SETWIDTHHEIGHT(wr, nc); 456#endif 457 for (n = h / nc; n-- > 0; ) { 458 int i, j; 459 460 if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) { 461#define d ((memType)dstPtr - (memType)pApm->FbBase) 462 A(WaitForFifo)(pApm, 1); 463 dstPtr = (CARD32 *)pApm->ScratchMemPtr; 464 switch(pApm->CurrentLayout.bitsPerPixel) { 465 case 8: case 24: 466 SETSOURCEOFF((d & 0xFFF000) << 4 | 467 (d & 0xFFF)); 468 break; 469 case 16: 470 SETSOURCEOFF((d & 0xFFE000) << 3 | 471 ((d & 0x1FFE) >> 1)); 472 break; 473 case 32: 474 SETSOURCEOFF((d & 0xFFC000) << 2 | 475 ((d & 0x3FFC) >> 2)); 476 break; 477 } 478#undef d 479 } 480 else { 481 (*pApm->AccelInfoRec->Sync)(pScrn); 482 dstPtr = (CARD32 *)pApm->ScratchMemOffset; 483 SETSOURCEOFF(pApm->ScratchMem); 484 } 485 pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc) + 4) 486 & ~(memType)7; 487 for (i = nc; i-- > 0; ) { 488 for (j = wrd; j-- > 0; ) { 489 *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); 490 src += 4; 491 } 492 src += srcwidth; 493 } 494 A(WaitForFifo)(pApm, 1); 495#ifdef FASTER 496 SETWIDTHHEIGHT(wr, nc); 497#else 498 SETDEC(c); 499#endif 500 } 501 } 502 else { 503#ifndef FASTER 504 if (h / nc) 505 SETWIDTHHEIGHT(wr, nc); 506#endif 507 for (n = h / nc; n-- > 0; ) { 508 int i, j; 509 510 if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) { 511#define d ((memType)dstPtr - (memType)pApm->FbBase) 512 A(WaitForFifo)(pApm, 1); 513 dstPtr = (CARD32 *)pApm->ScratchMemPtr; 514 switch(pApm->CurrentLayout.bitsPerPixel) { 515 case 8: case 24: 516 SETSOURCEOFF((d & 0xFFF000) << 4 | 517 (d & 0xFFF)); 518 break; 519 case 16: 520 SETSOURCEOFF((d & 0xFFE000) << 3 | 521 ((d & 0x1FFE) >> 1)); 522 break; 523 case 32: 524 SETSOURCEOFF((d & 0xFFC000) << 2 | 525 ((d & 0x3FFC) >> 2)); 526 break; 527 } 528#undef d 529 } 530 else { 531 (*pApm->AccelInfoRec->Sync)(pScrn); 532 dstPtr = (CARD32 *)pApm->ScratchMemOffset; 533 SETSOURCEOFF(pApm->ScratchMem); 534 } 535 pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc * 4) + 4) & ~7; 536 for (i = nc; i-- > 0; ) { 537 for (j = wrd; j-- > 0; ) { 538 if (i || j || n) 539 *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); 540 else if (srcwidth > -8) { 541 ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]]; 542 ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]]; 543 ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]]; 544 dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr); 545 } 546 else if (srcwidth > -16) { 547 ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]]; 548 ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]]; 549 dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr); 550 } 551 else { 552 *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src]; 553 dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr); 554 } 555 src += 4; 556 } 557 src += srcwidth; 558 } 559 A(WaitForFifo)(pApm, 1); 560#ifdef FASTER 561 SETWIDTHHEIGHT(wr, nc); 562#else 563 SETDEC(c); 564#endif 565 } 566 } 567 568 /* 569 * Same thing for the remnant 570 */ 571 UPDATEDEST(x, y + h + 1); 572 h %= nc; 573 if (h) { 574 if (!beCareful) { 575 int i, j; 576 577#ifndef FASTER 578 SETWIDTHHEIGHT(wr, h); 579#endif 580 if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) { 581#define d ((memType)dstPtr - (memType)pApm->FbBase) 582 A(WaitForFifo)(pApm, 1); 583 dstPtr = (CARD32 *)pApm->ScratchMemPtr; 584 switch(pApm->CurrentLayout.bitsPerPixel) { 585 case 8: case 24: 586 SETSOURCEOFF((d & 0xFFF000) << 4 | 587 (d & 0xFFF)); 588 break; 589 case 16: 590 SETSOURCEOFF((d & 0xFFE000) << 3 | 591 ((d & 0x1FFE) >> 1)); 592 break; 593 case 32: 594 SETSOURCEOFF((d & 0xFFC000) << 2 | 595 ((d & 0x3FFC) >> 2)); 596 break; 597 } 598#undef d 599 } 600 else { 601 (*pApm->AccelInfoRec->Sync)(pScrn); 602 dstPtr = (CARD32 *)pApm->ScratchMemOffset; 603 SETSOURCEOFF(pApm->ScratchMem); 604 } 605 pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7; 606 for (i = h; i-- > 0; ) { 607 for (j = wrd; j-- > 0; ) { 608 *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); 609 src += 4; 610 } 611 src += srcwidth; 612 } 613 A(WaitForFifo)(pApm, 1); 614#ifdef FASTER 615 SETWIDTHHEIGHT(wr, h); 616#else 617 SETDEC(c); 618#endif 619 } 620 else { 621 int i, j; 622 623#ifndef FASTER 624 SETWIDTHHEIGHT(w, h); 625#endif 626 if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) { 627#define d ((memType)dstPtr - (memType)pApm->FbBase) 628 A(WaitForFifo)(pApm, 1); 629 dstPtr = (CARD32 *)pApm->ScratchMemPtr; 630 switch(pApm->CurrentLayout.bitsPerPixel) { 631 case 8: case 24: 632 SETSOURCEOFF((d & 0xFFF000) << 4 | 633 (d & 0xFFF)); 634 break; 635 case 16: 636 SETSOURCEOFF((d & 0xFFE000) << 3 | 637 ((d & 0x1FFE) >> 1)); 638 break; 639 case 32: 640 SETSOURCEOFF((d & 0xFFC000) << 2 | 641 ((d & 0x3FFC) >> 2)); 642 break; 643 } 644#undef d 645 } 646 else { 647 (*pApm->AccelInfoRec->Sync)(pScrn); 648 dstPtr = (CARD32 *)pApm->ScratchMemOffset; 649 SETSOURCEOFF(pApm->ScratchMem); 650 } 651 pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7; 652 for (i = h; i-- > 0; ) { 653 for (j = wrd; j-- > 0; ) { 654 if (i || j) 655 *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); 656 else if (srcwidth > -8) { 657 ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]]; 658 ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]]; 659 ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]]; 660 dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr); 661 } 662 else if (srcwidth > -16) { 663 ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]]; 664 ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]]; 665 dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr); 666 } 667 else { 668 *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src]; 669 dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr); 670 } 671 src += 4; 672 } 673 src += srcwidth; 674 } 675 A(WaitForFifo)(pApm, 1); 676#ifdef FASTER 677 SETWIDTHHEIGHT(w, h); 678#else 679 SETDEC(c); 680#endif 681 } 682 } 683 pApm->apmClip = apmClip; 684} 685 686static void 687A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 688 int skipleft, int startline, 689 unsigned int **glyphs, int glyphWidth, 690 int fg, int bg, int rop, unsigned planemask) 691{ 692 CARD32 *base, *base0; 693 GlyphScanlineFuncPtr GlyphFunc; 694 static GlyphScanlineFuncPtr *GlyphTab = NULL; 695 int w2, h2, dwords; 696 697 if (!GlyphTab) GlyphTab = XAAGetGlyphScanlineFuncLSBFirst(); 698 GlyphFunc = GlyphTab[glyphWidth - 1]; 699 700 w2 = w + skipleft; 701 h2 = h; 702 dwords = (w2 + 31) >> 5; 703 dwords <<= 2; 704 705 base0 = base = malloc(dwords * h); 706 if (!base) 707 return; /* Should not happen : it's rather small... */ 708 709 while(h--) { 710 base = (*GlyphFunc)(base, glyphs, startline++, w2, glyphWidth); 711 } 712 713 A(WriteBitmap)(pScrn, x, y, w, h2, (unsigned char *)base0, dwords, 714 skipleft, fg, bg, rop, planemask); 715 716 free(base0); 717} 718 719static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, 720 int fg, int bg, int rop, 721 unsigned int planemask) 722{ 723 APMDECL(pScrn); 724 725 DPRINTNAME(SetupForMono8x8PatternFill); 726 pApm->apmTransparency = (pApm->Chipset >= AT3D) && (bg == -1); 727 pApm->Bg8x8 = bg; 728 pApm->Fg8x8 = fg; 729 pApm->rop = apmROP[rop]; 730 A(WaitForFifo)(pApm, 3 + pApm->apmClip); 731 if (bg == -1) 732 SETBACKGROUNDCOLOR(fg + 1); 733 else 734 SETBACKGROUNDCOLOR(bg); 735 SETFOREGROUNDCOLOR(fg); 736 if (pApm->Chipset >= AT3D) 737 SETROP(apmROP[rop] & 0xF0); 738 else 739 SETROP((apmROP[rop] & 0xF0) | 0x0A); 740 if (pApm->apmClip) { 741 SETCLIP_CTRL(0); 742 pApm->apmClip = FALSE; 743 } 744} 745 746static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, 747 int paty, int x, int y, 748 int w, int h) 749{ 750 APMDECL(pScrn); 751 752 DPRINTNAME(SubsequentMono8x8PatternFillRect); 753 SETDESTXY(x, y); 754 UPDATEDEST(x, y + h + 1); 755 A(WaitForFifo)(pApm, 6); 756 if (pApm->Chipset == AT24 && pApm->Bg8x8 != -1) { 757 SETROP(pApm->rop); 758 SETFOREGROUNDCOLOR(pApm->Bg8x8); 759#ifdef FASTER 760 SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | 761 DEC_DEST_XY | DEC_QUICKSTART_ONDIMX); 762 SETWIDTHHEIGHT(w, h); 763#else 764 SETWIDTHHEIGHT(w, h); 765 SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | 766 DEC_DEST_XY | DEC_START); 767#endif 768 A(WaitForFifo)(pApm, 6); 769 SETROP((pApm->rop & 0xF0) | 0x0A); 770 SETFOREGROUNDCOLOR(pApm->Fg8x8); 771 } 772 SETPATTERN(patx, paty); 773#ifdef FASTER 774 SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | 775 DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER | 776 (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | 777 DEC_QUICKSTART_ONDIMX); 778 SETWIDTHHEIGHT(w, h); 779#else 780 SETWIDTHHEIGHT(w, h); 781 SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | 782 DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER | 783 (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | 784 DEC_START); 785#endif 786} 787 788#if 0 789static void 790A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg, 791 int rop, unsigned int planemask) 792{ 793 APMDECL(pScrn); 794 795 DPRINTNAME(SetupForCPUToScreenColorExpandFill); 796 if (bg == -1) 797 { 798#ifndef FASTER 799 pApm->apmTransparency = TRUE; 800 A(WaitForFifo)(pApm, 3); 801#else 802 A(WaitForFifo)(pApm, 4); 803 SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 804 DEC_SOURCE_TRANSPARENCY | DEC_SOURCE_MONOCHROME | DEC_QUICKSTART_ONDIMX | 805 DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC); 806#endif 807 SETFOREGROUNDCOLOR(fg); 808 SETBACKGROUNDCOLOR(fg+1); 809 } 810 else 811 { 812#ifndef FASTER 813 pApm->apmTransparency = FALSE; 814 A(WaitForFifo)(pApm, 3); 815#else 816 A(WaitForFifo)(pApm, 4); 817 SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 818 DEC_DEST_UPD_TRCORNER | DEC_SOURCE_MONOCHROME | 819 DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); 820#endif 821 SETFOREGROUNDCOLOR(fg); 822 SETBACKGROUNDCOLOR(bg); 823 } 824 SETROP(apmROP[rop]); 825} 826 827static void 828A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, 829 int w, int h, int skipleft) 830{ 831 APMDECL(pScrn); 832#ifndef FASTER 833 u32 c; 834#endif 835 836 DPRINTNAME(SubsequentCPUToScreenColorExpandFill); 837#ifndef FASTER 838 c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 839 DEC_SOURCE_MONOCHROME | DEC_START | DEC_DEST_UPD_TRCORNER | 840 pApm->CurrentLayout.Setup_DEC; 841 842 if (pApm->apmTransparency) 843 c |= DEC_SOURCE_TRANSPARENCY; 844 845 A(WaitForFifo)(pApm, 7); 846#else 847 A(WaitForFifo)(pApm, 6); 848#endif 849 850 SETCLIP_LEFTTOP(x+skipleft, y); 851 SETCLIP_RIGHTBOT(x+w-1, y+h-1); 852 SETCLIP_CTRL(0x01); 853 pApm->apmClip = TRUE; 854 SETSOURCEX(0); /* According to manual, it just has to be zero */ 855 SETDESTXY(x, y); 856 SETWIDTHHEIGHT((w + 31) & ~31, h); 857 UPDATEDEST(x + ((w + 31) & ~31), y); 858 859#ifndef FASTER 860 SETDEC(c); 861#endif 862} 863#endif 864 865static void 866A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, unsigned int planemask, 867 int trans_color, int bpp, int depth) 868{ 869 APMDECL(pScrn); 870 871 DPRINTNAME(SetupForImageWrite); 872 if (trans_color != -1) 873 { 874#ifndef FASTER 875 pApm->apmTransparency = TRUE; 876 A(WaitForFifo)(pApm, 3); 877#else 878 A(WaitForFifo)(pApm, 4); 879 SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 880 DEC_SOURCE_TRANSPARENCY | DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); 881#endif 882 SETBACKGROUNDCOLOR(trans_color); 883 } 884 else { 885#ifndef FASTER 886 pApm->apmTransparency = FALSE; 887 A(WaitForFifo)(pApm, 2); 888#else 889 A(WaitForFifo)(pApm, 3); 890 SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 891 DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); 892#endif 893 } 894 895 SETROP(apmROP[rop]); 896} 897 898static void 899A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 900 int skipleft) 901{ 902 APMDECL(pScrn); 903#ifndef FASTER 904 u32 c; 905#endif 906 907 DPRINTNAME(SubsequentImageWriteRect); 908#ifndef FASTER 909 c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | 910 DEC_START | pApm->CurrentLayout.Setup_DEC; 911 912 if (pApm->apmTransparency) 913 c |= DEC_SOURCE_TRANSPARENCY; 914 915 if (pApm->Chipset >= AT24) 916 A(WaitForFifo)(pApm, 7); 917 else 918 A(WaitForFifo)(pApm, 3); 919#else 920 if (pApm->Chipset >= AT24) 921 A(WaitForFifo)(pApm, 6); 922 else 923 A(WaitForFifo)(pApm, 3); 924#endif 925 926 SETCLIP_LEFTTOP(x+skipleft, y); 927 SETCLIP_RIGHTBOT(x+w-1, y+h-1); 928 SETCLIP_CTRL(0x01); 929 pApm->apmClip = TRUE; 930 if (pApm->Chipset < AT24) 931 A(WaitForFifo)(pApm, 4); 932 SETSOURCEX(0); /* According to manual, it just has to be zero */ 933 SETDESTXY(x, y); 934 SETWIDTHHEIGHT((w + 3) & ~3, h); 935 936#ifndef FASTER 937 SETDEC(c); 938#endif 939} 940 941static void 942A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, 943 int w, int h, int srcx, int srcy, 944 int offset) 945{ 946 APMDECL(pScrn); 947 u32 c; 948 949 DPRINTNAME(SubsequentScreenToScreenColorExpandFill); 950#ifdef FASTER 951 c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | 952 DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC; 953#else 954 c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | 955 DEC_START | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC; 956#endif 957 958 if (pApm->apmTransparency) 959 c |= DEC_SOURCE_TRANSPARENCY; 960 961 if (srcy >= pApm->CurrentLayout.Scanlines) { 962 struct ApmStippleCacheRec *pCache; 963 CARD32 dist; 964 965 /* 966 * Offscreen linear stipple 967 */ 968 pCache = &pApm->apmCache[srcy / pApm->CurrentLayout.Scanlines - 1]; 969 if (w != pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel) { 970 A(WaitForFifo)(pApm, 3); 971 SETCLIP_LEFTTOP(x, y); 972 SETCLIP_RIGHTBOT(x + w - 1, y + h - 1); 973 SETCLIP_CTRL(0x01); 974 pApm->apmClip = TRUE; 975 w = pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel; 976 x -= srcx - pCache->apmStippleCache.x + offset; 977 srcx = (srcy - pCache->apmStippleCache.y) & 7; 978 srcy -= srcx; 979 y -= srcx; 980 h += srcx; 981 srcx = pCache->apmStippleCache.x; 982 } 983 else if (pApm->apmClip) { 984 A(WaitForFifo)(pApm, 1); 985 SETCLIP_CTRL(0x00); 986 pApm->apmClip = FALSE; 987 } 988 srcx += (srcy - pCache->apmStippleCache.y) * pCache->apmStippleCache.w; 989 srcy = pCache->apmStippleCache.y % pApm->CurrentLayout.Scanlines; 990 dist = srcx + srcy * pApm->CurrentLayout.displayWidth; 991 srcx = dist & 0xFFF; 992 srcy = dist >> 12; 993 c |= DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR; 994 } 995 else if (offset) { 996 A(WaitForFifo)(pApm, 3); 997 SETCLIP_LEFTTOP(x, y); 998 SETCLIP_RIGHTBOT(x + w, y + h); 999 SETCLIP_CTRL(0x01); 1000 pApm->apmClip = TRUE; 1001 w += offset; 1002 x -= offset; 1003 } 1004 else if (pApm->apmClip) { 1005 A(WaitForFifo)(pApm, 1); 1006 SETCLIP_CTRL(0x00); 1007 pApm->apmClip = FALSE; 1008 } 1009 1010 A(WaitForFifo)(pApm, 4); 1011 1012 SETSOURCEXY(srcx, srcy); 1013 SETDESTXY(x, y); 1014 1015#ifdef FASTER 1016 SETDEC(c); 1017 SETWIDTHHEIGHT(w, h); 1018#else 1019 SETWIDTHHEIGHT(w, h); 1020 SETDEC(c); 1021#endif 1022 UPDATEDEST(x + w + 1, h); 1023} 1024 1025static void 1026A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int e1, 1027 int e2, int err, int length, int octant) 1028{ 1029 APMDECL(pScrn); 1030#ifdef FASTER 1031 u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | 1032 pApm->CurrentLayout.Setup_DEC; 1033#else 1034 u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC; 1035#endif 1036 int tmp; 1037 1038 DPRINTNAME(SubsequentSolidBresenhamLine); 1039 1040 A(WaitForFifo)(pApm, 5); 1041 SETDESTXY(x1,y1); 1042 SETDDA_ERRORTERM(err); 1043 SETDDA_ADSTEP(e1, e2); 1044 1045 if (octant & YMAJOR) { 1046 c |= DEC_MAJORAXIS_Y; 1047 tmp = e1; e1 = e2; e2 = tmp; 1048 } 1049 else 1050 c |= DEC_MAJORAXIS_X; 1051 1052 if (octant & XDECREASING) { 1053 c |= DEC_DIR_X_NEG; 1054 e1 = -e1; 1055 } 1056 else 1057 c |= DEC_DIR_X_POS; 1058 1059 if (octant & YDECREASING) { 1060 c |= DEC_DIR_Y_NEG; 1061 e2 = -e2; 1062 } 1063 else 1064 c |= DEC_DIR_Y_POS; 1065 1066#ifdef FASTER 1067 SETDEC(c); 1068 SETWIDTH(length); 1069#else 1070 SETWIDTH(length); 1071 SETDEC(c); 1072#endif 1073 1074 if (octant & YMAJOR) 1075 UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2); 1076 else 1077 UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2); 1078 if (pApm->apmClip) 1079 { 1080 pApm->apmClip = FALSE; 1081 A(WaitForFifo)(pApm, 1); 1082 SETCLIP_CTRL(0); 1083 } 1084} 1085 1086static void 1087A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int e1, 1088 int e2, int err, int length, int octant) 1089{ 1090 APMDECL(pScrn); 1091#ifdef FASTER 1092 u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | 1093 pApm->CurrentLayout.Setup_DEC; 1094#else 1095 u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC; 1096#endif 1097 int tmp; 1098 1099 DPRINTNAME(SubsequentSolidBresenhamLine6422); 1100 1101 A(WaitForFifo)(pApm, 1); 1102 SETDESTXY(x1,y1); 1103 A(WaitForFifo)(pApm, 4); 1104 SETDDA_ERRORTERM(err); 1105 SETDDA_ADSTEP(e1, e2); 1106 1107 if (octant & YMAJOR) { 1108 c |= DEC_MAJORAXIS_Y; 1109 tmp = e1; e1 = e2; e2 = tmp; 1110 } 1111 else 1112 c |= DEC_MAJORAXIS_X; 1113 1114 if (octant & XDECREASING) { 1115 c |= DEC_DIR_X_NEG; 1116 e1 = -e1; 1117 } 1118 else 1119 c |= DEC_DIR_X_POS; 1120 1121 if (octant & YDECREASING) { 1122 c |= DEC_DIR_Y_NEG; 1123 e2 = -e2; 1124 } 1125 else 1126 c |= DEC_DIR_Y_POS; 1127 1128#ifdef FASTER 1129 SETDEC(c); 1130 SETWIDTH(length); 1131#else 1132 SETWIDTH(length); 1133 SETDEC(c); 1134#endif 1135 1136 if (octant & YMAJOR) 1137 UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2); 1138 else 1139 UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2); 1140 if (pApm->apmClip) 1141 { 1142 pApm->apmClip = FALSE; 1143 A(WaitForFifo)(pApm, 1); 1144 SETCLIP_CTRL(0); 1145 } 1146} 1147 1148static void 1149A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) 1150{ 1151 APMDECL(pScrn); 1152 1153 DPRINTNAME(SetClippingRectangle); 1154 A(WaitForFifo)(pApm, 3); 1155 SETCLIP_LEFTTOP(x1,y1); 1156 SETCLIP_RIGHTBOT(x2,y2); 1157 SETCLIP_CTRL(0x01); 1158 pApm->apmClip = TRUE; 1159} 1160 1161static void 1162A(SyncBlt)(ApmPtr pApm) 1163{ 1164 int again = (pApm->Chipset == AP6422); 1165 1166 do { 1167 while (!(STATUS() & STATUS_HOSTBLTBUSY)) 1168 ; 1169 } 1170 while (again--); /* See remark in Sync6422 */ 1171} 1172static void 1173A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, 1174 unsigned char *src, int srcwidth, int rop, 1175 unsigned int planemask, int trans, int bpp, int depth) 1176{ 1177 APMDECL(pScrn); 1178 int dwords, skipleft, Bpp = bpp >> 3; 1179 Bool beCareful = FALSE; 1180 unsigned char *dst = ((unsigned char *)pApm->FbBase) + x * Bpp + y * pApm->CurrentLayout.bytesPerScanline; 1181 int PlusOne = 0, mask, count; 1182 1183 DPRINTNAME(WritePixmap); 1184 if (rop == GXnoop) 1185 return; 1186 /* 1187 * The function seems to crash more than it feels good. I hope that a 1188 * good sync will help. This sync is anyway needed for direct write. 1189 */ 1190 (*pApm->AccelInfoRec->Sync)(pScrn); 1191 /* 1192 * First the fast case : source and dest have same alignment. Doc says 1193 * it's faster to do it here, which may be true since one has to read 1194 * the chip when CPU to screen-ing. 1195 */ 1196 if ((skipleft = (long)src & 3L) == ((long)dst & 3L) && rop == GXcopy) { 1197 int skipright; 1198 1199 if (skipleft) 1200 skipleft = 4 - skipleft; 1201 dwords = (skipright = w * Bpp - skipleft) >> 2; 1202 skipright %= 4; 1203 if (!skipleft && !skipright) 1204 while (h-- > 0) { 1205 CARD32 *src2 = (CARD32 *)src; 1206 CARD32 *dst2 = (CARD32 *)dst; 1207 1208 for (count = dwords; count-- > 0; ) 1209 *dst2++ = *src2++; 1210 src += srcwidth; 1211 dst += pApm->CurrentLayout.bytesPerScanline; 1212 } 1213 else if (!skipleft) 1214 while (h-- > 0) { 1215 CARD32 *src2 = (CARD32 *)src; 1216 CARD32 *dst2 = (CARD32 *)dst; 1217 1218 for (count = dwords; count-- > 0; ) 1219 *dst2++ = *src2++; 1220 for (count = skipright; count-- > 0; ) 1221 ((char *)dst2)[count] = ((char *)src2)[count]; 1222 src += srcwidth; 1223 dst += pApm->CurrentLayout.bytesPerScanline; 1224 } 1225 else if (!skipright) 1226 while (h-- > 0) { 1227 CARD32 *src2 = (CARD32 *)(src + skipleft); 1228 CARD32 *dst2 = (CARD32 *)(dst + skipleft); 1229 1230 for (count = skipleft; count-- > 0; ) 1231 dst[count] = src[count]; 1232 for (count = dwords; count-- > 0; ) 1233 *dst2++ = *src2++; 1234 src += srcwidth; 1235 dst += pApm->CurrentLayout.bytesPerScanline; 1236 } 1237 else 1238 while (h-- > 0) { 1239 CARD32 *src2 = (CARD32 *)(src + skipleft); 1240 CARD32 *dst2 = (CARD32 *)(dst + skipleft); 1241 1242 for (count = skipleft; count-- > 0; ) 1243 dst[count] = src[count]; 1244 for (count = dwords; count-- > 0; ) 1245 *dst2++ = *src2++; 1246 for (count = skipright; count-- > 0; ) 1247 ((char *)dst2)[count] = ((char *)src2)[count]; 1248 src += srcwidth; 1249 dst += pApm->CurrentLayout.bytesPerScanline; 1250 } 1251 1252 return; 1253 } 1254 1255 if (skipleft) { 1256 if (Bpp == 3) 1257 skipleft = 4 - skipleft; 1258 else 1259 skipleft /= Bpp; 1260 1261 if (x < skipleft) { 1262 skipleft = 0; 1263 beCareful = TRUE; 1264 goto BAD_ALIGNMENT; 1265 } 1266 1267 x -= skipleft; 1268 w += skipleft; 1269 1270 if (Bpp == 3) 1271 src -= 3 * skipleft; 1272 else /* is this Alpha friendly ? */ 1273 src = (unsigned char*)((long)src & ~0x03L); 1274 } 1275 1276BAD_ALIGNMENT: 1277 1278 dwords = ((w * Bpp) + 3) >> 2; 1279 mask = (pApm->CurrentLayout.bitsPerPixel / 8) - 1; 1280 1281 if (dwords & mask) { 1282 /* 1283 * Experimental... 1284 * It seems the AT3D needs a padding of scanline to a multiple of 1285 * 4 pixels, not only bytes. 1286 */ 1287 PlusOne = mask - (dwords & mask) + 1; 1288 } 1289 1290 A(SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth); 1291 A(SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft); 1292 1293 if (beCareful) { 1294 /* in cases with bad alignment we have to be careful not 1295 to read beyond the end of the source */ 1296 if (((x * Bpp) + (dwords << 2)) > srcwidth) h--; 1297 else beCareful = FALSE; 1298 } 1299 1300 srcwidth -= (dwords << 2); 1301 1302 while (h--) { 1303 for (count = dwords; count-- > 0; ) { 1304 A(SyncBlt)(pApm); 1305 *(CARD32*)pApm->BltMap = *(CARD32*)src; 1306 src += 4; 1307 } 1308 src += srcwidth; 1309 for (count = PlusOne; count-- > 0; ) { 1310 int status; 1311 1312 while (!((status = STATUS()) & STATUS_HOSTBLTBUSY)) 1313 if (!(status & STATUS_ENGINEBUSY)) 1314 break; 1315 if (pApm->Chipset == AP6422) /* See remark in Sync6422 */ 1316 while (!((status = STATUS()) & STATUS_HOSTBLTBUSY)) 1317 if (!(status & STATUS_ENGINEBUSY)) 1318 break; 1319 if (status & STATUS_ENGINEBUSY) 1320 *(CARD32*)pApm->BltMap = 0x00000000; 1321 } 1322 } 1323 if (beCareful) { 1324 int shift = ((long)src & 0x03L) << 3; 1325 1326 if (--dwords) { 1327 for (count = dwords >> 2; count-- > 0; ) { 1328 A(SyncBlt)(pApm); 1329 *(CARD32*)pApm->BltMap = *(CARD32*)src; 1330 src += 4; 1331 } 1332 } 1333 A(SyncBlt)(pApm); 1334 *((CARD32*)pApm->BltMap) = *((CARD32*)src) >> shift; 1335 } 1336 1337 pApm->apmClip = FALSE; 1338 A(WaitForFifo)(pApm, 1); 1339 SETCLIP_CTRL(0); 1340} 1341 1342static void 1343A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, unsigned int planemask, 1344 int nBox, BoxPtr pBox, int xorg, int yorg, 1345 PixmapPtr pPix) 1346{ 1347 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1348 int x, y, phaseY, phaseX, height, width, blit_w; 1349 int pHeight = pPix->drawable.height; 1350 int pWidth = pPix->drawable.width; 1351 int depth = pPix->drawable.depth; 1352 int bpp = pPix->drawable.bitsPerPixel; 1353 unsigned char *pSrc; 1354 int srcwidth = pPix->devKind; 1355 1356 while(nBox--) { 1357 x = pBox->x1; 1358 y = pBox->y1; 1359 phaseY = (pBox->y1 - yorg) % pHeight; 1360 if(phaseY < 0) phaseY += pHeight; 1361 phaseX = (x - xorg) % pWidth; 1362 pSrc = (unsigned char *)pPix->devPrivate.ptr + 1363 phaseX * pPix->drawable.bitsPerPixel / 8; 1364 if(phaseX < 0) phaseX += pWidth; 1365 height = pBox->y2 - pBox->y1; 1366 width = pBox->x2 - x; 1367 1368 while(1) { 1369 int ch = height, cp = phaseY, cy = y; 1370 1371 blit_w = pWidth - phaseX; 1372 if(blit_w > width) blit_w = width; 1373 1374 while (ch > 0) { 1375 int h = MIN(pHeight - cp, ch); 1376 1377 A(WritePixmap)(pScrn, x, cy, blit_w, h, pSrc + cp * srcwidth, 1378 srcwidth, rop, planemask, FALSE, bpp, depth); 1379 cy += h; 1380 ch -= h; 1381 cp = 0; 1382 } 1383 1384 width -= blit_w; 1385 if(!width) break; 1386 x += blit_w; 1387 phaseX = (phaseX + blit_w) % pWidth; 1388 } 1389 pBox++; 1390 } 1391 1392 SET_SYNC_FLAG(infoRec); 1393} 1394 1395static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty, 1396 int rop, unsigned int planemask, 1397 int transparency_color) 1398{ 1399 APMDECL(pScrn); 1400 1401 DPRINTNAME(SetupForColor8x8PatternFillRect); 1402 if (transparency_color != -1) { 1403#ifndef FASTER 1404 pApm->apmTransparency = TRUE; 1405 A(WaitForFifo)(pApm, 2 + pApm->apmClip); 1406#else 1407 A(WaitForFifo)(pApm, 3 + pApm->apmClip); 1408 SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | 1409 DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_SOURCE_TRANSPARENCY | 1410 DEC_QUICKSTART_ONDIMX); 1411#endif 1412 SETBACKGROUNDCOLOR(transparency_color); 1413 } 1414 else { 1415#ifndef FASTER 1416 pApm->apmTransparency = FALSE; 1417 A(WaitForFifo)(pApm, 1 + pApm->apmClip); 1418#else 1419 A(WaitForFifo)(pApm, 2 + pApm->apmClip); 1420 SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | 1421 DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_QUICKSTART_ONDIMX); 1422#endif 1423 } 1424 if (pApm->apmClip) { 1425 SETCLIP_CTRL(0); 1426 pApm->apmClip = FALSE; 1427 } 1428 SETROP(apmROP[rop]); 1429} 1430 1431static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, 1432 int paty, int x, int y, 1433 int w, int h) 1434{ 1435 APMDECL(pScrn); 1436 1437 DPRINTNAME(SubsequentColor8x8PatternFillRect); 1438#ifndef FASTER 1439 A(WaitForFifo)(pApm, 5); 1440#else 1441 A(WaitForFifo)(pApm, 4); 1442#endif 1443 SETSOURCEXY(patx, paty); 1444 SETDESTXY(x, y); 1445 SETWIDTHHEIGHT(w, h); 1446 UPDATEDEST(x + w + 1, y); 1447#ifndef FASTER 1448 SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | 1449 DEC_DEST_XY | (pApm->apmTransparency * DEC_SOURCE_TRANSPARENCY) | 1450 DEC_PATTERN_88_8bCOLOR | DEC_START); 1451#endif 1452} 1453#endif 1454 1455static void 1456A(Sync)(ScrnInfoPtr pScrn) 1457{ 1458 APMDECL(pScrn); 1459 volatile u32 i, stat; 1460 1461 for(i = 0; i < MAXLOOP; i++) { 1462 stat = STATUS(); 1463 if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) && 1464 ((stat & STATUS_FIFO) >= 8)) 1465 break; 1466 } 1467 if (i == MAXLOOP) { 1468 unsigned int status = STATUS(); 1469 1470 WRXB(0x1FF, 0); 1471 if (!xf86ServerIsExiting()) 1472 FatalError("Hung in ApmSync" APM_SUFF_24 "(%d) (Status = 0x%08X)\n", pScrn->pScreen->myNum, status); 1473 } 1474 if (pApm->apmClip) { 1475 SETCLIP_CTRL(0); 1476 pApm->apmClip = FALSE; 1477 } 1478} 1479 1480#if PSZ != 24 1481static void 1482A(Sync6422)(ScrnInfoPtr pScrn) 1483{ 1484 APMDECL(pScrn); 1485 volatile u32 i, j, stat; 1486 1487 for (j = 0; j < 2; j++) { 1488 /* 1489 * From Henrik Harmsen : 1490 * 1491 * This is a kludge. We can't trust the status register. Don't 1492 * know why... We shouldn't be forced to read the status reg and get 1493 * a correct value more than once... 1494 */ 1495 for(i = 0; i < MAXLOOP; i++) { 1496 stat = STATUS(); 1497 if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) && 1498 ((stat & STATUS_FIFO) >= 4)) 1499 break; 1500 } 1501 } 1502 if (i == MAXLOOP) { 1503 unsigned int status = STATUS(); 1504 1505 WRXB(0x1FF, 0); 1506 if (!xf86ServerIsExiting()) 1507 FatalError("Hung in ApmSync6422() (Status = 0x%08X)\n", status); 1508 } 1509 if (pApm->apmClip) { 1510 SETCLIP_CTRL(0); 1511 pApm->apmClip = FALSE; 1512 } 1513} 1514#endif 1515#include "apm_video.c" 1516 1517 1518#undef RDXB 1519#undef RDXW 1520#undef RDXL 1521#undef WRXB 1522#undef WRXW 1523#undef WRXL 1524#undef ApmWriteSeq 1525#define RDXB RDXB_M 1526#define RDXW RDXW_M 1527#define RDXL RDXL_M 1528#define WRXB WRXB_M 1529#define WRXW WRXW_M 1530#define WRXL WRXL_M 1531#define ApmWriteSeq(idx, val) do { APMVGAB(0x3C4) = (idx); APMVGAB(0x3C5) = (val); break; } while(1) 1532#undef DPRINTNAME 1533#undef A 1534#undef DEPTH 1535#undef PSZ 1536#undef APM_SUFF_24 1537