Added hardware support for transformation matrix (zoom, rotation, etc...).

Fixed the composition function for RGB and A8 format. Avoid syncing
    hardware after HW fills or copies.
This commit is contained in:
Damien Ciabrini 2005-07-06 15:34:22 +00:00
parent 4073f24c90
commit 4047191124
2 changed files with 243 additions and 105 deletions

View File

@ -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)
{
}

View File

@ -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;