#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf4bpp.h"
#include "OScompiler.h"
#include "vgaReg.h"
#include "vgaVideo.h"
#include "xf86str.h"
extern ScrnInfoPtr *xf86Screens;
#ifndef PC98_EGC
#define WORDSZ 8
#define HIGHPLANEMASK 0x08
#define HIGHPLANEINDEX 3
#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)
#define WSHIFT8 0x3
#define WMASK8 0x07
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
#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;
int alu;
int writeplanes;
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;
if ( ((x0 - x1) & 0x7) || (alu != GXcopy) ) {
SetVideoGraphics(Enb_Set_ResetIndex, 0);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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);
}
}
static void
shift(pWin,x0,x1,y0,y1,w,h,alu)
WindowPtr pWin;
int x0;
int x1;
int y0;
int y1;
int w;
int h;
int alu;
{
if ( ((x1 & WMASK) + w) <= WORDSZ ) {
shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu);
} else if ( x1 > x0 ) {
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
if ( r1 )
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 )
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
} else {
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
if ( l1 )
shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
shift_center(pWin,x0,x1,y0,y1,w,h,alu);
if ( r1 )
shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
}
}
static void
shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu)
WindowPtr pWin;
int x0;
int x1;
int y0;
int y1;
int w;
int h;
int alu;
{
int l0 = x0 & WMASK;
int l1 = x1 & WMASK;
int L0 = x0 >> WSHIFT;
int L1 = x1 >> WSHIFT;
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 ) {
pad = - BYTES_PER_LINE(pWin);
sp = SMEM(L0,y0+h-1);
dp = DMEM(L1,y1+h-1);
} else {
pad = BYTES_PER_LINE(pWin);
sp = SMEM(L0,y0);
dp = DMEM(L1,y1);
}
if ( l0+w > WORDSZ ) {
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 ) {
for ( htmp = h ; htmp ; htmp-- ) {
tmp = (sp[0] >> bs);
DO_ALU(dp[0],tmp,mask,alu);
dp += pad;
sp += pad;
}
} else {
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;
int x0;
int x1;
int y0;
int y1;
int w;
int h;
int alu;
{
int l1 = x1 & WMASK;
int r1 = (x1 + w) & WMASK;
int pad;
int htmp, wtmp;
volatile unsigned char tmp;
int bs;
int rem;
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 ) {
if ( x1 > x0 ) {
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 {
pad = - BYTES_PER_LINE(pWin) - bytecnt;
sp += BYTES_PER_LINE(pWin) * (h - 1);
dp += BYTES_PER_LINE(pWin) * (h - 1);
}
} else {
if ( x1 > x0 ) {
pad = BYTES_PER_LINE(pWin) + bytecnt;
sp += bytecnt - 1;
dp += bytecnt - 1;
} else {
pad = BYTES_PER_LINE(pWin) - bytecnt;
sp += 0;
dp += 0;
}
}
if ( x1 > x0 ) {
if ( bs == 0 ) {
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 {
if ( bs == 0 ) {
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;
}
}
}
}
static void
aligned_blit(pWin,x0,x1,y0,y1,w,h,alu,planes)
WindowPtr pWin;
int x0;
int x1;
int y0;
int y1;
int w;
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);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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 ) {
int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
if ( r1 ) {
SetVideoGraphics(Enb_Set_ResetIndex, 0);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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);
}
}
}
SetVideoGraphics(Graphics_ModeIndex, 1);
SetVideoSequencer(Mask_MapIndex, planes);
aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
if ( l1 ) {
SetVideoGraphics(Enb_Set_ResetIndex, 0);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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 ) {
SetVideoGraphics(Enb_Set_ResetIndex, 0);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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);
}
}
}
SetVideoGraphics(Graphics_ModeIndex, 1);
SetVideoSequencer(Mask_MapIndex, planes);
aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
if ( r1 ) {
SetVideoGraphics(Enb_Set_ResetIndex, 0);
SetVideoGraphics(Bit_MaskIndex, 0xFF);
SetVideoGraphics(Graphics_ModeIndex, 0);
SetVideoGraphics(Data_RotateIndex, 0);
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;
int x0;
int x1;
int y0;
int y1;
int w;
int h;
{
int l1 = x1 & WMASK;
int r1 = (x1 + w) & WMASK;
int pad;
int htmp, wtmp;
volatile unsigned char tmp;
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 ) {
if ( x1 > x0 ) {
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 {
pad = - BYTES_PER_LINE(pWin) - bytecnt;
sp += BYTES_PER_LINE(pWin) * (h - 1);
dp += BYTES_PER_LINE(pWin) * (h - 1);
}
} else {
if ( x1 > x0 ) {
pad = BYTES_PER_LINE(pWin) + bytecnt;
sp += bytecnt - 1;
dp += bytecnt - 1;
} else {
pad = BYTES_PER_LINE(pWin) - bytecnt;
sp += 0;
dp += 0;
}
}
if ( x1 > x0 ) {
for ( htmp = h ; htmp ; htmp-- ) {
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
tmp = sp[0];
dp[0] = tmp;
dp--;
sp--;
}
dp += pad;
sp += pad;
}
} else {
for ( htmp = h ; htmp ; htmp-- ) {
for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
tmp = sp[0];
dp[0] = tmp;
dp++;
sp++;
}
dp += pad;
sp += pad;
}
}
}
#else
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);
outw(EGC_PLANE, ~(writeplanes & VGA_ALLPLANES));
switch(alu) {
case GXnor:
ROP_value = 0x2903;
break;
case GXandInverted:
ROP_value = 0x290c;
break;
case GXand:
ROP_value = 0x29c0;
break;
case GXequiv:
ROP_value = 0x29c3;
break;
case GXxor:
ROP_value = 0x293c;
break;
case GXandReverse:
ROP_value = 0x2930;
break;
case GXorReverse:
ROP_value = 0x29f3;
break;
case GXnand:
ROP_value = 0x293f;
break;
case GXorInverted:
ROP_value = 0x29cf;
break;
case GXor:
ROP_value = 0x29fa;
break;
case GXcopyInverted:
ROP_value = 0x290f;
break;
case GXcopy:
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;
int alu;
int writeplanes;
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:
case GXinvert:
case GXset:
xf4bppFillSolid( pWin, VGA_ALLPLANES, alu, writeplanes, x1, y1, w, h ) ;
case GXnoop:
return ;
default:
break ;
}
egc_fast_blt ( pWin, alu, writeplanes, x0, y0, x1, y1, w, h);
return;
}
#endif