/******************************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; }