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