Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1551 lines
38 KiB

/******************************Module*Header*******************************\
* Module Name: pointer.c
*
* Copyright (c) 1992-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
//
// This will disable the sync with vertical retrace. Stress tests are failing with v-sync enabled.
//
#define NO_VERTICAL_SYNC
BOOL flag_shape;
BYTE HardWareCursorShape [CURSOR_CX][CURSOR_CY] ;
// BEGIN MACH32 ----------------------------------------------------------------
VOID vI32SetCursorOffset(PDEV *ppdev)
{
BYTE mem;
BYTE bytes_pp;
ULONG vga_mem;
LONG width;
LONG height;
LONG depth;
height = ppdev->ppointer->hwCursor.y;
depth = ppdev->cBitsPerPel;
width = ppdev->lDelta / depth;
mem = (BYTE) I32_IB(ppdev->pjIoBase, MEM_BNDRY);
if(mem&0x10)
{
vga_mem=(ULONG)(mem&0xf);
vga_mem=0x40000*vga_mem; /* vga boundary is enabled */
}
else
{
vga_mem=0;
}
switch(depth)
{
case 32:
bytes_pp=8;
break;
case 24:
bytes_pp=6;
break;
case 16:
bytes_pp=4;
break;
case 8:
bytes_pp=2;
break;
case 4:
bytes_pp=1;
break;
}
ppdev->ppointer->mono_offset = (vga_mem +
((ULONG)height*(ULONG)width*(ULONG)bytes_pp));
#if 0
DbgOut("Height %x\n", height);
DbgOut("Height %x\n", width);
DbgOut("Height %x\n", bytes_pp);
DbgOut("Mono Offset %x\n", ppdev->ppointer->mono_offset);
#endif
}
VOID vI32UpdateCursorOffset(
PDEV *ppdev,
LONG lXOffset,
LONG lYOffset,
LONG lCurOffset)
{
PBYTE pjIoBase = ppdev->pjIoBase;
I32_OW_DIRECT(pjIoBase, CURSOR_OFFSET_HI, 0) ;
I32_OW_DIRECT(pjIoBase, HORZ_CURSOR_OFFSET, (lXOffset & 0xff) | (lYOffset << 8));
I32_OW_DIRECT(pjIoBase, CURSOR_OFFSET_LO, (WORD)lCurOffset) ;
I32_OW_DIRECT(pjIoBase, CURSOR_OFFSET_HI, (lCurOffset >> 16) | 0x8000) ;
}
VOID vI32UpdateCursorPosition(
PDEV *ppdev,
LONG x,
LONG y)
{
PBYTE pjIoBase = ppdev->pjIoBase;
I32_OW_DIRECT(pjIoBase, HORZ_CURSOR_POSN, x); /* set base of cursor to X */
I32_OW_DIRECT(pjIoBase, VERT_CURSOR_POSN, y); /* set base of cursor to Y */
}
VOID vI32CursorOff(PDEV *ppdev)
{
I32_OW_DIRECT(ppdev->pjIoBase, CURSOR_OFFSET_HI, 0);
}
VOID vI32CursorOn(PDEV *ppdev, LONG lCurOffset)
{
I32_OW_DIRECT(ppdev->pjIoBase, CURSOR_OFFSET_HI, (lCurOffset >> 16) | 0x8000) ;
}
VOID vI32PointerBlit(
PDEV* ppdev,
LONG x,
LONG y,
LONG cx,
LONG cy,
PBYTE pbsrc,
LONG lDelta)
{
BYTE* pjIoBase = ppdev->pjIoBase;
WORD wCmd;
WORD wWords;
WORD wPixels;
UINT i;
wWords = (WORD)(cx + 15) / 16;
wPixels = (WORD) (wWords*16L/ppdev->cBitsPerPel);
wCmd = FG_COLOR_SRC_HOST | DRAW | WRITE | DATA_WIDTH | LSB_FIRST;
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7);
I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT);
I32_OW(pjIoBase, DP_CONFIG, wCmd);
I32_OW(pjIoBase, DEST_X_START, LOWORD(x));
I32_OW(pjIoBase, CUR_X, LOWORD(x));
I32_OW(pjIoBase, DEST_X_END, LOWORD(x) + wPixels);
I32_OW(pjIoBase, CUR_Y, LOWORD(y));
I32_OW(pjIoBase, DEST_Y_END, (LOWORD(y) + 1));
for (i=0; i < (UINT) wWords; i++)
{
if (i % 8 == 0)
I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
I32_OW(pjIoBase, PIX_TRANS, *((USHORT UNALIGNED *)pbsrc)++ );
}
}
VOID vPointerBlitLFB(
PDEV* ppdev,
LONG x,
LONG y,
LONG cx,
LONG cy,
PBYTE pbsrc,
LONG lDelta)
{
BYTE* pjDst;
ASSERTDD(ppdev->iBitmapFormat == BMF_24BPP, "BMF should be 24 here\n");
pjDst = ppdev->pjScreen + ppdev->lDelta * y + x * 3;
//
// Set cx equal to number of bytes.
//
cx >>= 3;
while (cy-- > 0)
{
memcpy( pjDst, pbsrc, cx);
pjDst += cx;
pbsrc += lDelta;
}
}
// END MACH32 ------------------------------------------------------------------
// BEGIN MACH64 ----------------------------------------------------------------
BOOLEAN flag_enable=FALSE;
/*
----------------------------------------------------------------------
-- NAME: vDacRegs
--
-- DESCRIPTION:
-- Calculate DAC regsiter I/O locations
--
----------------------------------------------------------------------
*/
_inline VOID vDacRegs(PDEV* ppdev, UCHAR** ucReg, UCHAR** ucCntl)
{
if (ppdev->FeatureFlags & EVN_PACKED_IO)
{
*ucReg = (ppdev->pjIoBase + DAC_REGS*4);
*ucCntl = (ppdev->pjIoBase + DAC_CNTL*4);
}
else
{
*ucReg = (ppdev->pjIoBase + ioDAC_REGS - ioBASE);
*ucCntl = (ppdev->pjIoBase + ioDAC_CNTL - ioBASE);
}
}
VOID vM64SetCursorOffset(PDEV* ppdev)
{
LONG bytes_pp;
LONG width;
LONG height;
LONG depth;
height = ppdev->ppointer->hwCursor.y;
depth = ppdev->cBitsPerPel;
width = ppdev->lDelta / depth;
switch(depth)
{
case 32:
bytes_pp=8;
break;
case 24:
bytes_pp=6;
break;
case 16:
bytes_pp=4;
break;
case 8:
bytes_pp=2;
break;
case 4:
bytes_pp=1;
break;
}
ppdev->ppointer->mono_offset = (ULONG)height*(ULONG)width*(ULONG)bytes_pp;
ppdev->ppointer->mono_offset += ppdev->ulVramOffset*2;
}
VOID vM64UpdateCursorOffset(
PDEV* ppdev,
LONG lXOffset,
LONG lYOffset,
LONG lCurOffset)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ppdev->pfnCursorOff(ppdev);
M64_OD_DIRECT(pjMmBase,CUR_OFFSET, lCurOffset >> 1);
M64_OD_DIRECT(pjMmBase,CUR_HORZ_VERT_OFF, lXOffset | (lYOffset << 16));
ppdev->pfnCursorOn(ppdev, lCurOffset);
}
VOID vM64UpdateCursorPosition(
PDEV* ppdev,
LONG x,
LONG y)
{
M64_OD_DIRECT(ppdev->pjMmBase, CUR_HORZ_VERT_POSN, x | (y << 16));
}
VOID vM64CursorOff(PDEV* ppdev)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ULONG ldata;
#ifndef NO_VERTICAL_SYNC
ULONG ldata1;
// Read the no. of total verticales lines (including the overscan)
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
//read the current verticale line
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
//synchronise the drawing with the vertical line
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
//Disable the hardware cursor
ldata = M64_ID(pjMmBase,GEN_TEST_CNTL);
M64_OD_DIRECT(pjMmBase, GEN_TEST_CNTL, ldata & ~GEN_TEST_CNTL_CursorEna);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64CursorOn(PDEV* ppdev, LONG lCurOffset)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ULONG ldata;
#ifndef NO_VERTICAL_SYNC
ULONG ldata1;
#endif // !NO_VERTICAL_SYNC
if (!flag_enable)
{
flag_enable=TRUE;
ldata = M64_ID(pjMmBase,GEN_TEST_CNTL);
M64_OD_DIRECT(pjMmBase, GEN_TEST_CNTL, ldata | GEN_TEST_CNTL_CursorEna);
}
#ifndef NO_VERTICAL_SYNC
/*
* Read the no. of total vertical lines (including the overscan)
*/
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
/*
* read the current vertical line
*/
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
/*
* Synchronise the drawing of cursor
*/
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
ppdev->pfnUpdateCursorPosition(ppdev,ppdev->ppointer->ptlLastPosition.x+0,ppdev->ppointer->ptlLastPosition.y+0);
ldata = M64_ID(pjMmBase,GEN_TEST_CNTL);
M64_OD_DIRECT(pjMmBase, GEN_TEST_CNTL, ldata | GEN_TEST_CNTL_CursorEna);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64SetCursorOffset_TVP(PDEV* ppdev)
{
}
VOID vM64UpdateCursorOffset_TVP(
PDEV* ppdev,
LONG lXOffset,
LONG lYOffset,
LONG lCurOffset)
{
ppdev->ppointer->ptlLastOffset.x=lXOffset;
ppdev->ppointer->ptlLastOffset.y=lYOffset;
/* Change the offset... used in UpdateCursorPosition */
}
VOID vM64UpdateCursorPosition_TVP(
PDEV* ppdev,
LONG x,
LONG y)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ULONG dacRead;
//DbgOut("\nvUpdateCursorPosition_TVP_M64 called");
ppdev->ppointer->ptlLastPosition.y=y;
ppdev->ppointer->ptlLastPosition.x=x;
// Note: SetCursorOffset, UpdateCursorOffset must set ptlLastOffset
x+= 64-ppdev->ppointer->ptlLastOffset.x;
y+= 64-ppdev->ppointer->ptlLastOffset.y;
// check for coordinate violations
if (x < 0) x = 0;
if (y < 0) y = 0;
dacRead = M64_ID(pjMmBase,DAC_CNTL);
M64_OD_DIRECT(pjMmBase, DAC_CNTL, (dacRead & 0xfffffffc) | 3);
M64_OD_DIRECT(pjMmBase, DAC_REGS+REG_W, (y<<16) | x);
dacRead = M64_ID(pjMmBase,DAC_CNTL);
M64_OD_DIRECT(pjMmBase, DAC_CNTL, dacRead & 0xfffffffc);
}
VOID vM64CursorOff_TVP(PDEV* ppdev)
{
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
// Initialize DAC registers
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
rioOB(ucDacReg+REG_W, 6); // register 6
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 2);
rioOB(ucDacReg+REG_M, 0); // (+Mask) disable
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
}
VOID vM64CursorOn_TVP(PDEV* ppdev, LONG lCurOffset)
{
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
/*
* Initialize DAC registers
*/
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
/*
* Access cursor control register
*/
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
rioOB(ucDacReg+REG_W, 6); // register 6
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 2);
rioOB(ucDacReg+REG_M, 2); // XGA cursor type
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
}
VOID vM64SetCursorOffset_IBM514(PDEV* ppdev)
{
}
VOID vM64UpdateCursorOffset_IBM514(
PDEV* ppdev,
LONG lXOffset,
LONG lYOffset,
LONG lCurOffset)
{
ppdev->ppointer->ptlLastOffset.x=lXOffset ;//-64;
ppdev->ppointer->ptlLastOffset.y=lYOffset ;//-64;
/*
* These two statements have been introduced in order to solve the ghost cursor on IBM Dac cards
*/
ppdev->pfnUpdateCursorPosition(ppdev,ppdev->ppointer->ptlLastPosition.x+0,ppdev->ppointer->ptlLastPosition.y+0);
ppdev->pfnCursorOn(ppdev, lCurOffset);
/* Change the offset... used in UpdateCursorPosition */
}
VOID vM64UpdateCursorPosition_IBM514(
PDEV* ppdev,
LONG x,
LONG y)
{
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
// Initialize DAC registers
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
ppdev->ppointer->ptlLastPosition.y=y;
ppdev->ppointer->ptlLastPosition.x=x;
// Note: SetCursorOffset, UpdateCursorOffset must set ptlLastOffset
x-= ppdev->ppointer->ptlLastOffset.x;
y-= ppdev->ppointer->ptlLastOffset.y;
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc)| 1);
rioOB(ucDacReg+REG_R, 1);
rioOB(ucDacReg+REG_W, 0x31);
rioOB(ucDacReg+REG_D, 0);
rioOB(ucDacReg+REG_M, x&0xFF);
rioOB(ucDacReg+REG_M, (UCHAR)(x>>8));
rioOB(ucDacReg+REG_M, y&0xFF);
rioOB(ucDacReg+REG_M, (UCHAR)(y>>8));
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
}
VOID vM64CursorOff_IBM514(PDEV* ppdev) // DONE
{
BYTE* pjMmBase = ppdev->pjMmBase;
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
#ifndef NO_VERTICAL_SYNC
ULONG ldata;
ULONG ldata1;
/*
* Read the no. of total vertical lines (including the overscan)
*/
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
/*
* Read the current vertical line
*/
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
/*
* Synchronise the drawing with the vertical line
*/
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
/*
* Initialize DAC registers
*/
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc)|1);
rioOB(ucDacReg+REG_R, 1);
rioOB(ucDacReg+REG_W, 0x30);
rioOB(ucDacReg+REG_D, 0); // (+Data)
rioOB(ucDacReg+REG_M, 0); // (+Mask)
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64CursorOn_IBM514(PDEV* ppdev, LONG lCurOffset) //DONE
{
BYTE* pjMmBase = ppdev->pjMmBase;
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
#ifndef NO_VERTICAL_SYNC
ULONG ldata;
ULONG ldata1;
/*
* Read the no. of total vertical lines (including the overscan)
*/
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
/*
* Read the current verticale line
*/
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
/*
* Synchronise the drawing of cursor
*/
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
// Initialize DAC registers
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
// access cursor control register
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 1);
rioOB(ucDacReg+REG_R, 1);
rioOB(ucDacReg+REG_W, 0x30);
rioOB(ucDacReg+REG_D, 0); // register 6
rioOB(ucDacReg+REG_M, 0xE); // register 6
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64UpdateCursorOffset_CT(
PDEV* ppdev,
LONG lXOffset,
LONG lYOffset,
LONG lCurOffset)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ppdev->pfnCursorOff(ppdev);
M64_OD_DIRECT(pjMmBase, CUR_OFFSET, lCurOffset >> 1);
M64_OD_DIRECT(pjMmBase, CUR_HORZ_VERT_OFF, lXOffset | (lYOffset << 16));
ppdev->pfnCursorOn(ppdev, lCurOffset);
}
VOID vM64CursorOff_CT(PDEV* ppdev)
{
BYTE* pjMmBase = ppdev->pjMmBase;
#ifndef NO_VERTICAL_SYNC
ULONG ldata;
ULONG ldata1;
// Read the no. of total verticales lines (including the overscan)
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
//read the current verticale line
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
//synchronise the drawing with the vertical line
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
ppdev->pfnUpdateCursorPosition(ppdev, -1, -1);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64CursorOn_CT(PDEV* ppdev, LONG lCurOffset)
{
BYTE* pjMmBase = ppdev->pjMmBase;
ULONG ldata;
#ifndef NO_VERTICAL_SYNC
ULONG ldata1;
#endif // !NO_VERTICAL_SYNC
if (!flag_enable)
{
flag_enable=TRUE;
ldata = M64_ID(pjMmBase,GEN_TEST_CNTL);
M64_OD_DIRECT(pjMmBase, GEN_TEST_CNTL, ldata | GEN_TEST_CNTL_CursorEna);
}
#ifndef NO_VERTICAL_SYNC
/*
* Read the no. of total vertical lines (including the overscan)
*/
ldata1 = M64_ID(pjMmBase,CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
/*
* read the current vertical line
*/
ldata = M64_ID(pjMmBase,CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
/*
* Synchronise the drawing of cursor
*/
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
ppdev->pfnUpdateCursorPosition(ppdev,ppdev->ppointer->ptlLastPosition.x+0,ppdev->ppointer->ptlLastPosition.y+0);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
}
VOID vM64PointerBlit(
PDEV *ppdev,
LONG x,
LONG y,
LONG cx,
LONG cy,
PBYTE pbsrc,
LONG lDelta)
{
BYTE* pjMmBase = ppdev->pjMmBase;
LONG cxbytes;
cxbytes = cx / 8;
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7);
//M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | ppdev->iDefContext );
M64_OD(pjMmBase,DP_PIX_WIDTH, 0x020202); // assert 8 bpp
M64_OD(pjMmBase,DST_OFF_PITCH,(ppdev->ulVramOffset + ((y*ppdev->lDelta) >> 3)) |
(ROUND8(cxbytes) << 19));
if (cxbytes >= (LONG)ppdev->cxScreen)
{
M64_OD(pjMmBase,SC_RIGHT, cxbytes);
}
M64_OD(pjMmBase,DP_MIX, (OVERPAINT << 16));
M64_OD(pjMmBase,DP_SRC, DP_SRC_Host << 8);
M64_OD(pjMmBase,DST_Y_X, 0L);
M64_OD(pjMmBase,DST_HEIGHT_WIDTH, 1 | (cxbytes << 16));
vM64DataPortOutB(ppdev, pbsrc, cxbytes);
// Fix a timing problem that leaves a remnant line segment in the lower right
// of the 64x64 cursor.
vM64QuietDown(ppdev, pjMmBase);
M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth);
M64_OD(pjMmBase, DST_OFF_PITCH, ppdev->ulScreenOffsetAndPitch);
M64_OD(pjMmBase, SC_RIGHT, M64_MAX_SCISSOR_R);
}
VOID vM64PointerBlit_TVP(
PDEV *ppdev,
LONG x,
LONG y,
LONG cx,
LONG cy,
PBYTE pbsrc,
LONG lDelta)
{
PBYTE cur_data;
ULONG i;
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
// Initialize DAC registers
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
cur_data=pbsrc;
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc); // Disable cursor
rioOB(ucDacReg+REG_W, 6); // register 6
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 2);
rioOB(ucDacReg+REG_M, 0); // (+Mask) disable
// set cursor RAM write address to 0
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
rioOB(ucDacReg+REG_W, 0);
// select cursor RAM data register - auto increments with each write
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 2);
for (i = 0; i < 1024; i++)
{
rioOB(ucDacReg+REG_R, *cur_data++);
}
// select default palette registers
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
rioOB(ucDacReg+REG_W, 6); // register 6
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc) | 2);
rioOB(ucDacReg+REG_M, 2); // XGA cursor type
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
}
VOID vM64PointerBlit_IBM514(
PDEV *ppdev,
LONG x,
LONG y,
LONG cx,
LONG cy,
PBYTE pbsrc,
LONG lDelta)
{
PBYTE cur_data, pjMmBase = ppdev->pjMmBase;
ULONG i;
UCHAR * ucDacReg;
UCHAR * ucDacCntl;
#ifndef NO_VERTICAL_SYNC
ULONG ldata;
ULONG ldata1;
#endif // !NO_VERTICAL_SYNC
// Initialize DAC registers
vDacRegs(ppdev, &ucDacReg, &ucDacCntl);
cur_data=pbsrc;
#ifndef NO_VERTICAL_SYNC
/*
* Read the no. of total vertical lines (including the overscan)
*/
ldata1 = M64_ID(pjMmBase, CRTC_V_TOTAL_DISP);
ldata1 = ldata1&0x7ff;
again:
/*
* Read the current vertical line
*/
ldata = M64_ID(pjMmBase, CRTC_CRNT_VLINE);
ldata = (ldata&0x7ff0000)>>16;
// synchronise the drawing of cursor
if (ldata >= (ldata1-3))
{
#endif // !NO_VERTICAL_SYNC
rioOB(ucDacCntl, (rioIB(ucDacCntl) & 0xfc)|1); // Disable cursor
rioOB(ucDacReg+REG_R, 1);
rioOB(ucDacReg+REG_W, 0);
rioOB(ucDacReg+REG_D, 1);
#ifndef NO_VERTICAL_SYNC
}
else
{
goto again;
}
#endif // !NO_VERTICAL_SYNC
// select cursor RAM data register - auto increments with each write
for (i = 0; i < 1024; i++)
{
rioOB(ucDacReg+REG_M, *cur_data++);
}
/* Set HOT SPOT registers.. RSL Important? */
rioOB(ucDacReg+REG_W, 0x35);
rioOB(ucDacReg+REG_D, 0);
rioOB(ucDacReg+REG_M, 0);
rioOB(ucDacReg+REG_M, 0);
rioOB(ucDacCntl, rioIB(ucDacCntl) & 0xfc);
}
// END MACH64 ------------------------------------------------------------------
/******************************Public*Routine******************************\
* CopyMonoCursor
*
* Copies two monochrome masks into a 2bpp bitmap. Returns TRUE if it
* can make a hardware cursor, FALSE if not.
*
* modified by Wendy Yee -1992-10-16- to accomodate 68800
\**************************************************************************/
BOOLEAN CopyMonoCursor(PDEV *ppdev, BYTE *pjSrcAnd, BYTE *pjSrcOr)
{
BYTE jSrcAnd;
BYTE jSrcOr;
LONG count;
BYTE *pjDest;
BYTE jDest = 0;
LONG nbytes;
pjDest = (PBYTE) HardWareCursorShape;
if ( ppdev->FeatureFlags & EVN_TVP_DAC_CUR)
{
nbytes=CURSOR_CX*CURSOR_CY/8;
for (count = 0; count < nbytes; count++)
{
*(pjDest )= *pjSrcOr; // Gives outline!
*(pjDest+nbytes)= *pjSrcAnd;
pjDest++;
pjSrcOr++;
pjSrcAnd++;
}
for (;count < 512; count++)
{
*pjDest=0;
*(pjDest+nbytes)=0xFF;
}
return(TRUE);
}
for (count = 0; count < (CURSOR_CX * CURSOR_CY);)
{
if (!(count & 0x07)) // need new src byte every 8th count;
{ // each byte = 8 pixels
jSrcAnd = *(pjSrcAnd++);
jSrcOr = *(pjSrcOr++);
}
if (jSrcAnd & 0x80) // AND mask's white-1 background
{
if (jSrcOr & 0x80) // XOR mask's white-1 outline
jDest |= 0xC0; // Complement
else
jDest |= 0x80; // Set destination to Transparent
}
else
{ // AND mask's cursor silhouette in black-0
if (jSrcOr & 0x80)
jDest |= 0x40; // Color 1 - white
else
jDest |= 0x00; // Color 0 - black
}
count++;
if (!(count & 0x3)) // New DestByte every 4 times for 4 pixels per byte
{
*pjDest = jDest; // save pixel after rotating to right 3x
pjDest++;
jDest = 0;
}
else
{
jDest >>= 2; // Next Pixel
}
jSrcOr <<= 1;
jSrcAnd <<= 1;
}
while (count++ < 64*64)
if (!(count & 0x3)) // need new src byte every 8th count;
{ // each byte = 8 pixels
*pjDest =0xaa;
pjDest++;
}
return(TRUE);
}
ULONG lSetMonoHwPointerShape(
SURFOBJ *pso,
SURFOBJ *psoMask,
SURFOBJ *psoColor,
XLATEOBJ *pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL *prcl,
FLONG fl)
{
LONG count;
ULONG cy;
PBYTE pjSrcAnd, pjSrcXor;
LONG lDeltaSrc, lDeltaDst;
LONG lSrcWidthInBytes;
ULONG cxSrc = pso->sizlBitmap.cx;
ULONG cySrc = pso->sizlBitmap.cy;
ULONG cxSrcBytes;
BYTE AndMask[CURSOR_CX][CURSOR_CX/8];
BYTE XorMask[CURSOR_CY][CURSOR_CY/8];
PBYTE pjDstAnd = (PBYTE)AndMask;
PBYTE pjDstXor = (PBYTE)XorMask;
PDEV* ppdev;
PCUROBJ ppointer;
ppdev=(PDEV*)pso->dhpdev;
ppointer = ppdev->ppointer;
// If the mask is NULL this implies the pointer is not
// visible.
if (psoMask == NULL)
{
if (ppointer->flPointer & MONO_POINTER_UP)
{
//DbgOut("\nThe cursor was disabled because of psoMask");
ppdev->pfnCursorOff(ppdev);
ppointer->flPointer &= ~MONO_POINTER_UP;
}
return (SPS_ACCEPT_NOEXCLUDE) ;
}
// Get the bitmap dimensions.
cxSrc = psoMask->sizlBitmap.cx ;
cySrc = psoMask->sizlBitmap.cy ;
// set the dest and mask to 0xff
memset(pjDstAnd, 0xFFFFFFFF, CURSOR_CX/8 * CURSOR_CY);
// Zero the dest XOR mask
memset(pjDstXor, 0, CURSOR_CX/8 * CURSOR_CY);
cxSrcBytes = (cxSrc + 7) / 8;
if ((lDeltaSrc = psoMask->lDelta) < 0)
lSrcWidthInBytes = -lDeltaSrc;
else
lSrcWidthInBytes = lDeltaSrc;
pjSrcAnd = (PBYTE) psoMask->pvScan0;
// Height of just AND mask
cySrc = cySrc / 2;
// Point to XOR mask
pjSrcXor = pjSrcAnd + (cySrc * lDeltaSrc);
// Offset from end of one dest scan to start of next
lDeltaDst = CURSOR_CX/8;
for (cy = 0; cy < cySrc; ++cy)
{
memcpy(pjDstAnd, pjSrcAnd, cxSrcBytes);
memcpy(pjDstXor, pjSrcXor, cxSrcBytes);
// Point to next source and dest scans
pjSrcAnd += lDeltaSrc;
pjSrcXor += lDeltaSrc;
pjDstAnd += lDeltaDst;
pjDstXor += lDeltaDst;
}
if (CopyMonoCursor(ppdev, (PBYTE)AndMask, (PBYTE)XorMask))
{
// Down load the pointer shape to the engine.
count = CURSOR_CX * CURSOR_CY * 2;
if (ppdev->iAsic == ASIC_88800GX)
{
// double buffering used for Ghost EPR
if (!ppdev->bAltPtrActive)
{
ppointer = ppdev->ppointer = &ppdev->pointer1;
ppdev->pointer1.ptlHotSpot = ppdev->pointer2.ptlHotSpot;
ppdev->pointer1.ptlLastPosition= ppdev->pointer2.ptlLastPosition;
ppdev->pointer1.ptlLastOffset = ppdev->pointer2.ptlLastOffset;
ppdev->pointer1.flPointer = ppdev->pointer2.flPointer;
ppdev->pointer1.szlPointer = ppdev->pointer2.szlPointer;
}
else
{
ppointer = ppdev->ppointer = &ppdev->pointer2;
ppdev->pointer2.ptlHotSpot = ppdev->pointer1.ptlHotSpot;
ppdev->pointer2.ptlLastPosition= ppdev->pointer1.ptlLastPosition;
ppdev->pointer2.ptlLastOffset = ppdev->pointer1.ptlLastOffset;
ppdev->pointer2.flPointer = ppdev->pointer1.flPointer;
ppdev->pointer2.szlPointer = ppdev->pointer1.szlPointer;
}
ppdev->bAltPtrActive = !ppdev->bAltPtrActive;
}
ppdev->pfnSetCursorOffset(ppdev);
ppdev->pfnPointerBlit(ppdev,
ppointer->hwCursor.x,
ppointer->hwCursor.y,
count,
1L,
(PBYTE) &HardWareCursorShape,
0L);
}
else
return(SPS_ERROR);
// Set the position of the cursor.
if (fl & SPS_ANIMATEUPDATE)
{
//DbgOut("animate cursor\n");
if ( (ppointer->ptlLastPosition.x < 0) ||
(ppointer->ptlLastPosition.y < 0) )
{
ppointer->ptlLastPosition.x = x - CURSOR_CX;
ppointer->ptlLastPosition.y = y - CURSOR_CY;
}
}
else
{
ppointer->ptlLastPosition.x = -x - 2;
ppointer->ptlLastPosition.y = -y - 2;
// DbgOut("See what last position we set in DrvSetPointerShape: x=%d y=%d\n",ppointer->ptlLastPosition.x,ppointer->ptlLastPosition.y);
}
if (x == -1)
{
ppointer->ptlLastPosition.x = x;
ppointer->ptlLastPosition.y = y;
return (SPS_ACCEPT_NOEXCLUDE) ;
}
//flag for enforcing a special approach from DrvMovePointer
flag_shape=TRUE;
DrvMovePointer(pso, x, y, NULL) ;
if (!(ppointer->flPointer & MONO_POINTER_UP))
{
ppointer->ptlLastPosition.x = x;
ppointer->ptlLastPosition.y = y;
ppdev->pfnCursorOn(ppdev, ppointer->mono_offset);
ppointer->flPointer |= MONO_POINTER_UP;
}
return (SPS_ACCEPT_NOEXCLUDE) ;
}
/******************************Public*Routine******************************\
* VOID DrvSetPointerShape
*
* Sets the new pointer shape.
*
\**************************************************************************/
ULONG DrvSetPointerShape(
SURFOBJ* pso,
SURFOBJ* psoMask,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
ULONG ulRet ;
PDEV* ppdev ;
LONG lX ;
PCUROBJ ppointer;
ppdev=(PDEV*)pso->dhpdev;
ppointer = ppdev->ppointer;
// Save the position and hot spot in pdev
ppointer->ptlHotSpot.x = xHot ;
ppointer->ptlHotSpot.y = yHot ;
ppointer->szlPointer.cx = psoMask->sizlBitmap.cx ;
ppointer->szlPointer.cy = psoMask->sizlBitmap.cy / 2;
// The pointer may be larger than we can handle.
// We don't want to draw colour cursors either - let GDI do it
// If it is we must cleanup the screen and let the engine
// take care of it.
if (psoMask->sizlBitmap.cx > CURSOR_CX ||
psoMask->sizlBitmap.cy > CURSOR_CY ||
psoColor != NULL ||
ppointer->flPointer & NO_HARDWARE_CURSOR)
{
// Disable the mono hardware pointer.
if (ppointer->flPointer & MONO_POINTER_UP)
{
ppdev->pfnCursorOff(ppdev);
ppointer->flPointer &= ~MONO_POINTER_UP;
}
return (SPS_DECLINE);
}
// odd cursor positions not displayed in 1280 mode
lX = x-xHot;
if (ppdev->cxScreen == 0x500)
lX &= 0xfffffffe;
if(ppdev->iAsic == ASIC_88800GX)
{
//disable the hardware cursor
ppdev->pfnCursorOff(ppdev);
#if MULTI_BOARDS
{
OH* poh;
if (x != -1)
{
poh = ((DSURF*) pso->dhsurf)->poh;
x += poh->x;
y += poh->y;
}
}
#endif
}
// Take care of the monochrome pointer.
ulRet = lSetMonoHwPointerShape(pso, psoMask, psoColor, pxlo,
xHot, yHot, x, y, prcl, fl) ;
return (ulRet) ;
}
/******************************Public*Routine******************************\
* VOID DrvMovePointer
*
* NOTE: Because we have set GCAPS_ASYNCMOVE, this call may occur at any
* time, even while we're executing another drawing call!
*
* Consequently, we have to explicitly synchronize any shared
* resources. In our case, since we touch the CRTC register here
* and in the banking code, we synchronize access using a critical
* section.
*
\**************************************************************************/
VOID DrvMovePointer(
SURFOBJ* pso,
LONG x,
LONG y,
RECTL* prcl)
{
PDEV* ppdev ;
PCUROBJ ppointer;
LONG lXOffset, lYOffset;
LONG lCurOffset;
BOOL bUpdatePtr = FALSE;
BOOL bUpdateOffset = FALSE;
ppdev=(PDEV*)pso->dhpdev;
ppointer = ppdev->ppointer;
// If x is -1 then take down the cursor.
if (x == -1)
{
ppointer->ptlLastPosition.x=-1;
ppointer->ptlLastPosition.y=y;
ppdev->pfnCursorOff(ppdev);
ppointer->flPointer &= ~MONO_POINTER_UP;
return;
}
#if MULTI_BOARDS
if (flag_shape!=TRUE)
{
OH* poh;
poh = ((DSURF*) pso->dhsurf)->poh;
x += poh->x;
y += poh->y;
}
#endif
// Adjust the actual pointer position depending upon
// the hot spot.
x -= ppointer->ptlHotSpot.x ;
y -= ppointer->ptlHotSpot.y ;
// odd cursor positions not displayed in 1280 mode
if (ppdev->cxScreen == 0x500)
x &= 0xfffffffe;
// get current offsets
lXOffset = ppointer->ptlLastOffset.x;
lYOffset = ppointer->ptlLastOffset.y;
lCurOffset = ppointer->mono_offset;
/*
;
;Deal with changes in X:
;
*/
if (x!=ppointer->ptlLastPosition.x) /* did our X coordinate change? */
{
bUpdatePtr = TRUE;
if (x<0) /* is cursor negative? */
{
bUpdateOffset = TRUE;
lXOffset = -x; /* reset size of cursor to < original */
x = 0; /* set cursor to origin */
}
else if (ppointer->ptlLastPosition.x<=0)
{
bUpdateOffset = TRUE; /* reset size of cursor to original */
lXOffset = 0;
}
}
/*
;
;Deal with changes in Y
;
*/
if (y!=ppointer->ptlLastPosition.y)
{
bUpdatePtr = TRUE;
if (y<0)
{
// Move start pointer of cursor down and cursor base up to
// compensate. The (-4) is the pitch if the cursor in dwords
bUpdateOffset = TRUE;
lYOffset = -y; /* reset size of cursor to < original */
lCurOffset -= 4*y;
y = 0; /* set base of cursor to Y */
}
else if (ppointer->ptlLastPosition.y<=0)
{
bUpdateOffset = TRUE; /* reset size of cursor to original */
lYOffset = 0;
}
}
if(ppdev->iAsic != ASIC_88800GX)
{
flag_shape=FALSE;
}
if (flag_shape)
{
flag_shape=FALSE;
ppointer->ptlLastPosition.x=x;
ppointer->ptlLastPosition.y=y;
if (bUpdateOffset)
{
ppdev->pfnUpdateCursorOffset(ppdev, lXOffset, lYOffset, lCurOffset);
ppointer->ptlLastOffset.x=lXOffset;
ppointer->ptlLastOffset.y=lYOffset;
ppointer->flPointer |= MONO_POINTER_UP;
}
else
{
if (ppdev->iAsic == ASIC_88800GX)
{
//this is a new statement imposed by double buffering
ppdev->pfnUpdateCursorOffset(ppdev, lXOffset, lYOffset, lCurOffset);
ppointer->flPointer |= MONO_POINTER_UP;
//only for no double buffering
//ppdev->_vCursorOn(ppdev, lCurOffset);
}
}
}
else
{
ppointer->ptlLastPosition.x=x;
ppointer->ptlLastPosition.y=y;
if (bUpdateOffset)
{
ppdev->pfnUpdateCursorOffset(ppdev, lXOffset, lYOffset, lCurOffset);
ppointer->ptlLastOffset.x=lXOffset;
ppointer->ptlLastOffset.y=lYOffset;
ppointer->flPointer |= MONO_POINTER_UP;
}
if (bUpdatePtr)
{
ppdev->pfnUpdateCursorPosition(ppdev, x, y);
}
}
}
/******************************Public*Routine******************************\
* VOID vDisablePointer
*
\**************************************************************************/
VOID vDisablePointer(
PDEV* ppdev)
{
// Nothing to do, really
}
/******************************Public*Routine******************************\
* VOID vAssertModePointer
*
\**************************************************************************/
VOID vAssertModePointer(
PDEV* ppdev,
BOOL bEnable)
{
if (!bEnable)
{
ppdev->pfnCursorOff(ppdev);
ppdev->ppointer->flPointer &= ~MONO_POINTER_UP;
}
else
{
flag_enable = FALSE; // force initial cursor enable
}
}
/******************************Public*Routine******************************\
* BOOL bEnablePointer
*
\**************************************************************************/
BOOL bEnablePointer(
PDEV* ppdev)
{
OH* poh;
ppdev->ppointer = &ppdev->pointer1;
ppdev->bAltPtrActive = FALSE;
// Allocate first buffer
poh = pohAllocate(ppdev, NULL,
ppdev->cxMemory,
(1024+(ppdev->lDelta-1))/ppdev->lDelta,
FLOH_MAKE_PERMANENT);
if (poh != NULL)
{
ppdev->ppointer->hwCursor.x = poh->x;
ppdev->ppointer->hwCursor.y = poh->y;
// Allocate second buffer
poh = pohAllocate(ppdev, NULL,
ppdev->cxMemory,
(1024+(ppdev->lDelta-1))/ppdev->lDelta,
FLOH_MAKE_PERMANENT);
if (poh != NULL)
{
ppdev->pointer2.hwCursor.x = poh->x;
ppdev->pointer2.hwCursor.y = poh->y;
if (ppdev->iMachType == MACH_MM_32 || ppdev->iMachType == MACH_IO_32)
{
ppdev->pfnSetCursorOffset = vI32SetCursorOffset;
ppdev->pfnUpdateCursorOffset = vI32UpdateCursorOffset;
ppdev->pfnUpdateCursorPosition = vI32UpdateCursorPosition;
ppdev->pfnCursorOff = vI32CursorOff;
ppdev->pfnCursorOn = vI32CursorOn;
// 24bpp on mach32 is only available with linear frame buffer.
// vI32PointerBlit can't handle 24bpp.
if (ppdev->iBitmapFormat == BMF_24BPP)
ppdev->pfnPointerBlit = vPointerBlitLFB;
else
ppdev->pfnPointerBlit = vI32PointerBlit;
}
else
{
if (ppdev->FeatureFlags & EVN_TVP_DAC_CUR)
{
/* TVP DAC Hardware Cursor is Buggy in Hardware */
ppdev->pfnSetCursorOffset = vM64SetCursorOffset_TVP;
ppdev->pfnUpdateCursorOffset = vM64UpdateCursorOffset_TVP;
ppdev->pfnUpdateCursorPosition = vM64UpdateCursorPosition_TVP;
ppdev->pfnCursorOff = vM64CursorOff_TVP;
ppdev->pfnCursorOn = vM64CursorOn_TVP;
ppdev->pfnPointerBlit = vM64PointerBlit_TVP;
}
else if (ppdev->FeatureFlags & EVN_IBM514_DAC_CUR)
{
/*
* On the DEC Alpha, the hardware cursor on the IBM 514
* DAC does not work properly.
*/
#if defined(ALPHA)
ppdev->ppointer->flPointer |= NO_HARDWARE_CURSOR;
#endif
ppdev->pfnSetCursorOffset = vM64SetCursorOffset_IBM514;
ppdev->pfnUpdateCursorOffset = vM64UpdateCursorOffset_IBM514;
ppdev->pfnUpdateCursorPosition = vM64UpdateCursorPosition_IBM514;
ppdev->pfnCursorOff = vM64CursorOff_IBM514;
ppdev->pfnCursorOn = vM64CursorOn_IBM514;
ppdev->pfnPointerBlit = vM64PointerBlit_IBM514;
}
else if (ppdev->FeatureFlags & EVN_INT_DAC_CUR)
{
ppdev->pfnSetCursorOffset = vM64SetCursorOffset;
ppdev->pfnUpdateCursorOffset = vM64UpdateCursorOffset_CT;
ppdev->pfnUpdateCursorPosition = vM64UpdateCursorPosition;
ppdev->pfnCursorOff = vM64CursorOff_CT;
ppdev->pfnCursorOn = vM64CursorOn_CT;
ppdev->pfnPointerBlit = vM64PointerBlit;
}
else
{
ppdev->pfnSetCursorOffset = vM64SetCursorOffset;
ppdev->pfnUpdateCursorOffset = vM64UpdateCursorOffset;
ppdev->pfnUpdateCursorPosition = vM64UpdateCursorPosition;
ppdev->pfnCursorOff = vM64CursorOff;
ppdev->pfnCursorOn = vM64CursorOn;
ppdev->pfnPointerBlit = vM64PointerBlit;
}
}
if (ppdev->pModeInfo->ModeFlags & AMI_ODD_EVEN ||
ppdev->iAsic == ASIC_38800_1)
{
ppdev->ppointer->flPointer |= NO_HARDWARE_CURSOR;
}
return TRUE;
}
}
ppdev->ppointer->flPointer |= NO_HARDWARE_CURSOR;
return TRUE;
}