/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/enhanced/vgaBitBlt.c,v 3.4 1996/12/23 06:59:15 dawes Exp $ */ /* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Thomas Roell not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Thomas Roell makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Thomas Roell, roell@informatik.tu-muenchen.de * */ /* $XConsortium: vgaBitBlt.c /main/4 1996/02/21 18:09:26 kaleb $ */ #include "vga256.h" #include "fastblt.h" #include "mergerop.h" void (*ourvgaBitBlt)(); void vgaBitBlt(pdstBase, psrcBase, widthSrc, widthDst, x, y, x1, y1, w, h, xdir, ydir, alu, planemask) unsigned char *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; int x, y, x1, y1, w, h; int xdir, ydir; int alu; unsigned long planemask; { unsigned char *psrc, *pdst; int hcount, vcount, count, srcPitch, dstPitch, tmp; if (alu == GXcopy && (planemask & 0xFF) == 0xFF) { if (xdir == 1) { /* left to right */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x; pdst = pdstBase+(y1*widthDst)+x1; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x; pdst = pdstBase-((y1+h-1)*widthDst)+x1; } srcPitch = widthSrc - w; dstPitch = widthDst - w; } else {/* right to left */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x+w; pdst = pdstBase+(y1 * widthDst)+x1+w; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x+w; pdst = pdstBase-((y1+h-1)*widthDst)+x1+w; } srcPitch = widthSrc + w; dstPitch = widthDst + w; } psrc = (unsigned char *)vgaSetRead(psrc); pdst = (unsigned char *)vgaSetWrite(pdst); vcount = 0; while (h || vcount) { /* * compute here the maximal linecount(hcount) before a * segment switch has to be made */ if (!vcount) { if (ydir == 1) { tmp = ((unsigned char *)vgaReadTop - psrc) / widthSrc; if ((xdir == -1) && ((psrc - (unsigned char *)vgaReadBottom) <= w)) tmp = 0; } else { tmp = (psrc - (unsigned char *)vgaReadBottom) / (-widthSrc); if ((xdir == 1) && (((unsigned char *)vgaReadTop - psrc) <= w)) tmp = 0; } hcount=min( h, tmp ); if(!hcount) vcount = w; if (ydir == 1) { tmp = ((unsigned char *)vgaWriteTop - pdst) / widthDst; if ((xdir == -1) && ((pdst - (unsigned char *)vgaWriteBottom) <= w)) tmp = 0; } else { tmp = (pdst - (unsigned char *)vgaWriteBottom) / (-widthDst); if ((xdir == 1) && (((unsigned char *)vgaWriteTop - pdst) <= w)) tmp = 0; } hcount=min( hcount, tmp ); if(!hcount) vcount = w; } /* * if we now have to make a segment switch within a line, * divide this line into small parts. */ if (vcount) { count = vcount; /* check which segment to switch first */ if (xdir == 1) { if (tmp = (unsigned char *)vgaReadTop - psrc) count = min(count, tmp); else psrc = (unsigned char *)vgaReadNext(psrc); } else { if (tmp = psrc - (unsigned char *)vgaReadBottom) count = min(count, tmp); else psrc = (unsigned char *)vgaReadPrev(psrc); } if (xdir == 1) { if (tmp = (unsigned char *)vgaWriteTop - pdst) count = min(count, tmp); else pdst = (unsigned char *)vgaWriteNext(pdst); } else { if (tmp = pdst - (unsigned char *)vgaWriteBottom) count = min(count, tmp); else pdst = (unsigned char *)vgaWritePrev(pdst); } fastBitBltCopy(xdir,psrc, pdst, 1, count, 0, 0); if (!(vcount -= count)) { h--; /* partial line finish */ if (xdir == 1) { psrc += (srcPitch + count); pdst += (dstPitch + count); } else { psrc += (srcPitch - count); pdst += (dstPitch - count); } if ( psrc >= (unsigned char *)vgaReadTop ) psrc = (unsigned char *)vgaReadNext(psrc); if ( psrc < (unsigned char *)vgaReadBottom ) psrc = (unsigned char *)vgaReadPrev(psrc); if ( pdst >= (unsigned char *)vgaWriteTop ) pdst = (unsigned char *)vgaWriteNext(pdst); if ( pdst < (unsigned char *)vgaWriteBottom ) pdst = (unsigned char *)vgaWritePrev(pdst); } else { if (xdir == 1) { psrc += count; pdst += count; } else { psrc -= count; pdst -= count; } } } else { h -= hcount; fastBitBltCopy(xdir, psrc, pdst, hcount, w, srcPitch, dstPitch); psrc += (hcount*widthSrc); pdst += (hcount*widthDst); } } } } void OneBankvgaBitBlt(pdstBase, psrcBase, widthSrc, widthDst, x, y, x1, y1, w, h, xdir, ydir, alu, planemask) unsigned char *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; int x, y, x1, y1, w, h; int xdir, ydir; int alu; unsigned long planemask; { #define BUFSIZE 4096 unsigned char buf[BUFSIZE]; int m,n,ww; if (alu == GXcopy && (planemask & 0xFF) == 0xFF) { if (w == 0) return; if (widthSrc != widthDst) return; ww = widthSrc >= 0 ? widthSrc : -widthSrc; m = BUFSIZE/ww; if (ydir == 1) { while (h) { n = m>h ? h : m; (void)vgaImageRead(buf, psrcBase, widthSrc,ww,x,y,0,0,w,n,xdir,ydir,alu,planemask); (void)vgaImageWrite(pdstBase, buf,ww,widthDst,0,0,x1,y1,w,n,xdir,ydir,alu,planemask); y += n; y1 += n; h -= n; } } else { y += h; y1 += h; while (h) { n = m>h ? h : m; y -= n; y1 -= n; h -= n; (void)vgaImageRead(buf+BUFSIZE-ww,psrcBase,widthSrc,ww,x,y,0,0,w,n,xdir,ydir,alu,planemask); (void)vgaImageWrite(pdstBase,buf+BUFSIZE-ww,ww,widthDst,0,0,x1,y1,w,n,xdir,ydir,alu,planemask); } } } } void vgaImageRead(pdstBase, psrcBase, widthSrc, widthDst, x, y, x1, y1, w, h, xdir, ydir, alu, planemask) unsigned char *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; int x, y, x1, y1, w, h; int xdir, ydir; int alu; unsigned long planemask; { register unsigned char *psrc, *pdst; int hcount, vcount, count, srcPitch, dstPitch, tmp; if (alu == GXcopy && (planemask & 0xFF) == 0xFF) { if (xdir == 1) { /* left to right */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x; pdst = pdstBase+(y1*widthDst)+x1; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x; pdst = pdstBase-((y1+h-1)*widthDst)+x1; } srcPitch = widthSrc - w; dstPitch = widthDst - w; } else {/* right to left */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x+w; pdst = pdstBase+(y1 * widthDst)+x1+w; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x+w; pdst = pdstBase-((y1+h-1)*widthDst)+x1+w; } srcPitch = widthSrc + w; dstPitch = widthDst + w; } psrc = (unsigned char *)vgaSetRead(psrc); vcount = 0; while (h || vcount) { /* * compute here the maximal linecount(hcount) before a * segment switch has to be made */ if (!vcount) { if (ydir == 1) { tmp = ((unsigned char *)vgaReadTop - psrc) / widthSrc; if ((xdir == -1) && ((psrc - (unsigned char *)vgaReadBottom) <= w)) tmp = 0; } else { tmp = (psrc - (unsigned char *)vgaReadBottom) / (-widthSrc); if ((xdir == 1) && (((unsigned char *)vgaReadTop - psrc) <= w)) tmp = 0; } hcount=min( h, tmp ); if(!hcount) vcount = w; } /* * if we now have to make a segment switch within a line, * divide this line into small parts. */ if (vcount) { count = vcount; /* check which segment to switch first */ if (xdir == 1) { if (tmp = (unsigned char *)vgaReadTop - psrc) count = min(count, tmp); else psrc = (unsigned char *)vgaReadNext(psrc); } else { if (tmp = psrc - (unsigned char *)vgaReadBottom) count = min(count, tmp); else psrc = (unsigned char *)vgaReadPrev(psrc); } fastBitBltCopy(xdir,psrc, pdst, 1, count, 0, 0); if (!(vcount -= count)) { h--; /* partial line finish */ if (xdir == 1) { psrc += (srcPitch + count); pdst += (dstPitch + count); } else { psrc += (srcPitch - count); pdst += (dstPitch - count); } if ( psrc >= (unsigned char *)vgaReadTop ) psrc = (unsigned char *)vgaReadNext(psrc); if ( psrc < (unsigned char *)vgaReadBottom ) psrc = (unsigned char *)vgaReadPrev(psrc); } else { if (xdir == 1) { psrc += count; pdst += count; } else { psrc -= count; pdst -= count; } } } else { h -= hcount; fastBitBltCopy(xdir, psrc, pdst, hcount, w, srcPitch, dstPitch); psrc += (hcount*widthSrc); pdst += (hcount*widthDst); } } } } void vgaImageWrite(pdstBase, psrcBase, widthSrc, widthDst, x, y, x1, y1, w, h, xdir, ydir, alu, planemask) unsigned char *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; int x, y, x1, y1, w, h; int xdir, ydir; int alu; unsigned long planemask; { register unsigned char *psrc, *pdst; int hcount, vcount, count, srcPitch, dstPitch, tmp; if (alu == GXcopy && (planemask & 0xFF) == 0xFF) { if (xdir == 1) { /* left to right */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x; pdst = pdstBase+(y1*widthDst)+x1; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x; pdst = pdstBase-((y1+h-1)*widthDst)+x1; } srcPitch = widthSrc - w; dstPitch = widthDst - w; } else {/* right to left */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x+w; pdst = pdstBase+(y1 * widthDst)+x1+w; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x+w; pdst = pdstBase-((y1+h-1)*widthDst)+x1+w; } srcPitch = widthSrc + w; dstPitch = widthDst + w; } pdst = (unsigned char *)vgaSetWrite(pdst); vcount = 0; while (h || vcount) { /* * compute here the maximal linecount(hcount) before a * segment switch has to be made */ if (!vcount) { if (ydir == 1) { tmp = ((unsigned char *)vgaWriteTop - pdst) / widthDst; if ((xdir == -1) && ((pdst - (unsigned char *)vgaWriteBottom) <= w)) tmp = 0; } else { tmp = (pdst - (unsigned char *)vgaWriteBottom) / (-widthDst); if ((xdir == 1) && (((unsigned char *)vgaWriteTop - pdst) <= w)) tmp = 0; } hcount=min( h, tmp ); if(!hcount) vcount = w; } /* * if we now have to make a segment switch within a line, * divide this line into small parts. */ if (vcount) { count = vcount; /* check which segment to switch first */ if (xdir == 1) { if (tmp = (unsigned char *)vgaWriteTop - pdst) count = min(count, tmp); else pdst = (unsigned char *)vgaWriteNext(pdst); } else { if (tmp = pdst - (unsigned char *)vgaWriteBottom) count = min(count, tmp); else pdst = (unsigned char *)vgaWritePrev(pdst); } fastBitBltCopy(xdir,psrc, pdst, 1, count, 0, 0); if (!(vcount -= count)) { h--; /* partial line finish */ if (xdir == 1) { psrc += (srcPitch + count); pdst += (dstPitch + count); } else { psrc += (srcPitch - count); pdst += (dstPitch - count); } if ( (void *)pdst >= vgaWriteTop ) pdst = (unsigned char *)vgaWriteNext(pdst); if ( (void *)pdst < vgaWriteBottom ) pdst = (unsigned char *)vgaWritePrev(pdst); } else { if (xdir == 1) { psrc += count; pdst += count; } else { psrc -= count; pdst -= count; } } } else { h -= hcount; fastBitBltCopy(xdir, psrc, pdst, hcount, w, srcPitch, dstPitch); psrc += (hcount*widthSrc); pdst += (hcount*widthDst); } } } } void vgaPixBitBlt(pdstBase, psrcBase, widthSrc, widthDst, x, y, x1, y1, w, h, xdir, ydir, alu, planemask) unsigned char *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; int x, y, x1, y1, w, h; int xdir, ydir; int alu; unsigned long planemask; { register unsigned char *psrc, *pdst; int srcPitch, dstPitch; if (alu == GXcopy && (planemask & 0xFF) == 0xFF) { if (xdir == 1) { /* left to right */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x; pdst = pdstBase+(y1*widthDst)+x1; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x; pdst = pdstBase-((y1+h-1)*widthDst)+x1; } srcPitch = widthSrc - w; dstPitch = widthDst - w; } else {/* right to left */ if (ydir == 1) /* top to bottom */ { psrc = psrcBase+(y*widthSrc)+x+w; pdst = pdstBase+(y1 * widthDst)+x1+w; } else /* bottom to top */ { psrc = psrcBase-((y+h-1)*widthSrc)+x+w; pdst = pdstBase-((y1+h-1)*widthDst)+x1+w; } srcPitch = widthSrc + w; dstPitch = widthDst + w; } fastBitBltCopy(xdir, psrc, pdst, h, w, srcPitch, dstPitch); } }