diff options
author | Keith Packard <keithp@keithp.com> | 2000-10-11 06:04:40 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2000-10-11 06:04:40 +0000 |
commit | f16d5d6817f15be35293ee995d073eb57fafe283 (patch) | |
tree | f68058e80514f8038dc2a98feff1148ec13564fd /hw/kdrive/trident | |
parent | d579bd5676ea570a8f2765cd2f6ba40074171593 (diff) |
Add composite operator support to trident
Diffstat (limited to 'hw/kdrive/trident')
-rw-r--r-- | hw/kdrive/trident/trident.c | 53 | ||||
-rw-r--r-- | hw/kdrive/trident/trident.h | 43 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentdraw.c | 279 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentdraw.h | 12 |
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 (®ion, + 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 (®ion); + pbox = REGION_RECTS (®ion); + + 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 (®ion, + 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 (®ion); + pbox = REGION_RECTS (®ion); + + 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) |