diff options
Diffstat (limited to 'src/apm_funcs.c')
-rw-r--r-- | src/apm_funcs.c | 1558 |
1 files changed, 1558 insertions, 0 deletions
diff --git a/src/apm_funcs.c b/src/apm_funcs.c new file mode 100644 index 0000000..71f0fe8 --- /dev/null +++ b/src/apm_funcs.c @@ -0,0 +1,1558 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_funcs.c,v 1.17 2002/05/07 12:53:49 alanh Exp $ */ + +#define FASTER +#ifndef PSZ +#define PSZ 8 +#endif +#ifdef IOP_ACCESS +# define APM_SUFF_IOP "_IOP" +# undef RDXB +# undef RDXW +# undef RDXL +# undef WRXB +# undef WRXW +# undef WRXL +# undef ApmWriteSeq +# define RDXB RDXB_IOP +# define RDXW RDXW_IOP +# define RDXL RDXL_IOP +# define WRXB WRXB_IOP +# define WRXW WRXW_IOP +# define WRXL WRXL_IOP +# define ApmWriteSeq(i, v) wrinx(pApm->xport, i, v) +#else +# define APM_SUFF_IOP "" +#endif +#if PSZ == 24 +# define APM_SUFF_24 "24" +# ifdef IOP_ACCESS +# define A(s) Apm##s##24##_IOP +# else +# define A(s) Apm##s##24 +# endif +#else +# define APM_SUFF_24 "" +# ifdef IOP_ACCESS +# define A(s) Apm##s##_IOP +# else +# define A(s) Apm##s +# endif +#endif +#define DPRINTNAME(s) do { xf86DrvMsgVerb(pScrn->pScreen->myNum, X_NOTICE, 4, "Apm" #s APM_SUFF_24 APM_SUFF_IOP "\n"); } while (0) + +#if PSZ == 24 +#undef SETSOURCEXY +#undef SETDESTXY +#undef SETWIDTH +#undef SETWIDTHHEIGHT +#undef UPDATEDEST +#define SETSOURCEXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1) +#define SETDESTXY(x,y) do { int off = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0x3FFF)) * 3); SETDESTOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); break;} while(1) +#define SETWIDTH(w) WRXW(0x58, ((w) & 0x3FFF) * 3) +#define SETWIDTHHEIGHT(w,h) WRXL(0x58, ((h) << 16) | (((w) & 0x3FFF) * 3)) +#define UPDATEDEST(x,y) (void)(curr32[0x54 / 4] = ((((y) & 0xFFFF) * pApm->CurrentLayout.displayWidth + ((x) & 0xFFFF)) * 3)) +#endif + +/* Defines */ +#define MAXLOOP 1000000 + + +/* Local functions */ +static void A(Sync)(ScrnInfoPtr pScrn); +static void A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); +static void A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, + int w, int h); +static void A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int transparency_color); +static void A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h); +#if PSZ != 24 +static void A(Sync6422)(ScrnInfoPtr pScrn); +static void A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask); +static void A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask); +static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask); +static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, + int paty, int x, int y, + int w, int h); +#if 0 +static void A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int bg, int fg, int rop, unsigned int planemask); +static void A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft); +#endif +static void A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int trans_color, + int bpp, int depth); +static void A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, + int w, int h, int skipleft); +static void A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, + int srcx, int srcy, + int offset); +static void A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length); +static void A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int octant, int err, int e1, int e2, int length); +static void A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2); +static void A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int trans, int bpp, + int depth); +static void A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int nBox, BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix); +static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty, + int rop, unsigned int planemask, + int transparency_color); +static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, + int paty, int x, int y, + int w, int h); +#endif + +/* Inline functions */ +static __inline__ void +A(WaitForFifo)(ApmPtr pApm, int slots) +{ + if (!pApm->UsePCIRetry) { + volatile int i; + + for(i = 0; i < MAXLOOP; i++) { + if ((STATUS() & STATUS_FIFO) >= slots) + break; + } + if (i == MAXLOOP) { + unsigned int status = STATUS(); + + WRXB(0x1FF, 0); + if (!xf86ServerIsExiting()) + FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status); + } + } +} + + +static void +A(SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForSolidFill); +#ifdef FASTER + A(WaitForFifo)(pApm, 3 + pApm->apmClip); + SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER | + pApm->CurrentLayout.Setup_DEC); +#else + A(WaitForFifo)(pApm, 2 + pApm->apmClip); +#endif +#if PSZ == 2 + pApm->color = ((color & 0xFF0000) << 8) | ((color & 0xFF0000) >> 16) | + ((color & 0xFF00) << 8) | ((color & 0xFF) << 16); +#else + SETFOREGROUNDCOLOR(color); +#endif + + if (pApm->apmClip) { + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } + + SETROP(apmROP[rop]); +} + +static void +A(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + APMDECL(pScrn); + + DPRINTNAME(SubsequentSolidFillRect); +#if PSZ == 24 +# ifndef FASTER + A(WaitForFifo)(pApm, 5); +# else + A(WaitForFifo)(pApm, 4); +# endif + SETOFFSET(3*(pApm->CurrentLayout.displayWidth - w)); +#if 0 + switch ((((y * pApm->CurrentLayout.displayWidth + x)* 3) / 8) % 3) { + case 0: + SETFOREGROUNDCOLOR(pApm->color); + break; + case 1: + SETFOREGROUNDCOLOR((pApm->color << 8) | (pApm->color >> 16)); + break; + case 2: + SETFOREGROUNDCOLOR(pApm->color >> 8); + break; + } +#endif +#else +# ifndef FASTER + A(WaitForFifo)(pApm, 3); +# else + A(WaitForFifo)(pApm, 2); +# endif +#endif + SETDESTXY(x, y); + SETWIDTHHEIGHT(w, h); + UPDATEDEST(x + w + 1, y); +#ifndef FASTER + SETDEC(DEC_START | DEC_OP_RECT | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC); +#endif +} + +static void +A(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + unsigned char tmp; + + APMDECL(pScrn); + + DPRINTNAME(SetupForScreenToScreenCopy); + + if (pApm->apmLock) { + /* + * This is just an attempt, because Daryll is tampering with MY registers. + */ + tmp = (RDXB(0xDB) & 0xF4) | 0x0A; + WRXB(0xDB, tmp); + ApmWriteSeq(0x1B, 0x20); + ApmWriteSeq(0x1C, 0x2F); + pApm->apmLock = FALSE; + } + + pApm->blitxdir = xdir; + pApm->blitydir = ydir; + + pApm->apmTransparency = (transparency_color != -1); + +#ifdef FASTER + A(WaitForFifo)(pApm, 2 + (transparency_color != -1)); + SETDEC(DEC_QUICKSTART_ONDIMX | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | + (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | pApm->CurrentLayout.Setup_DEC | + ((xdir < 0) ? DEC_DIR_X_NEG : DEC_DIR_X_POS) | + ((ydir < 0) ? DEC_DIR_Y_NEG : DEC_DIR_Y_POS)); +#else + A(WaitForFifo)(pApm, 1 + (transparency_color != -1)); +#endif + + if (transparency_color != -1) + SETBACKGROUNDCOLOR(transparency_color); + + SETROP(apmROP[rop]); +} + +static void +A(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + APMDECL(pScrn); +#ifndef FASTER + u32 c = pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0; +#endif + u32 sx, dx, sy, dy; + int i = y1 / pApm->CurrentLayout.Scanlines; + + DPRINTNAME(SubsequentScreenToScreenCopy); + if (i && pApm->pixelStride) { +#ifdef FASTER + A(WaitForFifo)(pApm, 1); + SETDEC(curr32[0x40 / 4] | (DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR)); +#else + c |= DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG; +#endif + pApm->apmClip = TRUE; + A(WaitForFifo)(pApm, 3); + SETCLIP_LEFTTOP(x2, y2); + SETCLIP_RIGHTBOT(x2 + w - 1, y2 + h - 1); + SETCLIP_CTRL(1); + w = (pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel; + } + else { +#ifdef FASTER + A(WaitForFifo)(pApm, 1 + pApm->apmClip); + SETDEC(curr32[0x40 / 4] & ~(DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR)); + if (pApm->apmClip) + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; +#else + if (pApm->apmClip) { + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } +#endif + } + if (i) { + if (pApm->pixelStride) { + x1 += (((y1 % pApm->CurrentLayout.Scanlines) - pApm->RushY[i - 1]) * pApm->pixelStride * 8) / pApm->CurrentLayout.bitsPerPixel; + y1 = pApm->RushY[i - 1]; + } + else + y1 -= i * pApm->CurrentLayout.Scanlines; + } + if (pApm->blitxdir < 0) + { +#ifndef FASTER + c |= DEC_DIR_X_NEG; +#endif + sx = x1+w-1; + dx = x2+w-1; + } + else + { +#ifndef FASTER + c |= DEC_DIR_X_POS; +#endif + sx = x1; + dx = x2; + } + + if (pApm->blitydir < 0) + { +#ifndef FASTER + c |= DEC_DIR_Y_NEG | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | + pApm->CurrentLayout.Setup_DEC; +#endif + sy = y1+h-1; + dy = y2+h-1; + } + else + { +#ifndef FASTER + c |= DEC_DIR_Y_POS | DEC_START | DEC_OP_BLT | DEC_DEST_UPD_TRCORNER | + pApm->CurrentLayout.Setup_DEC; +#endif + sy = y1; + dy = y2; + } + +#if PSZ == 24 +# ifndef FASTER + A(WaitForFifo)(pApm, 5); +# else + A(WaitForFifo)(pApm, 4); +# endif + if (pApm->blitxdir == pApm->blitydir) + SETOFFSET(3 * (pApm->CurrentLayout.displayWidth - w)); + else + SETOFFSET(3 * (pApm->CurrentLayout.displayWidth + w)); +#else +# ifndef FASTER + A(WaitForFifo)(pApm, 4); +# else + A(WaitForFifo)(pApm, 3); +# endif +#endif + + if (i && pApm->pixelStride) { + register unsigned int off = sx + sy * pApm->CurrentLayout.displayWidth; + + SETSOURCEOFF(((off & 0xFFF000) << 4) | (off & 0xFFF)); + } + else + SETSOURCEXY(sx,sy); + SETDESTXY(dx,dy); + SETWIDTHHEIGHT(w,h); + UPDATEDEST(dx + (w + 1)*pApm->blitxdir, dy); + +#ifndef FASTER + SETDEC(c); +#endif + if (i) A(Sync)(pScrn); /* Only for AT3D */ +} + + +#if PSZ != 24 +static void +A(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForScreenToScreenColorExpandFill); + A(WaitForFifo)(pApm, 3 + pApm->apmClip); + if (bg == -1) + { + SETFOREGROUNDCOLOR(fg); + SETBACKGROUNDCOLOR(fg+1); + pApm->apmTransparency = TRUE; + } + else + { + SETFOREGROUNDCOLOR(fg); + SETBACKGROUNDCOLOR(bg); + pApm->apmTransparency = FALSE; + } + + SETROP(apmROP[rop]); +} + +static void +A(WriteBitmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask) +{ + APMDECL(pScrn); + Bool beCareful, apmClip = FALSE; + int wc, n, nc, wr, wrd; + CARD32 *dstPtr; +#ifndef FASTER + int c; +#endif + + DPRINTNAME(WriteBitmap); + + if (w <= 0 && h <= 0) + return; + + /* + * The function is a bit long, but the spirit is simple : put the monochrome + * data in scratch memory and color-expand it using the + * ScreenToScreenColorExpand techniques. + */ + + w += skipleft; + x -= skipleft; + wc = pApm->ScratchMemSize * 8; + wrd = (w + 31) >> 5; + wr = wrd << 5; + nc = wc / wr; + if (nc > h) + nc = h; + if (wr / 8 > srcwidth) + beCareful = TRUE; + else + beCareful = FALSE; + srcwidth -= wr / 8; + + if (skipleft || w != wr) { + apmClip = TRUE; + A(WaitForFifo)(pApm, 3); + SETCLIP_LEFTTOP(x + skipleft, y); + SETCLIP_RIGHTBOT(x + w - 1, y + h - 1); + SETCLIP_CTRL(1); + } + else if (pApm->apmClip) { + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0); + } + pApm->apmClip = FALSE; + + A(SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); +#ifdef FASTER + A(WaitForFifo)(pApm, 2); + if (pApm->apmTransparency) + SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | + DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | + DEC_SOURCE_CONTIG | DEC_SOURCE_TRANSPARENCY | pApm->CurrentLayout.Setup_DEC); + else + SETDEC(DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | + DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | + DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC); +#else + A(WaitForFifo)(pApm, 1); + c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | + DEC_START | DEC_DEST_UPD_BLCORNER | DEC_SOURCE_LINEAR | + DEC_SOURCE_CONTIG | pApm->CurrentLayout.Setup_DEC; + if (pApm->apmTransparency) + c |= DEC_SOURCE_TRANSPARENCY; +#endif + + SETDESTXY(x, y); + + if (!beCareful || h % nc > 3 || (w > 16 && h % nc)) { +#ifndef FASTER + if (h / nc) + SETWIDTHHEIGHT(wr, nc); +#endif + for (n = h / nc; n-- > 0; ) { + int i, j; + + if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) { +#define d ((memType)dstPtr - (memType)pApm->FbBase) + A(WaitForFifo)(pApm, 1); + dstPtr = (CARD32 *)pApm->ScratchMemPtr; + switch(pApm->CurrentLayout.bitsPerPixel) { + case 8: case 24: + SETSOURCEOFF((d & 0xFFF000) << 4 | + (d & 0xFFF)); + break; + case 16: + SETSOURCEOFF((d & 0xFFE000) << 3 | + ((d & 0x1FFE) >> 1)); + break; + case 32: + SETSOURCEOFF((d & 0xFFC000) << 2 | + ((d & 0x3FFC) >> 2)); + break; + } +#undef d + } + else { + (*pApm->AccelInfoRec->Sync)(pScrn); + dstPtr = (CARD32 *)pApm->ScratchMemOffset; + SETSOURCEOFF(pApm->ScratchMem); + } + pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc) + 4) + & ~(memType)7; + for (i = nc; i-- > 0; ) { + for (j = wrd; j-- > 0; ) { + *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); + src += 4; + } + src += srcwidth; + } + A(WaitForFifo)(pApm, 1); +#ifdef FASTER + SETWIDTHHEIGHT(wr, nc); +#else + SETDEC(c); +#endif + } + } + else { +#ifndef FASTER + if (h / nc) + SETWIDTHHEIGHT(wr, nc); +#endif + for (n = h / nc; n-- > 0; ) { + int i, j; + + if (pApm->ScratchMemPtr + nc * wrd * 4 < pApm->ScratchMemEnd) { +#define d ((memType)dstPtr - (memType)pApm->FbBase) + A(WaitForFifo)(pApm, 1); + dstPtr = (CARD32 *)pApm->ScratchMemPtr; + switch(pApm->CurrentLayout.bitsPerPixel) { + case 8: case 24: + SETSOURCEOFF((d & 0xFFF000) << 4 | + (d & 0xFFF)); + break; + case 16: + SETSOURCEOFF((d & 0xFFE000) << 3 | + ((d & 0x1FFE) >> 1)); + break; + case 32: + SETSOURCEOFF((d & 0xFFC000) << 2 | + ((d & 0x3FFC) >> 2)); + break; + } +#undef d + } + else { + (*pApm->AccelInfoRec->Sync)(pScrn); + dstPtr = (CARD32 *)pApm->ScratchMemOffset; + SETSOURCEOFF(pApm->ScratchMem); + } + pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * nc * 4) + 4) & ~7; + for (i = nc; i-- > 0; ) { + for (j = wrd; j-- > 0; ) { + if (i || j || n) + *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); + else if (srcwidth > -8) { + ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]]; + ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]]; + ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]]; + dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr); + } + else if (srcwidth > -16) { + ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]]; + ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]]; + dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr); + } + else { + *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src]; + dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr); + } + src += 4; + } + src += srcwidth; + } + A(WaitForFifo)(pApm, 1); +#ifdef FASTER + SETWIDTHHEIGHT(wr, nc); +#else + SETDEC(c); +#endif + } + } + + /* + * Same thing for the remnant + */ + UPDATEDEST(x, y + h + 1); + h %= nc; + if (h) { + if (!beCareful) { + int i, j; + +#ifndef FASTER + SETWIDTHHEIGHT(wr, h); +#endif + if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) { +#define d ((memType)dstPtr - (memType)pApm->FbBase) + A(WaitForFifo)(pApm, 1); + dstPtr = (CARD32 *)pApm->ScratchMemPtr; + switch(pApm->CurrentLayout.bitsPerPixel) { + case 8: case 24: + SETSOURCEOFF((d & 0xFFF000) << 4 | + (d & 0xFFF)); + break; + case 16: + SETSOURCEOFF((d & 0xFFE000) << 3 | + ((d & 0x1FFE) >> 1)); + break; + case 32: + SETSOURCEOFF((d & 0xFFC000) << 2 | + ((d & 0x3FFC) >> 2)); + break; + } +#undef d + } + else { + (*pApm->AccelInfoRec->Sync)(pScrn); + dstPtr = (CARD32 *)pApm->ScratchMemOffset; + SETSOURCEOFF(pApm->ScratchMem); + } + pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7; + for (i = h; i-- > 0; ) { + for (j = wrd; j-- > 0; ) { + *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); + src += 4; + } + src += srcwidth; + } + A(WaitForFifo)(pApm, 1); +#ifdef FASTER + SETWIDTHHEIGHT(wr, h); +#else + SETDEC(c); +#endif + } + else { + int i, j; + +#ifndef FASTER + SETWIDTHHEIGHT(w, h); +#endif + if (pApm->ScratchMemPtr + h * wrd * 4 < pApm->ScratchMemEnd) { +#define d ((memType)dstPtr - (memType)pApm->FbBase) + A(WaitForFifo)(pApm, 1); + dstPtr = (CARD32 *)pApm->ScratchMemPtr; + switch(pApm->CurrentLayout.bitsPerPixel) { + case 8: case 24: + SETSOURCEOFF((d & 0xFFF000) << 4 | + (d & 0xFFF)); + break; + case 16: + SETSOURCEOFF((d & 0xFFE000) << 3 | + ((d & 0x1FFE) >> 1)); + break; + case 32: + SETSOURCEOFF((d & 0xFFC000) << 2 | + ((d & 0x3FFC) >> 2)); + break; + } +#undef d + } + else { + (*pApm->AccelInfoRec->Sync)(pScrn); + dstPtr = (CARD32 *)pApm->ScratchMemOffset; + SETSOURCEOFF(pApm->ScratchMem); + } + pApm->ScratchMemPtr = ((memType)(dstPtr + wrd * h) + 4) & ~7; + for (i = h; i-- > 0; ) { + for (j = wrd; j-- > 0; ) { + if (i || j) + *dstPtr++ = XAAReverseBitOrder(*(CARD32 *)src); + else if (srcwidth > -8) { + ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[2]]; + ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[1]]; + ((CARD8 *)dstPtr)[2] = byte_reversed[((CARD8 *)src)[0]]; + dstPtr = (CARD32 *)(3 + (CARD8 *)dstPtr); + } + else if (srcwidth > -16) { + ((CARD8 *)dstPtr)[0] = byte_reversed[((CARD8 *)src)[1]]; + ((CARD8 *)dstPtr)[1] = byte_reversed[((CARD8 *)src)[0]]; + dstPtr = (CARD32 *)(2 + (CARD8 *)dstPtr); + } + else { + *(CARD8 *)dstPtr = byte_reversed[*(CARD8 *)src]; + dstPtr = (CARD32 *)(1 + (CARD8 *)dstPtr); + } + src += 4; + } + src += srcwidth; + } + A(WaitForFifo)(pApm, 1); +#ifdef FASTER + SETWIDTHHEIGHT(w, h); +#else + SETDEC(c); +#endif + } + } + pApm->apmClip = apmClip; +} + +static void +A(TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask) +{ + CARD32 *base, *base0; + GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; + int w2, h2, dwords; + + w2 = w + skipleft; + h2 = h; + dwords = (w2 + 31) >> 5; + dwords <<= 2; + + base0 = base = (CARD32*)xalloc(dwords * h); + if (!base) + return; /* Should not happen : it's rather small... */ + + while(h--) { + base = (*GlyphFunc)(base, glyphs, startline++, w2, glyphWidth); + } + + A(WriteBitmap)(pScrn, x, y, w, h2, (unsigned char *)base0, dwords, + skipleft, fg, bg, rop, planemask); + + xfree(base0); +} + +static void A(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForMono8x8PatternFill); + pApm->apmTransparency = (pApm->Chipset >= AT3D) && (bg == -1); + pApm->Bg8x8 = bg; + pApm->Fg8x8 = fg; + pApm->rop = apmROP[rop]; + A(WaitForFifo)(pApm, 3 + pApm->apmClip); + if (bg == -1) + SETBACKGROUNDCOLOR(fg + 1); + else + SETBACKGROUNDCOLOR(bg); + SETFOREGROUNDCOLOR(fg); + if (pApm->Chipset >= AT3D) + SETROP(apmROP[rop] & 0xF0); + else + SETROP((apmROP[rop] & 0xF0) | 0x0A); + if (pApm->apmClip) { + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } +} + +static void A(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, + int paty, int x, int y, + int w, int h) +{ + APMDECL(pScrn); + + DPRINTNAME(SubsequentMono8x8PatternFillRect); + SETDESTXY(x, y); + UPDATEDEST(x, y + h + 1); + A(WaitForFifo)(pApm, 6); + if (pApm->Chipset == AT24 && pApm->Bg8x8 != -1) { + SETROP(pApm->rop); + SETFOREGROUNDCOLOR(pApm->Bg8x8); +#ifdef FASTER + SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | + DEC_DEST_XY | DEC_QUICKSTART_ONDIMX); + SETWIDTHHEIGHT(w, h); +#else + SETWIDTHHEIGHT(w, h); + SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | + DEC_DEST_XY | DEC_START); +#endif + A(WaitForFifo)(pApm, 6); + SETROP((pApm->rop & 0xF0) | 0x0A); + SETFOREGROUNDCOLOR(pApm->Fg8x8); + } + SETPATTERN(patx, paty); +#ifdef FASTER + SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | + DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER | + (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | + DEC_QUICKSTART_ONDIMX); + SETWIDTHHEIGHT(w, h); +#else + SETWIDTHHEIGHT(w, h); + SETDEC(pApm->CurrentLayout.Setup_DEC | ((h == 1) ? DEC_OP_STRIP : DEC_OP_RECT) | + DEC_DEST_XY | DEC_PATTERN_88_1bMONO | DEC_DEST_UPD_TRCORNER | + (pApm->apmTransparency ? DEC_SOURCE_TRANSPARENCY : 0) | + DEC_START); +#endif +} + +#if 0 +static void +A(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForCPUToScreenColorExpandFill); + if (bg == -1) + { +#ifndef FASTER + pApm->apmTransparency = TRUE; + A(WaitForFifo)(pApm, 3); +#else + A(WaitForFifo)(pApm, 4); + SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_SOURCE_TRANSPARENCY | DEC_SOURCE_MONOCHROME | DEC_QUICKSTART_ONDIMX | + DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC); +#endif + SETFOREGROUNDCOLOR(fg); + SETBACKGROUNDCOLOR(fg+1); + } + else + { +#ifndef FASTER + pApm->apmTransparency = FALSE; + A(WaitForFifo)(pApm, 3); +#else + A(WaitForFifo)(pApm, 4); + SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_DEST_UPD_TRCORNER | DEC_SOURCE_MONOCHROME | + DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); +#endif + SETFOREGROUNDCOLOR(fg); + SETBACKGROUNDCOLOR(bg); + } + SETROP(apmROP[rop]); +} + +static void +A(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, + int w, int h, int skipleft) +{ + APMDECL(pScrn); +#ifndef FASTER + u32 c; +#endif + + DPRINTNAME(SubsequentCPUToScreenColorExpandFill); +#ifndef FASTER + c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_SOURCE_MONOCHROME | DEC_START | DEC_DEST_UPD_TRCORNER | + pApm->CurrentLayout.Setup_DEC; + + if (pApm->apmTransparency) + c |= DEC_SOURCE_TRANSPARENCY; + + A(WaitForFifo)(pApm, 7); +#else + A(WaitForFifo)(pApm, 6); +#endif + + SETCLIP_LEFTTOP(x+skipleft, y); + SETCLIP_RIGHTBOT(x+w-1, y+h-1); + SETCLIP_CTRL(0x01); + pApm->apmClip = TRUE; + SETSOURCEX(0); /* According to manual, it just has to be zero */ + SETDESTXY(x, y); + SETWIDTHHEIGHT((w + 31) & ~31, h); + UPDATEDEST(x + ((w + 31) & ~31), y); + +#ifndef FASTER + SETDEC(c); +#endif +} +#endif + +static void +A(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, unsigned int planemask, + int trans_color, int bpp, int depth) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForImageWrite); + if (trans_color != -1) + { +#ifndef FASTER + pApm->apmTransparency = TRUE; + A(WaitForFifo)(pApm, 3); +#else + A(WaitForFifo)(pApm, 4); + SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_SOURCE_TRANSPARENCY | DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); +#endif + SETBACKGROUNDCOLOR(trans_color); + } + else { +#ifndef FASTER + pApm->apmTransparency = FALSE; + A(WaitForFifo)(pApm, 2); +#else + A(WaitForFifo)(pApm, 3); + SETDEC(DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_QUICKSTART_ONDIMX | pApm->CurrentLayout.Setup_DEC); +#endif + } + + SETROP(apmROP[rop]); +} + +static void +A(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft) +{ + APMDECL(pScrn); +#ifndef FASTER + u32 c; +#endif + + DPRINTNAME(SubsequentImageWriteRect); +#ifndef FASTER + c = DEC_OP_HOSTBLT_HOST2SCREEN | DEC_SOURCE_LINEAR | DEC_SOURCE_CONTIG | + DEC_START | pApm->CurrentLayout.Setup_DEC; + + if (pApm->apmTransparency) + c |= DEC_SOURCE_TRANSPARENCY; + + if (pApm->Chipset >= AT24) + A(WaitForFifo)(pApm, 7); + else + A(WaitForFifo)(pApm, 3); +#else + if (pApm->Chipset >= AT24) + A(WaitForFifo)(pApm, 6); + else + A(WaitForFifo)(pApm, 3); +#endif + + SETCLIP_LEFTTOP(x+skipleft, y); + SETCLIP_RIGHTBOT(x+w-1, y+h-1); + SETCLIP_CTRL(0x01); + pApm->apmClip = TRUE; + if (pApm->Chipset < AT24) + A(WaitForFifo)(pApm, 4); + SETSOURCEX(0); /* According to manual, it just has to be zero */ + SETDESTXY(x, y); + SETWIDTHHEIGHT((w + 3) & ~3, h); + +#ifndef FASTER + SETDEC(c); +#endif +} + +static void +A(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, int x, int y, + int w, int h, int srcx, int srcy, + int offset) +{ + APMDECL(pScrn); + u32 c; + + DPRINTNAME(SubsequentScreenToScreenColorExpandFill); +#ifdef FASTER + c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | + DEC_QUICKSTART_ONDIMX | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC; +#else + c = DEC_OP_BLT | DEC_DIR_X_POS | DEC_DIR_Y_POS | DEC_SOURCE_MONOCHROME | + DEC_START | DEC_DEST_UPD_TRCORNER | pApm->CurrentLayout.Setup_DEC; +#endif + + if (pApm->apmTransparency) + c |= DEC_SOURCE_TRANSPARENCY; + + if (srcy >= pApm->CurrentLayout.Scanlines) { + struct ApmStippleCacheRec *pCache; + CARD32 dist; + + /* + * Offscreen linear stipple + */ + pCache = &pApm->apmCache[srcy / pApm->CurrentLayout.Scanlines - 1]; + if (w != pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel) { + A(WaitForFifo)(pApm, 3); + SETCLIP_LEFTTOP(x, y); + SETCLIP_RIGHTBOT(x + w - 1, y + h - 1); + SETCLIP_CTRL(0x01); + pApm->apmClip = TRUE; + w = pCache->apmStippleCache.w * pApm->CurrentLayout.bitsPerPixel; + x -= srcx - pCache->apmStippleCache.x + offset; + srcx = (srcy - pCache->apmStippleCache.y) & 7; + srcy -= srcx; + y -= srcx; + h += srcx; + srcx = pCache->apmStippleCache.x; + } + else if (pApm->apmClip) { + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0x00); + pApm->apmClip = FALSE; + } + srcx += (srcy - pCache->apmStippleCache.y) * pCache->apmStippleCache.w; + srcy = pCache->apmStippleCache.y % pApm->CurrentLayout.Scanlines; + dist = srcx + srcy * pApm->CurrentLayout.displayWidth; + srcx = dist & 0xFFF; + srcy = dist >> 12; + c |= DEC_SOURCE_CONTIG | DEC_SOURCE_LINEAR; + } + else if (offset) { + A(WaitForFifo)(pApm, 3); + SETCLIP_LEFTTOP(x, y); + SETCLIP_RIGHTBOT(x + w, y + h); + SETCLIP_CTRL(0x01); + pApm->apmClip = TRUE; + w += offset; + x -= offset; + } + else if (pApm->apmClip) { + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0x00); + pApm->apmClip = FALSE; + } + + A(WaitForFifo)(pApm, 4); + + SETSOURCEXY(srcx, srcy); + SETDESTXY(x, y); + +#ifdef FASTER + SETDEC(c); + SETWIDTHHEIGHT(w, h); +#else + SETWIDTHHEIGHT(w, h); + SETDEC(c); +#endif + UPDATEDEST(x + w + 1, h); +} + +static void +A(SubsequentSolidBresenhamLine)(ScrnInfoPtr pScrn, int x1, int y1, int e1, + int e2, int err, int length, int octant) +{ + APMDECL(pScrn); +#ifdef FASTER + u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | + pApm->CurrentLayout.Setup_DEC; +#else + u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC; +#endif + int tmp; + + DPRINTNAME(SubsequentSolidBresenhamLine); + + A(WaitForFifo)(pApm, 5); + SETDESTXY(x1,y1); + SETDDA_ERRORTERM(err); + SETDDA_ADSTEP(e1, e2); + + if (octant & YMAJOR) { + c |= DEC_MAJORAXIS_Y; + tmp = e1; e1 = e2; e2 = tmp; + } + else + c |= DEC_MAJORAXIS_X; + + if (octant & XDECREASING) { + c |= DEC_DIR_X_NEG; + e1 = -e1; + } + else + c |= DEC_DIR_X_POS; + + if (octant & YDECREASING) { + c |= DEC_DIR_Y_NEG; + e2 = -e2; + } + else + c |= DEC_DIR_Y_POS; + +#ifdef FASTER + SETDEC(c); + SETWIDTH(length); +#else + SETWIDTH(length); + SETDEC(c); +#endif + + if (octant & YMAJOR) + UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2); + else + UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2); + if (pApm->apmClip) + { + pApm->apmClip = FALSE; + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0); + } +} + +static void +A(SubsequentSolidBresenhamLine6422)(ScrnInfoPtr pScrn, int x1, int y1, int e1, + int e2, int err, int length, int octant) +{ + APMDECL(pScrn); +#ifdef FASTER + u32 c = DEC_QUICKSTART_ONDIMX | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | + pApm->CurrentLayout.Setup_DEC; +#else + u32 c = DEC_START | DEC_OP_VECT_ENDP | DEC_DEST_UPD_LASTPIX | pApm->CurrentLayout.Setup_DEC; +#endif + int tmp; + + DPRINTNAME(SubsequentSolidBresenhamLine6422); + + A(WaitForFifo)(pApm, 1); + SETDESTXY(x1,y1); + A(WaitForFifo)(pApm, 4); + SETDDA_ERRORTERM(err); + SETDDA_ADSTEP(e1, e2); + + if (octant & YMAJOR) { + c |= DEC_MAJORAXIS_Y; + tmp = e1; e1 = e2; e2 = tmp; + } + else + c |= DEC_MAJORAXIS_X; + + if (octant & XDECREASING) { + c |= DEC_DIR_X_NEG; + e1 = -e1; + } + else + c |= DEC_DIR_X_POS; + + if (octant & YDECREASING) { + c |= DEC_DIR_Y_NEG; + e2 = -e2; + } + else + c |= DEC_DIR_Y_POS; + +#ifdef FASTER + SETDEC(c); + SETWIDTH(length); +#else + SETWIDTH(length); + SETDEC(c); +#endif + + if (octant & YMAJOR) + UPDATEDEST(x1 + e1 / 2, y1 + e2 / 2); + else + UPDATEDEST(x1 + e2 / 2, y1 + e1 / 2); + if (pApm->apmClip) + { + pApm->apmClip = FALSE; + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0); + } +} + +static void +A(SetClippingRectangle)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + APMDECL(pScrn); + + DPRINTNAME(SetClippingRectangle); + A(WaitForFifo)(pApm, 3); + SETCLIP_LEFTTOP(x1,y1); + SETCLIP_RIGHTBOT(x2,y2); + SETCLIP_CTRL(0x01); + pApm->apmClip = TRUE; +} + +static void +A(SyncBlt)(ApmPtr pApm) +{ + int again = (pApm->Chipset == AP6422); + + do { + while (!(STATUS() & STATUS_HOSTBLTBUSY)) + ; + } + while (again--); /* See remark in Sync6422 */ +} +static void +A(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int trans, int bpp, int depth) +{ + APMDECL(pScrn); + int dwords, skipleft, Bpp = bpp >> 3; + Bool beCareful = FALSE; + unsigned char *dst = ((unsigned char *)pApm->FbBase) + x * Bpp + y * pApm->CurrentLayout.bytesPerScanline; + int PlusOne = 0, mask, count; + + DPRINTNAME(WritePixmap); + if (rop == GXnoop) + return; + /* + * The function seems to crash more than it feels good. I hope that a + * good sync will help. This sync is anyway needed for direct write. + */ + (*pApm->AccelInfoRec->Sync)(pScrn); + /* + * First the fast case : source and dest have same alignment. Doc says + * it's faster to do it here, which may be true since one has to read + * the chip when CPU to screen-ing. + */ + if ((skipleft = (long)src & 3L) == ((long)dst & 3L) && rop == GXcopy) { + int skipright; + + if (skipleft) + skipleft = 4 - skipleft; + dwords = (skipright = w * Bpp - skipleft) >> 2; + skipright %= 4; + if (!skipleft && !skipright) + while (h-- > 0) { + CARD32 *src2 = (CARD32 *)src; + CARD32 *dst2 = (CARD32 *)dst; + + for (count = dwords; count-- > 0; ) + *dst2++ = *src2++; + src += srcwidth; + dst += pApm->CurrentLayout.bytesPerScanline; + } + else if (!skipleft) + while (h-- > 0) { + CARD32 *src2 = (CARD32 *)src; + CARD32 *dst2 = (CARD32 *)dst; + + for (count = dwords; count-- > 0; ) + *dst2++ = *src2++; + for (count = skipright; count-- > 0; ) + ((char *)dst2)[count] = ((char *)src2)[count]; + src += srcwidth; + dst += pApm->CurrentLayout.bytesPerScanline; + } + else if (!skipright) + while (h-- > 0) { + CARD32 *src2 = (CARD32 *)(src + skipleft); + CARD32 *dst2 = (CARD32 *)(dst + skipleft); + + for (count = skipleft; count-- > 0; ) + dst[count] = src[count]; + for (count = dwords; count-- > 0; ) + *dst2++ = *src2++; + src += srcwidth; + dst += pApm->CurrentLayout.bytesPerScanline; + } + else + while (h-- > 0) { + CARD32 *src2 = (CARD32 *)(src + skipleft); + CARD32 *dst2 = (CARD32 *)(dst + skipleft); + + for (count = skipleft; count-- > 0; ) + dst[count] = src[count]; + for (count = dwords; count-- > 0; ) + *dst2++ = *src2++; + for (count = skipright; count-- > 0; ) + ((char *)dst2)[count] = ((char *)src2)[count]; + src += srcwidth; + dst += pApm->CurrentLayout.bytesPerScanline; + } + + return; + } + + if (skipleft) { + if (Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + if (x < skipleft) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + x -= skipleft; + w += skipleft; + + if (Bpp == 3) + src -= 3 * skipleft; + else /* is this Alpha friendly ? */ + src = (unsigned char*)((long)src & ~0x03L); + } + +BAD_ALIGNMENT: + + dwords = ((w * Bpp) + 3) >> 2; + mask = (pApm->CurrentLayout.bitsPerPixel / 8) - 1; + + if (dwords & mask) { + /* + * Experimental... + * It seems the AT3D needs a padding of scanline to a multiple of + * 4 pixels, not only bytes. + */ + PlusOne = mask - (dwords & mask) + 1; + } + + A(SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth); + A(SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft); + + if (beCareful) { + /* in cases with bad alignment we have to be careful not + to read beyond the end of the source */ + if (((x * Bpp) + (dwords << 2)) > srcwidth) h--; + else beCareful = FALSE; + } + + srcwidth -= (dwords << 2); + + while (h--) { + for (count = dwords; count-- > 0; ) { + A(SyncBlt)(pApm); + *(CARD32*)pApm->BltMap = *(CARD32*)src; + src += 4; + } + src += srcwidth; + for (count = PlusOne; count-- > 0; ) { + int status; + + while (!((status = STATUS()) & STATUS_HOSTBLTBUSY)) + if (!(status & STATUS_ENGINEBUSY)) + break; + if (pApm->Chipset == AP6422) /* See remark in Sync6422 */ + while (!((status = STATUS()) & STATUS_HOSTBLTBUSY)) + if (!(status & STATUS_ENGINEBUSY)) + break; + if (status & STATUS_ENGINEBUSY) + *(CARD32*)pApm->BltMap = 0x00000000; + } + } + if (beCareful) { + int shift = ((long)src & 0x03L) << 3; + + if (--dwords) { + for (count = dwords >> 2; count-- > 0; ) { + A(SyncBlt)(pApm); + *(CARD32*)pApm->BltMap = *(CARD32*)src; + src += 4; + } + } + A(SyncBlt)(pApm); + *((CARD32*)pApm->BltMap) = *((CARD32*)src) >> shift; + } + + pApm->apmClip = FALSE; + A(WaitForFifo)(pApm, 1); + SETCLIP_CTRL(0); +} + +static void +A(FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, unsigned int planemask, + int nBox, BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, y, phaseY, phaseX, phaseXB, height, width, blit_w; + int pHeight = pPix->drawable.height; + int pWidth = pPix->drawable.width; + int depth = pPix->drawable.depth; + int bpp = pPix->drawable.bitsPerPixel; + unsigned char *pSrc; + int srcwidth = pPix->devKind; + + while(nBox--) { + x = pBox->x1; + y = pBox->y1; + phaseY = (pBox->y1 - yorg) % pHeight; + if(phaseY < 0) phaseY += pHeight; + phaseX = (x - xorg) % pWidth; + pSrc = (unsigned char *)pPix->devPrivate.ptr + + phaseX * pPix->drawable.bitsPerPixel / 8; + if(phaseX < 0) phaseX += pWidth; + height = pBox->y2 - pBox->y1; + width = pBox->x2 - x; + + while(1) { + int ch = height, cp = phaseY, cy = y; + + blit_w = pWidth - phaseX; + if(blit_w > width) blit_w = width; + + while (ch > 0) { + int h = MIN(pHeight - cp, ch); + + A(WritePixmap)(pScrn, x, cy, blit_w, h, pSrc + cp * srcwidth, + srcwidth, rop, planemask, FALSE, bpp, depth); + cy += h; + ch -= h; + cp = 0; + } + + width -= blit_w; + if(!width) break; + x += blit_w; + phaseX = (phaseX + blit_w) % pWidth; + phaseXB = phaseX * pPix->drawable.bitsPerPixel / 8; + } + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + +static void A(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn,int patx,int paty, + int rop, unsigned int planemask, + int transparency_color) +{ + APMDECL(pScrn); + + DPRINTNAME(SetupForColor8x8PatternFillRect); + if (transparency_color != -1) { +#ifndef FASTER + pApm->apmTransparency = TRUE; + A(WaitForFifo)(pApm, 2 + pApm->apmClip); +#else + A(WaitForFifo)(pApm, 3 + pApm->apmClip); + SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | + DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_SOURCE_TRANSPARENCY | + DEC_QUICKSTART_ONDIMX); +#endif + SETBACKGROUNDCOLOR(transparency_color); + } + else { +#ifndef FASTER + pApm->apmTransparency = FALSE; + A(WaitForFifo)(pApm, 1 + pApm->apmClip); +#else + A(WaitForFifo)(pApm, 2 + pApm->apmClip); + SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | + DEC_DEST_XY | DEC_PATTERN_88_8bCOLOR | DEC_QUICKSTART_ONDIMX); +#endif + } + if (pApm->apmClip) { + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } + SETROP(apmROP[rop]); +} + +static void A(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, + int paty, int x, int y, + int w, int h) +{ + APMDECL(pScrn); + + DPRINTNAME(SubsequentColor8x8PatternFillRect); +#ifndef FASTER + A(WaitForFifo)(pApm, 5); +#else + A(WaitForFifo)(pApm, 4); +#endif + SETSOURCEXY(patx, paty); + SETDESTXY(x, y); + SETWIDTHHEIGHT(w, h); + UPDATEDEST(x + w + 1, y); +#ifndef FASTER + SETDEC(pApm->CurrentLayout.Setup_DEC | DEC_OP_BLT | + DEC_DEST_XY | (pApm->apmTransparency * DEC_SOURCE_TRANSPARENCY) | + DEC_PATTERN_88_8bCOLOR | DEC_START); +#endif +} +#endif + +static void +A(Sync)(ScrnInfoPtr pScrn) +{ + APMDECL(pScrn); + volatile u32 i, stat; + + for(i = 0; i < MAXLOOP; i++) { + stat = STATUS(); + if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) && + ((stat & STATUS_FIFO) >= 8)) + break; + } + if (i == MAXLOOP) { + unsigned int status = STATUS(); + + WRXB(0x1FF, 0); + if (!xf86ServerIsExiting()) + FatalError("Hung in ApmSync" APM_SUFF_24 APM_SUFF_IOP "(%d) (Status = 0x%08X)\n", pScrn->pScreen->myNum, status); + } + if (pApm->apmClip) { + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } +} + +#if PSZ != 24 +static void +A(Sync6422)(ScrnInfoPtr pScrn) +{ + APMDECL(pScrn); + volatile u32 i, j, stat; + + for (j = 0; j < 2; j++) { + /* + * From Henrik Harmsen : + * + * This is a kludge. We can't trust the status register. Don't + * know why... We shouldn't be forced to read the status reg and get + * a correct value more than once... + */ + for(i = 0; i < MAXLOOP; i++) { + stat = STATUS(); + if ((!(stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY))) && + ((stat & STATUS_FIFO) >= 4)) + break; + } + } + if (i == MAXLOOP) { + unsigned int status = STATUS(); + + WRXB(0x1FF, 0); + if (!xf86ServerIsExiting()) + FatalError("Hung in ApmSync6422() (Status = 0x%08X)\n", status); + } + if (pApm->apmClip) { + SETCLIP_CTRL(0); + pApm->apmClip = FALSE; + } +} +#endif +#include "apm_video.c" + + +#undef RDXB +#undef RDXW +#undef RDXL +#undef WRXB +#undef WRXW +#undef WRXL +#undef ApmWriteSeq +#define RDXB RDXB_M +#define RDXW RDXW_M +#define RDXL RDXL_M +#define WRXB WRXB_M +#define WRXW WRXW_M +#define WRXL WRXL_M +#define ApmWriteSeq(idx, val) do { APMVGAB(0x3C4) = (idx); APMVGAB(0x3C5) = (val); break; } while(1) +#undef DPRINTNAME +#undef A +#undef DEPTH +#undef PSZ +#undef IOP_ACCESS +#undef APM_SUFF_24 +#undef APM_SUFF_IOP |