mirror of https://github.com/lianthony/NT4.0
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.
852 lines
26 KiB
852 lines
26 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: pointer.c *
|
|
* *
|
|
* This module contains the pointer support for the framebuffer *
|
|
* *
|
|
* Copyright (c) 1992 Microsoft Corporation *
|
|
* Copyright (c) 1995 IBM Corporation *
|
|
\**************************************************************************/
|
|
|
|
#include "driver.h"
|
|
#include "hw.h"
|
|
|
|
// Look-up table for masking the right edge of the given pointer bitmap:
|
|
|
|
BYTE gajMask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
|
|
|
|
//
|
|
// external functions
|
|
//
|
|
BOOL bIntersect (
|
|
RECTL *prcl1,
|
|
RECTL *prcl2,
|
|
RECTL *prclResult );
|
|
|
|
//
|
|
// function prototypes
|
|
//
|
|
VOID vShowHwPointer (
|
|
BOOL bShow );
|
|
|
|
BOOL bSetHwPointerShape (
|
|
SURFOBJ *pso,
|
|
SURFOBJ *psoMask,
|
|
SURFOBJ *psoColor,
|
|
XLATEOBJ *pxlo,
|
|
LONG x,
|
|
LONG y,
|
|
FLONG fl );
|
|
|
|
VOID vShowSimPointer (
|
|
PPDEV ppdev,
|
|
SURFOBJ *pso,
|
|
RECTL *prcl,
|
|
BOOL bShow );
|
|
|
|
BOOL bSetSimPointerShape (
|
|
SURFOBJ *pso,
|
|
SURFOBJ *psoMask,
|
|
SURFOBJ *psoColor,
|
|
XLATEOBJ *pxlo,
|
|
LONG x,
|
|
LONG y,
|
|
FLONG fl );
|
|
|
|
VOID vHwSaveScreen (
|
|
PPDEV ppdev,
|
|
RECTL *prclSrc,
|
|
ULONG ulDst );
|
|
|
|
VOID vHwRestoreScreen (
|
|
PPDEV ppdev,
|
|
RECTL *prclDst,
|
|
ULONG ulSrc );
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vShowHwPointer
|
|
*
|
|
* Turns on or off the hardware pointer
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vShowHwPointer (
|
|
BOOL bShow )
|
|
|
|
{
|
|
OUTPW(EPR_INDEX, SELECT_CUR | DISABLE_INC); // select H/W pointer registers
|
|
if (bShow) {
|
|
OUTPW(EPR_DATA, INPW(EPR_DATA) | CUR_ENABLE); // enable H/W pointer
|
|
} else {
|
|
OUTPW(EPR_DATA, INPW(EPR_DATA) & ~CUR_ENABLE); // disable H/W pointer
|
|
} /* endif */
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bSetHwPointerShape
|
|
*
|
|
* Changes the shape of the hardware pointer.
|
|
*
|
|
* Returns: TRUE if successful, FALSE if pointer shape can't be handled.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bSetHwPointerShape (
|
|
SURFOBJ *pso,
|
|
SURFOBJ *psoMask,
|
|
SURFOBJ *psoColor,
|
|
XLATEOBJ *pxlo,
|
|
LONG x,
|
|
LONG y,
|
|
FLONG fl )
|
|
|
|
{
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes;
|
|
LONG dx, dy;
|
|
ULONG cx, cy;
|
|
ULONG cxSrc, cySrc, cxSrcBytes, cxSrcFraction;
|
|
ULONG cxDst, cyDst, cxDstBytes;
|
|
LONG lDeltaSrc, lDeltaDst;
|
|
ULONG ulOffset;
|
|
PUSHORT pusPointerPattern;
|
|
PUSHORT pusDst;
|
|
PBYTE pjSrcAnd, pjSrcXor, pjSA, pjSX;
|
|
|
|
//
|
|
// Check if new pointer is monochrome or not
|
|
//
|
|
if ((psoColor != (SURFOBJ *) NULL) ||
|
|
(!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER))) {
|
|
return FALSE;
|
|
} /* endif */
|
|
|
|
//
|
|
// Check if the size of new pointer is smaller than hardware capability
|
|
//
|
|
cxSrc = psoMask->sizlBitmap.cx;
|
|
cySrc = psoMask->sizlBitmap.cy >> 1;
|
|
cxSrcBytes = (cxSrc + 7) / 8;
|
|
cxSrcFraction = cxSrc % 8; // Number of fractional pels
|
|
|
|
cxDst = ppdev->PointerCapabilities.MaxWidth;
|
|
cyDst = ppdev->PointerCapabilities.MaxHeight;
|
|
cxDstBytes = (cxDst + 7) / 8;
|
|
|
|
if ((cxSrc > cxDst) ||
|
|
(cySrc > cyDst) ||
|
|
(!(psoMask->fjBitmap & BMF_TOPDOWN))) {
|
|
return FALSE;
|
|
} /* endif */
|
|
|
|
//
|
|
// Update the attributes of pointer
|
|
//
|
|
pPointerAttributes->Flags |= VIDEO_MODE_MONO_POINTER;
|
|
pPointerAttributes->Flags &= ~VIDEO_MODE_COLOR_POINTER;
|
|
pPointerAttributes->Width = cxSrc;
|
|
pPointerAttributes->Height = cySrc;
|
|
pPointerAttributes->WidthInBytes = cxSrcBytes;
|
|
|
|
//
|
|
// Set entire pointer pattern area as transparent
|
|
//
|
|
// Before accessing to the off-screen memory, wait for a while until on-going
|
|
// BITBLT completes.
|
|
//
|
|
ulOffset = ppdev->cyScreen * ppdev->lDeltaScreen;
|
|
ulOffset += 64; // skip over solid color pattern used in bitblt.c
|
|
pusPointerPattern = (PUSHORT)(ppdev->pjScreen + ulOffset);
|
|
|
|
WAIT_BLT_COMPLETE(); // wait for BITBLT completion
|
|
|
|
pusDst = pusPointerPattern;
|
|
for (cy = 0; cy < cyDst; cy++) {
|
|
for (cx = 0; cx < cxDstBytes; cx++) {
|
|
*pusDst++ = 0x00FF;
|
|
} /* endfor */
|
|
} /* endfor */
|
|
|
|
//
|
|
// Load new pointer pattern in the off-screen memory
|
|
//
|
|
pjSrcAnd = psoMask->pvBits;
|
|
pjSrcXor = pjSrcAnd + cySrc * (ULONG) psoMask->lDelta;
|
|
lDeltaSrc = psoMask->lDelta;
|
|
lDeltaDst = cxDstBytes;
|
|
|
|
for (cy = 0; cy < cySrc; cy++) {
|
|
pusDst = pusPointerPattern;
|
|
pjSA = pjSrcAnd;
|
|
pjSX = pjSrcXor;
|
|
|
|
//
|
|
// Interleave AND and XOR bytes
|
|
//
|
|
for (cx = 0; cx < (cxSrcBytes - 1); cx++) {
|
|
*pusDst++ = ( (*pjSA++ & 0x00ff) |
|
|
((*pjSX++ & 0x00ff) << 8));
|
|
} /* endfor */
|
|
|
|
//
|
|
// Mask off the right edge if bitmap width is not a multiple of 8
|
|
//
|
|
*pusDst++ = ( (*pjSA++ | gajMask[cxSrcFraction]) |
|
|
((*pjSX++ & ~gajMask[cxSrcFraction]) << 8));
|
|
|
|
pusPointerPattern += lDeltaDst;
|
|
pjSrcAnd += lDeltaSrc;
|
|
pjSrcXor += lDeltaSrc;
|
|
} /* endfor */
|
|
|
|
//
|
|
// Set hardware cursor registers
|
|
//
|
|
dx = ppdev->ptlHotSpot.x;
|
|
dy = ppdev->ptlHotSpot.y;
|
|
|
|
OUTPW(EPR_INDEX, SELECT_CUR | DISABLE_INC); // select H/W pointer registers
|
|
OUTPW(EPR_DATA, CUR_ORIGIN | (USHORT)((dy << 6) | dx));
|
|
OUTPW(EPR_DATA, CUR_PAT_LO | (USHORT)(ulOffset >> 2) & 0x0FFF);
|
|
OUTPW(EPR_DATA, CUR_PAT_HI | (USHORT)(ulOffset >> 14) & 0x00FF);
|
|
OUTPW(EPR_DATA, CUR_PRI_CLR | 0xFF);
|
|
OUTPW(EPR_DATA, CUR_SEC_CLR | 0);
|
|
OUTPW(EPR_DATA, INPW(EPR_DATA) | 0x0220);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vShowSimPointer
|
|
*
|
|
* Show or hide the simulation pointer
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vShowSimPointer (
|
|
PPDEV ppdev,
|
|
SURFOBJ *pso,
|
|
RECTL *prcl,
|
|
BOOL bShow )
|
|
|
|
{
|
|
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes;
|
|
RECTL rclScreen, rclPointer;
|
|
POINTL ptlPointerOffset;
|
|
ULONG ulOffset;
|
|
BOOL b;
|
|
SURFOBJ *psoMask;
|
|
SURFOBJ *psoColor;
|
|
|
|
ulOffset = ppdev->cyScreen * ppdev->lDeltaScreen;
|
|
ulOffset += 64; // skip over solid color pattern used in bitblt.c
|
|
ulOffset += 1024; // skip over hardware pointer bitmap
|
|
|
|
if (bShow) {
|
|
rclScreen.top = 0;
|
|
rclScreen.bottom = ppdev->cyScreen;
|
|
rclScreen.left = 0;
|
|
rclScreen.right = ppdev->cxScreen;
|
|
|
|
rclPointer.top = pPointerAttributes->Row - ppdev->ptlHotSpot.y;
|
|
rclPointer.bottom = rclPointer.top + pPointerAttributes->Height;
|
|
rclPointer.left = pPointerAttributes->Column - ppdev->ptlHotSpot.x;
|
|
rclPointer.right = rclPointer.left + pPointerAttributes->Width;
|
|
|
|
//
|
|
// Trim down the simulation cursor beyond the screen
|
|
//
|
|
if (bIntersect(&rclScreen, &rclPointer, &ppdev->rclPrevPointer)) {
|
|
|
|
prcl->top = ppdev->rclPrevPointer.top;
|
|
prcl->bottom = ppdev->rclPrevPointer.bottom;
|
|
prcl->left = ppdev->rclPrevPointer.left;
|
|
prcl->right = ppdev->rclPrevPointer.right;
|
|
|
|
ptlPointerOffset.x = (rclPointer.left >= 0) ? 0 : (rclPointer.left * (-1));
|
|
ptlPointerOffset.y = (rclPointer.top >= 0) ? 0 : (rclPointer.top * (-1));
|
|
|
|
//
|
|
// Save the screen image where the pointer affects
|
|
//
|
|
vHwSaveScreen(ppdev, &ppdev->rclPrevPointer, ulOffset);
|
|
|
|
//
|
|
// Draw the pointer
|
|
//
|
|
// Note: Clipping the transparent portion of pointer is required for
|
|
// better performance.
|
|
//
|
|
if ((pso != NULL) && (pso->iType == STYPE_DEVICE))
|
|
pso = (SURFOBJ *)(((PPDEV)(pso->dhpdev))->pSurfObj);
|
|
|
|
psoMask = EngLockSurface(ppdev->hsurfMask);
|
|
psoColor = EngLockSurface(ppdev->hsurfColor);
|
|
|
|
b = EngBitBlt(pso, // Target surface
|
|
psoColor, // Source surface
|
|
psoMask, // Mask
|
|
(CLIPOBJ *) NULL, // Clip through this
|
|
(XLATEOBJ *) NULL, // Color translation
|
|
prcl, // Target offset and extent
|
|
&ptlPointerOffset, // Source offset
|
|
&ptlPointerOffset, // Mask offset
|
|
(BRUSHOBJ *) NULL, // Brush data (from cbRealizeBrush)
|
|
(POINTL *) NULL, // Brush offset (origin)
|
|
0x0000CC66); // Raster operation
|
|
|
|
EngUnlockSurface(psoMask);
|
|
EngUnlockSurface(psoColor);
|
|
|
|
} else {
|
|
|
|
//
|
|
// The entire pointer is outside of screen
|
|
//
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
} /* endif */
|
|
} else {
|
|
|
|
//
|
|
// Restore the screen image corrupted by the simulation pointer
|
|
//
|
|
vHwRestoreScreen(ppdev, &ppdev->rclPrevPointer, ulOffset);
|
|
|
|
} /* endif */
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bSetSimPointerShape
|
|
*
|
|
* Changes the shape of the simulation pointer.
|
|
*
|
|
* Returns: TRUE if successful, FALSE if pointer shape can't be simulated.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bSetSimPointerShape (
|
|
SURFOBJ *pso,
|
|
SURFOBJ *psoMask,
|
|
SURFOBJ *psoColor,
|
|
XLATEOBJ *pxlo,
|
|
LONG x,
|
|
LONG y,
|
|
FLONG fl )
|
|
|
|
{
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes;
|
|
ULONG cxSrc, cySrc, cxSrcBytes;
|
|
ULONG ulOffset;
|
|
HSURF hsurf;
|
|
SIZEL sizl;
|
|
ULONG ulBitmapType;
|
|
FLONG flBitmap;
|
|
SURFOBJ *psoSrc;
|
|
SURFOBJ *psoDst;
|
|
RECTL prclDst;
|
|
POINTL pptlSrc;
|
|
XLATEOBJ xlo;
|
|
ULONG ulXlate[2];
|
|
|
|
if (!(ppdev->flCaps & CAPS_NEED_SW_POINTER)) {
|
|
return FALSE;
|
|
} /* endif */
|
|
|
|
//
|
|
// Check if we have enough off-screen memory to hold the screen image underneath
|
|
// the new pointer
|
|
//
|
|
cxSrc = psoMask->sizlBitmap.cx;
|
|
cySrc = psoMask->sizlBitmap.cy >> 1;
|
|
cxSrcBytes = (cxSrc + 7) / 8;
|
|
|
|
ulOffset = ppdev->cyScreen * ppdev->lDeltaScreen;
|
|
ulOffset += 64; // skip over solid color pattern used in bitblt.c
|
|
ulOffset += 1024; // skip over hardware pointer bitmap
|
|
|
|
if ((ppdev->cScreenSize < ulOffset + cxSrc * cySrc * (ppdev->ulBitCount/8)) ||
|
|
(psoMask->iType & STYPE_BITMAP) ||
|
|
(!(psoMask->fjBitmap & BMF_TOPDOWN))) {
|
|
return FALSE;
|
|
} /* endif */
|
|
|
|
//
|
|
// Update the attributes of pointer
|
|
//
|
|
pPointerAttributes->Width = cxSrc;
|
|
pPointerAttributes->Height = cySrc;
|
|
pPointerAttributes->WidthInBytes = cxSrcBytes;
|
|
|
|
//
|
|
// Discard the old pointer
|
|
//
|
|
if (ppdev->hsurfMask != NULL) {
|
|
EngDeleteSurface(ppdev->hsurfMask);
|
|
EngDeleteSurface(ppdev->hsurfColor);
|
|
} /* endif */
|
|
|
|
//
|
|
// Create a copy of mask bitmap
|
|
//
|
|
sizl.cx = cxSrc;
|
|
sizl.cy = cySrc;
|
|
flBitmap = BMF_TOPDOWN;
|
|
prclDst.top = 0;
|
|
prclDst.bottom = cySrc;
|
|
prclDst.left = 0;
|
|
prclDst.right = cxSrc;
|
|
|
|
psoSrc = psoMask;
|
|
ulBitmapType = BMF_1BPP;
|
|
pptlSrc.x = 0;
|
|
pptlSrc.y = 0;
|
|
|
|
if (NULL == (hsurf = (HSURF) EngCreateBitmap(sizl,
|
|
0, // Let GDI choose ulWidth
|
|
ulBitmapType,
|
|
flBitmap,
|
|
NULL))) { // Let GDI allocate
|
|
return FALSE;
|
|
} else {
|
|
ppdev->hsurfMask = hsurf;
|
|
} /* endif */
|
|
|
|
psoDst = EngLockSurface(ppdev->hsurfMask);
|
|
if (!EngCopyBits(psoDst, // Target surface
|
|
psoSrc, // Source surface
|
|
(CLIPOBJ *) NULL, // Clip through this
|
|
(XLATEOBJ *) NULL, // Color translation
|
|
&prclDst, // Target offset and extent
|
|
&pptlSrc)) { // Source offset
|
|
EngDeleteSurface(ppdev->hsurfMask);
|
|
return FALSE;
|
|
} /* endif */
|
|
EngUnlockSurface(psoDst);
|
|
|
|
//
|
|
// Create a copy of pointer bitmap
|
|
//
|
|
ulBitmapType = pso->iBitmapFormat;
|
|
|
|
if (psoColor == (SURFOBJ *) NULL) {
|
|
|
|
//
|
|
// Use second half of mask bitmap if it is monochrome
|
|
//
|
|
pPointerAttributes->Flags |= VIDEO_MODE_MONO_POINTER;
|
|
pPointerAttributes->Flags &= ~VIDEO_MODE_COLOR_POINTER;
|
|
psoSrc = psoMask;
|
|
pptlSrc.x = 0;
|
|
pptlSrc.y = cySrc;
|
|
|
|
//
|
|
// Create the translation table for monochrome-to-color conversion
|
|
//
|
|
pxlo = &xlo;
|
|
xlo.iUniq = 0;
|
|
xlo.flXlate = XO_TABLE;
|
|
xlo.iSrcType = PAL_INDEXED;
|
|
xlo.iDstType = (ppdev->ulBitCount == 8) ? PAL_INDEXED : PAL_RGB;
|
|
xlo.cEntries = 2;
|
|
xlo.pulXlate = (ULONG *)ulXlate;
|
|
ulXlate[0] = 0x00000000; // Black
|
|
ulXlate[1] = (ppdev->ulBitCount == 8) ? 0x000000FF : 0x00FFFFFF; // White
|
|
|
|
} else {
|
|
|
|
pPointerAttributes->Flags &= ~VIDEO_MODE_MONO_POINTER;
|
|
pPointerAttributes->Flags |= VIDEO_MODE_COLOR_POINTER;
|
|
psoSrc = psoColor;
|
|
pptlSrc.x = 0;
|
|
pptlSrc.y = 0;
|
|
|
|
} /* endif */
|
|
|
|
if (NULL == (hsurf = (HSURF) EngCreateBitmap(sizl,
|
|
0, // Let GDI choose ulWidth
|
|
ulBitmapType,
|
|
flBitmap,
|
|
NULL))) { // Let GDI allocate
|
|
EngDeleteSurface(ppdev->hsurfMask);
|
|
return FALSE;
|
|
} else {
|
|
ppdev->hsurfColor = hsurf;
|
|
} /* endif */
|
|
|
|
psoDst = EngLockSurface(ppdev->hsurfColor);
|
|
if (!EngCopyBits(psoDst, // Target surface
|
|
psoSrc, // Source surface
|
|
(CLIPOBJ *) NULL, // Clip through this
|
|
pxlo, // Color translation
|
|
&prclDst, // Target offset and extent
|
|
&pptlSrc)) { // Source offset
|
|
EngDeleteSurface(ppdev->hsurfMask);
|
|
EngDeleteSurface(ppdev->hsurfColor);
|
|
return FALSE;
|
|
} /* endif */
|
|
EngUnlockSurface(psoDst);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vHwSaveScreen
|
|
*
|
|
* Save screen image to off-screen memory using WD hardware accelerator
|
|
*
|
|
\**************************************************************************/
|
|
VOID vHwSaveScreen (
|
|
PPDEV ppdev,
|
|
RECTL *prclSrc,
|
|
ULONG ulDst )
|
|
|
|
{
|
|
ULONG source, target, direction, width, height;
|
|
|
|
//
|
|
// Copy the screen image inside the rectangle to the off-screen memory in linear
|
|
//
|
|
width = prclSrc->right - prclSrc->left;
|
|
height = prclSrc->bottom - prclSrc->top;
|
|
|
|
direction = 0; // Start BITBLT at top left corner of rectangle
|
|
source = prclSrc->top * ppdev->lDeltaScreen + prclSrc->left;
|
|
target = ulDst;
|
|
|
|
//
|
|
// Adjust start address if 16bpp mode
|
|
//
|
|
if (ppdev->ulBitCount == 16) {
|
|
source += prclSrc->left;
|
|
width *= 2;
|
|
} /* endif */
|
|
|
|
WAIT_BLT_COMPLETE(); // wait for BITBLT completion
|
|
|
|
OUTPW(EPR_DATA, BLT_CTRL2 | 0);
|
|
OUTPW(EPR_DATA, BLT_SRC_LO | (USHORT)( source & 0x0FFF));
|
|
OUTPW(EPR_DATA, BLT_SRC_HI | (USHORT)((source >> 12) & 0x01FF));
|
|
OUTPW(EPR_DATA, BLT_DST_LO | (USHORT)( target & 0x0FFF));
|
|
OUTPW(EPR_DATA, BLT_DST_HI | (USHORT)((target >> 12) & 0x01FF));
|
|
OUTPW(EPR_DATA, BLT_SIZE_X | (USHORT)width);
|
|
OUTPW(EPR_DATA, BLT_SIZE_Y | (USHORT)height);
|
|
OUTPW(EPR_DATA, BLT_DELTA | (USHORT)ppdev->lDeltaScreen);
|
|
OUTPW(EPR_DATA, BLT_ROPS | 0x0300); // source copy operation
|
|
OUTPW(EPR_DATA, BLT_PLANE | 0x00FF); // enable all planes
|
|
OUTPW(EPR_DATA, BLT_CTRL1 | 0x0980 | (USHORT)direction ); // start BITBLT
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vHwRestoreScreen
|
|
*
|
|
* Restore screen image from off-screen memory using WD hardware accelerator
|
|
*
|
|
\**************************************************************************/
|
|
VOID vHwRestoreScreen (
|
|
PPDEV ppdev,
|
|
RECTL *prclDst,
|
|
ULONG ulSrc )
|
|
|
|
{
|
|
ULONG source, target, direction, width, height;
|
|
|
|
//
|
|
// Retrieve the screen image from the off-screen memory
|
|
//
|
|
width = prclDst->right - prclDst->left;
|
|
height = prclDst->bottom - prclDst->top;
|
|
|
|
direction = 0; // Start BITBLT at top left corner of rectangle
|
|
source = ulSrc;
|
|
target = prclDst->top * ppdev->lDeltaScreen + prclDst->left;
|
|
|
|
//
|
|
// Adjust start address if 16bpp mode
|
|
//
|
|
if (ppdev->ulBitCount == 16) {
|
|
target += prclDst->left;
|
|
width *= 2;
|
|
} /* endif */
|
|
|
|
WAIT_BLT_COMPLETE(); // wait for BITBLT completion
|
|
|
|
OUTPW(EPR_DATA, BLT_CTRL2 | 0);
|
|
OUTPW(EPR_DATA, BLT_SRC_LO | (USHORT)( source & 0x0FFF));
|
|
OUTPW(EPR_DATA, BLT_SRC_HI | (USHORT)((source >> 12) & 0x01FF));
|
|
OUTPW(EPR_DATA, BLT_DST_LO | (USHORT)( target & 0x0FFF));
|
|
OUTPW(EPR_DATA, BLT_DST_HI | (USHORT)((target >> 12) & 0x01FF));
|
|
OUTPW(EPR_DATA, BLT_SIZE_X | (USHORT)width);
|
|
OUTPW(EPR_DATA, BLT_SIZE_Y | (USHORT)height);
|
|
OUTPW(EPR_DATA, BLT_DELTA | (USHORT)ppdev->lDeltaScreen);
|
|
OUTPW(EPR_DATA, BLT_ROPS | 0x0300); // source copy operation
|
|
OUTPW(EPR_DATA, BLT_PLANE | 0x00FF); // enable all planes
|
|
OUTPW(EPR_DATA, BLT_CTRL1 | 0x0940 | (USHORT)direction ); // start BITBLT
|
|
|
|
return;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID DrvMovePointer
|
|
*
|
|
* Moves the pointer to a new position.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID DrvMovePointer (
|
|
SURFOBJ *pso,
|
|
LONG x,
|
|
LONG y,
|
|
RECTL *prcl )
|
|
|
|
{
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes;
|
|
DWORD returnedDataLength;
|
|
VIDEO_POINTER_POSITION NewPointerPosition;
|
|
|
|
if (x == -1) {
|
|
|
|
//
|
|
// A new position of (-1,-1) means hide the pointer.
|
|
//
|
|
if (ppdev->fHwCursorActive) {
|
|
vShowHwPointer(FALSE);
|
|
} else {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Remove the pointer from the screen
|
|
//
|
|
if (!ppdev->fHwCursorActive) {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
pPointerAttributes->Column = (SHORT) x;
|
|
pPointerAttributes->Row = (SHORT) y;
|
|
pPointerAttributes->Enable = 1;
|
|
|
|
//
|
|
// Draw the pointer at the new location
|
|
//
|
|
if (ppdev->fHwCursorActive) {
|
|
vShowHwPointer(TRUE); // Actually, miniport driver will change the location later
|
|
} else {
|
|
vShowSimPointer(ppdev, pso, prcl, TRUE);
|
|
} /* endif */
|
|
|
|
//
|
|
// Call miniport driver to adjust the visible region of virtual screen
|
|
//
|
|
NewPointerPosition.Column = (SHORT) x;
|
|
NewPointerPosition.Row = (SHORT) y;
|
|
|
|
if (EngDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_SET_POINTER_POSITION,
|
|
&NewPointerPosition,
|
|
sizeof(VIDEO_POINTER_POSITION),
|
|
NULL,
|
|
0,
|
|
&returnedDataLength))
|
|
{
|
|
// Not the end of the world, print warning in checked build.
|
|
|
|
DISPDBG((1, "DISP vMoveHardwarePointer failed IOCTL_VIDEO_SET_POINTER_POSITION\n"));
|
|
}
|
|
|
|
} /* endif */
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ULONG 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 )
|
|
|
|
{
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes;
|
|
|
|
//
|
|
// See if we are being asked to hide the pointer
|
|
//
|
|
if (psoMask == (SURFOBJ *) NULL) {
|
|
|
|
if (ppdev->fHwCursorActive) {
|
|
vShowHwPointer(FALSE);
|
|
} else {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Save the hot spot of the cursor
|
|
//
|
|
ppdev->ptlHotSpot.x = xHot;
|
|
ppdev->ptlHotSpot.y = yHot;
|
|
|
|
//
|
|
// Check if we can handle this pointer in hardware
|
|
//
|
|
if (bSetHwPointerShape(pso,psoMask,psoColor,pxlo,x,y,fl)) {
|
|
|
|
//
|
|
// Take the old pointer off the screen
|
|
//
|
|
if (ppdev->fHwCursorActive) {
|
|
// do nothing here
|
|
} else {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
ppdev->fHwCursorActive = TRUE;
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
//
|
|
// Draw the new pointer
|
|
//
|
|
DrvMovePointer(pso, x, y, (RECTL *)NULL);
|
|
|
|
//
|
|
// Accept the new pointer
|
|
//
|
|
return SPS_ACCEPT_NOEXCLUDE;
|
|
|
|
//
|
|
// Try to simulate the pointer in place of the engine simulation to keep track of
|
|
// pointer location for the virtual screen
|
|
//
|
|
} else if (bSetSimPointerShape(pso,psoMask,psoColor,pxlo,x,y,fl)) {
|
|
|
|
//
|
|
// Take the old pointer off the screen
|
|
//
|
|
if (ppdev->fHwCursorActive) {
|
|
vShowHwPointer(FALSE);
|
|
} else {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
ppdev->fHwCursorActive = FALSE;
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
//
|
|
// Draw the new pointer
|
|
//
|
|
DrvMovePointer(pso, x, y, prcl);
|
|
|
|
//
|
|
// Signal GDI to move the pointer before reading from/writting to prcl
|
|
//
|
|
return SPS_ACCEPT_EXCLUDE;
|
|
|
|
//
|
|
// Give up to handle this pointer. Let GDI simulate it.
|
|
//
|
|
} else {
|
|
|
|
//
|
|
// Take the old pointer off the screen
|
|
//
|
|
if (ppdev->fHwCursorActive) {
|
|
vShowHwPointer(FALSE);
|
|
} else {
|
|
if (pPointerAttributes->Enable)
|
|
vShowSimPointer(ppdev, pso, prcl, FALSE);
|
|
} /* endif */
|
|
|
|
ppdev->fHwCursorActive = FALSE;
|
|
pPointerAttributes->Enable = 0;
|
|
|
|
//
|
|
// Decline to realize the new pointer shape
|
|
//
|
|
return SPS_DECLINE;
|
|
|
|
} /* endif */
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bInitPointer
|
|
*
|
|
* Initialize the Pointer attributes.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bInitPointer (
|
|
PPDEV ppdev,
|
|
DEVINFO *pdevinfo )
|
|
|
|
{
|
|
|
|
if (ppdev->ulBitCount == 8) {
|
|
ppdev->PointerCapabilities.Flags = VIDEO_MODE_MONO_POINTER;
|
|
ppdev->PointerCapabilities.MaxWidth = 64;
|
|
ppdev->PointerCapabilities.MaxHeight = 64;
|
|
ppdev->PointerCapabilities.HWPtrBitmapStart = (ULONG) -1;
|
|
ppdev->PointerCapabilities.HWPtrBitmapEnd = (ULONG) -1;
|
|
} else {
|
|
ppdev->PointerCapabilities.Flags = 0; // no hardware pointer in 16bpp mode
|
|
ppdev->PointerCapabilities.MaxWidth = 0;
|
|
ppdev->PointerCapabilities.MaxHeight = 0;
|
|
ppdev->PointerCapabilities.HWPtrBitmapStart = (ULONG) -1;
|
|
ppdev->PointerCapabilities.HWPtrBitmapEnd = (ULONG) -1;
|
|
} /* endif */
|
|
|
|
ppdev->pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES) NULL;
|
|
ppdev->cjPointerAttributes = 0; // initialized in screen.c
|
|
|
|
// Note: The buffer itself is allocated after we set the
|
|
// mode. At that time we know the pixel depth and we can
|
|
// allocate the correct size for the color pointer if supported.
|
|
|
|
|
|
// Set the asynchronous support status (async means miniport is capable of
|
|
// drawing the Pointer at any time, with no interference with any ongoing
|
|
// drawing operation)
|
|
|
|
pdevinfo->flGraphicsCaps &= ~GCAPS_ASYNCMOVE; // drawing must be synchronized by GDI
|
|
|
|
ppdev->hsurfMask = (HSURF) NULL;
|
|
ppdev->hsurfColor = (HSURF) NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|