diff options
Diffstat (limited to 'xserver/hw/kdrive/savage')
-rw-r--r-- | xserver/hw/kdrive/savage/s3.c | 1835 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3.h | 533 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3.nick | 41 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3clock.c | 84 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3cmap.c | 122 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3curs.c | 422 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3draw.c | 3114 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3draw.h | 468 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3gc.c | 299 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3reg.c | 1301 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3reg.h | 227 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3rtst.c | 141 | ||||
-rw-r--r-- | xserver/hw/kdrive/savage/s3stub.c | 93 |
13 files changed, 8680 insertions, 0 deletions
diff --git a/xserver/hw/kdrive/savage/s3.c b/xserver/hw/kdrive/savage/s3.c new file mode 100644 index 000000000..c1b01e701 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3.c @@ -0,0 +1,1835 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" + +#define REGISTERS_OFFSET (0x1000000) +#define PACKED_OFFSET (0x8100) +#define IOMAP_OFFSET (0x8000) + +#define S3_MIN_CLOCK 250000 + +static void +_s3SetBlank (S3Ptr s3, S3Vga *s3vga, Bool blank) +{ + CARD8 clock_mode; + + s3SetImm(s3vga, s3_screen_off, blank ? 1 : 0); +} + +Bool +s3CardInit (KdCardInfo *card) +{ + S3CardInfo *s3c; + S3Ptr s3; + S3Vga *s3vga; + int size; + CARD8 *registers; + CARD32 s3FrameBuffer; + CARD32 s3Registers; + CARD8 *temp_buffer; + CARD32 max_memory; + VGA32 save_linear_window_size; + VGA32 save_enable_linear; + VGA32 save_register_lock_2; + VGA32 save_misc_output; + + s3c = (S3CardInfo *) xalloc (sizeof (S3CardInfo)); + if (!s3c) + { + goto bail0; + } + + memset (s3c, '\0', sizeof (S3CardInfo)); + + card->driver = s3c; + +#ifdef VXWORKS + s3c->bios_initialized = 0; +#else + s3c->bios_initialized = 1; +#endif + + if (card->attr.naddr > 1 && card->attr.address[1]) + { + s3FrameBuffer = card->attr.address[1]; + s3Registers = card->attr.address[0]; + max_memory = 32 * 1024 * 1024; + } + else + { + s3FrameBuffer = card->attr.address[0]; + s3Registers = s3FrameBuffer + REGISTERS_OFFSET; + max_memory = 16 * 1024 * 1024; + } + +#ifdef DEBUG + fprintf (stderr, "S3 at 0x%x/0x%x\n", s3Registers, s3FrameBuffer); +#endif + registers = KdMapDevice (s3Registers, + sizeof (S3) + PACKED_OFFSET); + if (!registers) + { + ErrorF ("Can't map s3 device\n"); + goto bail2; + } + s3 = (S3Ptr) (registers + PACKED_OFFSET); + s3c->registers = registers; + s3c->s3 = s3; + + s3vga = &s3c->s3vga; + s3RegInit (s3vga, (VGAVOL8 *) (registers + IOMAP_OFFSET)); + + if (!s3c->bios_initialized) + { + volatile CARD32 *wakeup; + + wakeup = (volatile CARD32 *) (registers + 0x8510); + ErrorF ("Wakeup S3 chip at 0x%x\n", wakeup); + ErrorF ("Wakeup was 0x%x\n", *wakeup); + /* wakeup the chip */ + *(volatile CARD32 *) (registers + 0x8510) = 1; + ErrorF ("Wakeup is 0x%x\n", *wakeup); + } + s3Set (s3vga, s3_io_addr_select, 1); + s3Set (s3vga, s3_enable_ram, 1); + VgaFlush (&s3vga->card); + + save_register_lock_2 = s3Get (s3vga, s3_register_lock_2); + s3SetImm (s3vga, s3_register_lock_2, 0xa0); + save_linear_window_size = s3Get (s3vga, s3_linear_window_size); + save_enable_linear = s3Get (s3vga, s3_enable_linear); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + VgaFinish (&s3vga->card); + + /* + * Can't trust S3 register value for frame buffer amount, must compute + */ + temp_buffer = KdMapDevice (s3FrameBuffer, max_memory); + + s3c->memory = KdFrameBufferSize (temp_buffer, max_memory); + + s3Set (s3vga, s3_linear_window_size, save_linear_window_size); + s3Set (s3vga, s3_enable_linear, save_enable_linear); + VgaFlush (&s3vga->card); + s3SetImm (s3vga, s3_register_lock_2, save_register_lock_2); + VgaFinish (&s3vga->card); +#ifdef DEBUG + fprintf (stderr, "Frame buffer 0x%x\n", s3c->memory); +#endif + KdUnmapDevice (temp_buffer, max_memory); + + if (!s3c->memory) + { + ErrorF ("Can't detect s3 frame buffer at 0x%x\n", s3FrameBuffer); + goto bail3; + } + + s3c->frameBuffer = KdMapDevice (s3FrameBuffer, s3c->memory); + if (!s3c->frameBuffer) + { + ErrorF ("Can't map s3 frame buffer\n"); + goto bail3; + } + + card->driver = s3c; + + return TRUE; +bail3: + KdUnmapDevice ((void *) s3, sizeof (S3)); +bail2: +bail1: + xfree (s3c); +bail0: + return FALSE; +} + +Bool +s3ModeSupported (KdScreenInfo *screen, + const KdMonitorTiming *t) +{ + if (screen->fb[1].depth) + { + /* + * Must have at least one true color stream + */ + if (screen->fb[0].depth <= 8 && + screen->fb[1].depth <= 8) + return FALSE; + } + /* make sure the clock isn't too fast */ + if (t->clock > S3_MAX_CLOCK * 2) + return FALSE; + /* width must be a multiple of 16 */ + if (t->horizontal & 0xf) + return FALSE; + return TRUE; +} + +Bool +s3ModeUsable (KdScreenInfo *screen) +{ + KdCardInfo *card = screen->card; + S3CardInfo *s3c = (S3CardInfo *) card->driver; + int screen_size; + int pixel_width; + int byte_width; + int fb; + + screen_size = 0; + for (fb = 0; fb < KD_MAX_FB && screen->fb[fb].depth; fb++) + { + if (screen->fb[fb].depth >= 24) + { + screen->fb[fb].depth = 24; + if (screen->fb[fb].bitsPerPixel != 24) + screen->fb[fb].bitsPerPixel = 32; + } + else if (screen->fb[fb].depth >= 16) + { + screen->fb[fb].depth = 16; + screen->fb[fb].bitsPerPixel = 16; + } + else if (screen->fb[fb].depth >= 15) + { + screen->fb[fb].depth = 15; + screen->fb[fb].bitsPerPixel = 16; + } + else + { + screen->fb[fb].depth = 8; + screen->fb[fb].bitsPerPixel = 8; + } + + /* + * SGRAM requires stride % 64 == 0 + */ + screen->fb[fb].pixelStride = (screen->width + 63) & ~63; + screen->fb[fb].byteStride = screen->fb[fb].pixelStride * (screen->fb[fb].bitsPerPixel >> 3); + screen_size += screen->fb[fb].byteStride * screen->height; + } + + return screen_size <= s3c->memory; +} + +Bool +s3ScreenInit (KdScreenInfo *screen) +{ + KdCardInfo *card = screen->card; + S3CardInfo *s3c = (S3CardInfo *) card->driver; + S3ScreenInfo *s3s; + int memory; + int requested_memory; + int v_total, h_total; + int m, n, r; + int i; + const KdMonitorTiming *t; + int screen_size; + int fb; + int ma; + + s3s = (S3ScreenInfo *) xalloc (sizeof (S3ScreenInfo)); + if (!s3s) + return FALSE; + + memset (s3s, '\0', sizeof (S3ScreenInfo)); + +#ifdef PHOENIX + screen->width = 1152; + screen->height = 900; + screen->rate = 85; + screen->depth = 32; +#endif + if (!screen->width || !screen->height) + { + screen->width = 800; + screen->height = 600; + screen->rate = 72; + } + if (!screen->fb[0].depth) + screen->fb[0].depth = 8; + + t = KdFindMode (screen, s3ModeSupported); + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + s3GetClock (t->clock, &m, &n, &r, 511, 127, 4, 250000); +#ifdef DEBUG + fprintf (stderr, "computed %d,%d,%d (%d)\n", + m, n, r, S3_CLOCK(m,n,r)); +#endif +#if 0 + /* + * Can only operate in pixel-doubled mode at 8 or 16 bits per pixel + */ + if (screen->depth > 16 && S3_CLOCK(m,n,r) > S3_MAX_CLOCK) + screen->depth = 16; +#endif + + if (!KdTuneMode (screen, s3ModeUsable, s3ModeSupported)) + { + xfree (s3s); + return FALSE; + } + + s3s->fbmap[2] = -1; + if (screen->fb[1].depth) + { + if (screen->fb[0].bitsPerPixel >= 16) + { + s3s->fbmap[0] = 1; + s3s->fbmap[1] = 0; + } + else + { + s3s->fbmap[0] = 0; + s3s->fbmap[1] = 1; + } + } + else + { + s3s->fbmap[0] = 0; + s3s->fbmap[1] = -1; + } + + screen_size = 0; + for (fb = 0; fb < KD_MAX_FB && screen->fb[fb].depth; fb++) + screen_size += screen->fb[fb].byteStride * screen->height; + + memory = s3c->memory - screen_size; + + /* + * Stick cursor at end of memory + */ + if (memory >= 2048) + { + s3s->cursor_base = s3c->frameBuffer + (s3c->memory - 2048); + memory -= 2048; + } + else + s3s->cursor_base = 0; + + screen_size = 0; + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + { + fb = s3s->fbmap[ma]; + screen->fb[fb].frameBuffer = s3c->frameBuffer + screen_size; + screen_size += screen->fb[fb].byteStride * screen->height; + + REGION_INIT(pScreen, (&s3s->region[fb]), NullBox, 0); + if (screen->fb[fb].bitsPerPixel == 8) + s3s->fb[ma].chroma_key = 0xff; + else + s3s->fb[ma].chroma_key = 0; + + /* + * Use remaining memory for off-screen storage, but only use + * one piece (either right or bottom). + */ + if (memory >= screen->fb[fb].byteStride * S3_TILE_SIZE) + { + s3s->fb[ma].offscreen = screen->fb[fb].frameBuffer; + s3s->fb[ma].offscreen_x = 0; + s3s->fb[ma].offscreen_y = screen->height; + s3s->fb[ma].offscreen_width = screen->fb[fb].pixelStride; + s3s->fb[ma].offscreen_height = S3_TILE_SIZE; + memory -= s3s->fb[ma].offscreen_height * screen->fb[fb].byteStride; + screen_size += s3s->fb[ma].offscreen_height * screen->fb[fb].byteStride; + } + else + s3s->fb[ma].offscreen = 0; + + switch (screen->fb[fb].depth) { + case 8: + screen->fb[fb].visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + screen->fb[fb].blueMask = 0x00; + screen->fb[fb].greenMask = 0x00; + screen->fb[fb].redMask = 0x00; + break; + case 15: + screen->fb[fb].visuals = (1 << TrueColor); + screen->fb[fb].blueMask = 0x001f; + screen->fb[fb].greenMask = 0x03e0; + screen->fb[fb].redMask = 0x7c00; + break; + case 16: + screen->fb[fb].visuals = (1 << TrueColor); + screen->fb[fb].blueMask = 0x001f; + screen->fb[fb].greenMask = 0x07e0; + screen->fb[fb].redMask = 0xf800; + break; + case 24: + screen->fb[fb].visuals = (1 << TrueColor); + screen->fb[fb].blueMask = 0x0000ff; + screen->fb[fb].greenMask = 0x00ff00; + screen->fb[fb].redMask = 0xff0000; + break; + } + } + + screen->driver = s3s; + + return TRUE; +} + +typedef struct _biosInit { + VGA16 reg; + VGA8 value; +} s3BiosInit; + +s3BiosInit s3BiosReg[] = { + S3_SR +0x15, 0x23, + S3_MISC_OUT, 0x2f, + 0xffff, 1, + S3_SR +0x15, 0x03, + + S3_SR + 0x0, 0x03, + S3_SR + 0x1, 0x00, + S3_SR + 0x2, 0x03, + S3_SR + 0x3, 0x00, + S3_SR + 0x4, 0x02, + S3_SR + 0x5, 0x05, + S3_SR + 0x6, 0x06, + S3_SR + 0x7, 0x07, +/* S3_SR + 0x8, 0x06, */ + S3_SR + 0x9, 0x00, + S3_SR + 0xa, 0x0a, + S3_SR + 0xb, 0x00, + S3_SR + 0xc, 0x0c, + S3_SR + 0xd, 0x00, + S3_SR + 0xe, 0x0e, + S3_SR + 0xf, 0x0f, + +/* S3_SR +0x10, 0x00, */ +/* S3_SR +0x11, 0x0c, */ + S3_SR +0x12, 0x01, + S3_SR +0x13, 0x52, + S3_SR +0x14, 0x00, + +/* S3_SR +0x15, 0x03, */ + + S3_SR +0x16, 0xc5, + S3_SR +0x17, 0xfc, + S3_SR +0x18, 0x40, + S3_SR +0x19, 0x00, + S3_SR +0x1a, 0x01, + S3_SR +0x1b, 0x02, + S3_SR +0x1c, 0x5d, + S3_SR +0x1d, 0x00, + S3_SR +0x1e, 0x00, + S3_SR +0x1f, 0x00, + S3_SR +0x20, 0x20, + S3_SR +0x21, 0x21, + S3_SR +0x22, 0x22, + S3_SR +0x23, 0x23, + S3_SR +0x24, 0x24, + S3_SR +0x25, 0x25, + S3_SR +0x26, 0x26, + S3_SR +0x27, 0x04, + S3_SR +0x28, 0xff, + S3_SR +0x29, 0x00, + S3_SR +0x2a, 0x2a, + S3_SR +0x2b, 0x2b, + S3_SR +0x2c, 0x2c, + S3_SR +0x2d, 0x2d, + S3_SR +0x2e, 0x2e, + S3_SR +0x2f, 0x2f, + S3_SR +0x30, 0x00, + S3_SR +0x31, 0x06, + S3_SR +0x32, 0x41, + S3_SR +0x33, 0x67, + S3_SR +0x34, 0x00, + S3_SR +0x35, 0x00, + S3_SR +0x36, 0x01, + S3_SR +0x37, 0x52, + S3_SR +0x38, 0x5d, + S3_SR +0x39, 0x05, + S3_SR +0x3a, 0x3a, + S3_SR +0x3b, 0x3b, + S3_SR +0x3c, 0x3c, + S3_SR +0x3d, 0x00, + S3_SR +0x3e, 0x3e, + S3_SR +0x3f, 0x00, + S3_SR +0x40, 0x40, + S3_SR +0x41, 0x41, + S3_SR +0x42, 0x42, + S3_SR +0x43, 0x43, + S3_SR +0x44, 0x44, + S3_SR +0x45, 0x45, + S3_SR +0x46, 0x46, + S3_SR +0x47, 0x47, + S3_SR +0x48, 0x48, + S3_SR +0x49, 0x49, + S3_SR +0x4a, 0x4a, + S3_SR +0x4b, 0x4b, + S3_SR +0x4c, 0x4c, + S3_SR +0x4d, 0x4d, + S3_SR +0x4e, 0x4e, + S3_SR +0x4f, 0x4f, + S3_SR +0x50, 0x00, + S3_SR +0x51, 0x00, + S3_SR +0x52, 0x00, + S3_SR +0x53, 0x00, + S3_SR +0x54, 0x00, + S3_SR +0x55, 0x00, + S3_SR +0x56, 0x00, + S3_SR +0x57, 0x00, + S3_SR +0x58, 0x00, + S3_SR +0x59, 0x70, + S3_SR +0x5a, 0x38, + S3_SR +0x5b, 0x08, + S3_SR +0x5c, 0x77, + S3_SR +0x5d, 0x77, + S3_SR +0x5e, 0x00, + S3_SR +0x5f, 0x00, + S3_SR +0x60, 0xff, + S3_SR +0x61, 0xbf, + S3_SR +0x62, 0xff, + S3_SR +0x63, 0xff, + S3_SR +0x64, 0xf7, + S3_SR +0x65, 0xff, + S3_SR +0x66, 0xff, + S3_SR +0x67, 0xff, + S3_SR +0x68, 0xff, + S3_SR +0x69, 0xff, + S3_SR +0x6a, 0xff, + S3_SR +0x6b, 0xff, + S3_SR +0x6c, 0xff, + S3_SR +0x6d, 0xff, + S3_SR +0x6e, 0x9b, + S3_SR +0x6f, 0xbf, + + S3_AR + 0x00, 0x00, + S3_AR + 0x01, 0x01, + S3_AR + 0x02, 0x02, + S3_AR + 0x03, 0x03, + S3_AR + 0x04, 0x04, + S3_AR + 0x05, 0x05, + S3_AR + 0x06, 0x06, + S3_AR + 0x07, 0x07, + S3_AR + 0x08, 0x08, + S3_AR + 0x09, 0x09, + S3_AR + 0x0a, 0x0a, + S3_AR + 0x0b, 0x0b, + S3_AR + 0x0c, 0x0c, + S3_AR + 0x0d, 0x0d, + S3_AR + 0x0e, 0x0e, + S3_AR + 0x0f, 0x0f, + S3_AR + 0x10, 0x05, + S3_AR + 0x11, 0x00, + S3_AR + 0x12, 0x0f, + S3_AR + 0x13, 0x08, + S3_AR + 0x14, 0x00, + + S3_GR + 0x00, 0x00, + S3_GR + 0x01, 0x00, + S3_GR + 0x02, 0x00, + S3_GR + 0x03, 0x00, + S3_GR + 0x04, 0x00, + S3_GR + 0x05, 0x10, + S3_GR + 0x06, 0x0e, + S3_GR + 0x07, 0x00, + + S3_CR + 0x00, 0x5f, + S3_CR + 0x01, 0x4f, + S3_CR + 0x02, 0x50, + S3_CR + 0x03, 0x82, + S3_CR + 0x04, 0x55, + S3_CR + 0x05, 0x81, + S3_CR + 0x06, 0xbf, + S3_CR + 0x07, 0x1f, + S3_CR + 0x08, 0x00, + S3_CR + 0x09, 0x4f, + S3_CR + 0x0a, 0x0d, + S3_CR + 0x0b, 0x0e, + S3_CR + 0x0c, 0x00, + S3_CR + 0x0d, 0x00, + S3_CR + 0x0e, 0x3f, + S3_CR + 0x0f, 0xff, + S3_CR + 0x10, 0x9c, + S3_CR + 0x11, 0x0e, + S3_CR + 0x12, 0x8f, + S3_CR + 0x13, 0x28, + S3_CR + 0x14, 0x1f, + S3_CR + 0x15, 0x96, + S3_CR + 0x16, 0xb9, + S3_CR + 0x17, 0xa3, + S3_CR + 0x18, 0xff, + S3_CR + 0x19, 0xdf, + S3_CR + 0x1a, 0xdf, + S3_CR + 0x1b, 0xdf, + S3_CR + 0x1c, 0xdf, + S3_CR + 0x1d, 0xdf, + S3_CR + 0x1e, 0xdf, + S3_CR + 0x1f, 0xdf, + S3_CR + 0x20, 0xdf, + S3_CR + 0x21, 0x00, +/* S3_CR + 0x22, 0x07, */ + S3_CR + 0x23, 0x00, + S3_CR + 0x24, 0xdf, + S3_CR + 0x25, 0xdf, + S3_CR + 0x26, 0x00, + S3_CR + 0x27, 0xdf, + S3_CR + 0x28, 0xdf, + S3_CR + 0x29, 0xdf, + S3_CR + 0x2a, 0xdf, + S3_CR + 0x2b, 0xdf, + S3_CR + 0x2c, 0xdf, + S3_CR + 0x2d, 0x8a, + S3_CR + 0x2e, 0x22, + S3_CR + 0x2f, 0x02, + S3_CR + 0x30, 0xe1, + S3_CR + 0x31, 0x05, + S3_CR + 0x32, 0x40, + S3_CR + 0x33, 0x08, + S3_CR + 0x34, 0x00, + S3_CR + 0x35, 0x00, + S3_CR + 0x36, 0xbf, + S3_CR + 0x37, 0x9b, +/* S3_CR + 0x38, 0x7b, */ +/* S3_CR + 0x39, 0xb8, */ + S3_CR + 0x3a, 0x45, + S3_CR + 0x3b, 0x5a, + S3_CR + 0x3c, 0x10, + S3_CR + 0x3d, 0x00, + S3_CR + 0x3e, 0xfd, + S3_CR + 0x3f, 0x00, + S3_CR + 0x40, 0x00, + S3_CR + 0x41, 0x92, + S3_CR + 0x42, 0xc0, + S3_CR + 0x43, 0x68, + S3_CR + 0x44, 0xff, + S3_CR + 0x45, 0xe8, + S3_CR + 0x46, 0xff, + S3_CR + 0x47, 0xff, + S3_CR + 0x48, 0xf8, + S3_CR + 0x49, 0xff, + S3_CR + 0x4a, 0xfe, + S3_CR + 0x4b, 0xff, + S3_CR + 0x4c, 0xff, + S3_CR + 0x4d, 0xff, + S3_CR + 0x4e, 0xff, + S3_CR + 0x4f, 0xff, + S3_CR + 0x50, 0x00, + S3_CR + 0x51, 0x00, + S3_CR + 0x52, 0x00, + S3_CR + 0x53, 0x00, + S3_CR + 0x54, 0x00, + S3_CR + 0x55, 0x00, + S3_CR + 0x56, 0x00, + S3_CR + 0x57, 0x00, +#if 0 + S3_CR + 0x58, 0x00, + S3_CR + 0x59, 0xf0, +#endif + S3_CR + 0x5a, 0x00, + S3_CR + 0x5b, 0x00, +#if 0 + S3_CR + 0x5c, 0x00, +#endif + S3_CR + 0x5d, 0x00, + S3_CR + 0x5e, 0x00, + S3_CR + 0x5f, 0x00, + S3_CR + 0x60, 0x09, + S3_CR + 0x61, 0x9d, + S3_CR + 0x62, 0xff, + S3_CR + 0x63, 0x00, + S3_CR + 0x64, 0xfd, + S3_CR + 0x65, 0x04, + S3_CR + 0x66, 0x88, + S3_CR + 0x67, 0x00, + S3_CR + 0x68, 0x7f, + S3_CR + 0x69, 0x00, + S3_CR + 0x6a, 0x00, + S3_CR + 0x6b, 0x00, + S3_CR + 0x6c, 0x00, + S3_CR + 0x6d, 0x11, + S3_CR + 0x6e, 0xff, + S3_CR + 0x6f, 0xfe, + + S3_CR + 0x70, 0x30, + S3_CR + 0x71, 0xc0, + S3_CR + 0x72, 0x07, + S3_CR + 0x73, 0x1f, + S3_CR + 0x74, 0x1f, + S3_CR + 0x75, 0x1f, + S3_CR + 0x76, 0x0f, + S3_CR + 0x77, 0x1f, + S3_CR + 0x78, 0x01, + S3_CR + 0x79, 0x01, + S3_CR + 0x7a, 0x1f, + S3_CR + 0x7b, 0x1f, + S3_CR + 0x7c, 0x17, + S3_CR + 0x7d, 0x17, + S3_CR + 0x7e, 0x17, + S3_CR + 0x7f, 0xfd, + S3_CR + 0x80, 0x00, + S3_CR + 0x81, 0x92, + S3_CR + 0x82, 0x10, + S3_CR + 0x83, 0x07, + S3_CR + 0x84, 0x42, + S3_CR + 0x85, 0x00, + S3_CR + 0x86, 0x00, + S3_CR + 0x87, 0x00, + S3_CR + 0x88, 0x10, + S3_CR + 0x89, 0xfd, + S3_CR + 0x8a, 0xfd, + S3_CR + 0x8b, 0xfd, + S3_CR + 0x8c, 0xfd, + S3_CR + 0x8d, 0xfd, + S3_CR + 0x8e, 0xfd, + S3_CR + 0x8f, 0xfd, + S3_CR + 0x90, 0x00, + S3_CR + 0x91, 0x4f, + S3_CR + 0x92, 0x10, + S3_CR + 0x93, 0x00, + S3_CR + 0x94, 0xfd, + S3_CR + 0x95, 0xfd, + S3_CR + 0x96, 0xfd, + S3_CR + 0x97, 0xfd, + S3_CR + 0x98, 0xfd, + S3_CR + 0x99, 0xff, + S3_CR + 0x9a, 0xfd, + S3_CR + 0x9b, 0xff, + S3_CR + 0x9c, 0xfd, + S3_CR + 0x9d, 0xfd, + S3_CR + 0x9e, 0xfd, + S3_CR + 0x9f, 0xff, + S3_CR + 0xa0, 0x0f, +#if 0 + S3_CR + 0xa1, 0x00, + S3_CR + 0xa2, 0x00, + S3_CR + 0xa3, 0x00, + S3_CR + 0xa4, 0x55, +#endif + S3_CR + 0xa5, 0x09, + S3_CR + 0xa6, 0x20, +#if 0 + S3_CR + 0xa7, 0x00, + S3_CR + 0xa8, 0x00, + S3_CR + 0xa9, 0x00, + S3_CR + 0xaa, 0x00, + S3_CR + 0xab, 0x00, + S3_CR + 0xac, 0x00, + S3_CR + 0xad, 0x00, + S3_CR + 0xae, 0x00, + S3_CR + 0xaf, 0x00, + S3_CR + 0xb0, 0xff, +#endif + S3_CR + 0xb1, 0x0e, +#if 0 + S3_CR + 0xb2, 0x55, + S3_CR + 0xb3, 0x00, + S3_CR + 0xb4, 0x55, + S3_CR + 0xb5, 0x00, + S3_CR + 0xb6, 0x00, +#endif + S3_CR + 0xb7, 0x84, +#if 0 + S3_CR + 0xb8, 0xff, + S3_CR + 0xb9, 0xff, + S3_CR + 0xba, 0xff, + S3_CR + 0xbb, 0xff, + S3_CR + 0xbc, 0xff, + S3_CR + 0xbd, 0xff, + S3_CR + 0xbe, 0xff, + S3_CR + 0xbf, 0xff, +#endif + + S3_SR +0x15, 0x23, + 0xffff, 1, + S3_SR +0x15, 0x03, + 0xffff, 1, +}; + +#define S3_NUM_BIOS_REG (sizeof (s3BiosReg) / sizeof (s3BiosReg[0])) + +typedef struct _bios32Init { + VGA16 offset; + VGA32 value; +} s3Bios32Init; + +s3Bios32Init s3Bios32Reg[] = { + 0x8168, 0x00000000, + 0x816c, 0x00000001, + 0x8170, 0x00000000, + 0x8174, 0x00000000, + 0x8178, 0x00000000, + 0x817c, 0x00000000, +#if 0 + 0x8180, 0x00140000, + 0x8184, 0x00000000, + 0x8188, 0x00000000, + 0x8190, 0x00000000, + 0x8194, 0x00000000, + 0x8198, 0x00000000, + 0x819c, 0x00000000, + 0x81a0, 0x00000000, +#endif + 0x81c0, 0x00000000, + 0x81c4, 0x01fbffff, + 0x81c8, 0x00f7ffbf, + 0x81cc, 0x00f7ff00, + 0x81d0, 0x11ffff7f, + 0x81d4, 0x7fffffdf, + 0x81d8, 0xfdfff9ff, + 0x81e0, 0xfd000000, + 0x81e4, 0x00000000, + 0x81e8, 0x00000000, + 0x81ec, 0x00010000, + 0x81f0, 0x07ff057f, + 0x81f4, 0x07ff07ff, + 0x81f8, 0x00000000, + 0x81fc, 0x00000000, + 0x8200, 0x00000000, + 0x8204, 0x00000000, + 0x8208, 0x33000000, + 0x820c, 0x7f000000, + 0x8210, 0x80000000, + 0x8214, 0x00000000, + 0x8218, 0xffffffff, + 0x8300, 0xff007fef, + 0x8304, 0xfffdf7bf, + 0x8308, 0xfdfffbff, +}; + +#define S3_NUM_BIOS32_REG (sizeof (s3Bios32Reg) / sizeof (s3Bios32Reg[0])) + +/* + * Initialize the card precisely as the bios does + */ +s3DoBiosInit (KdCardInfo *card) +{ + S3CardInfo *s3c = card->driver; + CARD32 *regs = (CARD32 *) s3c->registers; + S3Vga *s3vga = &s3c->s3vga; + int r; + + for (r = 0; r < S3_NUM_BIOS_REG; r++) + { + if (s3BiosReg[r].reg == 0xffff) + sleep (s3BiosReg[r].value); + else + VgaStore (&s3vga->card, s3BiosReg[r].reg, s3BiosReg[r].value); + } + VgaStore (&s3vga->card, S3_SR+0x10, 0x22); + VgaStore (&s3vga->card, S3_SR+0x11, 0x44); + VgaStore (&s3vga->card, S3_SR+0x15, 0x01); + sleep (1); + VgaStore (&s3vga->card, S3_SR+0x15, 0x03); + VgaStore (&s3vga->card, S3_CR+0x6f, 0xff); + VgaStore (&s3vga->card, S3_CR+0x3f, 0x3f); + sleep (1); + VgaStore (&s3vga->card, S3_CR+0x3f, 0x00); + VgaStore (&s3vga->card, S3_CR+0x6f, 0xfe); + VgaInvalidate (&s3vga->card); + for (r = 0; r < S3_NUM_BIOS32_REG; r++) + regs[s3Bios32Reg[r].offset/4] = s3Bios32Reg[r].value; +} + +void +s3Preserve (KdCardInfo *card) +{ + S3CardInfo *s3c = card->driver; + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + S3Save *save = &s3c->save; + CARD8 t1, t2; + CARD8 *cursor_base; + CARD8 streams_mode; + + s3Save (s3vga); + if (!s3c->bios_initialized) + s3DoBiosInit (card); + + _s3SetBlank (s3, s3vga, TRUE); + /* + * Preserve the first part of the frame buffer which holds + * the text mode fonts and data + */ + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + memcpy (save->text_save, s3c->frameBuffer, S3_TEXT_SAVE); + /* + * Preserve graphics engine state + */ + save->alt_mix = s3->alt_mix; + save->write_mask = s3->write_mask; + save->fg = s3->fg; + save->bg = s3->bg; + /* + * Preserve streams processor state + */ + streams_mode = s3Get (s3vga, s3_streams_mode); + s3SetImm (s3vga, s3_streams_mode, 3); + save->global_bitmap_1 = s3->global_bitmap_1; + save->global_bitmap_2 = s3->global_bitmap_2; + save->adv_func_cntl = s3->adv_func_cntl; + save->primary_bitmap_1 = s3->primary_bitmap_1; + save->primary_bitmap_2 = s3->primary_bitmap_2; + save->secondary_bitmap_1 = s3->secondary_bitmap_1; + save->secondary_bitmap_2 = s3->secondary_bitmap_2; + save->primary_stream_control = s3->primary_stream_control; + save->blend_control = s3->blend_control; + save->primary_stream_addr_0 = s3->primary_stream_addr_0; + save->primary_stream_addr_1 = s3->primary_stream_addr_1; + save->primary_stream_stride = s3->primary_stream_stride; + save->primary_stream_xy = s3->primary_stream_xy; + save->primary_stream_size = s3->primary_stream_size; + save->primary_stream_mem = s3->primary_stream_mem; + save->secondary_stream_xy = s3->secondary_stream_xy; + save->secondary_stream_size = s3->secondary_stream_size; + save->streams_fifo = s3->streams_fifo; + s3SetImm (s3vga, s3_streams_mode, streams_mode); + _s3SetBlank (s3, s3vga, FALSE); +} + +/* + * Enable the card for rendering. Manipulate the initial settings + * of the card here. + */ +int s3CpuTimeout, s3AccelTimeout; + +void +s3SetGlobalBitmap (ScreenPtr pScreen, int ma) +{ + KdScreenPriv(pScreen); + s3ScreenInfo (pScreenPriv); + + if (s3s->current_ma != ma) + { + s3CardInfo (pScreenPriv); + S3Vga *s3vga = &s3c->s3vga; + S3Ptr s3 = s3c->s3; + CARD32 gb1, gb2; + int depth; + int length; + KdCheckSync (pScreen); + switch (s3s->fb[ma].accel_bpp) { + case 8: + case 24: + length = 0; + break; + case 16: + length = 1; + break; + case 32: + length = 3; + break; + } + s3SetImm (s3vga, s3_pixel_length, length); + gb1 = s3s->fb[ma].bitmap_offset; + gb2 = ((1 << 0) | + (0 << 2) | + (1 << 3) | + ((s3s->fb[ma].accel_stride >> 4) << 4) | + (s3s->fb[ma].accel_bpp << 16) | + (0 << 24) | + (1 << 28)); + s3->global_bitmap_1 = gb1; + s3->global_bitmap_2 = gb2; + s3->global_bitmap_2 = gb2; + s3s->current_ma = ma; + } +} + +Bool +s3Enable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + KdScreenInfo *screen = pScreenPriv->screen; + s3CardInfo (pScreenPriv); + s3ScreenInfo (pScreenPriv); + + S3Vga *s3vga = &s3c->s3vga; + S3Ptr s3 = s3c->s3; + int hactive, hblank, hfp, hbp; + int vactive, vblank, vfp, vbp; + int hsize; + + int h_total; + int h_display_end; + int h_blank_start; + int h_blank_end; + int h_sync_start; + int h_sync_end; + int h_screen_off; + int h_start_fifo_fetch; + + int primary_stream_l1[KD_MAX_FB]; + + int v_total; + int v_retrace_start; + int v_retrace_end; + int v_display_end; + int v_blank_start; + int v_blank_end; + int v_blank_start_adjust = 0; + int v_blank_end_adjust = 0; + + int h_blank_start_adjust = 0; + int h_blank_end_adjust = 0; + int h_sync_start_adjust = 0; + int h_sync_end_adjust = 0; + int h_start_fifo_fetch_adjust = 0; + int h_sync_extend; + int h_blank_extend; + int i; + CARD16 cursor_address; + const KdMonitorTiming *t; + int m, n, r; + Bool clock_double; + int cpu_timeout; + int accel_timeout; + int bytes_per_ms; + CARD32 control[2]; + int fb; + int ma; + + s3s->primary_depth = screen->fb[s3s->fbmap[0]].depth; + + s3s->use_streams = TRUE; + + t = KdFindMode (screen, s3ModeSupported); + + hfp = t->hfp; + hbp = t->hbp; + hblank = t->hblank; + hactive = t->horizontal; + + vfp = t->vfp; + vbp = t->vbp; + vblank = t->vblank; + vactive = t->vertical; + + + m = s3Get (s3vga, s3_dclk_m); + n = s3Get (s3vga, s3_dclk_n); + r = s3Get (s3vga, s3_dclk_r); +#define DEBUG_CLOCK +#ifdef DEBUG_CLOCK + fprintf (stderr, "old clock %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r)); +#endif + clock_double = FALSE; + s3GetClock (t->clock, &m, &n, &r, 511, 127, 4, 250000); + if (S3_CLOCK(m,n,r) > S3_MAX_CLOCK && !s3s->use_streams) + clock_double = TRUE; + s3Set (s3vga, s3_clock_select, 3); + s3Set (s3vga, s3_dclk_m, m); + s3Set (s3vga, s3_dclk_n, n); + s3Set (s3vga, s3_dclk_r, r); +#ifdef DEBUG_CLOCK + fprintf (stderr, "new clock %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r)); +#endif + + if (s3s->use_streams) + { + s3Set (s3vga, s3_streams_mode, 3); + s3Set (s3vga, s3_enable_l1_parameter, 1); + } + else + { + s3Set (s3vga, s3_streams_mode, 0); + s3Set (s3vga, s3_enable_l1_parameter, 0); + } + s3Set (s3vga, s3_flat_panel_output_control_1, 0); + s3Set (s3vga, s3_flat_panel_output_control_2, 0); + s3Set (s3vga, s3_select_graphics_mode, 1); + s3Set (s3vga, s3_enable_blinking, 0); + s3Set (s3vga, s3_enable_vga_16bit, 0); + s3Set (s3vga, s3_enhanced_memory_mapping, 1); + s3Set (s3vga, s3_enable_sff, 1); + s3Set (s3vga, s3_enable_2d_access, 1); + s3Set (s3vga, s3_2bk_cga, 1); + s3Set (s3vga, s3_4bk_hga, 1); + s3Set (s3vga, s3_v_total_double, 0); + s3Set (s3vga, s3_address_16k_wrap, 1); + s3Set (s3vga, s3_word_mode, 0); + s3Set (s3vga, s3_byte_mode, 1); + s3Set (s3vga, s3_hardware_reset, 1); + s3Set (s3vga, s3_max_scan_line, 0); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + s3Set (s3vga, s3_enable_2d_3d, 1); + s3Set (s3vga, s3_refresh_control, 1); + s3Set (s3vga, s3_disable_pci_read_bursts, 0); + s3Set (s3vga, s3_pci_disconnect_enable, 1); + s3Set (s3vga, s3_primary_load_control, 0); + s3Set (s3vga, s3_secondary_load_control, 0); + s3Set (s3vga, s3_pci_retry_enable, 1); + s3Set (s3vga, s3_enable_256, 1); + s3Set (s3vga, s3_border_select, 1); /* eliminate white border */ + s3SetImm (s3vga, s3_lock_palette, 0); /* unlock palette/border regs */ + s3Set (s3vga, s3_disable_v_retrace_int, 1); + if (t->hpol == KdSyncPositive) + s3Set (s3vga, s3_horz_sync_neg, 0); + else + s3Set (s3vga, s3_horz_sync_neg, 1); + if (t->vpol == KdSyncPositive) + s3Set (s3vga, s3_vert_sync_neg, 0); + else + s3Set (s3vga, s3_vert_sync_neg, 1); + + s3Set (s3vga, s3_dot_clock_8, 1); + s3Set (s3vga, s3_enable_write_plane, 0xf); + s3Set (s3vga, s3_extended_memory_access, 1); + s3Set (s3vga, s3_sequential_addressing_mode, 1); + s3Set (s3vga, s3_select_chain_4_mode, 1); + s3Set (s3vga, s3_linear_addressing_control, 1); + + s3Set (s3vga, s3_enable_gamma_correction, 0); + + s3Set (s3vga, s3_enable_8_bit_luts, 1); + + s3Set (s3vga, s3_dclk_invert, 0); + s3Set (s3vga, s3_enable_clock_double, 0); + s3Set (s3vga, s3_dclk_over_2, 0); + + s3Set (s3vga, s3_delay_h_enable, 0); + s3Set (s3vga, s3_sdclk_skew, 0); + + s3Set (s3vga, s3_dac_mask, 0xff); + +#if 0 +#ifdef DEBUG_CLOCK + m = s3Get (s3vga, s3_mclk_m); + n = s3Get (s3vga, s3_mclk_n); + r = s3Get (s3vga, s3_mclk_r); + fprintf (stderr, "old mclk %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r)); +#endif + + s3GetClock (125282, &m, &n, &r, 127, 31, 3, 250000); + +#ifdef DEBUG_CLOCK + fprintf (stderr, "new mclk %d, %d, %d (%d)\n", m, n, r,S3_CLOCK(m,n,r)); +#endif + + s3Set (s3vga, s3_mclk_m, m); + s3Set (s3vga, s3_mclk_n, n); + s3Set (s3vga, s3_mclk_r, r); + +#ifdef DEBUG_CLOCK + m = s3Get (s3vga, s3_eclk_m); + n = s3Get (s3vga, s3_eclk_n); + r = s3Get (s3vga, s3_eclk_r); + fprintf (stderr, "old eclk %d, %d, %d (%d)\n", m, n, r, S3_CLOCK(m,n,r)); +#endif + +#define S3_ECLK 125282 + + s3GetClock (S3_ECLK, &m, &n, &r, 127, 31, 3, 250000); + +#ifdef DEBUG_CLOCK + fprintf (stderr, "new eclk %d, %d, %d (%d)\n", m, n, r,S3_CLOCK(m,n,r)); +#endif + + s3Set (s3vga, s3_eclk_m, m); + s3Set (s3vga, s3_eclk_n, n); + s3Set (s3vga, s3_eclk_r, r); +#endif + + /* + * Compute character lengths for horizontal timing values + */ + hactive = screen->width / 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + /* + * Set pixel size, choose clock doubling mode + */ + + bytes_per_ms = 0; + + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + { + fb = s3s->fbmap[ma]; + s3s->fb[ma].accel_bpp = screen->fb[fb].bitsPerPixel; + s3s->fb[ma].accel_stride = screen->fb[fb].pixelStride; + s3s->fb[ma].bitmap_offset = screen->fb[fb].frameBuffer - s3c->frameBuffer; + switch (s3s->fb[ma].accel_bpp) { + case 8: + h_screen_off = hactive; + s3Set (s3vga, s3_pixel_length, 0); + s3Set (s3vga, s3_color_mode, 0); + control[ma] = 0; + /* + * Set up for double-pixel mode, switch color modes, + * divide the dclk and delay h blank by 2 dclks + */ + if (clock_double) + { + s3Set (s3vga, s3_color_mode, 1); + s3Set (s3vga, s3_dclk_over_2, 1); + s3Set (s3vga, s3_enable_clock_double, 1); + s3Set (s3vga, s3_h_skew, 1); + h_blank_start_adjust = -3; + h_blank_end_adjust = -4; + s3Set (s3vga, s3_border_select, 0); + } + break; + case 16: + h_screen_off = hactive * 2; + s3Set (s3vga, s3_pixel_length, 1); + if (screen->fb[fb].depth == 15) + control[ma] = 3 << 24; + else + control[ma] = 5 << 24; + if (clock_double) + { + if (screen->fb[fb].depth == 15) + s3Set (s3vga, s3_color_mode, 3); + else + s3Set (s3vga, s3_color_mode, 5); + s3Set (s3vga, s3_dclk_over_2, 1); + s3Set (s3vga, s3_enable_clock_double, 1); + s3Set (s3vga, s3_border_select, 0); + h_blank_start_adjust = 4; + h_blank_end_adjust = -4; + } + else + { + if (screen->fb[fb].depth == 15) + s3Set (s3vga, s3_color_mode, 2); + else + s3Set (s3vga, s3_color_mode, 4); + s3Set (s3vga, s3_dclk_over_2, 0); + s3Set (s3vga, s3_enable_clock_double, 0); + s3Set (s3vga, s3_delay_blank, 0); + } + break; + case 24: + control[ma] = 6 << 24; + h_screen_off = hactive * 3; + s3s->fb[ma].accel_bpp = 8; + s3s->fb[ma].accel_stride = screen->fb[fb].pixelStride * 3; + break; + case 32: + control[ma] = 7 << 24; + h_screen_off = hactive * 4; + s3Set (s3vga, s3_pixel_length, 3); + s3Set (s3vga, s3_color_mode, 0xd); + break; + } + bytes_per_ms += t->clock * (screen->fb[fb].bitsPerPixel / 8); + primary_stream_l1[ma] = (screen->width * screen->fb[fb].bitsPerPixel / (8 * 8)) - 1; + } + + /* + * X server starts frame buffer at top of memory + */ + s3Set (s3vga, s3_start_address, 0); + + /* + * Set various registers to avoid snow on the screen + */ + + fprintf (stderr, "bytes_per_ms %d\n", bytes_per_ms); + fprintf (stderr, "primary 0x%x master 0x%x command 0x%x lpb 0x%x cpu 0x%x 2d 0x%x\n", + s3Get (s3vga, s3_primary_stream_timeout), + s3Get (s3vga, s3_master_control_unit_timeout), + s3Get (s3vga, s3_command_buffer_timeout), + s3Get (s3vga, s3_lpb_timeout), + s3Get (s3vga, s3_cpu_timeout), + s3Get (s3vga, s3_2d_graphics_engine_timeout)); + + /* + * Test: + * accel x11perf -line500 + * cpu x11perf -circle500 + * + * cpu accel + * 1600x1200x32x85 (918000) 1 1 not enough + * 1600x1200x32x75 (810000) 3 2 + * 1600x1200x32x70 (756000) 4 3 + * 1600x1200x32x60 (648000) 6 5 + * + * 1280x1024x32x85 (630000) 6 4 + * 1280x1024x32x75 (540000) a 6 + * 1280x1024x32x60 (432000) 1f a + * + * 1152x900x32x85 (490000) a 6 + * 1152x900x32x75 (433000) 1f 8 + * 1152x900x32x70 (401000) 1f a + * 1152x900x32x66 (380000) 1f a + * + * 1024x768x32x85 (378000) 1f a + * 1024x768x32x75 (315000) 1f b + * 1024x768x32x70 (300000) 1f b + * 1024x768x32x60 (260000) 1f 12 + * + * 800x600x32x85 (225000) 1f 1a + * 800x600x32x72 (200000) 1f 1d + * 800x600x32x75 (198000) 1f 1d + * + * 1600x1200x16x85 (459000) 1f 8 + * 1600x1200x16x75 (405000) 1f a + * 1600x1200x16x70 (378000) 1f b + * 1600x1200x16x60 (324000) 1f f + * + * 1280x1024x16x85 (315000) 1f 12 + * 1280x1024x16x75 (270000) 1f 16 + * 1280x1024x16x60 (216000) 1f 1d + * + * 1600x1200x8x85 (229000) 1f 1f + * + */ + + if (s3CpuTimeout) + { + if (s3CpuTimeout < 0) + cpu_timeout = 0; + else + cpu_timeout = s3CpuTimeout; + if (s3AccelTimeout < 0) + accel_timeout = 0; + else if (s3AccelTimeout) + accel_timeout = s3AccelTimeout; + else + accel_timeout = s3CpuTimeout; + } + else if (bytes_per_ms >= 900000) + { + cpu_timeout = 0x01; + accel_timeout = 0x01; + } + else if (bytes_per_ms >= 800000) + { + cpu_timeout = 0x03; + accel_timeout = 0x02; + } + else if (bytes_per_ms >= 700000) + { + cpu_timeout = 0x04; + accel_timeout = 0x03; + } + else if (bytes_per_ms >= 600000) + { + cpu_timeout = 0x06; + accel_timeout = 0x04; + } + else if (bytes_per_ms >= 475000) + { + cpu_timeout = 0x0a; + accel_timeout = 0x06; + } + else if (bytes_per_ms >= 425000) + { + cpu_timeout = 0x1f; + accel_timeout = 0x8; + } + else if (bytes_per_ms >= 300000) + { + cpu_timeout = 0x1f; + accel_timeout = 0x0a; + } + else if (bytes_per_ms >= 250000) + { + cpu_timeout = 0x1f; + accel_timeout = 0x12; + } + else if (bytes_per_ms >= 200000) + { + cpu_timeout = 0x1f; + accel_timeout = 0x1a; + } + else + { + cpu_timeout = 0x1f; + accel_timeout = 0x1f; + } + + fprintf (stderr, "cpu 0x%x accel 0x%x\n", cpu_timeout, accel_timeout); + + s3Set (s3vga, s3_primary_stream_timeout, 0xc0); + s3Set (s3vga, s3_master_control_unit_timeout, 0xf); + s3Set (s3vga, s3_command_buffer_timeout, 0x1f); + s3Set (s3vga, s3_lpb_timeout, 0xf); + s3Set (s3vga, s3_2d_graphics_engine_timeout, accel_timeout); + s3Set (s3vga, s3_cpu_timeout, cpu_timeout); + + s3Set (s3vga, s3_fifo_fetch_timing, 1); + s3Set (s3vga, s3_fifo_drain_delay, 2); + + /* + * Compute horizontal register values from timings + */ + h_total = hactive + hblank - 5; + h_display_end = hactive - 1; + + h_sync_start = hactive + hfp + h_sync_start_adjust; + h_sync_end = hactive + hblank - hbp + h_sync_end_adjust; + /* + * pad the blank values narrow a bit and use the border_select to + * eliminate the remaining border; don't know why, but it doesn't + * work in the documented fashion + */ + h_blank_start = hactive + 1 + h_blank_start_adjust; + h_blank_end = hactive + hblank - 2 + h_blank_end_adjust; + /* + * The manual says h_total - 5, but the + * bios does differently... + */ + if (screen->width >= 1600) + h_start_fifo_fetch = h_total - 24; + else if (screen->width >= 1280) + h_start_fifo_fetch = h_total - 19; + else if (screen->width >= 1024) + h_start_fifo_fetch = h_total - 14; + else if (screen->width >= 800) + h_start_fifo_fetch = h_total - 10; + else + h_start_fifo_fetch = h_total - 5; + + h_start_fifo_fetch += h_start_fifo_fetch_adjust; + if (h_blank_end - h_blank_start >= 0x40) + h_blank_extend = 1; + else + h_blank_extend = 0; + + if (h_sync_end - h_sync_start >= 0x20) + h_sync_extend = 1; + else + h_sync_extend = 0; + +#ifdef DEBUG + fprintf (stderr, "h_total %d h_display_end %d\n", + h_total, h_display_end); + fprintf (stderr, "h_sync_start %d h_sync_end %d h_sync_extend %d\n", + h_sync_start, h_sync_end, h_sync_extend); + fprintf (stderr, "h_blank_start %d h_blank_end %d h_blank_extend %d\n", + h_blank_start, h_blank_end, h_blank_extend); +#endif + + s3Set (s3vga, s3_h_total, h_total); + s3Set (s3vga, s3_h_display_end, h_display_end); + s3Set (s3vga, s3_h_blank_start, h_blank_start); + s3Set (s3vga, s3_h_blank_end, h_blank_end); + s3Set (s3vga, s3_h_sync_start, h_sync_start); + s3Set (s3vga, s3_h_sync_end, h_sync_end); + s3Set (s3vga, s3_screen_offset, h_screen_off); + s3Set (s3vga, s3_h_start_fifo_fetch, h_start_fifo_fetch); + s3Set (s3vga, s3_h_sync_extend, h_sync_extend); + s3Set (s3vga, s3_h_blank_extend, h_blank_extend); + + s3Set (s3vga, s3_dac_power_saving_disable, 0); + s3Set (s3vga, s3_dac_power_up_time, hactive + hblank); + + s3Set (s3vga, s3_primary_stream_l1, primary_stream_l1[0]); + + s3Set (s3vga, s3_streams_fifo_delay, 0); + + v_total = vactive + vblank - 2; + v_display_end = vactive - 1; + + v_blank_start = vactive - 1 + v_blank_start_adjust; + v_blank_end = v_blank_start + vblank - 1 + v_blank_end_adjust; + + v_retrace_start = vactive + vfp; + v_retrace_end = vactive + vblank - vbp; + + s3Set (s3vga, s3_v_total, v_total); + s3Set (s3vga, s3_v_retrace_start, v_retrace_start); + s3Set (s3vga, s3_v_retrace_end, v_retrace_end); + s3Set (s3vga, s3_v_display_end, v_display_end); + s3Set (s3vga, s3_v_blank_start, v_blank_start); + s3Set (s3vga, s3_v_blank_end, v_blank_end); + + if (vactive >= 1024) + s3Set (s3vga, s3_line_compare, 0x7ff); + else + s3Set (s3vga, s3_line_compare, 0x3ff); + + /* + * Set cursor + */ + if (!screen->softCursor) + { + cursor_address = (s3s->cursor_base - s3c->frameBuffer) / 1024; + + s3Set (s3vga, s3_cursor_address, cursor_address); + s3Set (s3vga, s3_cursor_ms_x11, 0); + s3Set (s3vga, s3_cursor_enable, 1); + } + else + s3Set (s3vga, s3_cursor_enable, 0); + +#define MAKE_GBF(bds,be,stride,bpp,tile) (\ + ((bds) << 0) | \ + ((be) << 3) | \ + ((stride) << 4) | \ + ((bpp) << 16) | \ + ((tile) << 24)) + /* + * Set accelerator + */ + switch (screen->width) { +#if 0 + case 640: s3Set (s3vga, s3_ge_screen_width, 1); break; + case 800: s3Set (s3vga, s3_ge_screen_width, 2); break; + case 1024: s3Set (s3vga, s3_ge_screen_width, 0); break; + case 1152: s3Set (s3vga, s3_ge_screen_width, 4); break; + case 1280: s3Set (s3vga, s3_ge_screen_width, 3); break; + case 1600: s3Set (s3vga, s3_ge_screen_width, 6); break; +#endif + default: + s3Set (s3vga, s3_ge_screen_width, 7); /* use global bitmap descriptor */ + } + +#if 0 + crtc->l_parm_0_7 = screen->width / 4; /* Undocumented. */ +#endif + + /* + * Set DPMS to normal + */ + s3Set (s3vga, s3_hsync_control, 0); + s3Set (s3vga, s3_vsync_control, 0); + + _s3SetBlank (s3, s3vga, TRUE); + if (s3s->use_streams) + s3Set (s3vga, s3_primary_stream_definition, 1); + else + s3Set (s3vga, s3_primary_stream_definition, 0); + + VgaFlush(&s3vga->card); + VgaSetImm (&s3vga->card, s3_clock_load_imm, 1); + VgaSetImm(&s3vga->card, s3_clock_load_imm, 0); + + + if (s3s->use_streams) + { + fb = s3s->fbmap[0]; + s3->primary_stream_control = control[0]; + s3->primary_stream_addr_0 = + s3->primary_stream_addr_1 = s3s->fb[0].bitmap_offset; + s3->primary_stream_stride = screen->fb[fb].byteStride; + s3->primary_stream_xy = (1 << 16) | 1; + s3->primary_stream_size = ((screen->fb[fb].pixelStride - 1) << 16) | screen->height; + s3->primary_stream_mem = (screen->fb[fb].byteStride * screen->height) / 8 - 1; + if (s3s->fbmap[1] >= 0) + { + fb = s3s->fbmap[1]; + s3->blend_control = 5 << 24; + if (s3s->fb[0].accel_bpp == 8) + s3->chroma_key_control = 0x33000000 | s3s->fb[0].chroma_key; + else + s3->chroma_key_control = 0x13010101; + s3->secondary_stream_control = control[1] | screen->width; + s3->secondary_stream_h_scale = (1 << 15); + s3->color_adjustment = 0; + s3->secondary_stream_vscale = (1 << 15); + s3->secondary_stream_vinit = 0; + s3->secondary_stream_mbuf = 0; + s3->secondary_stream_addr_0 = + s3->secondary_stream_addr_1 = s3s->fb[1].bitmap_offset; + s3->secondary_stream_stride = screen->fb[fb].byteStride; + s3->secondary_stream_scount = screen->height; + s3->secondary_stream_xy = (1 << 16) | 1; + s3->secondary_stream_size = ((screen->fb[fb].pixelStride - 1) << 16) | screen->height; + s3->secondary_stream_mem = (1 << 22) | ((screen->fb[fb].byteStride * screen->height) / 8 - 1); + } + else + { + s3->blend_control = 1 << 24; + s3->secondary_stream_xy = 0x07ff07ff; + s3->secondary_stream_size = 0x00010001; + } + s3->streams_fifo = (0x20 << 11) | (0x20 << 5) | 0x2; + } + s3->mult_misc_read_sel = (((1 << 9) | + (1 << 11) | + (0xe << 12)) | + (((0xe << 0) | + (0xf << 12)) << 16)); + + s3->cmd_overflow_buf_ptr = (1 << 3); + s3->bci_power_management = (1 << 9); + s3->adv_func_cntl = (3 << 8) | (1 << 4) | (1 << 2) | 1; + s3->primary_bitmap_1 = 0; + s3->primary_bitmap_2 = 0; + s3->secondary_bitmap_1 = 0; + s3->secondary_bitmap_2 = 0; + s3s->current_ma = -1; + _s3SetBlank (s3, s3vga, FALSE); +#if 0 + { + VGA16 r; + static CARD32 streams[][2] = { + /* PCI registers */ + 0x8000, 0x8024, + 0x802c, 0x8034, + 0x803c, 0x8040, +#if 0 + 0x8080, 0x808c, /* AGP */ +#endif + 0x80dc, 0x80e0, + + /* 2D registers */ + 0x8168, 0x8188, + 0x8190, 0x81a0, + 0x81c0, 0x81d8, + 0x81e0, 0x8218, + 0x8300, 0x8308, + 0x8504, 0x8510, + + /* LPB/VIP registers */ + 0xff00, 0xff18, + 0xff20, 0xff38, + 0xff40, 0xff40, + 0xff70, 0xff78, + 0xff8c, 0xffa0, + +#if 0 + /* 3D registers */ + 0x48508, 0x48508, + 0x48528, 0x48528, + 0x48548, 0x48548, + 0x48584, 0x485f0, +#endif + + /* motion compensation registers */ + 0x48900, 0x48924, +#if 0 + 0x48928, 0x48928, +#endif + + /* Mastered data transfer registers */ + 0x48a00, 0x48a1c, + + /* configuation/status registers */ + 0x48c00, 0x48c18, + 0x48c20, 0x48c24, + 0x48c40, 0x48c50, + 0x48c60, 0x48c64, + + 0, 0, + }; +#ifdef PHOENIX +#undef stderr +#define stderr stdout +#endif + CARD32 *regs = (CARD32 *) s3c->registers; + int i; + CARD32 reg; + + + for (r = S3_SR + 0; r < S3_SR + S3_NSR; r++) + fprintf (stderr, "SR%02x = %02x\n", r-S3_SR, VgaFetch (&s3vga->card, r)); + for (r = S3_GR + 0; r < S3_GR + S3_NGR; r++) + fprintf (stderr, "GR%02x = %02x\n", r-S3_GR, VgaFetch (&s3vga->card, r)); + for (r = S3_AR + 0; r < S3_AR + S3_NAR; r++) + fprintf (stderr, "AR%02x = %02x\n", r-S3_AR, VgaFetch (&s3vga->card, r)); + for (r = S3_CR + 0; r < S3_CR + S3_NCR; r++) + fprintf (stderr, "CR%02x = %02x\n", r-S3_CR, VgaFetch (&s3vga->card, r)); + for (r = S3_DAC + 0; r < S3_DAC + S3_NDAC; r++) + fprintf (stderr, "DAC%02x = %02x\n", r-S3_DAC, VgaFetch (&s3vga->card, r)); + fprintf (stderr, "MISC_OUT = %02x\n", VgaFetch (&s3vga->card, S3_MISC_OUT)); + fprintf (stderr, "INPUT_STATUS = %02x\n", VgaFetch (&s3vga->card, S3_INPUT_STATUS_1)); + + + for (i = 0; streams[i][0]; i++) + { + for (reg = streams[i][0]; reg <= streams[i][1]; reg += 4) + fprintf (stderr, "0x%4x: 0x%08x\n", reg, regs[reg/4]); + } + } +#endif + return TRUE; +} + +void +s3Disable (ScreenPtr pScreen) +{ +} + +void +s3Restore (KdCardInfo *card) +{ + S3CardInfo *s3c = card->driver; + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + S3Save *save = &s3c->save; + CARD8 *cursor_base; + CARD8 streams_mode; + + _s3SetBlank (s3, s3vga, TRUE); + /* streams processor state */ + streams_mode = s3Get (s3vga, s3_streams_mode); + s3SetImm (s3vga, s3_streams_mode, 3); + s3->global_bitmap_1 = save->global_bitmap_1; + s3->global_bitmap_2 = save->global_bitmap_2; + s3->adv_func_cntl = save->adv_func_cntl; + s3->primary_bitmap_1 = save->primary_bitmap_1; + s3->primary_bitmap_2 = save->primary_bitmap_2; + s3->secondary_bitmap_1 = save->secondary_bitmap_1; + s3->secondary_bitmap_2 = save->secondary_bitmap_2; + s3->primary_stream_control = save->primary_stream_control; + s3->blend_control = save->blend_control; + s3->primary_stream_addr_0 = save->primary_stream_addr_0; + s3->primary_stream_addr_0 = save->primary_stream_addr_0; + s3->primary_stream_stride = save->primary_stream_stride; + s3->primary_stream_xy = save->primary_stream_xy; + s3->primary_stream_size = save->primary_stream_size; + s3->primary_stream_mem = save->primary_stream_mem; + s3->secondary_stream_xy = save->secondary_stream_xy; + s3->secondary_stream_size = save->secondary_stream_size; + s3->streams_fifo = save->streams_fifo; + s3SetImm (s3vga, s3_streams_mode, streams_mode); + /* graphics engine state */ + s3->alt_mix = save->alt_mix; + s3->write_mask = save->write_mask; + s3->fg = save->fg; + s3->bg = save->bg; + /* XXX should save and restore real values? */ + s3->scissors_tl = 0x00000000; + s3->scissors_br = 0x0fff0fff; + + VgaRestore (&s3vga->card); + s3Set (s3vga, s3_linear_window_size, 3); + s3Set (s3vga, s3_enable_linear, 1); + VgaFlush (&s3vga->card); + memcpy (s3c->frameBuffer, save->text_save, S3_TEXT_SAVE); + s3Reset (s3vga); + _s3SetBlank (s3, s3vga, FALSE); +} + +void +_s3SetSync (S3CardInfo *s3c, int hsync, int vsync) +{ + /* this abuses the macros defined to access the crtc structure */ + S3Ptr s3 = s3c->s3; + S3Vga *s3vga = &s3c->s3vga; + + s3Set (s3vga, s3_hsync_control, hsync); + s3Set (s3vga, s3_vsync_control, vsync); + VgaFlush (&s3vga->card); +} + +Bool +s3DPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + S3Vga *s3vga = &s3c->s3vga; + + switch (mode) { + case KD_DPMS_NORMAL: + _s3SetSync (s3c, 0, 0); + _s3SetBlank (s3c->s3, s3vga, FALSE); + break; + case KD_DPMS_STANDBY: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 1, 0); + break; + case KD_DPMS_SUSPEND: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 0, 1); + break; + case KD_DPMS_POWERDOWN: + _s3SetBlank (s3c->s3, s3vga, TRUE); + _s3SetSync (s3c, 1, 1); + break; + } + return TRUE; +} + +Bool +s3InitScreen(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdCardInfo *card = pScreenPriv->card; + KdScreenInfo *screen = pScreenPriv->screen; + s3CardInfo (pScreenPriv); + s3ScreenInfo (pScreenPriv); + int ma, fb; + + if (screen->fb[1].depth) + { + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + { + fb = s3s->fbmap[ma]; + pScrPriv->layer[fb].key = s3s->fb[ma].chroma_key; + } + } + return TRUE; +} + +void +s3ScreenFini (KdScreenInfo *screen) +{ + S3ScreenInfo *s3s = (S3ScreenInfo *) screen->driver; + + xfree (s3s); + screen->driver = 0; +} + +void +s3CardFini (KdCardInfo *card) +{ + S3CardInfo *s3c = (S3CardInfo *) card->driver; + + KdUnmapDevice (s3c->frameBuffer, s3c->memory); + KdUnmapDevice (s3c->registers, sizeof (S3) + PACKED_OFFSET); + xfree (s3c); + card->driver = 0; +} + +KdCardFuncs s3Funcs = { + s3CardInit, + s3ScreenInit, + s3InitScreen, + s3Preserve, + s3Enable, + s3DPMS, + s3Disable, + s3Restore, + s3ScreenFini, + s3CardFini, + s3CursorInit, + s3CursorEnable, + s3CursorDisable, + s3CursorFini, + s3RecolorCursor, + s3DrawInit, + s3DrawEnable, + s3DrawSync, + s3DrawDisable, + s3DrawFini, + s3GetColors, + s3PutColors, +}; diff --git a/xserver/hw/kdrive/savage/s3.h b/xserver/hw/kdrive/savage/s3.h new file mode 100644 index 000000000..d8db0ebbf --- /dev/null +++ b/xserver/hw/kdrive/savage/s3.h @@ -0,0 +1,533 @@ +/* + * 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. + */ + +#ifndef _S3_H_ +#define _S3_H_ + +#include "kdrive.h" +#include "s3reg.h" + +/* VESA Approved Register Definitions */ + +/* + * Linear Addressing 000 0000 - 0ff ffff (16m) + * Image data transfer 100 0000 - 100 7fff (32k) + * PCI config 100 8000 - 100 8043 + * Packed enhanced regs 100 8100 - 100 814a + * Streams regs 100 8180 - 100 81ff + * Current Y pos 100 82e8 + * CRT VGA 3b? regs 100 83b0 - 100 83bf + * CRT VGA 3c? regs 100 83c0 - 100 83cf + * CRT VGA 3d? regs 100 83d0 - 100 83df + * Subsystem status (42e8h) 100 8504 + * Advanced function (42e8h) 100 850c + * Enhanced regs 100 86e8 - 100 eeea + * Local peripheral bus 100 ff00 - 100 ff5c + * + * We don't care about the image transfer or PCI regs, so + * this structure starts at the packed enhanced regs + */ + +typedef volatile CARD32 VOL32; +typedef volatile CARD16 VOL16; +typedef volatile CARD8 VOL8; + +typedef volatile struct _s3 { + VOL32 alt_curxy; /* 8100 */ + VOL32 _pad0; /* 8104 */ + VOL32 alt_step; /* 8108 */ + VOL32 _pad1; /* 810c */ + VOL32 err_term; /* 8110 */ + VOL32 _pad2; /* 8114 */ + VOL32 cmd_gp_stat; /* 8118 */ + VOL32 short_stroke; /* 811c */ + VOL32 bg; /* 8120 */ + VOL32 fg; /* 8124 */ + VOL32 write_mask; /* 8128 */ + VOL32 read_mask; /* 812c */ + VOL32 color_cmp; /* 8130 */ + VOL32 alt_mix; /* 8134 */ + VOL32 scissors_tl; /* 8138 */ + VOL32 scissors_br; /* 813c */ +#if 0 + VOL16 pix_cntl; /* 8140 */ + VOL16 mult_misc2; /* 8142 */ +#else + VOL32 pix_cntl_mult_misc2; /* 8140 */ +#endif + VOL32 mult_misc_read_sel; /* 8144 */ + VOL32 alt_pcnt; /* 8148 min_axis_pcnt, maj_axis_pcnt */ + VOL8 _pad3a[0x1c]; /* 814c */ + VOL32 global_bitmap_1; /* 8168 */ + VOL32 global_bitmap_2; /* 816c */ + VOL32 primary_bitmap_1; /* 8170 */ + VOL32 primary_bitmap_2; /* 8174 */ + VOL32 secondary_bitmap_1; /* 8178 */ + VOL32 secondary_bitmap_2; /* 817c */ + VOL32 primary_stream_control; /* 8180 */ + VOL32 chroma_key_control; /* 8184 */ + VOL32 genlocking_control; /* 8188 */ + VOL8 _pad3b[0x4]; /* 818c */ + VOL32 secondary_stream_control; /* 8190 */ + VOL32 chroma_key_upper_bound; /* 8194 */ + VOL32 secondary_stream_h_scale; /* 8198 */ + VOL32 color_adjustment; /* 819c */ + VOL32 blend_control; /* 81a0 */ + VOL8 _pad3c[0x1c]; /* 81a4 */ + VOL32 primary_stream_addr_0; /* 81c0 */ + VOL32 primary_stream_addr_1; /* 81c4 */ + VOL32 primary_stream_stride; /* 81c8 */ + VOL32 secondary_stream_mbuf; /* 81cc */ + VOL32 secondary_stream_addr_0;/* 81d0 */ + VOL32 secondary_stream_addr_1;/* 81d4 */ + VOL32 secondary_stream_stride;/* 81d8 */ + VOL8 _pad81dc[4]; /* 81dc */ + VOL32 secondary_stream_vscale;/* 81e0 */ + VOL32 secondary_stream_vinit; /* 81e4 */ + VOL32 secondary_stream_scount;/* 81e8 */ + VOL32 streams_fifo; /* 81ec */ + VOL32 primary_stream_xy; /* 81f0 */ + VOL32 primary_stream_size; /* 81f4 */ + VOL32 secondary_stream_xy; /* 81f8 */ + VOL32 secondary_stream_size; /* 81fc */ + VOL8 _pad8200[0xe8]; /* 8200 */ + VOL32 cur_y; /* 82e8 */ + VOL8 _pad4[0x14]; /* 82ec */ + VOL32 primary_stream_mem; /* 8300 */ + VOL32 secondary_stream_mem; /* 8304 */ + VOL8 _pad8308[0xD2]; /* 8308 */ + VOL8 input_status_1; /* 83da */ + VOL8 _pad83db[0x131]; /* 83db */ + VOL32 adv_func_cntl; /* 850c */ + VOL8 _pad8510[0x5dd8]; /* 8510 */ + VOL32 pix_trans; /* e2e8 */ + VOL8 _pade2ec[0x3a92c]; /* e2ec */ + VOL32 cmd_overflow_buf_ptr; /* 48c18 */ + VOL8 _pad48c1c[0x8]; /* 48c1c */ + VOL32 bci_power_management; /* 48c24 */ + VOL8 _pad48c28[0x38]; /* 48c28 */ + VOL32 alt_status_0; /* 48c60 */ + VOL32 alt_status_1; /* 48c64 */ +} S3, *S3Ptr; + +#define VGA_STATUS_1_DTM 0x01 +#define VGA_STATUS_1_VSY 0x08 + +#define DAC_MASK 0x03c6 +#define DAC_R_INDEX 0x03c7 +#define DAC_W_INDEX 0x03c8 +#define DAC_DATA 0x03c9 +#define DISP_STAT 0x02e8 +#define H_TOTAL 0x02e8 +#define H_DISP 0x06e8 +#define H_SYNC_STRT 0x0ae8 +#define H_SYNC_WID 0x0ee8 +#define V_TOTAL 0x12e8 +#define V_DISP 0x16e8 +#define V_SYNC_STRT 0x1ae8 +#define V_SYNC_WID 0x1ee8 +#define DISP_CNTL 0x22e8 +#define ADVFUNC_CNTL 0x4ae8 +#define SUBSYS_STAT 0x42e8 +#define SUBSYS_CNTL 0x42e8 +#define ROM_PAGE_SEL 0x46e8 +#define CUR_Y 0x82e8 +#define CUR_X 0x86e8 +#define DESTY_AXSTP 0x8ae8 +#define DESTX_DIASTP 0x8ee8 +#define ERR_TERM 0x92e8 +#define MAJ_AXIS_PCNT 0x96e8 +#define GP_STAT 0x9ae8 +#define CMD 0x9ae8 +#define SHORT_STROKE 0x9ee8 +#define BKGD_COLOR 0xa2e8 +#define FRGD_COLOR 0xa6e8 +#define WRT_MASK 0xaae8 +#define RD_MASK 0xaee8 +#define COLOR_CMP 0xb2e8 +#define BKGD_MIX 0xb6e8 +#define FRGD_MIX 0xbae8 +#define MULTIFUNC_CNTL 0xbee8 +#define MIN_AXIS_PCNT 0x0000 +#define SCISSORS_T 0x1000 +#define SCISSORS_L 0x2000 +#define SCISSORS_B 0x3000 +#define SCISSORS_R 0x4000 +#define MEM_CNTL 0x5000 +#define PATTERN_L 0x8000 +#define PATTERN_H 0x9000 +#define PIX_CNTL 0xa000 +#define CONTROL_MISC2 0xd000 +#define PIX_TRANS 0xe2e8 + +/* Advanced Function Control Regsiter */ +#define CLKSEL 0x0004 +#define DISABPASSTHRU 0x0001 + +/* Graphics Processor Status Register */ + +#define GPNSLOT 13 + +#define GPBUSY_1 0x0080 +#define GPBUSY_2 0x0040 +#define GPBUSY_3 0x0020 +#define GPBUSY_4 0x0010 +#define GPBUSY_5 0x0008 +#define GPBUSY_6 0x0004 +#define GPBUSY_7 0x0002 +#define GPBUSY_8 0x0001 +#define GPBUSY_9 0x8000 +#define GPBUSY_10 0x4000 +#define GPBUSY_11 0x2000 +#define GPBUSY_12 0x1000 +#define GPBUSY_13 0x0800 + +#define GPEMPTY 0x0400 +#define GPBUSY 0x0200 +#define DATDRDY 0x0100 + +/* Command Register */ +#define CMD_NOP 0x0000 +#define CMD_LINE 0x2000 +#define CMD_RECT 0x4000 +#define CMD_RECTV1 0x6000 +#define CMD_RECTV2 0x8000 +#define CMD_LINEAF 0xa000 +#define CMD_BITBLT 0xc000 +#define CMD_PATBLT 0xe000 +#define CMD_OP_MSK 0xe000 +#define BYTSEQ 0x1000 +#define _32BITNOPAD 0x0600 +#define _32BIT 0x0400 +#define _16BIT 0x0200 +#define _8BIT 0x0000 +#define PCDATA 0x0100 +#define INC_Y 0x0080 +#define YMAJAXIS 0x0040 +#define INC_X 0x0020 +#define DRAW 0x0010 +#define LINETYPE 0x0008 +#define LASTPIX 0x0004 /* Draw last pixel in line */ +#define PLANAR 0x0002 +#define WRTDATA 0x0001 + +/* Background Mix Register */ +#define BSS_BKGDCOL 0x0000 +#define BSS_FRGDCOL 0x0020 +#define BSS_PCDATA 0x0040 +#define BSS_BITBLT 0x0060 + +/* Foreground Mix Register */ +#define FSS_BKGDCOL 0x0000 +#define FSS_FRGDCOL 0x0020 +#define FSS_PCDATA 0x0040 +#define FSS_BITBLT 0x0060 + +/* The Mixes */ +#define MIX_MASK 0x001f + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +#define MIX_MIN 0x0010 +#define MIX_DST_MINUS_SRC 0x0011 +#define MIX_SRC_MINUS_DST 0x0012 +#define MIX_PLUS 0x0013 +#define MIX_MAX 0x0014 +#define MIX_HALF__DST_MINUS_SRC 0x0015 +#define MIX_HALF__SRC_MINUS_DST 0x0016 +#define MIX_AVERAGE 0x0017 +#define MIX_DST_MINUS_SRC_SAT 0x0018 +#define MIX_SRC_MINUS_DST_SAT 0x001a +#define MIX_HALF__DST_MINUS_SRC_SAT 0x001c +#define MIX_HALF__SRC_MINUS_DST_SAT 0x001e +#define MIX_AVERAGE_SAT 0x001f + +/* Pixel Control Register */ +#define MIXSEL_FRGDMIX 0x0000 +#define MIXSEL_PATT 0x0040 +#define MIXSEL_EXPPC 0x0080 +#define MIXSEL_EXPBLT 0x00c0 +#define COLCMPOP_F 0x0000 +#define COLCMPOP_T 0x0008 +#define COLCMPOP_GE 0x0010 +#define COLCMPOP_LT 0x0018 +#define COLCMPOP_NE 0x0020 +#define COLCMPOP_EQ 0x0028 +#define COLCMPOP_LE 0x0030 +#define COLCMPOP_GT 0x0038 +#define PLANEMODE 0x0004 + +/* Multifunction Control Misc 8144 */ +#define MISC_DST_BA_0 (0x0 << 0) +#define MISC_DST_BA_1 (0x1 << 0) +#define MISC_DST_BA_2 (0x2 << 0) +#define MISC_DST_BA_3 (0x3 << 0) +#define MISC_SRC_BA_0 (0x0 << 2) +#define MISC_SRC_BA_1 (0x1 << 2) +#define MISC_SRC_BA_2 (0x2 << 2) +#define MISC_SRC_BA_3 (0x3 << 2) +#define MISC_RSF (1 << 4) +#define MISC_EXT_CLIP (1 << 5) +#define MISC_SRC_NE (1 << 7) +#define MISC_ENB_CMP (1 << 8) +#define MISC_32B (1 << 9) +#define MISC_DC (1 << 11) +#define MISC_INDEX_E (0xe << 12) + +#define S3_SAVAGE4_SLOTS 0x0001ffff +#define S3_SAVAGE4_2DI 0x00800000 + +#define _s3WaitLoop(s3,mask,value){ \ + int __loop = 1000000; \ + while (((s3)->alt_status_0 & (mask)) != (value)) \ + if (--__loop == 0) { \ + ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \ + break; \ + } \ +} + +#define S3_SAVAGE4_ROOM 10 + +#define _s3WaitSlots(s3,n) { \ + int __loop = 1000000; \ + while (((s3)->alt_status_0 & S3_SAVAGE4_SLOTS) >= S3_SAVAGE4_ROOM-(n)) \ + if (--__loop == 0) { \ + ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \ + break; \ + } \ +} + +#define _s3WaitEmpty(s3) _s3WaitLoop(s3,S3_SAVAGE4_SLOTS, 0) +#define _s3WaitIdleEmpty(s3) _s3WaitLoop(s3,S3_SAVAGE4_SLOTS|S3_SAVAGE4_2DI, S3_SAVAGE4_2DI) +#define _s3WaitIdle(s3) _s3WaitLoop(s3,S3_SAVAGE4_2DI, S3_SAVAGE4_2DI) + +typedef struct _s3Cursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; +} S3Cursor; + +typedef struct _s3PatternCache { + int id; + int x, y; +} S3PatternCache; + +typedef struct _s3Patterns { + S3PatternCache *cache; + int ncache; + int last_used; + int last_id; +} S3Patterns; + +#define S3_CLOCK_REF 14318 /* KHz */ + +#define S3_CLOCK(m,n,r) ((S3_CLOCK_REF * ((m) + 2)) / (((n) + 2) * (1 << (r)))) + +#define S3_MAX_CLOCK 150000 /* KHz */ + +typedef struct _s3Timing { + /* label */ + int horizontal; + int vertical; + int rate; + /* horizontal timing */ + int hfp; /* front porch */ + int hbp; /* back porch */ + int hblank; /* blanking */ + /* vertical timing */ + int vfp; /* front porch */ + int vbp; /* back porch */ + int vblank; /* blanking */ + /* clock values */ + int dac_m; + int dac_n; + int dac_r; +} S3Timing; + +#define S3_TEXT_SAVE (64*1024) + +typedef struct _s3Save { + CARD8 cursor_fg; + CARD8 cursor_bg; + CARD8 lock1; + CARD8 lock2; + CARD8 locksrtc; + CARD8 clock_mode; + CARD32 alt_mix; + CARD32 write_mask; + CARD32 fg; + CARD32 bg; + CARD32 global_bitmap_1; + CARD32 global_bitmap_2; + CARD32 adv_func_cntl; + CARD32 primary_bitmap_1; + CARD32 primary_bitmap_2; + CARD32 secondary_bitmap_1; + CARD32 secondary_bitmap_2; + CARD32 primary_stream_control; + CARD32 blend_control; + CARD32 primary_stream_addr_0; + CARD32 primary_stream_addr_1; + CARD32 primary_stream_stride; + CARD32 primary_stream_xy; + CARD32 primary_stream_size; + CARD32 primary_stream_mem; + CARD32 secondary_stream_xy; + CARD32 secondary_stream_size; + CARD32 streams_fifo; + CARD8 text_save[S3_TEXT_SAVE]; +} S3Save; + +typedef struct _s3CardInfo { + S3Ptr s3; /* pointer to register structure */ + int memory; /* amount of memory */ + CARD8 *frameBuffer; /* pointer to frame buffer */ + CARD8 *registers; /* pointer to register map */ + S3Vga s3vga; + S3Save save; + Bool need_sync; + Bool bios_initialized; /* whether the bios has been run */ +} S3CardInfo; + +typedef struct _s3FbInfo { + CARD8 *offscreen; /* pointer to offscreen area */ + int offscreen_y; /* top y coordinate of offscreen area */ + int offscreen_x; /* top x coordinate of offscreen area */ + int offscreen_width; /* width of offscreen area */ + int offscreen_height; /* height of offscreen area */ + S3Patterns patterns; + CARD32 bitmap_offset; + int accel_stride; + int accel_bpp; + CARD32 chroma_key; +} S3FBInfo; + +typedef struct _s3ScreenInfo { + CARD8 *cursor_base; /* pointer to cursor area */ + S3Cursor cursor; + Bool managing_border; + Bool use_streams; + int primary_depth; + int current_ma; + CARD32 border_pixel; + S3FBInfo fb[KD_MAX_FB]; + RegionRec region[KD_MAX_FB]; + int fbmap[KD_MAX_FB+1]; /* map from fb to stream */ +} S3ScreenInfo; + +#define getS3CardInfo(kd) ((S3CardInfo *) ((kd)->card->driver)) +#define s3CardInfo(kd) S3CardInfo *s3c = getS3CardInfo(kd) + +#define getS3ScreenInfo(kd) ((S3ScreenInfo *) ((kd)->screen->driver)) +#define s3ScreenInfo(kd) S3ScreenInfo *s3s = getS3ScreenInfo(kd) + +Bool s3CardInit (KdCardInfo *); +Bool s3ScreenInit (KdScreenInfo *); +Bool s3Enable (ScreenPtr pScreen); +void s3Disable (ScreenPtr pScreen); +void s3Fini (ScreenPtr pScreen); + +Bool s3CursorInit (ScreenPtr pScreen); +void s3CursorEnable (ScreenPtr pScreen); +void s3CursorDisable (ScreenPtr pScreen); +void s3CursorFini (ScreenPtr pScreen); +void s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs); + +void s3DumbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +Bool s3DrawInit (ScreenPtr pScreen); +void s3DrawEnable (ScreenPtr pScreen); +void s3DrawSync (ScreenPtr pScreen); +void s3DrawDisable (ScreenPtr pScreen); +void s3DrawFini (ScreenPtr pScreen); + +void s3GetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs); +void s3PutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs); + +void S3InitCard (KdCardAttr *attr); + +void s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR, int minVco); + +extern KdCardFuncs s3Funcs; + +/* + * Wait for the begining of the retrace interval + */ + +#define S3_RETRACE_LOOP_CHECK if (++_loop_count > 300000) {\ + DRAW_DEBUG ((DEBUG_FAILURE, "S3 wait loop failed at %s:%d", \ + __FILE__, __LINE__)); \ + break; \ +} + +#define DRAW_DEBUG(a) + +#define _s3WaitVRetrace(s3vga) { \ + int _loop_count; \ + _loop_count = 0; \ + while (s3GetImm(s3vga, s3_vertical_sync_active) != 0) S3_RETRACE_LOOP_CHECK; \ + _loop_count = 0; \ + while (s3GetImm(s3vga, s3_vertical_sync_active) == 0) S3_RETRACE_LOOP_CHECK; \ +} +#define _s3WaitVRetraceFast(s3) { \ + int _loop_count; \ + _loop_count = 0; \ + while (s3->input_status_1 & 8) S3_RETRACE_LOOP_CHECK; \ + _loop_count = 0; \ + while ((s3->input_status_1 & 8) == 0) S3_RETRACE_LOOP_CHECK; \ +} +/* + * Wait for the begining of the retrace interval + */ +#define _s3WaitVRetraceEnd(s3vga) { \ + int _loop_count; \ + _loop_count = 0; \ + while (s3GetImm(s3vga, s3_vertical_sync_active) == 0) S3_RETRACE_LOOP_CHECK; \ + _loop_count = 0; \ + while (s3GetImm(s3vga, s3_vertical_sync_active) != 0) S3_RETRACE_LOOP_CHECK; \ +} + +#define S3_CURSOR_WIDTH 64 +#define S3_CURSOR_HEIGHT 64 +#define S3_CURSOR_SIZE ((S3_CURSOR_WIDTH * S3_CURSOR_HEIGHT + 7) / 8) + +#define S3_TILE_SIZE 8 + +#endif /* _S3_H_ */ diff --git a/xserver/hw/kdrive/savage/s3.nick b/xserver/hw/kdrive/savage/s3.nick new file mode 100644 index 000000000..8f6791f87 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3.nick @@ -0,0 +1,41 @@ +/* $RCSId: $ */ + +global f_ref = 14318000; + +function s3_clock (m, n, r) +{ + return f_ref * (m + 2) / ((n + 2) * (2 ^ r)); +} + +function s3_near (f1, f2) +{ + return abs (f1 - f2) < f1 / 10; +} + +function s3_clocks (f) +{ + auto m, n, r, ft; + auto dist, min_dist; + auto min_m, min_n, min_r; + + min_dist = f / 5; + for (r = 0; r <= 3; r++) + for (n = 0; n <= 31; n++) + for (m = 0; m <= 127; m++) + { + ft = s3_clock (m, n, r); + if (s3_near (ft, f)) + printf ("m %d n %d r %d = %d\n", + m, n, r, ft); + dist = abs (f - ft); + if (dist < min_dist) + { + min_dist = dist; + min_m = m; + min_n = n; + min_r = r; + } + } + printf ("m %d n %d r %d f %d dist %d\n", + min_m, min_n, min_r, s3_clock(min_m, min_n, min_r), min_dist); +} diff --git a/xserver/hw/kdrive/savage/s3clock.c b/xserver/hw/kdrive/savage/s3clock.c new file mode 100644 index 000000000..9e3f8b3e0 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3clock.c @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" + +/* + * Clock synthesis: + * + * f_out = f_ref * ((M + 2) / ((N + 2) * (1 << R))) + * + * Constraints: + * + * 1. 135MHz <= f_ref * ((M + 2) / (N + 2)) <= 270 MHz + * 2. N >= 1 + * + * Vertical refresh rate = clock / ((hsize + hblank) * (vsize + vblank)) + * Horizontal refresh rate = clock / (hsize + hblank) + */ + +/* all in kHz */ + +void +s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR, int minVco) +{ + int M, N, R, bestM, bestN; + int f_vco, f_out; + int err, abserr, besterr; + + /* + * Compute correct R value to keep VCO in range + */ + for (R = 0; R <= maxR; R++) + { + f_vco = target * (1 << R); + if (f_vco >= minVco) + break; + } + + /* M = f_out / f_ref * ((N + 2) * (1 << R)); */ + besterr = target; + for (N = 1; N <= maxN; N++) + { + M = ((target * (N + 2) * (1 << R) + (S3_CLOCK_REF/2)) + S3_CLOCK_REF/2) / S3_CLOCK_REF - 2; + if (0 <= M && M <= maxM) + { + f_out = S3_CLOCK(M,N,R); + err = target - f_out; + if (err < 0) + err = -err; + if (err < besterr) + { + besterr = err; + bestM = M; + bestN = N; + } + } + } + *Mp = bestM; + *Np = bestN; + *Rp = R; +} diff --git a/xserver/hw/kdrive/savage/s3cmap.c b/xserver/hw/kdrive/savage/s3cmap.c new file mode 100644 index 000000000..094a24755 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3cmap.c @@ -0,0 +1,122 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" + +void +s3GetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + S3Vga *s3vga = &s3c->s3vga; + + while (ndef--) + { + s3SetImm (s3vga, s3_dac_read_index, pdefs->pixel); + pdefs->red = s3GetImm (s3vga, s3_dac_data) << 8; + pdefs->green = s3GetImm (s3vga, s3_dac_data) << 8; + pdefs->blue = s3GetImm (s3vga, s3_dac_data) << 8; + pdefs++; + } +} + +#ifndef S3_TRIO +#define Shift(v,d) ((d) < 0 ? ((v) >> (-d)) : ((v) << (d))) + +void +s3SetTrueChromaKey (ScreenPtr pScreen, int pfb, xColorItem *pdef) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + KdScreenPriv(pScreen); + s3ScreenInfo(pScreenPriv); + int fb, ma; + CARD32 key; + int r, g, b; + + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + { + fb = s3s->fbmap[ma]; + if (fb != pfb && pScreenPriv->screen->fb[fb].redMask) + { + r = KdComputeCmapShift (pScreenPriv->screen->fb[fb].redMask); + g = KdComputeCmapShift (pScreenPriv->screen->fb[fb].greenMask); + b = KdComputeCmapShift (pScreenPriv->screen->fb[fb].blueMask); + key = ((Shift(pdef->red,r) & pScreenPriv->screen->fb[fb].redMask) | + (Shift(pdef->green,g) & pScreenPriv->screen->fb[fb].greenMask) | + (Shift(pdef->blue,b) & pScreenPriv->screen->fb[fb].blueMask)); + if (pScrPriv->layer[fb].key != key) + { + pScrPriv->layer[fb].key = key; + (*pScrPriv->PaintKey) (&pScrPriv->layer[fb].u.run.pixmap->drawable, + &pScrPriv->layer[pfb].u.run.region, + pScrPriv->layer[fb].key, fb); + } + } + } +} +#endif + +void +s3PutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + s3CardInfo(pScreenPriv); + s3ScreenInfo(pScreenPriv); + S3Vga *s3vga = &s3c->s3vga; + xColorItem *chroma = 0; + CARD32 key; + +#if 0 + _s3WaitVRetrace (s3vga); +#else + S3Ptr s3 = s3c->s3; + _s3WaitVRetraceFast(s3); +#endif +#ifndef S3_TRIO + if (pScreenPriv->screen->fb[1].depth) + { + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + key = pScrPriv->layer[fb].key; + } +#endif + else + key = ~0; + while (ndef--) + { + if (pdefs->pixel == key) + chroma = pdefs; + s3SetImm (s3vga, s3_dac_write_index, pdefs->pixel); + s3SetImm (s3vga, s3_dac_data, pdefs->red >> 8); + s3SetImm (s3vga, s3_dac_data, pdefs->green >> 8); + s3SetImm (s3vga, s3_dac_data, pdefs->blue >> 8); + pdefs++; + } +#ifndef S3_TRIO + if (chroma && !pScreenPriv->closed) + s3SetTrueChromaKey (pScreen, fb, chroma); +#endif +} + diff --git a/xserver/hw/kdrive/savage/s3curs.c b/xserver/hw/kdrive/savage/s3curs.c new file mode 100644 index 000000000..5928989a6 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3curs.c @@ -0,0 +1,422 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" +#include "s3draw.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + s3CardInfo(pScreenPriv); \ + s3ScreenInfo(pScreenPriv); \ + S3Ptr s3 = s3c->s3; \ + S3Vga *s3vga = &s3c->s3vga; \ + S3Cursor *pCurPriv = &s3s->cursor + +static void +_s3MoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor %d %d", x, y)); + + 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 */ + + s3SetImm (s3vga, s3_cursor_xhigh, xhigh); + s3SetImm (s3vga, s3_cursor_xlow, xlow); + s3SetImm (s3vga, s3_cursor_ylow, ylow); + s3SetImm (s3vga, s3_cursor_xoff, xoff); + s3SetImm (s3vga, s3_cursor_yoff, yoff); + s3SetImm (s3vga, s3_cursor_yhigh, yhigh); + + DRAW_DEBUG ((DEBUG_CURSOR, "s3MoveCursor done")); +} + +static void +s3MoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + _s3MoveCursor (pScreen, x, y); +} + +#define S3Trunc(c) (((c) >> 8) & 0xff) + +#define S3CursColor(r,g,b) ((S3Trunc(r) << 16) | \ + (S3Trunc(g) << 8) | \ + (S3Trunc(b))) + +static void +s3AllocCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + + if (s3s->use_streams) + { + pCurPriv->source = S3CursColor(pCursor->foreRed, + pCursor->foreGreen, + pCursor->foreBlue); + pCurPriv->mask = S3CursColor(pCursor->backRed, + pCursor->backGreen, + pCursor->backBlue); + } + else + { + KdAllocateCursorPixels (pScreen, 0, pCursor, + &pCurPriv->source, &pCurPriv->mask); + switch (pScreenPriv->screen->fb[0].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 +_s3SetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + /* set foreground */ + /* Reset cursor color stack pointers */ + (void) s3GetImm (s3vga, s3_cursor_enable); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 8); + s3SetImm (s3vga, s3_cursor_fg, pCurPriv->source >> 16); + + /* set background */ + /* Reset cursor color stack pointers */ + (void) s3GetImm (s3vga, s3_cursor_enable); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 8); + s3SetImm (s3vga, s3_cursor_bg, pCurPriv->mask >> 16); +} + +void +s3RecolorCursor (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; + } + s3AllocCursorColors (pScreen); + _s3SetCursorColors (pScreen); +} + +static void +s3LoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + unsigned char r[2], g[2], b[2]; + unsigned long *ram; + unsigned long *msk, *mskLine, *src, *srcLine; + unsigned long and, xor; + int i, j; + int cursor_address; + int wsrc; + unsigned char ramdac_control_; + + /* + * Allocate new colors + */ + s3AllocCursorColors (pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (unsigned long *) s3s->cursor_base; + mskLine = (unsigned long *) bits->mask; + srcLine = (unsigned long *) bits->source; + + h = bits->height; + if (h > S3_CURSOR_HEIGHT) + h = S3_CURSOR_HEIGHT; + + wsrc = BitmapBytePad(bits->width) / 4; /* ulongs per line */ + + for (i = 0; i < S3_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += wsrc; + srcLine += wsrc; + for (j = 0; j < S3_CURSOR_WIDTH / 32; j++) { + + unsigned long m, s; + + if (i < h && j < wsrc) + { + m = *msk++; + s = *src++; + xor = m & s; + and = ~m; + } + else + { + and = 0xffffffff; + xor = 0x00000000; + } + + S3AdjustBits32(and); + S3AdjustBits32(xor); +#define S3SwapNibbles(x) ((x) = (((x) & 0x0f0f0f0f) << 4 | \ + ((x) >> 4) & 0x0f0f0f0f)) + if (s3s->use_streams) + { + S3SwapNibbles(and); + S3SwapNibbles(xor); + } + *ram++ = (and & 0xffff) | (xor << 16); + *ram++ = (and >> 16) | (xor & 0xffff0000); + } + } + + _s3WaitIdle (s3); + + /* Set new color */ + _s3SetCursorColors (pScreen); + + /* Enable the cursor */ + s3SetImm (s3vga, s3_cursor_ms_x11, 0); + s3SetImm (s3vga, s3_cursor_enable, 1); + + /* Wait for VRetrace to make sure the position is read */ + _s3WaitVRetrace (s3vga); + + /* Move to new position */ + _s3MoveCursor (pScreen, x, y); +} + +static void +s3UnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + /* Disable cursor */ + s3SetImm (s3vga, s3_cursor_enable, 0); +} + +static Bool +s3RealizeCursor (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); + s3LoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +s3UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +s3SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + s3LoadCursor (pScreen, x, y); + else + s3UnloadCursor (pScreen); +} + +miPointerSpriteFuncRec s3PointerSpriteFuncs = { + s3RealizeCursor, + s3UnrealizeCursor, + s3SetCursor, + s3MoveCursor, +}; + +static void +s3QueryBestSize (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 +s3CursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!s3s->cursor_base) + { + DRAW_DEBUG ((DEBUG_CURSOR,"Not enough screen memory for cursor %d", s3d->memory)); + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = S3_CURSOR_WIDTH; + pCurPriv->height= S3_CURSOR_HEIGHT; + pScreen->QueryBestSize = s3QueryBestSize; + miPointerInitialize (pScreen, + &s3PointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +s3CursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + DRAW_DEBUG ((DEBUG_INIT, "s3CursorEnable")); + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + s3LoadCursor (pScreen, x, y); + } + else + s3UnloadCursor (pScreen); + } +} + +void +s3CursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + s3UnloadCursor (pScreen); + } + } +} + +void +s3CursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/xserver/hw/kdrive/savage/s3draw.c b/xserver/hw/kdrive/savage/s3draw.c new file mode 100644 index 000000000..da0d6849f --- /dev/null +++ b/xserver/hw/kdrive/savage/s3draw.c @@ -0,0 +1,3114 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" +#include "s3draw.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" + +/* + * Map X rops to S3 rops + */ + +short s3alu[16] = { + MIX_0, + MIX_AND, + MIX_SRC_AND_NOT_DST, + MIX_SRC, + MIX_NOT_SRC_AND_DST, + MIX_DST, + MIX_XOR, + MIX_OR, + MIX_NOR, + MIX_XNOR, + MIX_NOT_DST, + MIX_SRC_OR_NOT_DST, + MIX_NOT_SRC, + MIX_NOT_SRC_OR_DST, + MIX_NAND, + MIX_1 +}; + +/* + * Handle pixel transfers + */ + +#define BURST +#ifdef BURST +#define PixTransDeclare VOL32 *pix_trans_base = (VOL32 *) (s3c->registers),\ + *pix_trans = pix_trans_base +#define PixTransStart(n) if (pix_trans + (n) > pix_trans_base + 8192) pix_trans = pix_trans_base +#define PixTransStore(t) *pix_trans++ = (t) +#else +#define PixTransDeclare VOL32 *pix_trans = &s3->pix_trans +#define PixTransStart(n) +#define PixTransStore(t) *pix_trans = (t) +#endif + +DevPrivateKey s3GCPrivateKey = &s3GCPrivateKey; +DevPrivateKey s3WindowPrivateKey = &s3WindowPrivateKey; + +/* + s3DoBitBlt + ============= + Bit Blit for all window to window blits. +*/ + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +void +s3CopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + int flags; + + if (sourceInvarient (pGC->alu)) + { + s3FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask); + return; + } + + s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC)); + _s3SetBlt(s3,pGC->alu,pGC->planemask); + DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x", + pGC->alu, pGC->planemask)); + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = pbox->x2 - 1; + } + else + { + dstX = pbox->x1; + flags |= INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= INC_Y; + } + srcY = dstY + dy; + + _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags); + pbox++; + } + MarkSyncS3 (pSrcDrawable->pScreen); +} + +RegionPtr +s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + SetupS3(pDstDrawable->pScreen); + + if (pSrcDrawable->type == DRAWABLE_WINDOW && + pDstDrawable->type == DRAWABLE_WINDOW) + { + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, s3CopyNtoN, 0, 0); + } + return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); +} + +typedef struct _s31toNargs { + unsigned long copyPlaneFG, copyPlaneBG; + Bool opaque; +} s31toNargs; + +void +_s3Stipple (S3CardInfo *s3c, + FbStip *psrcBase, + FbStride widthSrc, + int srcx, + int srcy, + int dstx, + int dsty, + int width, + int height) +{ + S3Ptr s3 = s3c->s3; + FbStip *psrcLine, *psrc; + FbStride widthRest; + FbStip bits, tmp, lastTmp; + int leftShift, rightShift; + int nl, nlMiddle; + int r; + PixTransDeclare; + + /* Compute blt address and parameters */ + psrc = psrcBase + srcy * widthSrc + (srcx >> 5); + nlMiddle = (width + 31) >> 5; + leftShift = srcx & 0x1f; + rightShift = 32 - leftShift; + widthRest = widthSrc - nlMiddle; + + _s3PlaneBlt(s3,dstx,dsty,width,height); + + if (leftShift == 0) + { + while (height--) + { + nl = nlMiddle; + PixTransStart(nl); + while (nl--) + { + tmp = *psrc++; + S3AdjustBits32 (tmp); + PixTransStore (tmp); + } + psrc += widthRest; + } + } + else + { + widthRest--; + while (height--) + { + bits = *psrc++; + nl = nlMiddle; + PixTransStart(nl); + while (nl--) + { + tmp = FbStipLeft(bits, leftShift); + bits = *psrc++; + tmp |= FbStipRight(bits, rightShift); + S3AdjustBits32(tmp); + PixTransStore (tmp); + } + psrc += widthRest; + } + } +} + +void +s3Copy1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + + s31toNargs *args = closure; + int dstx, dsty; + FbStip *psrcBase; + FbStride widthSrc; + int srcBpp; + int srcXoff, srcYoff; + + if (args->opaque && sourceInvarient (pGC->alu)) + { + s3FillBoxSolid (pDstDrawable, nbox, pbox, + pGC->bgPixel, pGC->alu, pGC->planemask); + return; + } + + s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC)); + fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff); + + if (args->opaque) + { + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,args->copyPlaneFG, + args->copyPlaneBG); + } + else + { + _s3SetTransparentPlaneBlt (s3, pGC->alu, + pGC->planemask, args->copyPlaneFG); + } + + while (nbox--) + { + dstx = pbox->x1; + dsty = pbox->y1; + + _s3Stipple (s3c, + psrcBase, widthSrc, + dstx + dx - srcXoff, dsty + dy - srcYoff, + dstx, dsty, + pbox->x2 - dstx, pbox->y2 - dsty); + pbox++; + } + MarkSyncS3 (pDstDrawable->pScreen); +} + +RegionPtr +s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + SetupS3 (pDstDrawable->pScreen); + RegionPtr ret; + s31toNargs args; + + if (pDstDrawable->type == DRAWABLE_WINDOW && + pSrcDrawable->depth == 1) + { + args.copyPlaneFG = pGC->fgPixel; + args.copyPlaneBG = pGC->bgPixel; + args.opaque = TRUE; + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, s3Copy1toN, bitPlane, &args); + } + return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); +} + +void +s3PushPixels (GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, + int w, int h, int x, int y) +{ + SetupS3 (pDrawable->pScreen); + s31toNargs args; + + if (pDrawable->type == DRAWABLE_WINDOW && pGC->fillStyle == FillSolid) + { + args.opaque = FALSE; + args.copyPlaneFG = pGC->fgPixel; + (void) fbDoCopy ((DrawablePtr) pBitmap, pDrawable, pGC, + 0, 0, w, h, x, y, s3Copy1toN, 1, &args); + } + else + { + KdCheckPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + } +} + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask) +{ + SetupS3(pDrawable->pScreen); + register int r; + + s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable)); + _s3SetSolidFill(s3,pixel,alu,planemask); + + while (nBox--) { + _s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1); + pBox++; + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +_s3SetPattern (ScreenPtr pScreen, int ma, + int alu, unsigned long planemask, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + S3PatternCache *cache; + + _s3LoadPattern (pScreen, ma, pPattern); + cache = pPattern->cache; + + switch (pPattern->fillStyle) { + case FillTiled: + _s3SetTile(s3,alu,planemask); + break; + case FillStippled: + _s3SetStipple(s3,alu,planemask,pPattern->fore); + break; + case FillOpaqueStippled: + _s3SetOpaqueStipple(s3,alu,planemask,pPattern->fore,pPattern->back); + break; + } +} + +void +s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + int alu, unsigned long planemask, s3PatternPtr pPattern) +{ + SetupS3(pDrawable->pScreen); + S3PatternCache *cache; + int patx, paty; + + s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable)); + _s3SetPattern (pDrawable->pScreen, s3DrawMap(pDrawable), alu, planemask, pPattern); + cache = pPattern->cache; + while (nBox--) + { + _s3PatRect(s3,cache->x, cache->y, + pBox->x1, pBox->y1, + pBox->x2-pBox->x1, pBox->y2-pBox->y1); + pBox++; + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3FillBoxLargeStipple (DrawablePtr pDrawable, GCPtr pGC, + int nBox, BoxPtr pBox) +{ + SetupS3(pDrawable->pScreen); + DrawablePtr pStipple = &pGC->stipple->drawable; + int xRot = pGC->patOrg.x + pDrawable->x; + int yRot = pGC->patOrg.y + pDrawable->y; + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; + int stipWidth, stipHeight; + int dstX, dstY, width, height; + + stipWidth = pStipple->width; + stipHeight = pStipple->height; + fbGetStipDrawable (pStipple, stip, stipStride, stipBpp, stipXoff, stipYoff); + + s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable)); + if (pGC->fillStyle == FillOpaqueStippled) + { + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask, + pGC->fgPixel, pGC->bgPixel); + + } + else + { + _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel); + } + + while (nBox--) + { + int stipX, stipY, sx; + int widthTmp; + int h, w; + int x, y; + + dstX = pBox->x1; + dstY = pBox->y1; + width = pBox->x2 - pBox->x1; + height = pBox->y2 - pBox->y1; + pBox++; + modulus (dstY - yRot - stipYoff, stipHeight, stipY); + modulus (dstX - xRot - stipXoff, stipWidth, stipX); + y = dstY; + while (height) + { + h = stipHeight - stipY; + if (h > height) + h = height; + height -= h; + widthTmp = width; + x = dstX; + sx = stipX; + while (widthTmp) + { + w = (stipWidth - sx); + if (w > widthTmp) + w = widthTmp; + widthTmp -= w; + _s3Stipple (s3c, + stip, + stipStride, + sx, stipY, + x, y, + w, h); + x += w; + sx = 0; + } + y += h; + stipY = 0; + } + } + MarkSyncS3 (pDrawable->pScreen); +} + +#define NUM_STACK_RECTS 1024 + +void +s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + s3GCPrivate(pGC); + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + int numRects; + int n; + int xorg, yorg; + int x, y; + + 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) + { + if (pGC->fillStyle == FillSolid) + s3FillBoxSolid(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->fgPixel, pGC->alu, pGC->planemask); + else if (s3Priv->pPattern) + s3FillBoxPattern (pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->alu, pGC->planemask, + s3Priv->pPattern); + else + s3FillBoxLargeStipple (pDrawable, pGC, + pboxClipped-pboxClippedBase, + pboxClippedBase); + } + if (pboxClippedBase != stackRects) + xfree(pboxClippedBase); +} + +void +_s3FillSpanLargeStipple (DrawablePtr pDrawable, GCPtr pGC, + int n, DDXPointPtr ppt, int *pwidth) +{ + SetupS3 (pDrawable->pScreen); + DrawablePtr pStipple = &pGC->stipple->drawable; + int xRot = pGC->patOrg.x + pDrawable->x; + int yRot = pGC->patOrg.y + pDrawable->y; + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; + int stipWidth, stipHeight; + int dstX, dstY, width, height; + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + stipWidth = pStipple->width; + stipHeight = pStipple->height; + fbGetStipDrawable (pStipple, stip, stipStride, stipBpp, stipXoff, stipYoff); + if (pGC->fillStyle == FillOpaqueStippled) + { + _s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask, + pGC->fgPixel, pGC->bgPixel); + + } + else + { + _s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel); + } + while (n--) + { + int stipX, stipY, sx; + int w; + int x, y; + + dstX = ppt->x; + dstY = ppt->y; + ppt++; + width = *pwidth++; + modulus (dstY - yRot - stipYoff, stipHeight, stipY); + modulus (dstX - xRot - stipXoff, stipWidth, stipX); + y = dstY; + x = dstX; + sx = stipX; + while (width) + { + w = (stipWidth - sx); + if (w > width) + w = width; + width -= w; + _s3Stipple (s3c, + stip, + stipStride, + sx, stipY, + x, y, + w, 1); + x += w; + sx = 0; + } + } +} + +void +s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + s3GCPrivate(pGC); + SetupS3(pDrawable->pScreen); + int x, y, x1, y1, x2, y2; + int width; + /* next three parameters are post-clip */ + int nTmp; + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + BoxPtr extents; + S3PatternCache *cache; + RegionPtr pClip = fbGetCompositeClip (pGC); + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + if (REGION_NUM_RECTS(pClip) == 1 && + (pGC->fillStyle == FillSolid || s3Priv->pPattern)) + { + extents = REGION_RECTS(pClip); + x1 = extents->x1; + x2 = extents->x2; + y1 = extents->y1; + y2 = extents->y2; + if (pGC->fillStyle == FillSolid) + { + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + cache = 0; + } + else + { + _s3SetPattern (pDrawable->pScreen, s3GCMap(pGC), pGC->alu, pGC->planemask, + s3Priv->pPattern); + cache = s3Priv->pPattern->cache; + } + while (n--) + { + y = ppt->y; + if (y1 <= y && y < y2) + { + x = ppt->x; + width = *pwidth; + if (x < x1) + { + width -= (x1 - x); + x = x1; + } + if (x2 < x + width) + width = x2 - x; + if (width > 0) + { + if (cache) + { + _s3PatRect(s3, cache->x, cache->y, x, y, width, 1); + } + else + { + _s3SolidRect(s3,x,y,width,1); + } + } + } + ppt++; + pwidth++; + } + } + else + { + nTmp = n * miFindMaxBand(pClip); + pwidthFree = (int *)xalloc(nTmp * sizeof(int)); + pptFree = (DDXPointRec *)xalloc(nTmp * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) xfree(pptFree); + if (pwidthFree) xfree(pwidthFree); + return; + } + n = miClipSpans(fbGetCompositeClip(pGC), + ppt, pwidth, n, + pptFree, pwidthFree, fSorted); + pwidth = pwidthFree; + ppt = pptFree; + if (pGC->fillStyle == FillSolid) + { + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _s3SolidRect(s3,x,y,width,1); + } + } + } + else if (s3Priv->pPattern) + { + _s3SetPattern (pDrawable->pScreen, s3GCMap(pGC), pGC->alu, pGC->planemask, + s3Priv->pPattern); + cache = s3Priv->pPattern->cache; + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _s3PatRect(s3, cache->x, cache->y, x, y, width, 1); + } + } + } + else + { + _s3FillSpanLargeStipple (pDrawable, pGC, n, ppt, pwidth); + } + xfree(pptFree); + xfree(pwidthFree); + } + MarkSyncS3 (pDrawable->pScreen); +} + +#include "mifillarc.h" + +#define FILLSPAN(s3,y,__x1,__x2) {\ + DRAW_DEBUG ((DEBUG_ARCS, "FILLSPAN %d: %d->%d", y, __x1, __x2)); \ + if ((__x2) >= (__x1)) {\ + _s3SolidRect(s3,(__x1),(y),(__x2)-(__x1)+1,1); \ + } \ +} + +#define FILLSLICESPANS(flip,__y) \ + if (!flip) \ + { \ + FILLSPAN(s3,__y,xl,xr) \ + } \ + else \ + { \ + xc = xorg - x; \ + FILLSPAN(s3, __y, xc, xr) \ + xc += slw - 1; \ + FILLSPAN(s3, __y, xl, xc) \ + } + +static void +_s3FillEllipse (DrawablePtr pDraw, S3Ptr s3, xArc *arc) +{ + KdScreenPriv(pDraw->pScreen); + int x, y, e; + int yk, xk, ym, xm, dx, dy, xorg, yorg; + int y_top, y_bot; + miFillArcRec info; + register int xpos; + int slw; + + s3SetGlobalBitmap (pDraw->pScreen, s3DrawMap (pDraw)); + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + y_top = pDraw->y + yorg - y; + y_bot = pDraw->y + yorg + y + dy; + xorg += pDraw->x; + while (y) + { + y_top++; + y_bot--; + MIFILLARCSTEP(slw); + if (!slw) + continue; + xpos = xorg - x; + _s3SolidRect (s3,xpos,y_top,slw,1); + if (miFillArcLower(slw)) + _s3SolidRect (s3,xpos,y_bot,slw,1); + } +} + + +static void +_s3FillArcSlice (DrawablePtr pDraw, GCPtr pGC, S3Ptr s3, xArc *arc) +{ + KdScreenPriv(pDraw->pScreen); + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int xl, xr, xc; + int y_top, y_bot; + + s3SetGlobalBitmap (pDraw->pScreen, s3DrawMap (pDraw)); + DRAW_DEBUG ((DEBUG_ARCS, "slice %dx%d+%d+%d %d->%d", + arc->width, arc->height, arc->x, arc->y, + arc->angle1, arc->angle2)); + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + DRAW_DEBUG ((DEBUG_ARCS, "edge1.x %d edge2.x %d", + slice.edge1.x, slice.edge2.x)); + MIFILLARCSETUP(); + DRAW_DEBUG ((DEBUG_ARCS, "xorg %d yorg %d", + xorg, yorg)); + xorg += pDraw->x; + yorg += pDraw->y; + y_top = yorg - y; + y_bot = yorg + y + dy; + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + DRAW_DEBUG ((DEBUG_ARCS, "xorg %d y_top %d y_bot %d", + xorg, y_top, y_bot)); + while (y > 0) + { + y_top++; + y_bot--; + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) + { + MIARCSLICEUPPER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_top, y_top); + } + if (miFillSliceLower(slice)) + { + MIARCSLICELOWER(xl, xr, slice, slw); + FILLSLICESPANS(slice.flip_bot, y_bot); + } + } +} + +void +s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) +{ + SetupS3(pDraw->pScreen); + xArc *arc; + int i; + int x, y; + BoxRec box; + RegionPtr pClip = fbGetCompositeClip(pGC); + BOOL set; + + set = FALSE; + for (; --narcs >= 0; parcs++) + { + if (miFillArcEmpty(parcs)) + continue; + if (miCanFillArc(parcs)) + { + box.x1 = parcs->x + pDraw->x; + box.y1 = parcs->y + pDraw->y; + box.x2 = box.x1 + (int)parcs->width + 1; + box.y2 = box.y1 + (int)parcs->height + 1; + switch (RECT_IN_REGION(pDraw->pScreen, pClip, &box)) + { + case rgnIN: + if (!set) + { + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + set = TRUE; + } + if ((parcs->angle2 >= FULLCIRCLE) || + (parcs->angle2 <= -FULLCIRCLE)) + { + DRAW_DEBUG ((DEBUG_ARCS, "Full circle ellipse %dx%d", + parcs->width, parcs->height)); + _s3FillEllipse (pDraw, s3, parcs); + } + else + { + DRAW_DEBUG ((DEBUG_ARCS, "Partial ellipse %dx%d", + parcs->width, parcs->height)); + _s3FillArcSlice (pDraw, pGC, s3, parcs); + } + /* fall through ... */ + case rgnOUT: + continue; + case rgnPART: + break; + } + } + if (set) + { + MarkSyncS3 (pDraw->pScreen); + set = FALSE; + } + KdCheckPolyFillArc(pDraw, pGC, 1, parcs); + } + if (set) + { + MarkSyncS3 (pDraw->pScreen); + set = FALSE; + } +} + +void +s3FillPoly (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int countInit, DDXPointPtr ptsIn) +{ + SetupS3(pDrawable->pScreen); + int nwidth; + int maxy; + int origin; + int count; + register int vertex1, vertex2; + int c; + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr extents; + int clip; + int y, sy; + int *vertex1p, *vertex2p; + int *endp; + int x1, x2, sx; + int dx1, dx2; + int dy1, dy2; + int e1, e2; + int step1, step2; + int sign1, sign2; + int h; + int l, r; + int nmiddle; + + if (mode == CoordModePrevious || REGION_NUM_RECTS(pClip) != 1) + { + KdCheckFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + sy = pDrawable->y; + sx = pDrawable->x; + origin = *((int *) &pDrawable->x); + origin -= (origin & 0x8000) << 1; + extents = &pClip->extents; + vertex1 = *((int *) &extents->x1) - origin; + vertex2 = *((int *) &extents->x2) - origin - 0x00010001; + clip = 0; + + y = 32767; + maxy = 0; + vertex2p = (int *) ptsIn; + endp = vertex2p + countInit; + if (shape == Convex) + { + count = countInit; + while (count--) + { + c = *vertex2p; + clip |= (c - vertex1) | (vertex2 - c); + c = intToY(c); + DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c)); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + } + } + else + { + int yFlip = 0; + dx1 = 1; + x2 = -1; + x1 = -1; + count = countInit; + while (count--) + { + c = *vertex2p; + clip |= (c - vertex1) | (vertex2 - c); + c = intToY(c); + DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c)); + if (c < y) + { + y = c; + vertex1p = vertex2p; + } + vertex2p++; + if (c > maxy) + maxy = c; + if (c == x1) + continue; + if (dx1 > 0) + { + if (x2 < 0) + x2 = c; + else + dx2 = dx1 = (c - x1) >> 31; + } + else + if ((c - x1) >> 31 != dx1) + { + dx1 = ~dx1; + yFlip++; + } + x1 = c; + } + x1 = (x2 - c) >> 31; + if (x1 != dx1) + yFlip++; + if (x1 != dx2) + yFlip++; + if (yFlip != 2) + clip = 0x8000; + } + if (y == maxy) + return; + + if (clip & 0x80008000) + { + KdCheckFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn); + return; + } + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + + vertex2p = vertex1p; + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; +#define Setup(c,x,vertex,dx,dy,e,sign,step) {\ + x = intToX(vertex); \ + if (dy = intToY(c) - y) { \ + dx = intToX(c) - x; \ + step = 0; \ + if (dx >= 0) \ + { \ + e = 0; \ + sign = 1; \ + if (dx >= dy) {\ + step = dx / dy; \ + dx = dx % dy; \ + } \ + } \ + else \ + { \ + e = 1 - dy; \ + sign = -1; \ + dx = -dx; \ + if (dx >= dy) { \ + step = - (dx / dy); \ + dx = dx % dy; \ + } \ + } \ + } \ + x += sx; \ + vertex = c; \ +} + +#define Step(x,dx,dy,e,sign,step) {\ + x += step; \ + if ((e += dx) > 0) \ + { \ + x += sign; \ + e -= dy; \ + } \ +} + sy += y; + DRAW_DEBUG ((DEBUG_POLYGON, "Starting polygon at %d", sy)); + for (;;) + { + DRAW_DEBUG ((DEBUG_POLYGON, "vertex1 0x%x vertex2 0x%x y %d vy1 %d vy2 %d", + vertex1, vertex2, + y, intToY(vertex1), intToY (vertex2))); + if (y == intToY(vertex1)) + { + DRAW_DEBUG ((DEBUG_POLYGON, "Find next -- vertext")); + do + { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1); + DRAW_DEBUG ((DEBUG_POLYGON, "-- vertex 0x%x y %d", + vertex1, intToY(vertex1))); + } while (y >= intToY(vertex1)); + h = dy1; + } + else + { + Step(x1,dx1,dy1,e1,sign1,step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) + { + DRAW_DEBUG ((DEBUG_POLYGON, "Find next ++ vertext")); + do + { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2) + DRAW_DEBUG ((DEBUG_POLYGON, "++ vertex 0x%x y %d", + vertex1, intToY(vertex1))); + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else + { + Step(x2,dx2,dy2,e2,sign2,step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + DRAW_DEBUG ((DEBUG_POLYGON, "This band %d", h)); + /* fill spans for this segment */ + for (;;) + { + nmiddle = x2 - x1; + DRAW_DEBUG ((DEBUG_POLYGON, "This span %d->%d", x1, x2)); + if (nmiddle) + { + l = x1; + if (nmiddle < 0) + { + nmiddle = -nmiddle; + l = x2; + } + _s3SolidRect(s3,l,sy,nmiddle,1); + } + y++; + sy++; + if (!--h) + break; + Step(x1,dx1,dy1,e1,sign1,step1) + Step(x2,dx2,dy2,e2,sign2,step2) + } + if (y == maxy) + break; + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3PolyGlyphBltClipped (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int h; + int w; + int xBack, yBack; + int hBack, wBack; + int lw; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + unsigned long *bits; + BoxPtr extents; + BoxRec bbox; + CARD32 b; + CharInfoPtr *ppci; + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nbox; + int x1, y1, x2, y2; + unsigned char alu; + Bool set; + PixTransDeclare; + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + x += pDrawable->x; + y += pDrawable->y; + + if (pglyphBase == (pointer) 1) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + h = nglyph; + ppci = ppciInit; + while (h--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask); + for (nbox = REGION_NUM_RECTS (pClip), + pBox = REGION_RECTS (pClip); + nbox--; + pBox++) + { + x1 = xBack; + x2 = xBack + wBack; + y1 = yBack; + y2 = yBack + hBack; + if (x1 < pBox->x1) x1 = pBox->x1; + if (x2 > pBox->x2) x2 = pBox->x2; + if (y1 < pBox->y1) y1 = pBox->y1; + if (y2 > pBox->y2) y2 = pBox->y2; + if (x1 < x2 && y1 < y2) + { + _s3SolidRect (s3, x1, y1, x2 - x1, y2 - y1); + } + } + MarkSyncS3 (pDrawable->pScreen); + } + ppci = ppciInit; + set = FALSE; + while (nglyph--) + { + pci = *ppci++; + h = pci->metrics.ascent + pci->metrics.descent; + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + x1 = x + pci->metrics.leftSideBearing; + y1 = y - pci->metrics.ascent; + bbox.x1 = x1; + bbox.y1 = y1; + bbox.x2 = x1 + w; + bbox.y2 = y1 + h; + switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox)) + { + case rgnIN: +#if 1 + lw = h * ((w + 31) >> 5); + if (lw) + { + if (!set) + { + _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel); + set = TRUE; + } + _s3PlaneBlt(s3, + x + pci->metrics.leftSideBearing, + y - pci->metrics.ascent, + w, h); + bits = (unsigned long *) pci->bits; + PixTransStart (lw); + while (lw--) + { + b = *bits++; + S3AdjustBits32 (b); + PixTransStore(b); + } + MarkSyncS3 (pDrawable->pScreen); + } + break; +#endif + case rgnPART: + set = FALSE; + CheckSyncS3 (pDrawable->pScreen); + fbPutXYImage (pDrawable, + pClip, + fbPriv->fg, + fbPriv->bg, + fbPriv->pm, + alu, + FALSE, + x1, y1, + w, h, + (FbStip *) pci->bits, + (w + 31) >> 5, + 0); + break; + case rgnOUT: + break; + } + x += pci->metrics.characterWidth; + } +} + +/* + * Blt glyphs using S3 image transfer register, this does both + * poly glyph blt and image glyph blt (when pglyphBase == 1) + */ + +void +s3PolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int h; + int w; + int xBack, yBack; + int hBack, wBack; + int lw; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + unsigned long *bits; + BoxPtr extents; + BoxRec bbox; + CARD32 b; + CharInfoPtr *ppci; + unsigned char alu; + PixTransDeclare; + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + x += pDrawable->x; + y += pDrawable->y; + + /* compute an approximate (but covering) bounding box */ + ppci = ppciInit; + w = 0; + h = nglyph; + while (h--) + w += (*ppci++)->metrics.characterWidth; + if (w < 0) + { + bbox.x1 = x + w; + bbox.x2 = x; + } + else + { + bbox.x1 = x; + bbox.x2 = x + w; + } + w = FONTMINBOUNDS(pfont,leftSideBearing); + if (w < 0) + bbox.x1 += w; + w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth); + if (w > 0) + bbox.x2 += w; + bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent); + bbox.y2 = y + FONTMAXBOUNDS(pfont,descent); + + DRAW_DEBUG ((DEBUG_TEXT, "PolyGlyphBlt %d box is %d %d", nglyph, + bbox.x1, bbox.x2)); + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnIN: + break; + case rgnPART: + s3PolyGlyphBltClipped(pDrawable, pGC, x - pDrawable->x, + y - pDrawable->y, + nglyph, ppciInit, pglyphBase); + case rgnOUT: + return; + } + + if (pglyphBase == (pointer) 1) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + h = nglyph; + ppci = ppciInit; + while (h--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask); + _s3SolidRect (s3, xBack, yBack, wBack, hBack); + } + _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel); + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + h = pci->metrics.ascent + pci->metrics.descent; + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + lw = h * ((w + 31) >> 5); + if (lw) + { + _s3PlaneBlt(s3, + x + pci->metrics.leftSideBearing, + y - pci->metrics.ascent, + w, h); + bits = (unsigned long *) pci->bits; + PixTransStart(lw); + while (lw--) + { + b = *bits++; + S3AdjustBits32 (b); + PixTransStore(b); + } + } + x += pci->metrics.characterWidth; + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3ImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + s3PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1); +} + +/* + * Blt TE fonts using S3 image transfer. Differs from + * above in that it doesn't need to fill a solid rect for + * the background and it can draw multiple characters at a time + */ + +void +s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + SetupS3(pDrawable->pScreen); + int x, y; + int h, lw, lwTmp; + int w; + FontPtr pfont = pGC->font; + unsigned long *char1, *char2, *char3, *char4; + int widthGlyphs, widthGlyph; + BoxRec bbox; + CARD32 tmp; + PixTransDeclare; + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); + if (!widthGlyph) + return; + + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + if (!h) + return; + + DRAW_DEBUG ((DEBUG_TEXT, "ImageTEGlyphBlt chars are %d %d", + widthGlyph, h)); + + x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x; + y = yInit - FONTASCENT(pfont) + pDrawable->y; + + bbox.x1 = x; + bbox.x2 = x + (widthGlyph * nglyph); + bbox.y1 = y; + bbox.y2 = y + h; + + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnIN: + break; + case rgnPART: + if (pglyphBase == (pointer) 1) + pglyphBase = 0; + else + pglyphBase = (pointer) 1; + s3PolyGlyphBltClipped(pDrawable, pGC, + xInit, + yInit, + nglyph, ppci, + pglyphBase); + case rgnOUT: + return; + } + + if (pglyphBase == (pointer) 1) + { + _s3SetTransparentPlaneBlt (s3, pGC->alu, pGC->planemask, pGC->fgPixel); + } + else + { + _s3SetOpaquePlaneBlt (s3, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel); + } + +#if BITMAP_BIT_ORDER == LSBFirst +#define SHIFT << +#else +#define SHIFT >> +#endif + +#define LoopIt(count, w, loadup, fetch) \ + while (nglyph >= count) \ + { \ + nglyph -= count; \ + _s3PlaneBlt (s3, x, y, w, h); \ + x += w; \ + loadup \ + lwTmp = h; \ + PixTransStart(h); \ + while (lwTmp--) { \ + tmp = fetch; \ + S3AdjustBits32(tmp); \ + PixTransStore(tmp); \ + } \ + } + + if (widthGlyph <= 8) + { + widthGlyphs = widthGlyph << 2; + LoopIt(4, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits; + char4 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | ((*char3++ | (*char4++ + SHIFT widthGlyph)) + SHIFT widthGlyph)) + SHIFT widthGlyph))) + } + else if (widthGlyph <= 10) + { + widthGlyphs = (widthGlyph << 1) + widthGlyph; + LoopIt(3, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | (*char3++ SHIFT widthGlyph)) SHIFT widthGlyph))) + } + else if (widthGlyph <= 16) + { + widthGlyphs = widthGlyph << 1; + LoopIt(2, widthGlyphs, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | (*char2++ SHIFT widthGlyph))) + } + lw = h * ((widthGlyph + 31) >> 5); + while (nglyph--) + { + _s3PlaneBlt (s3, x, y, widthGlyph, h); + x += widthGlyph; + char1 = (unsigned long *) (*ppci++)->bits; + lwTmp = lw; + PixTransStart(lw); + while (lwTmp--) + { + tmp = *char1++; + S3AdjustBits32(tmp); + PixTransStore(tmp); + } + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase) +{ + s3ImageTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1); +} + +Bool +_s3Segment (DrawablePtr pDrawable, + GCPtr pGC, + int x1, + int y1, + int x2, + int y2, + Bool drawLast, + Bool s3Set) +{ + SetupS3(pDrawable->pScreen); + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nBox; + int adx; /* abs values of dx and dy */ + int ady; + int signdx; /* sign of dx and dy */ + int signdy; + int e, e1, e2; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + int cmd; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + cmd = LASTPIX; + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } + else + { + cmd |= YMAJAXIS; + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + len = ady; + } + + /* S3 line drawing hardware has limited resolution for error terms */ + if (len >= 4096) + { + int dashOff = 0; + + KdCheckSync (pDrawable->pScreen); + fbSegment (pDrawable, pGC, x1, y1, x2, y2, drawLast, &dashOff); + return FALSE; + } + + FIXUP_ERROR (e, octant, bias); + + nBox = REGION_NUM_RECTS (pClip); + pBox = REGION_RECTS (pClip); + + if (signdx > 0) + cmd |= INC_X; + if (signdy > 0) + cmd |= INC_Y; + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + if (drawLast) + len++; + while(nBox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pBox); + OUTCODES(oc2, x2, y2, pBox); + if ((oc1 | oc2) == 0) + { + if (!s3Set) + { + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + s3Set = TRUE; + } + _s3SetCur (s3, x1, y1); + _s3ClipLine (s3, cmd, e1, e2, e, len); + break; + } + else if (oc1 & oc2) + { + pBox++; + } + else + { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int clipdx, clipdy; + int err; + + if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1, + pBox->y2-1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) + { + pBox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); + if (clip2 != 0 || drawLast) + len++; + if (len) + { + /* unwind bresenham error term to first point */ + err = e; + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + err += (e2 - e1) * clipdy + e1 * clipdx; + else + err += (e2 - e1) * clipdx + e1 * clipdy; + } + if (!s3Set) + { + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask); + s3Set = TRUE; + } + _s3SetCur (s3, new_x1, new_y1); + _s3ClipLine (s3, cmd, e1, e2, err, len); + } + pBox++; + } + } /* while (nBox--) */ + return s3Set; +} + +void +s3Polylines (DrawablePtr pDrawable, GCPtr pGC, + int mode, int npt, DDXPointPtr ppt) +{ + SetupS3(pDrawable->pScreen); + int x, y, nx, ny; + int ox = pDrawable->x, oy = pDrawable->y; + Bool s3Set = FALSE; + + if (!npt) + return; + + x = ppt->x + ox; + y = ppt->y + oy; + while (--npt) + { + ++ppt; + if (mode == CoordModePrevious) + { + nx = x + ppt->x; + ny = y + ppt->y; + } + else + { + nx = ppt->x + ox; + ny = ppt->y + oy; + } + s3Set = _s3Segment (pDrawable, pGC, x, y, nx, ny, + npt == 1 && pGC->capStyle != CapNotLast, + s3Set); + x = nx; + y = ny; + } + if (s3Set) + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3PolySegment (DrawablePtr pDrawable, GCPtr pGC, + int nsegInit, xSegment *pSegInit) +{ + SetupS3(pDrawable->pScreen); + int x, y; + int ox = pDrawable->x, oy = pDrawable->y; + RegionPtr pClip = fbGetCompositeClip (pGC); + BoxPtr pBox; + int nbox; + int nseg; + xSegment *pSeg; + int dx, dy; + int maj, min, len, inc; + int t; + CARD32 cmd; + CARD32 init_cmd; + Bool drawLast; + Bool s3Set = FALSE; + + drawLast = pGC->capStyle != CapNotLast; + + for (nseg = nsegInit, pSeg = pSegInit; nseg--; pSeg++) + { + s3Set = _s3Segment (pDrawable, pGC, pSeg->x1 + ox, pSeg->y1 + oy, + pSeg->x2 + ox, pSeg->y2 + oy, drawLast, s3Set); + + } + if (s3Set) + MarkSyncS3 (pDrawable->pScreen); +} + +/* + * Check to see if a pattern can be painted with the S3 + */ + +#define _s3CheckPatternSize(s) ((s) <= S3_TILE_SIZE && ((s) & ((s) - 1)) == 0) +#define s3CheckPattern(w,h) (_s3CheckPatternSize(w) && _s3CheckPatternSize(h)) + +Bool +s3AllocPattern (ScreenPtr pScreen, + int ma, + PixmapPtr pPixmap, + int xorg, int yorg, + int fillStyle, Pixel fg, Pixel bg, + s3PatternPtr *ppPattern) +{ + KdScreenPriv(pScreen); + s3ScreenInfo(pScreenPriv); + s3PatternPtr pPattern; + + if (s3s->fb[ma].patterns.cache && fillStyle != FillSolid && + s3CheckPattern (pPixmap->drawable.width, pPixmap->drawable.height)) + { + if (!(pPattern = *ppPattern)) + { + pPattern = (s3PatternPtr) xalloc (sizeof (s3PatternRec)); + if (!pPattern) + return FALSE; + *ppPattern = pPattern; + } + + pPattern->cache = 0; + pPattern->id = 0; + pPattern->pPixmap = pPixmap; + pPattern->fillStyle = fillStyle; + pPattern->xrot = (-xorg) & (S3_TILE_SIZE-1); + pPattern->yrot = (-yorg) & (S3_TILE_SIZE-1); + pPattern->fore = fg; + pPattern->back = bg; + return TRUE; + } + else + { + if (*ppPattern) + { + xfree (*ppPattern); + *ppPattern = 0; + } + return FALSE; + } +} + +void +s3CheckGCFill (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + PixmapPtr pPixmap; + + switch (pGC->fillStyle) { + case FillSolid: + pPixmap = 0; + break; + case FillOpaqueStippled: + case FillStippled: + pPixmap = pGC->stipple; + break; + case FillTiled: + pPixmap = pGC->tile.pixmap; + break; + } + s3AllocPattern (pGC->pScreen, + s3GCMap(pGC), + pPixmap, + pGC->patOrg.x + pGC->lastWinOrg.x, + pGC->patOrg.y + pGC->lastWinOrg.y, + pGC->fillStyle, pGC->fgPixel, pGC->bgPixel, + &s3Priv->pPattern); +} + +void +s3MoveGCFill (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + int xorg, yorg; + s3PatternPtr pPattern; + + if (pPattern = s3Priv->pPattern) + { + /* + * Reset origin + */ + xorg = pGC->patOrg.x + pGC->lastWinOrg.x; + yorg = pGC->patOrg.y + pGC->lastWinOrg.y; + pPattern->xrot = (-xorg) & (S3_TILE_SIZE - 1); + pPattern->yrot = (-yorg) & (S3_TILE_SIZE - 1); + /* + * Invalidate cache entry + */ + pPattern->id = 0; + pPattern->cache = 0; + } +} + +/* + * S3 Patterns. These are always full-depth images, stored in off-screen + * memory. + */ + +Pixel +s3FetchPatternPixel (s3PatternPtr pPattern, int x, int y) +{ + CARD8 *src; + CARD16 *src16; + CARD32 *src32; + PixmapPtr pPixmap = pPattern->pPixmap; + + x = (x + pPattern->xrot) % pPixmap->drawable.width; + y = (y + pPattern->yrot) % pPixmap->drawable.height; + src = (CARD8 *) pPixmap->devPrivate.ptr + y * pPixmap->devKind; + switch (pPixmap->drawable.bitsPerPixel) { + case 1: + return (src[x>>3] >> (x & 7)) & 1 ? 0xffffffff : 0x00; + case 4: + if (x & 1) + return src[x>>1] >> 4; + else + return src[x>>1] & 0xf; + case 8: + return src[x]; + case 16: + src16 = (CARD16 *) src; + return src16[x]; + case 32: + src32 = (CARD32 *) src; + return src32[x]; + } +} + +/* + * Place pattern image on screen; done with S3 locked + */ +void +_s3PutPattern (ScreenPtr pScreen, int ma, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + int x, y; + CARD8 *dstLine, *dst8; + CARD16 *dst16; + CARD32 *dst32; + S3PatternCache *cache = pPattern->cache; +#ifdef S3_TRIO + int fb = 0; +#else + int fb = s3s->fbmap[ma]; +#endif + + DRAW_DEBUG ((DEBUG_PATTERN, "_s3PutPattern 0x%x id %d to %d %d", + pPattern, pPattern->id, cache->x, cache->y)); + + dstLine = (pScreenPriv->screen->fb[fb].frameBuffer + + cache->y * pScreenPriv->screen->fb[fb].byteStride + + cache->x * pScreenPriv->bytesPerPixel[fb]); + + CheckSyncS3 (pScreen); + + for (y = 0; y < S3_TILE_SIZE; y++) + { + switch (pScreenPriv->screen->fb[fb].bitsPerPixel) { + case 8: + dst8 = dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst8++ = s3FetchPatternPixel (pPattern, x, y); + DRAW_DEBUG ((DEBUG_PATTERN, "%c%c%c%c%c%c%c%c", + dstLine[0] ? 'X' : ' ', + dstLine[1] ? 'X' : ' ', + dstLine[2] ? 'X' : ' ', + dstLine[3] ? 'X' : ' ', + dstLine[4] ? 'X' : ' ', + dstLine[5] ? 'X' : ' ', + dstLine[6] ? 'X' : ' ', + dstLine[7] ? 'X' : ' ')); + break; + case 16: + dst16 = (CARD16 *) dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst16++ = s3FetchPatternPixel (pPattern, x, y); + break; + case 32: + dst32 = (CARD32 *) dstLine; + for (x = 0; x < S3_TILE_SIZE; x++) + *dst32++ = s3FetchPatternPixel (pPattern, x, y); + break; + } + dstLine += pScreenPriv->screen->fb[fb].byteStride; + } +} + +/* + * Load a stipple to off-screen memory; done with S3 locked + */ +void +_s3LoadPattern (ScreenPtr pScreen, int ma, s3PatternPtr pPattern) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + S3PatternCache *cache; + + DRAW_DEBUG((DEBUG_PATTERN, + "s3LoadPattern 0x%x id %d cache 0x%x cacheid %d", + pPattern, pPattern->id, pPattern->cache, + pPattern->cache ? pPattern->cache->id : -1)); + /* + * Check to see if its still loaded + */ + cache = pPattern->cache; + if (cache && cache->id == pPattern->id) + return; + /* + * Lame replacement strategy; assume we'll have plenty of room. + */ + cache = &s3s->fb[ma].patterns.cache[s3s->fb[ma].patterns.last_used]; + if (++s3s->fb[ma].patterns.last_used == s3s->fb[ma].patterns.ncache) + s3s->fb[ma].patterns.last_used = 0; + cache->id = ++s3s->fb[ma].patterns.last_id; + pPattern->id = cache->id; + pPattern->cache = cache; + _s3PutPattern (pScreen, ma, pPattern); +} + +void +s3DestroyGC (GCPtr pGC) +{ + s3PrivGCPtr s3Priv = s3GetGCPrivate (pGC); + + if (s3Priv->pPattern) + xfree (s3Priv->pPattern); + miDestroyGC (pGC); +} + +GCFuncs s3GCFuncs = { + s3ValidateGC, + miChangeGC, + miCopyGC, + s3DestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +int +s3CreateGC (GCPtr pGC) +{ + KdScreenPriv(pGC->pScreen); + s3ScreenInfo(pScreenPriv); + s3PrivGCPtr s3Priv; + + if (!fbCreateGC (pGC)) + return FALSE; + + if (pGC->depth != 1) + pGC->funcs = &s3GCFuncs; + + s3Priv = s3GetGCPrivate(pGC); + s3Priv->type = DRAWABLE_PIXMAP; + s3Priv->pPattern = 0; +#ifndef S3_TRIO + if (pGC->depth == s3s->primary_depth) + s3Priv->ma = 0; + else + s3Priv->ma = 1; +#endif + return TRUE; +} + +Bool +s3CreateWindow (WindowPtr pWin) +{ + KdScreenPriv(pWin->drawable.pScreen); + s3ScreenInfo(pScreenPriv); + + dixSetPrivate(&pWin->devPrivates, s3WindowPrivateKey, NULL); + return KdCreateWindow (pWin); +} + +Bool +s3DestroyWindow (WindowPtr pWin) +{ + s3PatternPtr pPattern; + if (pPattern = s3GetWindowPrivate(pWin)) + xfree (pPattern); + return fbDestroyWindow (pWin); +} + +Bool +s3ChangeWindowAttributes (WindowPtr pWin, Mask mask) +{ + KdScreenPriv(pWin->drawable.pScreen); + Bool ret; + s3PatternPtr pPattern; + PixmapPtr pPixmap; + int fillStyle; + + ret = fbChangeWindowAttributes (pWin, mask); + if (mask & CWBackPixmap) + { + if (pWin->backgroundState == BackgroundPixmap) + { + pPixmap = pWin->background.pixmap; + fillStyle = FillTiled; + } + else + { + pPixmap = 0; + fillStyle = FillSolid; + } + pPattern = s3GetWindowPrivate(pWin); + s3AllocPattern (pWin->drawable.pScreen, + s3DrawMap (&pWin->drawable), + pPixmap, + pWin->drawable.x, pWin->drawable.y, + fillStyle, 0, 0, &pPattern); + DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "Background pattern 0x%x pixmap 0x%x style %d", + pPattern, pPixmap, fillStyle)); + s3SetWindowPrivate (pWin, pPattern); + } + return ret; +} + + +#ifndef S3_TRIO +void +s3PaintKey (DrawablePtr pDrawable, + RegionPtr pRegion, + CARD32 pixel, + int fb) +{ + SetupS3 (pDrawable->pScreen); + s3ScreenInfo (pScreenPriv); + int nBox = REGION_NUM_RECTS(pRegion); + BoxPtr pBox = REGION_RECTS(pRegion); + int ma; + + if (!nBox) + return; + + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + if (s3s->fbmap[ma] == fb) + break; + s3SetGlobalBitmap (pDrawable->pScreen, ma); + _s3SetSolidFill (s3, pixel, GXcopy, 0xffffffff); + while (nBox--) + { + _s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1); + pBox++; + } + MarkSyncS3 (pDrawable->pScreen); +} +#endif + +void +s3CopyWindowProc (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pboxOrig, + int nboxOrig, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + s3ScreenInfo(pScreenPriv); + KdScreenInfo *screen = pScreenPriv->screen; + int srcX, srcY, dstX, dstY; + int x1, x2; + int w, h; + int flags; + int fb = (int) closure; + int ma; + BoxPtr pbox; + int nbox; + int bitsPerPixel; + +#ifdef S3_TRIO + ma = 0; +#else + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) + if (s3s->fbmap[ma] == fb) + break; +#endif + bitsPerPixel = screen->fb[fb].bitsPerPixel; + if (bitsPerPixel == 24) + dx *= 3; + nbox = nboxOrig; + pbox = pboxOrig; + s3SetGlobalBitmap (pDstDrawable->pScreen, ma); + _s3SetBlt(s3,GXcopy,~0); + while (nbox--) + { + x1 = pbox->x1; + x2 = pbox->x2; + if (bitsPerPixel == 24) + { + x1 *= 3; + x2 *= 3; + } + + w = x2 - x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = x2 - 1; + } + else + { + dstX = x1; + flags |= INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= INC_Y; + } + srcY = dstY + dy; + + _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags); + pbox++; + } + MarkSyncS3 (pDstDrawable->pScreen); +} + +void +s3CopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdScreenPriv (pScreen); + s3ScreenInfo (pScreenPriv); + KdScreenInfo *screen = pScreenPriv->screen; + 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, s3CopyWindowProc, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + +void +s3_24FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask) +{ + SetupS3(pDrawable->pScreen); + register int r; + int x1, x2; + + s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable)); + _s3SetSolidFill(s3,pixel,alu,planemask); + + while (nBox--) { + x1 = pBox->x1 * 3; + x2 = pBox->x2 * 3; + _s3SolidRect(s3,x1,pBox->y1,x2-x1,pBox->y2-pBox->y1); + pBox++; + } + MarkSyncS3 (pDrawable->pScreen); +} + +#define ok24(p) (((p) & 0xffffff) == ((((p) & 0xff) << 16) | (((p) >> 8) & 0xffff))) + +void +s3_24FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + SetupS3(pDrawable->pScreen); + int x, y, x1, y1, x2, y2; + int width; + /* next three parameters are post-clip */ + int nTmp; + int *pwidthFree;/* copies of the pointers to free */ + DDXPointPtr pptFree; + BoxPtr extents; + RegionPtr pClip = fbGetCompositeClip (pGC); + + if (pGC->fillStyle != FillSolid || !ok24 (pGC->fgPixel) || !ok24(pGC->planemask)) + { + KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); + return; + } + + s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC)); + if (REGION_NUM_RECTS(pClip) == 1) + { + extents = REGION_RECTS(pClip); + x1 = extents->x1; + x2 = extents->x2; + y1 = extents->y1; + y2 = extents->y2; + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + while (n--) + { + y = ppt->y; + if (y1 <= y && y < y2) + { + x = ppt->x; + width = *pwidth; + if (x < x1) + { + width -= (x1 - x); + x = x1; + } + if (x2 < x + width) + width = x2 - x; + if (width > 0) + { + _s3SolidRect(s3,x*3,y,width*3,1); + } + } + ppt++; + pwidth++; + } + } + else + { + nTmp = n * miFindMaxBand(pClip); + pwidthFree = (int *)xalloc(nTmp * sizeof(int)); + pptFree = (DDXPointRec *)xalloc(nTmp * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) xfree(pptFree); + if (pwidthFree) xfree(pwidthFree); + return; + } + n = miClipSpans(fbGetCompositeClip(pGC), + ppt, pwidth, n, + pptFree, pwidthFree, fSorted); + pwidth = pwidthFree; + ppt = pptFree; + _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask); + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _s3SolidRect(s3,x*3,y,width*3,1); + } + } + xfree(pptFree); + xfree(pwidthFree); + } + MarkSyncS3 (pDrawable->pScreen); +} + +void +s3_24CopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupS3(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + int flags; + int x1, x2; + + if (sourceInvarient (pGC->alu)) + { + s3_24FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask); + return; + } + + s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC)); + _s3SetBlt(s3,pGC->alu,pGC->planemask); + DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x", + pGC->alu, pGC->planemask)); + dx *= 3; + while (nbox--) + { + x1 = pbox->x1 * 3; + x2 = pbox->x2 * 3; + w = x2 - x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = x2 - 1; + } + else + { + dstX = x1; + flags |= INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= INC_Y; + } + srcY = dstY + dy; + + _s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags); + pbox++; + } + MarkSyncS3 (pSrcDrawable->pScreen); +} + +RegionPtr +s3_24CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + SetupS3(pDstDrawable->pScreen); + + if (pSrcDrawable->type == DRAWABLE_WINDOW && + pDstDrawable->type == DRAWABLE_WINDOW && + ok24(pGC->planemask)) + { + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, s3_24CopyNtoN, 0, 0); + } + return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); +} + + +#define NUM_STACK_RECTS 1024 + +void +s3_24PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + s3GCPrivate(pGC); + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + int numRects; + int n; + int xorg, yorg; + int x, y; + + if (pGC->fillStyle != FillSolid || !ok24 (pGC->fgPixel) || !ok24(pGC->planemask)) + { + KdCheckPolyFillRect (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) + { + s3_24FillBoxSolid(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->fgPixel, pGC->alu, pGC->planemask); + } + if (pboxClippedBase != stackRects) + xfree(pboxClippedBase); +} + +void +s3_24SolidBoxClipped (DrawablePtr pDrawable, + RegionPtr pClip, + int x1, + int y1, + int x2, + int y2, + FbBits fg) +{ + SetupS3 (pDrawable->pScreen); + BoxPtr pbox; + int nbox; + int partX1, partX2, partY1, partY2; + + s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable)); + _s3SetSolidFill(s3,fg,GXcopy,~0); + + 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; + + partX1 *= 3; + partX2 *= 3; + _s3SolidRect(s3,partX1, partY1, partX2-partX1, partY2-partY1); + } + MarkSyncS3(pDrawable->pScreen); +} + +void +s3_24ImageGlyphBlt (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; + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbBits depthMask; + int xBack, widthBack; + int yBack, heightBack; + + depthMask = FbFullMask(pDrawable->depth); + if (!ok24 (pGC->fgPixel) || + !ok24(pGC->bgPixel) || + !ok24(pGC->planemask)) + { + KdCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); + return; + } + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + x += pDrawable->x; + y += pDrawable->y; + + 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); + s3_24SolidBoxClipped (pDrawable, + fbGetCompositeClip(pGC), + xBack, + yBack, + xBack + widthBack, + yBack + heightBack, + pPriv->bg); + + KdCheckSync (pDrawable->pScreen); + + 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 (gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) + { + fbGlyph24 (dst + (gy - dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, + pPriv->fg, + gx - dstXoff, + gHeight); + } + else + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + GXcopy, + FALSE, + + gx, + gy, + gWidth, gHeight, + + (FbStip *) pglyph, + gStride, + 0); + } + } + x += pci->metrics.characterWidth; + } +} + +static const GCOps s3_24GCOps = { + s3_24FillSpans, + KdCheckSetSpans, + KdCheckPutImage, + KdCheckCopyArea, + KdCheckCopyPlane, + KdCheckPolyPoint, + KdCheckPolylines, + KdCheckPolySegment, + KdCheckPolyRectangle, + KdCheckPolyArc, + KdCheckFillPolygon, + s3_24PolyFillRect, + KdCheckPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3_24ImageGlyphBlt, + KdCheckPolyGlyphBlt, + KdCheckPushPixels, +}; + +void +s3_24ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + if (pDrawable->type != DRAWABLE_WINDOW) + pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; + else + pGC->ops = (GCOps *) &s3_24GCOps; + fbValidateGC (pGC, changes, pDrawable); +} + +GCFuncs s3_24GCFuncs = { + s3_24ValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +Bool +s3_24CreateGC (GCPtr pGC) +{ + if (!fbCreateGC (pGC)) + return FALSE; + + if (pGC->depth != 1) + pGC->funcs = &s3_24GCFuncs; + + return TRUE; +} + +Bool +s3_24CreateWindow(WindowPtr pWin) +{ + return fbCreateWindow (pWin); +} + + +Bool +s3DrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + s3ScreenInfo(pScreenPriv); + int ncache_w, ncache_h, ncache; + int px, py; + S3PatternCache *cache; + Bool dumb = FALSE; + int ma; + + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 8: + case 16: + case 32: + break; + case 24: + dumb = TRUE; + break; + default: + return FALSE; + } + /* + * Hook up asynchronous drawing + */ + RegisterSync (pScreen); + /* + * Replace various fb screen functions + */ + if (dumb) + { + pScreen->CreateGC = s3_24CreateGC; + pScreen->CreateWindow = s3_24CreateWindow; + pScreen->CopyWindow = s3CopyWindow; + } + else + { + if (!dixRequestPrivate(s3GCPrivateKey, sizeof (s3PrivGCRec))) + return FALSE; + pScreen->CreateGC = s3CreateGC; + pScreen->CreateWindow = s3CreateWindow; + pScreen->ChangeWindowAttributes = s3ChangeWindowAttributes; + pScreen->DestroyWindow = s3DestroyWindow; +#ifndef S3_TRIO + if (pScreenPriv->screen->fb[1].depth) + { + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + pScrPriv->PaintKey = s3PaintKey; + pScrPriv->CopyWindow = s3CopyWindowProc; + pScreen->CopyWindow = fbOverlayCopyWindow; + } + else +#endif + pScreen->CopyWindow = s3CopyWindow; + + /* + * Initialize patterns + */ +#ifdef S3_TRIO + ma = 0; +#else + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) +#endif + { + ncache_w = s3s->fb[ma].offscreen_width / S3_TILE_SIZE; + ncache_h = s3s->fb[ma].offscreen_height / S3_TILE_SIZE; + ncache = ncache_w * ncache_h; + if (ncache > 64) + ncache = 64; + DRAW_DEBUG ((DEBUG_S3INIT, "ncache_w %d ncache_h %d ncache %d", + ncache_w, ncache_h, ncache)); + s3s->fb[ma].patterns.cache = (S3PatternCache *) xalloc (ncache * sizeof (S3PatternCache)); + if (s3s->fb[ma].patterns.cache) + { + DRAW_DEBUG ((DEBUG_S3INIT, "Have pattern cache")); + s3s->fb[ma].patterns.ncache = ncache; + s3s->fb[ma].patterns.last_used = 0; + s3s->fb[ma].patterns.last_id = 0; + cache = s3s->fb[ma].patterns.cache; + for (py = 0; py < ncache_h && ncache; py++) + for (px = 0; px < ncache_w && ncache; px++) + { + cache->id = 0; + cache->x = s3s->fb[ma].offscreen_x + px * S3_TILE_SIZE; + cache->y = s3s->fb[ma].offscreen_y + py * S3_TILE_SIZE; + cache++; + ncache--; + } + } + } + } + return TRUE; +} + +void +s3DrawEnable (ScreenPtr pScreen) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + int c; + int ma; + + s3SetGlobalBitmap (pScreen, 0); + _s3WaitIdleEmpty (s3); + if (pScreenPriv->screen->fb[0].bitsPerPixel == 24) + { + _s3SetScissorsTl(s3, 0, 0); + _s3SetScissorsBr(s3, pScreenPriv->screen->width*3 - 1, pScreenPriv->screen->height - 1); + _s3SetSolidFill(s3, pScreen->whitePixel, GXcopy, ~0); + _s3SolidRect (s3, 0, 0, pScreenPriv->screen->width*3, pScreenPriv->screen->height); + } + else + { + /* + * Flush pattern cache + */ +#ifdef S3_TRIO + ma = 0; +#else + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) +#endif + { + for (c = 0; c < s3s->fb[ma].patterns.ncache; c++) + s3s->fb[ma].patterns.cache[c].id = 0; + } + + _s3SetScissorsTl(s3, 0, 0); + _s3SetScissorsBr(s3, pScreenPriv->screen->width - 1, pScreenPriv->screen->height - 1); + _s3SetSolidFill(s3, pScreen->blackPixel, GXcopy, ~0); + _s3SolidRect (s3, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height); + } + MarkSyncS3 (pScreen); +} + +void +s3DrawDisable (ScreenPtr pScreen) +{ + SetupS3 (pScreen); + _s3WaitIdleEmpty (s3); +} + +void +s3DrawFini (ScreenPtr pScreen) +{ + SetupS3(pScreen); + s3ScreenInfo(pScreenPriv); + int ma; + +#ifdef S3_TRIO + ma = 0; +#else + for (ma = 0; s3s->fbmap[ma] >= 0; ma++) +#endif + { + if (s3s->fb[ma].patterns.cache) + { + xfree (s3s->fb[ma].patterns.cache); + s3s->fb[ma].patterns.cache = 0; + s3s->fb[ma].patterns.ncache = 0; + } + } +} + +void +s3DrawSync (ScreenPtr pScreen) +{ + SetupS3(pScreen); + + _s3WaitIdleEmpty(s3c->s3); +} diff --git a/xserver/hw/kdrive/savage/s3draw.h b/xserver/hw/kdrive/savage/s3draw.h new file mode 100644 index 000000000..eab8e395e --- /dev/null +++ b/xserver/hw/kdrive/savage/s3draw.h @@ -0,0 +1,468 @@ +/* + * 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. + */ + +#ifndef _S3DRAW_H_ +#define _S3DRAW_H_ + +extern DevPrivateKey s3GCPrivateKey; +extern DevPrivateKey s3WindowPrivateKey; + +typedef struct _s3Pattern { + S3PatternCache *cache; + int id; + PixmapPtr pPixmap; + int fillStyle; + int xrot, yrot; + unsigned int fore, back; +} s3PatternRec, *s3PatternPtr; + +typedef struct _s3PrivGC { + int type; /* type of drawable validated against */ + int ma; /* stream descriptor */ + s3PatternPtr pPattern; /* pattern */ +} s3PrivGCRec, *s3PrivGCPtr; + +#define s3GetGCPrivate(g) ((s3PrivGCPtr) \ + dixLookupPrivate(&(g)->devPrivates, s3GCPrivateKey)) + +#define s3GCPrivate(g) s3PrivGCPtr s3Priv = s3GetGCPrivate(g) + +#define s3GetWindowPrivate(w) ((s3PatternPtr) \ + dixLookupPrivate(&(w)->devPrivates, s3WindowPrivateKey)) + +#define s3SetWindowPrivate(w,p) \ + dixSetPrivate(&(w)->devPrivates, s3WindowPrivateKey, p) + +void _s3LoadPattern (ScreenPtr pScreen, int fb, s3PatternPtr pPattern); + +#define SetupS3(s) KdScreenPriv(s); \ + s3CardInfo(pScreenPriv); \ + S3Ptr s3 = s3c->s3 + +#ifdef S3_SYNC_DEBUG +#define SYNC_DEBUG() fprintf (stderr, "Sync at %s:%d\n", __FILE__,__LINE__) +#else +#define SYNC_DEBUG() +#endif + +#define S3_ASYNC +#ifdef S3_ASYNC +#define CheckSyncS3(s) KdCheckSync(s) +#define MarkSyncS3(s) KdMarkSync(s) +#define RegisterSync(screen) KdScreenInitAsync (screen) +#else +#define CheckSyncS3(s3c) +#define MarkSyncS3(s3c) _s3WaitIdleEmpty(s3c->s3) +#define RegisterSync(screen) +#endif + +#define WIDEN(x) ((unsigned long) (x)) +#define MERGE(a,b) ((WIDEN(a) << 16) | WIDEN(b)) + +#define s3BitmapDescriptor(_stream) ((_stream) + 1) + +#ifdef S3_TRIO +#define s3DrawMap(pDraw) 0 +#define s3SetGlobalBitmap(s,d) +#else +#define s3DrawMap(pDraw) ((pDraw)->depth == \ + getS3ScreenInfo(pScreenPriv)->primary_depth ? 0 : 1) +#endif + +#define s3GCMap(pGC) (s3GetGCPrivate(pGC)->ma) + +/* + * Ok, so the S3 is broken -- it expects bitmaps to come MSB bit order, + * but it's willing to take them in LSB byte order. These macros + * flip bits around without flipping bytes. Instead of using a table + * and burning memory bandwidth, do them in place with the CPU. + */ + +/* The MIPS compiler automatically places these constants in registers */ +#define S3InvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +#define S3InvertBits16(v) { \ + v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \ + v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \ + v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \ +} + +#define S3InvertBits8(v) { \ + v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \ + v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \ + v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \ +} + +#define S3ByteSwap32(x) ((x) = (((x) >> 24) | \ + (((x) >> 8) & 0xff00) | \ + (((x) << 8) & 0xff0000) | \ + ((x) << 24))) + +#define S3ByteSwap16(x) ((x) = ((x) << 8) | ((x) >> 8)) + +#if BITMAP_BIT_ORDER == LSBFirst +#define S3AdjustBits32(x) S3InvertBits32(x) +#define S3AdjustBits16(x) S3InvertBits16(x) +#else +#define S3AdjustBits32(x) S3ByteSwap32(x) +#define S3AdjustBits16(x) S3ByteSwap16(x) +#endif + +#define _s3WaitSlot(s3) _s3WaitSlots(s3,1) + +#define _s3SetFg(s3,_fg) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " fg <- 0x%x", _fg));\ + s3->fg = (_fg); \ +} + +#define _s3SetBg(s3,_bg) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " bg <- 0x%x", _bg));\ + s3->bg = (_bg); \ +} + +#define _s3SetWriteMask(s3,_mask) {\ + DRAW_DEBUG((DEBUG_REGISTERS," write_mask <- 0x%x", _mask)); \ + s3->write_mask = (_mask); \ +} + +#define _s3SetReadMask(s3,_mask) {\ + DRAW_DEBUG((DEBUG_REGISTERS," read_mask <- 0x%x", _mask)); \ + s3->read_mask = (_mask); \ +} + +#define _s3SetPixelControl(s3,_ctl) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " pix_cntl <- 0x%x", PIX_CNTL | (_ctl))); \ + s3->pix_cntl_mult_misc2 = MERGE (CONTROL_MISC2, PIX_CNTL | (_ctl)); \ +} + +#define _s3SetFgMix(s3,_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " fg_mix <- 0x%x", _mix)); \ + s3->enh_fg_mix = (_mix); \ +} + +#define _s3SetBgMix(s3,_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " bg_mix <- 0x%x", _mix)); \ + s3->enh_bg_mix = (_mix); \ +} + +#define _s3SetMix(s3,fg_mix,bg_mix) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " alt_mix <- 0x%x", MERGE(fg_mix,bg_mix))); \ + s3->alt_mix = MERGE(fg_mix,bg_mix); \ +} + +#define _s3SetCur(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_curxy <- 0x%x", MERGE(_x,_y))); \ + s3->alt_curxy = MERGE(_x,_y); \ +} + +#define _s3SetStep(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_step <- 0x%x", MERGE(_x,_y))); \ + s3->alt_step = MERGE(_x,_y); \ +} + +#define _s3SetErr(s3,_e) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " err_term <- 0x%x", _e)); \ + s3->err_term = (_e); \ +} + +#define _s3SetPcnt(s3,_x,_y) { \ + DRAW_DEBUG ((DEBUG_REGISTERS, " alt_pcnt <- 0x%x", MERGE(_x,_y))); \ + s3->alt_pcnt = MERGE(_x,_y); \ +} + +#define _s3SetScissorsTl(s3,t,l) {\ + DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_tl <- 0x%x", MERGE(t,l))); \ + s3->scissors_tl = MERGE(t,l); \ +} + +#define _s3SetScissorsBr(s3,b,r) {\ + DRAW_DEBUG ((DEBUG_REGISTERS, " scissors_br <- 0x%x", MERGE(b,r))); \ + s3->scissors_br = MERGE(b,r); \ +} + +#define _s3CmdWait(s3) + +#define _s3SetCmd(s3,_cmd) { \ + DRAW_DEBUG((DEBUG_REGISTERS, " cmd <- 0x%x", _cmd)); \ + _s3CmdWait(s3); \ + s3->cmd_gp_stat = (_cmd); \ + /* { CARD32 __junk__; __junk__ = s3->cmd_gp_stat; } */ \ +} + +#define _s3SetSolidFill(s3,pix,alu,mask) { \ + DRAW_DEBUG((DEBUG_SET,"set fill 0x%x %d 0x%x",pix,alu,mask)); \ + _s3WaitSlots(s3,4); \ + _s3SetFg (s3, pix); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL | MIX_SRC); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SolidRect(s3,x,y,w,h) {\ + DRAW_DEBUG((DEBUG_RENDER,"solid rect %d,%d %dx%d",x,y,w,h)); \ + _s3WaitSlots(s3,3); \ + _s3SetCur(s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, CMD_RECT|INC_X|INC_Y|DRAW|WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SolidLine(s3,maj,min,len,cmd) { \ + DRAW_DEBUG ((DEBUG_RENDER, "solid line 0x%x 0x%x 0x%x", maj, min, cmd)); \ + _s3WaitSlots(s3,4); \ + _s3SetPcnt(s3, (len), 0); \ + _s3SetStep(s3, 2*((min) - (maj)), 2*(min)); \ + _s3SetErr(s3, 2*(min) - (maj)); \ + _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \ +} + +#define _s3ClipLine(s3,cmd,e1,e2,e,len) {\ + DRAW_DEBUG ((DEBUG_RENDER, "clip line 0x%x 0x%x 0x%x 0x%x 0x%x", cmd,e1,e2,e,len)); \ + _s3WaitSlots(s3, 4); \ + _s3SetPcnt (s3, (len), 0); \ + _s3SetStep (s3, e2, e1); \ + _s3SetErr (s3, e); \ + _s3SetCmd (s3, CMD_LINE | (cmd) | DRAW | WRTDATA); \ +} + +#define _s3SetTile(s3,alu,mask) { \ + DRAW_DEBUG ((DEBUG_SET,"set tile %d 0x%x", alu, mask)); \ + _s3WaitSlots(s3,3); \ + _s3SetWriteMask(s3, mask); \ + _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT|s3alu[alu]); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +/* + * For some reason, MIX_DST doesn't work in this mode; use MIX_OR with + * an explicit 0 pixel value + */ +#define _s3SetStipple(s3,alu,mask,_fg) {\ + DRAW_DEBUG ((DEBUG_SET,"set stipple 0x%x %d 0x%x", _fg, alu, mask)); \ + _s3WaitSlots(s3,5); \ + _s3SetFg (s3, _fg); \ + _s3SetBg (s3, 0); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|MIX_OR); \ + _s3SetPixelControl (s3, MIXSEL_EXPBLT); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SetOpaqueStipple(s3,alu,mask,_fg,_bg) {\ + DRAW_DEBUG ((DEBUG_SET,"set opaque stipple 0x%x 0x%x %d 0x%x", _fg, _bg, alu, mask)); \ + _s3WaitSlots(s3,5); \ + _s3SetFg (s3, _fg); \ + _s3SetBg (s3, _bg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix (s3, FSS_FRGDCOL | s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \ + _s3SetPixelControl (s3, MIXSEL_EXPBLT); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3PatRect(s3,px,py,x,y,w,h) {\ + DRAW_DEBUG ((DEBUG_RENDER, "pat rect %d,%d %dx%d", x,y,w,h)); \ + _s3WaitSlots(s3, 4); \ + _s3SetCur (s3, px, py); \ + _s3SetStep (s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, CMD_PATBLT|INC_X|INC_Y|DRAW|PLANAR|WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetBlt(s3,alu,mask) { \ + DRAW_DEBUG ((DEBUG_SET,"set blt %d 0x%x", alu, mask)); \ + _s3WaitSlots(s3,3); \ + _s3SetPixelControl (s3, MIXSEL_FRGDMIX); \ + _s3SetMix(s3, FSS_BITBLT | s3alu[alu], BSS_BITBLT | s3alu[alu]); \ + _s3SetWriteMask(s3, mask); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3Blt(s3,_sx,_sy,_dx,_dy,_w,_h,_dir) { \ + DRAW_DEBUG ((DEBUG_RENDER, "blt %d,%d -> %d,%d %dx%d 0x%x", \ + _sx,_sy,_dx,_dy,_w,_h,_dir)); \ + _s3WaitSlots(s3,4); \ + _s3SetCur(s3,_sx,_sy); \ + _s3SetStep(s3,_dx,_dy); \ + _s3SetPcnt(s3,(_w)-1,(_h)-1); \ + _s3SetCmd (s3, CMD_BITBLT | (_dir) | DRAW | WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetOpaquePlaneBlt(s3,alu,mask,_fg,_bg) {\ + DRAW_DEBUG ((DEBUG_SET,"set opaque plane blt 0x%x 0x%x %d 0x%x", \ + _fg, _bg, alu, mask)); \ + /* _s3WaitSlots(s3, 5); */ \ + _s3WaitIdleEmpty (s3); \ + _s3SetFg(s3,_fg); \ + _s3SetBg(s3,_bg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|s3alu[alu]); \ + _s3SetPixelControl(s3,MIXSEL_EXPPC); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3SetTransparentPlaneBlt(s3,alu,mask,_fg) {\ + DRAW_DEBUG ((DEBUG_SET,"set transparent plane blt 0x%x %d 0x%x", \ + _fg, alu, mask)); \ + /*_s3WaitSlots(s3, 4); */ \ + _s3WaitIdleEmpty (s3); \ + _s3SetFg(s3,_fg); \ + _s3SetWriteMask(s3,mask); \ + _s3SetMix(s3,FSS_FRGDCOL|s3alu[alu], BSS_BKGDCOL|MIX_DST); \ + _s3SetPixelControl(s3,MIXSEL_EXPPC); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +/* Across the plane blt */ +#define _s3PlaneBlt(s3,x,y,w,h) {\ + DRAW_DEBUG ((DEBUG_RENDER, "plane blt %d,%d %dx%d", x,y,w,h)); \ + _s3WaitSlots(s3, 4); \ + _s3SetPixelControl(s3,MIXSEL_EXPPC); \ + _s3SetCur(s3, x, y); \ + _s3SetPcnt (s3, (w)-1, (h)-1); \ + _s3SetCmd (s3, \ + CMD_RECT| /* Fill rectangle */ \ + BYTSEQ| /* LSB byte order */ \ + _32BIT| /* 32 bit data on 32 bit boundaries */ \ + PCDATA| /* Data from CPU */ \ + INC_X|INC_Y| /* X and Y both increasing */ \ + DRAW| /* Draw, not move */ \ + PLANAR| /* multi pixel */ \ + WRTDATA); \ + DRAW_DEBUG((DEBUG_RENDER," done")); \ +} + +#define _s3SetClip(s3,pbox) {\ + DRAW_DEBUG ((DEBUG_SET, "set clip %dx%d -> %dx%d ", \ + pbox->x1, pbox->y1, pbox->x2, pbox->y2)); \ + _s3WaitSlots(s3, 2); \ + _s3SetScissorsTl(s3,(pbox)->x1, (pbox)->y1); \ + _s3SetScissorsBr(s3,(pbox)->x2 - 1, (pbox)->y2 - 1); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +#define _s3ResetClip(s3,pScreen) { \ + DRAW_DEBUG ((DEBUG_SET, "reset clip")); \ + _s3WaitSlots(s3, 2); \ + _s3SetScissorsTl(s3,0,0); \ + _s3SetScissorsBr(s3,pScreen->width - 1, pScreen->height - 1); \ + DRAW_DEBUG((DEBUG_SET," done")); \ +} + +RegionPtr +s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty); + +RegionPtr +s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane); + +void +s3PushPixels (GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, + int w, int h, int x, int y); + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask); + +void +s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + int alu, unsigned long planemask, s3PatternPtr pPattern); + +void +s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit); + +void +s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted); + +void +s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs); + +void +s3FillPoly (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + +void +s3PolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase); + +void +s3ImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase); + +void +s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int xInit, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase); + +void +s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, + int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); + +void +s3Polylines (DrawablePtr pDrawable, GCPtr pGC, + int mode, int nptInit, DDXPointPtr pptInit); + +void +s3PolySegment (DrawablePtr pDrawable, GCPtr pGC, + int nsegInit, xSegment *pSegInit); + +void +s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu, unsigned long planemask); + +void s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable); + +void +s3CheckGCFill (GCPtr pGC); + +void +s3MoveGCFill (GCPtr pGC); + +void +s3SyncProc (DrawablePtr pDrawable); + +#endif diff --git a/xserver/hw/kdrive/savage/s3gc.c b/xserver/hw/kdrive/savage/s3gc.c new file mode 100644 index 000000000..ade14fa1f --- /dev/null +++ b/xserver/hw/kdrive/savage/s3gc.c @@ -0,0 +1,299 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" +#include "s3draw.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 "migc.h" + +/* + * Common op groups. Common assumptions: + * + * lineWidth 0 + * lineStyle LineSolid + * fillStyle FillSolid + * rop GXcopy + * font <= 32 pixels wide + */ + +/* TE font */ +static const GCOps s3TEOps = { + s3FillSpans, + KdCheckSetSpans, + KdCheckPutImage, + s3CopyArea, + s3CopyPlane, + KdCheckPolyPoint, + s3Polylines, + s3PolySegment, + KdCheckPolyRectangle, + KdCheckPolyArc, + s3FillPoly, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageTEGlyphBlt, + s3PolyTEGlyphBlt, + s3PushPixels +}; + +/* Non TE font */ +static const GCOps s3NonTEOps = { + s3FillSpans, + KdCheckSetSpans, + KdCheckPutImage, + s3CopyArea, + s3CopyPlane, + KdCheckPolyPoint, + s3Polylines, + s3PolySegment, + KdCheckPolyRectangle, + KdCheckPolyArc, + s3FillPoly, + s3PolyFillRect, + s3PolyFillArcSolid, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + s3ImageGlyphBlt, + s3PolyGlyphBlt, + s3PushPixels +}; + +static GCOps * +s3MatchCommon (DrawablePtr pDraw, GCPtr pGC, FbGCPrivPtr fbPriv) +{ + KdScreenPriv (pDraw->pScreen); + + if (!REGION_NOTEMPTY(pDraw->pScreen,fbGetCompositeClip(pGC))) + { + DRAW_DEBUG ((DEBUG_CLIP, "Empty composite clip, clipping all ops")); + return &kdNoopOps; + } + + if (pDraw->type != DRAWABLE_WINDOW) + return (GCOps *) &kdAsyncPixmapGCOps; + + if (pGC->lineWidth != 0) + return 0; + if (pGC->lineStyle != LineSolid) + return 0; + if (pGC->fillStyle != FillSolid) + return 0; + if (fbPriv->and != 0) + return 0; + if (pGC->font) + { + if (TERMINALFONT(pGC->font)) + return (GCOps *) &s3TEOps; + else + return (GCOps *) &s3NonTEOps; + } + return 0; +} + +void +s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + int new_type; /* drawable type has changed */ + int new_origin; + + /* flags for changing the proc vector */ + FbGCPrivPtr fbPriv; + s3PrivGCPtr s3Priv; + int oneRect; + GCOps *newops; + + fbPriv = fbGetGCPrivate(pGC); + s3Priv = s3GetGCPrivate(pGC); + + new_type = FALSE; + new_origin = FALSE; + + /* + * If the type of drawable has changed, fix up accelerated functions + */ + if (s3Priv->type != pDrawable->type) + { + new_type = TRUE; + s3Priv->type = pDrawable->type; + } + + /* + * Check tile/stipple origin + */ + if (pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y) + new_origin = TRUE; + + /* + * Call down to FB to set clip list and rrop values + */ + + fbValidateGC (pGC, changes, pDrawable); + + /* + * Check accelerated pattern if necessary + */ + if (changes & (GCFillStyle|GCStipple|GCTile)) + s3CheckGCFill (pGC); + else if (s3Priv->pPattern && + (new_origin || changes & (GCTileStipXOrigin|GCTileStipYOrigin))) + s3MoveGCFill (pGC); + + /* + * Try to match common vector + */ + + if (newops = s3MatchCommon (pDrawable, pGC, fbPriv)) + { + if (pGC->ops->devPrivate.val) + miDestroyGCOps (pGC->ops); + pGC->ops = newops; + return; + } + + /* + * No common vector matched, create private ops vector and + * fill it in + */ + if (!pGC->ops->devPrivate.val) + { + /* + * Switch from noop vector by first switching to fb + * vector and fixing it up + */ + if (pGC->ops == &kdNoopOps) + { + pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; + new_type = TRUE; + } + pGC->ops = miCreateGCOps (pGC->ops); + pGC->ops->devPrivate.val = 1; + } + + /* + * Fills + */ + if (new_type || (changes & (GCFillStyle|GCTile|GCStipple))) + { + pGC->ops->FillSpans = KdCheckFillSpans; + pGC->ops->PolyFillRect = KdCheckPolyFillRect; + if (s3Priv->type == DRAWABLE_WINDOW && + (pGC->fillStyle != FillTiled || s3Priv->pPattern)) + { + pGC->ops->FillSpans = s3FillSpans; + pGC->ops->PolyFillRect = s3PolyFillRect; + } + } + + /* + * Blt + */ + if (new_type) + { + pGC->ops->CopyArea = s3CopyArea; + pGC->ops->CopyPlane = s3CopyPlane; + pGC->ops->PushPixels = s3PushPixels; + } + + /* + * Lines + */ + if (new_type || (changes & (GCLineStyle|GCLineWidth|GCFillStyle))) + { + pGC->ops->Polylines = KdCheckPolylines; + pGC->ops->PolySegment = KdCheckPolySegment; + if (pGC->lineStyle == LineSolid && + pGC->lineWidth == 0 && + pGC->fillStyle == FillSolid && + s3Priv->type == DRAWABLE_WINDOW) + { + pGC->ops->Polylines = s3Polylines; + pGC->ops->PolySegment = s3PolySegment; + } + } + + /* + * Polygons + */ + if (new_type || (changes & (GCFillStyle))) + { + pGC->ops->FillPolygon = KdCheckFillPolygon; + if (s3Priv->type == DRAWABLE_WINDOW && + pGC->fillStyle == FillSolid) + { + pGC->ops->FillPolygon = s3FillPoly; + } + } + + /* + * Filled arcs + */ + if (new_type || (changes & GCFillStyle)) + { + pGC->ops->PolyFillArc = KdCheckPolyFillArc; + if (s3Priv->type == DRAWABLE_WINDOW && + pGC->fillStyle == FillSolid) + { + pGC->ops->PolyFillArc = s3PolyFillArcSolid; + } + } + + /* + * Text + */ + if (new_type || (changes & (GCFont|GCFillStyle))) + { + pGC->ops->PolyGlyphBlt = KdCheckPolyGlyphBlt; + pGC->ops->ImageGlyphBlt = KdCheckImageGlyphBlt; + if (s3Priv->type == DRAWABLE_WINDOW && pGC->font) + { + if (pGC->fillStyle == FillSolid) + { + if (TERMINALFONT(pGC->font)) + pGC->ops->PolyGlyphBlt = s3PolyTEGlyphBlt; + else + pGC->ops->PolyGlyphBlt = s3PolyGlyphBlt; + } + if (TERMINALFONT(pGC->font)) + pGC->ops->ImageGlyphBlt = s3ImageTEGlyphBlt; + else + pGC->ops->ImageGlyphBlt = s3ImageGlyphBlt; + } + } +} diff --git a/xserver/hw/kdrive/savage/s3reg.c b/xserver/hw/kdrive/savage/s3reg.c new file mode 100644 index 000000000..673a2ac8f --- /dev/null +++ b/xserver/hw/kdrive/savage/s3reg.c @@ -0,0 +1,1301 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3reg.h" + +#define CR00 S3_CR+0x00 +#define CR01 S3_CR+0x01 +#define CR02 S3_CR+0x02 +#define CR03 S3_CR+0x03 +#define CR04 S3_CR+0x04 +#define CR05 S3_CR+0x05 +#define CR06 S3_CR+0x06 +#define CR07 S3_CR+0x07 +#define CR08 S3_CR+0x08 +#define CR09 S3_CR+0x09 +#define CR0A S3_CR+0x0A +#define CR0B S3_CR+0x0B +#define CR0C S3_CR+0x0C +#define CR0D S3_CR+0x0D +#define CR0E S3_CR+0x0E +#define CR0F S3_CR+0x0F +#define CR10 S3_CR+0x10 +#define CR11 S3_CR+0x11 +#define CR12 S3_CR+0x12 +#define CR13 S3_CR+0x13 +#define CR14 S3_CR+0x14 +#define CR15 S3_CR+0x15 +#define CR16 S3_CR+0x16 +#define CR17 S3_CR+0x17 +#define CR18 S3_CR+0x18 +#define CR19 S3_CR+0x19 +#define CR1A S3_CR+0x1A +#define CR1B S3_CR+0x1B +#define CR1C S3_CR+0x1C +#define CR1D S3_CR+0x1D +#define CR1E S3_CR+0x1E +#define CR1F S3_CR+0x1F +#define CR20 S3_CR+0x20 +#define CR21 S3_CR+0x21 +#define CR22 S3_CR+0x22 +#define CR23 S3_CR+0x23 +#define CR24 S3_CR+0x24 +#define CR25 S3_CR+0x25 +#define CR26 S3_CR+0x26 +#define CR27 S3_CR+0x27 +#define CR28 S3_CR+0x28 +#define CR29 S3_CR+0x29 +#define CR2A S3_CR+0x2A +#define CR2B S3_CR+0x2B +#define CR2C S3_CR+0x2C +#define CR2D S3_CR+0x2D +#define CR2E S3_CR+0x2E +#define CR2F S3_CR+0x2F +#define CR30 S3_CR+0x30 +#define CR31 S3_CR+0x31 +#define CR32 S3_CR+0x32 +#define CR33 S3_CR+0x33 +#define CR34 S3_CR+0x34 +#define CR35 S3_CR+0x35 +#define CR36 S3_CR+0x36 +#define CR37 S3_CR+0x37 +#define CR38 S3_CR+0x38 +#define CR39 S3_CR+0x39 +#define CR3A S3_CR+0x3A +#define CR3B S3_CR+0x3B +#define CR3C S3_CR+0x3C +#define CR3D S3_CR+0x3D +#define CR3E S3_CR+0x3E +#define CR3F S3_CR+0x3F +#define CR40 S3_CR+0x40 +#define CR41 S3_CR+0x41 +#define CR42 S3_CR+0x42 +#define CR43 S3_CR+0x43 +#define CR44 S3_CR+0x44 +#define CR45 S3_CR+0x45 +#define CR46 S3_CR+0x46 +#define CR47 S3_CR+0x47 +#define CR48 S3_CR+0x48 +#define CR49 S3_CR+0x49 +#define CR4A S3_CR+0x4A +#define CR4B S3_CR+0x4B +#define CR4C S3_CR+0x4C +#define CR4D S3_CR+0x4D +#define CR4E S3_CR+0x4E +#define CR4F S3_CR+0x4F +#define CR50 S3_CR+0x50 +#define CR51 S3_CR+0x51 +#define CR52 S3_CR+0x52 +#define CR53 S3_CR+0x53 +#define CR54 S3_CR+0x54 +#define CR55 S3_CR+0x55 +#define CR56 S3_CR+0x56 +#define CR57 S3_CR+0x57 +#define CR58 S3_CR+0x58 +#define CR59 S3_CR+0x59 +#define CR5A S3_CR+0x5A +#define CR5B S3_CR+0x5B +#define CR5C S3_CR+0x5C +#define CR5D S3_CR+0x5D +#define CR5E S3_CR+0x5E +#define CR5F S3_CR+0x5F +#define CR60 S3_CR+0x60 +#define CR61 S3_CR+0x61 +#define CR62 S3_CR+0x62 +#define CR63 S3_CR+0x63 +#define CR64 S3_CR+0x64 +#define CR65 S3_CR+0x65 +#define CR66 S3_CR+0x66 +#define CR67 S3_CR+0x67 +#define CR68 S3_CR+0x68 +#define CR69 S3_CR+0x69 +#define CR6A S3_CR+0x6A +#define CR6B S3_CR+0x6B +#define CR6C S3_CR+0x6C +#define CR6D S3_CR+0x6D +#define CR6E S3_CR+0x6E +#define CR6F S3_CR+0x6F +#define CR70 S3_CR+0x70 +#define CR71 S3_CR+0x71 +#define CR72 S3_CR+0x72 +#define CR73 S3_CR+0x73 +#define CR74 S3_CR+0x74 +#define CR75 S3_CR+0x75 +#define CR76 S3_CR+0x76 +#define CR77 S3_CR+0x77 +#define CR78 S3_CR+0x78 +#define CR79 S3_CR+0x79 +#define CR7A S3_CR+0x7A +#define CR7B S3_CR+0x7B +#define CR7C S3_CR+0x7C +#define CR7D S3_CR+0x7D +#define CR7E S3_CR+0x7E +#define CR7F S3_CR+0x7F +#define CR80 S3_CR+0x80 +#define CR81 S3_CR+0x81 +#define CR82 S3_CR+0x82 +#define CR83 S3_CR+0x83 +#define CR84 S3_CR+0x84 +#define CR85 S3_CR+0x85 +#define CR86 S3_CR+0x86 +#define CR87 S3_CR+0x87 +#define CR88 S3_CR+0x88 +#define CR89 S3_CR+0x89 +#define CR8A S3_CR+0x8A +#define CR8B S3_CR+0x8B +#define CR8C S3_CR+0x8C +#define CR8D S3_CR+0x8D +#define CR8E S3_CR+0x8E +#define CR8F S3_CR+0x8F +#define CR90 S3_CR+0x90 +#define CR91 S3_CR+0x91 +#define CR92 S3_CR+0x92 +#define CR93 S3_CR+0x93 +#define CR94 S3_CR+0x94 +#define CR95 S3_CR+0x95 +#define CR96 S3_CR+0x96 +#define CR97 S3_CR+0x97 +#define CR98 S3_CR+0x98 +#define CR99 S3_CR+0x99 +#define CR9A S3_CR+0x9A +#define CR9B S3_CR+0x9B +#define CR9C S3_CR+0x9C +#define CR9D S3_CR+0x9D +#define CR9E S3_CR+0x9E +#define CR9F S3_CR+0x9F +#define CRA0 S3_CR+0xA0 +#define CRA1 S3_CR+0xA1 +#define CRA2 S3_CR+0xA2 +#define CRA3 S3_CR+0xA3 +#define CRA4 S3_CR+0xA4 +#define CRA5 S3_CR+0xA5 +#define CRA6 S3_CR+0xA6 +#define CRA7 S3_CR+0xA7 +#define CRA8 S3_CR+0xA8 +#define CRA9 S3_CR+0xA9 +#define CRAA S3_CR+0xAA +#define CRAB S3_CR+0xAB +#define CRAC S3_CR+0xAC +#define CRAD S3_CR+0xAD +#define CRAE S3_CR+0xAE +#define CRAF S3_CR+0xAF +#define CRB0 S3_CR+0xB0 +#define CRB1 S3_CR+0xB1 +#define CRB2 S3_CR+0xB2 +#define CRB3 S3_CR+0xB3 +#define CRB4 S3_CR+0xB4 +#define CRB5 S3_CR+0xB5 +#define CRB6 S3_CR+0xB6 +#define CRB7 S3_CR+0xB7 +#define CRB8 S3_CR+0xB8 +#define CRB9 S3_CR+0xB9 +#define CRBA S3_CR+0xBA +#define CRBB S3_CR+0xBB +#define CRBC S3_CR+0xBC +#define CRBD S3_CR+0xBD +#define CRBE S3_CR+0xBE +#define CRBF S3_CR+0xBF + +#define CR_FIRST CR00 + +VgaReg s3_h_total[] = { + CR00, 0, 8, + CR5D, 0, 1, + CR5F, 0, 2, + VGA_REG_END +}; + +VgaReg s3_h_display_end[] = { + CR01, 0, 8, + CR5D, 1, 1, + CR5F, 2, 2, + VGA_REG_END +}; + +VgaReg s3_h_blank_start[] = { + CR02, 0, 8, + CR5D, 2, 1, + CR5F, 4, 2, + VGA_REG_END +}; + +VgaReg s3_h_blank_end[] = { + CR03, 0, 5, + CR05, 7, 1, + VGA_REG_END +}; + +VgaReg s3_display_skew[] = { + CR03, 5, 2, + VGA_REG_END +}; + +VgaReg s3_h_sync_start[] = { + CR04, 0, 8, + CR5D, 4, 1, + CR5F, 6, 2, + VGA_REG_END +}; + +VgaReg s3_h_sync_end[] = { + CR05, 0, 5, + VGA_REG_END +}; + +VgaReg s3_h_skew[] = { + CR05, 5, 2, + VGA_REG_END +}; + +VgaReg s3_v_total[] = { + CR06, 0, 8, + CR07, 0, 1, + CR07, 5, 1, + CR5E, 0, 1, + VGA_REG_END +}; + +VgaReg s3_preset_row_scan[] = { + CR08, 0, 8, + VGA_REG_END +}; + +VgaReg s3_max_scan_line[] = { + CR09, 0, 5, + VGA_REG_END +}; + +VgaReg s3_start_address[] = { + CR0D, 0, 8, + CR0C, 0, 8, + CR69, 0, 7, + VGA_REG_END +}; + +VgaReg s3_v_retrace_start[] = { + CR10, 0, 8, + CR07, 2, 1, + CR07, 7, 1, + CR5E, 4, 1, + VGA_REG_END +}; + +VgaReg s3_v_retrace_end[] = { + CR11, 0, 4, + VGA_REG_END +}; + +VgaReg s3_clear_v_retrace_int[] = { + CR11, 4, 1, + VGA_REG_END +}; + +VgaReg s3_disable_v_retrace_int[] = { + CR11, 5, 1, + VGA_REG_END +}; + +VgaReg s3_lock_crtc[] = { + CR11, 7, 1, + VGA_REG_END +}; + +VgaReg s3_v_display_end[] = { + CR12, 0, 8, + CR07, 1, 1, + CR07, 6, 1, + CR5E, 1, 1, + VGA_REG_END +}; + +VgaReg s3_screen_offset[] = { + CR13, 0, 8, + CR51, 4, 2, + VGA_REG_END +}; + +VgaReg s3_count_by_4_mode[] = { + CR14, 5, 1, + VGA_REG_END +}; + +VgaReg s3_doubleword_mode[] = { + CR14, 6, 1, + VGA_REG_END +}; + +VgaReg s3_v_blank_start[] = { + CR15, 0, 8, + CR07, 3, 1, + CR09, 5, 1, + CR5E, 2, 1, + VGA_REG_END +}; + +VgaReg s3_v_blank_end[] = { + CR16, 0, 8, + VGA_REG_END +}; + +VgaReg s3_2bk_cga[] = { + CR17, 0, 1, + VGA_REG_END +}; + +VgaReg s3_4bk_hga[] = { + CR17, 1, 1, + VGA_REG_END +}; + +VgaReg s3_v_total_double[] = { + CR17, 2, 1, + VGA_REG_END +}; + +VgaReg s3_word_mode[] = { + CR17, 3, 1, + VGA_REG_END +}; + +VgaReg s3_address_16k_wrap[] = { + CR17, 5, 1, + VGA_REG_END +}; + +VgaReg s3_byte_mode[] = { + CR17, 6, 1, + VGA_REG_END +}; + +VgaReg s3_hardware_reset[] = { + CR17, 7, 1, + VGA_REG_END +}; + +VgaReg s3_line_compare[] = { + CR18, 0, 8, + CR07, 4, 1, + CR09, 6, 1, + CR5E, 6, 1, + VGA_REG_END +}; + +VgaReg s3_delay_primary_load[] = { + CR21, 1, 1, + VGA_REG_END +}; + +VgaReg s3_device_id[] = { + CR2E, 0, 8, + CR2D, 0, 8, + VGA_REG_END +}; + +VgaReg s3_revision[] = { + CR2F, 0, 8, + VGA_REG_END +}; + +VgaReg s3_enable_vga_16bit[] = { + CR31, 2, 1, + VGA_REG_END +}; + +VgaReg s3_enhanced_memory_mapping[] = { + CR31, 3, 1, + VGA_REG_END +}; + +VgaReg s3_lock_dac_writes[] = { + CR33, 4, 1, + VGA_REG_END +}; + +VgaReg s3_border_select[] = { + CR33, 5, 1, + VGA_REG_END +}; + +VgaReg s3_lock_palette[] = { + CR33, 6, 1, + VGA_REG_END +}; + +VgaReg s3_enable_sff[] = { + CR34, 4, 1, + VGA_REG_END +}; + +VgaReg s3_lock_vert[] = { + CR35, 4, 1, + VGA_REG_END +}; + +VgaReg s3_lock_horz[] = { + CR35, 5, 1, + VGA_REG_END +}; + +VgaReg s3_io_disable[] = { + CR36, 4, 1, + VGA_REG_END +}; + +VgaReg s3_mem_size[] = { + CR36, 5, 3, + VGA_REG_END +}; + +VgaReg s3_register_lock_1 [] = { + CR38, 0, 8, /* load with 0x48 */ + VGA_REG_END +}; + +VgaReg s3_register_lock_2 [] = { + CR39, 0, 8, /* load with 0xa0 */ + VGA_REG_END +}; + +VgaReg s3_refresh_control[] = { + CR3A, 0, 2, + VGA_REG_END +}; + +VgaReg s3_enable_256[] = { + CR3A, 4, 1, + VGA_REG_END +}; + +VgaReg s3_disable_pci_read_bursts[] = { + CR3A, 7, 1, + VGA_REG_END +}; + +VgaReg s3_h_start_fifo_fetch[] = { + CR3B, 0, 8, + CR5D, 6, 1, + CR5B, 2, 2, + VGA_REG_END +}; + +VgaReg s3_enable_2d_access[] = { + CR40, 0, 1, + VGA_REG_END +}; + +VgaReg s3_interlace[] = { + CR42, 5, 1, + VGA_REG_END +}; + +VgaReg s3_old_screen_off_8[] = { + CR43, 2, 1, + VGA_REG_END +}; + +VgaReg s3_h_counter_double_mode[] = { + CR43, 7, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_enable[] = { + CR45, 0, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_right[] = { + CR45, 4, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_xhigh[] = { + CR46, 0, 3, + VGA_REG_END +}; + +VgaReg s3_cursor_xlow[] = { + CR47, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_yhigh[] = { + CR48, 0, 3, + VGA_REG_END +}; + +VgaReg s3_cursor_ylow[] = { + CR49, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_fg[] = { + CR4A, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_bg[] = { + CR4B, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_address[] = { + CR4D, 0, 8, + CR4C, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cursor_xoff[] = { + CR4E, 0, 6, + VGA_REG_END +}; + +VgaReg s3_cursor_yoff[] = { + CR4F, 0, 6, + VGA_REG_END +}; + +VgaReg s3_ge_screen_width[] = { + CR50, 6, 2, + CR50, 0, 1, + VGA_REG_END +}; + +VgaReg s3_pixel_length[] = { + CR50, 4, 2, + VGA_REG_END +}; + +VgaReg s3_big_endian_linear[] = { + CR53, 1, 2, + VGA_REG_END +}; + +VgaReg s3_mmio_select[] = { + CR53, 3, 2, + VGA_REG_END +}; + +VgaReg s3_mmio_window[] = { + CR53, 5, 1, + VGA_REG_END +}; + +VgaReg s3_swap_nibbles[] = { + CR53, 6, 1, + VGA_REG_END +}; + +VgaReg s3_cursor_ms_x11[] = { + CR55, 4, 1, + VGA_REG_END +}; + +VgaReg s3_linear_window_size[] = { + CR58, 0, 2, + VGA_REG_END +}; + +VgaReg s3_enable_linear[] = { + CR58, 4, 1, + VGA_REG_END +}; + +VgaReg s3_h_blank_extend[] = { + CR5D, 3, 1, + VGA_REG_END +}; + +VgaReg s3_h_sync_extend[] = { + CR5D, 5, 1, + VGA_REG_END +}; + +VgaReg s3_sdclk_skew[] = { + CR60, 0, 4, + VGA_REG_END +}; + +VgaReg s3_delay_blank[] = { + CR65, 3, 2, + VGA_REG_END +}; + +VgaReg s3_delay_h_enable[] = { + CR65, 6, 2, + CR65, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_2d_3d[] = { + CR66, 0, 1, + VGA_REG_END +}; + +VgaReg s3_pci_disconnect_enable[] = { + CR66, 3, 1, + VGA_REG_END +}; + +VgaReg s3_primary_load_control[] = { + CR66, 4, 1, + VGA_REG_END +}; + +VgaReg s3_secondary_load_control[] = { + CR66, 5, 1, + VGA_REG_END +}; + +VgaReg s3_pci_retry_enable[] = { + CR66, 7, 1, + VGA_REG_END +}; + +VgaReg s3_streams_mode[] = { + CR67, 2, 2, + VGA_REG_END +}; + +VgaReg s3_color_mode[] = { + CR67, 4, 4, + VGA_REG_END +}; + +VgaReg s3_primary_stream_definition[] = { + CR69, 7, 1, + VGA_REG_END +}; + +VgaReg s3_primary_stream_timeout[] = { + CR71, 0, 8, + VGA_REG_END +}; + +VgaReg s3_master_control_unit_timeout[] = { + CR74, 0, 8, + VGA_REG_END +}; + +VgaReg s3_command_buffer_timeout[] = { + CR75, 0, 8, + VGA_REG_END +}; + +VgaReg s3_lpb_timeout[] = { + CR76, 0, 8, + VGA_REG_END +}; + +VgaReg s3_cpu_timeout[] = { + CR78, 0, 8, + VGA_REG_END +}; + +VgaReg s3_2d_graphics_engine_timeout[] = { + CR79, 0, 8, + VGA_REG_END +}; + +VgaReg s3_fifo_drain_delay[] = { + CR85, 0, 3, + VGA_REG_END +}; + +VgaReg s3_fifo_fetch_timing[] = { + CR85, 4, 1, + VGA_REG_END +}; + +VgaReg s3_dac_power_up_time[] = { + CR86, 0, 7, + VGA_REG_END +}; + +VgaReg s3_dac_power_saving_disable[] = { + CR86, 7, 1, + VGA_REG_END +}; + +VgaReg s3_flat_panel_output_control_1[] = { + CR90, 3, 1, + VGA_REG_END +}; + +VgaReg s3_streams_fifo_delay[] = { + CR90, 4, 2, + VGA_REG_END +}; + +VgaReg s3_flat_panel_output_control_2[] = { + CR90, 6, 1, + VGA_REG_END +}; + +VgaReg s3_enable_l1_parameter[] = { + CR90, 7, 1, + VGA_REG_END +}; + +VgaReg s3_primary_stream_l1[] = { + CR91, 0, 8, + CR90, 0, 3, + VGA_REG_END +}; + +#define CR_LAST CR91 + +#define SR00 S3_SR+0x00 +#define SR01 S3_SR+0x01 +#define SR02 S3_SR+0x02 +#define SR03 S3_SR+0x03 +#define SR04 S3_SR+0x04 +#define SR05 S3_SR+0x05 +#define SR06 S3_SR+0x06 +#define SR07 S3_SR+0x07 +#define SR08 S3_SR+0x08 +#define SR09 S3_SR+0x09 +#define SR0A S3_SR+0x0A +#define SR0B S3_SR+0x0B +#define SR0C S3_SR+0x0C +#define SR0D S3_SR+0x0D +#define SR0E S3_SR+0x0E +#define SR0F S3_SR+0x0F +#define SR10 S3_SR+0x10 +#define SR11 S3_SR+0x11 +#define SR12 S3_SR+0x12 +#define SR13 S3_SR+0x13 +#define SR14 S3_SR+0x14 +#define SR15 S3_SR+0x15 +#define SR16 S3_SR+0x16 +#define SR17 S3_SR+0x17 +#define SR18 S3_SR+0x18 +#define SR19 S3_SR+0x19 +#define SR1A S3_SR+0x1A +#define SR1B S3_SR+0x1B +#define SR1C S3_SR+0x1C +#define SR1D S3_SR+0x1D +#define SR1E S3_SR+0x1E +#define SR1F S3_SR+0x1F +#define SR20 S3_SR+0x20 +#define SR21 S3_SR+0x21 +#define SR22 S3_SR+0x22 +#define SR23 S3_SR+0x23 +#define SR24 S3_SR+0x24 +#define SR25 S3_SR+0x25 +#define SR26 S3_SR+0x26 +#define SR27 S3_SR+0x27 +#define SR28 S3_SR+0x28 +#define SR29 S3_SR+0x29 +#define SR2A S3_SR+0x2A +#define SR2B S3_SR+0x2B +#define SR2C S3_SR+0x2C +#define SR2D S3_SR+0x2D +#define SR2E S3_SR+0x2E +#define SR2F S3_SR+0x2F +#define SR30 S3_SR+0x30 +#define SR31 S3_SR+0x31 +#define SR32 S3_SR+0x32 +#define SR33 S3_SR+0x33 +#define SR34 S3_SR+0x34 +#define SR35 S3_SR+0x35 +#define SR36 S3_SR+0x36 +#define SR37 S3_SR+0x37 +#define SR38 S3_SR+0x38 +#define SR39 S3_SR+0x39 +#define SR3A S3_SR+0x3A +#define SR3B S3_SR+0x3B +#define SR3C S3_SR+0x3C +#define SR3D S3_SR+0x3D +#define SR3E S3_SR+0x3E +#define SR3F S3_SR+0x3F +#define SR40 S3_SR+0x40 +#define SR41 S3_SR+0x41 +#define SR42 S3_SR+0x42 +#define SR43 S3_SR+0x43 +#define SR44 S3_SR+0x44 +#define SR45 S3_SR+0x45 +#define SR46 S3_SR+0x46 +#define SR47 S3_SR+0x47 +#define SR48 S3_SR+0x48 +#define SR49 S3_SR+0x49 +#define SR4A S3_SR+0x4A +#define SR4B S3_SR+0x4B +#define SR4C S3_SR+0x4C +#define SR4D S3_SR+0x4D +#define SR4E S3_SR+0x4E +#define SR4F S3_SR+0x4F +#define SR50 S3_SR+0x50 +#define SR51 S3_SR+0x51 +#define SR52 S3_SR+0x52 +#define SR53 S3_SR+0x53 +#define SR54 S3_SR+0x54 +#define SR55 S3_SR+0x55 +#define SR56 S3_SR+0x56 +#define SR57 S3_SR+0x57 +#define SR58 S3_SR+0x58 +#define SR59 S3_SR+0x59 +#define SR5A S3_SR+0x5A +#define SR5B S3_SR+0x5B +#define SR5C S3_SR+0x5C +#define SR5D S3_SR+0x5D +#define SR5E S3_SR+0x5E +#define SR5F S3_SR+0x5F +#define SR60 S3_SR+0x60 +#define SR61 S3_SR+0x61 +#define SR62 S3_SR+0x62 +#define SR63 S3_SR+0x63 +#define SR64 S3_SR+0x64 +#define SR65 S3_SR+0x65 +#define SR66 S3_SR+0x66 +#define SR67 S3_SR+0x67 +#define SR68 S3_SR+0x68 +#define SR69 S3_SR+0x69 +#define SR6A S3_SR+0x6A +#define SR6B S3_SR+0x6B +#define SR6C S3_SR+0x6C +#define SR6D S3_SR+0x6D +#define SR6E S3_SR+0x6E +#define SR6F S3_SR+0x6F + +#define SR_FIRST SR02 + +VgaReg s3_dot_clock_8[] = { + SR01, 0, 1, + VGA_REG_END +}; + +VgaReg s3_screen_off[] = { + SR01, 5, 1, + VGA_REG_END +}; + +VgaReg s3_enable_write_plane[] = { + SR02, 0, 4, + VGA_REG_END +}; + +VgaReg s3_extended_memory_access[] = { + SR04, 1, 1, + VGA_REG_END +}; + +VgaReg s3_sequential_addressing_mode[] = { + SR04, 2, 1, + VGA_REG_END +}; + +VgaReg s3_select_chain_4_mode[] = { + SR04, 3, 1, + VGA_REG_END +}; + +VgaReg s3_unlock_extended_sequencer[] = { + SR08, 0, 8, /* write 0x06 */ + VGA_REG_END +}; + +VgaReg s3_linear_addressing_control[] = { + SR09, 0, 1, + VGA_REG_END +}; + +VgaReg s3_disable_io_ports[] = { + SR09, 7, 1, + VGA_REG_END +}; + +VgaReg s3_hsync_control[] = { + SR0D, 4, 2, + VGA_REG_END +}; + +VgaReg s3_vsync_control[] = { + SR0D, 6, 2, + VGA_REG_END +}; + +VgaReg s3_mclk_n[] = { + SR10, 0, 5, + VGA_REG_END +}; + +VgaReg s3_mclk_r[] = { + SR10, 5, 2, + VGA_REG_END +}; + +VgaReg s3_mclk_m[] = { + SR11, 0, 7, + VGA_REG_END +}; + +VgaReg s3_dclk_n[] = { + SR12, 0, 6, + SR29, 4, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_r[] = { + SR12, 6, 2, + SR29, 2, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_m[] = { + SR13, 0, 8, + SR29, 3, 1, + VGA_REG_END +}; + +VgaReg s3_mclk_load[] = { + SR15, 0, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_load[] = { + SR15, 1, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_over_2[] = { + SR15, 4, 1, + VGA_REG_END +}; + +VgaReg s3_clock_load_imm[] = { + SR15, 5, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_invert[] = { + SR15, 6, 1, + VGA_REG_END +}; + +VgaReg s3_enable_clock_double[] = { + SR18, 7, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_double_15_16_invert[] = { + SR1A, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_gamma_correction[] = { + SR1B, 3, 1, + VGA_REG_END +}; + +VgaReg s3_enable_8_bit_luts[] = { + SR1B, 4, 1, + VGA_REG_END +}; + +VgaReg s3_dclk_control[] = { + SR1B, 7, 1, + VGA_REG_END +}; + +VgaReg s3_eclk_n[] = { + SR32, 0, 5, + VGA_REG_END +}; + +VgaReg s3_eclk_r[] = { + SR32, 5, 2, + VGA_REG_END +}; + +VgaReg s3_eclk_m[] = { + SR32, 0, 5, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_n[] = { + SR36, 0, 6, + SR39, 4, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_r[] = { + SR36, 6, 2, + SR39, 2, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_m1[] = { + SR37, 0, 8, + SR39, 3, 1, + VGA_REG_END +}; + +VgaReg s3_vga_dclk_m2[] = { + SR38, 0, 8, + SR39, 3, 1, + VGA_REG_END +}; + +VgaReg s3_vga_clk_select[] = { + SR39, 0, 1, + VGA_REG_END +}; + +#define SR_LAST SR39 + +#define AR00 (S3_AR+0x00) +#define AR10 (S3_AR+0x10) +#define AR11 (S3_AR+0x11) +#define AR12 (S3_AR+0x12) +#define AR13 (S3_AR+0x13) +#define AR14 (S3_AR+0x14) + +#define AR_FIRST AR00 + +VgaReg s3_select_graphics_mode[] = { + AR10, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_blinking[] = { + AR10, 3, 1, + VGA_REG_END +}; + +VgaReg s3_border_color[] = { + AR11, 0, 8, + VGA_REG_END +}; + +#define AR_LAST AR11 + +VgaReg s3_io_addr_select[] = { + S3_MISC_OUT, 0, 1, + VGA_REG_END +}; + +VgaReg s3_enable_ram[] = { + S3_MISC_OUT, 1, 1, + VGA_REG_END +}; + +VgaReg s3_clock_select[] = { + S3_MISC_OUT, 2, 2, + VGA_REG_END +}; + +VgaReg s3_horz_sync_neg[] = { + S3_MISC_OUT, 6, 1, + VGA_REG_END +}; + +VgaReg s3_vert_sync_neg[] = { + S3_MISC_OUT, 7, 1, + VGA_REG_END +}; + +VgaReg s3_display_mode_inactive[] = { + S3_INPUT_STATUS_1, 0, 1, + VGA_REG_END +}; + +VgaReg s3_vertical_sync_active[] = { + S3_INPUT_STATUS_1, 3, 1, + VGA_REG_END +}; + +VgaReg s3_dac_mask[] = { + S3_DAC + 0, 0, 8, + VGA_REG_END +}; + +VgaReg s3_dac_read_index[] = { + S3_DAC + 1, 0, 8, + VGA_REG_END +}; + +VgaReg s3_dac_write_index[] = { + S3_DAC + 2, 0, 8, + VGA_REG_END +}; + +VgaReg s3_dac_data[] = { + S3_DAC + 3, 0, 8, + VGA_REG_END +}; + +VGA8 +_s3Inb (VgaCard *card, VGA16 port) +{ + VGAVOL8 *reg; + + if (card->closure) + return VgaReadMemb ((VGA32) card->closure + port); + else + return VgaInb (port); +} + +void +_s3Outb (VgaCard *card, VGA8 value, VGA16 port) +{ + if (card->closure) + VgaWriteMemb (value, (VGA32) card->closure + port); + else + VgaOutb (value, port); +} + +void +_s3RegMap (VgaCard *card, VGA16 reg, VgaMap *map, VGABOOL write) +{ + + if (reg < S3_SR + S3_NSR) + { + map->access = VgaAccessIndIo; + map->port = 0x3c4; + map->addr = 0; + map->value = 1; + map->index = reg - S3_SR; + } + else if (reg < S3_GR + S3_NGR) + { + map->access = VgaAccessIndIo; + map->port = 0x3ce; + map->addr = 0; + map->value = 1; + map->index = reg - S3_GR; + } + else if (reg < S3_AR + S3_NAR) + { + reg -= S3_AR; + map->access = VgaAccessDone; + /* reset AFF to index */ + (void) _s3Inb (card, 0x3da); + if (reg >= 16) + reg |= 0x20; + _s3Outb (card, reg, 0x3c0); + if (write) + _s3Outb (card, map->value, 0x3c0); + else + map->value = _s3Inb (card, 0x3c1); + if (!(reg & 0x20)) + { + /* enable video display again */ + (void) _s3Inb (card, 0x3da); + _s3Outb (card, 0x20, 0x3c0); + } + return; + } + else if (reg < S3_CR + S3_NCR) + { + map->access = VgaAccessIndIo; + map->port = 0x3d4; + map->addr = 0; + map->value = 1; + map->index = reg - S3_CR; + } + else if (reg < S3_DAC + S3_NDAC) + { + map->access = VgaAccessIo; + map->port = 0x3c6 + reg - S3_DAC; + } + else switch (reg) { + case S3_MISC_OUT: + map->access = VgaAccessIo; + if (write) + map->port = 0x3c2; + else + map->port = 0x3cc; + break; + case S3_INPUT_STATUS_1: + map->access = VgaAccessIo; + map->port = 0x3da; + break; + } + if (card->closure) + { + map->port = map->port + (VGA32) card->closure; + if (map->access == VgaAccessIo) + map->access = VgaAccessMem; + if (map->access == VgaAccessIndIo) + map->access = VgaAccessIndMem; + } +} + +VgaSave s3Saves[] = { + CR_FIRST, CR18, + CR31, CR_LAST, + SR_FIRST, SR15, + SR18, SR_LAST, + AR_FIRST, AR_LAST, + S3_MISC_OUT, S3_MISC_OUT, + VGA_SAVE_END +}; + +void +s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio) +{ + s3vga->card.map = _s3RegMap; + s3vga->card.closure = (void *) mmio; + s3vga->card.max = S3_NREG; + s3vga->card.values = s3vga->values; + s3vga->card.saves = s3Saves; +} + +void +s3Save (S3Vga *s3vga) +{ + s3vga->save_lock_crtc = s3Get(s3vga, s3_lock_crtc); + s3SetImm (s3vga, s3_lock_crtc, 0); + s3vga->save_register_lock_1 = s3Get (s3vga, s3_register_lock_1); + s3SetImm (s3vga, s3_register_lock_1, 0x48); + s3vga->save_register_lock_2 = s3Get (s3vga, s3_register_lock_2); + s3SetImm (s3vga, s3_register_lock_2, 0xa5); + s3vga->save_unlock_extended_sequencer = s3Get (s3vga, s3_unlock_extended_sequencer); + s3SetImm (s3vga, s3_unlock_extended_sequencer, 0x06); + s3vga->save_lock_horz = s3Get (s3vga, s3_lock_horz); + s3SetImm (s3vga, s3_lock_horz, 0); + s3vga->save_lock_vert = s3Get (s3vga, s3_lock_vert); + s3SetImm (s3vga, s3_lock_vert, 0); + s3vga->save_dot_clock_8 = s3Get (s3vga, s3_dot_clock_8); + VgaPreserve (&s3vga->card); +} + +void +s3Reset (S3Vga *s3vga) +{ + VgaRestore (&s3vga->card); + s3SetImm (s3vga, s3_clock_load_imm, 1); + s3SetImm (s3vga, s3_clock_load_imm, 0); + s3SetImm (s3vga, s3_dot_clock_8, s3vga->save_dot_clock_8); + s3SetImm (s3vga, s3_lock_vert, s3vga->save_lock_vert); + s3SetImm (s3vga, s3_lock_horz, s3vga->save_lock_horz); + s3SetImm (s3vga, s3_lock_dac_writes, s3vga->save_lock_dac_writes); + s3SetImm (s3vga, s3_unlock_extended_sequencer, s3vga->save_unlock_extended_sequencer); + s3SetImm (s3vga, s3_register_lock_2, s3vga->save_register_lock_2); + s3SetImm (s3vga, s3_register_lock_1, s3vga->save_register_lock_1); + s3SetImm (s3vga, s3_lock_crtc, s3vga->save_lock_crtc); + VgaFinish (&s3vga->card); +} diff --git a/xserver/hw/kdrive/savage/s3reg.h b/xserver/hw/kdrive/savage/s3reg.h new file mode 100644 index 000000000..5c5b09f6d --- /dev/null +++ b/xserver/hw/kdrive/savage/s3reg.h @@ -0,0 +1,227 @@ +/* + * 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. + */ + +#ifndef _S3REG_H_ +#define _S3REG_H_ + +#include "vga.h" + +#define S3_SR 0 +#define S3_NSR 0x70 +#define S3_GR (S3_SR+S3_NSR) +#define S3_NGR 0x09 +#define S3_AR (S3_GR+S3_NGR) +#define S3_NAR 0x15 +#define S3_CR (S3_AR+S3_NAR) +#define S3_NCR 0xc0 +#define S3_DAC (S3_CR+S3_NCR) +#define S3_NDAC 4 +#define S3_MISC_OUT (S3_DAC + S3_NDAC) +#define S3_INPUT_STATUS_1 (S3_MISC_OUT+1) +#define S3_NREG (S3_INPUT_STATUS_1+1) + +extern VgaReg s3_h_total[]; +extern VgaReg s3_h_display_end[]; +extern VgaReg s3_h_blank_start[]; +extern VgaReg s3_h_blank_end[]; +extern VgaReg s3_display_skew[]; +extern VgaReg s3_h_sync_start[]; +extern VgaReg s3_h_sync_end[]; +extern VgaReg s3_h_skew[]; +extern VgaReg s3_v_total[]; +extern VgaReg s3_preset_row_scan[]; +extern VgaReg s3_max_scan_line[]; +extern VgaReg s3_start_address[]; +extern VgaReg s3_v_retrace_start[]; +extern VgaReg s3_v_retrace_end[]; +extern VgaReg s3_clear_v_retrace_int[]; +extern VgaReg s3_disable_v_retrace_int[]; +extern VgaReg s3_lock_crtc[]; +extern VgaReg s3_v_display_end[]; +extern VgaReg s3_screen_offset[]; +extern VgaReg s3_count_by_4_mode[]; +extern VgaReg s3_doubleword_mode[]; +extern VgaReg s3_v_blank_start[]; +extern VgaReg s3_v_blank_end[]; +extern VgaReg s3_2bk_cga[]; +extern VgaReg s3_4bk_hga[]; +extern VgaReg s3_v_total_double[]; +extern VgaReg s3_address_16k_wrap[]; +extern VgaReg s3_word_mode[]; +extern VgaReg s3_byte_mode[]; +extern VgaReg s3_hardware_reset[]; +extern VgaReg s3_line_compare[]; +extern VgaReg s3_delay_primary_load[]; +extern VgaReg s3_device_id[]; +extern VgaReg s3_revision[]; +extern VgaReg s3_enable_vga_16bit[]; +extern VgaReg s3_enhanced_memory_mapping[]; +extern VgaReg s3_enable_sff[]; +extern VgaReg s3_lock_dac_writes[]; +extern VgaReg s3_border_select[]; +extern VgaReg s3_lock_palette[]; +extern VgaReg s3_lock_vert[]; +extern VgaReg s3_lock_horz[]; +extern VgaReg s3_io_disable[]; +extern VgaReg s3_mem_size[]; +extern VgaReg s3_register_lock_1 []; +extern VgaReg s3_register_lock_2 []; +extern VgaReg s3_refresh_control[]; +extern VgaReg s3_enable_256[]; +extern VgaReg s3_disable_pci_read_bursts[]; +extern VgaReg s3_h_start_fifo_fetch[]; +extern VgaReg s3_enable_2d_access[]; +extern VgaReg s3_interlace[]; +extern VgaReg s3_old_screen_off_8[]; +extern VgaReg s3_h_counter_double_mode[]; +extern VgaReg s3_cursor_enable[]; +extern VgaReg s3_cursor_right[]; +extern VgaReg s3_cursor_xhigh[]; +extern VgaReg s3_cursor_xlow[]; +extern VgaReg s3_cursor_yhigh[]; +extern VgaReg s3_cursor_ylow[]; +extern VgaReg s3_cursor_fg[]; +extern VgaReg s3_cursor_bg[]; +extern VgaReg s3_cursor_address[]; +extern VgaReg s3_cursor_xoff[]; +extern VgaReg s3_cursor_yoff[]; +extern VgaReg s3_ge_screen_width[]; +extern VgaReg s3_pixel_length[]; +extern VgaReg s3_big_endian_linear[]; +extern VgaReg s3_mmio_select[]; +extern VgaReg s3_mmio_window[]; +extern VgaReg s3_swap_nibbles[]; +extern VgaReg s3_cursor_ms_x11[]; +extern VgaReg s3_linear_window_size[]; +extern VgaReg s3_enable_linear[]; +extern VgaReg s3_h_blank_extend[]; +extern VgaReg s3_h_sync_extend[]; +extern VgaReg s3_sdclk_skew[]; +extern VgaReg s3_delay_blank[]; +extern VgaReg s3_delay_h_enable[]; +extern VgaReg s3_enable_2d_3d[]; +extern VgaReg s3_pci_disconnect_enable[]; +extern VgaReg s3_primary_load_control[]; +extern VgaReg s3_secondary_load_control[]; +extern VgaReg s3_pci_retry_enable[]; +extern VgaReg s3_streams_mode[]; +extern VgaReg s3_color_mode[]; +extern VgaReg s3_primary_stream_definition[]; +extern VgaReg s3_primary_stream_timeout[]; +extern VgaReg s3_master_control_unit_timeout[]; +extern VgaReg s3_command_buffer_timeout[]; +extern VgaReg s3_lpb_timeout[]; +extern VgaReg s3_cpu_timeout[]; +extern VgaReg s3_2d_graphics_engine_timeout[]; +extern VgaReg s3_fifo_drain_delay[]; +extern VgaReg s3_fifo_fetch_timing[]; +extern VgaReg s3_dac_power_up_time[]; +extern VgaReg s3_dac_power_saving_disable[]; +extern VgaReg s3_flat_panel_output_control_1[]; +extern VgaReg s3_streams_fifo_delay[]; +extern VgaReg s3_flat_panel_output_control_2[]; +extern VgaReg s3_enable_l1_parameter[]; +extern VgaReg s3_primary_stream_l1[]; + +extern VgaReg s3_dot_clock_8[]; +extern VgaReg s3_screen_off[]; +extern VgaReg s3_enable_write_plane[]; +extern VgaReg s3_extended_memory_access[]; +extern VgaReg s3_sequential_addressing_mode[]; +extern VgaReg s3_select_chain_4_mode[]; + +extern VgaReg s3_unlock_extended_sequencer[]; +extern VgaReg s3_linear_addressing_control[]; +extern VgaReg s3_disable_io_ports[]; +extern VgaReg s3_hsync_control[]; +extern VgaReg s3_vsync_control[]; +extern VgaReg s3_mclk_n[]; +extern VgaReg s3_mclk_r[]; +extern VgaReg s3_mclk_m[]; +extern VgaReg s3_dclk_n[]; +extern VgaReg s3_dclk_r[]; +extern VgaReg s3_dclk_m[]; +extern VgaReg s3_mclk_load[]; +extern VgaReg s3_dclk_load[]; +extern VgaReg s3_dclk_over_2[]; +extern VgaReg s3_clock_load_imm[]; +extern VgaReg s3_dclk_invert[]; +extern VgaReg s3_enable_clock_double[]; +extern VgaReg s3_dclk_double_15_16_invert[]; +extern VgaReg s3_enable_gamma_correction[]; +extern VgaReg s3_enable_8_bit_luts[]; +extern VgaReg s3_dclk_control[]; +extern VgaReg s3_eclk_n[]; +extern VgaReg s3_eclk_r[]; +extern VgaReg s3_eclk_m[]; +extern VgaReg s3_vga_dclk_n[]; +extern VgaReg s3_vga_dclk_r[]; +extern VgaReg s3_vga_dclk_m1[]; +extern VgaReg s3_vga_dclk_m2[]; +extern VgaReg s3_vga_clk_select[]; +extern VgaReg s3_select_graphics_mode[]; +extern VgaReg s3_enable_blinking[]; +extern VgaReg s3_border_color[]; + +extern VgaReg s3_io_addr_select[]; +extern VgaReg s3_enable_ram[]; +extern VgaReg s3_clock_select[]; +extern VgaReg s3_horz_sync_neg[]; +extern VgaReg s3_vert_sync_neg[]; + +extern VgaReg s3_display_mode_inactive[]; +extern VgaReg s3_vertical_sync_active[]; + +extern VgaReg s3_dac_mask[]; +extern VgaReg s3_dac_read_index[]; +extern VgaReg s3_dac_write_index[]; +extern VgaReg s3_dac_data[]; + +#define s3Get(sv,r) VgaGet(&(sv)->card, (r)) +#define s3GetImm(sv,r) VgaGetImm(&(sv)->card, (r)) +#define s3Set(sv,r,v) VgaSet(&(sv)->card, (r), (v)) +#define s3SetImm(sv,r,v) VgaSetImm(&(sv)->card, (r), (v)) + +typedef struct _s3Vga { + VgaCard card; + VgaValue values[S3_NREG]; + VGA32 save_lock_crtc; + VGA32 save_register_lock_1; + VGA32 save_register_lock_2; + VGA32 save_unlock_extended_sequencer; + VGA32 save_lock_dac_writes; + VGA32 save_lock_horz; + VGA32 save_lock_vert; + VGA32 save_dot_clock_8; +} S3Vga; + +void +s3RegInit (S3Vga *s3vga, VGAVOL8 *mmio); + +void +s3Save (S3Vga *s3vga); + +void +s3Reset (S3Vga *s3vga); + +#endif /* _S3REG_H_ */ diff --git a/xserver/hw/kdrive/savage/s3rtst.c b/xserver/hw/kdrive/savage/s3rtst.c new file mode 100644 index 000000000..c24b860ac --- /dev/null +++ b/xserver/hw/kdrive/savage/s3rtst.c @@ -0,0 +1,141 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <stdio.h> +#include "s3reg.h" + +typedef struct { + VgaReg *reg; + char *name; +} NamedVgaReg; + +NamedVgaReg s3VRegs[] = { + s3_h_total, "h_total", + s3_h_display_end, "h_display_end", + s3_h_blank_start, "h_blank_start", + s3_h_blank_end, "h_blank_end", + s3_display_skew, "display_skew", + s3_h_sync_start, "h_sync_start", + s3_h_sync_end, "h_sync_end", + s3_h_skew, "h_skew", + s3_v_total, "v_total", + s3_preset_row_scan, "preset_row_scan", + s3_max_scan_line, "max_scan_line", + s3_start_address, "start_address", + s3_v_retrace_start, "v_retrace_start", + s3_v_retrace_end, "v_retrace_end", + s3_clear_v_retrace_int, "clear_v_retrace_int", + s3_disable_v_retrace_int, "disable_v_retrace_int", + s3_lock_crtc, "lock_crtc", + s3_v_display_end, "v_display_end", + s3_screen_offset, "screen_offset", + s3_count_by_4_mode, "count_by_4_mode", + s3_doubleword_mode, "doubleword_mode", + s3_v_blank_start, "v_blank_start", + s3_v_blank_end, "v_blank_end", + s3_v_total_double, "v_total_double", + s3_word_mode, "word_mode", + s3_byte_mode, "byte_mode", + s3_line_compare, "line_compare", + s3_device_id, "device_id", + s3_revision, "revision", + s3_lock_vert, "lock_vert", + s3_lock_horz, "lock_horz", + s3_io_disable, "io_disable", + s3_mem_size, "mem_size", + s3_register_lock_1 , "register_lock_1 ", + s3_register_lock_2 , "register_lock_2 ", + s3_refresh_control, "refresh_control", + s3_enable_256, "enable_256", + s3_enable_pci_read_bursts, "enable_pci_read_bursts", + s3_h_start_fifo_fetch, "h_start_fifo_fetch", + s3_interlace, "interlace", + s3_old_screen_off_8, "old_screen_off_8", + s3_h_counter_double_mode, "h_counter_double_mode", + s3_hardware_cursor_enable, "hardware_cursor_enable", + s3_hardware_cursor_right, "hardware_cursor_right", + s3_hardware_cursor_x, "hardware_cursor_x", + s3_hardware_cursor_y, "hardware_cursor_y", + s3_hardware_cursor_fg, "hardware_cursor_fg", + s3_cursor_address, "cursor_address", + s3_cursor_start_x, "cursor_start_x", + s3_cursor_start_y, "cursor_start_y", + s3_ge_screen_width, "ge_screen_width", + s3_pixel_length, "pixel_length", + s3_big_endian_linear, "big_endian_linear", + s3_mmio_select, "mmio_select", + s3_mmio_window, "mmio_window", + s3_swap_nibbles, "swap_nibbles", + s3_hardware_cursor_ms_x11, "hardware_cursor_ms_x11", + s3_h_blank_extend, "h_blank_extend", + s3_h_sync_extend, "h_sync_extend", + s3_enable_2d_3d, "enable_2d_3d", + s3_pci_disconnect_enable, "pci_disconnect_enable", + s3_pci_retry_enable, "pci_retry_enable", + s3_color_mode, "color_mode", + s3_screen_off, "screen_off", + s3_unlock_extended_sequencer, "unlock_extended_sequencer", + s3_disable_io_ports, "disable_io_ports", + s3_hsync_control, "hsync_control", + s3_vsync_control, "vsync_control", + s3_mclk_n, "mclk_n", + s3_mclk_r, "mclk_r", + s3_mclk_m, "mclk_m", + s3_dclk_n, "dclk_n", + s3_dclk_r, "dclk_r", + s3_dclk_m, "dclk_m", + s3_mclk_load, "mclk_load", + s3_dclk_load, "dclk_load", + s3_dclk_over_2, "dclk_over_2", + s3_clock_load_imm, "clock_load_imm", + s3_dclk_invert, "dclk_invert", + s3_enable_clock_double, "enable_clock_double", + s3_dclk_double_15_16_invert, "dclk_double_15_16_invert", + s3_enable_gamma_correction, "enable_gamma_correction", + s3_enable_8_bit_luts, "enable_8_bit_luts", + s3_dclk_control, "dclk_control", + s3_vga_dclk_n, "vga_dclk_n", + s3_vga_dclk_r, "vga_dclk_r", + s3_vga_dclk_m1, "vga_dclk_m1", + s3_vga_dclk_m2, "vga_dclk_m2", + s3_vga_clk_select, "vga_clk_select", + s3_clock_select, "clock_select", +}; + +#define NUM_S3_VREGS (sizeof (s3VRegs)/ sizeof (s3VRegs[0])) + +main (int argc, char **argv) +{ + int i; + + iopl(3); + s3SetImm(s3_register_lock_1, 0x48); + s3SetImm(s3_register_lock_2, 0xa0); + s3SetImm(s3_unlock_extended_sequencer, 0x06); + for (i = 0; i < NUM_S3_VREGS; i++) + printf ("%-20.20s %8x\n", s3VRegs[i].name, s3Get (s3VRegs[i].reg)); + s3Restore (); +} diff --git a/xserver/hw/kdrive/savage/s3stub.c b/xserver/hw/kdrive/savage/s3stub.c new file mode 100644 index 000000000..145c5c1f6 --- /dev/null +++ b/xserver/hw/kdrive/savage/s3stub.c @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "s3.h" + +void +InitCard (char *name) +{ + KdCardAttr attr; +#ifdef VXWORKS + attr.naddr = 2; + attr.io = 0; + attr.address[0] = 0xbc000000; /* registers */ + attr.address[1] = 0xba000000; /* frame buffer */ + KdCardInfoAdd (&s3Funcs, &attr, 0); +#else + CARD32 count; + + count = 0; + while (LinuxFindPci (0x5333, 0x8a22, count, &attr)) + { + KdCardInfoAdd (&s3Funcs, &attr, 0); + count++; + } +#endif +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdOsAddInputDrivers (); + KdInitInput (); +} + +extern int s3CpuTimeout; +extern int s3AccelTimeout; + +void +ddxUseMsg (void) +{ + ErrorF("\nSavage Driver Options:\n"); + ErrorF("-cpu Sets CPU timout\n"); + ErrorF("-accel Sets acceleration timout\n"); + + KdUseMsg(); +} + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + int ret; + + if (!strcmp (argv[i], "-cpu")) + { + s3CpuTimeout = strtol(argv[i+1], NULL, 0); + return 2; + } + if (!strcmp (argv[i], "-accel")) + { + s3AccelTimeout = strtol (argv[i+1], NULL, 0); + return 2; + } + return KdProcessArgument (argc, argv, i); +} |