2004-03-14 09:34:49 +01:00
|
|
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/xf4bpp/vgaBitBlt.c,v 1.6 2003/11/17 22:20:42 dawes Exp $ */
|
2003-11-14 17:48:57 +01:00
|
|
|
/* GJA -- span move routines */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* $XConsortium: vgaBitBlt.c /main/8 1996/10/27 11:06:39 kaleb $ */
|
|
|
|
|
|
|
|
#include "xf4bpp.h"
|
|
|
|
#include "OScompiler.h"
|
|
|
|
#include "vgaReg.h"
|
|
|
|
#include "vgaVideo.h"
|
|
|
|
|
|
|
|
#include "xf86str.h" /* for pScrn->vtSema */
|
|
|
|
extern ScrnInfoPtr *xf86Screens;
|
|
|
|
|
|
|
|
#ifndef PC98_EGC /* not PC98_EGC */
|
|
|
|
/* NOTE: It seems that there is no way to program the VGA to copy just
|
|
|
|
* a part of a byte in the smarter modes. Therefore we copy the boundaries
|
|
|
|
* plane by plane.
|
|
|
|
*/
|
|
|
|
#define WORDSZ 8
|
|
|
|
/* The fast blit code requires WORDSZ = 8 for its read-modify write cycle.
|
|
|
|
* Therefore, we do not fully implement the other options.
|
|
|
|
*/
|
|
|
|
#define HIGHPLANEMASK 0x08
|
|
|
|
#define HIGHPLANEINDEX 3
|
|
|
|
|
|
|
|
/* Of course, we want the following anyway:
|
|
|
|
* (Yes, they're identical now.)
|
|
|
|
*/
|
|
|
|
#define SMEM(x,y) ( VIDBASE(pWin) + (y) * BYTES_PER_LINE(pWin) + (x) )
|
|
|
|
#define DMEM(x,y) ( VIDBASE(pWin) + (y) * BYTES_PER_LINE(pWin) + (x) )
|
|
|
|
|
|
|
|
#define WORD8 unsigned char
|
|
|
|
#define LW8 BYTES_PER_LINE(pWin) /* Line width */
|
|
|
|
#define WSHIFT8 0x3
|
|
|
|
#define WMASK8 0x07
|
|
|
|
/* NOTE: lmask[8] matters. It must be different from lmask[0] */
|
|
|
|
static unsigned char lmasktab[] = {
|
|
|
|
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF
|
|
|
|
} ;
|
|
|
|
static unsigned char rmasktab[] = {
|
|
|
|
0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
|
|
|
|
} ;
|
|
|
|
|
|
|
|
#define LMASK8(n) lmasktab[n]
|
|
|
|
#define RMASK8(n) rmasktab[n]
|
|
|
|
#define SWAPB8(x) (x)
|
|
|
|
|
|
|
|
#if (WORDSZ == 8)
|
|
|
|
|
|
|
|
#define WORD WORD8
|
|
|
|
#define LW LW8
|
|
|
|
#define WSHIFT WSHIFT8
|
|
|
|
#define WMASK WMASK8
|
|
|
|
|
|
|
|
#define LMASK(n) LMASK8(n)
|
|
|
|
#define RMASK(n) RMASK8(n)
|
|
|
|
#define SWAPB(x) SWAPB8(x)
|
|
|
|
|
|
|
|
#endif /* WORDSZ == 8 */
|
|
|
|
|
|
|
|
#define DO_ALU(dst,src,mask,alu) {\
|
|
|
|
int _ndst, _odst; _odst = dst; \
|
|
|
|
switch ( alu ) { \
|
|
|
|
case GXclear: \
|
|
|
|
_ndst = 0; break; \
|
|
|
|
case GXand: \
|
|
|
|
_ndst = src & _odst; break; \
|
|
|
|
case GXandReverse: \
|
|
|
|
_ndst = src & ~ _odst; break; \
|
|
|
|
case GXcopy: \
|
|
|
|
_ndst = src; break; \
|
|
|
|
case GXandInverted: \
|
|
|
|
_ndst = ~ src & _odst; break; \
|
|
|
|
default: \
|
|
|
|
case GXnoop: \
|
|
|
|
_ndst = _odst; break; \
|
|
|
|
case GXxor: \
|
|
|
|
_ndst = src ^ _odst; break; \
|
|
|
|
case GXor: \
|
|
|
|
_ndst = src | _odst; break; \
|
|
|
|
case GXnor: \
|
|
|
|
_ndst = ~ src & ~ _odst; break; \
|
|
|
|
case GXequiv: \
|
|
|
|
_ndst = ~ src ^ _odst; break; \
|
|
|
|
case GXinvert: \
|
|
|
|
_ndst = ~ _odst; break; \
|
|
|
|
case GXorReverse: \
|
|
|
|
_ndst = src | ~ _odst; break; \
|
|
|
|
case GXcopyInverted: \
|
|
|
|
_ndst = ~ src; break; \
|
|
|
|
case GXorInverted: \
|
|
|
|
_ndst = ~ src | _odst; break; \
|
|
|
|
case GXnand: \
|
|
|
|
_ndst = ~ src | ~ _odst; break; \
|
|
|
|
case GXset: \
|
|
|
|
_ndst = ~0; break; \
|
|
|
|
} \
|
|
|
|
dst = (_odst & ~(mask)) | (_ndst & (mask)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aligned_blit(
|
|
|
|
WindowPtr, int, int, int, int, int, int, int, int
|
|
|
|
);
|
|
|
|
|
|
|
|
static void aligned_blit_center(
|
|
|
|
WindowPtr, int, int, int, int, int, int
|
|
|
|
);
|
|
|
|
|
|
|
|
static void shift(
|
|
|
|
WindowPtr, int, int, int, int, int, int, int
|
|
|
|
);
|
|
|
|
|
|
|
|
static void shift_thin_rect(
|
|
|
|
WindowPtr, int, int, int, int, int, int, int
|
|
|
|
);
|
|
|
|
|
|
|
|
static void shift_center(
|
|
|
|
WindowPtr, int, int, int, int, int, int, int
|
|
|
|
);
|
|
|
|
|
|
|
|
void xf4bppBitBlt(pWin,alu,writeplanes,x0,y0,x1,y1,w,h)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int alu;
|
|
|
|
int writeplanes; /* planes */
|
|
|
|
int x0, y0, x1, y1, w, h;
|
|
|
|
{
|
|
|
|
IOADDRESS REGBASE;
|
|
|
|
int plane, bit;
|
|
|
|
|
|
|
|
if ( !w || !h ) return;
|
|
|
|
|
|
|
|
if ( ! xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->vtSema ) {
|
|
|
|
xf4bppOffBitBlt(pWin,alu,writeplanes,x0,y0,x1,y1,w,h);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
REGBASE =
|
|
|
|
xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->domainIOBase + 0x300;
|
|
|
|
|
|
|
|
/* 0x7, not WMASK: it is hardware dependant */
|
|
|
|
if ( ((x0 - x1) & 0x7) || (alu != GXcopy) ) {
|
|
|
|
/* Use slow copy */
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX ;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( writeplanes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift(pWin,x0,x1,y0,y1,w,h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
aligned_blit(pWin,x0,x1,y0,y1,w,h,alu,writeplanes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy a span a number of places to the right.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
shift(pWin,x0,x1,y0,y1,w,h,alu)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int x0; /* left edge of source */
|
|
|
|
int x1; /* left edge of target */
|
|
|
|
int y0;
|
|
|
|
int y1;
|
|
|
|
int w; /* length of source, and of target */
|
|
|
|
int h;
|
|
|
|
int alu;
|
|
|
|
{
|
|
|
|
if ( ((x1 & WMASK) + w) <= WORDSZ ) {
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu);
|
|
|
|
} else if ( x1 > x0 ) { /* Shift right: start right */
|
|
|
|
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
|
|
|
|
|
|
|
|
if ( r1 ) /* right edge */
|
|
|
|
shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
|
|
|
|
shift_center(pWin,x0,x1,y0,y1,w,h,alu);
|
|
|
|
if ( l1 ) /* left edge */
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
|
|
|
|
} else {
|
|
|
|
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
|
|
|
|
|
|
|
|
if ( l1 ) /* left edge */
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
|
|
|
|
shift_center(pWin,x0,x1,y0,y1,w,h,alu);
|
|
|
|
if ( r1 ) /* right edge */
|
|
|
|
shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The whole rectangle is so thin that it fits in one byte written */
|
|
|
|
static void
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int x0; /* left edge of source */
|
|
|
|
int x1; /* left edge of target */
|
|
|
|
int y0;
|
|
|
|
int y1;
|
|
|
|
int w; /* length of source, and of target */
|
|
|
|
int h;
|
|
|
|
int alu;
|
|
|
|
{
|
|
|
|
int l0 = x0 & WMASK; /* Left edge of source, as bit */
|
|
|
|
int l1 = x1 & WMASK; /* Left edge of target, as bit */
|
|
|
|
int L0 = x0 >> WSHIFT; /* Left edge of source, as byte */
|
|
|
|
int L1 = x1 >> WSHIFT; /* Left edge of target, as byte */
|
|
|
|
int pad;
|
|
|
|
int htmp;
|
|
|
|
int mask;
|
|
|
|
int tmp;
|
|
|
|
int bs;
|
|
|
|
|
|
|
|
volatile unsigned char *sp, *dp;
|
|
|
|
|
|
|
|
mask = RMASK(l1) & LMASK(l1+w);
|
|
|
|
bs = (x1 - x0) & WMASK;
|
|
|
|
|
|
|
|
if ( y1 > y0 ) { /* Move down, start at the bottom */
|
|
|
|
pad = - BYTES_PER_LINE(pWin);
|
|
|
|
sp = SMEM(L0,y0+h-1);
|
|
|
|
dp = DMEM(L1,y1+h-1);
|
|
|
|
} else { /* Move up, start at the top */
|
|
|
|
pad = BYTES_PER_LINE(pWin);
|
|
|
|
sp = SMEM(L0,y0);
|
|
|
|
dp = DMEM(L1,y1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( l0+w > WORDSZ ) {
|
|
|
|
/* Need two bytes */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
tmp = (sp[0] << (WORDSZ - bs));
|
|
|
|
sp++;
|
|
|
|
tmp |= (sp[0] >> bs);
|
|
|
|
sp--;
|
|
|
|
DO_ALU(dp[0],tmp,mask,alu);
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
} else if ( l0 <= l1 ) {
|
|
|
|
/* Need one byte, shifted right */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
tmp = (sp[0] >> bs);
|
|
|
|
DO_ALU(dp[0],tmp,mask,alu);
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Need one byte, shifted left */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
tmp = (sp[0] << (WORDSZ - bs));
|
|
|
|
DO_ALU(dp[0],tmp,mask,alu);
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shift_center(pWin,x0,x1,y0,y1,w,h,alu)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int x0; /* left edge of source */
|
|
|
|
int x1; /* left edge of target */
|
|
|
|
int y0;
|
|
|
|
int y1;
|
|
|
|
int w; /* length of source, and of target */
|
|
|
|
int h;
|
|
|
|
int alu;
|
|
|
|
{
|
|
|
|
int l1 = x1 & WMASK; /* Left edge of target, as bit */
|
|
|
|
int r1 = (x1 + w) & WMASK; /* Right edge of target, as bit */
|
|
|
|
int pad;
|
|
|
|
int htmp, wtmp; /* Temporaries for indices over height and width */
|
|
|
|
volatile unsigned char tmp; /* Temporary result of the shifts */
|
|
|
|
int bs;
|
|
|
|
int rem; /* Remaining bits; temporary in loop */
|
|
|
|
int bytecnt;
|
|
|
|
|
|
|
|
volatile unsigned char *sp, *dp;
|
|
|
|
|
|
|
|
bs = (x1 - x0) & WMASK;
|
|
|
|
|
|
|
|
if ( l1 ) {
|
|
|
|
bytecnt = (w - (WORDSZ - l1) - r1) >> WSHIFT;
|
|
|
|
sp = SMEM( ((x0 + (WORDSZ - l1)) >> WSHIFT), y0);
|
|
|
|
dp = DMEM( ((x1 + (WORDSZ - l1)) >> WSHIFT), y1);
|
|
|
|
} else {
|
|
|
|
bytecnt = (w - r1) >> WSHIFT;
|
|
|
|
sp = SMEM( (x0 >> WSHIFT), y0);
|
|
|
|
dp = DMEM( (x1 >> WSHIFT), y1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( y1 > y0 ) { /* Move down, start at the bottom */
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
pad = - BYTES_PER_LINE(pWin) + bytecnt;
|
|
|
|
sp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
|
|
|
|
dp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
|
|
|
|
} else { /* Move left, start left */
|
|
|
|
pad = - BYTES_PER_LINE(pWin) - bytecnt;
|
|
|
|
sp += BYTES_PER_LINE(pWin) * (h - 1);
|
|
|
|
dp += BYTES_PER_LINE(pWin) * (h - 1);
|
|
|
|
}
|
|
|
|
} else { /* Move up, start at the top */
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
pad = BYTES_PER_LINE(pWin) + bytecnt;
|
|
|
|
sp += bytecnt - 1;
|
|
|
|
dp += bytecnt - 1;
|
|
|
|
} else { /* Move left, start left */
|
|
|
|
pad = BYTES_PER_LINE(pWin) - bytecnt;
|
|
|
|
sp += 0;
|
|
|
|
dp += 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
if ( bs == 0 ) { /* No shift. Need one byte only */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = sp[0];
|
|
|
|
DO_ALU(dp[0],tmp,~0,alu);
|
|
|
|
dp--;
|
|
|
|
sp--;
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
if ( bytecnt ) {
|
|
|
|
sp++;
|
|
|
|
rem = sp[0];
|
|
|
|
sp--;
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = (rem >> bs);
|
|
|
|
rem = sp[0];
|
|
|
|
tmp |= (rem << (WORDSZ - bs)) ;
|
|
|
|
DO_ALU(dp[0],tmp,~0,alu);
|
|
|
|
dp--;
|
|
|
|
sp--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else { /* x1 <= x0 */ /* Move left, start left */
|
|
|
|
if ( bs == 0 ) { /* No shift. Need one byte only */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = sp[0];
|
|
|
|
DO_ALU(dp[0],tmp,~0,alu);
|
|
|
|
dp++;
|
|
|
|
sp++;
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
if ( bytecnt ) {
|
|
|
|
rem = sp[0];
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = (rem << (WORDSZ - bs));
|
|
|
|
sp++;
|
|
|
|
rem = sp[0];
|
|
|
|
sp--;
|
|
|
|
tmp |= (rem >> bs);
|
|
|
|
DO_ALU(dp[0],tmp,~0,alu);
|
|
|
|
dp++;
|
|
|
|
sp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy a rectangle.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
aligned_blit(pWin,x0,x1,y0,y1,w,h,alu,planes)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int x0; /* left edge of source */
|
|
|
|
int x1; /* left edge of target */
|
|
|
|
int y0;
|
|
|
|
int y1;
|
|
|
|
int w; /* length of source, and of target */
|
|
|
|
int h;
|
|
|
|
int alu;
|
|
|
|
int planes;
|
|
|
|
{
|
|
|
|
IOADDRESS REGBASE =
|
|
|
|
xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->domainIOBase + 0x300;
|
|
|
|
int plane, bit;
|
|
|
|
|
|
|
|
if ( ((x1 & WMASK) + w) <= WORDSZ ) {
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
if ( planes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( x1 > x0 ) { /* Shift right: start right */
|
|
|
|
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
|
|
|
|
|
|
|
|
if ( r1 ) { /* right edge */
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
if ( planes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Center */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 1); /* Write mode 1 */
|
|
|
|
SetVideoSequencer(Mask_MapIndex, planes);
|
|
|
|
|
|
|
|
aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
|
|
|
|
|
|
|
|
if ( l1 ) { /* left edge */
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
if ( planes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
|
|
|
|
|
|
|
|
if ( l1 ) { /* left edge */
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
if ( planes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Center */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 1); /* Write mode 1 */
|
|
|
|
SetVideoSequencer(Mask_MapIndex, planes);
|
|
|
|
|
|
|
|
aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
|
|
|
|
|
|
|
|
if ( r1 ) { /* right edge */
|
|
|
|
SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
|
|
|
|
SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
|
|
|
|
SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
|
|
|
|
SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
|
|
|
|
|
|
|
|
for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX ;
|
|
|
|
plane ; plane >>= 1, bit-- )
|
|
|
|
{
|
|
|
|
if ( planes & plane) {
|
|
|
|
SetVideoGraphics(Read_Map_SelectIndex, bit);
|
|
|
|
SetVideoSequencer(Mask_MapIndex, plane);
|
|
|
|
|
|
|
|
shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
aligned_blit_center(pWin,x0,x1,y0,y1,w,h)
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int x0; /* left edge of source */
|
|
|
|
int x1; /* left edge of target */
|
|
|
|
int y0;
|
|
|
|
int y1;
|
|
|
|
int w; /* length of source, and of target */
|
|
|
|
int h;
|
|
|
|
{
|
|
|
|
int l1 = x1 & WMASK; /* Left edge of target, as bit */
|
|
|
|
int r1 = (x1 + w) & WMASK; /* Right edge of target, as bit */
|
|
|
|
int pad;
|
|
|
|
int htmp, wtmp; /* Temporaries for indices over height and width */
|
|
|
|
volatile unsigned char tmp; /* Temporary result of the shifts */
|
|
|
|
int bytecnt;
|
|
|
|
|
|
|
|
volatile unsigned char *sp, *dp;
|
|
|
|
|
|
|
|
if ( l1 ) {
|
|
|
|
bytecnt = (w - (WORDSZ - l1) - r1) >> WSHIFT;
|
|
|
|
sp = SMEM( ((x0 + (WORDSZ - l1)) >> WSHIFT), y0);
|
|
|
|
dp = DMEM( ((x1 + (WORDSZ - l1)) >> WSHIFT), y1);
|
|
|
|
} else {
|
|
|
|
bytecnt = (w - r1) >> WSHIFT;
|
|
|
|
sp = SMEM( (x0 >> WSHIFT), y0);
|
|
|
|
dp = DMEM( (x1 >> WSHIFT), y1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( y1 > y0 ) { /* Move down, start at the bottom */
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
pad = - BYTES_PER_LINE(pWin) + bytecnt;
|
|
|
|
sp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
|
|
|
|
dp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
|
|
|
|
} else { /* Move left, start left */
|
|
|
|
pad = - BYTES_PER_LINE(pWin) - bytecnt;
|
|
|
|
sp += BYTES_PER_LINE(pWin) * (h - 1);
|
|
|
|
dp += BYTES_PER_LINE(pWin) * (h - 1);
|
|
|
|
}
|
|
|
|
} else { /* Move up, start at the top */
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
pad = BYTES_PER_LINE(pWin) + bytecnt;
|
|
|
|
sp += bytecnt - 1;
|
|
|
|
dp += bytecnt - 1;
|
|
|
|
} else { /* Move left, start left */
|
|
|
|
pad = BYTES_PER_LINE(pWin) - bytecnt;
|
|
|
|
sp += 0;
|
|
|
|
dp += 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( x1 > x0 ) { /* Move right, start right */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = sp[0];
|
|
|
|
dp[0] = tmp;
|
|
|
|
dp--;
|
|
|
|
sp--;
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
} else { /* x1 <= x0 */ /* Move left, start left */
|
|
|
|
for ( htmp = h ; htmp ; htmp-- ) {
|
|
|
|
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
|
|
|
|
tmp = sp[0];
|
|
|
|
dp[0] = tmp;
|
|
|
|
dp++;
|
|
|
|
sp++;
|
|
|
|
}
|
|
|
|
dp += pad;
|
|
|
|
sp += pad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else /* PC98_EGC */
|
|
|
|
|
|
|
|
static void
|
|
|
|
egc_fast_blt (pWin, alu, writeplanes, x0, y0, x1, y1, w, h)
|
|
|
|
WindowPtr pWin;
|
|
|
|
const int alu, writeplanes ;
|
|
|
|
register int x0, x1 ;
|
|
|
|
int y0, y1 ;
|
|
|
|
register int w, h ;
|
|
|
|
{
|
|
|
|
register volatile unsigned char *src ;
|
|
|
|
register volatile unsigned char *dst ;
|
|
|
|
unsigned short *src_x ;
|
|
|
|
unsigned short *dst_x ;
|
|
|
|
int x_direction, y_interval ;
|
|
|
|
int src_off, dst_off ;
|
|
|
|
register int k, i ;
|
|
|
|
unsigned short ROP_value;
|
|
|
|
|
|
|
|
src = (unsigned char *)SCREENADDRESS( pWin, 0, y0);
|
|
|
|
dst = (unsigned char *)SCREENADDRESS( pWin, 0, y1);
|
|
|
|
|
|
|
|
/* Set Map Mask */
|
|
|
|
outw(EGC_PLANE, ~(writeplanes & VGA_ALLPLANES));
|
|
|
|
switch(alu) {
|
|
|
|
case GXnor: /* ~(S|D) */
|
|
|
|
ROP_value = 0x2903;
|
|
|
|
break;
|
|
|
|
case GXandInverted: /* ~S&D */
|
|
|
|
ROP_value = 0x290c;
|
|
|
|
break;
|
|
|
|
case GXand: /* S&D */
|
|
|
|
ROP_value = 0x29c0;
|
|
|
|
break;
|
|
|
|
case GXequiv: /* ~S ^ D */
|
|
|
|
ROP_value = 0x29c3;
|
|
|
|
break;
|
|
|
|
case GXxor: /* S^D */
|
|
|
|
ROP_value = 0x293c;
|
|
|
|
break;
|
|
|
|
case GXandReverse: /* S&~D */
|
|
|
|
ROP_value = 0x2930;
|
|
|
|
break;
|
|
|
|
case GXorReverse: /* S|~D */
|
|
|
|
ROP_value = 0x29f3;
|
|
|
|
break;
|
|
|
|
case GXnand: /* ~(S&D) */
|
|
|
|
ROP_value = 0x293f;
|
|
|
|
break;
|
|
|
|
case GXorInverted: /* ~S|D */
|
|
|
|
ROP_value = 0x29cf;
|
|
|
|
break;
|
|
|
|
case GXor: /* S|D */
|
|
|
|
ROP_value = 0x29fa;
|
|
|
|
break;
|
|
|
|
case GXcopyInverted: /* ~S */
|
|
|
|
ROP_value = 0x290f;
|
|
|
|
break;
|
|
|
|
case GXcopy: /* S */
|
|
|
|
default:
|
|
|
|
ROP_value = 0x29f0;
|
|
|
|
}
|
|
|
|
outw(EGC_MODE, ROP_value);
|
|
|
|
if ( y1 > y0 ) {
|
|
|
|
y_interval = - BYTES_PER_LINE(pWin) * 8 ;
|
|
|
|
src += BYTES_PER_LINE(pWin) * ( h - 1 ) ;
|
|
|
|
dst += BYTES_PER_LINE(pWin) * ( h - 1 ) ;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
y_interval = BYTES_PER_LINE(pWin) * 8 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
src = (unsigned char *)((int)src << 3) ;
|
|
|
|
dst = (unsigned char *)((int)dst << 3) ;
|
|
|
|
|
|
|
|
if ( y1 > y0) {
|
|
|
|
x_direction = 0x1000 ;
|
|
|
|
src += x0 + w - 1 ;
|
|
|
|
dst += x1 + w - 1 ;
|
|
|
|
} else if ( y1 < y0 ) {
|
|
|
|
x_direction = 0 ;
|
|
|
|
src += x0 ;
|
|
|
|
dst += x1 ;
|
|
|
|
} else {
|
|
|
|
if ( x1 < x0 ) {
|
|
|
|
x_direction = 0 ;
|
|
|
|
src += x0 ;
|
|
|
|
dst += x1 ;
|
|
|
|
} else {
|
|
|
|
x_direction = 0x1000 ;
|
|
|
|
src += x0 + w - 1 ;
|
|
|
|
dst += x1 + w - 1 ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
outw ( EGC_LENGTH , w - 1 ) ;
|
|
|
|
|
|
|
|
for ( ; h-- ; ) {
|
|
|
|
if ( x_direction ) {
|
|
|
|
src_off = 15 - (int)src & 0xf ;
|
|
|
|
dst_off = 15 - (int)dst & 0xf ;
|
|
|
|
} else {
|
|
|
|
src_off = (int)src & 0xf ;
|
|
|
|
dst_off = (int)dst & 0xf ;
|
|
|
|
}
|
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
|
|
src_x = (unsigned short *)(((unsigned int)src >> 4 ) << 1) ;
|
|
|
|
dst_x = (unsigned short *)(((unsigned int)dst >> 4 ) << 1) ;
|
|
|
|
#else
|
|
|
|
src_x = (unsigned short *)(((int)src >> 4 ) << 1) ;
|
|
|
|
dst_x = (unsigned short *)(((int)dst >> 4 ) << 1) ;
|
|
|
|
#endif
|
|
|
|
k = ( src_off + w + 15 ) >> 4 ;
|
|
|
|
if ( src_off < dst_off ) {
|
|
|
|
if ( ((src_off + w - 1 ) >> 4) < ((dst_off + w - 1) >> 4)) k++ ;
|
|
|
|
}
|
|
|
|
if ( src_off > dst_off ) {
|
|
|
|
if ( ((src_off + w - 1) >> 4 ) == ((dst_off + w - 1) >> 4) ) k++ ;
|
|
|
|
if ( x_direction ) dst_x ++ ;
|
|
|
|
else dst_x -- ;
|
|
|
|
}
|
|
|
|
outw ( EGC_ADD , x_direction | src_off | dst_off << 4 );
|
|
|
|
if ( x_direction ) {
|
|
|
|
wcopyl ( src_x, dst_x, k, VIDBASE(pWin) ) ;
|
|
|
|
} else {
|
|
|
|
wcopyr ( src_x, dst_x, k, VIDBASE(pWin) ) ;
|
|
|
|
}
|
|
|
|
src += y_interval ;
|
|
|
|
dst += y_interval ;
|
|
|
|
}
|
|
|
|
outw ( EGC_ADD, 0 ) ;
|
|
|
|
outw ( EGC_LENGTH , 0xf );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xf4bppBitBlt( pWin,alu, writeplanes, x0, y0, x1, y1, w, h )
|
|
|
|
WindowPtr pWin; /* GJA */
|
|
|
|
int alu;
|
|
|
|
int writeplanes; /* planes */
|
|
|
|
int x0, y0, x1, y1, w, h;
|
|
|
|
{
|
|
|
|
if ( ! xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->vtSema ) {
|
|
|
|
xf4bppOffBitBlt( pWin, alu, writeplanes,
|
|
|
|
x0, y0, x1, y1, w, h );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( alu ) {
|
|
|
|
case GXclear: /* 0x0 Zero 0 */
|
|
|
|
case GXinvert: /* 0xa NOT dst */
|
|
|
|
case GXset: /* 0xf 1 */
|
|
|
|
xf4bppFillSolid( pWin, VGA_ALLPLANES, alu, writeplanes, x1, y1, w, h ) ;
|
|
|
|
/* x1, y1, GJA */
|
|
|
|
case GXnoop: /* 0x5 dst */
|
|
|
|
return ;
|
|
|
|
default:
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
|
|
|
|
egc_fast_blt ( pWin, alu, writeplanes, x0, y0, x1, y1, w, h);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|