1/* 2Copyright (C) 2006 Dennis De Winter All Rights Reserved. 3Copyright (C) 2007 Alex Deucher 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 22*/ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "smi.h" 29 30#if SMI501_CLI_DEBUG 31# include "smi_501.h" 32# undef WRITE_DPR 33# define WRITE_DPR(pSmi, dpr, data) \ 34 do { \ 35 if (pSmi->batch_active) \ 36 BATCH_LOAD_REG((pSmi->DPRBase - pSmi->MapBase) + \ 37 dpr, data); \ 38 else \ 39 MMIO_OUT32(pSmi->DPRBase, dpr, data); \ 40 DEBUG("DPR%02X = %08X\n", dpr, data); \ 41 } while (0) 42#endif 43 44static void 45SMI_EXASync(ScreenPtr pScreen, int marker); 46 47static Bool 48SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, 49 int xdir, int ydir, int alu, Pixel planemask); 50 51static void 52SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height); 53 54static void 55SMI_DoneCopy(PixmapPtr pDstPixmap); 56 57static Bool 58SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg); 59 60static void 61SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2); 62 63static void 64SMI_DoneSolid(PixmapPtr pPixmap); 65 66Bool 67SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch); 68 69Bool 70SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch); 71 72static Bool 73SMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture); 74static Bool 75SMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, 76 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); 77static void 78SMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 79 int dstX, int dstY, int width, int height); 80static void 81SMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 82 int dstX, int dstY, int width, int height); 83static void 84SMI_DoneComposite(PixmapPtr pDst); 85 86 87#define PIXMAP_FORMAT(pixmap) SMI_DEDataFormat(pixmap->drawable.bitsPerPixel) 88#define PIXMAP_OFFSET(pixmap) IS_MSOC(pSmi) ? \ 89 exaGetPixmapOffset(pixmap) : exaGetPixmapOffset(pixmap) >> 3 90 91Bool 92SMI_EXAInit(ScreenPtr pScreen) 93{ 94 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 95 SMIPtr pSmi = SMIPTR(pScrn); 96 97 ENTER(); 98 99 if (!(pSmi->EXADriverPtr = exaDriverAlloc())) { 100 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate EXADriverRec.\n"); 101 LEAVE(FALSE); 102 } 103 104 /* Require 2.1 semantics: 105 Don't uninitialize the memory manager when swapping out */ 106 pSmi->EXADriverPtr->exa_major = 2; 107 pSmi->EXADriverPtr->exa_minor = 1; 108 109 SMI_EngineReset(pScrn); 110 111 /* Memory Manager */ 112 pSmi->EXADriverPtr->memoryBase = pSmi->FBBase; 113 pSmi->EXADriverPtr->memorySize = pSmi->FBReserved; 114 115 /* The framebuffer is allocated as an offscreen area with the 116 memory manager (It makes easier further resizing) */ 117 pSmi->EXADriverPtr->offScreenBase = 0; 118 119 /* Flags */ 120 pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS; 121 if (pSmi->EXADriverPtr->memorySize > pSmi->EXADriverPtr->offScreenBase) { 122 /* Offscreen Pixmaps */ 123 pSmi->EXADriverPtr->flags |= EXA_OFFSCREEN_PIXMAPS; 124 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 125 "EXA offscreen memory manager enabled.\n"); 126 } 127 else 128 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 129 "Not enough video RAM for EXA offscreen memory manager.\n"); 130 131 /* 12 bit coordinates */ 132 pSmi->EXADriverPtr->maxX = 4096; 133 pSmi->EXADriverPtr->maxY = 4096; 134 135 if (pScrn->bitsPerPixel == 24) { 136 pSmi->EXADriverPtr->maxX = 4096 / 3; 137 138 if (pSmi->Chipset == SMI_LYNX) { 139 pSmi->EXADriverPtr->maxY = 4096 / 3; 140 } 141 } 142 143 pSmi->EXADriverPtr->pixmapPitchAlign = 16; 144 pSmi->EXADriverPtr->pixmapOffsetAlign = 8; 145 146 /* Sync */ 147 pSmi->EXADriverPtr->WaitMarker = SMI_EXASync; 148 149 /* Copy */ 150 pSmi->EXADriverPtr->PrepareCopy = SMI_PrepareCopy; 151 pSmi->EXADriverPtr->Copy = SMI_Copy; 152 pSmi->EXADriverPtr->DoneCopy = SMI_DoneCopy; 153 154 /* Solid */ 155 pSmi->EXADriverPtr->PrepareSolid = SMI_PrepareSolid; 156 pSmi->EXADriverPtr->Solid = SMI_Solid; 157 pSmi->EXADriverPtr->DoneSolid = SMI_DoneSolid; 158 159#if 0 160 /* DFS & UTS */ 161 pSmi->EXADriverPtr->UploadToScreen = SMI_UploadToScreen; 162 pSmi->EXADriverPtr->DownloadFromScreen = SMI_DownloadFromScreen; 163#endif 164 165 /* Composite */ 166 pSmi->EXADriverPtr->CheckComposite = SMI_CheckComposite; 167 pSmi->EXADriverPtr->PrepareComposite = SMI_PrepareComposite; 168 169 if (IS_MSOC(pSmi) || pSmi->Chipset == SMI_COUGAR3DR) 170 pSmi->EXADriverPtr->Composite = SMI730_Composite; 171 else 172 pSmi->EXADriverPtr->Composite = SMI_Composite; 173 174 pSmi->EXADriverPtr->DoneComposite = SMI_DoneComposite; 175 176 if(!exaDriverInit(pScreen, pSmi->EXADriverPtr)) { 177 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "exaDriverInit failed.\n"); 178 LEAVE(FALSE); 179 } 180 181 182 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n"); 183 184 LEAVE(TRUE); 185} 186 187static void 188SMI_EXASync(ScreenPtr pScreen, int marker) 189{ 190 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 191 192 ENTER(); 193 194 SMI_AccelSync(pScrn); 195 196 LEAVE(); 197} 198 199/* ----------------------------------------------------- EXA Copy ---------------------------------------------- */ 200 201CARD8 SMI_BltRop[16] = /* table stolen from KAA */ 202{ 203 /* GXclear */ 0x00, /* 0 */ 204 /* GXand */ 0x88, /* src AND dst */ 205 /* GXandReverse */ 0x44, /* src AND NOT dst */ 206 /* GXcopy */ 0xCC, /* src */ 207 /* GXandInverted*/ 0x22, /* NOT src AND dst */ 208 /* GXnoop */ 0xAA, /* dst */ 209 /* GXxor */ 0x66, /* src XOR dst */ 210 /* GXor */ 0xEE, /* src OR dst */ 211 /* GXnor */ 0x11, /* NOT src AND NOT dst */ 212 /* GXequiv */ 0x99, /* NOT src XOR dst */ 213 /* GXinvert */ 0x55, /* NOT dst */ 214 /* GXorReverse */ 0xDD, /* src OR NOT dst */ 215 /* GXcopyInverted*/ 0x33, /* NOT src */ 216 /* GXorInverted */ 0xBB, /* NOT src OR dst */ 217 /* GXnand */ 0x77, /* NOT src OR NOT dst */ 218 /* GXset */ 0xFF, /* 1 */ 219}; 220 221static Bool 222SMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, 223 int alu, Pixel planemask) 224{ 225 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); 226 SMIPtr pSmi = SMIPTR(pScrn); 227 int src_pitch, dst_pitch; 228 unsigned long src_offset, dst_offset; 229 230 ENTER(); 231 DEBUG("xdir=%d ydir=%d alu=%02X", xdir, ydir, alu); 232 233 /* Bit Mask not supported > 16 bpp */ 234 if ((pSrcPixmap->drawable.bitsPerPixel > 16) && 235 (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask))) 236 LEAVE(FALSE); 237 238 /* calculate pitch in pixel unit */ 239 src_pitch = exaGetPixmapPitch(pSrcPixmap) / (pSrcPixmap->drawable.bitsPerPixel >> 3); 240 dst_pitch = exaGetPixmapPitch(pDstPixmap) / (pDstPixmap->drawable.bitsPerPixel >> 3); 241 /* calculate offset in 8 byte (64 bit) unit */ 242 src_offset = PIXMAP_OFFSET(pSrcPixmap); 243 dst_offset = PIXMAP_OFFSET(pDstPixmap); 244 245 pSmi->AccelCmd = SMI_BltRop[alu] 246 | SMI_BITBLT 247 | SMI_QUICK_START; 248 249 if (xdir < 0 || (ydir < 0)) { 250 pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT; 251 } 252 253 if (pDstPixmap->drawable.bitsPerPixel == 24) { 254 src_pitch *= 3; 255 dst_pitch *= 3; 256 } 257 258#if SMI501_CLI_DEBUG 259 BATCH_BEGIN(7); 260#else 261 WaitQueue(); 262#endif 263 /* Destination and Source Window Widths */ 264 WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF)); 265 /* Destination and Source Row Pitch */ 266 WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF)); 267 268 /* Bit Mask (planemask) - 16 bit only */ 269 if (pSrcPixmap->drawable.bitsPerPixel == 16) { 270 WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000); 271 } else { 272 WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF); 273 } 274 /* Drawing engine data format */ 275 WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDstPixmap)); 276 /* Destination and Source Base Address (offset) */ 277 WRITE_DPR(pSmi, 0x40, src_offset); 278 WRITE_DPR(pSmi, 0x44, dst_offset); 279 280 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 281#if SMI501_CLI_DEBUG 282 BATCH_END(); 283#endif 284 285 LEAVE(TRUE); 286} 287 288static void 289SMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, 290 int dstY, int width, int height) 291{ 292 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); 293 SMIPtr pSmi = SMIPTR(pScrn); 294 295 ENTER(); 296 DEBUG("srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n", 297 srcX, srcY, dstX, dstY, width, height); 298 299 if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { 300 srcX += width - 1; 301 srcY += height - 1; 302 dstX += width - 1; 303 dstY += height - 1; 304 } 305 306 if (pDstPixmap->drawable.bitsPerPixel == 24) { 307 srcX *= 3; 308 dstX *= 3; 309 width *= 3; 310 311 if (pSmi->Chipset == SMI_LYNX) { 312 srcY *= 3; 313 dstY *= 3; 314 } 315 316 if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) { 317 srcX += 2; 318 dstX += 2; 319 } 320 } 321 322#if SMI501_CLI_DEBUG 323 BATCH_BEGIN(3); 324#else 325 WaitQueue(); 326#endif 327 WRITE_DPR(pSmi, 0x00, (srcX << 16) + (srcY & 0xFFFF)); 328 WRITE_DPR(pSmi, 0x04, (dstX << 16) + (dstY & 0xFFFF)); 329 WRITE_DPR(pSmi, 0x08, (width << 16) + (height & 0xFFFF)); 330#if SMI501_CLI_DEBUG 331 BATCH_END(); 332#endif 333 334 LEAVE(); 335} 336 337static void 338SMI_DoneCopy(PixmapPtr pDstPixmap) 339{ 340 ENTER(); 341 342 LEAVE(); 343} 344 345/* ----------------------------------------------------- EXA Solid --------------------------------------------- */ 346 347CARD8 SMI_SolidRop[16] = /* table stolen from KAA */ 348{ 349 /* GXclear */ 0x00, /* 0 */ 350 /* GXand */ 0xA0, /* src AND dst */ 351 /* GXandReverse */ 0x50, /* src AND NOT dst */ 352 /* GXcopy */ 0xF0, /* src */ 353 /* GXandInverted*/ 0x0A, /* NOT src AND dst */ 354 /* GXnoop */ 0xAA, /* dst */ 355 /* GXxor */ 0x5A, /* src XOR dst */ 356 /* GXor */ 0xFA, /* src OR dst */ 357 /* GXnor */ 0x05, /* NOT src AND NOT dst */ 358 /* GXequiv */ 0xA5, /* NOT src XOR dst */ 359 /* GXinvert */ 0x55, /* NOT dst */ 360 /* GXorReverse */ 0xF5, /* src OR NOT dst */ 361 /* GXcopyInverted*/ 0x0F, /* NOT src */ 362 /* GXorInverted */ 0xAF, /* NOT src OR dst */ 363 /* GXnand */ 0x5F, /* NOT src OR NOT dst */ 364 /* GXset */ 0xFF, /* 1 */ 365}; 366 367static Bool 368SMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 369{ 370 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); 371 SMIPtr pSmi = SMIPTR(pScrn); 372 int dst_pitch; 373 unsigned long dst_offset; 374 375 ENTER(); 376 DEBUG("alu=%02X\n", alu); 377 378 /* HW ignores alpha */ 379 if (pPixmap->drawable.bitsPerPixel == 32) 380 LEAVE(FALSE); 381 382 /* Bit Mask not supported > 16 bpp */ 383 if ((pPixmap->drawable.bitsPerPixel > 16) && 384 (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))) 385 LEAVE(FALSE); 386 387 /* calculate pitch in pixel unit */ 388 dst_pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel >> 3); 389 /* calculate offset in 8 byte (64 bit) unit */ 390 dst_offset = PIXMAP_OFFSET(pPixmap); 391 392 pSmi->AccelCmd = SMI_SolidRop[alu] 393 | SMI_BITBLT 394 | SMI_QUICK_START; 395 396 if (pPixmap->drawable.bitsPerPixel == 24) { 397 dst_pitch *= 3; 398 } 399 400#if SMI501_CLI_DEBUG 401 BATCH_BEGIN(10); 402#else 403 WaitQueue(); 404#endif 405 406 /* Destination Window Width */ 407 WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (dst_pitch & 0xFFFF)); 408 /* Destination Row Pitch */ 409 WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (dst_pitch & 0xFFFF)); 410 411 /* Bit Mask (planemask) - 16 bit only */ 412 if (pPixmap->drawable.bitsPerPixel == 16) { 413 WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000); 414 } else { 415 WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF); 416 } 417 418 /* Drawing engine data format */ 419 WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pPixmap)); 420 /* Source and Destination Base Address (offset) */ 421 WRITE_DPR(pSmi, 0x40, dst_offset); 422 WRITE_DPR(pSmi, 0x44, dst_offset); 423 /* Foreground Color */ 424 WRITE_DPR(pSmi, 0x14, fg); 425 /* Mono Pattern High and Low */ 426 WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF); 427 WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF); 428 429 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 430#if SMI501_CLI_DEBUG 431 BATCH_END(); 432#endif 433 434 LEAVE(TRUE); 435} 436 437static void 438SMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 439{ 440 ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); 441 SMIPtr pSmi = SMIPTR(pScrn); 442 int w, h; 443 444 ENTER(); 445 DEBUG("x1=%d y1=%d x2=%d y2=%d\n", x1, y1, x2, y2); 446 447 w = (x2 - x1); 448 h = (y2 - y1); 449 450 if (pPixmap->drawable.bitsPerPixel == 24) { 451 x1 *= 3; 452 w *= 3; 453 454 if (pSmi->Chipset == SMI_LYNX) { 455 y1 *= 3; 456 } 457 } 458 459#if SMI501_CLI_DEBUG 460 BATCH_BEGIN(2); 461#else 462 WaitQueue(); 463#endif 464 WRITE_DPR(pSmi, 0x04, (x1 << 16) | (y1 & 0xFFFF)); 465 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 466#if SMI501_CLI_DEBUG 467 BATCH_END(); 468#endif 469 470 LEAVE(); 471} 472 473static void 474SMI_DoneSolid(PixmapPtr pPixmap) 475{ 476 ENTER(); 477 478 LEAVE(); 479} 480 481/* --------------------------------------- EXA DFS & UTS ---------------------------------------- */ 482 483Bool 484SMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 485 char *dst, int dst_pitch) 486{ 487 unsigned char *src = pSrc->devPrivate.ptr; 488 int src_pitch = exaGetPixmapPitch(pSrc); 489 490 ENTER(); 491 DEBUG("x=%d y=%d w=%d h=%d dst=%d dst_pitch=%d\n", 492 x, y, w, h, dst, dst_pitch); 493 494 exaWaitSync(pSrc->drawable.pScreen); 495 496 src += (y * src_pitch) + (x * pSrc->drawable.bitsPerPixel/8); 497 w *= pSrc->drawable.bitsPerPixel/8; 498 499 while (h--) { 500 memcpy(dst, src, w); 501 src += src_pitch; 502 dst += dst_pitch; 503 } 504 505 LEAVE(TRUE); 506} 507 508Bool 509SMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 510 char *src, int src_pitch) 511{ 512 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); 513 SMIPtr pSmi = SMIPTR(pScrn); 514 int dst_pixelpitch, src_pixelpitch, align, aligned_pitch; 515 unsigned long dst_offset; 516 517 ENTER(); 518 DEBUG("x=%d y=%d w=%d h=%d src=%d src_pitch=%d\n", 519 x, y, w, h, src, src_pitch); 520 521 if (pDst->drawable.bitsPerPixel == 24) { 522 align = 16; 523 } else { 524 align = 128 / pDst->drawable.bitsPerPixel; 525 } 526 527 aligned_pitch = ((w*pDst->drawable.bitsPerPixel >> 3) + align - 1) & ~(align - 1); 528 529 /* calculate pitch in pixel unit */ 530 dst_pixelpitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3); 531 src_pixelpitch = src_pitch / (pDst->drawable.bitsPerPixel >> 3); 532 /* calculate offset in 8 byte (64 bit) unit */ 533 dst_offset = PIXMAP_OFFSET(pDst); 534 535 pSmi->AccelCmd = 0xCC /* GXcopy */ 536 | SMI_HOSTBLT_WRITE 537 | SMI_QUICK_START; 538 539 /* set clipping */ 540 SMI_SetClippingRectangle(pScrn, x, y, x+w, y+h); 541 542#if SMI501_CLI_DEBUG 543 BATCH_BEGIN(9); 544#else 545 WaitQueue(); 546#endif 547 /* Destination and Source Window Widths */ 548 WRITE_DPR(pSmi, 0x3C, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF)); 549 550 if (pDst->drawable.bitsPerPixel == 24) { 551 x *= 3; 552 w *= 3; 553 dst_pixelpitch *= 3; 554 if (pSmi->Chipset == SMI_LYNX) { 555 y *= 3; 556 } 557 } 558 559 /* Source and Destination Row Pitch */ 560 WRITE_DPR(pSmi, 0x10, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF)); 561 /* Drawing engine data format */ 562 WRITE_DPR(pSmi, 0x1C,PIXMAP_FORMAT(pDst)); 563 /* Source and Destination Base Address (offset) */ 564 WRITE_DPR(pSmi, 0x40, 0); 565 WRITE_DPR(pSmi, 0x44, dst_offset); 566 567 WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd); 568 WRITE_DPR(pSmi, 0x00, 0); 569 WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF)); 570 WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); 571#if SMI501_CLI_DEBUG 572 BATCH_END(); 573#endif 574 575 while (h--) { 576 memcpy(pSmi->DataPortBase, src, aligned_pitch); 577 src += src_pitch; 578 } 579 580 /* disable clipping */ 581 SMI_DisableClipping(pScrn); 582 583 exaWaitSync(pDst->drawable.pScreen); 584 585 LEAVE(TRUE); 586} 587 588/* --------------------------------------- EXA Composite ---------------------------------------- */ 589/* This is a very incomplete Composite implementation that only 590 accelerates PictOpSrc with source coordinates transformation by 591 using 2D Engine rotate-BITBLTs */ 592 593#define SMI_ISROTATION_90(t) \ 594 (t->matrix[0][0] == 0 && t->matrix[0][1] == xFixed1 && \ 595 t->matrix[1][0] == -xFixed1 && t->matrix[1][1] == 0) 596 597#define SMI_ISROTATION_270(t) \ 598 (t->matrix[0][0] == 0 && t->matrix[0][1] == -xFixed1 && \ 599 t->matrix[1][0] == xFixed1 && t->matrix[1][1] == 0) 600 601static Bool 602SMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) 603{ 604 ENTER(); 605 606 if(op!=PictOpSrc || pMaskPicture || 607 pSrcPicture->repeatType || !pSrcPicture->transform) 608 LEAVE(FALSE); 609 610 if(!SMI_ISROTATION_90(pSrcPicture->transform) && 611 !SMI_ISROTATION_270(pSrcPicture->transform)) 612 LEAVE(FALSE); 613 614 if(PICT_FORMAT_BPP(pSrcPicture->format) == 24) 615 LEAVE(FALSE); 616 617 LEAVE(TRUE); 618} 619 620static Bool 621SMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, 622 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) 623{ 624 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); 625 SMIPtr pSmi = SMIPTR(pScrn); 626 627 if (!pSrc) return FALSE; 628 if (!pSrcPicture->pDrawable) return FALSE; 629 630 int src_pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel >> 3); 631 int dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3); 632 633 ENTER(); 634 635#if SMI501_CLI_DEBUG 636 BATCH_BEGIN(7); 637#else 638 WaitQueue(); 639#endif 640 641 /* Destination and Source Window Widths */ 642 WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF)); 643 644 /* Destination and Source Row Pitch */ 645 WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF)); 646 647 /* Drawing engine data format */ 648 WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDst)); 649 650 /* DE Bit Mask */ 651 WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF); 652 653 /* Destination and Source Base Address (offset) */ 654 WRITE_DPR(pSmi, 0x40, PIXMAP_OFFSET(pSrc)); 655 WRITE_DPR(pSmi, 0x44, PIXMAP_OFFSET(pDst)); 656 657 /* DE command*/ 658 if(SMI_ISROTATION_90(pSrcPicture->transform)) 659 WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT | 660 SMI_ROTATE_CW | SMI_QUICK_START); 661 else 662 WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT | 663 SMI_ROTATE_CCW | SMI_QUICK_START); 664 665#if SMI501_CLI_DEBUG 666 BATCH_END(); 667#endif 668 669 pSmi->renderTransform = pSrcPicture->transform; 670 671 LEAVE(TRUE); 672} 673 674static void 675SMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 676 int dstX, int dstY, int width, int height) 677{ 678 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); 679 SMIPtr pSmi = SMIPTR(pScrn); 680 PictTransformPtr t = pSmi->renderTransform; 681 PictVector v; 682 683 ENTER(); 684 685 if(SMI_ISROTATION_90(t)){ 686 srcX=srcX+width; 687 dstX=dstX+width-1; 688 }else{ 689 srcY=srcY+height; 690 dstY=dstY+height-1; 691 } 692 693 v.vector[0] = IntToxFixed(srcX); 694 v.vector[1] = IntToxFixed(srcY); 695 v.vector[2] = xFixed1; 696 PictureTransformPoint(t, &v); 697 698#if SMI501_CLI_DEBUG 699 BATCH_BEGIN(3); 700#else 701 WaitQueue(); 702#endif 703 704 WRITE_DPR(pSmi, 0x00, (xFixedToInt(v.vector[0]) << 16) + (xFixedToInt(v.vector[1]) & 0xFFFF)); 705 WRITE_DPR(pSmi, 0x04, (dstX << 16) + (dstY & 0xFFFF)); 706 WRITE_DPR(pSmi, 0x08, (height << 16) + (width & 0xFFFF)); 707#if SMI501_CLI_DEBUG 708 BATCH_END(); 709#endif 710 711 LEAVE(); 712} 713 714static void 715SMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, 716 int dstX, int dstY, int width, int height) 717{ 718 ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); 719 SMIPtr pSmi = SMIPTR(pScrn); 720 int maxPixels; 721 722 ENTER(); 723 724 /* Both SM501 and SM731 cannot rotate-blt more than a certain 725 number of pixels. */ 726 if(IS_MSOC(pSmi)) 727 maxPixels = 128 / pDst->drawable.bitsPerPixel; 728 else 729 maxPixels = 1280 / pDst->drawable.bitsPerPixel; 730 731 while(height>0){ 732 SMI_Composite(pDst, srcX, srcY, maskX, maskY, dstX, dstY, width, min(height, maxPixels)); 733 734 srcY += maxPixels; 735 dstY += maxPixels; 736 height -= maxPixels; 737 } 738 739 LEAVE(); 740} 741 742static void 743SMI_DoneComposite(PixmapPtr pDst) 744{ 745 ENTER(); 746 LEAVE(); 747} 748