2 * PROJECT: ReactOS Framebuffer Display Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/displays/framebuf/pointer.c
5 * PURPOSE: Hardware Pointer Support
6 * PROGRAMMERS: Copyright (c) 1992-1995 Microsoft Corporation
11 BOOL
bCopyColorPointer(
17 BOOL
bCopyMonoPointer(
21 BOOL
bSetHardwarePointerShape(
30 /******************************Public*Routine******************************\
33 * Moves the hardware pointer to a new position.
35 \**************************************************************************/
45 PPDEV ppdev
= (PPDEV
) pso
->dhpdev
;
46 DWORD returnedDataLength
;
47 VIDEO_POINTER_POSITION NewPointerPosition
;
49 // We don't use the exclusion rectangle because we only support
50 // hardware Pointers. If we were doing our own Pointer simulations
51 // we would want to update prcl so that the engine would call us
52 // to exclude out pointer before drawing to the pixels in prcl.
54 UNREFERENCED_PARAMETER(prcl
);
59 // A new position of (-1,-1) means hide the pointer.
62 if (EngDeviceIoControl(ppdev
->hDriver
,
63 IOCTL_VIDEO_DISABLE_POINTER
,
71 // Not the end of the world, print warning in checked build.
74 DISPDBG((1, "DISP vMoveHardwarePointer failed IOCTL_VIDEO_DISABLE_POINTER\n"));
79 NewPointerPosition
.Column
= (SHORT
) x
- (SHORT
) (ppdev
->ptlHotSpot
.x
);
80 NewPointerPosition
.Row
= (SHORT
) y
- (SHORT
) (ppdev
->ptlHotSpot
.y
);
83 // Call miniport driver to move Pointer.
86 if (EngDeviceIoControl(ppdev
->hDriver
,
87 IOCTL_VIDEO_SET_POINTER_POSITION
,
89 sizeof(VIDEO_POINTER_POSITION
),
95 // Not the end of the world, print warning in checked build.
98 DISPDBG((1, "DISP vMoveHardwarePointer failed IOCTL_VIDEO_SET_POINTER_POSITION\n"));
103 /******************************Public*Routine******************************\
106 * Sets the new pointer shape.
108 \**************************************************************************/
110 ULONG DrvSetPointerShape
124 PPDEV ppdev
= (PPDEV
) pso
->dhpdev
;
125 DWORD returnedDataLength
;
127 // We don't use the exclusion rectangle because we only support
128 // hardware Pointers. If we were doing our own Pointer simulations
129 // we would want to update prcl so that the engine would call us
130 // to exclude out pointer before drawing to the pixels in prcl.
131 UNREFERENCED_PARAMETER(prcl
);
133 if (ppdev
->pPointerAttributes
== (PVIDEO_POINTER_ATTRIBUTES
) NULL
)
135 // Mini-port has no hardware Pointer support.
139 // See if we are being asked to hide the pointer
141 if (psoMask
== (SURFOBJ
*) NULL
)
143 if (EngDeviceIoControl(ppdev
->hDriver
,
144 IOCTL_VIDEO_DISABLE_POINTER
,
149 &returnedDataLength
))
152 // It should never be possible to fail.
153 // Message supplied for debugging.
156 DISPDBG((1, "DISP bSetHardwarePointerShape failed IOCTL_VIDEO_DISABLE_POINTER\n"));
162 ppdev
->ptlHotSpot
.x
= xHot
;
163 ppdev
->ptlHotSpot
.y
= yHot
;
165 if (!bSetHardwarePointerShape(pso
,psoMask
,psoColor
,pxlo
,x
,y
,fl
))
167 if (ppdev
->fHwCursorActive
) {
168 ppdev
->fHwCursorActive
= FALSE
;
170 if (EngDeviceIoControl(ppdev
->hDriver
,
171 IOCTL_VIDEO_DISABLE_POINTER
,
176 &returnedDataLength
)) {
178 DISPDBG((1, "DISP bSetHardwarePointerShape failed IOCTL_VIDEO_DISABLE_POINTER\n"));
183 // Mini-port declines to realize this Pointer
190 ppdev
->fHwCursorActive
= TRUE
;
193 return(SPS_ACCEPT_NOEXCLUDE
);
196 /******************************Public*Routine******************************\
197 * bSetHardwarePointerShape
199 * Changes the shape of the Hardware Pointer.
201 * Returns: True if successful, False if Pointer shape can't be hardware.
203 \**************************************************************************/
205 BOOL
bSetHardwarePointerShape(
214 PPDEV ppdev
= (PPDEV
) pso
->dhpdev
;
215 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes
= ppdev
->pPointerAttributes
;
216 DWORD returnedDataLength
;
218 if (psoColor
!= (SURFOBJ
*) NULL
)
220 if ((ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_COLOR_POINTER
) &&
221 bCopyColorPointer(ppdev
, psoMask
, psoColor
, pxlo
))
223 pPointerAttributes
->Flags
|= VIDEO_MODE_COLOR_POINTER
;
230 if ((ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_MONO_POINTER
) &&
231 bCopyMonoPointer(ppdev
, psoMask
))
233 pPointerAttributes
->Flags
|= VIDEO_MODE_MONO_POINTER
;
240 // Initialize Pointer attributes and position
243 pPointerAttributes
->Enable
= 1;
246 // if x,y = -1,-1 then pass them directly to the miniport so that
247 // the cursor will be disabled
249 pPointerAttributes
->Column
= (SHORT
)(x
);
250 pPointerAttributes
->Row
= (SHORT
)(y
);
252 if ((x
!= -1) || (y
!= -1)) {
253 pPointerAttributes
->Column
-= (SHORT
)(ppdev
->ptlHotSpot
.x
);
254 pPointerAttributes
->Row
-= (SHORT
)(ppdev
->ptlHotSpot
.y
);
261 if (fl
& SPS_ANIMATESTART
) {
262 pPointerAttributes
->Flags
|= VIDEO_MODE_ANIMATE_START
;
263 } else if (fl
& SPS_ANIMATEUPDATE
) {
264 pPointerAttributes
->Flags
|= VIDEO_MODE_ANIMATE_UPDATE
;
268 // Set the new Pointer shape.
271 if (EngDeviceIoControl(ppdev
->hDriver
,
272 IOCTL_VIDEO_SET_POINTER_ATTR
,
274 ppdev
->cjPointerAttributes
,
277 &returnedDataLength
)) {
279 DISPDBG((1, "DISP:Failed IOCTL_VIDEO_SET_POINTER_ATTR call\n"));
286 /******************************Public*Routine******************************\
289 * Copies two monochrome masks into a buffer of the maximum size handled by the
290 * miniport, with any extra bits set to 0. The masks are converted to topdown
291 * form if they aren't already. Returns TRUE if we can handle this pointer in
292 * hardware, FALSE if not.
294 \**************************************************************************/
296 BOOL
bCopyMonoPointer(
301 PBYTE pjSrcAnd
, pjSrcXor
;
302 LONG lDeltaSrc
, lDeltaDst
;
303 LONG lSrcWidthInBytes
;
304 ULONG cxSrc
= pso
->sizlBitmap
.cx
;
305 ULONG cySrc
= pso
->sizlBitmap
.cy
;
307 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes
= ppdev
->pPointerAttributes
;
308 PBYTE pjDstAnd
= pPointerAttributes
->Pixels
;
309 PBYTE pjDstXor
= pPointerAttributes
->Pixels
;
311 // Make sure the new pointer isn't too big to handle
312 // (*2 because both masks are in there)
313 if ((cxSrc
> ppdev
->PointerCapabilities
.MaxWidth
) ||
314 (cySrc
> (ppdev
->PointerCapabilities
.MaxHeight
* 2)))
319 pjDstXor
+= ((ppdev
->PointerCapabilities
.MaxWidth
+ 7) / 8) *
320 ppdev
->pPointerAttributes
->Height
;
322 // set the desk and mask to 0xff
323 RtlFillMemory(pjDstAnd
, ppdev
->pPointerAttributes
->WidthInBytes
*
324 ppdev
->pPointerAttributes
->Height
, 0xFF);
326 // Zero the dest XOR mask
327 RtlZeroMemory(pjDstXor
, ppdev
->pPointerAttributes
->WidthInBytes
*
328 ppdev
->pPointerAttributes
->Height
);
330 cxSrcBytes
= (cxSrc
+ 7) / 8;
332 if ((lDeltaSrc
= pso
->lDelta
) < 0)
334 lSrcWidthInBytes
= -lDeltaSrc
;
336 lSrcWidthInBytes
= lDeltaSrc
;
339 pjSrcAnd
= (PBYTE
) pso
->pvBits
;
341 // If the incoming pointer bitmap is bottomup, we'll flip it to topdown to
342 // save the miniport some work
343 if (!(pso
->fjBitmap
& BMF_TOPDOWN
))
345 // Copy from the bottom
346 pjSrcAnd
+= lSrcWidthInBytes
* (cySrc
- 1);
349 // Height of just AND mask
353 pjSrcXor
= pjSrcAnd
+ (cySrc
* lDeltaSrc
);
355 // Offset from end of one dest scan to start of next
356 lDeltaDst
= ppdev
->pPointerAttributes
->WidthInBytes
;
358 for (cy
= 0; cy
< cySrc
; ++cy
)
360 RtlCopyMemory(pjDstAnd
, pjSrcAnd
, cxSrcBytes
);
361 RtlCopyMemory(pjDstXor
, pjSrcXor
, cxSrcBytes
);
363 // Point to next source and dest scans
364 pjSrcAnd
+= lDeltaSrc
;
365 pjSrcXor
+= lDeltaSrc
;
366 pjDstAnd
+= lDeltaDst
;
367 pjDstXor
+= lDeltaDst
;
373 /******************************Public*Routine******************************\
376 * Copies the mono and color masks into the buffer of maximum size
377 * handled by the miniport with any extra bits set to 0. Color translation
378 * is handled at this time. The masks are converted to topdown form if they
379 * aren't already. Returns TRUE if we can handle this pointer in hardware,
382 \**************************************************************************/
383 BOOL
bCopyColorPointer(
393 /******************************Public*Routine******************************\
396 * Initialize the Pointer attributes.
398 \**************************************************************************/
400 BOOL
bInitPointer(PPDEV ppdev
, DEVINFO
*pdevinfo
)
402 DWORD returnedDataLength
;
404 ppdev
->pPointerAttributes
= (PVIDEO_POINTER_ATTRIBUTES
) NULL
;
405 ppdev
->cjPointerAttributes
= 0; // initialized in screen.c
408 // Ask the miniport whether it provides pointer support.
411 if (EngDeviceIoControl(ppdev
->hDriver
,
412 IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES
,
415 &ppdev
->PointerCapabilities
,
416 sizeof(ppdev
->PointerCapabilities
),
417 &returnedDataLength
))
423 // If neither mono nor color hardware pointer is supported, there's no
424 // hardware pointer support and we're done.
427 if ((!(ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_MONO_POINTER
)) &&
428 (!(ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_COLOR_POINTER
)))
434 // Note: The buffer itself is allocated after we set the
435 // mode. At that time we know the pixel depth and we can
436 // allocate the correct size for the color pointer if supported.
440 // Set the asynchronous support status (async means miniport is capable of
441 // drawing the Pointer at any time, with no interference with any ongoing
442 // drawing operation)
445 if (ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_ASYNC_POINTER
)
447 pdevinfo
->flGraphicsCaps
|= GCAPS_ASYNCMOVE
;
451 pdevinfo
->flGraphicsCaps
&= ~GCAPS_ASYNCMOVE
;