summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2000-10-11 06:04:40 +0000
committerKeith Packard <keithp@keithp.com>2000-10-11 06:04:40 +0000
commitf16d5d6817f15be35293ee995d073eb57fafe283 (patch)
treef68058e80514f8038dc2a98feff1148ec13564fd /hw
parentd579bd5676ea570a8f2765cd2f6ba40074171593 (diff)
Add composite operator support to trident
Diffstat (limited to 'hw')
-rw-r--r--hw/kdrive/trident/trident.c53
-rw-r--r--hw/kdrive/trident/trident.h43
-rw-r--r--hw/kdrive/trident/tridentdraw.c279
-rw-r--r--hw/kdrive/trident/tridentdraw.h12
4 files changed, 370 insertions, 17 deletions
diff --git a/hw/kdrive/trident/trident.c b/hw/kdrive/trident/trident.c
index 57b2b93c2..df4e6cde9 100644
--- a/hw/kdrive/trident/trident.c
+++ b/hw/kdrive/trident/trident.c
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.10 2000/09/24 13:51:22 alanh Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.c,v 1.12 2000/09/27 20:46:36 keithp Exp $ */
#include "trident.h"
#define extern
@@ -52,9 +52,15 @@ tridentCardInit (KdCardInfo *card)
}
iopl (3);
- tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE,
- TRIDENT_COP_SIZE);
- tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF);
+ tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE(card),
+ TRIDENT_COP_SIZE(card));
+ tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF(card));
+ tridentc->mmio = FALSE;
+#ifdef USE_PCI
+ tridentc->window = (CARD32 *) (tridentc->cop_base + 0x10000);
+#else
+ tridentc->window = 0;
+#endif
card->driver = tridentc;
return TRUE;
@@ -114,16 +120,32 @@ tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index)
{
CARD8 value;
- outb (index, port);
- value = inb (port+1);
+ if (tridentc->mmio)
+ {
+ tridentc->cop_base[port] = index;
+ value = tridentc->cop_base[port+1];
+ }
+ else
+ {
+ outb (index, port);
+ value = inb (port+1);
+ }
return value;
}
void
tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 value)
{
- outb (index, port);
- outb (value, port+1);
+ if (tridentc->mmio)
+ {
+ tridentc->cop_base[port] = index;
+ tridentc->cop_base[port+1] = value;
+ }
+ else
+ {
+ outb (index, port);
+ outb (value, port+1);
+ }
}
void
@@ -191,10 +213,22 @@ tridentSetMMIO (TridentCardInfo *tridentc)
}
/* enable screen */
tridentWriteIndex (tridentc, 0x3ce, 0x21, 0x80);
+#ifdef USE_PCI
+ /* enable burst r/w, enable memory mapped ports */
+ tridentWriteIndex (tridentc, 0x3d4, 0x39, 7);
+ tridentc->mmio = TRUE;
+ /* reset GE, enable GE, set GE to pci 1 */
+ tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x90);
+#else
/* enable burst r/w, disable memory mapped ports */
tridentWriteIndex (tridentc, 0x3d4, 0x39, 0x6);
/* reset GE, enable GE, set GE to 0xbff00 */
tridentWriteIndex (tridentc, 0x3d4, 0x36, 0x92);
+#endif
+#ifdef TRI_DEBUG
+ fprintf (stderr, "0x36: 0x%02x\n",
+ tridentReadIndex (tridentc, 0x3d4, 0x36));
+#endif
if (tridentc->cop->status != 0xffffffff)
break;
}
@@ -216,6 +250,7 @@ tridentResetMMIO (TridentCardInfo *tridentc)
tridentPause ();
tridentWriteIndex (tridentc, 0x3d4, 0x62, tridentc->save.reg_3d4_62);
tridentWriteIndex (tridentc, 0x3d4, 0x39, tridentc->save.reg_3d4_39);
+ tridentc->mmio = FALSE;
tridentWriteIndex (tridentc, 0x3d4, 0x36, tridentc->save.reg_3d4_36);
tridentWriteIndex (tridentc, 0x3c4, 0x0e, tridentc->save.reg_3c4_0e);
tridentPause ();
@@ -299,7 +334,7 @@ tridentCardFini (KdCardInfo *card)
TridentCardInfo *tridentc = card->driver;
if (tridentc->cop_base)
- KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE);
+ KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE(card));
#ifdef VESA
vesaCardFini (card);
#else
diff --git a/hw/kdrive/trident/trident.h b/hw/kdrive/trident/trident.h
index 0855ff873..15b64a01f 100644
--- a/hw/kdrive/trident/trident.h
+++ b/hw/kdrive/trident/trident.h
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.h,v 1.5 2000/09/03 05:11:20 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/trident.h,v 1.6 2000/09/15 07:25:12 keithp Exp $ */
#ifndef _TRIDENT_H_
#define _TRIDENT_H_
@@ -34,9 +34,17 @@
/*
* offset from ioport beginning
*/
-#define TRIDENT_COP_BASE 0xbf000
-#define TRIDENT_COP_OFF 0x00f00
-#define TRIDENT_COP_SIZE (0x2000)
+#define USE_PCI
+
+#ifdef USE_PCI
+#define TRIDENT_COP_BASE(c) (c->attr.address[1])
+#define TRIDENT_COP_OFF(c) 0x2100
+#define TRIDENT_COP_SIZE(c) 0x20000
+#else
+#define TRIDENT_COP_BASE(c) 0xbf000
+#define TRIDENT_COP_OFF(c) 0x00f00
+#define TRIDENT_COP_SIZE(c) (0x2000)
+#endif
typedef volatile CARD8 VOL8;
typedef volatile CARD16 VOL16;
@@ -72,6 +80,31 @@ typedef struct _cop {
#define COP_DEPTH_DITHER_DISABLE 0x00000008
+#define COP_ALPHA_SRC_BLEND_0 0x00000000
+#define COP_ALPHA_SRC_BLEND_1 0x00000001
+#define COP_ALPHA_SRC_BLEND_SRC_C 0x00000002
+#define COP_ALPHA_SRC_BLEND_1_SRC_C 0x00000003
+#define COP_ALPHA_SRC_BLEND_SRC_A 0x00000004
+#define COP_ALPHA_SRC_BLEND_1_SRC_A 0x00000005
+#define COP_ALPHA_SRC_BLEND_DST_A 0x00000006
+#define COP_ALPHA_SRC_BLEND_1_DST_A 0x00000007
+#define COP_ALPHA_SRC_BLEND_DST_C 0x00000008
+#define COP_ALPHA_SRC_BLEND_1_DST_C 0x00000009
+#define COP_ALPHA_SRC_BLEND_SAT 0x0000000A
+#define COP_ALPHA_SRC_BLEND_BG 0x0000000B
+
+#define COP_ALPHA_DST_BLEND_0 0x00000000
+#define COP_ALPHA_DST_BLEND_1 0x00000010
+#define COP_ALPHA_DST_BLEND_SRC_C 0x00000020
+#define COP_ALPHA_DST_BLEND_1_SRC_C 0x00000030
+#define COP_ALPHA_DST_BLEND_SRC_A 0x00000040
+#define COP_ALPHA_DST_BLEND_1_SRC_A 0x00000050
+#define COP_ALPHA_DST_BLEND_DST_A 0x00000060
+#define COP_ALPHA_DST_BLEND_1_DST_A 0x00000070
+#define COP_ALPHA_DST_BLEND_DST_C 0x00000080
+#define COP_ALPHA_DST_BLEND_1_DST_C 0x00000090
+#define COP_ALPHA_DST_BLEND_OTHER 0x000000A0
+
#define COP_ALPHA_RESULT_ALPHA 0x00100000
#define COP_ALPHA_DEST_ALPHA 0x00200000
#define COP_ALPHA_SOURCE_ALPHA 0x00400000
@@ -157,8 +190,10 @@ typedef struct _tridentCardInfo {
#endif
CARD8 *cop_base;
Cop *cop;
+ CARD32 *window;
CARD32 cop_depth;
CARD32 cop_stride;
+ Bool mmio;
TridentSave save;
} TridentCardInfo;
diff --git a/hw/kdrive/trident/tridentdraw.c b/hw/kdrive/trident/tridentdraw.c
index 195927fa3..900bfacfa 100644
--- a/hw/kdrive/trident/tridentdraw.c
+++ b/hw/kdrive/trident/tridentdraw.c
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/tridentdraw.c,v 1.2 1999/12/30 03:03:17 robin Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/trident/tridentdraw.c,v 1.5 2000/08/26 00:17:50 keithp Exp $ */
#include "trident.h"
#include "tridentdraw.h"
@@ -37,6 +37,7 @@
#include "fb.h"
#include "migc.h"
#include "miline.h"
+#include "picturestr.h"
CARD8 tridentRop[16] = {
/* GXclear */ 0x00, /* 0 */
@@ -151,6 +152,7 @@ tridentCopyNtoN (DrawablePtr pSrcDrawable,
cop->dst_end_xy = TRI_XY (pbox->x2 - 1,
pbox->y2 - 1);
}
+ _tridentWaitDone(cop);
cop->command = cmd;
pbox++;
}
@@ -685,6 +687,274 @@ tridentCreateGC (GCPtr pGC)
}
void
+tridentComposite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ SetupTrident (pDst->pDrawable->pScreen);
+ RegionRec region;
+ int n;
+ BoxPtr pbox;
+ CARD32 rgb;
+ CARD8 *msk, *mskLine;
+ FbBits *mskBits;
+ FbStride mskStride;
+ int mskBpp;
+ CARD32 *src, *srcLine;
+ FbBits *srcBits;
+ FbStride srcStride;
+ int srcBpp;
+ int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+ int x2;
+ int w, h, w_this, h_this, w_remain;
+ int win_remain;
+ CARD32 *window;
+ int mskExtra;
+
+ if (pMask &&
+ !pMask->repeat &&
+ pMask->format == PICT_a8 &&
+ op == PictOpOver &&
+ pSrc->repeat &&
+ pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ PICT_FORMAT_BPP(pSrc->format) == 32 &&
+ (PICT_FORMAT_A(pSrc->format) == 0 ||
+ ((rgb = (*((CARD32 *) ((PixmapPtr) (pSrc->pDrawable))->devPrivate.ptr))
+ & 0xff000000) == 0xff000000)) &&
+ pDst->pDrawable->bitsPerPixel == 32 &&
+ pDst->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ if (pMask)
+ {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ }
+
+ rgb = (*((CARD32 *) ((PixmapPtr) (pSrc->pDrawable))->devPrivate.ptr)
+ & 0xffffff);
+
+ if (!miComputeCompositeRegion (&region,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height))
+ return;
+
+ fbGetDrawable (pMask->pDrawable, mskBits, mskStride, mskBpp);
+ mskStride = mskStride * sizeof (FbBits) / sizeof (CARD8);
+
+ cop->multi = (COP_MULTI_ROP | 0xcc);
+
+ cop->multi = (COP_MULTI_ALPHA |
+ COP_ALPHA_BLEND_ENABLE |
+ COP_ALPHA_WRITE_ENABLE |
+ 0x7 << 16 |
+ COP_ALPHA_DST_BLEND_1_SRC_A |
+ COP_ALPHA_SRC_BLEND_SRC_A);
+
+ n = REGION_NUM_RECTS (&region);
+ pbox = REGION_RECTS (&region);
+
+ while (n--)
+ {
+ h = pbox->y2 - pbox->y1;
+ x2 = pbox->x2;
+ w = x2 - pbox->x1;
+ cop->multi = COP_MULTI_CLIP_TOP_LEFT | TRI_XY(0,0);
+ cop->clip_bottom_right = TRI_XY(x2-1, 0xfff);
+ if (w & 1)
+ {
+ x2++;
+ w++;
+ }
+
+ y_msk = pbox->y1 - yDst + yMask;
+ y_dst = pbox->y1;
+ x_msk = pbox->x1 - xDst + xMask;
+ x_dst = pbox->x1;
+
+ mskLine = (CARD8 *) mskBits + y_msk * mskStride + x_msk;
+
+ cop->dst_start_xy = TRI_XY(pbox->x1, pbox->y1);
+ cop->dst_end_xy = TRI_XY(x2-1,pbox->y2-1);
+
+ _tridentWaitDone(cop);
+
+ cop->command = (COP_OP_BLT | COP_SCL_OPAQUE | COP_CLIP | COP_OP_ROP);
+
+ win_remain = 0;
+ while (h--)
+ {
+ w_remain = w;
+ msk = mskLine;
+ mskLine += mskStride;
+ while (w_remain)
+ {
+ if (!win_remain)
+ {
+ window = tridentc->window;
+ win_remain = 0x1000 / 4;
+ }
+ w_this = w_remain;
+ if (w_this > win_remain)
+ w_this = win_remain;
+ win_remain -= w_this;
+ w_remain -= w_this;
+ while (w_this--)
+ *window++ = rgb | (*msk++ << 24);
+ }
+ }
+ pbox++;
+ }
+
+ cop->multi = TridentAlpha;
+ cop->clip_bottom_right = 0x0fff0fff;
+
+ KdMarkSync (pDst->pDrawable->pScreen);
+ }
+ else if (!pMask &&
+ op == PictOpOver &&
+ !pSrc->repeat &&
+ PICT_FORMAT_A(pSrc->format) == 8 &&
+ PICT_FORMAT_BPP(pSrc->format) == 32 &&
+ pDst->pDrawable->bitsPerPixel == 32 &&
+ pDst->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ if (pMask)
+ {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ }
+
+ if (!miComputeCompositeRegion (&region,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height))
+ return;
+
+ fbGetDrawable (pSrc->pDrawable, srcBits, srcStride, srcBpp);
+
+ cop->multi = (COP_MULTI_ROP | 0xcc);
+
+ cop->multi = (COP_MULTI_ALPHA |
+ COP_ALPHA_BLEND_ENABLE |
+ COP_ALPHA_WRITE_ENABLE |
+ 0x7 << 16 |
+ COP_ALPHA_DST_BLEND_1_SRC_A |
+ COP_ALPHA_SRC_BLEND_1);
+
+ n = REGION_NUM_RECTS (&region);
+ pbox = REGION_RECTS (&region);
+
+ while (n--)
+ {
+ h = pbox->y2 - pbox->y1;
+ x2 = pbox->x2;
+ w = x2 - pbox->x1;
+ cop->multi = COP_MULTI_CLIP_TOP_LEFT | TRI_XY(0,0);
+ cop->clip_bottom_right = TRI_XY(x2-1, 0xfff);
+ if (w & 1)
+ {
+ x2++;
+ w++;
+ }
+
+ y_src = pbox->y1 - yDst + ySrc;
+ y_dst = pbox->y1;
+ x_src = pbox->x1 - xDst + xSrc;
+ x_dst = pbox->x1;
+
+ srcLine = srcBits + y_src * srcStride + x_src;
+
+ cop->dst_start_xy = TRI_XY(pbox->x1, pbox->y1);
+ cop->dst_end_xy = TRI_XY(x2-1,pbox->y2-1);
+
+ _tridentWaitDone(cop);
+
+ cop->command = (COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_CLIP);
+
+ win_remain = 0;
+ while (h--)
+ {
+ w_remain = w;
+ src = srcLine;
+ srcLine += srcStride;
+ while (w_remain)
+ {
+ if (!win_remain)
+ {
+ window = tridentc->window;
+ win_remain = 0x1000 / 4;
+ }
+ w_this = w_remain;
+ if (w_this > win_remain)
+ w_this = win_remain;
+ win_remain -= w_this;
+ w_remain -= w_this;
+ while (w_this--)
+ *window++ = *src++;
+ }
+ }
+ pbox++;
+ }
+
+ cop->multi = TridentAlpha;
+ cop->multi = COP_MULTI_CLIP_TOP_LEFT;
+ cop->clip_bottom_right = 0x0fff0fff;
+
+ KdMarkSync (pDst->pDrawable->pScreen);
+ }
+ else
+ {
+ KdCheckComposite (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+ }
+}
+
+void
tridentCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
@@ -786,6 +1056,9 @@ tridentPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
Bool
tridentDrawInit (ScreenPtr pScreen)
{
+ SetupTrident(pScreen);
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
/*
* Hook up asynchronous drawing
*/
@@ -797,6 +1070,9 @@ tridentDrawInit (ScreenPtr pScreen)
pScreen->CopyWindow = tridentCopyWindow;
pScreen->PaintWindowBackground = tridentPaintWindow;
pScreen->PaintWindowBorder = tridentPaintWindow;
+
+ if (ps && tridentc->window)
+ ps->Composite = tridentComposite;
return TRUE;
}
@@ -811,6 +1087,7 @@ tridentDrawEnable (ScreenPtr pScreen)
CARD32 format;
CARD32 alpha;
int tries;
+ int nwrite;
stride = pScreenPriv->screen->fb[0].pixelStride;
switch (pScreenPriv->screen->fb[0].bitsPerPixel) {
diff --git a/hw/kdrive/trident/tridentdraw.h b/hw/kdrive/trident/tridentdraw.h
index b90d4fbcc..8a1817a39 100644
--- a/hw/kdrive/trident/tridentdraw.h
+++ b/hw/kdrive/trident/tridentdraw.h
@@ -49,15 +49,21 @@
#define _tridentRect(cop,x1,y1,x2,y2,cmd) { \
(cop)->dst_start_xy = TRI_XY (x1,y1); \
(cop)->dst_end_xy = TRI_XY(x2,y2); \
+ _tridentWaitDone(cop); \
(cop)->command = (cmd); \
}
#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \
COP_STATUS_DPE_BUSY | \
- COP_STATUS_MI_BUSY | \
- COP_STATUS_FIFO_BUSY)
+ COP_STATUS_MI_BUSY)
-#define _tridentWaitDone(cop) while ((cop)->status & COP_STATUS_BUSY)
+#define _tridentWaitDone(cop) { \
+ int __q__ = 500000; \
+ while (__q__-- && (cop)->status & COP_STATUS_BUSY) \
+ ; \
+ if (!__q__) \
+ (cop)->status = 0; \
+}
#define _tridentWaitIdleEmpty(cop) _tridentWaitDone(cop)