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