diff options
Diffstat (limited to 'hw/kdrive/trident')
-rw-r--r-- | hw/kdrive/trident/Imakefile | 15 | ||||
-rw-r--r-- | hw/kdrive/trident/trident.c | 279 | ||||
-rw-r--r-- | hw/kdrive/trident/trident.h | 205 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentcurs.c | 414 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentdraw.c | 859 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentdraw.h | 63 | ||||
-rw-r--r-- | hw/kdrive/trident/tridentstub.c | 54 |
7 files changed, 1889 insertions, 0 deletions
diff --git a/hw/kdrive/trident/Imakefile b/hw/kdrive/trident/Imakefile new file mode 100644 index 000000000..f2456a214 --- /dev/null +++ b/hw/kdrive/trident/Imakefile @@ -0,0 +1,15 @@ +XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $ +XCOMM $XFree86: xc/programs/Xserver/hw/nvfb/Imakefile,v 3.8 1996/12/23 06:30:19 dawes Exp $ +#include <Server.tmpl> + +SRCS = trident.c tridentdraw.c tridentcurs.c tridentstub.c + +OBJS = trident.o tridentdraw.o tridentcurs.o tridentstub.o + +INCLUDES = -I.. -I../fbdev -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I../../../fb -I../../../mi -I../../../include -I../../../os \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) + +NormalLibraryObjectRule() +NormalLibraryTarget(trident,$(OBJS)) +DependTarget() diff --git a/hw/kdrive/trident/trident.c b/hw/kdrive/trident/trident.c new file mode 100644 index 000000000..384800f78 --- /dev/null +++ b/hw/kdrive/trident/trident.c @@ -0,0 +1,279 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#include "trident.h" +#define extern +#include <asm/io.h> +#undef extern + +#undef TRI_DEBUG + +Bool +tridentCardInit (KdCardInfo *card) +{ + int k; + char *pixels; + TridentCardInfo *tridentc; + + tridentc = (TridentCardInfo *) xalloc (sizeof (TridentCardInfo)); + if (!tridentc) + return FALSE; + + if (!fbdevInitialize (card, &tridentc->fb)) + { + xfree (tridentc); + return FALSE; + } + + iopl (3); + tridentc->cop_base = (CARD8 *) KdMapDevice (TRIDENT_COP_BASE, + TRIDENT_COP_SIZE); + tridentc->cop = (Cop *) (tridentc->cop_base + TRIDENT_COP_OFF); + card->driver = tridentc; + + return TRUE; +} + +Bool +tridentScreenInit (KdScreenInfo *screen) +{ + TridentCardInfo *tridentc = screen->card->driver; + TridentScreenInfo *tridents; + int screen_size, memory; + + tridents = (TridentScreenInfo *) xalloc (sizeof (TridentScreenInfo)); + if (!tridents) + return FALSE; + memset (tridents, '\0', sizeof (TridentScreenInfo)); + if (!fbdevScreenInit (screen)) + { + xfree (tridents); + return FALSE; + } + if (!tridentc->cop) + screen->dumb = TRUE; + screen_size = screen->byteStride * screen->height; + memory = (2048 + 512) * 1024; + if (memory >= screen_size + 2048) + { + tridents->cursor_base = tridentc->fb.fb + memory - 2048; + } + else + tridents->cursor_base = 0; + screen->driver = tridents; + return TRUE; +} + +CARD8 +tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index) +{ + CARD8 value; + + 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); +} + +void +tridentPause () +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 200 * 1000; + select (1, 0, 0, 0, &tv); +} + +void +tridentPreserve (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + fbdevPreserve (card); + tridentc->save.reg_3c4_0e = tridentReadIndex (tridentc, 0x3c4, 0x0e); + tridentc->save.reg_3d4_36 = tridentReadIndex (tridentc, 0x3d4, 0x36); + tridentc->save.reg_3d4_39 = tridentReadIndex (tridentc, 0x3d4, 0x39); + tridentc->save.reg_3d4_62 = tridentReadIndex (tridentc, 0x3d4, 0x62); + tridentc->save.reg_3ce_21 = tridentReadIndex (tridentc, 0x3ce, 0x21); +#ifdef TRI_DEBUG + fprintf (stderr, "3c4 0e: %02x\n", tridentc->save.reg_3c4_0e); + fprintf (stderr, "3d4 36: %02x\n", tridentc->save.reg_3d4_36); + fprintf (stderr, "3d4 39: %02x\n", tridentc->save.reg_3d4_39); + fprintf (stderr, "3d4 62: %02x\n", tridentc->save.reg_3d4_62); + fprintf (stderr, "3ce 21: %02x\n", tridentc->save.reg_3ce_21); + fflush (stderr); +#endif + tridentPause (); +} + +void +tridentSetMMIO (TridentCardInfo *tridentc) +{ + int tries; + CARD8 v; + +#ifdef TRI_DEBUG + fprintf (stderr, "Set MMIO\n"); +#endif + /* enable config port writes */ + for (tries = 0; tries < 3; tries++) + { + /* enable direct read when GE busy, enable PCI retries */ + tridentWriteIndex (tridentc, 0x3d4, 0x62, + tridentc->save.reg_3d4_62 | 0x70); + /* make sure the chip is in new mode */ + tridentReadIndex (tridentc, 0x3c4, 0xb); + /* enable access to upper registers */ + tridentWriteIndex (tridentc, 0x3c4, 0xe, + tridentc->save.reg_3c4_0e | 0x80); + v = tridentReadIndex (tridentc, 0x3c4, 0xe); + if (!(v & 0x80)) + { + fprintf (stderr, "Trident GE not enabled 0x%x\n", v); + continue; + } + /* 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); + if (tridentc->cop->status != 0xffffffff) + break; + } +#ifdef TRI_DEBUG + fprintf (stderr, "COP status 0x%x\n", tridentc->cop->status); +#endif + if (tridentc->cop->status == 0xffffffff) + FatalError ("Trident COP not visible\n"); +} + +void +tridentResetMMIO (TridentCardInfo *tridentc) +{ +#ifdef TRI_DEBUG + fprintf (stderr, "Reset MMIO\n"); +#endif + tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentc->save.reg_3ce_21); + tridentWriteIndex (tridentc, 0x3d4, 0x62, tridentc->save.reg_3d4_62); + tridentWriteIndex (tridentc, 0x3d4, 0x39, tridentc->save.reg_3d4_39); + tridentWriteIndex (tridentc, 0x3d4, 0x36, tridentc->save.reg_3d4_36); + tridentWriteIndex (tridentc, 0x3c4, 0x0e, tridentc->save.reg_3c4_0e); + tridentPause (); +} + +void +tridentEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + TridentCardInfo *tridentc = pScreenPriv->card->driver; + + fbdevEnable (pScreen); + tridentSetMMIO (tridentc); +} + +void +tridentDisable (ScreenPtr pScreen) +{ + fbdevDisable (pScreen); +} + +const CARD8 tridentDPMSModes[4] = { + 0x80, /* KD_DPMS_NORMAL */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ + 0x8c, /* KD_DPMS_STANDBY */ +/* 0xb0, /* KD_DPMS_SUSPEND */ +/* 0xbc, /* KD_DPMS_POWERDOWN */ +}; + +Bool +tridentDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + TridentCardInfo *tridentc = pScreenPriv->card->driver; + + tridentWriteIndex (tridentc, 0x3ce, 0x21, tridentDPMSModes[mode]); + return TRUE; +} + +void +tridentRestore (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + tridentResetMMIO (tridentc); + fbdevRestore (card); +} + +void +tridentScreenFini (KdScreenInfo *screen) +{ + TridentScreenInfo *tridents = (TridentScreenInfo *) screen->driver; + + xfree (tridents); + screen->driver = 0; +} + +void +tridentCardFini (KdCardInfo *card) +{ + TridentCardInfo *tridentc = card->driver; + + if (tridentc->cop_base) + KdUnmapDevice ((void *) tridentc->cop_base, TRIDENT_COP_SIZE); + fbdevCardFini (card); +} + +KdCardFuncs tridentFuncs = { + tridentCardInit, /* cardinit */ + tridentScreenInit, /* scrinit */ + tridentPreserve, /* preserve */ + tridentEnable, /* enable */ + tridentDPMS, /* dpms */ + tridentDisable, /* disable */ + tridentRestore, /* restore */ + tridentScreenFini, /* scrfini */ + tridentCardFini, /* cardfini */ + + tridentCursorInit, /* initCursor */ + tridentCursorEnable, /* enableCursor */ + tridentCursorDisable, /* disableCursor */ + tridentCursorFini, /* finiCursor */ + tridentRecolorCursor, /* recolorCursor */ + + tridentDrawInit, /* initAccel */ + tridentDrawEnable, /* enableAccel */ + tridentDrawDisable, /* disableAccel */ + tridentDrawFini, /* finiAccel */ + + fbdevGetColors, /* getColors */ + fbdevPutColors, /* putColors */ +}; diff --git a/hw/kdrive/trident/trident.h b/hw/kdrive/trident/trident.h new file mode 100644 index 000000000..f726e0701 --- /dev/null +++ b/hw/kdrive/trident/trident.h @@ -0,0 +1,205 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#ifndef _TRIDENT_H_ +#define _TRIDENT_H_ +#include <fbdev.h> + +/* + * offset from ioport beginning + */ +#define TRIDENT_COP_BASE 0xbf000 +#define TRIDENT_COP_OFF 0x00f00 +#define TRIDENT_COP_SIZE (0x2000) + +typedef volatile CARD8 VOL8; +typedef volatile CARD16 VOL16; +typedef volatile CARD32 VOL32; + +typedef struct _cop { + VOL32 src_start_xy; /* 0x00 */ + VOL32 src_end_xy; /* 0x04 */ + VOL32 dst_start_xy; /* 0x08 */ + VOL32 dst_end_xy; /* 0x0c */ + VOL32 alpha; /* 0x10 */ + CARD8 pad14[0xc]; /* 0x14 */ + VOL32 multi; /* 0x20 */ + +#define COP_MULTI_CLIP_TOP_LEFT 0x10000000 +#define COP_MULTI_DEPTH 0x40000000 +#define COP_MULTI_COLOR_KEY 0x70000000 +#define COP_MULTI_STYLE 0x50000000 +#define COP_MULTI_PATTERN 0x80000000 +#define COP_MULTI_ROP 0x90000000 +#define COP_MULTI_STRIDE 0x60000000 +#define COP_MULTI_Z 0xa0000000 +#define COP_MULTI_ALPHA 0xb0000000 +#define COP_MULTI_TEXTURE 0xd0000000 +#define COP_MULTI_TEXTURE_BOUND 0xe0000000 +#define COP_MULTI_TEXTURE_ADVANCED 0x20000000 +#define COP_MULTI_MASK 0xf0000000 + + +#define COP_DEPTH_8 0x00000000 +#define COP_DEPTH_16 0x00000001 +#define COP_DEPTH_24_32 0x00000002 +#define COP_DEPTH_15 0x00000005 +#define COP_DEPTH_DITHER_DISABLE 0x00000008 + + VOL32 command; /* 0x24 */ +#define COP_OP_NULL 0x00000000 +#define COP_OP_LINE 0x20000000 +#define COP_OP_BLT 0x80000000 +#define COP_OP_TEXT 0x90000000 +#define COP_OP_POLY 0xb0000000 +#define COP_OP_POLY2 0xe0000000 +#define COP_SCL_EXPAND 0x00800000 +#define COP_SCL_OPAQUE 0x00400000 +#define COP_SCL_REVERSE 0x00200000 +#define COP_SCL_MONO_OFF 0x001c0000 +#define COP_LIT_TEXTURE 0x00004000 +#define COP_BILINEAR 0x00002000 +#define COP_OP_ZBUF 0x00000800 +#define COP_OP_ROP 0x00000400 +#define COP_OP_FG 0x00000200 +#define COP_OP_FB 0x00000080 +#define COP_X_REVERSE 0x00000004 +#define COP_CLIP 0x00000001 + VOL32 texture_format; /* 0x28 */ + CARD8 pad2c[0x4]; /* 0x2c */ + + VOL32 clip_bottom_right; /* 0x30 */ + VOL32 dataIII; /* 0x34 */ + VOL32 dataIV; /* 0x38 */ + CARD8 pad3c[0x8]; /* 0x3c */ + + VOL32 fg; /* 0x44 */ + VOL32 bg; /* 0x48 */ + CARD8 pad4c[0x4]; /* 0x4c */ + + VOL32 pattern_fg; /* 0x50 */ + VOL32 pattern_bg; /* 0x54 */ + CARD8 pad58[0xc]; /* 0x58 */ + + VOL32 status; /* 0x64 */ +#define COP_STATUS_BE_BUSY 0x80000000 +#define COP_STATUS_DPE_BUSY 0x20000000 +#define COP_STATUS_MI_BUSY 0x10000000 +#define COP_STATUS_FIFO_BUSY 0x08000000 +#define COP_STATUS_WB_BUSY 0x00800000 +#define COP_STATUS_Z_FAILED 0x00400000 +#define COP_STATUS_EFFECTIVE 0x00200000 +#define COP_STATUS_LEFT_VIEW 0x00080000 + + CARD8 pad68[0x4]; /* 0x68 */ + + VOL32 src_offset; /* 0x6c */ + VOL32 z_offset; /* 0x70 */ + CARD8 pad74[0x4]; /* 0x74 */ + + VOL32 display_offset; /* 0x78 */ + VOL32 dst_offset; /* 0x7c */ + CARD8 pad80[0x34]; /* 0x80 */ + + VOL32 semaphore; /* 0xb4 */ +} Cop; + +#define TRI_XY(x,y) ((y) << 16 | (x)) + +typedef struct _tridentSave { + CARD8 reg_3c4_0e; /* config port value */ + CARD8 reg_3d4_36; + CARD8 reg_3d4_39; + CARD8 reg_3d4_62; /* GE setup */ + CARD8 reg_3ce_21; /* DPMS */ +} TridentSave; + +typedef struct _tridentCardInfo { + FbdevPriv fb; + CARD8 *cop_base; + Cop *cop; + CARD32 cop_depth; + CARD32 cop_stride; + TridentSave save; +} TridentCardInfo; + +#define getTridentCardInfo(kd) ((TridentCardInfo *) ((kd)->card->driver)) +#define tridentCardInfo(kd) TridentCardInfo *tridentc = getTridentCardInfo(kd) + +typedef struct _tridentCursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; +} TridentCursor; + +#define TRIDENT_CURSOR_WIDTH 64 +#define TRIDENT_CURSOR_HEIGHT 64 + +typedef struct _tridentScreenInfo { + CARD8 *cursor_base; + TridentCursor cursor; +} TridentScreenInfo; + +#define getTridentScreenInfo(kd) ((TridentScreenInfo *) ((kd)->screen->driver)) +#define tridentScreenInfo(kd) TridentScreenInfo *tridents = getTridentScreenInfo(kd) + +Bool +tridentDrawInit (ScreenPtr pScreen); + +void +tridentDrawEnable (ScreenPtr pScreen); + +void +tridentDrawDisable (ScreenPtr pScreen); + +void +tridentDrawFini (ScreenPtr pScreen); + +CARD8 +tridentReadIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index); + +void +tridentWriteIndex (TridentCardInfo *tridentc, CARD16 port, CARD8 index, CARD8 value); + +Bool +tridentCursorInit (ScreenPtr pScreen); + +void +tridentCursorEnable (ScreenPtr pScreen); + +void +tridentCursorDisable (ScreenPtr pScreen); + +void +tridentCursorFini (ScreenPtr pScreen); + +void +tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef); + +extern KdCardFuncs tridentFuncs; + +#endif /* _TRIDENT_H_ */ diff --git a/hw/kdrive/trident/tridentcurs.c b/hw/kdrive/trident/tridentcurs.c new file mode 100644 index 000000000..9c4ebb5d0 --- /dev/null +++ b/hw/kdrive/trident/tridentcurs.c @@ -0,0 +1,414 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#include "trident.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + tridentScreenInfo(pScreenPriv); \ + TridentCursor *pCurPriv = &tridents->cursor + +static void +_tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + + + /* This is the recommended order to move the cursor */ + + tridentWriteIndex (tridentc, 0x3d4, 0x41, xhigh); + tridentWriteIndex (tridentc, 0x3d4, 0x40, xlow); + tridentWriteIndex (tridentc, 0x3d4, 0x42, ylow); + tridentWriteIndex (tridentc, 0x3d4, 0x46, xoff); + tridentWriteIndex (tridentc, 0x3d4, 0x47, yoff); + tridentWriteIndex (tridentc, 0x3d4, 0x43, yhigh); +} + +static void +tridentMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _tridentMoveCursor (pScreen, x, y); +} + + +static void +tridentAllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + /* + * Set these to an invalid pixel value so that + * when the store colors comes through, the cursor + * won't get recolored + */ + pCurPriv->source = ~0; + pCurPriv->mask = ~0; + /* + * XXX S3 bug workaround; s3 chip doesn't use RGB values from + * the cursor color registers as documented, rather it uses + * them to index the DAC. This is in the errata though. + */ + sourceColor.red = pCursor->foreRed; + sourceColor.green = pCursor->foreGreen; + sourceColor.blue = pCursor->foreBlue; + FakeAllocColor(pScreenPriv->pInstalledmap, &sourceColor); + maskColor.red = pCursor->backRed; + maskColor.green = pCursor->backGreen; + maskColor.blue = pCursor->backBlue; + FakeAllocColor(pScreenPriv->pInstalledmap, &maskColor); + FakeFreeColor(pScreenPriv->pInstalledmap, sourceColor.pixel); + FakeFreeColor(pScreenPriv->pInstalledmap, maskColor.pixel); + + pCurPriv->source = sourceColor.pixel; + pCurPriv->mask = maskColor.pixel; + switch (pScreenPriv->screen->bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +tridentSetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CARD32 fg, bg; + + fg = pCurPriv->source; + bg = pCurPriv->mask; + tridentWriteIndex (tridentc, 0x3d4, 0x48, fg); + tridentWriteIndex (tridentc, 0x3d4, 0x49, fg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4a, fg >> 16); + + tridentWriteIndex (tridentc, 0x3d4, 0x4c, bg); + tridentWriteIndex (tridentc, 0x3d4, 0x4d, bg >> 8); + tridentWriteIndex (tridentc, 0x3d4, 0x4e, bg >> 16); +} + +void +tridentRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + xColorItem sourceColor, maskColor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) + { + while (ndef) + { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + if (!ndef) + return; + } + tridentAllocCursorColors (pScreen); + tridentSetCursorColors (pScreen); +} + +#define InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +static void +tridentLoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + CARD32 *ram, *msk, *mskLine, *src, *srcLine; + int i, j; + int cursor_address; + int lwsrc; + unsigned char ramdac_control_; + CARD32 offset; + + /* + * Allocate new colors + */ + tridentAllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (CARD32 *) tridents->cursor_base; + mskLine = (CARD32 *) bits->mask; + srcLine = (CARD32 *) bits->source; + + h = bits->height; + if (h > TRIDENT_CURSOR_HEIGHT) + h = TRIDENT_CURSOR_HEIGHT; + + lwsrc = BitmapBytePad(bits->width) / 4; /* words per line */ + + for (i = 0; i < TRIDENT_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + for (j = 0; j < TRIDENT_CURSOR_WIDTH / 32; j++) { + + CARD32 m, s; + +#if 1 + if (i < h && j < lwsrc) + { + m = *msk++; + s = *src++; + InvertBits32(m); + InvertBits32(s); + } + else + { + m = 0; + s = 0; + } +#endif + *ram++ = m; + *ram++ = s; + } + } + + /* Set address for cursor bits */ + offset = tridents->cursor_base - (CARD8 *) tridentc->fb.fb; + offset >>= 10; + tridentWriteIndex (tridentc, 0x3d4, 0x44, (CARD8) (offset & 0xff)); + tridentWriteIndex (tridentc, 0x3d4, 0x45, (CARD8) (offset >> 8)); + + /* Set new color */ + tridentSetCursorColors (pScreen); + + /* Enable the cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0xc1); + + /* Move to new position */ + tridentMoveCursor (pScreen, x, y); +} + +static void +tridentUnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + tridentWriteIndex (tridentc, 0x3d4, 0x50, 0); +} + +static Bool +tridentRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +tridentUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +tridentSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + tridentLoadCursor (pScreen, x, y); + else + tridentUnloadCursor (pScreen); +} + +miPointerSpriteFuncRec tridentPointerSpriteFuncs = { + tridentRealizeCursor, + tridentUnrealizeCursor, + tridentSetCursor, + tridentMoveCursor, +}; + +static void +tridentQueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +tridentCursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!tridents->cursor_base) + { + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = TRIDENT_CURSOR_WIDTH; + pCurPriv->height= TRIDENT_CURSOR_HEIGHT; + pScreen->QueryBestSize = tridentQueryBestSize; + miPointerInitialize (pScreen, + &tridentPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +tridentCursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + tridentLoadCursor (pScreen, x, y); + } + else + tridentUnloadCursor (pScreen); + } +} + +void +tridentCursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + tridentUnloadCursor (pScreen); + } + } +} + +void +tridentCursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/hw/kdrive/trident/tridentdraw.c b/hw/kdrive/trident/tridentdraw.c new file mode 100644 index 000000000..f64444c53 --- /dev/null +++ b/hw/kdrive/trident/tridentdraw.c @@ -0,0 +1,859 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#include "trident.h" +#include "tridentdraw.h" + +#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" + +CARD8 tridentRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0x88, /* src AND dst */ + /* GXandReverse */ 0x44, /* src AND NOT dst */ + /* GXcopy */ 0xcc, /* src */ + /* GXandInverted*/ 0x22, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x66, /* src XOR dst */ + /* GXor */ 0xee, /* src OR dst */ + /* GXnor */ 0x11, /* NOT src AND NOT dst */ + /* GXequiv */ 0x99, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xdd, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x33, /* NOT src */ + /* GXorInverted */ 0xbb, /* NOT src OR dst */ + /* GXnand */ 0x77, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + +#define tridentFillPix(bpp,pixel) {\ + if (bpp == 8) \ + { \ + pixel = pixel & 0xff; \ + pixel = pixel | pixel << 8; \ + } \ + if (bpp <= 16) \ + { \ + pixel = pixel & 0xffff; \ + pixel = pixel | pixel << 16; \ + } \ +} +void +tridentFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu) +{ + SetupTrident(pDrawable->pScreen); + CARD32 cmd; + + tridentFillPix(pDrawable->bitsPerPixel,pixel); + _tridentInit(cop,tridentc); + _tridentSetSolidRect(cop,pixel,alu,cmd); + while (nBox--) + { + _tridentRect(cop,pBox->x1,pBox->y1,pBox->x2-1,pBox->y2-1,cmd); + pBox++; + } + _tridentWaitIdleEmpty(cop); +} + +void +tridentCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupTrident(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + CARD32 flags; + CARD32 cmd; + CARD8 alu; + + if (pGC) + { + alu = pGC->alu; + if (sourceInvarient (pGC->alu)) + { + tridentFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu); + return; + } + } + else + alu = GXcopy; + + _tridentInit(cop,tridentc); + cop->multi = COP_MULTI_PATTERN; + cop->multi = COP_MULTI_ROP | tridentRop[alu]; + if (reverse) + upsidedown = TRUE; + cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FB; + if (upsidedown) + cmd |= COP_X_REVERSE; + while (nbox--) + { + if (upsidedown) + { + cop->src_start_xy = TRI_XY (pbox->x2 + dx - 1, + pbox->y2 + dy - 1); + cop->src_end_xy = TRI_XY (pbox->x1 + dx, + pbox->y1 + dy); + cop->dst_start_xy = TRI_XY (pbox->x2 - 1, + pbox->y2 - 1); + cop->dst_end_xy = TRI_XY (pbox->x1, + pbox->y1); + } + else + { + cop->src_start_xy = TRI_XY (pbox->x1 + dx, + pbox->y1 + dy); + cop->src_end_xy = TRI_XY (pbox->x2 + dx - 1, + pbox->y2 + dy - 1); + cop->dst_start_xy = TRI_XY (pbox->x1, + pbox->y1); + cop->dst_end_xy = TRI_XY (pbox->x2 - 1, + pbox->y2 - 1); + } + cop->command = cmd; + pbox++; + } + _tridentWaitIdleEmpty(cop); +} + +RegionPtr +tridentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + KdScreenPriv(pDstDrawable->pScreen); + FbBits depthMask; + + depthMask = FbFullMask (pDstDrawable->depth); + if ((pGC->planemask & depthMask) == depthMask && + pSrcDrawable->type == DRAWABLE_WINDOW && + pDstDrawable->type == DRAWABLE_WINDOW) + { + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, tridentCopyNtoN, 0, 0); + } + return fbCopyArea (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); +} + +BOOL +tridentFillOk (GCPtr pGC) +{ + FbBits depthMask; + + depthMask = FbFullMask(pGC->depth); + if ((pGC->planemask & depthMask) != depthMask) + return FALSE; + switch (pGC->fillStyle) { + case FillSolid: + return TRUE; +#if 0 + case FillTiled: + return (tridentPatternDimOk (pGC->tile.pixmap->drawable.width) && + tridentPatternDimOk (pGC->tile.pixmap->drawable.height)); + case FillStippled: + case FillOpaqueStippled: + return (tridentPatternDimOk (pGC->stipple->drawable.width) && + tridentPatternDimOk (pGC->stipple->drawable.height)); +#endif + } + return FALSE; +} + +void +tridentFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + SetupTrident(pDrawable->pScreen); + DDXPointPtr pptFree; + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + int *pwidthFree;/* copies of the pointers to free */ + CARD32 cmd; + int nTmp; + INT16 x, y; + int width; + CARD32 pixel; + + if (!tridentFillOk (pGC)) + { + fbFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); + return; + } + nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC)); + pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int)); + pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) DEALLOCATE_LOCAL(pptFree); + if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); + return; + } + n = miClipSpans(fbGetCompositeClip(pGC), + ppt, pwidth, n, + pptFree, pwidthFree, fSorted); + pwidth = pwidthFree; + ppt = pptFree; + _tridentInit(cop,tridentc); + switch (pGC->fillStyle) { + case FillSolid: + pixel = pGC->fgPixel; + tridentFillPix (pDrawable->bitsPerPixel,pixel); + _tridentSetSolidRect(cop,pixel,pGC->alu,cmd); + break; +#if 0 + case FillTiled: + cmd = tridentTilePrepare (pGC->tile.pixmap, + pGC->patOrg.x + pDrawable->x, + pGC->patOrg.y + pDrawable->y, + pGC->alu); + break; + default: + cmd = tridentStipplePrepare (pDrawable, pGC); + break; +#endif + } + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _tridentRect(cop,x,y,x + width,y,cmd); + } + } + _tridentWaitIdleEmpty (cop); + DEALLOCATE_LOCAL(pptFree); + DEALLOCATE_LOCAL(pwidthFree); +} + +#define NUM_STACK_RECTS 1024 + +void +tridentPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + SetupTrident(pDrawable->pScreen); + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC); + int numRects; + int n; + int xorg, yorg; + int x, y; + + if (!tridentFillOk (pGC)) + { + fbPolyFillRect (pDrawable, pGC, nrectFill, prectInit); + return; + } + prgnClip = fbGetCompositeClip(pGC); + xorg = pDrawable->x; + yorg = pDrawable->y; + + if (xorg || yorg) + { + prect = prectInit; + n = nrectFill; + while(n--) + { + prect->x += xorg; + prect->y += yorg; + prect++; + } + } + + prect = prectInit; + + numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; + if (numRects > NUM_STACK_RECTS) + { + pboxClippedBase = (BoxPtr)xalloc(numRects * sizeof(BoxRec)); + if (!pboxClippedBase) + return; + } + else + pboxClippedBase = stackRects; + + pboxClipped = pboxClippedBase; + + if (REGION_NUM_RECTS(prgnClip) == 1) + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_RECTS(prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + if ((pboxClipped->x1 = prect->x) < x1) + pboxClipped->x1 = x1; + + if ((pboxClipped->y1 = prect->y) < y1) + pboxClipped->y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + pboxClipped->x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + pboxClipped->y2 = by2; + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) + { + pboxClipped++; + } + } + } + else + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + BoxRec box; + + if ((box.x1 = prect->x) < x1) + box.x1 = x1; + + if ((box.y1 = prect->y) < y1) + box.y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + box.x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + box.y2 = by2; + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = REGION_NUM_RECTS (prgnClip); + pbox = REGION_RECTS(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while(n--) + { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if(pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) + { + pboxClipped++; + } + } + } + } + if (pboxClipped != pboxClippedBase) + { + switch (pGC->fillStyle) { + case FillSolid: + tridentFillBoxSolid(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->fgPixel, pGC->alu); + break; +#if 0 + case FillTiled: + tridentFillBoxTiled(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->tile.pixmap, + pGC->patOrg.x + pDrawable->x, + pGC->patOrg.y + pDrawable->y, + pGC->alu); + break; + case FillStippled: + case FillOpaqueStippled: + tridentFillBoxStipple (pDrawable, pGC, + pboxClipped-pboxClippedBase, pboxClippedBase); + break; +#endif + } + } + if (pboxClippedBase != stackRects) + xfree(pboxClippedBase); +} + +void +tridentSolidBoxClipped (DrawablePtr pDrawable, + RegionPtr pClip, + int x1, + int y1, + int x2, + int y2, + FbBits fg) +{ + SetupTrident (pDrawable->pScreen); + BoxPtr pbox; + int nbox; + int partX1, partX2, partY1, partY2; + CARD32 cmd; + + _tridentInit (cop, tridentc); + _tridentSetSolidRect (cop, fg, GXcopy, cmd); + + for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + partX1 = pbox->x1; + if (partX1 < x1) + partX1 = x1; + + partX2 = pbox->x2; + if (partX2 > x2) + partX2 = x2; + + if (partX2 <= partX1) + continue; + + partY1 = pbox->y1; + if (partY1 < y1) + partY1 = y1; + + partY2 = pbox->y2; + if (partY2 > y2) + partY2 = y2; + + if (partY2 <= partY1) + continue; + + _tridentRect(cop,partX1, partY1, partX2-1, partY2-1,cmd); + } + _tridentWaitIdleEmpty(cop); +} + +void +tridentImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + CharInfoPtr *ppci; + CharInfoPtr pci; + unsigned char *pglyph; /* pointer bits in glyph */ + int gWidth, gHeight; /* width and height of glyph */ + FbStride gStride; /* stride of glyph */ + Bool opaque; + int n; + int gx, gy; + void (*glyph) (FbBits *, + FbStride, + int, + FbStip *, + FbBits, + int, + int); + FbBits *dst; + FbStride dstStride; + int dstBpp; + FbBits depthMask; + + depthMask = FbFullMask(pDrawable->depth); + if ((pGC->planemask & depthMask) != depthMask) + { + fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); + return; + } + glyph = 0; + fbGetDrawable (pDrawable, dst, dstStride, dstBpp); + switch (dstBpp) { + case 8: glyph = fbGlyph8; break; + case 16: glyph = fbGlyph16; break; + case 24: glyph = fbGlyph24; break; + case 32: glyph = fbGlyph32; break; + } + + x += pDrawable->x; + y += pDrawable->y; + + if (TERMINALFONT (pGC->font) && !glyph) + { + opaque = TRUE; + } + else + { + int xBack, widthBack; + int yBack, heightBack; + + ppci = ppciInit; + n = nglyph; + widthBack = 0; + while (n--) + widthBack += (*ppci++)->metrics.characterWidth; + + xBack = x; + if (widthBack < 0) + { + xBack += widthBack; + widthBack = -widthBack; + } + yBack = y - FONTASCENT(pGC->font); + heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + tridentSolidBoxClipped (pDrawable, + fbGetCompositeClip(pGC), + xBack, + yBack, + xBack + widthBack, + yBack + heightBack, + pPriv->bg); + opaque = FALSE; + } + + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) + { + gx = x + pci->metrics.leftSideBearing; + gy = y - pci->metrics.ascent; + if (glyph && gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) + { + (*glyph) (dst + gy * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, + pPriv->fg, + gx, + gHeight); + } + else + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + GXcopy, + opaque, + + gx, + gy, + gWidth, gHeight, + + (FbStip *) pglyph, + gStride, + 0); + } + } + x += pci->metrics.characterWidth; + } +} + +static const GCOps tridentOps = { + tridentFillSpans, + fbSetSpans, + fbPutImage, + tridentCopyArea, + fbCopyPlane, + fbPolyPoint, + fbPolyLine, + fbPolySegment, + miPolyRectangle, + fbPolyArc, + miFillPolygon, + tridentPolyFillRect, + fbPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + tridentImageGlyphBlt, + fbPolyGlyphBlt, + fbPushPixels, +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +void +tridentValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + + fbValidateGC (pGC, changes, pDrawable); + + if (pDrawable->type == DRAWABLE_WINDOW) + pGC->ops = (GCOps *) &tridentOps; + else + pGC->ops = (GCOps *) &fbGCOps; +} + +GCFuncs tridentGCFuncs = { + tridentValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +int +tridentCreateGC (GCPtr pGC) +{ + if (!fbCreateGC (pGC)) + return FALSE; + + if (pGC->depth != 1) + pGC->funcs = &tridentGCFuncs; + + return TRUE; +} + +void +tridentCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdScreenPriv(pScreen); + RegionRec rgnDst; + int dx, dy; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + + REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); + + REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + 0, + &rgnDst, dx, dy, tridentCopyNtoN, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + +void +tridentPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + KdScreenPriv(pWin->drawable.pScreen); + PixmapPtr pTile; + + if (!REGION_NUM_RECTS(pRegion)) + return; + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + return; +#if 0 + case BackgroundPixmap: + pTile = pWin->background.pixmap; + if (tridentPatternDimOk (pTile->drawable.width) && + tridentPatternDimOk (pTile->drawable.height)) + { + tridentFillBoxTiled ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pTile, + pWin->drawable.x, pWin->drawable.y, GXcopy); + return; + } + break; +#endif + case BackgroundPixel: + tridentFillBoxSolid((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->background.pixel, GXcopy); + return; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + tridentFillBoxSolid((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pWin->border.pixel, GXcopy); + return; + } +#if 0 + else + { + pTile = pWin->border.pixmap; + if (tridentPatternDimOk (pTile->drawable.width) && + tridentPatternDimOk (pTile->drawable.height)) + { + tridentFillBoxTiled ((DrawablePtr)pWin, + (int)REGION_NUM_RECTS(pRegion), + REGION_RECTS(pRegion), + pTile, + pWin->drawable.x, pWin->drawable.y, GXcopy); + return; + } + } +#endif + break; + } + fbPaintWindow (pWin, pRegion, what); +} + +Bool +tridentDrawInit (ScreenPtr pScreen) +{ + /* + * Replace various fb screen functions + */ + pScreen->CreateGC = tridentCreateGC; + pScreen->CopyWindow = tridentCopyWindow; + pScreen->PaintWindowBackground = tridentPaintWindow; + pScreen->PaintWindowBorder = tridentPaintWindow; + + return TRUE; +} + +void +tridentDrawEnable (ScreenPtr pScreen) +{ + SetupTrident(pScreen); + CARD32 cmd; + CARD32 base; + CARD16 stride; + CARD32 format; + int tries; + + stride = pScreenPriv->screen->pixelStride; + switch (pScreenPriv->screen->bitsPerPixel) { + case 8: + format = COP_DEPTH_8; + break; + case 16: + format = COP_DEPTH_16; + break; + case 24: + format = COP_DEPTH_24_32; + break; + case 32: + format = COP_DEPTH_24_32; + break; + } + /* + * compute a few things which will be set every time the + * accelerator is used; this avoids problems with APM + */ + tridentc->cop_depth = COP_MULTI_DEPTH | format; + tridentc->cop_stride = COP_MULTI_STRIDE | (stride << 16) | (stride); + +#define NUM_TRIES 100000 + for (tries = 0; tries < NUM_TRIES; tries++) + if (!(cop->status & COP_STATUS_BUSY)) + break; + if (cop->status & COP_STATUS_BUSY) + FatalError ("Can't initialize graphics coprocessor"); + cop->multi = COP_MULTI_CLIP_TOP_LEFT; + cop->multi = COP_MULTI_MASK | 0; + cop->src_offset = 0; + cop->dst_offset = 0; + cop->z_offset = 0; + cop->clip_bottom_right = 0x0fff0fff; + + _tridentInit(cop,tridentc); + _tridentSetSolidRect(cop, pScreen->blackPixel, GXcopy, cmd); + _tridentRect (cop, 0, 0, + pScreenPriv->screen->width, pScreenPriv->screen->height, + cmd); + _tridentWaitIdleEmpty (cop); +} + +void +tridentDrawDisable (ScreenPtr pScreen) +{ +} + +void +tridentDrawFini (ScreenPtr pScreen) +{ +} diff --git a/hw/kdrive/trident/tridentdraw.h b/hw/kdrive/trident/tridentdraw.h new file mode 100644 index 000000000..5fa64d2a7 --- /dev/null +++ b/hw/kdrive/trident/tridentdraw.h @@ -0,0 +1,63 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: $ */ + +#ifndef _TRIDENTDRAW_H_ +#define _TRIDENTDRAW_H_ + +#define SetupTrident(s) KdScreenPriv(s); \ + tridentCardInfo(pScreenPriv); \ + Cop *cop = tridentc->cop + +#define _tridentInit(cop,tridentc) { \ + if ((cop)->status == 0xffffffff) tridentSetMMIO(tridentc); \ + (cop)->multi = (tridentc)->cop_depth; \ + (cop)->multi = (tridentc)->cop_stride; \ +} \ + +#define _tridentSetSolidRect(cop,pix,alu,cmd) {\ + cop->multi = COP_MULTI_PATTERN; \ + cop->multi = COP_MULTI_ROP | tridentRop[alu]; \ + cop->fg = (pix); \ + cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FG; \ +} + +#define _tridentRect(cop,x1,y1,x2,y2,cmd) { \ + (cop)->dst_start_xy = TRI_XY (x1,y1); \ + (cop)->dst_end_xy = TRI_XY(x2,y2); \ + (cop)->command = (cmd); \ +} + +#define COP_STATUS_BUSY (COP_STATUS_BE_BUSY | \ + COP_STATUS_DPE_BUSY | \ + COP_STATUS_MI_BUSY | \ + COP_STATUS_FIFO_BUSY) + +#define _tridentWaitDone(cop) while ((cop)->status & COP_STATUS_BUSY) + +#define _tridentWaitIdleEmpty(cop) _tridentWaitDone(cop); + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +#endif diff --git a/hw/kdrive/trident/tridentstub.c b/hw/kdrive/trident/tridentstub.c new file mode 100644 index 000000000..b0005e7c7 --- /dev/null +++ b/hw/kdrive/trident/tridentstub.c @@ -0,0 +1,54 @@ +/* + * $Id$ + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ +/* $XFree86: $ */ + +#include "trident.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; + + if (LinuxFindPci (0x1023, 0x9525, 0, &attr)) + KdCardInfoAdd (&tridentFuncs, &attr, 0); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdInitInput (&Ps2MouseFuncs, &LinuxKeyboardFuncs); +} + +void +OsVendorInit (void) +{ + KdOsInit (&LinuxFuncs); +} |