📄 atimach64render.c
字号:
/* * Copyright 2006 George Sapountzis * All Rights Reserved. * * Based on the mach64 DRI and DRM drivers: * Copyright 2000 Gareth Hughes * Copyright 2002-2003 Leif Delgass * All Rights Reserved. * * Based on the ati hw/kdrive driver: * Copyright 2003 Eric Anholt, Anders Carlsson * * Based on the via hw/xfree86 driver: * Copyright 2006 Thomas Hellstrom. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Authors: * George Sapountzis <gsap7@yahoo.gr> *//* * Interesting cases for RENDER acceleration: * * cursor : ARGB8888 (24x24) Over * RGB565 * * glyph : A8 (9x10) Add * A8 (420x13) * glyph set : ARGB8888 (1x1 R) In * A8 (420x13) Over * RGB565 * * shadow : ARGB8888 (1x1 R) In * A8 (670x362) Over * RGB565 * translucent : RGB565 (652x344) In * A8 (1x1 R) Over * RGB565 * * In all interesting cases one of src/mask is "1x1 R". *//* * Assumptions and limitations of mach64 RENDER acceleration: * * RENDER acceleration is supported for GTPRO and later chips using the 3D * triangle setup, i.e. the VERTEX_? registers (see the dri driver). According * to atiregs.h, SCALE_3D_CNTL and TEX_?_OFF appear in GT, thus chips as old * as GT should be capable of RENDER acceleration, using the S_?_INC, T_?_INC * registers for texture mapping (see the directfb driver). * * GTPRO added a triangle setup engine and multitexturing. However, it seems * that none of the 8bpp mach64 formats expands the 8bit value to the alpha * channel in texture mapping, RGB8 appears to expand to (I,I,I,0). This makes * GTPRO multitexturing unsuitable for emulating the IN operation. Moreover, * it seems that GT/GTPRO has a muxltiplexer instead of a blender for computing * the final alpha channel which forbids destinations with an alpha channel and * generic two-pass compositing. * * A texture unit combines the fragment color (VERTEX_?_ARGB) coming in from * triangle rasterization with the texel from the texture according to the * texture environment (TEX_LIGHT_FCN_). "1x1 R" textures may come in as frag- * ment colors, eliminating the need for multitexturing in all interesting * cases (via also uses this optimization). * * Texture registers are saved/restored and cached (see atimach64.c). TEX_CNTL * cannot be cached because it flushes the texture cache. TEX_?_OFF are also * not cached because I am not sure whether writing at some offset register * affects the value at another offset. * * Vertex registers are not saved/restored. This shouldn't be a problem though * either for DRI or VT switch because vertex registers are set and used within * a signle acceleration hook. Synchronization between the DDX and DRI is based * on calling ATIDRISync() at the beginning of each DDX acceleration hook, * which suggests the assumption that individual acceleration hooks are not * interrupted. */#include <string.h>#include <stdio.h>/* * Helper functions copied from exa and via. */#if 0static voidMach64ExaCompositePictDesc(PicturePtr pict, char *string, int n){ char format[20]; char size[20]; if (!pict) { snprintf(string, n, "None"); return; } switch (pict->format) { case PICT_x8r8g8b8: snprintf(format, 20, "RGB8888 "); break; case PICT_x8b8g8r8: snprintf(format, 20, "BGR8888 "); break; case PICT_a8r8g8b8: snprintf(format, 20, "ARGB8888"); break; case PICT_a8b8g8r8: snprintf(format, 20, "ABGR8888"); break; case PICT_r5g6b5: snprintf(format, 20, "RGB565 "); break; case PICT_x1r5g5b5: snprintf(format, 20, "RGB555 "); break; case PICT_a8: snprintf(format, 20, "A8 "); break; case PICT_a1: snprintf(format, 20, "A1 "); break; default: snprintf(format, 20, "0x%x", (int)pict->format); break; } snprintf(size, 20, "%dx%d%s%s", pict->pDrawable->width, pict->pDrawable->height, pict->repeat ? " R" : "", pict->componentAlpha ? " C" : "" ); snprintf(string, n, "%-10p: fmt %s (%s)", (void *)pict->pDrawable, format, size);}static voidMach64ExaPrintComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, char *string){ char sop[20]; char srcdesc[40], maskdesc[40], dstdesc[40]; switch (op) { case PictOpSrc: sprintf(sop, "Src"); break; case PictOpOver: sprintf(sop, "Over"); break; case PictOpInReverse: sprintf(sop, "InR"); break; case PictOpOutReverse: sprintf(sop, "OutR"); break; case PictOpAdd: sprintf(sop, "Add"); break; default: sprintf(sop, "0x%x", (int)op); break; } Mach64ExaCompositePictDesc(pSrc, srcdesc, 40); Mach64ExaCompositePictDesc(pMask, maskdesc, 40); Mach64ExaCompositePictDesc(pDst, dstdesc, 40); sprintf(string, "op %s, \n" " src %s\n" " mask %s\n" " dst %s\n", sop, srcdesc, maskdesc, dstdesc);}#endifstatic __inline__ CARD32viaBitExpandHelper(CARD32 component, CARD32 bits){ CARD32 tmp, mask; mask = (1 << (8 - bits)) - 1; tmp = component << (8 - bits); return ((component & 1) ? tmp | mask : tmp);}static __inline__ voidMach64PixelARGB(PixmapPtr pPixmap, CARD32 format, CARD32 *argb){ CARD32 pixel; CARD8 comp; int bits, shift; /* Ensure that texture drawing has completed. */ exaWaitSync(pPixmap->drawable.pScreen); /* exaGetPixmapFirstPixel() */ switch (pPixmap->drawable.bitsPerPixel) { case 32: pixel = *(CARD32 *)(pPixmap->devPrivate.ptr); break; case 16: pixel = *(CARD16 *)(pPixmap->devPrivate.ptr); break; default: pixel = *(CARD8 *)(pPixmap->devPrivate.ptr); break; } /* exaGetRGBAFromPixel()/viaPixelARGB8888() */ switch (PICT_FORMAT_TYPE(format)) { case PICT_TYPE_A: shift = 0; bits = PICT_FORMAT_A(format); comp = (pixel >> shift) & ((1 << bits) - 1); comp = viaBitExpandHelper(comp, bits); *argb = comp << 24; break; case PICT_TYPE_ARGB: shift = 0; bits = PICT_FORMAT_B(format); comp = (pixel >> shift) & ((1 << bits) - 1); comp = viaBitExpandHelper(comp, bits); *argb = comp; shift += bits; bits = PICT_FORMAT_G(format); comp = (pixel >> shift) & ((1 << bits) - 1); comp = viaBitExpandHelper(comp, bits); *argb |= comp << 8; shift += bits; bits = PICT_FORMAT_R(format); comp = (pixel >> shift) & ((1 << bits) - 1); comp = viaBitExpandHelper(comp, bits); *argb |= comp << 16; shift += bits; bits = PICT_FORMAT_A(format); if (bits) { comp = (pixel >> shift) & ((1 << bits) - 1); comp = viaBitExpandHelper(comp, bits); } else { comp = 0xff; } *argb |= comp << 24; break; case PICT_TYPE_ABGR: break; default: break; }}/* * RENDER acceleration for mach64 */typedef struct { Bool supported; CARD32 scale_3d_cntl;} Mach64BlendOp;static Mach64BlendOp Mach64BlendOps[] = { /* Clear */ {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_ZERO}, /* Src */ {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_ZERO}, /* Dst */ {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_ONE}, /* Over */ {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, /* OverReverse */ {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_ONE}, /* In */ {1, MACH64_ALPHA_BLEND_SRC_DSTALPHA | MACH64_ALPHA_BLEND_DST_ZERO}, /* InReverse */ {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_SRCALPHA}, /* Out */ {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_ZERO}, /* OutReverse */ {1, MACH64_ALPHA_BLEND_SRC_ZERO | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, /* Atop */ {0, MACH64_ALPHA_BLEND_SRC_DSTALPHA | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, /* AtopReverse */ {0, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_SRCALPHA}, /* Xor */ {1, MACH64_ALPHA_BLEND_SRC_INVDSTALPHA | MACH64_ALPHA_BLEND_DST_INVSRCALPHA}, /* Add */ {1, MACH64_ALPHA_BLEND_SRC_ONE | MACH64_ALPHA_BLEND_DST_ONE}};#define MACH64_NR_BLEND_OPS \ (sizeof(Mach64BlendOps) / sizeof(Mach64BlendOps[0]))typedef struct { CARD32 pictFormat; CARD32 dstFormat; CARD32 texFormat;} Mach64TexFormat;static Mach64TexFormat Mach64TexFormats[] = { {PICT_a8r8g8b8, -1, MACH64_DATATYPE_ARGB8888}, {PICT_x8r8g8b8, MACH64_DATATYPE_ARGB8888, MACH64_DATATYPE_ARGB8888}, {PICT_a1r5g5b5, -1, MACH64_DATATYPE_ARGB1555}, {PICT_x1r5g5b5, MACH64_DATATYPE_ARGB1555, MACH64_DATATYPE_ARGB1555}, {PICT_r5g6b5, MACH64_DATATYPE_RGB565, MACH64_DATATYPE_RGB565 }, {PICT_a8, MACH64_DATATYPE_RGB8, MACH64_DATATYPE_RGB8 }};#define MACH64_NR_TEX_FORMATS \ (sizeof(Mach64TexFormats) / sizeof(Mach64TexFormats[0]))#define MACH64_PICT_IS_1x1R(_pPict) \ ((_pPict) && \ (_pPict)->pDrawable->width == 1 && \ (_pPict)->pDrawable->height == 1 && \ (_pPict)->repeat)/* * CheckComposite hook helper functions. */static __inline__ BoolMach64GetOrder(int val, int *shift){ *shift = 0; while (val > (1 << *shift)) (*shift)++; return (val == (1 << *shift));}static BoolMach64CheckTexture(PicturePtr pPict){ int w = pPict->pDrawable->width; int h = pPict->pDrawable->height; int l2w, l2h, level, i; for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { if (Mach64TexFormats[i].pictFormat == pPict->format) break; } if (i == MACH64_NR_TEX_FORMATS) MACH64_FALLBACK(("Unsupported picture format 0x%x\n", (int)pPict->format)); /* l2w equals l2p (pitch) for all interesting cases (w >= 64) */ Mach64GetOrder(w, &l2w); Mach64GetOrder(h, &l2h); level = (l2w > l2h) ? l2w : l2h; if (level > 10) MACH64_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); return TRUE;}/* * CheckComposite acceleration hook. */BoolMach64CheckComposite( int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture){ Bool src_solid, mask_solid, mask_comp, op_comp; int i; if (op >= MACH64_NR_BLEND_OPS || !Mach64BlendOps[op].supported) return FALSE; if (!Mach64CheckTexture(pSrcPicture)) return FALSE; if (pMaskPicture && !Mach64CheckTexture(pMaskPicture)) return FALSE; /* Check destination format */ for (i = 0; i < MACH64_NR_TEX_FORMATS; i++) { if (Mach64TexFormats[i].pictFormat == pDstPicture->format) break; } if (i == MACH64_NR_TEX_FORMATS || Mach64TexFormats[i].dstFormat == -1) MACH64_FALLBACK(("Unsupported dst format 0x%x\n", (int)pDstPicture->format)); /* Check that A8 src/dst appears only as "A8 ADD A8" */ if (pDstPicture->format == PICT_a8) { if (pMaskPicture || pSrcPicture->format != PICT_a8 || op != PictOpAdd) MACH64_FALLBACK(("A8 dst with mask or non-A8 src.\n")); } if (pDstPicture->format != PICT_a8) { if (pSrcPicture->format == PICT_a8) MACH64_FALLBACK(("A8 src with non-A8 dst.\n")); } /* Check that one of src/mask can come in as the fragment color. */ src_solid = MACH64_PICT_IS_1x1R(pSrcPicture); mask_solid = MACH64_PICT_IS_1x1R(pMaskPicture); mask_comp = pMaskPicture && pMaskPicture->componentAlpha; op_comp = op == PictOpAdd || op == PictOpInReverse || op == PictOpOutReverse; if (mask_solid && src_solid) MACH64_FALLBACK(("Bad one-pixel IN composite operation.\n")); if (pMaskPicture) { if (!mask_solid && !src_solid) MACH64_FALLBACK(("Multitexturing required.\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -