#include "xf86.h"
#include "miline.h"
#include "s3.h"
#include "s3_reg.h"
#if 0
static Bool NicePattern;
static int DashPatternSize;
#define MAX_LINE_PATTERN_LENGTH 512
#define LINE_PATTERN_START ((MAX_LINE_PATTERN_LENGTH >> 5) - 1)
static CARD32 DashPattern[MAX_LINE_PATTERN_LENGTH >> 5];
#endif
static void S3Sync(ScrnInfoPtr pScrn)
{
WaitIdle();
}
static void S3SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask)
{
S3Ptr pS3 = S3PTR(pScrn);
WaitQueue16_32(4,6);
SET_PIX_CNTL(0);
SET_FRGD_COLOR(color);
SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
SET_WRT_MASK(planemask);
}
static void S3SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
int w, int h)
{
#ifdef S3_NEWMMIO
S3Ptr pS3 = S3PTR(pScrn);
#endif
WaitQueue(5);
SET_CURPT((short)x, (short)y);
SET_AXIS_PCNT(w - 1, h - 1);
SET_CMD(CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
}
static void S3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
int ydir, int rop,
unsigned int planemask,
int trans_color)
{
S3Ptr pS3 = S3PTR(pScrn);
pS3->BltDir = CMD_BITBLT | DRAW | WRTDATA;
if (xdir == 1)
pS3->BltDir |= INC_X;
if (ydir == 1)
pS3->BltDir |= INC_Y;
pS3->trans_color = trans_color;
WaitQueue16_32(3,4);
SET_PIX_CNTL(0);
SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
SET_WRT_MASK(planemask);
}
static void S3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
int srcx, int srcy,
int dstx, int dsty,
int w, int h)
{
S3Ptr pS3 = S3PTR(pScrn);
w--;
h--;
if (!(pS3->BltDir & INC_Y)) {
srcy += h;
dsty += h;
}
if (!(pS3->BltDir & INC_X)) {
srcx += w;
dstx += w;
}
if (pS3->trans_color == -1) {
WaitQueue(7);
SET_CURPT((short)srcx, (short)srcy);
SET_DESTSTP((short)dstx, (short)dsty);
SET_AXIS_PCNT((short)w, (short)h);
SET_CMD(pS3->BltDir);
} else {
WaitQueue16_32(2,3);
SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
SET_COLOR_CMP(pS3->trans_color);
WaitQueue(8);
SET_CURPT((short)srcx, (short)srcy);
SET_DESTSTP((short)dstx, (short)dsty);
SET_AXIS_PCNT((short)w, (short)h);
SET_CMD(pS3->BltDir);
SET_MULT_MISC(CMD_REG_WIDTH);
}
}
static void S3SetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
int patx, int paty,
int rop, unsigned int planemask,
int trans_color)
{
S3Ptr pS3 = S3PTR(pScrn);
pS3->trans_color = trans_color;
WaitQueue16_32(3,4);
SET_PIX_CNTL(0);
SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
SET_WRT_MASK(planemask);
}
static void S3SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn,
int patx, int paty,
int x, int y,
int w, int h)
{
S3Ptr pS3 = S3PTR(pScrn);
if (pS3->trans_color == -1) {
WaitQueue(7);
SET_CURPT((short)patx, (short)paty);
SET_DESTSTP((short)x, (short)y);
SET_AXIS_PCNT(w - 1, h - 1);
SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
} else {
WaitQueue16_32(2,3);
SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
SET_COLOR_CMP(pS3->trans_color);
WaitQueue(8);
SET_CURPT((short)patx, (short)paty);
SET_DESTSTP((short)x, (short)y);
SET_AXIS_PCNT(w - 1, h - 1);
SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
SET_MULT_MISC(CMD_REG_WIDTH);
}
}
#ifdef S3_NEWMMIO
static void S3SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int fg, int bg,
int rop,
unsigned int planemask)
{
S3Ptr pS3 = S3PTR(pScrn);
WaitQueue16_32(3,4);
if (bg == -1) {
if (pS3->ColorExpandBug) {
SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_XOR);
SET_BKGD_COLOR(0);
} else
SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_DST);
} else {
SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | s3alu[rop]);
SET_BKGD_COLOR(bg);
}
WaitQueue16_32(3,5);
SET_FRGD_COLOR(fg);
SET_WRT_MASK(planemask);
SET_PIX_CNTL(MIXSEL_EXPPC);
}
static void S3SubsequentCPUToScreenColorExpandFill32(ScrnInfoPtr pScrn,
int x, int y,
int w, int h,
int skipleft)
{
S3Ptr pS3 = S3PTR(pScrn);
WaitQueue(4);
SET_CURPT((short)x, (short)y);
SET_AXIS_PCNT((short)w-1, (short)h-1);
WaitIdle();
SET_CMD(CMD_RECT | BYTSEQ | _32BIT | PCDATA | DRAW |
PLANAR | INC_Y | INC_X | WRTDATA);
}
#endif
#if 0
#ifndef S3_NEWMMIO
static void S3SetupForScanlineImageWriteNoMMIO(ScrnInfoPtr pScrn, int rop,
unsigned int planemask,
int trans_color,
int bpp, int depth)
{
S3Ptr pS3 = S3PTR(pScrn);
WaitQueue16_32(3,4)
SET_FRGD_MIX(FSS_PCDATA | s3alu[rop]);
SET_WRT_MASK(planemask);
SET_PIX_CNTL(0);
}
static void S3SubsequentScanlineImageWriteRectNoMMIO(ScrnInfoPtr pScrn,
int x, int y,
int w, int h,
int skipleft)
{
S3Ptr pS3 = S3PTR(pScrn);
pS3->imageWidth = w;
pS3->imageHeight = h;
WaitQueue(5);
SET_CURPT((short)x, (short)y);
SET_AXIS_PCNT((short)w-1, (short)h-1);
WaitIdle();
SET_CMD(CMD_RECT | BYTSEQ | _16BIT | INC_Y | INC_X | DRAW |
PCDATA | WRTDATA);
}
static void S3SubsequentImageWriteScanlineNoMMIO(ScrnInfoPtr pScrn,
int bufno)
{
S3Ptr pS3 = S3PTR(pScrn);
int i, j;
int w, h;
CARD16 *src = (CARD16 *)&pS3->imageBuffer;
w = pS3->imageWidth * pS3->s3Bpp;
h = pS3->imageHeight;
for(j=0; j<h; j++) {
for(i=0; i<(w & ~1); ) {
SET_PIX_TRANS_W(ldw_u(src));
src++;
i += 2;
}
}
}
#endif
#endif
static void S3SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask)
{
S3Ptr pS3 = S3PTR(pScrn);
WaitQueue16_32(4,6);
SET_PIX_CNTL(0);
SET_FRGD_COLOR(color);
SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
SET_WRT_MASK(planemask);
}
static void S3SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
int x, int y,
int major, int minor,
int err, int len, int octant)
{
#ifdef S3_NEWMMIO
S3Ptr pS3 = S3PTR(pScrn);
#endif
unsigned short cmd;
int error, e1, e2;
error = minor + err;
e1 = minor;
e2 = minor - major;
if (major) {
cmd = CMD_LINE | DRAW | WRTDATA | LASTPIX;
if (octant & YMAJOR)
cmd |= YMAJAXIS;
if (!(octant & XDECREASING))
cmd |= INC_X;
if (!(octant & YDECREASING))
cmd |= INC_Y;
WaitQueue(7);
SET_CURPT((short)x, (short)y);
SET_ERR_TERM((short)error);
SET_DESTSTP((short)e2, (short)e1);
SET_MAJ_AXIS_PCNT((short)len);
SET_CMD(cmd);
} else {
WaitQueue(4);
SET_CURPT((short)x, (short)y);
SET_MAJ_AXIS_PCNT((short)len-1);
SET_CMD(CMD_LINE | DRAW | LINETYPE | WRTDATA | VECDIR_270);
}
}
static void S3SubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
int x, int y, int len, int dir)
{
if (dir == DEGREES_0)
S3SubsequentSolidFillRect(pScrn, x, y, len, 1);
else
S3SubsequentSolidFillRect(pScrn, x, y, 1, len);
}
#if 0
static void S3SetupForDashedLine(ScrnInfoPtr pScrn,
int fg, int bg,
int rop, unsigned int planemask,
int len, unsigned char *pattern)
{
#ifdef S3_NEWMMIO
S3Ptr pS3 = S3PTR(pScrn);
S3SetupForCPUToScreenColorExpandFill(pScrn, bg, fg, rop, planemask);
#endif
WaitQueue(4);
NicePattern = FALSE;
if (len <= 32) {
register CARD32 scratch = DashPattern[LINE_PATTERN_START];
if (len & (len - 1)) {
while (len < 16) {
scratch |= (scratch >> len);
len <<= 1;
}
scratch |= (scratch >> len);
DashPattern[LINE_PATTERN_START] = scratch;
} else {
switch (len) {
case 2:
scratch |= scratch >> 2;
case 4:
scratch |= scratch >> 4;
case 8:
scratch |= scratch >> 8;
case 16:
scratch |= scratch >> 16;
DashPattern[LINE_PATTERN_START] = scratch;
case 32:
NicePattern = TRUE;
default:
break;
}
}
}
DashPatternSize = len;
}
static void S3SubsequentDashedBresenhamLine32(ScrnInfoPtr pScrn,
int x, int y,
int absmaj, int absmin,
int err, int len,
int octant, int phase)
{
#ifdef S3_NEWMMIO
S3Ptr pS3 = S3PTR(pScrn);
#endif
register int count = (len + 31) >> 5;
register CARD32 pattern;
int error, e1, e2;
error = absmin + err;
e1 = absmaj;
e2 = absmin - absmaj;
if (err) {
unsigned short cmd = _32BIT | PLANAR | WRTDATA | DRAW |
PCDATA | LASTPIX | CMD_LINE;
if (octant & YMAJOR)
cmd |= YMAJAXIS;
if (!(octant & XDECREASING))
cmd |= INC_X;
if (!(octant & YDECREASING))
cmd |= INC_Y;
WaitQueue(7);
SET_CURPT((short)x, (short)y);
SET_ERR_TERM((short)error);
SET_DESTSTP((short)e2, (short)e1);
SET_MAJ_AXIS_PCNT((short)len);
SET_CMD(cmd);
} else {
if (octant & YMAJOR) {
WaitQueue(4);
SET_CURPT((short)x, (short)y);
SET_MAJ_AXIS_PCNT((short)len - 1);
if (octant & YDECREASING) {
SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
CMD_LINE | LINETYPE | VECDIR_090);
} else {
SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
CMD_LINE | LINETYPE | VECDIR_270);
}
} else {
if (octant & XDECREASING) {
WaitQueue(4);
SET_CURPT((short)x, (short)y);
SET_MAJ_AXIS_PCNT((short)len - 1);
SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
PCDATA | CMD_LINE | LINETYPE | VECDIR_180);
} else {
WaitQueue(4);
SET_CURPT((short)x, (short)y);
SET_MAJ_AXIS_PCNT((short)len - 1);
SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
PCDATA | CMD_RECT | INC_Y | INC_X);
}
}
}
if (NicePattern) {
#ifdef S3_NEWMMIO
register CARD32 *dest = (CARD32*)&IMG_TRANS;
#endif
pattern = (phase) ? (DashPattern[LINE_PATTERN_START] << phase) |
(DashPattern[LINE_PATTERN_START] >> (32 - phase)) :
DashPattern[LINE_PATTERN_START];
#ifdef S3_NEWMMIO
while (count & ~0x03) {
dest[0] = dest[1] = dest[2] = dest[3] = pattern;
dest += 4;
count -= 4;
}
switch (count) {
case 1:
dest[0] = pattern;
break;
case 2:
dest[0] = dest[1] = pattern;
break;
case 3:
dest[0] = dest[1] = dest[2] = pattern;
break;
}
#else
while (count--)
SET_PIX_TRANS_L(pattern);
#endif
} else if (DashPatternSize < 32) {
register int offset = phase;
while (count--) {
SET_PIX_TRANS_L((DashPattern[LINE_PATTERN_START] << offset) |
(DashPattern[LINE_PATTERN_START] >>
(DashPatternSize - offset)));
offset += 32;
while (offset > DashPatternSize)
offset -= DashPatternSize;
}
} else {
int offset = phase;
register unsigned char *srcp = (unsigned char *)(DashPattern) +
(MAX_LINE_PATTERN_LENGTH >> 3) - 1;
register CARD32 *scratch;
int scratch2, shift;
while (count--) {
shift = DashPatternSize - offset;
scratch = (CARD32*)(srcp - (offset >> 3) - 3);
scratch2 = offset & 0x07;
if (shift & ~31) {
if (scratch2) {
pattern = (*scratch << scratch2) |
(*(scratch - 1) >> (32 - scratch2));
} else
pattern = *scratch;
} else {
pattern = (*((CARD32*)(srcp - 3)) >> shift) |
(*scratch << scratch2);
}
SET_PIX_TRANS_L(pattern);
offset += 32;
while (offset >= DashPatternSize)
offset -= DashPatternSize;
}
}
}
#endif
#ifdef S3_NEWMMIO
Bool S3AccelInitNewMMIO(ScreenPtr pScreen)
#else
Bool S3AccelInitPIO(ScreenPtr pScreen)
#endif
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
S3Ptr pS3 = S3PTR(pScrn);
XAAInfoRecPtr pXAA;
if (pS3->Chipset == PCI_CHIP_968)
pS3->ColorExpandBug = TRUE;
else
pS3->ColorExpandBug = FALSE;
if (!(pXAA = XAACreateInfoRec()))
return FALSE;
pS3->pXAA = pXAA;
pXAA->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS |
LINEAR_FRAMEBUFFER);
pXAA->Sync = S3Sync;
pXAA->SetupForSolidFill = S3SetupForSolidFill;
pXAA->SubsequentSolidFillRect = S3SubsequentSolidFillRect;
pXAA->SetupForScreenToScreenCopy = S3SetupForScreenToScreenCopy;
pXAA->SubsequentScreenToScreenCopy = S3SubsequentScreenToScreenCopy;
pXAA->SetupForColor8x8PatternFill = S3SetupForColor8x8PatternFill;
pXAA->SubsequentColor8x8PatternFillRect = S3SubsequentColor8x8PatternFillRect;
#ifdef S3_NEWMMIO
pXAA->SetupForCPUToScreenColorExpandFill =
S3SetupForCPUToScreenColorExpandFill;
pXAA->SubsequentCPUToScreenColorExpandFill =
S3SubsequentCPUToScreenColorExpandFill32;
pXAA->ColorExpandBase = (void *) &IMG_TRANS;
pXAA->ColorExpandRange = 0x8000;
pXAA->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD |
BIT_ORDER_IN_BYTE_MSBFIRST |
SCANLINE_PAD_DWORD;
#endif
#if 0
#ifndef S3_NEWMMIO
pXAA->ScanlineImageWriteFlags = NO_TRANSPARENCY;
pXAA->SetupForScanlineImageWrite =
S3SetupForScanlineImageWriteNoMMIO;
pXAA->SubsequentScanlineImageWriteRect =
S3SubsequentScanlineImageWriteRectNoMMIO;
pXAA->SubsequentImageWriteScanline =
S3SubsequentImageWriteScanlineNoMMIO;
pXAA->NumScanlineImageWriteBuffers = 1;
pXAA->ScanlineImageWriteBuffers = &pS3->imageBuffer;
#endif
#endif
pXAA->SetupForSolidLine = S3SetupForSolidLine;
pXAA->SubsequentSolidBresenhamLine = S3SubsequentSolidBresenhamLine;
pXAA->SubsequentSolidHorVertLine = S3SubsequentSolidHorVertLine;
pXAA->SolidBresenhamLineErrorTermBits = 12;
#if 0
pXAA->SetupForDashedLine = S3SetupForDashedLine;
pXAA->SubsequentDashedBresenhamLine = S3SubsequentDashedBresenhamLine32;
pXAA->DashPatternMaxLength = MAX_LINE_PATTERN_LENGTH;
#endif
return XAAInit(pScreen, pXAA);
}