atimach64render.c revision 11b80dae
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 348 w = pPict->pDrawable->width; 349 h = pPict->pDrawable->height; 350 351 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 352 if (Mach64TexFormats[i].pictFormat == pPict->format) 353 break; 354 } 355 356 if (i == MACH64_NR_TEX_FORMATS) 357 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 358 (int)pPict->format)); 359 360 /* l2w equals l2p (pitch) for all interesting cases (w >= 64) */ 361 Mach64GetOrder(w, &l2w); 362 Mach64GetOrder(h, &l2h); 363 364 level = (l2w > l2h) ? l2w : l2h; 365 366 if (level > 10) 367 MACH64_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); 368 369 return TRUE; 370} 371 372/* 373 * CheckComposite acceleration hook. 374 */ 375Bool 376Mach64CheckComposite 377( 378 int op, 379 PicturePtr pSrcPicture, 380 PicturePtr pMaskPicture, 381 PicturePtr pDstPicture 382) 383{ 384 Bool src_solid, mask_solid, mask_comp, op_comp; 385 int i; 386 387 if (op >= MACH64_NR_BLEND_OPS || !Mach64BlendOps[op].supported) 388 return FALSE; 389 390 if (!Mach64CheckTexture(pSrcPicture)) 391 return FALSE; 392 393 if (pMaskPicture && !Mach64CheckTexture(pMaskPicture)) 394 return FALSE; 395 396 /* Check destination format */ 397 398 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 399 if (Mach64TexFormats[i].pictFormat == pDstPicture->format) 400 break; 401 } 402 403 if (i == MACH64_NR_TEX_FORMATS || Mach64TexFormats[i].dstFormat == -1) 404 MACH64_FALLBACK(("Unsupported dst format 0x%x\n", 405 (int)pDstPicture->format)); 406 407 /* Check that A8 src/dst appears only as "A8 ADD A8" */ 408 409 if (pDstPicture->format == PICT_a8) { 410 if (pMaskPicture || pSrcPicture->format != PICT_a8 || op != PictOpAdd) 411 MACH64_FALLBACK(("A8 dst with mask or non-A8 src.\n")); 412 } 413 414 if (pDstPicture->format != PICT_a8) { 415 if (pSrcPicture->format == PICT_a8) 416 MACH64_FALLBACK(("A8 src with non-A8 dst.\n")); 417 } 418 419 /* Check that one of src/mask can come in as the fragment color. */ 420 421 src_solid = MACH64_PICT_IS_1x1R(pSrcPicture); 422 423 mask_solid = MACH64_PICT_IS_1x1R(pMaskPicture); 424 425 mask_comp = pMaskPicture && pMaskPicture->componentAlpha; 426 427 op_comp = op == PictOpAdd || 428 op == PictOpInReverse || 429 op == PictOpOutReverse; 430 431 if (mask_solid && src_solid) 432 MACH64_FALLBACK(("Bad one-pixel IN composite operation.\n")); 433 434 if (pMaskPicture) { 435 if (!mask_solid && !src_solid) 436 MACH64_FALLBACK(("Multitexturing required.\n")); 437 438 if (!mask_solid && !op_comp) 439 MACH64_FALLBACK(("Non-solid mask.\n")); 440 441 if (mask_comp && !src_solid) 442 MACH64_FALLBACK(("Component-alpha mask.\n")); 443 444 if (!mask_comp && pMaskPicture->format != PICT_a8) 445 MACH64_FALLBACK(("Non-A8 mask.\n")); 446 447 if (mask_comp && pMaskPicture->format != PICT_a8r8g8b8) 448 MACH64_FALLBACK(("Non-ARGB mask.\n")); 449 } 450 451 return TRUE; 452} 453 454/* 455 * This function setups the fragment color from a solid pixmap in the presence 456 * of a mask. 457 */ 458static __inline__ Bool 459Mach64PrepareMask 460( 461 Mach64ContextRegs3D *m3d, 462 int op, 463 PicturePtr pSrcPicture, 464 PicturePtr pMaskPicture, 465 PixmapPtr pSrc, 466 PixmapPtr pMask 467) 468{ 469 Bool mask_solid, src_solid; 470 CARD32 argb = 0; 471 472 mask_solid = MACH64_PICT_IS_1x1R(pMaskPicture); 473 474 src_solid = MACH64_PICT_IS_1x1R(pSrcPicture); 475 476 if (mask_solid) { 477 Mach64PixelARGB(pMask, pMaskPicture->format, &argb); 478 argb >>= 24; 479 argb &= 0xff; 480 481 m3d->frag_mask = TRUE; 482 m3d->frag_color = (argb << 24) | (argb << 16) | (argb << 8) | argb; 483 return TRUE; 484 } 485 486 if (src_solid) { 487 /* We can only handle cases where either the src color (e.g. ADD) or 488 * the src alpha (e.g. IN_REV, OUT_REV) is used but not both. 489 * 490 * (ARGB8888 IN A8) OVER RGB565 is implemented as: 491 * (ARGB8888 IN A8) ADD ((ARGB8888 IN A8) OUT_REV RGB565). 492 */ 493 if (op == PictOpInReverse || op == PictOpOutReverse) { 494 Mach64PixelARGB(pSrc, pSrcPicture->format, &argb); 495 argb >>= 24; 496 argb &= 0xff; 497 498 m3d->frag_src = TRUE; 499 m3d->frag_color = (argb << 24) | (argb << 16) | (argb << 8) | argb; 500 m3d->color_alpha = TRUE; 501 return TRUE; 502 } 503 504 if (op == PictOpAdd) { 505 Mach64PixelARGB(pSrc, pSrcPicture->format, &argb); 506 507 m3d->frag_src = TRUE; 508 m3d->frag_color = argb; 509 return TRUE; 510 } 511 } 512 513 return FALSE; 514} 515 516/* 517 * This function setups the texturing and blending environments. It also 518 * manipulates blend control for non-solid masks. 519 */ 520static void __inline__ 521Mach64BlendCntl(Mach64ContextRegs3D *m3d, int op) 522{ 523 m3d->scale_3d_cntl |= MACH64_SCALE_PIX_EXPAND_DYNAMIC_RANGE | 524 MACH64_SCALE_DITHER_2D_TABLE | 525 MACH64_DITHER_INIT_RESET; 526 527 m3d->scale_3d_cntl |= Mach64BlendOps[op].scale_3d_cntl; 528 529 if (m3d->color_alpha) { 530 /* A8 uses RGB8 which expands to (I,I,I,0). Thus, we use the color 531 * channels instead of the alpha channel as the alpha factor. We also 532 * use the color channels for ARGB8888 masks with component-alpha. 533 */ 534 CARD32 Ad = m3d->scale_3d_cntl & MACH64_ALPHA_BLEND_DST_MASK; 535 536 /* InReverse */ 537 if (Ad == MACH64_ALPHA_BLEND_DST_SRCALPHA) { 538 m3d->scale_3d_cntl &= ~MACH64_ALPHA_BLEND_DST_MASK; 539 m3d->scale_3d_cntl |= MACH64_ALPHA_BLEND_DST_SRCCOLOR; 540 } 541 542 /* OutReverse */ 543 if (Ad == MACH64_ALPHA_BLEND_DST_INVSRCALPHA) { 544 m3d->scale_3d_cntl &= ~MACH64_ALPHA_BLEND_DST_MASK; 545 m3d->scale_3d_cntl |= MACH64_ALPHA_BLEND_DST_INVSRCCOLOR; 546 } 547 } 548 549 /* Can't color mask and blend at the same time */ 550 m3d->dp_write_mask = 0xffffffff; 551 552 /* Can't fog and blend at the same time */ 553 m3d->scale_3d_cntl |= MACH64_ALPHA_FOG_EN_ALPHA; 554 555 /* Enable texture mapping mode */ 556 m3d->scale_3d_cntl |= MACH64_SCALE_3D_FCN_TEXTURE; 557 m3d->scale_3d_cntl |= MACH64_MIP_MAP_DISABLE; 558 559 /* Setup the texture environment */ 560 m3d->scale_3d_cntl |= MACH64_TEX_LIGHT_FCN_MODULATE; 561 562 /* Initialize texture unit */ 563 m3d->tex_cntl |= MACH64_TEX_ST_DIRECT | 564 MACH64_TEX_SRC_LOCAL | 565 MACH64_TEX_UNCOMPRESSED | 566 MACH64_TEX_CACHE_FLUSH | 567 MACH64_TEX_CACHE_SIZE_4K; 568} 569 570/* 571 * This function setups the texture unit. 572 */ 573static Bool 574Mach64PrepareTexture(PicturePtr pPict, PixmapPtr pPix) 575{ 576 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pPix->drawable.pScreen); 577 ATIPtr pATI = ATIPTR(pScreenInfo); 578 Mach64ContextRegs3D *m3d = &pATI->m3d; 579 580 CARD32 texFormat; 581 582 int w = pPict->pDrawable->width; 583 int h = pPict->pDrawable->height; 584 int l2w, l2h, l2p, level, pitch, cpp, i; 585 586 /* Prepare picture format */ 587 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 588 if (Mach64TexFormats[i].pictFormat == pPict->format) 589 break; 590 } 591 if (i == MACH64_NR_TEX_FORMATS) 592 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 593 (int)pPict->format)); 594 texFormat = Mach64TexFormats[i].texFormat; 595 596 /* Prepare picture size */ 597 cpp = PICT_FORMAT_BPP(pPict->format) / 8; 598 pitch = exaGetPixmapPitch(pPix) / cpp; 599 600 Mach64GetOrder(w, &l2w); 601 Mach64GetOrder(h, &l2h); 602 Mach64GetOrder(pitch, &l2p); 603 604 if (pPict->repeat && w == 1 && h == 1) 605 l2p = 0; 606 else if (pPict->repeat) 607 MACH64_FALLBACK(("Repeat not supported for w,h != 1,1\n")); 608 609 l2w = l2p; 610 611 level = (l2w > l2h) ? l2w : l2h; 612 613 m3d->tex_width = (1 << l2w); 614 m3d->tex_height = (1 << l2h); 615 616 /* Update hw state */ 617 m3d->dp_pix_width |= SetBits(texFormat, DP_SCALE_PIX_WIDTH); 618 619 m3d->tex_size_pitch = (l2w << 0) | 620 (level << 4) | 621 (l2h << 8); 622 623 m3d->tex_offset = exaGetPixmapOffset(pPix); 624 625 if (PICT_FORMAT_A(pPict->format)) 626 m3d->scale_3d_cntl |= MACH64_TEX_MAP_AEN; 627 628 switch (pPict->filter) { 629 case PictFilterNearest: 630 m3d->scale_3d_cntl |= MACH64_TEX_BLEND_FCN_NEAREST; 631 break; 632 case PictFilterBilinear: 633 /* FIXME */ 634#if 0 635 m3d->scale_3d_cntl |= MACH64_TEX_BLEND_FCN_LINEAR; 636 m3d->scale_3d_cntl |= MACH64_BILINEAR_TEX_EN; 637#endif 638 MACH64_FALLBACK(("Bilinear filter 0x%x\n", pPict->filter)); 639 break; 640 default: 641 MACH64_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); 642 } 643 644 m3d->transform = pPict->transform; 645 646 return TRUE; 647} 648 649/* 650 * PrepareComposite acceleration hook. 651 */ 652Bool 653Mach64PrepareComposite 654( 655 int op, 656 PicturePtr pSrcPicture, 657 PicturePtr pMaskPicture, 658 PicturePtr pDstPicture, 659 PixmapPtr pSrc, 660 PixmapPtr pMask, 661 PixmapPtr pDst 662) 663{ 664 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 665 ATIPtr pATI = ATIPTR(pScreenInfo); 666 Mach64ContextRegs3D *m3d = &pATI->m3d; 667 668 CARD32 dstFormat; 669 int offset, i; 670 671 ATIDRISync(pScreenInfo); 672 673 /* Initialize state */ 674 m3d->dp_mix = SetBits(MIX_SRC, DP_BKGD_MIX) | 675 SetBits(MIX_SRC, DP_FRGD_MIX); 676 677 m3d->dp_src = SetBits(SRC_SCALER_3D, DP_BKGD_SRC) | 678 SetBits(SRC_SCALER_3D, DP_FRGD_SRC) | 679 DP_MONO_SRC_ALLONES; 680 681 Mach64GetPixmapOffsetPitch(pDst, &m3d->dst_pitch_offset); 682 683 m3d->scale_3d_cntl = 0; 684 m3d->tex_cntl = 0; 685 686 m3d->frag_src = FALSE; 687 m3d->frag_mask = FALSE; 688 m3d->frag_color = 0xffffffff; 689 690 m3d->color_alpha = FALSE; 691 692 m3d->transform = NULL; 693 694 /* Compute state */ 695 if (pMaskPicture && !Mach64PrepareMask(m3d, op, pSrcPicture, pMaskPicture, 696 pSrc, pMask)) 697 return FALSE; 698 699 Mach64BlendCntl(m3d, op); 700 701 for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { 702 if (Mach64TexFormats[i].pictFormat == pDstPicture->format) 703 break; 704 } 705 if (i == MACH64_NR_TEX_FORMATS) 706 MACH64_FALLBACK(("Unsupported picture format 0x%x\n", 707 (int)pPict->format)); 708 dstFormat = Mach64TexFormats[i].dstFormat; 709 710 m3d->dp_pix_width = SetBits(dstFormat, DP_DST_PIX_WIDTH) | 711 SetBits(dstFormat, DP_SRC_PIX_WIDTH) | 712 SetBits(dstFormat, DP_HOST_PIX_WIDTH); 713 714 if (!m3d->frag_src) { 715 if (!Mach64PrepareTexture(pSrcPicture, pSrc)) 716 return FALSE; 717 } 718 719 if (pMaskPicture && !m3d->frag_mask) { 720 if (!Mach64PrepareTexture(pMaskPicture, pMask)) 721 return FALSE; 722 } 723 724 offset = TEX_LEVEL(m3d->tex_size_pitch); 725 726 /* Emit state */ 727 ATIMach64WaitForFIFO(pATI, 12); 728 outf(DP_SRC, m3d->dp_src); 729 outf(DP_MIX, m3d->dp_mix); 730 731 outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); 732 outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); 733 outf(DST_OFF_PITCH, m3d->dst_pitch_offset); 734 735 outf(SCALE_3D_CNTL, m3d->scale_3d_cntl); 736 outf(DP_WRITE_MASK, m3d->dp_write_mask); 737 outf(DP_PIX_WIDTH, m3d->dp_pix_width); 738 739 outf(SETUP_CNTL, 0); 740 741 outf(TEX_SIZE_PITCH, m3d->tex_size_pitch); 742 outf(TEX_CNTL, m3d->tex_cntl); 743 outf(TEX_0_OFF + offset, m3d->tex_offset); 744 745 return TRUE; 746} 747 748/* 749 * Vertex format, setup and emission. 750 */ 751typedef struct { 752 float s0; /* normalized texture coords */ 753 float t0; 754 float x; /* quarter-pixels */ 755 float y; 756 CARD32 argb; /* fragment color */ 757} Mach64Vertex; 758 759#define VTX_SET(_v, _col, _dstX, _dstY, _srcX, _dx, _srcY, _dy) \ 760do { \ 761 _v.s0 = ((float)(_srcX) + _dx) / m3d->tex_width; \ 762 _v.t0 = ((float)(_srcY) + _dy) / m3d->tex_height; \ 763 _v.x = ((float)(_dstX) * 4.0); \ 764 _v.y = ((float)(_dstY) * 4.0); \ 765 _v.argb = _col; \ 766} while (0) 767 768static __inline__ CARD32 769FVAL(float f) 770{ 771 union { float f; CARD32 c; } fc; 772 773 fc.f = f; 774 return fc.c; 775} 776 777#define VTX_OUT(_v, n) \ 778do { \ 779 float w = 1.0; \ 780 CARD32 z = 0xffff << 15; \ 781 CARD32 x_y = ((CARD16)_v.x << 16) | \ 782 ((CARD16)_v.y & 0xffff); \ 783 \ 784 ATIMach64WaitForFIFO(pATI, 6); \ 785 outf(VERTEX_##n##_S, FVAL(_v.s0)); \ 786 outf(VERTEX_##n##_T, FVAL(_v.t0)); \ 787 outf(VERTEX_##n##_W, FVAL(w)); \ 788 \ 789 outf(VERTEX_##n##_Z, z); \ 790 outf(VERTEX_##n##_ARGB, _v.argb); \ 791 outf(VERTEX_##n##_X_Y, x_y); \ 792} while (0) 793 794/* 795 * Composite acceleration hook. 796 */ 797void 798Mach64Composite 799( 800 PixmapPtr pDst, 801 int srcX, 802 int srcY, 803 int maskX, 804 int maskY, 805 int dstX, 806 int dstY, 807 int w, 808 int h 809) 810{ 811 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 812 ATIPtr pATI = ATIPTR(pScreenInfo); 813 Mach64ContextRegs3D *m3d = &pATI->m3d; 814 815 Mach64Vertex v0, v1, v2, v3; 816 float ooa; 817 CARD32 col; 818 PictVector v; 819 int srcXend, srcYend; 820 float dxy = 0.0, dwh = 0.0; 821 822 ATIDRISync(pScreenInfo); 823 824 /* Disable clipping if it gets in the way */ 825 ATIMach64ValidateClip(pATI, dstX, dstX + w - 1, dstY, dstY + h - 1); 826 827 /* Handle solid textures which come in as fragment color */ 828 col = m3d->frag_color; 829 if (m3d->frag_src) { 830 srcX = maskX; 831 srcY = maskY; 832 } 833 834 /* Handle transform */ 835 srcXend = srcX + w; 836 srcYend = srcY + h; 837 if (m3d->transform) { 838 v.vector[0] = IntToxFixed(srcX); 839 v.vector[1] = IntToxFixed(srcY); 840 v.vector[2] = xFixed1; 841 PictureTransformPoint(m3d->transform, &v); 842 srcX = xFixedToInt(v.vector[0]); 843 srcY = xFixedToInt(v.vector[1]); 844 845 v.vector[0] = IntToxFixed(srcXend); 846 v.vector[1] = IntToxFixed(srcYend); 847 v.vector[2] = xFixed1; 848 PictureTransformPoint(m3d->transform, &v); 849 srcXend = xFixedToInt(v.vector[0]); 850 srcYend = xFixedToInt(v.vector[1]); 851 852#if 0 853 /* Bilinear needs manipulation of texture coordinates */ 854 if (m3d->scale_3d_cntl & MACH64_BILINEAR_TEX_EN) { 855 dxy = 0.5; 856 dwh = -1.0; 857 } 858#endif 859 } 860 861 /* Create vertices in clock-wise order */ 862 VTX_SET(v0, col, dstX, dstY, srcX, dxy, srcY, dxy); 863 VTX_SET(v1, col, dstX + w, dstY, srcXend, dwh, srcY, dxy); 864 VTX_SET(v2, col, dstX + w, dstY + h, srcXend, dwh, srcYend, dwh); 865 VTX_SET(v3, col, dstX, dstY + h, srcX, dxy, srcYend, dwh); 866 867 /* Setup upper triangle (v0, v1, v3) */ 868 VTX_OUT(v0, 1); 869 VTX_OUT(v1, 2); 870 VTX_OUT(v3, 3); 871 872 ooa = 1.0 / (w * h); 873 outf(ONE_OVER_AREA, FVAL(ooa)); 874 875 /* Setup lower triangle (v2, v1, v3) */ 876 VTX_OUT(v2, 1); 877 878 ooa = -ooa; 879 outf(ONE_OVER_AREA, FVAL(ooa)); 880} 881 882/* 883 * DoneComposite acceleration hook. 884 */ 885void 886Mach64DoneComposite(PixmapPtr pDst) 887{ 888 ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pDst->drawable.pScreen); 889 ATIPtr pATI = ATIPTR(pScreenInfo); 890 891 ATIDRISync(pScreenInfo); 892 893 outf(SCALE_3D_CNTL, 0); 894} 895