summaryrefslogtreecommitdiff
path: root/hw/kdrive
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-06-09 21:59:26 +0000
committerEric Anholt <anholt@freebsd.org>2005-06-09 21:59:26 +0000
commite11e60b361d63ae02918dd6b43038a5c92b73a49 (patch)
treeb3d6a778d4647b348960af0dc49dc8ea93fc7720 /hw/kdrive
parent9f81ce945680515e6db7da6c87458bee7c0f053d (diff)
Greatly improve the correctness and performance of the MGA render
implementation. Includes cache flushing to prevent bad first reads of the framebuffer, fixing blending of many formats, falling back on many unsupported operations, and falling back early to prevent migration. Passes all of rendercheck except some of the blend (!) tests.
Diffstat (limited to 'hw/kdrive')
-rw-r--r--hw/kdrive/mga/g400_common.h14
-rw-r--r--hw/kdrive/mga/g400_composite.c270
-rw-r--r--hw/kdrive/mga/mga.h1
-rw-r--r--hw/kdrive/mga/mgadraw.c10
4 files changed, 183 insertions, 112 deletions
diff --git a/hw/kdrive/mga/g400_common.h b/hw/kdrive/mga/g400_common.h
index a62f8dae8..c4093d908 100644
--- a/hw/kdrive/mga/g400_common.h
+++ b/hw/kdrive/mga/g400_common.h
@@ -51,6 +51,7 @@
# define MGA_SRC_DST_ALPHA (0x00000006)
# define MGA_SRC_ONE_MINUS_DST_ALPHA (0x00000007)
# define MGA_SRC_SRC_ALPHA_SATURATE (0x00000008)
+# define MGA_SRC_BLEND_MASK (0x0000000f)
# define MGA_DST_ZERO (0x00000000)
# define MGA_DST_ONE (0x00000010)
@@ -60,6 +61,7 @@
# define MGA_DST_ONE_MINUS_SRC_ALPHA (0x00000050)
# define MGA_DST_DST_ALPHA (0x00000060)
# define MGA_DST_ONE_MINUS_DST_ALPHA (0x00000070)
+# define MGA_DST_BLEND_MASK (0x00000070)
# define MGA_ALPHACHANNEL (0x00000100)
# define MGA_VIDEOALPHA (0x00000200)
@@ -93,7 +95,7 @@
# define MGA_TW8AL (0x00000008)
# define MGA_TW422 (0x0000000A)
# define MGA_TW422UYVY (0x0000000B)
-# define MGA_PITCHEXT (0x00000100)
+# define MGA_PITCHLIN (0x00000100)
# define MGA_NOPERSPECTIVE (0x00200000)
# define MGA_TAKEY (0x02000000)
# define MGA_TAMASK (0x04000000)
@@ -168,14 +170,8 @@
/* Composition Prototypes. MMIO Access */
Bool
-mgaPrepareBlend(int op, PicturePtr pSrcPicture, PicturePtr pDstPicture,
- PixmapPtr pSrc, PixmapPtr pDst);
-
-void
-mgaBlend(int srcX, int srcY, int dstX, int dstY, int width, int height);
-
-void
-mgaDoneBlend(void);
+mgaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture);
Bool
mgaPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
diff --git a/hw/kdrive/mga/g400_composite.c b/hw/kdrive/mga/g400_composite.c
index 11e550487..1992e024a 100644
--- a/hw/kdrive/mga/g400_composite.c
+++ b/hw/kdrive/mga/g400_composite.c
@@ -34,37 +34,56 @@
static PixmapPtr currentSrc;
static PixmapPtr currentMask;
-static CARD32 mgaBlendOP[14] = {
- /* Clear */
- MGA_SRC_ZERO | MGA_DST_ZERO,
- /* Src */
- MGA_SRC_ONE | MGA_DST_ZERO,
- /* Dst */
- MGA_SRC_ZERO | MGA_DST_ONE,
- /* Over */
- MGA_SRC_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA,
- /* OverReverse */
- MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE,
- /* In */
- MGA_SRC_DST_ALPHA | MGA_DST_ZERO,
- /* InReverse */
- MGA_SRC_ZERO | MGA_DST_SRC_ALPHA,
- /* Out */
- MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ZERO,
- /* OutReverse */
- MGA_SRC_ZERO | MGA_DST_ONE_MINUS_SRC_ALPHA,
- /* Atop */
- MGA_SRC_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA,
- /* AtopReverse */
- MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_SRC_ALPHA,
- /* Xor */
- MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA,
- /* Add */
- MGA_SRC_ONE | MGA_DST_ONE,
- /* Saturate */
- MGA_SRC_SRC_ALPHA_SATURATE | MGA_DST_ONE
+struct blendinfo {
+ Bool dst_alpha;
+ Bool src_alpha;
+ CARD32 blend_cntl;
};
+static struct blendinfo mgaBlendOP[] = {
+ /* Clear */
+ {0, 0, MGA_SRC_ZERO | MGA_DST_ZERO},
+ /* Src */
+ {0, 0, MGA_SRC_ONE | MGA_DST_ZERO},
+ /* Dst */
+ {0, 0, MGA_SRC_ZERO | MGA_DST_ONE},
+ /* Over */
+ {0, 1, MGA_SRC_ONE | MGA_DST_ONE_MINUS_SRC_ALPHA},
+ /* OverReverse */
+ {1, 0, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE},
+ /* In */
+ {1, 0, MGA_SRC_DST_ALPHA | MGA_DST_ZERO},
+ /* InReverse */
+ {0, 1, MGA_SRC_ZERO | MGA_DST_SRC_ALPHA},
+ /* Out */
+ {1, 0, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ZERO},
+ /* OutReverse */
+ {0, 1, MGA_SRC_ZERO | MGA_DST_ONE_MINUS_SRC_ALPHA},
+ /* Atop */
+ {1, 1, MGA_SRC_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA},
+ /* AtopReverse */
+ {1, 1, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_SRC_ALPHA},
+ /* Xor */
+ {1, 1, MGA_SRC_ONE_MINUS_DST_ALPHA | MGA_DST_ONE_MINUS_SRC_ALPHA},
+ /* Add */
+ {0, 0, MGA_SRC_ONE | MGA_DST_ONE},
+};
+
+struct formatinfo {
+ int fmt;
+ CARD32 card_fmt;
+};
+
+static struct formatinfo texformats[] = {
+ {PICT_a8r8g8b8, MGA_TW32},
+ {PICT_x8r8g8b8, MGA_TW32},
+ {PICT_r5g6b5, MGA_TW16},
+ {PICT_a1r5g5b5, MGA_TW15},
+ {PICT_x1r5g5b5, MGA_TW15},
+ {PICT_a4r4g4b4, MGA_TW12},
+ {PICT_x4r4g4b4, MGA_TW12},
+ {PICT_a8, MGA_TW8A},
+};
static int MGA_LOG2( int val )
{
@@ -76,36 +95,31 @@ static int MGA_LOG2( int val )
return ((1 << (ret-1)) == val) ? (ret-1) : ret;
}
-
-Bool
-mgaPrepareBlend (int op,
- PicturePtr pSrcPicture,
- PicturePtr pDstPicture,
- PixmapPtr pSrc,
- PixmapPtr pDst)
-{
- return mgaPrepareComposite (op, pSrcPicture, NULL, pDstPicture,
- pSrc, NULL, pDst);
-}
-
-void
-mgaBlend (int srcX,
- int srcY,
- int dstX,
- int dstY,
- int width,
- int height)
+static Bool
+mgaCheckSourceTexture (int tmu,
+ PicturePtr pPict)
{
- mgaComposite (srcX, srcY, 0, 0, dstX, dstY, width, height);
-}
+ int w = pPict->pDrawable->width;
+ int h = pPict->pDrawable->height;
+ int i;
+ CARD32 texctl = 0;
-void
-mgaDoneBlend (void)
-{
- mgaDoneComposite ();
-}
+ if ((w > 2047) || (h > 2047))
+ MGA_FALLBACK(("Picture too large for composition (%dx%d)\n", w, h));
+ for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) {
+ if (texformats[i].fmt == pPict->format) {
+ texctl = texformats[i].card_fmt;
+ break;
+ }
+ }
+ if (texctl == 0) {
+ MGA_FALLBACK(("Picture is in unsupported format 0x%x\n"
+ pPict->format));
+ }
+ return TRUE;
+}
static Bool
PrepareSourceTexture (int tmu,
@@ -115,39 +129,31 @@ PrepareSourceTexture (int tmu,
KdScreenPriv (pSrc->drawable.pScreen);
int mem_base=(int)pScreenPriv->screen->memory_base;
int pitch = pSrc->devKind / (pSrc->drawable.bitsPerPixel >> 3);
+ int i;
int w = pSrc->drawable.width;
int h = pSrc->drawable.height;
int w_log2 = MGA_LOG2(w);
int h_log2 = MGA_LOG2(h);
-
- int texctl=MGA_PITCHEXT | ((pitch&0x7ff)<<9) |
- MGA_TAKEY | MGA_CLAMPUV | MGA_NOPERSPECTIVE;
- int texctl2=MGA_G400_TC2_MAGIC;
-
- if ((w > 2047) || (h > 2047))
- MGA_FALLBACK(("Picture too large for composition (%dx%d)\n", w, h));
- switch (pSrcPicture->format) {
- case PICT_a8r8g8b8:
- case PICT_x8r8g8b8:
- case PICT_a8b8g8r8:
- case PICT_x8b8g8r8:
- texctl |= MGA_TW32;
- break;
- case PICT_r5g6b5:
- case PICT_b5g6r5:
- texctl |= MGA_TW16;
- break;
- case PICT_a8:
- texctl |= MGA_TW8A;
- break;
- default:
- MGA_FALLBACK(("unsupported Picture format for composition (%x)\n",
- pSrcPicture->format));
+ int texctl = MGA_PITCHLIN | ((pitch & (2048 - 1)) << 9) |
+ MGA_CLAMPUV | MGA_NOPERSPECTIVE;
+ int texctl2=MGA_G400_TC2_MAGIC;
+
+ for (i = 0; i < sizeof(texformats) / sizeof(texformats[0]); i++) {
+ if (texformats[i].fmt == pSrcPicture->format) {
+ texctl |= texformats[i].card_fmt;
+ break;
+ }
}
-
- if (tmu == 1) texctl2 |= MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1;
+ if (PICT_FORMAT_A(pSrcPicture->format) != 0) {
+ texctl |= MGA_TAKEY;
+ } else {
+ texctl |= MGA_TAMASK | MGA_TAKEY;
+ }
+
+ if (tmu == 1)
+ texctl2 |= MGA_TC2_DUALTEX | MGA_TC2_SELECT_TMU1;
mgaWaitAvail (6);
MGA_OUT32 (mmio, MGA_REG_TEXCTL2, texctl2);
@@ -168,6 +174,50 @@ PrepareSourceTexture (int tmu,
}
Bool
+mgaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ if (op >= sizeof(mgaBlendOP) / sizeof(mgaBlendOP[0]))
+ 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)
+ MGA_FALLBACK(("Component alpha unsupported"));
+
+ switch (pDstPicture->format) {
+ case PICT_a8:
+ MGA_FALLBACK(("render to A8 unsupported"));
+ }
+
+ return TRUE;
+}
+
+#define C_ARG1_CUR 0x0
+#define C_ARG2_DIFFUSE MGA_TDS_COLOR_ARG2_DIFFUSE
+#define C_ARG2_PREV MGA_TDS_COLOR_ARG2_PREVSTAGE
+#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_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,
PicturePtr pMaskPicture,
@@ -178,17 +228,7 @@ mgaPrepareComposite (int op,
{
KdScreenPriv (pSrc->drawable.pScreen);
int mem_base=(int)pScreenPriv->screen->memory_base;
- int cmd;
-
- /* sometimes mgaPrepareComposite is given the same pointer for Src
- * and Mask. PSrcPicture is an unsupported format (x8b8g8r8) whereas
- * pMaskPicture is supported (a8r8g8b8). We Choose to render a
- * simple blend and using pMaskPicture as the Source.
- */
- if (pMask == pSrc) {
- pMask=NULL;
- pMaskPicture=NULL;
- }
+ int cmd, blendcntl;
mgaWaitIdle();
/* Init MGA (clipping) */
@@ -202,6 +242,18 @@ mgaPrepareComposite (int op,
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);
+
/* Destination flags */
mgaWaitAvail (2);
MGA_OUT32 (mmio, MGA_REG_DSTORG, ((int)pDst->devPrivate.ptr - mem_base));
@@ -214,17 +266,29 @@ mgaPrepareComposite (int op,
if (!PrepareSourceTexture (1, pMaskPicture, pMask)) return FALSE;
/* MultiTexture modulation */
- mgaWaitAvail (2);
- MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE0, MGA_TDS_COLOR_SEL_ARG1);
+ 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,
- MGA_TDS_COLOR_ARG2_PREVSTAGE | MGA_TDS_COLOR_SEL_ARG2 |
- MGA_TDS_ALPHA_SEL_ARG1);
+ 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,
- MGA_TDS_COLOR_ARG2_PREVSTAGE | MGA_TDS_COLOR_SEL_ARG2 |
- MGA_TDS_ALPHA_ARG2_PREVSTAGE | MGA_TDS_ALPHA_SEL_MUL);
+ C_ARG1_CUR | C_ARG2_PREV | COLOR_MUL |
+ A_ARG1_CUR | A_ARG2_PREV | ALPHA_MUL |
+ MGA_TDS_COLOR_ARG1_REPLICATEALPHA);
}
} else {
MGA_OUT32 (mmio, MGA_REG_TDUALSTAGE1, 0);
@@ -234,9 +298,17 @@ mgaPrepareComposite (int op,
MGA_DWGCTL_SHIFTZERO | MGA_DWGCTL_SGNZERO | MGA_DWGCTL_ARZERO |
MGA_ATYPE_I;
+ blendcntl = mgaBlendOP[op].blend_cntl;
+ if (PICT_FORMAT_A(pDstPicture->format) == 0 && mgaBlendOP[op].dst_alpha) {
+ if ((blendcntl & MGA_SRC_BLEND_MASK) == MGA_SRC_DST_ALPHA)
+ blendcntl = (blendcntl & ~MGA_SRC_BLEND_MASK) | MGA_SRC_ONE;
+ else if ((blendcntl & MGA_SRC_BLEND_MASK) == MGA_SRC_ONE_MINUS_DST_ALPHA)
+ blendcntl = (blendcntl & ~MGA_SRC_BLEND_MASK) | MGA_SRC_ZERO;
+ }
+
mgaWaitAvail (2);
MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
- MGA_OUT32 (mmio, MGA_REG_ALPHACTRL, MGA_ALPHACHANNEL | mgaBlendOP[op]);
+ MGA_OUT32 (mmio, MGA_REG_ALPHACTRL, MGA_ALPHACHANNEL | blendcntl);
currentSrc=pSrc;
currentMask=pMask;
diff --git a/hw/kdrive/mga/mga.h b/hw/kdrive/mga/mga.h
index 979702e57..2c6b809c1 100644
--- a/hw/kdrive/mga/mga.h
+++ b/hw/kdrive/mga/mga.h
@@ -56,6 +56,7 @@
#define MGA_REG_YBOT (0x1c9c)
#define MGA_REG_FIFOSTATUS (0x1e10)
#define MGA_REG_STATUS (0x1e14)
+#define MGA_REG_CACHEFLUSH (0x1fff)
#define MGA_REG_SRCORG (0x2cb4)
#define MGA_REG_DSTORG (0x2cb8)
diff --git a/hw/kdrive/mga/mgadraw.c b/hw/kdrive/mga/mgadraw.c
index 3f6d8b2a2..301c6bd40 100644
--- a/hw/kdrive/mga/mgadraw.c
+++ b/hw/kdrive/mga/mgadraw.c
@@ -68,7 +68,11 @@ mgaWaitAvail (int n)
void
mgaWaitIdle (void)
{
- while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000);
+ while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000)
+ ;
+
+ mgaWaitAvail (1);
+ MGA_OUT32(mmio, MGA_REG_CACHEFLUSH, 0);
}
static void
@@ -268,9 +272,7 @@ mgaDrawInit (ScreenPtr pScreen)
mgas->kaa.flags = KAA_OFFSCREEN_PIXMAPS;
if (card->attr.deviceID == MGA_G4XX_DEVICE_ID) {
- mgas->kaa.PrepareBlend = mgaPrepareBlend;
- mgas->kaa.Blend = mgaBlend;
- mgas->kaa.DoneBlend = mgaDoneBlend;
+ mgas->kaa.CheckComposite = mgaCheckComposite;
mgas->kaa.PrepareComposite = mgaPrepareComposite;
mgas->kaa.Composite = mgaComposite;
mgas->kaa.DoneComposite = mgaDoneComposite;