/******************************Module*Header*******************************\ * * ******************* * * GDI SAMPLE CODE * * ******************* * * Module Name: pointer.c * * * * This module contains the hardware Pointer support for the framebuffer * * * * Copyright (c) 1992-1998 Microsoft Corporation * \**************************************************************************/ #include "driver.h" BOOL bCopyColorPointer( PPDEV ppdev, SURFOBJ *psoMask, SURFOBJ *psoColor, XLATEOBJ *pxlo); BOOL bCopyMonoPointer( PPDEV ppdev, SURFOBJ *psoMask); BOOL bSetHardwarePointerShape( SURFOBJ *pso, SURFOBJ *psoMask, SURFOBJ *psoColor, XLATEOBJ *pxlo, LONG x, LONG y, FLONG fl); /******************************Public*Routine******************************\ * DrvMovePointer * * Moves the hardware pointer to a new position. * \**************************************************************************/ VOID DrvMovePointer ( SURFOBJ *pso, LONG x, LONG y, RECTL *prcl ) { /* PPDEV ppdev = (PPDEV) pso->dhpdev; DWORD returnedDataLength; VIDEO_POINTER_POSITION NewPointerPosition; // 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. UNREFERENCED_PARAMETER(prcl); // Convert the pointer's position from relative to absolute // coordinates (this is only significant for multiple board // support). x -= ppdev->ptlOrg.x; y -= ppdev->ptlOrg.y; // If x is -1 after the offset then take down the cursor. 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((1, "DISP vMoveHardwarePointer failed IOCTL_VIDEO_DISABLE_POINTER\n")); } } else { NewPointerPosition.Column = (SHORT) x - (SHORT) (ppdev->ptlHotSpot.x); NewPointerPosition.Row = (SHORT) y - (SHORT) (ppdev->ptlHotSpot.y); // // Call miniport 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((1, "DISP vMoveHardwarePointer failed IOCTL_VIDEO_SET_POINTER_POSITION\n")); } } */ } /******************************Public*Routine******************************\ * 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; DWORD returnedDataLength; // 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. UNREFERENCED_PARAMETER(prcl); if (ppdev->pPointerAttributes == (PVIDEO_POINTER_ATTRIBUTES) NULL) { // Mini-port has no hardware Pointer support. return(SPS_ERROR); } // See if we are being asked to hide the pointer if (psoMask == (SURFOBJ *) NULL) { /* if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_DISABLE_POINTER, NULL, 0, NULL, 0, &returnedDataLength)) { // // It should never be possible to fail. // Message supplied for debugging. // DISPDBG((1, "DISP bSetHardwarePointerShape failed IOCTL_VIDEO_DISABLE_POINTER\n")); } */ return(TRUE); } ppdev->ptlHotSpot.x = xHot; ppdev->ptlHotSpot.y = yHot; if (!bSetHardwarePointerShape(pso,psoMask,psoColor,pxlo,x,y,fl)) { if (ppdev->fHwCursorActive) { ppdev->fHwCursorActive = FALSE; /* if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_DISABLE_POINTER, NULL, 0, NULL, 0, &returnedDataLength)) { DISPDBG((1, "DISP bSetHardwarePointerShape failed IOCTL_VIDEO_DISABLE_POINTER\n")); } */ } // // Mini-port declines to realize this Pointer // return(SPS_DECLINE); } else { ppdev->fHwCursorActive = TRUE; } return(SPS_ACCEPT_NOEXCLUDE); } /******************************Public*Routine******************************\ * 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) { PPDEV ppdev = (PPDEV) pso->dhpdev; PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes; DWORD returnedDataLength; if (psoColor != (SURFOBJ *) NULL) { if ((ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER) && bCopyColorPointer(ppdev, psoMask, psoColor, pxlo)) { pPointerAttributes->Flags |= VIDEO_MODE_COLOR_POINTER; } else { return(FALSE); } } else { 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->Enable = 1; // // if x,y = -1,-1 then pass them directly to the miniport so that // the cursor will be disabled pPointerAttributes->Column = (SHORT)(x); pPointerAttributes->Row = (SHORT)(y); if ((x != -1) || (y != -1)) { pPointerAttributes->Column -= (SHORT)(ppdev->ptlHotSpot.x); pPointerAttributes->Row -= (SHORT)(ppdev->ptlHotSpot.y); } // // set animate flags // 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. // if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SET_POINTER_ATTR, pPointerAttributes, ppdev->cjPointerAttributes, NULL, 0, &returnedDataLength)) { DISPDBG((1, "DISP:Failed IOCTL_VIDEO_SET_POINTER_ATTR call\n")); return(FALSE); } */ return(TRUE); } /******************************Public*Routine******************************\ * 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( PPDEV ppdev, SURFOBJ *pso) { ULONG cy; PBYTE pjSrcAnd, pjSrcXor; LONG lDeltaSrc, lDeltaDst; LONG lSrcWidthInBytes; ULONG cxSrc = pso->sizlBitmap.cx; ULONG cySrc = pso->sizlBitmap.cy; ULONG cxSrcBytes; PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = ppdev->pPointerAttributes; PBYTE pjDstAnd = pPointerAttributes->Pixels; PBYTE 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) * ppdev->pPointerAttributes->Height; // set the desk and mask to 0xff RtlFillMemory(pjDstAnd, ppdev->pPointerAttributes->WidthInBytes * ppdev->pPointerAttributes->Height, 0xFF); // Zero the dest XOR mask RtlZeroMemory(pjDstXor, ppdev->pPointerAttributes->WidthInBytes * ppdev->pPointerAttributes->Height); cxSrcBytes = (cxSrc + 7) / 8; if ((lDeltaSrc = pso->lDelta) < 0) { lSrcWidthInBytes = -lDeltaSrc; } else { lSrcWidthInBytes = lDeltaSrc; } pjSrcAnd = (PBYTE) pso->pvBits; // If the incoming pointer bitmap is bottomup, we'll flip it to topdown to // save the miniport some work if (!(pso->fjBitmap & BMF_TOPDOWN)) { // Copy from the bottom pjSrcAnd += lSrcWidthInBytes * (cySrc - 1); } // 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 = ppdev->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******************************\ * bCopyColorPointer * * Copies the mono and color masks into the buffer of maximum size * handled by the miniport with any extra bits set to 0. Color translation * is handled at this time. 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 bCopyColorPointer( PPDEV ppdev, SURFOBJ *psoMask, SURFOBJ *psoColor, XLATEOBJ *pxlo) { return(FALSE); } /******************************Public*Routine******************************\ * bInitPointer * * Initialize the Pointer attributes. * \**************************************************************************/ BOOL bInitPointer(PPDEV ppdev, DEVINFO *pdevinfo) { DWORD returnedDataLength; ppdev->pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES) NULL; ppdev->cjPointerAttributes = 0; // initialized in screen.c // // 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(FALSE); } // // 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. // // // 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) // if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_ASYNC_POINTER) { pdevinfo->flGraphicsCaps |= GCAPS_ASYNCMOVE; } else { pdevinfo->flGraphicsCaps &= ~GCAPS_ASYNCMOVE; } */ return(TRUE); }