windows-nt/Source/XPSP1/NT/drivers/video/ms/compaq.qv/disp/pointer.c

361 lines
9.6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************Module*Header*******************************\
* Module Name: pointer.c
*
* This module contains the hardware pointer support for the display
* driver.
*
* Copyright (c) 1994-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
// This should match the miniport definition:
#define VIDEO_MODE_LOCAL_POINTER 0x08
// Look-up table for masking the right edge of the given pointer bitmap:
BYTE gajMask[] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFc, 0xFE };
/******************************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)
{
VIDEO_POINTER_POSITION Position;
PDEV* ppdev;
DWORD returnedDataLength;
ppdev = (PDEV*) pso->dhpdev;
#if MULTI_BOARDS
{
if (x != -1)
{
OH* poh;
poh = ((DSURF*) pso->dhsurf)->poh;
x += poh->x;
y += poh->y;
}
}
#endif
if (x == -1)
{
ppdev->bPointerEnabled = FALSE;
EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_DISABLE_POINTER,
NULL,
0,
NULL,
0,
&returnedDataLength);
}
else
{
Position.Column = (short) (x - ppdev->ptlHotSpot.x);
Position.Row = (short) (y - ppdev->ptlHotSpot.y);
if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_LOCAL_POINTER)
{
// This is rather dumb:
IO_CURSOR_X(ppdev, ppdev->pjIoBase, Position.Column + CURSOR_CX);
IO_CURSOR_Y(ppdev, ppdev->pjIoBase, Position.Row + CURSOR_CY);
}
else
{
EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_SET_POINTER_POSITION,
&Position,
sizeof(VIDEO_POINTER_POSITION),
NULL,
0,
&returnedDataLength);
}
// Don't forget to turn on the pointer, if it was off:
if (!ppdev->bPointerEnabled)
{
ppdev->bPointerEnabled = TRUE;
EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_ENABLE_POINTER,
NULL,
0,
NULL,
0,
&returnedDataLength);
}
}
}
/******************************Public*Routine******************************\
* VOID DrvSetPointerShape
*
* Sets the new pointer shape.
*
\**************************************************************************/
ULONG DrvSetPointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
VIDEO_POINTER_ATTRIBUTES* pPointerAttributes;
PDEV* ppdev;
ULONG cx;
ULONG cy;
LONG cjWhole;
LONG cjDst;
BYTE* pjSrc;
BYTE* pjDst;
LONG lSrcDelta;
LONG lDstDelta;
LONG i;
DWORD returnedDataLength;
ppdev = (PDEV*) pso->dhpdev;
pPointerAttributes = ppdev->pPointerAttributes;
if (pPointerAttributes == NULL)
{
// There are no hardware pointer capabilities:
return(SPS_DECLINE);
}
cx = psoMsk->sizlBitmap.cx;
cy = psoMsk->sizlBitmap.cy / 2;
if ((cx > ppdev->PointerCapabilities.MaxWidth) ||
(cy > ppdev->PointerCapabilities.MaxHeight) ||
(psoColor != NULL) ||
!(fl & SPS_CHANGE) ||
(cx & 0x7))
{
goto HideAndDecline;
}
#if MULTI_BOARDS
{
if (x != -1)
{
OH* poh;
poh = ((DSURF*) pso->dhsurf)->poh;
x += poh->x;
y += poh->y;
}
}
#endif
cjWhole = cx / 8;
cjDst = pPointerAttributes->WidthInBytes * pPointerAttributes->Height;
// Copy AND bits:
pjSrc = psoMsk->pvScan0;
lSrcDelta = psoMsk->lDelta;
pjDst = pPointerAttributes->Pixels;
lDstDelta = pPointerAttributes->WidthInBytes;
memset(pjDst, -1, cjDst); // Pad unused AND bits
for (i = cy; i != 0; i--)
{
memcpy(pjDst, pjSrc, cjWhole);
pjSrc += lSrcDelta;
pjDst += lDstDelta;
}
// Copy XOR bits:
pjDst = pPointerAttributes->Pixels + ppdev->cjXorMaskStartOffset;
memset(pjDst, 0, cjDst); // Pad unused XOR bits
for (i = cy; i != 0; i--)
{
memcpy(pjDst, pjSrc, cjWhole);
pjSrc += lSrcDelta;
pjDst += lDstDelta;
}
// Initialize the pointer attributes:
ppdev->ptlHotSpot.x = xHot;
ppdev->ptlHotSpot.y = yHot;
pPointerAttributes->Column = (short) (x - xHot);
pPointerAttributes->Row = (short) (y - yHot);
pPointerAttributes->Enable = (x != -1);
pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
if (fl & SPS_ANIMATESTART)
pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_START;
else if (fl & SPS_ANIMATEUPDATE)
pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_UPDATE;
if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_LOCAL_POINTER)
{
// This is rather dumb:
IO_CURSOR_X(ppdev, ppdev->pjIoBase, pPointerAttributes->Column + CURSOR_CX);
IO_CURSOR_Y(ppdev, ppdev->pjIoBase, pPointerAttributes->Row + CURSOR_CY);
}
// Send the bits to the miniport:
ppdev->bPointerEnabled = pPointerAttributes->Enable;
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_SET_POINTER_ATTR,
ppdev->pPointerAttributes,
ppdev->cjPointerAttributes,
NULL,
0,
&returnedDataLength))
{
goto HideAndDecline;
}
return(SPS_ACCEPT_NOEXCLUDE);
HideAndDecline:
DrvMovePointer(pso, -1, -1, NULL);
return(SPS_DECLINE);
}
/******************************Public*Routine******************************\
* VOID vDisablePointer
*
\**************************************************************************/
VOID vDisablePointer(
PDEV* ppdev)
{
// Nothing to do, really
}
/******************************Public*Routine******************************\
* VOID vAssertModePointer
*
\**************************************************************************/
VOID vAssertModePointer(
PDEV* ppdev,
BOOL bEnable)
{
// Nothing to do, really
}
/******************************Public*Routine******************************\
* BOOL bEnablePointer
*
\**************************************************************************/
BOOL bEnablePointer(
PDEV* ppdev)
{
return(TRUE);
}
/******************************Public*Routine******************************\
* BOOL bInitializePointer
*
* Initialize pointer during driver PDEV initialization -- early enough
* so that we can affect what 'flGraphicsCaps' are passed back to GDI,
* so that we can set GCAPS_ASYNCMOVE appropriately.
*
\**************************************************************************/
BOOL bInitializePointer(
PDEV* ppdev)
{
VIDEO_POINTER_ATTRIBUTES* pPointerAttributes;
LONG cjWidth;
LONG cjMaxPointer;
DWORD returnedDataLength;
if (!EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES,
NULL,
0,
&ppdev->PointerCapabilities,
sizeof(ppdev->PointerCapabilities),
&returnedDataLength))
{
if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER)
{
cjWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
cjMaxPointer = 2 * cjWidth * ppdev->PointerCapabilities.MaxHeight;
ppdev->cjXorMaskStartOffset = cjMaxPointer / 2;
ppdev->cjPointerAttributes = sizeof(VIDEO_POINTER_ATTRIBUTES)
+ cjMaxPointer;
pPointerAttributes = (VIDEO_POINTER_ATTRIBUTES*)
EngAllocMem(0, ppdev->cjPointerAttributes, ALLOC_TAG);
if (pPointerAttributes != NULL)
{
ppdev->pPointerAttributes = pPointerAttributes;
pPointerAttributes->WidthInBytes
= cjWidth;
pPointerAttributes->Width
= ppdev->PointerCapabilities.MaxWidth;
pPointerAttributes->Height
= ppdev->PointerCapabilities.MaxHeight;
}
}
}
// We were successful even if the miniport doesn't support a
// hardware pointer:
return(TRUE);
}
/******************************Public*Routine******************************\
* VOID vUnitializePointer
*
* Undoes bInitializePointer.
*
\**************************************************************************/
VOID vUninitializePointer(
PDEV* ppdev)
{
EngFreeMem(ppdev->pPointerAttributes);
}