atimach64render.c revision 621ff18c
1/* 2 * Copyright 2006 George Sapountzis 3 * All Rights Reserved. 4 * 5 * Based on the mach64 DRI and DRM drivers: 6 * Copyright 2000 Gareth Hughes 7 * Copyright 2002-2003 Leif Delgass 8 * All Rights Reserved. 9 * 10 * Based on the ati hw/kdrive driver: 11 * Copyright 2003 Eric Anholt, Anders Carlsson 12 * 13 * Based on the via hw/xfree86 driver: 14 * Copyright 2006 Thomas Hellstrom. All Rights Reserved. 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice (including the next 24 * paragraph) shall be included in all copies or substantial portions of the 25 * Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 * Authors: 36 * George Sapountzis <gsap7@yahoo.gr> 37 */ 38 39/* 40 * Interesting cases for RENDER acceleration: 41 * 42 * cursor : ARGB8888 (24x24) Over 43 * RGB565 44 * 45 * glyph : A8 (9x10) Add 46 * A8 (420x13) 47 * glyph set : ARGB8888 (1x1 R) In 48 * A8 (420x13) Over 49 * RGB565 50 * 51 * shadow : ARGB8888 (1x1 R) In 52 * A8 (670x362) Over 53 * RGB565 54 * translucent : RGB565 (652x344) In 55 * A8 (1x1 R) Over 56 * RGB565 57 * 58 * In all interesting cases one of src/mask is "1x1 R". 59 */ 60 61/* 62 * Assumptions and limitations of mach64 RENDER acceleration: 63 * 64 * RENDER acceleration is supported for GTPRO and later chips using the 3D 65 * triangle setup, i.e. the VERTEX_? registers (see the dri driver). According 66 * to atiregs.h, SCALE_3D_CNTL and TEX_?_OFF appear in GT, thus chips as old 67 * as GT should be capable of RENDER acceleration, using the S_?_INC, T_?_INC 68 * registers for texture mapping (see the directfb driver). 69 * 70 * GTPRO added a triangle setup engine and multitexturing. However, it seems 71 * that none of the 8bpp mach64 formats expands the 8bit value to the alpha 72 * channel in texture mapping, RGB8 appears to expand to (I,I,I,0). This makes 73 * GTPRO multitexturing unsuitable for emulating the IN operation. Moreover, 74 * it seems that GT/GTPRO has a muxltiplexer instead of a blender for computing 75 * the final alpha channel which forbids destinations with an alpha channel and 76 * generic two-pass compositing. 77 * 78 * A texture unit combines the fragment color (VERTEX_?_ARGB) coming in from 79 * triangle rasterization with the texel from the texture according to the 80 * texture environment (TEX_LIGHT_FCN_). "1x1 R" textures may come in as frag- 81 * ment colors, eliminating the need for multitexturing in all interesting 82 * cases (via also uses this optimization). 83 * 84 * Texture registers are saved/restored and cached (see atimach64.c). TEX_CNTL 85 * cannot be cached because it flushes the texture cache. TEX_?_OFF are also 86 * not cached because I am not sure whether writing at some offset register 87 * affects the value at another offset. 88 * 89 * Vertex registers are not saved/restored. This shouldn't be a problem though 90 * either for DRI or VT switch because vertex registers are set and used within 91 * a signle acceleration hook. Synchronization between the DDX and DRI is based 92 * on calling ATIDRISync() at the beginning of each DDX acceleration hook, 93 * which suggests the assumption that individual acceleration hooks are not 94 * interrupted. 95 */ 96 97#include <string.h> 98#include <stdio.h> 99 100/* 101 * Helper functions copied from exa and via. 102 */ 103 104#if 0 105static void 106Mach64ExaCompositePictDesc(PicturePtr pict, char *string, int n) 107{ 108 char format[20]; 109 char size[20]; 110 111 if (!pict) { 112 snprintf(string, n, "None"); 113 return; 114 } 115 116 switch (pict->format) { 117 case PICT_x8r8g8b8: 118 snprintf(format, 20, "RGB8888 "); 119 break; 120 case PICT_x8b8g8r8: 121 snprintf(format, 20, "BGR8888 "); 122 break; 123 case PICT_a8r8g8b8: 124 snprintf(format, 20, "ARGB8888"); 125 break; 126 case PICT_a8b8g8r8: 127 snprintf(format, 20, "ABGR8888"); 128 break; 129 case PICT_r5g6b5: 130 snprintf(format, 20, "RGB565 "); 131 break; 132 case PICT_x1r5g5b5: 133 snprintf(format, 20, "RGB555 "); 134 break; 135 case PICT_a8: 136 snprintf(format, 20, "A8 "); 137 break; 138 case PICT_a1: 139 snprintf(format, 20, "A1 "); 140 break; 141 default: 142 snprintf(format, 20, "0x%x", (int)pict->format); 143 break; 144 } 145 146 snprintf(size, 20, "%dx%d%s%s", 147 pict->pDrawable->width, 148 pict->pDrawable->height, 149 pict->repeat ? " R" : "", 150 pict->componentAlpha ? " C" : "" 151 ); 152 153 snprintf(string, n, "%-10p: fmt %s (%s)", (void *)pict->pDrawable, format, size); 154} 155 156static void 157Mach64ExaPrintComposite(CARD8 op, 158 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, char *string) 159{ 160 char sop[20]; 161 char srcdesc[40], maskdesc[40], dstdesc[40]; 162 163 switch (op) { 164 case PictOpSrc: 165 sprintf(sop, "Src"); 166 break; 167 case PictOpOver: 168 sprintf(sop, "Over"); 169 break; 170 case PictOpInReverse: 171 sprintf(sop, "InR"); 172 break; 173 case PictOpOutReverse: 174 sprintf(sop, "OutR"); 175 break; 176 case PictOpAdd: 177 sprintf(sop, "Add"); 178 break; 179 default: 180 sprintf(sop, "0x%x", (int)op); 181 break; 182 } 183 184 Mach64ExaCompositePictDesc(pSrc, srcdesc, 40); 185 Mach64ExaCompositePictDesc(pMask, maskdesc, 40); 186 Mach64ExaCompositePictDesc(pDst, dstdesc, 40); 187 188 sprintf(string, "op %s, \n" 189 " src %s\n" 190 " mask %s\n" 191 " dst %s\n", sop, srcdesc, maskdesc, dstdesc); 192} 193#endif 194 195static __inline__ CARD32 196viaBitExpandHelper(CARD32 component, CARD32 bits) 197{ 198 CARD32 tmp, mask; 199 200 mask = (1 << (8 - bits)) - 1; 201 tmp = component << (8 - bits); 202 return ((component & 1) ? tmp | mask : tmp); 203} 204 205static __inline__ void 206Mach64PixelARGB(PixmapPtr pPixmap, CARD32 format, CARD32 *argb) 207{ 208 CARD32 pixel; 209 CARD8 comp; 210 int bits, shift; 211 212 pixel = exaGetPixmapFirstPixel(pPixmap); 213 214 /* exaGetRGBAFromPixel()/viaPixelARGB8888() */ 215 216 switch (PICT_FORMAT_TYPE(format)) { 217 case PICT_TYPE_A: 218 shift = 0; 219 bits = PICT_FORMAT_A(format); 220 comp = (pixel >> shift) & ((1 << bits) - 1); 221 comp = viaBitExpandHelper(comp, bits); 222 *argb = comp << 24; 223 break; 224 case PICT_TYPE_ARGB: 225 shift = 0; 226 bits = PICT_FORMAT_B(format); 227 comp = (pixel >> shift) & ((1 << bits) - 1); 228 comp = viaBitExpandHelper(comp, bits); 229 *argb = comp; 230 231 shift += bits; 232 bits = PICT_FORMAT_G(format); 233 comp = (pixel >> shift) & ((1 << bits) - 1); 234 comp = viaBitExpandHelper(comp, bits); 235 *argb |= comp << 8; 236 237 shift += bits; 238 bits = PICT_FORMAT_R(format); 239 comp = (pixel >> shift) & ((1 << bits) - 1); 240 comp = viaBitExpandHelper(comp, bits); 241 *argb |= comp << 16; 242 243 shift += bits; 244 bits = PICT_FORMAT_A(format); 245 if (bits) { 246 comp = (pixel >> shift) & ((1 << bits) - 1); 247 comp = viaBitExpandHelper(comp, bits); 248 } else { 249 comp = 0xff; 250 } 251 *argb |= comp << 24; 252 break; 253 case PICT_TYPE_ABGR: 254 break; 255 default: 256 break; 257 } 258} 259 260/* 261 * RENDER acceleration for mach64 262 */ 263 264typedef struct { 265 Bool supported; 266 CARD32 scale_3d_cntl; 267} Mach64BlendOp; 268 269static Mach64BlendOp Mach64BlendOps[] = { 270 /* Clear */ 271 {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_ZERO}, 272 /* Src */ 273 {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_ZERO}, 274 /* Dst */ 275 {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_ONE}, 276 /* Over */ 277 {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, 278 /* OverReverse */ 279 {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_ONE}, 280 /* In */ 281 {1, MACH64_ALPHA_BLEND_SRC_DSTALPHA | MACH64_ALPHA_BLEND_DST_ZERO}, 282 /* InReverse */ 283 {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_SRCALPHA}, 284 /* Out */ 285 {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_ZERO}, 286 /* OutReverse */ 287 {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, 288 /* Atop */ 289 {0, MACH64_ALPHA_BLEND_SRC_DSTALPHA | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, 290 /* AtopReverse */ 291 {0, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_SRCALPHA}, 292 /* Xor */ 293 {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, 294 /* Add */ 295 {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_ONE} 296}; 297 298#define MACH64_NR_BLEND_OPS \ 299 (sizeof(Mach64BlendOps) / sizeof(Mach64BlendOps[0])) 300 301typedef struct { 302 CARD32 pictFormat; 303 CARD32 dstFormat; 304 CARD32 texFormat; 305} Mach64TexFormat; 306 307static Mach64TexFormat Mach64TexFormats[] = { 308 {PICT_a8r8g8b8, -1, MACH64_DATATYPE_ARGB8888}, 309 {PICT_x8r8g8b8, MACH64_DATATYPE_ARGB8888, MACH64_DATATYPE_ARGB8888}, 310 {PICT_a1r5g5b5, -1, MACH64_DATATYPE_ARGB1555}, 311 {PICT_x1r5g5b5, MACH64_DATATYPE_ARGB1555, MACH64_DATATYPE_ARGB1555}, 312 {PICT_r5g6b5, MACH64_DATATYPE_RGB565, MACH64_DATATYPE_RGB565 }, 313 {PICT_a8, MACH64_DATATYPE_RGB8, MACH64_DATATYPE_RGB8 } 314}; 315 316#define MACH64_NR_TEX_FORMATS \ 317 (sizeof(Mach64TexFormats) / sizeof(Mach64TexFormats[0])) 318 319#define MACH64_PICT_IS_1x1R(_pPict) \ 320 ((_pPict) && \ 321 (_pPict)->pDrawable->width == 1 && \ 322 (_pPict)->pDrawable->height == 1 && \ 323 (_pPict)->repeat) 324 325/* 326 * CheckComposite hook helper functions. 327 */ 328static __inline__ Bool 329Mach64GetOrder(int val, int *shift) 330{ 331 *shift = 0; 332 333 while (val > (1 << *shift)) 334 (*shift)++; 335 336 return (val == (1 << *shift)); 337} 338 339static Bool 340Mach64CheckTexture(PicturePtr pPict) 341{ 342 int h,w; 343 int l2w, l2h, level, i; 344 345 if (pPict->pDrawable == NULL) 346 return FALSE; 347 w = pPict->pDrawable->width; 348 h = pPict->pDrawable->height; 349 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 350 if (Mach64TexFormats[i].pictFormat == pPict->format) 351 break; 352 } 353 354 if (i == MACH64_NR_TEX_FORMATS) 355 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 356 (int)pPict->format)); 357 358 /* l2w equals l2p (pitch) for all interesting cases (w >= 64) */ 359 Mach64GetOrder(w, &l2w); 360 Mach64GetOrder(h, &l2h); 361 362 level = (l2w > l2h) ? l2w : l2h; 363 364 if (level > 10) 365 MACH64_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); 366 367 return TRUE; 368} 369 370/* 371 * CheckComposite acceleration hook. 372 */ 373Bool 374Mach64CheckComposite 375( 376 int op, 377 PicturePtr pSrcPicture, 378 PicturePtr pMaskPicture, 379 PicturePtr pDstPicture 380) 381{ 382 Bool src_solid, mask_solid, mask_comp, op_comp; 383 int i; 384 385 if (op >= MACH64_NR_BLEND_OPS || !Mach64BlendOps[op].supported) 386 return FALSE; 387 388 if (!Mach64CheckTexture(pSrcPicture)) 389 return FALSE; 390 391 if (pMaskPicture && !Mach64CheckTexture(pMaskPicture)) 392 return FALSE; 393 394 /* Check destination format */ 395 396 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 397 if (Mach64TexFormats[i].pictFormat == pDstPicture->format) 398 break; 399 } 400 401 if (i == MACH64_NR_TEX_FORMATS || Mach64TexFormats[i].dstFormat == -1) 402 MACH64_FALLBACK(("Unsupported dst format 0x%x\n", 403 (int)pDstPicture->format)); 404 405 /* Check that A8 src/dst appears only as "A8 ADD A8" */ 406 407 if (pDstPicture->format == PICT_a8) { 408 if (pMaskPicture || pSrcPicture->format != PICT_a8 || op != PictOpAdd) 409 MACH64_FALLBACK(("A8 dst with mask or non-A8 src.\n")); 410 } 411 412 if (pDstPicture->format != PICT_a8) { 413 if (pSrcPicture->format == PICT_a8) 414 MACH64_FALLBACK(("A8 src with non-A8 dst.\n")); 415 } 416 417 /* Check that one of src/mask can come in as the fragment color. */ 418 419 src_solid = MACH64_PICT_IS_1x1R(pSrcPicture); 420 421 mask_solid = MACH64_PICT_IS_1x1R(pMaskPicture); 422 423 mask_comp = pMaskPicture && pMaskPicture->componentAlpha; 424 425 op_comp = op == PictOpAdd || 426 op == PictOpInReverse || 427 op == PictOpOutReverse; 428 429 if (mask_solid && src_solid) 430 MACH64_FALLBACK(("Bad one-pixel IN composite operation.\n")); 431 432 if (pMaskPicture) { 433 if (!mask_solid && !src_solid) 434 MACH64_FALLBACK(("Multitexturing required.\n")); 435 436 if (!mask_solid && !op_comp) 437 MACH64_FALLBACK(("Non-solid mask.\n")); 438 439 if (mask_comp && !src_solid) 440 MACH64_FALLBACK(("Component-alpha mask.\n")); 441 442 if (!mask_comp && pMaskPicture->format != PICT_a8) 443 MACH64_FALLBACK(("Non-A8 mask.\n")); 444 445 if (mask_comp && pMaskPicture->format != PICT_a8r8g8b8) 446 MACH64_FALLBACK(("Non-ARGB mask.\n")); 447 } 448 449 return TRUE; 450} 451 452/* 453 * This function setups the fragment color from a solid pixmap in the presence 454 * of a mask. 455 */ 456static __inline__ Bool 457Mach64PrepareMask 458( 459 Mach64ContextRegs3D *m3d, 460 int op, 461 PicturePtr pSrcPicture, 462 PicturePtr pMaskPicture, 463 PixmapPtr pSrc, 464 PixmapPtr pMask 465) 466{ 467 Bool mask_solid, src_solid; 468 CARD32 argb = 0; 469 470 mask_solid = MACH64_PICT_IS_1x1R(pMaskPicture); 471 472 src_solid = MACH64_PICT_IS_1x1R(pSrcPicture); 473 474 if (mask_solid) { 475 Mach64PixelARGB(pMask, pMaskPicture->format, &argb); 476 argb >>= 24; 477 argb &= 0xff; 478 479 m3d->frag_mask = TRUE; 480 m3d->frag_color = (argb << 24) | (argb << 16) | (argb << 8) | argb; 481 return TRUE; 482 } 483 484 if (src_solid) { 485 /* We can only handle cases where either the src color (e.g. ADD) or 486 * the src alpha (e.g. IN_REV, OUT_REV) is used but not both. 487 * 488 * (ARGB8888 IN A8) OVER RGB565 is implemented as: 489 * (ARGB8888 IN A8) ADD ((ARGB8888 IN A8) OUT_REV RGB565). 490 */ 491 if (op == PictOpInReverse || op == PictOpOutReverse) { 492 Mach64PixelARGB(pSrc, pSrcPicture->format, &argb); 493 argb >>= 24; 494 argb &= 0xff; 495 496 m3d->frag_src = TRUE; 497 m3d->frag_color = (argb << 24) | (argb << 16) | (argb << 8) | argb; 498 m3d->color_alpha = TRUE; 499 return TRUE; 500 } 501 502 if (op == PictOpAdd) { 503 Mach64PixelARGB(pSrc, pSrcPicture->format, &argb); 504 505 m3d->frag_src = TRUE; 506 m3d->frag_color = argb; 507 return TRUE; 508 } 509 } 510 511 return FALSE; 512} 513 514/* 515 * This function setups the texturing and blending environments. It also 516 * manipulates blend control for non-solid masks. 517 */ 518static void __inline__ 519Mach64BlendCntl(Mach64ContextRegs3D *m3d, int op) 520{ 521 m3d->scale_3d_cntl |= MACH64_SCALE_PIX_EXPAND_DYNAMIC_RANGE | 522 MACH64_SCALE_DITHER_2D_TABLE | 523 MACH64_DITHER_INIT_RESET; 524 525 m3d->scale_3d_cntl |= Mach64BlendOps[op].scale_3d_cntl; 526 527 if (m3d->color_alpha) { 528 /* A8 uses RGB8 which expands to (I,I,I,0). Thus, we use the color 529 * channels instead of the alpha channel as the alpha factor. We also 530 * use the color channels for ARGB8888 masks with component-alpha. 531 */ 532 CARD32 Ad = m3d->scale_3d_cntl & MACH64_ALPHA_BLEND_DST_MASK; 533 534 /* InReverse */ 535 if (Ad == MACH64_ALPHA_BLEND_DST_SRCALPHA) { 536 m3d->scale_3d_cntl &= ~MACH64_ALPHA_BLEND_DST_MASK; 537 m3d->scale_3d_cntl |= MACH64_ALPHA_BLEND_DST_SRCCOLOR; 538 } 539 540 /* OutReverse */ 541 if (Ad == MACH64_ALPHA_BLEND_DST_INVSRCALPHA) { 542 m3d->scale_3d_cntl &= ~MACH64_ALPHA_BLEND_DST_MASK; 543 m3d->scale_3d_cntl |= MACH64_ALPHA_BLEND_DST_INVSRCCOLOR; 544 } 545 } 546 547 /* Can't color mask and blend at the same time */ 548 m3d->dp_write_mask = 0xffffffff; 549 550 /* Can't fog and blend at the same time */ 551 m3d->scale_3d_cntl |= MACH64_ALPHA_FOG_EN_ALPHA; 552 553 /* Enable texture mapping mode */ 554 m3d->scale_3d_cntl |= MACH64_SCALE_3D_FCN_TEXTURE; 555 m3d->scale_3d_cntl |= MACH64_MIP_MAP_DISABLE; 556 557 /* Setup the texture environment */ 558 m3d->scale_3d_cntl |= MACH64_TEX_LIGHT_FCN_MODULATE; 559 560 /* Initialize texture unit */ 561 m3d->tex_cntl |= MACH64_TEX_ST_DIRECT | 562 MACH64_TEX_SRC_LOCAL | 563 MACH64_TEX_UNCOMPRESSED | 564 MACH64_TEX_CACHE_FLUSH | 565 MACH64_TEX_CACHE_SIZE_4K; 566} 567 568/* 569 * This function setups the texture unit. 570 */ 571static Bool 572Mach64PrepareTexture(PicturePtr pPict, PixmapPtr pPix) 573{ 574 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pPix->drawable.pScreen); 575 ATIPtr pATI = ATIPTR(pScreenInfo); 576 Mach64ContextRegs3D *m3d = &pATI->m3d; 577 578 CARD32 texFormat; 579 580 int w = pPict->pDrawable->width; 581 int h = pPict->pDrawable->height; 582 int l2w, l2h, l2p, level, pitch, cpp, i; 583 584 /* Prepare picture format */ 585 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 586 if (Mach64TexFormats[i].pictFormat == pPict->format) 587 break; 588 } 589 if (i == MACH64_NR_TEX_FORMATS) 590 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 591 (int)pPict->format)); 592 texFormat = Mach64TexFormats[i].texFormat; 593 594 /* Prepare picture size */ 595 cpp = PICT_FORMAT_BPP(pPict->format) / 8; 596 pitch = exaGetPixmapPitch(pPix) / cpp; 597 598 Mach64GetOrder(w, &l2w); 599 Mach64GetOrder(h, &l2h); 600 Mach64GetOrder(pitch, &l2p); 601 602 if (pPict->repeat && w == 1 && h == 1) 603 l2p = 0; 604 else if (pPict->repeat) 605 MACH64_FALLBACK(("Repeat not supported for w,h != 1,1\n")); 606 607 l2w = l2p; 608 609 level = (l2w > l2h) ? l2w : l2h; 610 611 m3d->tex_width = (1 << l2w); 612 m3d->tex_height = (1 << l2h); 613 614 /* Update hw state */ 615 m3d->dp_pix_width |= SetBits(texFormat, DP_SCALE_PIX_WIDTH); 616 617 m3d->tex_size_pitch = (l2w << 0) | 618 (level << 4) | 619 (l2h << 8); 620 621 m3d->tex_offset = exaGetPixmapOffset(pPix); 622 623 if (PICT_FORMAT_A(pPict->format)) 624 m3d->scale_3d_cntl |= MACH64_TEX_MAP_AEN; 625 626 switch (pPict->filter) { 627 case PictFilterNearest: 628 m3d->scale_3d_cntl |= MACH64_TEX_BLEND_FCN_NEAREST; 629 break; 630 case PictFilterBilinear: 631 /* FIXME */ 632#if 0 633 m3d->scale_3d_cntl |= MACH64_TEX_BLEND_FCN_LINEAR; 634 m3d->scale_3d_cntl |= MACH64_BILINEAR_TEX_EN; 635#endif 636 MACH64_FALLBACK(("Bilinear filter 0x%x\n", pPict->filter)); 637 break; 638 default: 639 MACH64_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); 640 } 641 642 m3d->transform = pPict->transform; 643 644 return TRUE; 645} 646 647/* 648 * PrepareComposite acceleration hook. 649 */ 650Bool 651Mach64PrepareComposite 652( 653 int op, 654 PicturePtr pSrcPicture, 655 PicturePtr pMaskPicture, 656 PicturePtr pDstPicture, 657 PixmapPtr pSrc, 658 PixmapPtr pMask, 659 PixmapPtr pDst 660) 661{ 662 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 663 ATIPtr pATI = ATIPTR(pScreenInfo); 664 Mach64ContextRegs3D *m3d = &pATI->m3d; 665 666 CARD32 dstFormat; 667 int offset, i; 668 669 ATIDRISync(pScreenInfo); 670 671 /* Initialize state */ 672 m3d->dp_mix = SetBits(MIX_SRC, DP_BKGD_MIX) | 673 SetBits(MIX_SRC, DP_FRGD_MIX); 674 675 m3d->dp_src = SetBits(SRC_SCALER_3D, DP_BKGD_SRC) | 676 SetBits(SRC_SCALER_3D, DP_FRGD_SRC) | 677 DP_MONO_SRC_ALLONES; 678 679 Mach64GetPixmapOffsetPitch(pDst, &m3d->dst_pitch_offset); 680 681 m3d->scale_3d_cntl = 0; 682 m3d->tex_cntl = 0; 683 684 m3d->frag_src = FALSE; 685 m3d->frag_mask = FALSE; 686 m3d->frag_color = 0xffffffff; 687 688 m3d->color_alpha = FALSE; 689 690 m3d->transform = NULL; 691 692 /* Compute state */ 693 if (pMaskPicture && !Mach64PrepareMask(m3d, op, pSrcPicture, pMaskPicture, 694 pSrc, pMask)) 695 return FALSE; 696 697 Mach64BlendCntl(m3d, op); 698 699 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 700 if (Mach64TexFormats[i].pictFormat == pDstPicture->format) 701 break; 702 } 703 if (i == MACH64_NR_TEX_FORMATS) 704 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 705 (int)pPict->format)); 706 dstFormat = Mach64TexFormats[i].dstFormat; 707 708 m3d->dp_pix_width = SetBits(dstFormat, DP_DST_PIX_WIDTH) | 709 SetBits(dstFormat, DP_SRC_PIX_WIDTH) | 710 SetBits(dstFormat, DP_HOST_PIX_WIDTH); 711 712 if (!m3d->frag_src) { 713 if (!Mach64PrepareTexture(pSrcPicture, pSrc)) 714 return FALSE; 715 } 716 717 if (pMaskPicture && !m3d->frag_mask) { 718 if (!Mach64PrepareTexture(pMaskPicture, pMask)) 719 return FALSE; 720 } 721 722 offset = TEX_LEVEL(m3d->tex_size_pitch); 723 724 /* Emit state */ 725 ATIMach64WaitForFIFO(pATI, 12); 726 outf(DP_SRC, m3d->dp_src); 727 outf(DP_MIX, m3d->dp_mix); 728 729 outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); 730 outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); 731 outf(DST_OFF_PITCH, m3d->dst_pitch_offset); 732 733 outf(SCALE_3D_CNTL, m3d->scale_3d_cntl); 734 outf(DP_WRITE_MASK, m3d->dp_write_mask); 735 outf(DP_PIX_WIDTH, m3d->dp_pix_width); 736 737 outf(SETUP_CNTL, 0); 738 739 outf(TEX_SIZE_PITCH, m3d->tex_size_pitch); 740 outf(TEX_CNTL, m3d->tex_cntl); 741 outf(TEX_0_OFF + offset, m3d->tex_offset); 742 743 return TRUE; 744} 745 746/* 747 * Vertex format, setup and emission. 748 */ 749typedef struct { 750 float s0; /* normalized texture coords */ 751 float t0; 752 float x; /* quarter-pixels */ 753 float y; 754 CARD32 argb; /* fragment color */ 755} Mach64Vertex; 756 757#define VTX_SET(_v, _col, _dstX, _dstY, _srcX, _dx, _srcY, _dy) \ 758do { \ 759 _v.s0 = ((float)(_srcX) + _dx) / m3d->tex_width; \ 760 _v.t0 = ((float)(_srcY) + _dy) / m3d->tex_height; \ 761 _v.x = ((float)(_dstX) * 4.0); \ 762 _v.y = ((float)(_dstY) * 4.0); \ 763 _v.argb = _col; \ 764} while (0) 765 766static __inline__ CARD32 767FVAL(float f) 768{ 769 union { float f; CARD32 c; } fc; 770 771 fc.f = f; 772 return fc.c; 773} 774 775#define VTX_OUT(_v, n) \ 776do { \ 777 float w = 1.0; \ 778 CARD32 z = 0xffff << 15; \ 779 CARD32 x_y = ((CARD16)_v.x << 16) | \ 780 ((CARD16)_v.y & 0xffff); \ 781 \ 782 ATIMach64WaitForFIFO(pATI, 6); \ 783 outf(VERTEX_##n##_S, FVAL(_v.s0)); \ 784 outf(VERTEX_##n##_T, FVAL(_v.t0)); \ 785 outf(VERTEX_##n##_W, FVAL(w)); \ 786 \ 787 outf(VERTEX_##n##_Z, z); \ 788 outf(VERTEX_##n##_ARGB, _v.argb); \ 789 outf(VERTEX_##n##_X_Y, x_y); \ 790} while (0) 791 792/* 793 * Composite acceleration hook. 794 */ 795void 796Mach64Composite 797( 798 PixmapPtr pDst, 799 int srcX, 800 int srcY, 801 int maskX, 802 int maskY, 803 int dstX, 804 int dstY, 805 int w, 806 int h 807) 808{ 809 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 810 ATIPtr pATI = ATIPTR(pScreenInfo); 811 Mach64ContextRegs3D *m3d = &pATI->m3d; 812 813 Mach64Vertex v0, v1, v2, v3; 814 float ooa; 815 CARD32 col; 816 PictVector v; 817 int srcXend, srcYend; 818 float dxy = 0.0, dwh = 0.0; 819 820 ATIDRISync(pScreenInfo); 821 822 /* Disable clipping if it gets in the way */ 823 ATIMach64ValidateClip(pATI, dstX, dstX + w - 1, dstY, dstY + h - 1); 824 825 /* Handle solid textures which come in as fragment color */ 826 col = m3d->frag_color; 827 if (m3d->frag_src) { 828 srcX = maskX; 829 srcY = maskY; 830 } 831 832 /* Handle transform */ 833 srcXend = srcX + w; 834 srcYend = srcY + h; 835 if (m3d->transform) { 836 v.vector[0] = IntToxFixed(srcX); 837 v.vector[1] = IntToxFixed(srcY); 838 v.vector[2] = xFixed1; 839 PictureTransformPoint(m3d->transform, &v); 840 srcX = xFixedToInt(v.vector[0]); 841 srcY = xFixedToInt(v.vector[1]); 842 843 v.vector[0] = IntToxFixed(srcXend); 844 v.vector[1] = IntToxFixed(srcYend); 845 v.vector[2] = xFixed1; 846 PictureTransformPoint(m3d->transform, &v); 847 srcXend = xFixedToInt(v.vector[0]); 848 srcYend = xFixedToInt(v.vector[1]); 849 850#if 0 851 /* Bilinear needs manipulation of texture coordinates */ 852 if (m3d->scale_3d_cntl & MACH64_BILINEAR_TEX_EN) { 853 dxy = 0.5; 854 dwh = -1.0; 855 } 856#endif 857 } 858 859 /* Create vertices in clock-wise order */ 860 VTX_SET(v0, col, dstX, dstY, srcX, dxy, srcY, dxy); 861 VTX_SET(v1, col, dstX + w, dstY, srcXend, dwh, srcY, dxy); 862 VTX_SET(v2, col, dstX + w, dstY + h, srcXend, dwh, srcYend, dwh); 863 VTX_SET(v3, col, dstX, dstY + h, srcX, dxy, srcYend, dwh); 864 865 /* Setup upper triangle (v0, v1, v3) */ 866 VTX_OUT(v0, 1); 867 VTX_OUT(v1, 2); 868 VTX_OUT(v3, 3); 869 870 ooa = 1.0 / (w * h); 871 outf(ONE_OVER_AREA, FVAL(ooa)); 872 873 /* Setup lower triangle (v2, v1, v3) */ 874 VTX_OUT(v2, 1); 875 876 ooa = -ooa; 877 outf(ONE_OVER_AREA, FVAL(ooa)); 878} 879 880/* 881 * DoneComposite acceleration hook. 882 */ 883void 884Mach64DoneComposite(PixmapPtr pDst) 885{ 886 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 887 ATIPtr pATI = ATIPTR(pScreenInfo); 888 889 ATIDRISync(pScreenInfo); 890 891 outf(SCALE_3D_CNTL, 0); 892} 893