/* $XFree86: xc/programs/Xserver/hw/xfree86/mono/drivers/apollo/apolloBlt.c,v 3.2 1994/06/28 12:30:08 dawes Exp $ */ /* * MONO: Driver family for interlaced and banked monochrome video adaptors * Pascal Haible 8/93, 3/94, 4/94 haible@IZFM.Uni-Stuttgart.DE * * bdm2/driver/apollo/apolloBlt.c * Hamish Coleman 11/93 hamish@zot.apana.org.au */ #include "X.h" #include "Xmd.h" #include "Xproto.h" #include "gcstruct.h" #include "windowstr.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "regionstr.h" #include "compiler.h" #ifdef NOTYET #include "mfb.h" #endif #include "mono.h" #include "apolloHW.h" #include #ifndef MINIX #include #else #include #endif extern unsigned Apollo_IOBASE; void _ApolloDoBitblt(pdstBase, psrcBase, widthSrc, widthDst, X_Src, Y_Src, X_Dest, Y_Dest, X_Count, Y_Count, xdir, ydir, alu) unsigned char *pdstBase, *psrcBase; int X_Src, Y_Src, X_Dest, Y_Dest, X_Count, Y_Count; int xdir, ydir, alu; { int Src_Addr; int Dest_Addr; int Src_Ptr; int Dest_Ptr; int Combined_Mask; int Y_Delta; int X_End; int X_Word_Count; int Start_Mask; int End_Mask; int Shift; int Preread; int YC; int Dummy; int XC; int Incr; ErrorF("_DoBitblt called\n"); /* KLUDGE !!!! */ if (xdir>0 && ydir>0) { Incr = 1; } else { Incr = -1; } outb(AP_PORT_CONTROL_3,AP_BIT_ROP|AP_ON); outw(AP_PORT_ROP,alu|alu<<4|alu<<8|alu<<12); /* switch (controller type) monochrome: */ outb(AP_PORT_CONTROL_2,AP_DATA_PLN); Src_Addr = (int)psrcBase + Y_Src * Word_Width + X_Src/16; Dest_Addr = (int)pdstBase + Y_Dest * Word_Width + X_Dest/16; if (Incr > 0) { Y_Delta = Word_Width; X_End = X_Dest + X_Count - 1; X_Word_Count = X_End/16 - X_Dest/16 + 1; Start_Mask = 0xFFFF0000 << (X_Dest%16); End_Mask = 0x00007fff << (X_End%16); Combined_Mask = Start_Mask | End_Mask; Shift = ((X_Dest % 16) - (X_Src % 16)) % 16; if ((X_Dest % 16) < (X_Src % 16)) { Preread = 1; } else { Preread = 0; } } else { Y_Delta = - Word_Width; X_End = X_Dest - X_Count + 1; X_Word_Count = X_Dest/16 - X_End/16 + 1; Start_Mask = 0x00007fff << (X_Dest % 16); End_Mask = 0xffff0000 << (X_End % 16); Combined_Mask = Start_Mask | End_Mask; Shift = -((X_Src % 16) - (X_Dest % 16)) % 16; if ((X_Dest % 16) > (X_Src % 16)) { Preread = 1; } else { Preread = 0; } } outb(AP_PORT_CONTROL_0,AP_MODE_DBLT|Shift); for (YC=0;YC 1) { tmp = htons(Start_Mask); outw(AP_PORT_WRITE_ENABLE,tmp); *(short *)Src_Ptr = htons((short)Dest_Ptr); Src_Ptr += Incr; Dest_Ptr += Incr; outw(AP_PORT_WRITE_ENABLE,0); for (XC=1;XCtype == DRAWABLE_WINDOW) { psrcBase = (unsigned char *) (((PixmapPtr)(pSrc->pScreen->devPrivate))->devPrivate.ptr); widthSrc = (int)((PixmapPtr)(pSrc->pScreen->devPrivate))->devKind; } else { psrcBase = (unsigned char *)(((PixmapPtr)pSrc)->devPrivate.ptr); widthSrc = (int)(((PixmapPtr)pSrc)->devKind); } if (pDst->type == DRAWABLE_WINDOW) { pdstBase = (unsigned char *) (((PixmapPtr)(pDst->pScreen->devPrivate))->devPrivate.ptr); widthDst = (int) ((PixmapPtr)(pDst->pScreen->devPrivate))->devKind; } else { pdstBase = (unsigned char *)(((PixmapPtr)pDst)->devPrivate.ptr); widthDst = (int)(((PixmapPtr)pDst)->devKind); } /* XXX we have to err on the side of safety when both are windows, * because we don't know if IncludeInferiors is being used. */ careful = ((pSrc == pDst) || ((pSrc->type == DRAWABLE_WINDOW) && (pDst->type == DRAWABLE_WINDOW))); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); if (careful && (pptSrc->y < pbox->y1)) NoAccel = 1; if (careful && (pptSrc->x < pbox->x1)) NoAccel = 1; #ifdef NOTYET if (CHECKSCREEN(psrcBase)) { if (CHECKSCREEN(pdstBase)) /* Screen -> Screen */ { /* all ok */ } else /* Screen -> Mem */ { return(-1); } } else { if (CHECKSCREEN(pdstBase)) /* Mem -> Screen */ { return(-1); } else /* Mem -> Mem */ { return(-1); } } #endif ErrorF("DoBitblt used\n"); pboxNew1 = NULL; pptNew1 = NULL; pboxNew2 = NULL; pptNew2 = NULL; if (careful && (pptSrc->y < pbox->y1)) { /* walk source botttom to top */ ydir = -1; widthSrc = -widthSrc; widthDst = -widthDst; if (nbox > 1) { /* keep ordering in each band, reverse order of bands */ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); if(!pboxNew1) return(0); pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if(!pptNew1) { DEALLOCATE_LOCAL(pboxNew1); return(0); } pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext+1; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp <= pboxBase) { *pboxNew1++ = *pboxTmp++; *pptNew1++ = *pptTmp++; } pboxBase = pboxNext; } pboxNew1 -= nbox; pbox = pboxNew1; pptNew1 -= nbox; pptSrc = pptNew1; } } else { /* walk source top to bottom */ ydir = 1; } if (careful && (pptSrc->x < pbox->x1)) { /* walk source right to left */ xdir = -1; if (nbox > 1) { /* reverse order of rects in each band */ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if(!pboxNew2 || !pptNew2) { if (pptNew2) DEALLOCATE_LOCAL(pptNew2); if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } return(0); } pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp != pboxBase) { *pboxNew2++ = *--pboxTmp; *pptNew2++ = *--pptTmp; } pboxBase = pboxNext; } pboxNew2 -= nbox; pbox = pboxNew2; pptNew2 -= nbox; pptSrc = pptNew2; } } else { /* walk source left to right */ xdir = 1; } while(nbox--) { _ApolloDoBitblt(pdstBase, psrcBase,widthSrc,widthDst, pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, xdir, ydir, alu); pbox++; pptSrc++; } /* free up stuff */ if (pboxNew2) { DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); } if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } return(0); }