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