2 * PROJECT: ReactOS VGA display driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/video/displays/vga/objects/pointer.c
5 * PURPOSE: Draws the mouse pointer
6 * PROGRAMMERS: Copyright (C) 1998-2001 ReactOS Team
9 /* INCLUDES ******************************************************************/
13 /* GLOBALS *******************************************************************/
15 static VOID
VGADDI_HideCursor(PPDEV ppdev
);
16 static VOID
VGADDI_ShowCursor(PPDEV ppdev
, PRECTL prcl
);
18 /* FUNCTIONS *****************************************************************/
21 VGADDI_BltPointerToVGA(
30 ULONG DestX
, EndX
, DestY
, EndY
;
40 DestX
= StartX
< 0 ? 0 : StartX
;
41 DestY
= StartY
< 0 ? 0 : StartY
;
42 EndX
= StartX
+ SizeX
;
43 EndY
= StartY
+ SizeY
;
45 /* Set write mode zero. */
46 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 5);
47 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0);
49 /* Select raster op. */
50 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 3);
51 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, MaskOp
);
55 /* Disable writes to pixels outside of the destination rectangle. */
56 Mask
= (1 << (8 - (DestX
% 8))) - 1;
57 if ((EndX
- DestX
) < (8 - (DestX
% 8)))
59 Mask
&= ~((1 << (8 - (EndX
% 8))) - 1);
61 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
62 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, Mask
);
65 Video
= (PUCHAR
)vidmem
+ DestY
* 80 + (DestX
>> 3);
66 Src
= MaskBits
+ (SizeY
- (DestY
- StartY
)) * MaskPitch
;
67 for (i
= DestY
; i
< EndY
; i
++, Video
+= 80)
70 SrcValue
= (*Src
) >> (DestX
% 8);
71 (VOID
)READ_REGISTER_UCHAR(Video
);
72 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
76 /* Enable writes to all pixels. */
77 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
78 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
80 /* Have we finished. */
81 if ((EndX
- DestX
) < (8 - (DestX
% 8)))
84 /* Fill any whole rows of eight pixels. */
85 Left
= (DestX
+ 7) & ~0x7;
86 Length
= (EndX
>> 3) - (Left
>> 3);
91 for (i
= DestY
; i
< EndY
; i
++)
93 Video
= (PUCHAR
)vidmem
+ i
* 80 + (Left
>> 3);
94 Src
= MaskBits
+ (EndY
- i
- 1) * MaskPitch
+ ((DestX
- StartX
) >> 3);
95 for (j
= 0; j
< Length
; j
++, Video
++, Src
++)
99 SrcValue
= (Src
[0] << (8 - Bits
));
100 SrcValue
|= (Src
[1] >> Bits
);
106 (VOID
)READ_REGISTER_UCHAR(Video
);
107 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
111 /* Fill any pixels on the right which don't fall into a complete row. */
114 /* Disable writes to pixels outside the destination rectangle. */
115 Mask
= ~((1 << (8 - (EndX
% 8))) - 1);
116 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
117 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, Mask
);
119 Video
= (PUCHAR
)vidmem
+ DestY
* 80 + (EndX
>> 3);
120 Src
= MaskBits
+ (SizeY
- (DestY
- StartY
)) * MaskPitch
+ (SizeX
>> 3) - 1;
121 for (i
= DestY
; i
< EndY
; i
++, Video
+= 80)
124 SrcValue
= (Src
[0] << (8 - Bits
));
125 (VOID
)READ_REGISTER_UCHAR(Video
);
126 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
129 /* Restore the default write masks. */
130 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
131 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
134 /* Set write mode two. */
135 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 5);
136 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 2);
138 /* Select raster op replace. */
139 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 3);
140 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0);
143 BOOL
InitPointer(PPDEV ppdev
)
145 ULONG CursorWidth
= 32, CursorHeight
= 32;
146 ULONG PointerAttributesSize
;
149 ppdev
->xyHotSpot
.x
= 0;
150 ppdev
->xyHotSpot
.y
= 0;
152 /* Determine the size of the pointer attributes */
153 PointerAttributesSize
= sizeof(VIDEO_POINTER_ATTRIBUTES
) +
154 ((CursorWidth
* CursorHeight
* 2) >> 3);
156 /* Allocate memory for pointer attributes */
157 ppdev
->pPointerAttributes
= EngAllocMem(0, PointerAttributesSize
, ALLOC_TAG
);
159 ppdev
->pPointerAttributes
->Flags
= 0; /* FIXME: Do this right */
160 ppdev
->pPointerAttributes
->Width
= CursorWidth
;
161 ppdev
->pPointerAttributes
->Height
= CursorHeight
;
162 ppdev
->pPointerAttributes
->WidthInBytes
= CursorWidth
>> 3;
163 ppdev
->pPointerAttributes
->Enable
= 0;
164 ppdev
->pPointerAttributes
->Column
= 0;
165 ppdev
->pPointerAttributes
->Row
= 0;
167 /* Allocate memory for the pixels behind the cursor */
168 SavedMemSize
= ((((CursorWidth
+ 7) & ~0x7) + 16) * CursorHeight
) >> 3;
169 ppdev
->ImageBehindCursor
= VGADDI_AllocSavedScreenBits(SavedMemSize
);
181 PPDEV ppdev
= (PPDEV
)pso
->dhpdev
;
183 VGADDI_HideCursor(ppdev
);
187 ppdev
->pPointerAttributes
->Column
= x
;
188 ppdev
->pPointerAttributes
->Row
= y
;
190 VGADDI_ShowCursor(ppdev
, prcl
);
199 IN SURFOBJ
* psoColor
,
208 PPDEV ppdev
= (PPDEV
)pso
->dhpdev
;
209 ULONG NewWidth
, NewHeight
;
216 /* Hide the cursor */
217 VGADDI_HideCursor(ppdev
);
219 NewWidth
= abs(psoMask
->lDelta
) << 3;
220 NewHeight
= (psoMask
->cjBits
/ abs(psoMask
->lDelta
)) / 2;
222 /* Reallocate the space for the cursor if necessary. */
223 if (ppdev
->pPointerAttributes
->Width
!= NewWidth
||
224 ppdev
->pPointerAttributes
->Height
!= NewHeight
)
226 ULONG PointerAttributesSize
;
227 PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes
;
230 /* Determine the size of the pointer attributes */
231 PointerAttributesSize
= sizeof(VIDEO_POINTER_ATTRIBUTES
) +
232 ((NewWidth
* NewHeight
* 2) >> 3);
234 /* Allocate memory for pointer attributes */
235 NewPointerAttributes
= EngAllocMem(0, PointerAttributesSize
, ALLOC_TAG
);
236 *NewPointerAttributes
= *ppdev
->pPointerAttributes
;
237 NewPointerAttributes
->Width
= NewWidth
;
238 NewPointerAttributes
->Height
= NewHeight
;
239 NewPointerAttributes
->WidthInBytes
= NewWidth
>> 3;
240 EngFreeMem(ppdev
->pPointerAttributes
);
241 ppdev
->pPointerAttributes
= NewPointerAttributes
;
243 /* Reallocate the space for the saved bits. */
244 VGADDI_FreeSavedScreenBits(ppdev
->ImageBehindCursor
);
245 SavedMemSize
= ((((NewWidth
+ 7) & ~0x7) + 16) * NewHeight
) >> 3;
246 ppdev
->ImageBehindCursor
= VGADDI_AllocSavedScreenBits(SavedMemSize
);
249 Src
= (PUCHAR
)psoMask
->pvScan0
;
250 /* Copy the new cursor in. */
251 for (i
= 0; i
< (NewHeight
* 2); i
++)
253 Dest
= (PUCHAR
)ppdev
->pPointerAttributes
->Pixels
;
255 Dest
+= (((NewHeight
* 3) - i
- 1) * (NewWidth
>> 3));
257 Dest
+= ((NewHeight
- i
- 1) * (NewWidth
>> 3));
258 memcpy(Dest
, Src
, NewWidth
>> 3);
259 Src
+= psoMask
->lDelta
;
262 /* Set the new cursor position */
263 ppdev
->xyHotSpot
.x
= xHot
;
264 ppdev
->xyHotSpot
.y
= yHot
;
268 ppdev
->pPointerAttributes
->Column
= x
;
269 ppdev
->pPointerAttributes
->Row
= y
;
271 /* show the cursor */
272 VGADDI_ShowCursor(ppdev
, prcl
);
275 return SPS_ACCEPT_NOEXCLUDE
;
279 VGADDI_ComputePointerRect(
287 SizeX
= min(((X
+ (LONG
)ppdev
->pPointerAttributes
->Width
) + 7) & ~0x7, ppdev
->sizeSurf
.cx
);
289 SizeY
= min((LONG
)ppdev
->pPointerAttributes
->Height
, ppdev
->sizeSurf
.cy
- Y
);
291 Rect
->left
= max(X
, 0) & ~0x7;
292 Rect
->top
= max(Y
, 0);
293 Rect
->right
= Rect
->left
+ SizeX
;
294 Rect
->bottom
= Rect
->top
+ SizeY
;
298 VGADDI_HideCursor(PPDEV ppdev
)
300 if(ppdev
->pPointerAttributes
->Enable
)
305 ppdev
->pPointerAttributes
->Enable
= 0;
307 cx
= ppdev
->pPointerAttributes
->Column
- ppdev
->xyHotSpot
.x
;
308 cy
= ppdev
->pPointerAttributes
->Row
- ppdev
->xyHotSpot
.y
;
310 VGADDI_ComputePointerRect(ppdev
, cx
, cy
, &Rect
);
312 /* Display what was behind cursor */
313 VGADDI_BltFromSavedScreenBits(Rect
.left
,
315 ppdev
->ImageBehindCursor
,
316 Rect
.right
- Rect
.left
,
317 Rect
.bottom
- Rect
.top
);
322 VGADDI_ShowCursor(PPDEV ppdev
, PRECTL prcl
)
325 PUCHAR AndMask
, XorMask
;
329 if(ppdev
->pPointerAttributes
->Enable
)
332 /* Mark the cursor as currently displayed. */
333 ppdev
->pPointerAttributes
->Enable
= 1;
335 cx
= ppdev
->pPointerAttributes
->Column
- ppdev
->xyHotSpot
.x
;
336 cy
= ppdev
->pPointerAttributes
->Row
- ppdev
->xyHotSpot
.y
;
338 /* Capture pixels behind the cursor */
339 VGADDI_ComputePointerRect(ppdev
, cx
, cy
, &Rect
);
341 VGADDI_BltToSavedScreenBits(ppdev
->ImageBehindCursor
,
344 Rect
.right
- Rect
.left
,
345 Rect
.bottom
- Rect
.top
);
347 /* Display the cursor. */
348 SizeX
= min((LONG
)ppdev
->pPointerAttributes
->Width
, ppdev
->sizeSurf
.cx
- cx
);
349 SizeY
= min((LONG
)ppdev
->pPointerAttributes
->Height
, ppdev
->sizeSurf
.cy
- cy
);
350 AndMask
= ppdev
->pPointerAttributes
->Pixels
+
351 (ppdev
->pPointerAttributes
->Height
- SizeY
) * ppdev
->pPointerAttributes
->WidthInBytes
;
352 VGADDI_BltPointerToVGA(cx
,
357 ppdev
->pPointerAttributes
->WidthInBytes
,
360 ppdev
->pPointerAttributes
->WidthInBytes
*
361 ppdev
->pPointerAttributes
->Height
;
362 VGADDI_BltPointerToVGA(cx
,
367 ppdev
->pPointerAttributes
->WidthInBytes
,