/* * Accelerated Driver for the SGI Indy's Newport graphics card * * (c) 2004 Dominik Behr * this code is released under xfree 4.3.0 and xorg 6.8.0 license * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "newport.h" #include #ifdef NEWPORT_ACCEL #include "mi.h" #include "mizerarc.h" #define BARF(a) xf86DrvMsg(0, X_INFO, (a)) #define BARF1(a,b) xf86DrvMsg(0, X_INFO, (a), (b)) #define BARF2(a,b,c) xf86DrvMsg(0, X_INFO, (a), (b), (c)) #define BARF3(a,b,c,d) xf86DrvMsg(0, X_INFO, (a), (b), (c), (d)) #define BARF4(a,b,c,d,e) xf86DrvMsg(0, X_INFO, (a), (b), (c), (d), (e)) #define BARF5(a,b,c,d,e,f) xf86DrvMsg(0, X_INFO, (a), (b), (c), (d), (e), (f)) #define BARF6(a,b,c,d,e,f,g) xf86DrvMsg(0, X_INFO, (a), (b), (c), (d), (e), (f), (g)) /* XAA Functions */ #define NEWPORT_PREROTATE /* there is a bug in XAA which causes it to reference NULL pointer to pattern cache when using HARDWARE_PROGRAMMED_PATTERN only (try x11perf -strap1) thus we have to also set HARDWARE_PROGRAMMED_ORIGIN and prerotate the pattern in the setup function */ #define NEWPORT_GFIFO_ENTRIES 30 /* I dont know how many entries are in the gfx FIFO, judging by 6 bits in the GFIFO level status register it can be at most 63. it must be at least 32 because otherwise they would use less bits for status for now 16 seems to be safe value */ #define NEWPORT_DELAY 128 /******************************************************************************* *******************************************************************************/ static void NewportWaitIdle(NewportPtr pNewport, unsigned int uEntries) { NewportRegsPtr pNewportRegs; pNewportRegs = pNewport->pNewportRegs; /* wait for the GFIFO to drain */ while ((pNewportRegs->cset.stat & NPORT_STAT_GLMSK)) { int i; volatile int x; for (x = 0, i = 0; i < NEWPORT_DELAY; i++) { x += i; } } /* and then wait for the graphic to be idle */ while (pNewportRegs->cset.stat & NPORT_STAT_GBUSY) { int i; volatile int x; for (x = 0, i = 0; i < NEWPORT_DELAY; i++) { x += i; } } pNewport->fifoleft = NEWPORT_GFIFO_ENTRIES-uEntries; } #if 0 /******************************************************************************* *******************************************************************************/ static void NewportWaitGFIFO(NewportPtr pNewport, unsigned int uEntries) { unsigned int uWaitLevel; /* NewportWaitIdle(pNewport, NEWPORT_GFIFO_ENTRIES); return;*/ if (uEntries >= NEWPORT_GFIFO_ENTRIES) { uWaitLevel = 0; } else { uWaitLevel = NEWPORT_GFIFO_ENTRIES-uEntries; } /* HACK */ /*uWaitLevel = 0;*/ while (((pNewport->pNewportRegs->cset.stat & NPORT_STAT_GLMSK) >> 7) > uWaitLevel) { int i; volatile int x; for (x = 0, i = 0; i < NEWPORT_DELAY; i++) { x += i; } } } #endif #if 1 /******************************************************************************* *******************************************************************************/ /* * Wait until 'uEntries' are available in the GFIFO. * * This tracks how many entries are in the fifo via the * fifoleft value, and will avoid reading the FIFO itself * if it estimates enough entries are left in the FIFO. * Once the estimate runs out, it will update the * number of FIFO entries available. * * TODO: add some counters here; it'd be nice to know * how often the prediction works, how often we ran out * and needed to read the GFIFO register, how often we * had to spin waiting. */ static void NewportWaitGFIFO(NewportPtr pNewport, unsigned int uEntries) { if (uEntries > NEWPORT_GFIFO_ENTRIES) { uEntries = NEWPORT_GFIFO_ENTRIES; } if (uEntries <= pNewport->fifoleft) { pNewport->fifoleft -= uEntries; return; } while (1) { unsigned int fifolevel; int i; volatile int x; fifolevel = (pNewport->pNewportRegs->cset.stat & NPORT_STAT_GLMSK) >> 7; if (fifolevel < NEWPORT_GFIFO_ENTRIES) { pNewport->fifoleft = NEWPORT_GFIFO_ENTRIES - fifolevel; } else { pNewport->fifoleft = 0; } if (uEntries <= pNewport->fifoleft) { pNewport->fifoleft -= uEntries; return; } /* * This is a CPU busy loop which is not the most efficient * use of CPU, especially if the X server is multi-threaded. * * TODO: attempt to keep counters here; it'd be nice to know * how often this is being hit. */ for (x = 0, i = 0; i < NEWPORT_DELAY; i++) { x += i; } } } #endif /******************************************************************************* *******************************************************************************/ static void NewportXAASync(ScrnInfoPtr pScrn) { NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); NewportWaitIdle(pNewport, 0); } /******************************************************************************* *******************************************************************************/ static unsigned int Rop2LogicOp(int rop) { return (unsigned int)rop << 28; } /******************************************************************************* *******************************************************************************/ static void NewportUpdateClipping(NewportPtr pNewport) { unsigned int smask0x, smask0y; if (pNewport->skipleft > pNewport->clipsx) { smask0x = ((pNewport->skipleft & 0xFFFF) << 16) | (pNewport->clipex & 0xFFFF); } else { smask0x = ((pNewport->clipsx & 0xFFFF) << 16) | (pNewport->clipex & 0xFFFF); } if (smask0x != pNewport->shadow_smask0x) { NewportWaitGFIFO(pNewport, 1); pNewport->shadow_smask0x = smask0x; pNewport->pNewportRegs->set.smask0x = smask0x; } smask0y = ((pNewport->clipsy & 0xFFFF) << 16) | (pNewport->clipey & 0xFFFF); if (smask0y != pNewport->shadow_smask0y) { NewportWaitGFIFO(pNewport, 1); pNewport->shadow_smask0y = smask0y; pNewport->pNewportRegs->set.smask0y = smask0y; } } /******************************************************************************* *******************************************************************************/ /* * Map the XAA colours to the HOSTRW format. * * The HOSTRW format for RGBA-32 is ABGR, A being MSB and * R being LSB. * * See the REX3 specification, Section 3.10 (Framebuffer PIO and DMA.) */ static unsigned int NewportColor2HOSTRW(unsigned int color) { /* default XAA color is 0,R,G,B */ #if 0 return ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 16) | ((color & 0x00FF00)) ; #endif /* but we changed masks to match the native format */ return color; } /******************************************************************************* *******************************************************************************/ /* * Map the 24 bit RGB colour into the required framebuffer pixel * layout for 24 bit pixels. * * The pixel format is in the REX3 specification Section 3.9 * (framebuffer formats.) It's an interleaved pixel format, * starting at the MSB (bit 23), going BRG(0), BRG(1), BRG(2) .. * BRG(7). */ static unsigned int NewportColor2Planes24RGB(unsigned int color) { unsigned int res; unsigned int i; unsigned int mr, mg, mb; unsigned int sr, sg, sb; res = 0; #if 0 /* XAA color is 0,R,G,B */ mr = 0x800000; mg = 0x008000; mb = 0x000080; #endif /* * The XAA format is now BGR, to match the hardware mapping. * However the raw pixel format is not this. */ mr = 0x000080; mg = 0x008000; mb = 0x800000; sr = 2; sg = 1; sb = 4; for (i = 0; i < 8; i++) { res |= (color & mr)?sr:0; res |= (color & mg)?sg:0; res |= (color & mb)?sb:0; sr <<= 3; sg <<= 3; sb <<= 3; mr >>= 1; mg >>= 1; mb >>= 1; } return res; } /******************************************************************************* *******************************************************************************/ /* * Map the 8 bit colour index to the underlying framebuffer pixel layout. * * For Psuedocolour pixels, this is a 1:1 mapping of bits 7:0. */ static unsigned int NewportColor2Planes8CI(unsigned int color) { return color; } /******************************************************************************* *******************************************************************************/ static void NewportUpdateCOLORI(NewportPtr pNewport, unsigned long colori) { if (colori != pNewport->shadow_colori) { NewportWaitGFIFO(pNewport, 1); pNewport->shadow_colori = colori; pNewport->pNewportRegs->set.colori = colori; } } /******************************************************************************* *******************************************************************************/ /* * Update the DRAWMODE0 register. * * TODO: does this register stall the pipeline? The REX3 documentation * is unclear. */ static void NewportUpdateDRAWMODE0(NewportPtr pNewport, unsigned long drawmode0) { if (drawmode0 != pNewport->shadow_drawmode0) { NewportWaitGFIFO(pNewport, 1); pNewport->shadow_drawmode0 = drawmode0; pNewport->pNewportRegs->set.drawmode0 = drawmode0; } } /******************************************************************************* *******************************************************************************/ /* * Update the DRAWMODE1 register. * * This register stalls the pipeline until clear when written to. * * TODO: should update GFIFO depth when this is written to! */ static void NewportUpdateDRAWMODE1(NewportPtr pNewport, unsigned long drawmode1) { if (drawmode1 != pNewport->shadow_drawmode1) { NewportWaitIdle(pNewport, 1); pNewport->shadow_drawmode1 = drawmode1; pNewport->pNewportRegs->set.drawmode1 = drawmode1; } } /******************************************************************************* *******************************************************************************/ /* * Update the COLORVRAM register. * * This register stalls the pipeline until clear when written to. * * TODO: should update GFIFO depth when this is written to! */ static void NewportUpdateCOLORVRAM(NewportPtr pNewport, unsigned long colorvram) { if (colorvram != pNewport->shadow_colorvram) { NewportWaitIdle(pNewport, 1); pNewport->shadow_colorvram = colorvram; pNewport->pNewportRegs->set.colorvram = colorvram; } } /******************************************************************************* *******************************************************************************/ /* * Update the COLORBACK register. * * This register stalls the pipeline until clear when written to. * * TODO: should update GFIFO depth when this is written to! */ static void NewportUpdateCOLORBACK(NewportPtr pNewport, unsigned long colorback) { if (colorback != pNewport->shadow_colorback) { NewportWaitIdle(pNewport, 1); pNewport->shadow_colorback = colorback; pNewport->pNewportRegs->set.colorback = colorback; } } /******************************************************************************* *******************************************************************************/ /* * Update the WRMASK register. * * This register stalls the pipeline until clear when written to. * * TODO: should update GFIFO depth when this is written to! */ static void NewportUpdateWRMASK(NewportPtr pNewport, unsigned long wrmask) { if (wrmask != pNewport->shadow_wrmask) { NewportWaitIdle(pNewport, 1); pNewport->shadow_wrmask = wrmask; pNewport->pNewportRegs->set.wrmask = wrmask; } } /******************************************************************************* *******************************************************************************/ /* * Update the XYMOVE register. * * This register stalls the pipeline until clear when written to. * * TODO: should update GFIFO depth when this is written to! */ static void NewportUpdateXYMOVE(NewportPtr pNewport, unsigned long xymove) { if (xymove != pNewport->shadow_xymove) { NewportWaitIdle(pNewport, 1); pNewport->shadow_xymove = xymove; pNewport->pNewportRegs->set.xymove = xymove; } } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned int planemask, int trans_color) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int width, int height) { int dx, dy; unsigned int sx, sy, ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); dx = x2 - x1; dy = y2 - y1; if (!dx && !dy) return; if (width) x2 = x1 + width - 1; else x2 = x1; if (height) y2 = y1 + height - 1; else y2 = y1; if (dx < 0) { sx = x1 & 0xFFFF; ex = x2 & 0xFFFF; } else { sx = x2 & 0xFFFF; ex = x1 & 0xFFFF; } if (dy < 0) { sy = y1 & 0xFFFF; ey = y2 & 0xFFFF; } else { sy = y2 & 0xFFFF; ey = y1 & 0xFFFF; } dx &= 0xFFFF; dy &= 0xFFFF; NewportUpdateXYMOVE(pNewport, (dx << 16) | dy); /* this is bad because it stalls the pipeline but nothing can be done about it */ NewportWaitGFIFO(pNewport, 2); pNewportRegs->set.xystarti = (sx << 16) | sy; pNewportRegs->go.xyendi = (ex << 16) | ey; } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForSolidFill(ScrnInfoPtr pScrn, int Color, int rop, unsigned int planemask) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (rop == GXcopy || rop == GXclear || rop == GXset) { /* if possible try to set up a fast clear which is 4x faster */ NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | NPORT_DMODE1_FCLR | Rop2LogicOp(GXcopy)); if (rop == GXclear) NewportUpdateCOLORVRAM(pNewport, 0); else if (rop == GXset) NewportUpdateCOLORVRAM(pNewport, 0xFFFFFF); else NewportUpdateCOLORVRAM(pNewport, pNewport->Color2Planes((unsigned int)Color)); } else { NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(Color)); } NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) { int ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; NewportWaitGFIFO(pNewport, 2); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->go.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); } /******************************************************************************* *******************************************************************************/ /* * Setup for a Solid Line draw */ static void NewportXAASetupForSolidLine(ScrnInfoPtr pScrn, int Color, int rop, unsigned int planemask) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(Color)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); pNewport->setup_drawmode0 = (0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_ILINE | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY ); } /******************************************************************************* *******************************************************************************/ /* * Draw a solid line * * TODO: surely the XAA server is feeding us a list of lines * to write, rather than a constant setup/line/setup/line etc. * See xaa/xaaLine.c for more info. * * Apparently if POLYSEGMENT is defined then we get a flag * that says whether to draw the last pixel or not, but it's * not really a "this is the last line to batch". */ static void NewportXAASubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); /* * TODO: if this doesn't stall the pipeline then it makes sense * that we can keep changing drawmode0 on each line draw. */ NewportUpdateDRAWMODE0(pNewport, pNewport->setup_drawmode0 | ((flags & OMIT_LAST) ? NPORT_DMODE0_SKLST : 0) ); NewportWaitGFIFO(pNewport, 2); pNewportRegs->set.xystarti = ((x1 & 0xFFFF) << 16) | (y1 & 0xFFFF); pNewportRegs->go.xyendi = ((x2 & 0xFFFF) << 16) | (y2 & 0xFFFF); } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int length, unsigned char *pattern) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; int i; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); pNewport->dashline_patlen = length; for (i = 0; i < (length+7)>>3; i++) pNewport->dashline_pat[i] = pattern[i]; NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); if (bg != -1) NewportUpdateCOLORBACK(pNewport, NewportColor2HOSTRW(bg)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(fg)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); pNewport->setup_drawmode0 = (0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_ILINE | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY | NPORT_DMODE0_L32 | NPORT_DMODE0_ZPENAB | ((bg == -1) ? 0 : NPORT_DMODE0_ZOPQ) ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags, int phase) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; int dx, dy; unsigned int linelen; unsigned int dwords; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); dx = x2 - x1; if (dx < 0) dx = -dx; dx++; dy = y2 - y1; if (dy < 0) dy = -dy; dy++; if (dx > dy) linelen = dx; else linelen = dy; dwords = (linelen + 31) >> 5; NewportUpdateDRAWMODE0(pNewport, pNewport->setup_drawmode0 | ((flags & OMIT_LAST) ? NPORT_DMODE0_SKLST : 0) ); NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x1 & 0xFFFF) << 16) | (y1 & 0xFFFF); pNewportRegs->set.xyendi = ((x2 & 0xFFFF) << 16) | (y2 & 0xFFFF); pNewportRegs->set._setup = 1; phase %= pNewport->dashline_patlen; while (dwords--) { unsigned int bit; unsigned int pat; unsigned int mask; pat = 0; mask = 0x80000000; for (bit = 0; bit < 32; bit++) { if (pNewport->dashline_pat[phase >> 3] & (0x80 >> (phase & 7))) pat |= mask; phase = (phase + 1) % pNewport->dashline_patlen; mask >>= 1; } NewportWaitGFIFO(pNewport, 1); pNewportRegs->go.zpattern = pat; } } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); if (bg != -1) NewportUpdateCOLORBACK(pNewport, NewportColor2HOSTRW(bg)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(fg)); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | ((bg == -1) ? 0 : NPORT_DMODE0_ZOPQ) | NPORT_DMODE0_L32 ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft) { int ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; if (skipleft) { pNewport->skipleft = x + skipleft; } else { pNewport->skipleft = 0; } NewportUpdateClipping(pNewport); NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->set.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); pNewportRegs->set._setup = 1; /* after return XAA will start blasting the pattern to go.zpattern register */ /* we have to wait here for idle because if there is something in the pipeline that will take long time to complete and if following cpu transfers will overflow the FIFO causing GIO bus stall it will end up in bus error */ NewportWaitIdle(pNewport, NEWPORT_GFIFO_ENTRIES); } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, int trans_color, int bpp, int depth) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_CHOST | NPORT_DMODE0_DOSETUP ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft) { int ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; if (skipleft) { pNewport->skipleft = x + skipleft; } else { pNewport->skipleft = 0; } NewportUpdateClipping(pNewport); NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->set.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); pNewportRegs->set._setup = 1; /* after return XAA will start blasting the image to go.hostrw0 register */ /* we have to wait here for idle because if there is something in the pipeline that will take long time to complete and if following cpu transfers will overflow the FIFO causing GIO bus stall it will end up in bus error */ NewportWaitIdle(pNewport, NEWPORT_GFIFO_ENTRIES); } static unsigned int repbyte(unsigned int b) { b &= 0xFF; return b | (b << 8) | (b << 16) | (b << 24); } static void prerotatebyte(unsigned int b, unsigned int *p) { int i; b &= 0xFF; for (i = 0; i < 8; i++) { p[i] = repbyte(b); if (b & 1) b = (b >> 1) | 0x80; else b = b >> 1; } } /******************************************************************************* *******************************************************************************/ static void NewportXAASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg, int bg, int rop, unsigned int planemask) { NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); #ifdef NEWPORT_PREROTATE /* prerotate the pattern */ prerotatebyte((unsigned int)patx >> 24, pNewport->pat8x8[0]); prerotatebyte((unsigned int)patx >> 16, pNewport->pat8x8[1]); prerotatebyte((unsigned int)patx >> 8, pNewport->pat8x8[2]); prerotatebyte((unsigned int)patx, pNewport->pat8x8[3]); prerotatebyte((unsigned int)paty >> 24, pNewport->pat8x8[4]); prerotatebyte((unsigned int)paty >> 16, pNewport->pat8x8[5]); prerotatebyte((unsigned int)paty >> 8, pNewport->pat8x8[6]); prerotatebyte((unsigned int)paty, pNewport->pat8x8[7]); #endif NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(planemask)); if (bg != -1) NewportUpdateCOLORBACK(pNewport, NewportColor2HOSTRW(bg)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(fg)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | ((bg == -1) ? 0 : NPORT_DMODE0_ZOPQ) | NPORT_DMODE0_L32 ); } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty, int x, int y, int w, int h) { int ex, ey; unsigned int d; #ifndef NEWPORT_PREROTATE unsigned int p; unsigned int epat[8]; #endif NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->set.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); pNewportRegs->set._setup = 1; #ifdef NEWPORT_PREROTATE patx &= 7; paty &= 7; while (h--) { for (d = (w + 31) >> 5; d; d--) { NewportWaitGFIFO(pNewport, 1); pNewportRegs->go.zpattern = pNewport->pat8x8[paty][patx]; } paty = (paty + 1) & 7; } #else epat[0] = repbyte(patx >> 24); epat[1] = repbyte(patx >> 16); epat[2] = repbyte(patx >> 8); epat[3] = repbyte(patx); epat[4] = repbyte(paty >> 24); epat[5] = repbyte(paty >> 16); epat[6] = repbyte(paty >> 8); epat[7] = repbyte(paty); p = 0; while (h--) { for (d = (w + 31) >> 5; d; d--) { NewportWaitGFIFO(pNewport, 1); pNewportRegs->go.zpattern = epat[p]; } p = (p + 1) ^ 7; } #endif } /******************************************************************************* *******************************************************************************/ static void NewportXAAReadPixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *dst, int dstwidth, int bpp, int depth) { int ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; NewportWaitIdle(pNewport, 0); NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(GXcopy) | NPORT_DMODE1_PFENAB); NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(0xFFFFFFFF)); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_RD | NPORT_DMODE0_BLOCK | NPORT_DMODE0_CHOST | NPORT_DMODE0_DOSETUP ); NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->set.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); /* with prefetch enabled go has to be issued before we start reading */ pNewportRegs->go._setup = 1; if (pScrn->bitsPerPixel == 8) { unsigned int d; while (h--) { unsigned char *p; p = (unsigned char *)dst; for (x = 0; x < w; x += 4) { if (!h && x+4 >= w) { /* the last dword does not need go */ d = pNewportRegs->set.hostrw0; } else { d = pNewportRegs->go.hostrw0; } *p++ = (d & 0xFF000000) >> 24; if (x+1 < w) { *p++ = (d & 0x00FF0000) >> 16; } if (x+2 < w) { *p++ = (d & 0x0000FF00) >> 8; } if (x+3 < w) { *p++ = d & 0x000000FF; } } dst += dstwidth; } } else { while (h--) { unsigned int *p; p = (unsigned int *)dst; for (x = 0; x < w; x++) { if (!h && x+1 == w) { /* the last dword does not need go */ *p++ = pNewportRegs->set.hostrw0; } else { *p++ = pNewportRegs->go.hostrw0; } } dst += dstwidth; } } } /******************************************************************************* *******************************************************************************/ static void NewportXAASetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right, int bottom) { NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); if (left < 0) left = 0; if (right > pScrn->virtualX-1) right = pScrn->virtualX-1; if (top < 0) top = 0; if (bottom > pScrn->virtualY-1) bottom = pScrn->virtualY-1; pNewport->clipsx = left; pNewport->clipex = right; pNewport->clipsy = top; pNewport->clipey = bottom; NewportUpdateClipping(pNewport); } /******************************************************************************* *******************************************************************************/ static void NewportXAADisableClipping(ScrnInfoPtr pScrn) { NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewport->clipsx = 0; pNewport->clipex = pScrn->virtualX-1; pNewport->clipsy = 0; pNewport->clipey = pScrn->virtualY-1; NewportUpdateClipping(pNewport); } /******************************************************************************* *******************************************************************************/ /* * TODO: it would be good to keep some counters on how large * the average/min/max fill is and how many points are passed * in; that'd give us a good idea as to whether these would * benefit by being turned into DMA and save some CPU resources. */ static void NewportPolyPoint(DrawablePtr pDraw, GCPtr pGC, int mode, int npt, xPoint *ppt) { ScrnInfoPtr pScrn; int numRects = REGION_NUM_RECTS(pGC->pCompositeClip); int rect; XAAInfoRecPtr infoRec; BoxPtr pbox; int x, y; int rop; NewportRegsPtr pNewportRegs; NewportPtr pNewport; infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); pScrn = infoRec->pScrn; if (!numRects) return; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); x = pDraw->x; y = pDraw->y; rop = pGC->alu; NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(pGC->planemask)); if (rop == GXcopy || rop == GXclear || rop == GXset) { /* if possible try to set up a fast clear which is 4x faster */ NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | NPORT_DMODE1_FCLR | Rop2LogicOp(GXcopy)); if (rop == GXclear) NewportUpdateCOLORVRAM(pNewport, 0); else if (rop == GXset) NewportUpdateCOLORVRAM(pNewport, 0xFFFFFF); else NewportUpdateCOLORVRAM(pNewport, pNewport->Color2Planes((unsigned int)(pGC->fgPixel))); } else { NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(rop)); NewportUpdateCOLORI(pNewport, NewportColor2HOSTRW(pGC->fgPixel)); } pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP ); pbox = REGION_RECTS(pGC->pCompositeClip); while (npt--) { if (mode == CoordModePrevious) { x += ppt->x; y += ppt->y; } else { x = pDraw->x + ppt->x; y = pDraw->y + ppt->y; } for (rect = 0; rect < numRects; rect++) if (x >= pbox[rect].x1 && x < pbox[rect].x2 && y >= pbox[rect].y1 && y < pbox[rect].y2) { /* draw point */ unsigned int xy; xy = ((x & 0xFFFF) << 16) | (y & 0xFFFF); NewportWaitGFIFO(pNewport, 2); pNewportRegs->set.xystarti = xy; pNewportRegs->go.xyendi = xy; break; } ppt++; } } /******************************************************************************* *******************************************************************************/ static void NewportValidatePolyPoint(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) { if (pDraw->type == DRAWABLE_WINDOW) { pGC->ops->PolyPoint = NewportPolyPoint; } else { pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint; } } #if 1 /******************************************************************************* *******************************************************************************/ static void NewportPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) { xArc *arc; BoxRec box; int i, x2, y2; RegionPtr cclip; cclip = pGC->pCompositeClip; if(!REGION_NUM_RECTS(cclip)) return; for (arc = parcs, i = narcs; --i >= 0; arc++) { if (miCanZeroArc(arc)) { box.x1 = arc->x + pDraw->x; box.y1 = arc->y + pDraw->y; x2 = box.x1 + (int)arc->width + 1; box.x2 = x2; y2 = box.y1 + (int)arc->height + 1; box.y2 = y2; if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) && (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) ) miZeroPolyArc(pDraw, pGC, 1, arc); } else miPolyArc(pDraw, pGC, 1, arc); } } #endif /******************************************************************************* *******************************************************************************/ static void NewportValidatePolyArc(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) { if (pDraw->type == DRAWABLE_WINDOW) { pGC->ops->PolyPoint = NewportPolyPoint; /*pGC->ops->PolyArc = miPolyArc;*/ pGC->ops->PolyArc = NewportPolyArc; } else { pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint; pGC->ops->PolyArc = XAAGetFallbackOps()->PolyArc; } } #ifdef RENDER /******************************************************************************* *******************************************************************************/ static Bool NewportXAASetupForCPUToScreenAlphaTexture( ScrnInfoPtr pScrn, int op, CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, CARD32 maskFormat, CARD32 dstFormat, CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags) { unsigned int col, a; unsigned char *pSrc; unsigned int *pDst; unsigned int w; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (width * height * sizeof(unsigned int) > pNewport->uTextureSize) { free(pNewport->pTexture); pNewport->pTexture = xnfalloc(pNewport->uTextureSize = width * height * sizeof(unsigned int)); } col = (((unsigned int)red & 0xFF00) << 8) | ((unsigned int)green & 0xFF00) | ((unsigned int)blue >> 8); pNewport->uTextureWidth = width; pNewport->uTextureHeight = height; pNewport->uTextureFlags = flags; /* copy texture */ pDst = pNewport->pTexture; while (height--) { pSrc = (unsigned char *)alphaPtr; for (w = width; w; w--) { /* premultiply alpha */ a = *pSrc++; a *= alpha; a /= 0xFFFF; a <<= 24; *pDst++ = col | a; } alphaPtr += alphaPitch; } #define SFACTOR (4 << 19) #define DFACTOR (5 << 22) NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(GXcopy) | NPORT_DMODE1_BENAB | SFACTOR | DFACTOR ); #undef SFACTOR #undef DFACTOR NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(0xFFFFFFFF)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_CHOST | NPORT_DMODE0_AHOST | NPORT_DMODE0_DOSETUP ); return TRUE; } /******************************************************************************* *******************************************************************************/ static Bool NewportXAASetupForCPUToScreenTexture( ScrnInfoPtr pScrn, int op, CARD32 srcFormat, CARD32 dstFormat, CARD8 *texPtr, int texPitch, int width, int height, int flags) { unsigned int *pSrc, *pDst; unsigned int w; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (width * height * sizeof(unsigned int) > pNewport->uTextureSize) { free(pNewport->pTexture); pNewport->pTexture = xnfalloc(pNewport->uTextureSize = width * height * sizeof(unsigned int)); } pNewport->uTextureWidth = width; pNewport->uTextureHeight = height; pNewport->uTextureFlags = flags; /* copy texture */ pDst = pNewport->pTexture; if (srcFormat == PICT_a8r8g8b8) { while (height--) { pSrc = (unsigned int *)texPtr; for (w = width; w; w--) { unsigned int v; v = *pSrc++; *pDst++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16); } texPtr += texPitch; } } else if (srcFormat == PICT_a8b8g8r8) { while (height--) { pSrc = (unsigned int *)texPtr; for (w = width; w; w--) *pDst++ = *pSrc++; texPtr += texPitch; } } else { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown texture format\n"); } #define SFACTOR (4 << 19) #define DFACTOR (5 << 22) NewportUpdateDRAWMODE1(pNewport, pNewport->setup_drawmode1 | Rop2LogicOp(GXcopy) | NPORT_DMODE1_BENAB | SFACTOR | DFACTOR ); #undef SFACTOR #undef DFACTOR NewportUpdateWRMASK(pNewport, pNewport->Color2Planes(0xFFFFFFFF)); pNewport->skipleft = 0; NewportUpdateClipping(pNewport); NewportUpdateDRAWMODE0(pNewport, 0 | NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_CHOST | NPORT_DMODE0_AHOST | NPORT_DMODE0_DOSETUP ); return TRUE; } /******************************************************************************* *******************************************************************************/ static void NewportRenderTexture1to1(NewportPtr pNewport, int srcx, int srcy, int w, int h) { unsigned int *p; unsigned int add, d; NewportRegsPtr pNewportRegs; pNewportRegs = pNewport->pNewportRegs; p = pNewport->pTexture + srcx + (srcy * pNewport->uTextureWidth); add = pNewport->uTextureWidth - w + srcx; while (h--) { for (d = w; d; d--) { NewportWaitGFIFO(pNewport, 1); /* hopefully we cannot write faster than XL24 can blend */ pNewportRegs->go.hostrw0 = *p++; } p += add; } } /******************************************************************************* *******************************************************************************/ static void NewportRenderTextureScale(NewportPtr pNewport, int srcx, int srcy, int w, int h) { int d; int dx, dy; int curx, cury; unsigned int *pLine; int l, p; NewportRegsPtr pNewportRegs; pNewportRegs = pNewport->pNewportRegs; dx = ((pNewport->uTextureWidth - srcx) << 16) / w; dy = ((pNewport->uTextureHeight - srcy) << 16) / h; cury = srcy << 16; while (h--) { l = (cury + 0x7FFF) >> 16; if (l >= pNewport->uTextureHeight) l = pNewport->uTextureHeight-1; pLine = pNewport->pTexture + l * pNewport->uTextureWidth; curx = srcx << 16; for (d = w; d; d--) { p = (curx + 0x7FFF) >> 16; if (p >= pNewport->uTextureWidth) p = pNewport->uTextureWidth-1; /* TODO: does this need a FIFO check? */ NewportWaitGFIFO(pNewport, 1); pNewportRegs->go.hostrw0 = pLine[p]; curx += dx; } cury += dy; } } /******************************************************************************* *******************************************************************************/ static void NewportRenderTextureRepeat(NewportPtr pNewport, int srcx, int srcy, int w, int h) { int d; unsigned int *pLine; NewportRegsPtr pNewportRegs; pNewportRegs = pNewport->pNewportRegs; srcx %= pNewport->uTextureWidth; srcy %= pNewport->uTextureHeight; while (h--) { pLine = pNewport->pTexture + pNewport->uTextureWidth * srcy; for (d = w; d; d--) { NewportWaitGFIFO(pNewport, 1); pNewportRegs->go.hostrw0 = pLine[srcx]; srcx++; if (srcx >= pNewport->uTextureWidth) srcx = 0; } srcy++; if (srcy >= pNewport->uTextureHeight) srcy = 0; } } /******************************************************************************* *******************************************************************************/ static void NewportXAASubsequentCPUToScreenTexture( ScrnInfoPtr pScrn, int x, int y, int srcx, int srcy, int w, int h) { int ex, ey; NewportRegsPtr pNewportRegs; NewportPtr pNewport; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); if (w == 0) w = 1; if (h == 0) h = 1; ex = x + w - 1; ey = y + h - 1; NewportWaitGFIFO(pNewport, 3); pNewportRegs->set.xystarti = ((x & 0xFFFF) << 16) | (y & 0xFFFF); pNewportRegs->set.xyendi = ((ex & 0xFFFF) << 16) | (ey & 0xFFFF); pNewportRegs->set._setup = 1; NewportWaitIdle(pNewport, NEWPORT_GFIFO_ENTRIES); if (srcx + w == pNewport->uTextureWidth && srcy + h == pNewport->uTextureHeight) NewportRenderTexture1to1(pNewport, srcx, srcy, w, h); else if (pNewport->uTextureFlags & XAA_RENDER_REPEAT) NewportRenderTextureRepeat(pNewport, srcx, srcy, w, h); else NewportRenderTextureScale(pNewport, srcx, srcy, w, h); NewportWaitIdle(pNewport, NEWPORT_GFIFO_ENTRIES); } CARD32 NewportAlphaTextureFormats[2] = {PICT_a8, 0}; CARD32 NewportTextureFormats[3] = {PICT_a8r8g8b8, PICT_a8b8g8r8, 0}; /*CARD32 NewportTextureFormats[2] = {PICT_a8r8g8b8, 0};*/ CARD32 NewportDstFormats[7] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_x8r8g8b8, PICT_x8b8g8r8, PICT_r8g8b8, PICT_b8g8r8, 0}; #endif /******************************************************************************* *******************************************************************************/ Bool NewportXAAScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn; NewportPtr pNewport; NewportRegsPtr pNewportRegs; XAAInfoRecPtr pXAAInfoRec; /* First get a pointer to our private info */ pScrn = xf86Screens[pScreen->myNum]; pNewport = NEWPORTPTR(pScrn); pNewportRegs = NEWPORTREGSPTR(pScrn); pXAAInfoRec = pNewport->pXAAInfoRec = XAACreateInfoRec(); /* initialize accelerated functions */ pXAAInfoRec->Sync = NewportXAASync; pXAAInfoRec->Flags = 0 /*| LINEAR_FRAMEBUFFER*/ ; /* screen to screen copy */ pXAAInfoRec->ScreenToScreenCopyFlags = 0 | NO_TRANSPARENCY ; pXAAInfoRec->SetupForScreenToScreenCopy = NewportXAASetupForScreenToScreenCopy; pXAAInfoRec->SubsequentScreenToScreenCopy = NewportXAASubsequentScreenToScreenCopy; /* solid fills */ pXAAInfoRec->SolidFillFlags = 0 ; pXAAInfoRec->SetupForSolidFill = NewportXAASetupForSolidFill; pXAAInfoRec->SubsequentSolidFillRect = NewportXAASubsequentSolidFillRect; /* solid lines */ pXAAInfoRec->SolidLineFlags = 0 ; pXAAInfoRec->SetupForSolidLine = NewportXAASetupForSolidLine; pXAAInfoRec->SubsequentSolidTwoPointLine = NewportXAASubsequentSolidTwoPointLine; /* dashed lines */ pXAAInfoRec->DashedLineFlags = 0 | LINE_PATTERN_MSBFIRST_MSBJUSTIFIED ; pXAAInfoRec->DashPatternMaxLength = 2048; pXAAInfoRec->SetupForDashedLine = NewportXAASetupForDashedLine; pXAAInfoRec->SubsequentDashedTwoPointLine = NewportXAASubsequentDashedTwoPointLine; /* cpu to screen expand color fill */ pXAAInfoRec->CPUToScreenColorExpandFillFlags = 0 | BIT_ORDER_IN_BYTE_LSBFIRST | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_DWORD | CPU_TRANSFER_BASE_FIXED | LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X /*| SYNC_AFTER_COLOR_EXPAND*/ ; pXAAInfoRec->SetupForCPUToScreenColorExpandFill = NewportXAASetupForCPUToScreenColorExpandFill; pXAAInfoRec->SubsequentCPUToScreenColorExpandFill = NewportXAASubsequentCPUToScreenColorExpandFill; pXAAInfoRec->ColorExpandRange = 4; /* * TODO: is this OK? There's no FIFO check here, is it possible * that we'd fill the GFIFO and bus error? */ pXAAInfoRec->ColorExpandBase = (unsigned char *)&(pNewportRegs->go.zpattern); /* mono 8x8 pattern fill */ pXAAInfoRec->Mono8x8PatternFillFlags = 0 | BIT_ORDER_IN_BYTE_LSBFIRST | HARDWARE_PATTERN_PROGRAMMED_BITS #ifdef NEWPORT_PREROTATE | HARDWARE_PATTERN_PROGRAMMED_ORIGIN #endif ; pXAAInfoRec->SetupForMono8x8PatternFill = NewportXAASetupForMono8x8PatternFill; pXAAInfoRec->SubsequentMono8x8PatternFillRect = NewportXAASubsequentMono8x8PatternFillRect; /* Image write */ pXAAInfoRec->ImageWriteFlags = 0 | NO_TRANSPARENCY | CPU_TRANSFER_BASE_FIXED | CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD | LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X /*| SYNC_AFTER_IMAGE_WRITE*/ ; pXAAInfoRec->SetupForImageWrite = NewportXAASetupForImageWrite; pXAAInfoRec->SubsequentImageWriteRect = NewportXAASubsequentImageWriteRect; pXAAInfoRec->ImageWriteRange = 4; /* * TODO: is this OK? There's no FIFO check here, is it possible * that we'd fill the GFIFO and bus error? */ pXAAInfoRec->ImageWriteBase = (unsigned char *)&(pNewportRegs->go.hostrw0); /* read pixmap */ pXAAInfoRec->ReadPixmapFlags = 0 | CPU_TRANSFER_PAD_DWORD ; pXAAInfoRec->ReadPixmap = NewportXAAReadPixmap; /* clipping */ pXAAInfoRec->ClippingFlags = 0 /*| HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND*/ | HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | HARDWARE_CLIP_MONO_8x8_FILL /*| HARDWARE_CLIP_COLOR_8x8_FILL*/ | HARDWARE_CLIP_SOLID_FILL | HARDWARE_CLIP_DASHED_LINE | HARDWARE_CLIP_SOLID_LINE ; pXAAInfoRec->SetClippingRectangle = NewportXAASetClippingRectangle; pXAAInfoRec->DisableClipping = NewportXAADisableClipping; /* make it draw points using our function */ pXAAInfoRec->ValidatePolyPoint = NewportValidatePolyPoint; pXAAInfoRec->PolyPointMask = GCFunction | GCPlaneMask; /*pXAAInfoRec->PolyPointMask = 0xFFFFFFFF;*/ pXAAInfoRec->ValidatePolyArc = NewportValidatePolyArc; pXAAInfoRec->PolyArcMask = GCFunction | GCLineWidth; /* * TODO: Revisit this once the rest of the driver is converted to * properly separate the newport device type / bitplane count versus * the screen depth. * * We're not doing alpha blending on 8bpp screens because * they're psuedo colour screens, but we CAN do alpha blending * on an XL8 that's being fed RGB-24 and RGBA-32 pixel data * via HOSTRW. */ #ifdef RENDER if (pScrn->bitsPerPixel > 8) { pXAAInfoRec->CPUToScreenTextureFlags = 0 ; pXAAInfoRec->CPUToScreenTextureFormats = NewportTextureFormats; pXAAInfoRec->CPUToScreenTextureDstFormats = NewportDstFormats; pXAAInfoRec->SetupForCPUToScreenTexture2 = NewportXAASetupForCPUToScreenTexture; pXAAInfoRec->SubsequentCPUToScreenTexture = NewportXAASubsequentCPUToScreenTexture; pXAAInfoRec->CPUToScreenAlphaTextureFlags = 0 ; pXAAInfoRec->CPUToScreenAlphaTextureFormats = NewportAlphaTextureFormats; pXAAInfoRec->CPUToScreenAlphaTextureDstFormats = NewportDstFormats; pXAAInfoRec->SetupForCPUToScreenAlphaTexture2 = NewportXAASetupForCPUToScreenAlphaTexture; pXAAInfoRec->SubsequentCPUToScreenAlphaTexture = NewportXAASubsequentCPUToScreenTexture; /* this is the same for both */ pNewport->pTexture = (unsigned int *)xnfalloc(pNewport->uTextureSize = 16*16*sizeof(unsigned int)); } #endif /* * Configure acceleration based on the screen config and the * Newport bitplane config. * * The WRMASK register (which this routine is populating) is * based on the raw framebuffer pixel data being written, * /not/ specifically the HOSTRW format being written. * The HOSTRW format can include whether the pixel values * are packed or not; whereas this field is the raw field * in the table. * * See REX3 specification section 3.3 (Clipping and Masking) * and 3.9 (Framebuffer formats) for more information. * * TODO: this needs to be revisited when configuring other * framebuffer pixel layouts, eg 24 bit colour writes * into HOSTRW, but a RGB-332 framebuffer. * * In this instance, we'd choose a function based on * pixel config (eg RGB888, RGB444, RGB332, CI) and * eventually also the double buffering target plane. */ pNewport->Color2Planes = NewportColor2Planes24RGB; /* * TODO: this is looking at the screen bpp, it should be changed * to look at the DRAWDEPTH/PLANES/RWPACKED field and choose * appropriately. */ if (pScrn->bitsPerPixel == 8) { pNewport->Color2Planes = NewportColor2Planes8CI; } if (!XAAInit(pScreen, pXAAInfoRec)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Failed!\n"); return FALSE; } pNewport->fifoleft = 0; /* init bunch of registers */ pNewport->shadow_drawmode0 = pNewportRegs->set.drawmode0; pNewport->shadow_colori = pNewportRegs->set.colori; pNewport->shadow_smask0x = pNewportRegs->set.smask0x; pNewport->shadow_smask0y = pNewportRegs->set.smask0y; pNewport->shadow_drawmode1 = pNewport->drawmode1; pNewportRegs->set.drawmode1 = pNewport->drawmode1; pNewport->setup_drawmode1 = pNewport->drawmode1 & ~NPORT_DMODE1_LOMASK; pNewport->shadow_xymove = 0; pNewportRegs->set.xymove = 0; pNewport->shadow_wrmask = 0xFFFFFF; pNewportRegs->set.wrmask = 0xFFFFFF; pNewport->shadow_colorvram = 0; pNewportRegs->set.colorvram = 0; pNewport->shadow_colorback = 0; pNewportRegs->set.colorback = 0; pNewport->clipsx = 0; pNewport->clipex = pScrn->virtualX-1; pNewport->clipsy = 0; pNewport->clipey = pScrn->virtualY-1; pNewport->skipleft = 0; BARF1("CLIPMODE %08X\n", pNewportRegs->cset.clipmode); BARF1("XYWIN %08X\n", pNewportRegs->cset.xywin); BARF1("CONFIG %08X\n", pNewportRegs->cset.config); BARF1("SMASK0X %08X\n", pNewportRegs->set.smask0x); BARF1("SMASK0Y %08X\n", pNewportRegs->set.smask0y); /* set GIO bus timeout to highest possible value 4.32us this will allow for longer bus stalls without bus error */ { unsigned int conf; conf = pNewportRegs->cset.config; conf &= ~NPORT_CFG_TOMSK; conf |= NPORT_CFG_TOMSK; conf &= ~NPORT_CFG_GDMSK; conf |= NPORT_CFG_GDMSK; pNewportRegs->cset.config = conf; } BARF1("CONFIG %08X\n", pNewportRegs->cset.config); pNewport->shadow_clipmode = pNewportRegs->cset.clipmode; pNewportRegs->cset.clipmode |= 1; /* enable clipping mask 0 */ NewportUpdateClipping(pNewport); return TRUE; } #endif /* NEWPORT_ACCEL */