xenocara/driver/xf86-video-i128/src/i128accel.c
2006-11-26 20:04:28 +00:00

521 lines
14 KiB
C

/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i128/i128accel.c,v 1.7 2000/12/06 01:07:34 robin Exp $ */
/*
* Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org>
*
* 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 Robin Cutshaw not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Robin Cutshaw makes no representations
* about the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL ROBIN CUTSHAW 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.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xaa.h"
#include "xaalocal.h"
#include "xf86fbman.h"
#include "miline.h"
#include "servermd.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86Pci.h"
#include "xf86PciInfo.h"
#include "i128.h"
#include "i128reg.h"
static void I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
int w, int h);
static void I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
int ydir, int rop, unsigned planemask, int transparency_color);
static void I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2, int w, int h);
static void I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
unsigned planemask);
static void I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w,
int h);
static void I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2, int flags);
static void I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2);
static void I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop,
unsigned int planemask, int nBox, register BoxPtr pBoxI);
static void I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox,
DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir, int alu,
unsigned planemask);
#define ENG_PIPELINE_READY() { while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY) ; }
#define ENG_DONE() { while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV)) ;}
/* pre-shift rops and just or in as needed */
static const CARD32 i128alu[16] =
{
CR_CLEAR<<8,
CR_AND<<8,
CR_AND_REV<<8,
CR_COPY<<8,
CR_AND_INV<<8,
CR_NOOP<<8,
CR_XOR<<8,
CR_OR<<8,
CR_NOR<<8,
CR_EQUIV<<8,
CR_INVERT<<8,
CR_OR_REV<<8,
CR_COPY_INV<<8,
CR_OR_INV<<8,
CR_NAND<<8,
CR_SET<<8
};
/* 8bpp 16bpp 32bpp unused */
static const int min_size[] = { 0x62, 0x32, 0x1A, 0x00 };
static const int max_size[] = { 0x80, 0x40, 0x20, 0x00 };
static const int split_size[] = { 0x20, 0x10, 0x08, 0x00 };
void
I128EngineDone(ScrnInfoPtr pScrn)
{
I128Ptr pI128 = I128PTR(pScrn);
ENG_DONE();
}
static void
I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h)
{
I128Ptr pI128 = I128PTR(pScrn);
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BB %d,%d %d,%d %d,%d 0x%x/0x%x\n", x1, y1, x2, y2, w, h, pI128->cmd);
#endif
ENG_PIPELINE_READY();
pI128->mem.rbase_a[CMD] = pI128->cmd;
/*pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;*/
if (pI128->blitdir & DIR_RL_TB) {
x1 += w; x1--;
x2 += w; x2--;
}
if (pI128->blitdir & DIR_LR_BT) {
y1 += h; y1--;
y2 += h; y2--;
}
if (pI128->Chipset == PCI_CHIP_I128) {
int bppi;
static int first_time_through = 1;
/* The I128-1 has a nasty bitblit bug
* that occurs when dest is exactly 8 pages wide
*/
bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24;
if ((w >= min_size[bppi]) && (w <= max_size[bppi])) {
if (first_time_through) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Using I128-1 workarounds.\n");
first_time_through = 0;
}
bppi = split_size[bppi];
#if 1
/* split method */
pI128->mem.rbase_a[XY2_WH] = (bppi<<16) | h;
pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
ENG_PIPELINE_READY();
w -= bppi;
if (pI128->blitdir & DIR_RL_TB) {
/* right to left blit */
x1 -= bppi;
x2 -= bppi;
} else {
/* left to right blit */
x1 += bppi;
x2 += bppi;
}
#else
/* clip method */
pI128->mem.rbase_a[CLPTL] = (x2<<16) | y2;
pI128->mem.rbase_a[CLPBR] = ((x2+w)<<16) | (y2+h);
w += bppi;
#endif
}
}
pI128->mem.rbase_a[XY2_WH] = (w<<16) | h;
pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
}
static void
I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
int rop, unsigned planemask, int transparency_color)
{
I128Ptr pI128 = I128PTR(pScrn);
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSSC %d,%d %d 0x%x %d\n", xdir, ydir, rop, planemask, transparency_color);
#endif
ENG_PIPELINE_READY();
if (planemask == -1)
pI128->mem.rbase_a[MASK] = -1;
else switch (pI128->bitsPerPixel) {
case 8:
pI128->mem.rbase_a[MASK] = planemask |
(planemask<<8) |
(planemask<<16) |
(planemask<<24);
break;
case 16:
pI128->mem.rbase_a[MASK] = planemask | (planemask<<16);
break;
case 24:
case 32:
default:
pI128->mem.rbase_a[MASK] = planemask;
break;
}
pI128->mem.rbase_a[CLPTL] = 0x00000000;
pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047;
if (transparency_color != -1)
pI128->mem.rbase_a[BACK] = transparency_color;
if (xdir == -1) {
if (ydir == -1) pI128->blitdir = DIR_RL_BT;
else pI128->blitdir = DIR_RL_TB;
} else {
if (ydir == -1) pI128->blitdir = DIR_LR_BT;
else pI128->blitdir = DIR_LR_TB;
}
pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;
pI128->rop = i128alu[rop];
pI128->cmd = (transparency_color != -1 ? (CS_TRNSP<<16) : 0) |
pI128->rop | CO_BITBLT;
pI128->mem.rbase_a[CMD] = pI128->cmd;
}
static void
I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2, int w, int h)
{
I128BitBlit(pScrn, x1, y1, x2, y2, w, h);
}
static void
I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
{
I128Ptr pI128 = I128PTR(pScrn);
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSF color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", color, rop, i128alu[rop]>>8, planemask);
#endif
ENG_PIPELINE_READY();
if (planemask == -1)
pI128->mem.rbase_a[MASK] = -1;
else switch (pI128->bitsPerPixel) {
case 8:
pI128->mem.rbase_a[MASK] = planemask |
(planemask<<8) |
(planemask<<16) |
(planemask<<24);
break;
case 16:
pI128->mem.rbase_a[MASK] = planemask | (planemask<<16);
break;
case 24:
case 32:
default:
pI128->mem.rbase_a[MASK] = planemask;
break;
}
pI128->mem.rbase_a[FORE] = color;
pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000;
pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ;
pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir = DIR_LR_TB;
pI128->rop = i128alu[rop];
pI128->cmd = (CS_SOLID<<16) | pI128->rop | CO_BITBLT;
pI128->mem.rbase_a[CMD] = pI128->cmd;
}
static void
I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
{
#if 0
I128Ptr pI128 = I128PTR(pScrn);
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SSFR %d,%d %d,%d\n", x, y, w, h);
#endif
I128BitBlit(pScrn, 0, 0, x, y, w, h);
}
static void
I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int flags)
{
I128Ptr pI128 = I128PTR(pScrn);
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STPL I128rop 0x%x %d,%d %d,%d clip %d,%d %d,%d\n", pI128->rop, x1, y1, x2, y2, pI128->clptl>>16, pI128->clptl&0xffff, (pI128->clpbr>>16)&0xffff, pI128->clpbr&0xffff);
#endif
ENG_PIPELINE_READY();
pI128->mem.rbase_a[CMD] =
((flags&0x0100) ? (CP_NLST<<24) : 0) |
(CC_CLPRECI<<21) |
(CS_SOLID<<16) |
pI128->rop |
CO_LINE;
pI128->mem.rbase_a[CLPTL] = pI128->clptl;
pI128->mem.rbase_a[CLPBR] = pI128->clpbr;
pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
}
static void
I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
{
I128Ptr pI128 = I128PTR(pScrn);
int tmp;
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SCR %d,%d %d,%d\n", x1, y1, x2, y2);
#endif
if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
pI128->clptl = (x1<<16) | y1;
pI128->clpbr = (x2<<16) | y2;
}
static void
I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask,
int nBox, register BoxPtr pBoxI)
{
I128Ptr pI128 = I128PTR(pScrn);
register int w, h;
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", fg, rop, i128alu[rop]>>8, planemask);
#endif
ENG_PIPELINE_READY();
if (planemask != -1) {
if (pI128->bitsPerPixel == 8) {
planemask |= (planemask<<8) |
(planemask<<16) |
(planemask<<24);
} else if (pI128->bitsPerPixel == 16)
planemask |= planemask<<16;
}
pI128->mem.rbase_a[MASK] = planemask;
pI128->mem.rbase_a[FORE] = fg;
pI128->mem.rbase_a[CMD] = (CS_SOLID<<16) | i128alu[rop] | CO_BITBLT;
pI128->mem.rbase_a[CLPTL] = 0x00000000;
pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047;
pI128->mem.rbase_a[XY3_DIR] = DIR_LR_TB;
pI128->mem.rbase_a[XY0_SRC] = 0x00000000;
while (nBox > 0) {
w = pBoxI->x2 - pBoxI->x1;
h = pBoxI->y2 - pBoxI->y1;
if (w > 0 && h > 0) {
pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; MB;
pI128->mem.rbase_a[XY1_DST] =
(pBoxI->x1<<16) | pBoxI->y1; MB;
ENG_PIPELINE_READY();
#if 0
if (pI128->Debug)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR x,y %d,%d w,h %d,%d\n", pBoxI->x1, pBoxI->y1, w, h);
#endif
}
pBoxI++;
nBox--;
}
ENG_DONE();
}
static void
I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, DDXPointPtr pptSrc,
BoxPtr pbox, int xdir, int ydir, int alu, unsigned planemask)
{
I128Ptr pI128 = I128PTR(pScrn);
I128SetupForScreenToScreenCopy(pScrn, xdir, ydir, alu, planemask, -1);
for (; nbox; pbox++, pptSrc++, nbox--)
I128SubsequentScreenToScreenCopy(pScrn, pptSrc->x, pptSrc->y,
pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
ENG_DONE();
}
Bool
I128XaaInit(ScreenPtr pScreen)
{
XAAInfoRecPtr infoPtr;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I128Ptr pI128 = I128PTR(pScrn);
BoxRec AvailFBArea;
CARD32 buf_ctrl;
int maxlines;
pI128->XaaInfoRec = infoPtr = XAACreateInfoRec();
if (!infoPtr) return FALSE;
infoPtr->Flags = PIXMAP_CACHE |
OFFSCREEN_PIXMAPS |
LINEAR_FRAMEBUFFER ;
infoPtr->Sync = I128EngineDone;
/* screen to screen copy */
infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
if (pI128->Chipset == PCI_CHIP_I128_T2R)
infoPtr->ScreenToScreenCopyFlags |= ONLY_LEFT_TO_RIGHT_BITBLT;
infoPtr->SetupForScreenToScreenCopy = I128SetupForScreenToScreenCopy;
infoPtr->SubsequentScreenToScreenCopy =
I128SubsequentScreenToScreenCopy;
#if 0
/* screen to screen color expansion */
if (pI128->Chipset == PCI_CHIP_I128_T2R)
infoPtr->ScreenToScreenColorExpandFillFlags |=
ONLY_LEFT_TO_RIGHT_BITBLT;
infoPtr->SetupForScreenToScreenColorExpandFill =
I128SetupForScreenToScreenColorExpandFill;
infoPtr->SubsequentScreenToScreenColorExpandFill =
I128SubsequentScreenToScreenColorExpandFill;
#endif
/* solid fills */
infoPtr->SetupForSolidFill = I128SetupForSolidFill;
infoPtr->SubsequentSolidFillRect = I128SubsequentSolidFillRect;
infoPtr->FillSolidRects = I128FillSolidRects;
/* solid lines */
infoPtr->SubsequentSolidTwoPointLine = I128SubsequentSolidTwoPointLine;
/* clipping */
infoPtr->ClippingFlags = HARDWARE_CLIP_LINE;
infoPtr->SetClippingRectangle = I128SetClippingRectangle;
infoPtr->PolyFillRectSolidFlags = 0;
maxlines = ((pI128->MemorySize * 1024) - 1024) /
(pScrn->displayWidth * pI128->bitsPerPixel / 8);
AvailFBArea.x1 = 0;
AvailFBArea.x2 = pI128->displayWidth;
AvailFBArea.y1 = 0;
AvailFBArea.y2 = maxlines;
xf86InitFBManager(pScreen, &AvailFBArea);
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Using %d lines for offscreen memory\n",
maxlines - pScrn->virtualY);
switch (pI128->bitsPerPixel) {
case 8: buf_ctrl = BC_PSIZ_8B; break;
case 16: buf_ctrl = BC_PSIZ_16B; break;
case 24:
case 32: buf_ctrl = BC_PSIZ_32B; break;
default: buf_ctrl = 0; break; /* error */
}
if (pI128->Chipset == PCI_CHIP_I128_T2R) {
if (pI128->MemoryType == I128_MEMORY_SGRAM)
buf_ctrl |= BC_MDM_PLN;
else
buf_ctrl |= BC_BLK_ENA;
}
pI128->mem.rbase_a[BUF_CTRL] = buf_ctrl;
pI128->mem.rbase_a[DE_PGE] = 0x00;
pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset;
pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset;
pI128->mem.rbase_a[DE_MSRC] = 0x00;
pI128->mem.rbase_a[DE_WKEY] = 0x00;
pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH];
pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH];
if (pI128->Chipset == PCI_CHIP_I128_T2R4)
pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH];
pI128->mem.rbase_a[RMSK] = 0x00000000;
pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE;
pI128->mem.rbase_a[LPAT] = 0xffffffff; /* for lines */
pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */
pI128->mem.rbase_a[CLPTL] = 0x00000000;
pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ;
pI128->mem.rbase_a[ACNTRL] = 0x00000000;
pI128->mem.rbase_a[INTM] = 0x03;
if (pI128->Debug) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128XaaInit done\n");
I128DumpActiveRegisters(pScrn);
}
return(XAAInit(pScreen, infoPtr));
}