diff --git a/hw/kdrive/mga/g400_composite.c b/hw/kdrive/mga/g400_composite.c index 1992e024a..e0ecdcd73 100644 --- a/hw/kdrive/mga/g400_composite.c +++ b/hw/kdrive/mga/g400_composite.c @@ -31,8 +31,14 @@ #include "g400_common.h" +static PicturePtr currentSrcPicture; +static PicturePtr currentMaskPicture; static PixmapPtr currentSrc; static PixmapPtr currentMask; +static int src_w2; +static int src_h2; +static int mask_w2; +static int mask_h2; struct blendinfo { Bool dst_alpha; @@ -85,16 +91,18 @@ static struct formatinfo texformats[] = { {PICT_a8, MGA_TW8A}, }; -static int MGA_LOG2( int val ) +static int +MGA_LOG2( int val ) { int ret = 0; - + if (val==1) return 0; while (val >> ret) ret++; return ((1 << (ret-1)) == val) ? (ret-1) : ret; } + static Bool mgaCheckSourceTexture (int tmu, PicturePtr pPict) @@ -105,7 +113,7 @@ mgaCheckSourceTexture (int tmu, CARD32 texctl = 0; if ((w > 2047) || (h > 2047)) - MGA_FALLBACK(("Picture too large for composition (%dx%d)\n", w, h)); + MGA_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) { if (texformats[i].fmt == pPict->format) { @@ -114,10 +122,16 @@ mgaCheckSourceTexture (int tmu, } } if (texctl == 0) { - MGA_FALLBACK(("Picture is in unsupported format 0x%x\n" - pPict->format)); + MGA_FALLBACK(("Unsupported picture format 0x%x\n", pPict->format)); } + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + MGA_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + MGA_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter)); + return TRUE; } @@ -138,22 +152,28 @@ PrepareSourceTexture (int tmu, int texctl = MGA_PITCHLIN | ((pitch & (2048 - 1)) << 9) | MGA_CLAMPUV | MGA_NOPERSPECTIVE; - int texctl2=MGA_G400_TC2_MAGIC; - + int flags = 0; + int texctl2 = MGA_G400_TC2_MAGIC | flags; + for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) { if (texformats[i].fmt == pSrcPicture->format) { texctl |= texformats[i].card_fmt; break; } } + if (PICT_FORMAT_A(pSrcPicture->format) != 0) { texctl |= MGA_TAKEY; } else { texctl |= MGA_TAMASK | MGA_TAKEY; } - + + if (pSrcPicture->repeat) { + texctl &= ~MGA_CLAMPUV; + } + if (tmu == 1) - texctl2 |= MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1; + texctl2 |= MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1 | flags; mgaWaitAvail (6); MGA_OUT32 (mmio, MGA_REG_TEXCTL2, texctl2); @@ -162,17 +182,91 @@ PrepareSourceTexture (int tmu, MGA_OUT32 (mmio, MGA_REG_TEXORG, ((int)pSrc->devPrivate.ptr - mem_base)); MGA_OUT32 (mmio, MGA_REG_TEXWIDTH, (w-1)<<18 | ((8-w_log2)&63)<<9 | w_log2); MGA_OUT32 (mmio, MGA_REG_TEXHEIGHT, (h-1)<<18 | ((8-h_log2)&63)<<9 | h_log2); - /* Disable filtering since we aren't doing stretch blit */ - MGA_OUT32 (mmio, MGA_REG_TEXFILTER, (0x10<<21) | MGA_MAG_NRST | MGA_MIN_NRST); - + /* Set blit filtering flags */ + if (pSrcPicture->filter == PictFilterBilinear) { + MGA_OUT32 (mmio, MGA_REG_TEXFILTER, + (0x10<<21) | MGA_MAG_BILIN | MGA_MIN_BILIN); + } else { + MGA_OUT32 (mmio, MGA_REG_TEXFILTER, + (0x10<<21) | MGA_MAG_NRST | MGA_MIN_NRST); + } + if (tmu == 1) { mgaWaitAvail (1); - MGA_OUT32 (mmio, MGA_REG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX); + MGA_OUT32 (mmio, MGA_REG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX | flags); } return TRUE; } + +/* + * The formals params are the elements of the following matrix: + * + * Dest Transform Src + * coords coords + * / Xdst \ / X_incx X_incy X_init \ / Xsrc \ + * | Ydst | = | Y_incx Y_incy Y_init | x | Ysrc | + * \ 1 / \ H_incx H_incy H_init / \ 1 / + * + * matrix elements are 32bits fixed points (16.16) + * mga_fx_* is the size of the fixed point for the TMU + */ +static void +setTMIncrementsRegs(int X_incx, + int X_incy, + int X_init, + int Y_incx, + int Y_incy, + int Y_init, + int H_incx, + int H_incy, + int H_init, + int mga_fx_width_size, + int mga_fx_height_size) { + int decalw = mga_fx_width_size - 16; + int decalh = mga_fx_height_size - 16; + + /* Convert 16 bits fixpoint -> MGA variable size fixpoint */ + if (decalw >= 0) { + X_incx = X_incx << decalw; + X_incy = X_incy << decalw; + X_init = X_init << decalw; + } else { + decalw =- decalw; + X_incx = X_incx >> decalw; + X_incy = X_incy >> decalw; + X_init = X_init >> decalw; + } + + /* Convert 16 bits fixpoint -> MGA variable size fixpoint */ + if (decalh >= 0) { + Y_incx = Y_incx << decalh; + Y_incy = Y_incy << decalh; + Y_init = Y_init << decalh; + } else { + decalh =- decalh; + Y_incx = Y_incx >> decalh; + Y_incy = Y_incy >> decalh; + Y_init = Y_init >> decalh; + } + + /* Set TM registers */ + mgaWaitAvail (9); + MGA_OUT32 (mmio, MGA_REG_TMR0, X_incx); + MGA_OUT32 (mmio, MGA_REG_TMR1, Y_incx); + MGA_OUT32 (mmio, MGA_REG_TMR2, X_incy); + MGA_OUT32 (mmio, MGA_REG_TMR3, Y_incy); + MGA_OUT32 (mmio, MGA_REG_TMR4, H_incx); + MGA_OUT32 (mmio, MGA_REG_TMR5, H_incy); + MGA_OUT32 (mmio, MGA_REG_TMR6, X_init); + MGA_OUT32 (mmio, MGA_REG_TMR7, Y_init); + MGA_OUT32 (mmio, MGA_REG_TMR8, H_init); +} + + + + Bool mgaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) @@ -181,15 +275,12 @@ mgaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, MGA_FALLBACK(("unsupported op %x", op)); if (!mgaCheckSourceTexture (0, pSrcPicture)) return FALSE; - if (pSrcPicture->transform != NULL) - MGA_FALLBACK(("Transformed src unsupported")); + if (pMaskPicture != NULL) { if (PICT_FORMAT_A(pMaskPicture->format) == 0) MGA_FALLBACK(("Mask without alpha unsupported")); if (!mgaCheckSourceTexture (1, pMaskPicture)) return FALSE; - if (pMaskPicture->transform != NULL) - MGA_FALLBACK(("Transformed mask unsupported")); } if (pMaskPicture->componentAlpha) @@ -203,20 +294,26 @@ mgaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, return TRUE; } -#define C_ARG1_CUR 0x0 +#define C_ARG1_CUR 0x0 +#define C_ARG1_ALPHA MGA_TDS_COLOR_ARG1_REPLICATEALPHA #define C_ARG2_DIFFUSE MGA_TDS_COLOR_ARG2_DIFFUSE +#define C_ARG2_FCOL MGA_TDS_COLOR_ARG2_FCOL #define C_ARG2_PREV MGA_TDS_COLOR_ARG2_PREVSTAGE +#define C_ARG1_INV MGA_TDS_COLOR_ARG1_INV +#define C_ARG2_INV MGA_TDS_COLOR_ARG2_INV #define COLOR_MUL MGA_TDS_COLOR_SEL_MUL #define COLOR_ARG1 MGA_TDS_COLOR_SEL_ARG1 #define COLOR_ARG2 MGA_TDS_COLOR_SEL_ARG2 #define A_ARG1_CUR 0x0 #define A_ARG2_IGN A_ARG2_DIFFUSE +#define A_ARG2_FCOL MGA_TDS_ALPHA_ARG2_FCOL #define A_ARG2_DIFFUSE MGA_TDS_ALPHA_ARG2_DIFFUSE #define A_ARG2_PREV MGA_TDS_ALPHA_ARG2_PREVSTAGE #define ALPHA_MUL MGA_TDS_ALPHA_SEL_MUL #define ALPHA_ARG1 MGA_TDS_ALPHA_SEL_ARG1 #define ALPHA_ARG2 MGA_TDS_ALPHA_SEL_ARG2 + Bool mgaPrepareComposite (int op, PicturePtr pSrcPicture, @@ -229,71 +326,84 @@ mgaPrepareComposite (int op, KdScreenPriv (pSrc->drawable.pScreen); int mem_base=(int)pScreenPriv->screen->memory_base; int cmd, blendcntl; - - mgaWaitIdle(); + int ds0, ds1; + /* Init MGA (clipping) */ - mgaSetup (pSrc->drawable.pScreen, pDst->drawable.bitsPerPixel, 5); - MGA_OUT32 (mmio, MGA_REG_TMR1, 0); - MGA_OUT32 (mmio, MGA_REG_TMR2, 0); - MGA_OUT32 (mmio, MGA_REG_TMR3, 0); - MGA_OUT32 (mmio, MGA_REG_TMR4, 0); - MGA_OUT32 (mmio, MGA_REG_TMR5, 0); - MGA_OUT32 (mmio, MGA_REG_TMR6, 0); - MGA_OUT32 (mmio, MGA_REG_TMR7, 0); - MGA_OUT32 (mmio, MGA_REG_TMR8, 0x10000); - - /* Initialize colors to 0, used in the src = A8 case */ - mgaWaitAvail(9); - MGA_OUT32 (mmio, MGA_REG_DR4, 0); - MGA_OUT32 (mmio, MGA_REG_DR6, 0); - MGA_OUT32 (mmio, MGA_REG_DR7, 0); - MGA_OUT32 (mmio, MGA_REG_DR8, 0); - MGA_OUT32 (mmio, MGA_REG_DR10, 0); - MGA_OUT32 (mmio, MGA_REG_DR11, 0); - MGA_OUT32 (mmio, MGA_REG_DR12, 0); - MGA_OUT32 (mmio, MGA_REG_DR14, 0); - MGA_OUT32 (mmio, MGA_REG_DR15, 0); + mgaSetup (pSrc->drawable.pScreen, pDst->drawable.bitsPerPixel, 1); + /* Initialize fg color to 0, used in the src = A8 case */ + MGA_OUT32 (mmio, MGA_REG_FCOL, 0xff000000); + /* Destination flags */ mgaWaitAvail (2); MGA_OUT32 (mmio, MGA_REG_DSTORG, ((int)pDst->devPrivate.ptr - mem_base)); MGA_OUT32 (mmio, MGA_REG_PITCH, pDst->devKind / (pDst->drawable.bitsPerPixel >> 3)); - + + /* Source(s) flags */ if (!PrepareSourceTexture (0, pSrcPicture, pSrc)) return FALSE; - if (pMask != NULL) - if (!PrepareSourceTexture (1, pMaskPicture, pMask)) return FALSE; + if (pMask != NULL) { + if (!PrepareSourceTexture (1, pMaskPicture, pMask)) return FALSE; + } + + /* Prepare multi-texture registers */ + ds0=ds1=0; - /* MultiTexture modulation */ - mgaWaitAvail (2); if (pSrcPicture->format == PICT_a8) { /* C = 0 A = As */ - MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE0, - C_ARG2_DIFFUSE | COLOR_ARG2 | - A_ARG1_CUR | ALPHA_ARG1); - } else { - /* C = Cs A = As */ - MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE0, - C_ARG1_CUR | COLOR_ARG1 | - A_ARG1_CUR | ALPHA_ARG1); - } - if (pMask != NULL) { - if (PICT_FORMAT_A (pSrcPicture->format) == 0) { - MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE1, - C_ARG1_CUR | C_ARG2_PREV | COLOR_MUL | - A_ARG1_CUR | A_ARG2_IGN | ALPHA_ARG1 | - MGA_TDS_COLOR_ARG1_REPLICATEALPHA); - } else { - MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE1, - C_ARG1_CUR | C_ARG2_PREV | COLOR_MUL | - A_ARG1_CUR | A_ARG2_PREV | ALPHA_MUL | - MGA_TDS_COLOR_ARG1_REPLICATEALPHA); + /* MGA HW: A8 format makes RGB white. We use FCOL for the black + * If FCOL was not 0, it would have been be premultiplied (RENDER) + * color component would have been: + * C_ARG1_ALPHA | C_ARG2_FCOL | COLOR_MUL + */ + ds0=C_ARG2_FCOL | COLOR_ARG2 | + A_ARG1_CUR | ALPHA_ARG1; + /* MGA HW: TMU1 must be enabled when DUALSTAGE0 contains something */ + if (pMask == NULL) { + if (!PrepareSourceTexture (1, pSrcPicture, pSrc)) return FALSE; + ds1=C_ARG2_PREV | COLOR_ARG2 | + A_ARG2_PREV | ALPHA_ARG2; } } else { - MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE1, 0); + /* C = Cs A = As */ + ds0=C_ARG1_CUR | COLOR_ARG1 | + A_ARG1_CUR | ALPHA_ARG1; } - + + if (pMask != NULL) { + /* As or Am might be NULL. in this case we don't multiply because, + * the alpha component holds garbage. + */ + int color,alpha; + if (PICT_FORMAT_A (pMaskPicture->format) == 0) { + /* C = Cs */ + color = C_ARG2_PREV | COLOR_ARG2; + } else { + /* C = Am * Cs */ + color = C_ARG1_ALPHA | C_ARG2_PREV | COLOR_MUL; + } + + if (PICT_FORMAT_A (pMaskPicture->format) == 0) { + /* A = As */ + alpha = A_ARG2_PREV | ALPHA_ARG2; + } else if (PICT_FORMAT_A (pSrcPicture->format) == 0) { + /* A = Am */ + alpha = A_ARG1_CUR | ALPHA_ARG1; + } else { + /* A = Am * As */ + alpha = A_ARG1_CUR | A_ARG2_PREV | ALPHA_MUL; + } + + ds1 = color | alpha; + } + + /* MultiTexture modulation */ + mgaWaitAvail (2); + MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE0, ds0); + MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE1, ds1); + + cmd = MGA_OPCOD_TEXTURE_TRAP | MGA_ATYPE_RSTR | 0x000c0000 | MGA_DWGCTL_SHIFTZERO | MGA_DWGCTL_SGNZERO | MGA_DWGCTL_ARZERO | MGA_ATYPE_I; @@ -309,13 +419,20 @@ mgaPrepareComposite (int op, mgaWaitAvail (2); MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd); MGA_OUT32 (mmio, MGA_REG_ALPHACTRL, MGA_ALPHACHANNEL | blendcntl); - - currentSrc=pSrc; - currentMask=pMask; + + currentSrcPicture = pSrcPicture; + currentMaskPicture = pMaskPicture; + currentSrc = pSrc; + currentMask = pMask; + src_w2 = MGA_LOG2 (currentSrc->drawable.width); + src_h2 = MGA_LOG2 (currentSrc->drawable.height); + mask_w2 = MGA_LOG2 (currentMask->drawable.width); + mask_h2 = MGA_LOG2 (currentMask->drawable.height); return TRUE; } + void mgaComposite (int srcX, int srcY, @@ -326,9 +443,6 @@ mgaComposite (int srcX, int width, int height) { - int src_w2 = MGA_LOG2 (currentSrc->drawable.width); - int src_h2 = MGA_LOG2 (currentSrc->drawable.height); - /* Source positions can be outside source textures' boundaries. * We clamp the values here to avoid rendering glitches. */ @@ -336,31 +450,55 @@ mgaComposite (int srcX, srcY=srcY % currentSrc->drawable.height; maskX=maskX % currentMask->drawable.width; maskY=maskY % currentMask->drawable.height; - - mgaWaitAvail (4); - /* Start position in the texture */ - MGA_OUT32 (mmio, MGA_REG_TMR6, srcX<<(20-src_w2)); - MGA_OUT32 (mmio, MGA_REG_TMR7, srcY<<(20-src_h2)); - /* Increments (1 since we aren't doing stretch blit) */ - MGA_OUT32 (mmio, MGA_REG_TMR0, 1<<(20-src_w2)); - MGA_OUT32 (mmio, MGA_REG_TMR3, 1<<(20-src_h2)); - + + if (currentSrcPicture->transform) { + setTMIncrementsRegs (currentSrcPicture->transform->matrix[0][0], + currentSrcPicture->transform->matrix[0][1], + currentSrcPicture->transform->matrix[0][2] + + (srcX << 16), + currentSrcPicture->transform->matrix[1][0], + currentSrcPicture->transform->matrix[1][1], + currentSrcPicture->transform->matrix[1][2] + + (srcY << 16), + currentSrcPicture->transform->matrix[2][0], + currentSrcPicture->transform->matrix[2][1], + currentSrcPicture->transform->matrix[2][2], + 20-src_w2, 20-src_h2); + } else { + setTMIncrementsRegs (1 << 16, 0, srcX << 16, + 0, 1 << 16, srcY << 16, + 0, 0, 0x10000, + 20-src_w2, 20-src_h2); + } + if (currentMask != NULL) { - int mask_w2 = MGA_LOG2 (currentMask->drawable.width); - int mask_h2 = MGA_LOG2 (currentMask->drawable.height); - - mgaWaitAvail (6); + mgaWaitAvail (1); MGA_OUT32 (mmio, MGA_REG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1); - - MGA_OUT32 (mmio, MGA_REG_TMR6, maskX<<(20-mask_w2)); - MGA_OUT32 (mmio, MGA_REG_TMR7, maskY<<(20-mask_h2)); - MGA_OUT32 (mmio, MGA_REG_TMR0, 1<<(20-mask_w2)); - MGA_OUT32 (mmio, MGA_REG_TMR3, 1<<(20-mask_h2)); - + if (currentMaskPicture->transform) { + setTMIncrementsRegs (currentMaskPicture->transform->matrix[0][0], + currentMaskPicture->transform->matrix[0][1], + currentMaskPicture->transform->matrix[0][2] + + (maskX << 16), + currentMaskPicture->transform->matrix[1][0], + currentMaskPicture->transform->matrix[1][1], + currentMaskPicture->transform->matrix[1][2] + + (maskY << 16), + currentMaskPicture->transform->matrix[2][0], + currentMaskPicture->transform->matrix[2][1], + currentMaskPicture->transform->matrix[2][2], + 20-mask_w2, 20-mask_h2); + } else { + setTMIncrementsRegs (1 << 16, 0, maskX << 16, + 0, 1 << 16, maskY << 16, + 0, 0, 0x10000, + 20-mask_w2, 20-mask_h2); + } + + mgaWaitAvail (1); MGA_OUT32 (mmio, MGA_REG_TEXCTL2, MGA_G400_TC2_MAGIC | MGA_TC2_DUALTEX); } - + /* Destination Bounding Box * (Boundary Right | Boundary Left, Y dest | Height) */ @@ -374,5 +512,4 @@ mgaComposite (int srcX, void mgaDoneComposite (void) { - } diff --git a/hw/kdrive/mga/mgadraw.c b/hw/kdrive/mga/mgadraw.c index 7c08949c2..c7b89da8b 100644 --- a/hw/kdrive/mga/mgadraw.c +++ b/hw/kdrive/mga/mgadraw.c @@ -65,14 +65,18 @@ mgaWaitAvail (int n) fifo_size -= n; } +#define MGA_OUT8(mmio, a, v) (*(VOL8 *) ((mmio) + (a)) = (v)) +#define MGA_REG_CRTC_INDEX (0x1fd4) + void mgaWaitIdle (void) { + + mgaWaitAvail (2); + MGA_OUT32(mmio, MGA_REG_CACHEFLUSH, 0); + /* MGA_OUT8 (mmio, MGA_REG_CRTC_INDEX, 0); */ while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000) ; - - mgaWaitAvail (1); - MGA_OUT32(mmio, MGA_REG_CACHEFLUSH, 0); } static void @@ -168,7 +172,6 @@ mgaSolid (int x1, int y1, int x2, int y2) static void mgaDoneSolid (void) { - mgaWaitIdle(); } #define BLIT_LEFT 1 @@ -179,7 +182,6 @@ mgaPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy, int alu, Pixel pm) { KdScreenPriv(pSrcPixmap->drawable.pScreen); - int cmd; cmd = MGA_OPCOD_BITBLT | MGA_DWGCTL_BFCOL | MGA_DWGCTL_SHIFTZERO | mgaRop[alu]; @@ -214,7 +216,6 @@ static void mgaCopy (int srcX, int srcY, int dstX, int dstY, int w, int h) { int start, end; - if (dir & BLIT_UP) { srcY += h - 1; @@ -239,13 +240,12 @@ mgaCopy (int srcX, int srcY, int dstX, int dstY, int w, int h) static void mgaDoneCopy (void) { - mgaWaitIdle(); } #if 0 static Bool mgaUploadToScreen(PixmapPtr pDst, char *src, int src_pitch) { - /* fprintf(stderr,"Upload to Screen %p [%d]\n",src,src_pitch); */ + /*fprintf(stderr,"Upload to Screen %p [%d]\n",src,src_pitch);*/ return TRUE; } #endif @@ -272,14 +272,15 @@ mgaDrawInit (ScreenPtr pScreen) */ mgas->kaa.pitchAlign = 128; mgas->kaa.flags = KAA_OFFSCREEN_PIXMAPS; - + if (card->attr.deviceID == MGA_G4XX_DEVICE_ID) { mgas->kaa.CheckComposite = mgaCheckComposite; mgas->kaa.PrepareComposite = mgaPrepareComposite; mgas->kaa.Composite = mgaComposite; mgas->kaa.DoneComposite = mgaDoneComposite; } - /*mgaKaa.UploadToScreen=mgaUploadToScreen;*/ + + /*mgas->kaa.UploadToScreen=mgaUploadToScreen;*/ if (!kaaDrawInit (pScreen, &mgas->kaa)) return FALSE;