windows-nt/Source/XPSP1/NT/drivers/video/ms/weitek/disp/pointer.c
2020-09-26 16:20:57 +08:00

435 lines
12 KiB
C

/******************************Module*Header*******************************\
* Module Name: pointer.c
*
* This module contains the hardware Pointer support.
*
* Copyright (c) 1992-1995 Microsoft Corporation
* Copyright (c) 1993-1995 Weitek Corporation
\**************************************************************************/
#include "precomp.h"
/******************************Public*Routine******************************\
* BOOL bCopyMonoPointer
*
* Copies two monochrome masks into a buffer of the maximum size handled by the
* miniport, with any extra bits set to 0. The masks are converted to topdown
* form if they aren't already. Returns TRUE if we can handle this pointer in
* hardware, FALSE if not.
*
\**************************************************************************/
BOOL bCopyMonoPointer(
PDEV* ppdev,
SURFOBJ* pso)
{
ULONG cy;
BYTE* pjSrcAnd;
BYTE* pjSrcXor;
LONG lDeltaSrc;
LONG lDeltaDst;
LONG lSrcWidthInBytes;
ULONG cxSrc;
ULONG cySrc;
ULONG cxSrcBytes;
BYTE* pjDstAnd;
BYTE* pjDstXor;
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes;
pPointerAttributes = ppdev->pPointerAttributes;
cxSrc = pso->sizlBitmap.cx;
cySrc = pso->sizlBitmap.cy;
pjDstAnd = pPointerAttributes->Pixels;
pjDstXor = pPointerAttributes->Pixels;
// Make sure the new pointer isn't too big to handle
// (*2 because both masks are in there)
if ((cxSrc > ppdev->PointerCapabilities.MaxWidth) ||
(cySrc > (ppdev->PointerCapabilities.MaxHeight * 2)))
{
return(FALSE);
}
pjDstXor += ((ppdev->PointerCapabilities.MaxWidth + 7) / 8) *
pPointerAttributes->Height;
// Set the desk and mask to 0xff
RtlFillMemory(pjDstAnd, pPointerAttributes->WidthInBytes *
pPointerAttributes->Height, 0xFF);
// Zero the dest XOR mask
RtlZeroMemory(pjDstXor, pPointerAttributes->WidthInBytes *
pPointerAttributes->Height);
cxSrcBytes = (cxSrc + 7) / 8;
if ((lDeltaSrc = pso->lDelta) < 0)
{
lSrcWidthInBytes = -lDeltaSrc;
}
else
{
lSrcWidthInBytes = lDeltaSrc;
}
pjSrcAnd = (BYTE*) pso->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 = pPointerAttributes->WidthInBytes;
for (cy = 0; cy < cySrc; ++cy)
{
RtlCopyMemory(pjDstAnd, pjSrcAnd, cxSrcBytes);
RtlCopyMemory(pjDstXor, pjSrcXor, cxSrcBytes);
// Point to next source and dest scans
pjSrcAnd += lDeltaSrc;
pjSrcXor += lDeltaSrc;
pjDstAnd += lDeltaDst;
pjDstXor += lDeltaDst;
}
return(TRUE);
}
/******************************Public*Routine******************************\
* BOOL bSetHardwarePointerShape
*
* Changes the shape of the Hardware Pointer.
*
* Returns: True if successful, False if Pointer shape can't be hardware.
*
\**************************************************************************/
BOOL bSetHardwarePointerShape(
SURFOBJ* pso,
SURFOBJ* psoMask,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG x,
LONG y,
FLONG fl)
{
PDEV* ppdev;
DWORD returnedDataLength;
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes;
ppdev = (PDEV*) pso->dhpdev;
pPointerAttributes = ppdev->pPointerAttributes;
// Don't make any assumptions about the pointer flags.
pPointerAttributes->Flags = 0;
// We don't support color pointers.
if (psoColor != NULL)
{
return(FALSE);
}
if ((ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER) &&
bCopyMonoPointer(ppdev, psoMask))
{
pPointerAttributes->Flags |= VIDEO_MODE_MONO_POINTER;
}
else
{
return(FALSE);
}
// Initialize Pointer attributes and position
pPointerAttributes->Column = (SHORT)(x - ppdev->ptlHotSpot.x);
pPointerAttributes->Row = (SHORT)(y - ppdev->ptlHotSpot.y);
pPointerAttributes->Enable = 1;
if (fl & SPS_ANIMATESTART)
{
pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_START;
}
else if (fl & SPS_ANIMATEUPDATE)
{
pPointerAttributes->Flags |= VIDEO_MODE_ANIMATE_UPDATE;
}
// Set the new Pointer shape.
CP_WAIT(ppdev, ppdev->pjBase);
if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SET_POINTER_ATTR,
pPointerAttributes, ppdev->cjPointerAttributes, NULL, 0,
&returnedDataLength))
{
DISPDBG((0, "Failed IOCTL_VIDEO_SET_POINTER_ATTR call"));
return(FALSE);
}
return(TRUE);
}
/******************************Public*Routine******************************\
* VOID DrvMovePointer
*
* Moves the hardware pointer to a new position.
*
\**************************************************************************/
VOID DrvMovePointer(
SURFOBJ* pso,
LONG x,
LONG y,
RECTL* prcl)
{
PDEV* ppdev;
DWORD returnedDataLength;
VIDEO_POINTER_POSITION NewPointerPosition;
ppdev = (PDEV*) pso->dhpdev;
// We don't use the exclusion rectangle because we only support
// hardware Pointers. If we were doing our own Pointer simulations
// we would want to update prcl so that the engine would call us
// to exclude out pointer before drawing to the pixels in prcl.
CP_WAIT(ppdev, ppdev->pjBase);
if (x == -1)
{
// A new position of (-1,-1) means hide the pointer.
if (EngDeviceIoControl(ppdev->hDriver,IOCTL_VIDEO_DISABLE_POINTER,
NULL, 0, NULL, 0, &returnedDataLength))
{
// Not the end of the world, print warning in checked build.
DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
}
}
else
{
NewPointerPosition.Column = (SHORT) x - (SHORT) (ppdev->ptlHotSpot.x);
NewPointerPosition.Row = (SHORT) y - (SHORT) (ppdev->ptlHotSpot.y);
// Call NT screen driver to move Pointer.
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((0, "Failed IOCTL_VIDEO_SET_POINTER_POSITION"));
}
}
}
/******************************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)
{
PDEV* ppdev;
DWORD returnedDataLength;
ppdev = (PDEV*) pso->dhpdev;
// We don't use the exclusion rectangle because we only support
// hardware Pointers. If we were doing our own Pointer simulations
// we would want to update prcl so that the engine would call us
// to exclude out pointer before drawing to the pixels in prcl.
if (ppdev->pPointerAttributes == (PVIDEO_POINTER_ATTRIBUTES) NULL)
{
// Mini-port has no hardware Pointer support.
return(SPS_DECLINE);
}
// See if we are being asked to hide the pointer
// !!! Wrong
if (psoMask == (SURFOBJ *) NULL)
{
CP_WAIT(ppdev, ppdev->pjBase);
if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_DISABLE_POINTER,
NULL, 0, NULL, 0, &returnedDataLength))
{
// It should never be possible to fail.
DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
}
return(TRUE); // !!! Wrong
}
ppdev->ptlHotSpot.x = xHot;
ppdev->ptlHotSpot.y = yHot;
if (!bSetHardwarePointerShape(pso,psoMask,psoColor,pxlo,x,y,fl))
{
if (ppdev->bHwPointerActive)
{
ppdev->bHwPointerActive = FALSE;
CP_WAIT(ppdev, ppdev->pjBase);
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_DISABLE_POINTER, NULL, 0, NULL, 0,
&returnedDataLength))
{
DISPDBG((0, "Failed IOCTL_VIDEO_DISABLE_POINTER"));
}
}
// Mini-port declines to realize this Pointer
return(SPS_DECLINE);
}
else
{
ppdev->bHwPointerActive = TRUE;
}
return(SPS_ACCEPT_NOEXCLUDE);
}
/******************************Public*Routine******************************\
* VOID vDisablePointer
*
\**************************************************************************/
VOID vDisablePointer(
PDEV* ppdev)
{
EngFreeMem(ppdev->pPointerAttributes);
}
/******************************Public*Routine******************************\
* VOID vAssertModePointer
*
\**************************************************************************/
VOID vAssertModePointer(
PDEV* ppdev,
BOOL bEnable)
{
}
/******************************Public*Routine******************************\
* BOOL bEnablePointer
*
* Note: We can return TRUE, as long as pPointerAttributes is set to NULL,
* and we will make due with a software cursor.
*
\**************************************************************************/
BOOL bEnablePointer(
PDEV* ppdev)
{
DWORD returnedDataLength;
DWORD MaxWidth;
DWORD MaxHeight;
VIDEO_POINTER_ATTRIBUTES* pPointerAttributes;
ppdev->pPointerAttributes = NULL;
ppdev->cjPointerAttributes = 0;
// Ask the miniport whether it provides pointer support.
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES, &ppdev->ulMode,
sizeof(PVIDEO_MODE), &ppdev->PointerCapabilities,
sizeof(ppdev->PointerCapabilities), &returnedDataLength))
{
return(TRUE);
}
// If neither mono nor color hardware pointer is supported, there's no
// hardware pointer support and we're done.
if ((!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_MONO_POINTER)) &&
(!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER)))
{
return(TRUE);
}
// 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.
// It's a hardware pointer; set up pointer attributes.
MaxHeight = ppdev->PointerCapabilities.MaxHeight;
// Allocate space for two DIBs (data/mask) for the pointer. If this
// device supports a color Pointer, we will allocate a larger bitmap.
// If this is a color bitmap we allocate for the largest possible
// bitmap because we have no idea of what the pixel depth might be.
// Width rounded up to nearest byte multiple
if (!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER))
{
MaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
}
else
{
MaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(DWORD);
}
ppdev->cjPointerAttributes =
sizeof(VIDEO_POINTER_ATTRIBUTES) +
((sizeof(UCHAR) * MaxWidth * MaxHeight) * 2);
pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)
EngAllocMem(FL_ZERO_MEMORY,
ppdev->cjPointerAttributes, ALLOC_TAG);
if (pPointerAttributes == NULL)
{
return(TRUE);
}
pPointerAttributes->WidthInBytes = MaxWidth;
pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
pPointerAttributes->Height = MaxHeight;
pPointerAttributes->Column = 0;
pPointerAttributes->Row = 0;
pPointerAttributes->Enable = 0;
ppdev->pPointerAttributes = pPointerAttributes;
return(TRUE);
}