smi_xaa.c revision 09885543
1/* 2Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 3Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a copy of 6this software and associated documentation files (the "Software"), to deal in 7the Software without restriction, including without limitation the rights to 8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9of the Software, and to permit persons to whom the Software is furnished to do 10so, subject to the following conditions: 11 12The above copyright notice and this permission notice shall be included in all 13copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the names of the XFree86 Project and 23Silicon Motion shall not be used in advertising or otherwise to promote the 24sale, use or other dealings in this Software without prior written 25authorization from the XFree86 Project and silicon Motion. 26*/ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "smi.h" 33 34#include "miline.h" 35#include "xaalocal.h" 36#include "xaarop.h" 37#include "servermd.h" 38 39static void SMI_SetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int, 40 unsigned int, int); 41static void SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int, 42 int, int); 43static void SMI_SetupForSolidFill(ScrnInfoPtr, int, int, unsigned); 44static void SMI_SubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int); 45static void SMI_SubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int); 46static void SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, 47 unsigned int); 48static void SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int, 49 int, int); 50static void SMI_SetupForMono8x8PatternFill(ScrnInfoPtr, int, int, int, int, int, 51 unsigned int); 52static void SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr, int, int, int, 53 int, int, int); 54static void SMI_SetupForColor8x8PatternFill(ScrnInfoPtr, int, int, int, 55 unsigned int, int); 56static void SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr, int, int, int, 57 int, int, int); 58#if SMI_USE_IMAGE_WRITES 59static void SMI_SetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, int, 60 int); 61static void SMI_SubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int); 62#endif 63/* #671 */ 64static void SMI_ValidatePolylines(GCPtr, unsigned long, DrawablePtr); 65static void SMI_Polylines(DrawablePtr, GCPtr, int, int, DDXPointPtr); 66 67 68Bool 69SMI_XAAInit(ScreenPtr pScreen) 70{ 71 XAAInfoRecPtr infoPtr; 72 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 73 SMIPtr pSmi = SMIPTR(pScrn); 74 /*BoxRec AvailFBArea;*/ 75 Bool ret; 76 /*int numLines, maxLines;*/ 77 78 ENTER_PROC("SMI_XAAInit"); 79 80 pSmi->XAAInfoRec = infoPtr = XAACreateInfoRec(); 81 if (infoPtr == NULL) { 82 LEAVE_PROC("SMI_AccelInit"); 83 return FALSE; 84 } 85 86 infoPtr->Flags = PIXMAP_CACHE 87 | LINEAR_FRAMEBUFFER 88 | OFFSCREEN_PIXMAPS; 89 90 infoPtr->Sync = SMI_AccelSync; 91 92 /* Screen to screen copies */ 93 infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK 94 | ONLY_TWO_BITBLT_DIRECTIONS; 95 infoPtr->SetupForScreenToScreenCopy = SMI_SetupForScreenToScreenCopy; 96 infoPtr->SubsequentScreenToScreenCopy = SMI_SubsequentScreenToScreenCopy; 97 if (pScrn->bitsPerPixel == 24) { 98 infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; 99 } 100 if ((pSmi->Chipset == SMI_LYNX3D) && (pScrn->bitsPerPixel == 8)) { 101 infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY; 102 } 103 104 /* Solid Fills */ 105 infoPtr->SolidFillFlags = NO_PLANEMASK; 106 infoPtr->SetupForSolidFill = SMI_SetupForSolidFill; 107 infoPtr->SubsequentSolidFillRect = SMI_SubsequentSolidFillRect; 108 109 /* Solid Lines */ 110 infoPtr->SolidLineFlags = NO_PLANEMASK; 111 infoPtr->SetupForSolidLine = SMI_SetupForSolidFill; 112 infoPtr->SubsequentSolidHorVertLine = SMI_SubsequentSolidHorVertLine; 113 114 /* Color Expansion Fills */ 115 infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE 116 | NO_PLANEMASK 117 | BIT_ORDER_IN_BYTE_MSBFIRST 118 | LEFT_EDGE_CLIPPING 119 | CPU_TRANSFER_PAD_DWORD 120 | SCANLINE_PAD_DWORD; 121 infoPtr->ColorExpandBase = pSmi->DataPortBase; 122 infoPtr->ColorExpandRange = pSmi->DataPortSize; 123 infoPtr->SetupForCPUToScreenColorExpandFill = 124 SMI_SetupForCPUToScreenColorExpandFill; 125 infoPtr->SubsequentCPUToScreenColorExpandFill = 126 SMI_SubsequentCPUToScreenColorExpandFill; 127 128 /* 8x8 Mono Pattern Fills */ 129 infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK 130 | HARDWARE_PATTERN_PROGRAMMED_BITS 131 | HARDWARE_PATTERN_SCREEN_ORIGIN 132 | BIT_ORDER_IN_BYTE_MSBFIRST; 133 infoPtr->SetupForMono8x8PatternFill = SMI_SetupForMono8x8PatternFill; 134 infoPtr->SubsequentMono8x8PatternFillRect = 135 SMI_SubsequentMono8x8PatternFillRect; 136 137 /* 8x8 Color Pattern Fills */ 138 if (!SMI_LYNX3D_SERIES(pSmi->Chipset) || (pScrn->bitsPerPixel != 24)) { 139 infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK 140 | HARDWARE_PATTERN_SCREEN_ORIGIN; 141 infoPtr->SetupForColor8x8PatternFill = 142 SMI_SetupForColor8x8PatternFill; 143 infoPtr->SubsequentColor8x8PatternFillRect = 144 SMI_SubsequentColor8x8PatternFillRect; 145 } 146 147#if SMI_USE_IMAGE_WRITES 148 /* Image Writes */ 149 infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE 150 | NO_PLANEMASK 151 | CPU_TRANSFER_PAD_DWORD 152 | SCANLINE_PAD_DWORD; 153 infoPtr->ImageWriteBase = pSmi->DataPortBase; 154 infoPtr->ImageWriteRange = pSmi->DataPortSize; 155 infoPtr->SetupForImageWrite = SMI_SetupForImageWrite; 156 infoPtr->SubsequentImageWriteRect = SMI_SubsequentImageWriteRect; 157#endif 158 159 /* Clipping */ 160 infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY 161 | HARDWARE_CLIP_MONO_8x8_FILL 162 | HARDWARE_CLIP_COLOR_8x8_FILL 163 | HARDWARE_CLIP_SOLID_FILL 164 | HARDWARE_CLIP_SOLID_LINE 165 | HARDWARE_CLIP_DASHED_LINE; 166 infoPtr->SetClippingRectangle = SMI_SetClippingRectangle; 167 infoPtr->DisableClipping = SMI_DisableClipping; 168 169 /* Pixmap Cache */ 170 if (pScrn->bitsPerPixel == 24) { 171 infoPtr->CachePixelGranularity = 16; 172 } else { 173 infoPtr->CachePixelGranularity = 128 / pScrn->bitsPerPixel; 174 } 175 176 /* Offscreen Pixmaps */ 177 infoPtr->maxOffPixWidth = 4096; 178 infoPtr->maxOffPixHeight = 4096; 179 if (pScrn->bitsPerPixel == 24) { 180 infoPtr->maxOffPixWidth = 4096 / 3; 181 182 if (pSmi->Chipset == SMI_LYNX) { 183 infoPtr->maxOffPixHeight = 4096 / 3; 184 } 185 } 186 187 SMI_EngineReset(pScrn); 188 189 190 /* CZ 18.06.2001: moved to smi_driver.c before the NoAccel question 191 to have offscreen framebuffer in NoAccel mode */ 192#if 0 193 maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp); 194 if (pSmi->rotate) { 195 numLines = maxLines; 196 } else { 197#if SMI_USE_VIDEO 198 numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp * pSmi->height) 199 * 25 / 100 + pSmi->width * pSmi->Bpp - 1) 200 / (pSmi->width * pSmi->Bpp); 201 numLines += pSmi->height; 202#else 203 numLines = maxLines; 204#endif 205 } 206 207 AvailFBArea.x1 = 0; 208 AvailFBArea.y1 = 0; 209 AvailFBArea.x2 = pSmi->width; 210 AvailFBArea.y2 = numLines; 211 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FrameBuffer Box: %d,%d - %d,%d\n", 212 AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2); 213 xf86InitFBManager(pScreen, &AvailFBArea); 214#endif 215 216 ret = XAAInit(pScreen, infoPtr); 217 if (ret && pSmi->shadowFB) /* #671 */ { 218 pSmi->ValidatePolylines = infoPtr->ValidatePolylines; 219 infoPtr->ValidatePolylines = SMI_ValidatePolylines; 220 } 221 222 LEAVE_PROC("SMI_XAAInit"); 223 return ret; 224} 225 226/******************************************************************************/ 227/* Screen to Screen Copies */ 228/******************************************************************************/ 229 230static void 231SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, 232 unsigned int planemask, int trans) 233{ 234 SMIPtr pSmi = SMIPTR(pScrn); 235 236 ENTER_PROC("SMI_SetupForScreenToScreenCopy"); 237 DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir, 238 rop, trans)); 239 240 pSmi->AccelCmd = XAAGetCopyROP(rop) 241 | SMI_BITBLT 242 | SMI_START_ENGINE; 243 244 if ((xdir == -1) || (ydir == -1)) { 245 pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT; 246 } 247 248 if (trans != -1) { 249 pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; 250 WaitQueue(1); 251 WRITE_DPR(pSmi, 0x20, trans); 252 } 253 254 if (pSmi->ClipTurnedOn) { 255 WaitQueue(1); 256 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 257 pSmi->ClipTurnedOn = FALSE; 258 } 259 260 LEAVE_PROC("SMI_SetupForScreenToScreenCopy"); 261} 262 263static void 264SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, 265 int y2, int w, int h) 266{ 267 SMIPtr pSmi = SMIPTR(pScrn); 268 269 ENTER_PROC("SMI_SubsequentScreenToScreenCopy"); 270 DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w, h)); 271 272 if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { 273 x1 += w - 1; 274 y1 += h - 1; 275 x2 += w - 1; 276 y2 += h - 1; 277 } 278 279 if (pScrn->bitsPerPixel == 24) { 280 x1 *= 3; 281 x2 *= 3; 282 w *= 3; 283 284 if (pSmi->Chipset == SMI_LYNX) { 285 y1 *= 3; 286 y2 *= 3; 287 } 288 289 if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { 290 x1 += 2; 291 x2 += 2; 292 } 293 } 294 295 WaitQueue(4); 296 WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF)); 297 WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF)); 298 WRITE_DPR(pSmi, 0x08, (w << 16) + (h & 0xFFFF)); 299 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 300 301 LEAVE_PROC("SMI_SubsequentScreenToScreenCopy"); 302} 303 304/******************************************************************************/ 305/* Solid Fills */ 306/******************************************************************************/ 307 308static void 309SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 310 unsigned int planemask) 311{ 312 SMIPtr pSmi = SMIPTR(pScrn); 313 314 ENTER_PROC("SMI_SetupForSolidFill"); 315 DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop)); 316 317 pSmi->AccelCmd = XAAGetPatternROP(rop) 318 | SMI_BITBLT 319 | SMI_START_ENGINE; 320 321 if (pSmi->ClipTurnedOn) { 322 WaitQueue(4); 323 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 324 pSmi->ClipTurnedOn = FALSE; 325 } else { 326 WaitQueue(3); 327 } 328 WRITE_DPR(pSmi, 0x14, color); 329 WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF); 330 WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF); 331 332 LEAVE_PROC("SMI_SetupForSolidFill"); 333} 334 335void 336SMI_SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 337{ 338 SMIPtr pSmi = SMIPTR(pScrn); 339 340 ENTER_PROC("SMI_SubsequentSolidFillRect"); 341 DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); 342 343 if (pScrn->bitsPerPixel == 24) { 344 x *= 3; 345 w *= 3; 346 347 if (pSmi->Chipset == SMI_LYNX) { 348 y *= 3; 349 } 350 } 351 352 WaitQueue(3); 353 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 354 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 355 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 356 357 LEAVE_PROC("SMI_SubsequentSolidFillRect"); 358} 359 360/******************************************************************************/ 361/* Solid Lines */ 362/******************************************************************************/ 363 364static void 365SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, 366 int dir) 367{ 368 SMIPtr pSmi = SMIPTR(pScrn); 369 int w, h; 370 371 ENTER_PROC("SMI_SubsequentSolidHorVertLine"); 372 DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir)); 373 374 if (dir == DEGREES_0) { 375 w = len; 376 h = 1; 377 } else { 378 w = 1; 379 h = len; 380 } 381 382 if (pScrn->bitsPerPixel == 24) { 383 x *= 3; 384 w *= 3; 385 386 if (pSmi->Chipset == SMI_LYNX) { 387 y *= 3; 388 } 389 } 390 391 WaitQueue(3); 392 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 393 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 394 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 395 396 LEAVE_PROC("SMI_SubsequentSolidHorVertLine"); 397} 398 399/******************************************************************************/ 400/* Color Expansion Fills */ 401/******************************************************************************/ 402 403static void 404SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, 405 int rop, unsigned int planemask) 406{ 407 SMIPtr pSmi = SMIPTR(pScrn); 408 409 ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill"); 410 DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop)); 411 412 pSmi->AccelCmd = XAAGetCopyROP(rop) 413 | SMI_HOSTBLT_WRITE 414 | SMI_SRC_MONOCHROME 415 | SMI_START_ENGINE; 416 417 if (bg == -1) { 418 pSmi->AccelCmd |= SMI_TRANSPARENT_SRC; 419 420 WaitQueue(3); 421 WRITE_DPR(pSmi, 0x14, fg); 422 WRITE_DPR(pSmi, 0x18, ~fg); 423 WRITE_DPR(pSmi, 0x20, fg); 424 } else { 425 WaitQueue(2); 426 WRITE_DPR(pSmi, 0x14, fg); 427 WRITE_DPR(pSmi, 0x18, bg); 428 } 429 430 LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill"); 431} 432 433void 434SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w, 435 int h, int skipleft) 436{ 437 SMIPtr pSmi = SMIPTR(pScrn); 438 439 ENTER_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); 440 DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); 441 442 if (pScrn->bitsPerPixel == 24) { 443 x *= 3; 444 w *= 3; 445 skipleft *= 3; 446 447 if (pSmi->Chipset == SMI_LYNX) { 448 y *= 3; 449 } 450 } 451 452 if (skipleft) { 453 WaitQueue(5); 454 WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) 455 | (x + skipleft) | 0x2000); 456 pSmi->ClipTurnedOn = TRUE; 457 } else { 458 if (pSmi->ClipTurnedOn) { 459 WaitQueue(5); 460 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 461 pSmi->ClipTurnedOn = FALSE; 462 } else { 463 WaitQueue(4); 464 } 465 } 466 WRITE_DPR(pSmi, 0x00, 0); 467 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 468 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 469 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 470 471 LEAVE_PROC("SMI_SubsequentCPUToScreenColorExpandFill"); 472} 473 474/******************************************************************************/ 475/* 8x8 Mono Pattern Fills */ 476/******************************************************************************/ 477 478static void 479SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg, 480 int bg, int rop, unsigned int planemask) 481{ 482 SMIPtr pSmi = SMIPTR(pScrn); 483 484 ENTER_PROC("SMI_SetupForMono8x8PatternFill"); 485 DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx, 486 paty, fg, bg, rop)); 487 488 pSmi->AccelCmd = XAAGetPatternROP(rop) 489 | SMI_BITBLT 490 | SMI_START_ENGINE; 491 492 if (pSmi->ClipTurnedOn) { 493 WaitQueue(1); 494 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 495 pSmi->ClipTurnedOn = FALSE; 496 } 497 498 if (bg == -1) { 499 WaitQueue(5); 500 WRITE_DPR(pSmi, 0x14, fg); 501 WRITE_DPR(pSmi, 0x18, ~fg); 502 WRITE_DPR(pSmi, 0x20, fg); 503 WRITE_DPR(pSmi, 0x34, patx); 504 WRITE_DPR(pSmi, 0x38, paty); 505 } else { 506 WaitQueue(4); 507 WRITE_DPR(pSmi, 0x14, fg); 508 WRITE_DPR(pSmi, 0x18, bg); 509 WRITE_DPR(pSmi, 0x34, patx); 510 WRITE_DPR(pSmi, 0x38, paty); 511 } 512 513 LEAVE_PROC("SMI_SetupForMono8x8PatternFill"); 514} 515 516static void 517SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, 518 int x, int y, int w, int h) 519{ 520 SMIPtr pSmi = SMIPTR(pScrn); 521 522 ENTER_PROC("SMI_SubsequentMono8x8PatternFillRect"); 523 DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); 524 525 if (pScrn->bitsPerPixel == 24) { 526 x *= 3; 527 w *= 3; 528 if (pSmi->Chipset == SMI_LYNX) { 529 y *= 3; 530 } 531 } 532 533 WaitQueue(3); 534 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 535 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 536 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 537 538 LEAVE_PROC("SMI_SubsequentMono8x8PatternFillRect"); 539} 540 541/******************************************************************************/ 542/* 8x8 Color Pattern Fills */ 543/******************************************************************************/ 544 545static void 546SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop, 547 unsigned int planemask, int trans_color) 548{ 549 SMIPtr pSmi = SMIPTR(pScrn); 550 551 ENTER_PROC("SMI_SetupForColor8x8PatternFill"); 552 DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty, 553 rop, trans_color)); 554 555 pSmi->AccelCmd = XAAGetPatternROP(rop) 556 | SMI_BITBLT 557 | SMI_COLOR_PATTERN 558 | SMI_START_ENGINE; 559 560 if (pScrn->bitsPerPixel <= 16) { 561 /* PDR#950 */ 562 CARD8* pattern = pSmi->FBBase + (patx + paty * pSmi->Stride) * pSmi->Bpp; 563 564 WaitIdleEmpty(); 565 WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN); 566 memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8); 567 } else { 568 if (pScrn->bitsPerPixel == 24) { 569 patx *= 3; 570 571 if (pSmi->Chipset == SMI_LYNX) { 572 paty *= 3; 573 } 574 } 575 576 WaitQueue(1); 577 WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF)); 578 } 579 580 if (trans_color == -1) { 581 pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; 582 583 WaitQueue(1); 584 WRITE_DPR(pSmi, 0x20, trans_color); 585 } 586 587 if (pSmi->ClipTurnedOn) { 588 WaitQueue(1); 589 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 590 pSmi->ClipTurnedOn = FALSE; 591 } 592 593 LEAVE_PROC("SMI_SetupForColor8x8PatternFill"); 594} 595 596static void 597SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, 598 int x, int y, int w, int h) 599{ 600 SMIPtr pSmi = SMIPTR(pScrn); 601 602 ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect"); 603 DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h)); 604 605 if (pScrn->bitsPerPixel == 24) { 606 x *= 3; 607 w *= 3; 608 609 if (pSmi->Chipset == SMI_LYNX) { 610 y *= 3; 611 } 612 } 613 614 WaitQueue(3); 615 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 616 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); /* PDR#950 */ 617 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 618 619 LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect"); 620} 621 622#if SMI_USE_IMAGE_WRITES 623/******************************************************************************/ 624/* Image Writes */ 625/******************************************************************************/ 626 627static void 628SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, 629 int trans_color, int bpp, int depth) 630{ 631 SMIPtr pSmi = SMIPTR(pScrn); 632 633 ENTER_PROC("SMI_SetupForImageWrite"); 634 DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop, 635 trans_color, bpp, depth)); 636 637 pSmi->AccelCmd = XAAGetCopyROP(rop) 638 | SMI_HOSTBLT_WRITE 639 | SMI_START_ENGINE; 640 641 if (trans_color != -1) { 642 pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL; 643 644 WaitQueue(1); 645 WRITE_DPR(pSmi, 0x20, trans_color); 646 } 647 648 LEAVE_PROC("SMI_SetupForImageWrite"); 649} 650 651static void 652SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, 653 int skipleft) 654{ 655 SMIPtr pSmi = SMIPTR(pScrn); 656 657 ENTER_PROC("SMI_SubsequentImageWriteRect"); 658 DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft)); 659 660 if (pScrn->bitsPerPixel == 24) { 661 x *= 3; 662 w *= 3; 663 skipleft *= 3; 664 665 if (pSmi->Chipset == SMI_LYNX) { 666 y *= 3; 667 } 668 } 669 670 if (skipleft) { 671 WaitQueue(5); 672 WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) | 673 (x + skipleft) | 0x2000); 674 pSmi->ClipTurnedOn = TRUE; 675 } else { 676 if (pSmi->ClipTurnedOn) { 677 WaitQueue(5); 678 WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft); 679 pSmi->ClipTurnedOn = FALSE; 680 } else { 681 WaitQueue(4); 682 } 683 } 684 WRITE_DPR(pSmi, 0x00, 0); 685 WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF)); 686 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 687 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 688 689 LEAVE_PROC("SMI_SubsequentImageWriteRect"); 690} 691#endif 692 693/******************************************************************************/ 694/* Polylines #671 */ 695/******************************************************************************/ 696 697/* 698 699In order to speed up the "logout" screen in rotated modes, we need to intercept 700the Polylines function. Normally, the polylines are drawn and the shadowFB is 701then sending a request of the bounding rectangle of those poylines. This should 702be okay, if it weren't for the fact that the Gnome logout screen is drawing 703polylines in rectangles and this asks for a rotation of the entire rectangle. 704This is very slow. 705 706To circumvent this slowness, we intercept the ValidatePolylines function and 707override the default "Fallback" Polylines with our own Polylines function. Our 708Polylines function first draws the polylines through the original Fallback 709function and then rotates the lines, line by line. We then set a flag and 710return control to the shadowFB which will try to rotate the bounding rectangle. 711However, the flag has been set and the RefreshArea function does nothing but 712clear the flag so the next Refresh that comes in shoiuld be handled correctly. 713 714All this code improves the speed quite a bit. 715 716*/ 717 718#define IS_VISIBLE(pWin) \ 719( \ 720 pScrn->vtSema \ 721 && (((WindowPtr) pWin)->visibility != VisibilityFullyObscured) \ 722) 723 724#define TRIM_BOX(box, pGC) \ 725{ \ 726 BoxPtr extents = &pGC->pCompositeClip->extents; \ 727 if (box.x1 < extents->x1) box.x1 = extents->x1; \ 728 if (box.y1 < extents->y1) box.y1 = extents->y1; \ 729 if (box.x2 > extents->x2) box.x2 = extents->x2; \ 730 if (box.y2 > extents->y2) box.y2 = extents->y2; \ 731} 732 733#define TRANSLATE_BOX(box, pDraw) \ 734{ \ 735 box.x1 += pDraw->x; \ 736 box.y1 += pDraw->y; \ 737 box.x2 += pDraw->x; \ 738 box.y2 += pDraw->y; \ 739} 740 741#define BOX_NOT_EMPTY(box) \ 742 ((box.x2 > box.x1) && (box.y2 > box.y1)) 743 744static void 745SMI_ValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) 746{ 747 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 748 SMIPtr pSmi = SMIPTR(infoRec->pScrn); 749 750 ENTER_PROC("SMI_ValidatePolylines"); 751 752 pSmi->ValidatePolylines(pGC, changes, pDraw); 753 if (pGC->ops->Polylines == XAAGetFallbackOps()->Polylines) { 754 /* Override the Polylines function with our own Polylines function. */ 755 pGC->ops->Polylines = SMI_Polylines; 756 } 757 758 LEAVE_PROC("SMI_ValidatePolylines"); 759} 760 761static void 762SMI_Polylines(DrawablePtr pDraw, GCPtr pGC, int mode, int npt, 763 DDXPointPtr pptInit) 764{ 765 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 766 ScrnInfoPtr pScrn = infoRec->pScrn; 767 SMIPtr pSmi = SMIPTR(pScrn); 768 769 ENTER_PROC("SMI_Polylines"); 770 771 /* Call the original Polylines function. */ 772 pGC->ops->Polylines = XAAGetFallbackOps()->Polylines; 773 (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); 774 pGC->ops->Polylines = SMI_Polylines; 775 776 if (IS_VISIBLE(pDraw) && npt) { 777 /* Allocate a temporary buffer for all segments of the polyline. */ 778 BoxPtr pBox = xnfcalloc(sizeof(BoxRec), npt); 779 int extra = pGC->lineWidth >> 1, box; 780 781 if (npt > 1) { 782 /* Adjust the extra space required per polyline segment. */ 783 if (pGC->joinStyle == JoinMiter) { 784 extra = 6 * pGC->lineWidth; 785 } else if (pGC->capStyle == CapProjecting) { 786 extra = pGC->lineWidth; 787 } 788 } 789 790 for (box = 0; --npt;) { 791 /* Setup the bounding box for one polyline segment. */ 792 pBox[box].x1 = pptInit->x; 793 pBox[box].y1 = pptInit->y; 794 pptInit++; 795 pBox[box].x2 = pptInit->x; 796 pBox[box].y2 = pptInit->y; 797 if (mode == CoordModePrevious) { 798 pBox[box].x2 += pBox[box].x1; 799 pBox[box].y2 += pBox[box].y1; 800 } 801 802 /* Sort coordinates. */ 803 if (pBox[box].x1 > pBox[box].x2) { 804 int tmp = pBox[box].x1; 805 pBox[box].x1 = pBox[box].x2; 806 pBox[box].x2 = tmp; 807 } 808 if (pBox[box].y1 > pBox[box].y2) { 809 int tmp = pBox[box].y1; 810 pBox[box].y1 = pBox[box].y2; 811 pBox[box].y2 = tmp; 812 } 813 814 /* Add extra space required for each polyline segment. */ 815 pBox[box].x1 -= extra; 816 pBox[box].y1 -= extra; 817 pBox[box].x2 += extra + 1; 818 pBox[box].y2 += extra + 1; 819 820 /* See if we need to draw this polyline segment. */ 821 TRANSLATE_BOX(pBox[box], pDraw); 822 TRIM_BOX(pBox[box], pGC); 823 if (BOX_NOT_EMPTY(pBox[box])) { 824 box++; 825 } 826 } 827 828 if (box) { 829 /* Refresh all polyline segments now. */ 830 if (pSmi->Chipset == SMI_COUGAR3DR) { 831 SMI_RefreshArea730(pScrn, box, pBox); 832 } else { 833 SMI_RefreshArea(pScrn, box, pBox); 834 } 835 } 836 837 /* Free the temporary buffer. */ 838 xfree(pBox); 839 } 840 841 pSmi->polyLines = TRUE; 842 LEAVE_PROC("SMI_Polylines"); 843} 844 845