3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS VGA16 display driver
22 * FILE: drivers/dd/vga/display/objects/pointer.c
23 * PURPOSE: Draws the mouse pointer.
26 /* INCLUDES ******************************************************************/
28 #include "../vgaddi.h"
29 #include "../vgavideo/vgavideo.h"
31 /* GLOBALS *******************************************************************/
33 static ULONG oldx, oldy;
34 static PSAVED_SCREEN_BITS ImageBehindCursor = NULL;
35 VOID VGADDI_HideCursor(PPDEV ppdev);
36 VOID VGADDI_ShowCursor(PPDEV ppdev);
38 /* FUNCTIONS *****************************************************************/
41 VGADDI_BltPointerToVGA(ULONG StartX, ULONG StartY, ULONG SizeX,
42 ULONG SizeY, PUCHAR MaskBits, ULONG MaskOp)
54 EndX = StartX + SizeX;
55 EndY = StartY + SizeY;
56 MaskPitch = SizeX >> 3;
58 /* Set write mode zero. */
59 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
60 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0);
62 /* Select raster op. */
63 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3);
64 WRITE_PORT_UCHAR((PUCHAR)GRA_D, MaskOp);
66 if ((StartX % 8) != 0)
68 /* Disable writes to pixels outside of the destination rectangle. */
69 Mask = (1 << (8 - (StartX % 8))) - 1;
70 if ((EndX - StartX) < (8 - (StartX % 8)))
72 Mask &= ~((1 << (8 - (EndX % 8))) - 1);
74 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
75 WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
78 Video = (PUCHAR)vidmem + StartY * 80 + (StartX >> 3);
79 Src = MaskBits + SizeY * MaskPitch;
80 for (i = 0; i < SizeY; i++, Video+=80)
83 SrcValue = (*Src) >> (StartX % 8);
84 (VOID)READ_REGISTER_UCHAR(Video);
85 WRITE_REGISTER_UCHAR(Video, SrcValue);
89 /* Enable writes to all pixels. */
90 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
91 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
93 /* Have we finished. */
94 if ((EndX - StartX) < (8 - (StartX % 8)))
99 /* Fill any whole rows of eight pixels. */
100 Left = (StartX + 7) & ~0x7;
101 Length = (EndX >> 3) - (Left >> 3);
102 for (i = StartY; i < EndY; i++)
104 Video = (PUCHAR)vidmem + i * 80 + (Left >> 3);
105 Src = MaskBits + (EndY - i - 1) * MaskPitch;
106 for (j = 0; j < Length; j++, Video++, Src++)
108 if ((StartX % 8) != 0)
110 SrcValue = (Src[0] << (8 - (StartX % 8)));
111 SrcValue |= (Src[1] >> (StartX % 8));
117 (VOID)READ_REGISTER_UCHAR(Video);
118 WRITE_REGISTER_UCHAR(Video, SrcValue);
122 /* Fill any pixels on the right which don't fall into a complete row. */
125 /* Disable writes to pixels outside the destination rectangle. */
126 Mask = ~((1 << (8 - (EndX % 8))) - 1);
127 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
128 WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
130 Video = (PUCHAR)vidmem + StartY * 80 + (EndX >> 3);
131 Src = MaskBits + SizeY * MaskPitch + (SizeX >> 3) - 1;
132 for (i = StartY; i < EndY; i++, Video+=80)
135 SrcValue = (Src[0] << (8 - (StartX % 8)));
136 (VOID)READ_REGISTER_UCHAR(Video);
137 WRITE_REGISTER_UCHAR(Video, SrcValue);
140 /* Restore the default write masks. */
141 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
142 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
145 /* Set write mode two. */
146 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
147 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
149 /* Select raster op replace. */
150 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3);
151 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0);
154 BOOL InitPointer(PPDEV ppdev)
156 ULONG CursorWidth = 32, CursorHeight = 32;
157 ULONG PointerAttributesSize;
160 /* Determine the size of the pointer attributes */
161 PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) +
162 ((CursorWidth * CursorHeight * 2) >> 3);
164 /* Allocate memory for pointer attributes */
165 ppdev->pPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG);
167 ppdev->pPointerAttributes->Flags = 0; /* FIXME: Do this right */
168 ppdev->pPointerAttributes->Width = CursorWidth;
169 ppdev->pPointerAttributes->Height = CursorHeight;
170 ppdev->pPointerAttributes->WidthInBytes = CursorWidth >> 3;
171 ppdev->pPointerAttributes->Enable = 0;
172 ppdev->pPointerAttributes->Column = 0;
173 ppdev->pPointerAttributes->Row = 0;
175 /* Allocate memory for the pixels behind the cursor */
176 SavedMemSize = ((((CursorWidth + 7) & ~0x7) + 16) * CursorHeight) >> 3;
177 ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize);
184 DrvMovePointer(IN PSURFOBJ pso,
189 PPDEV ppdev = (PPDEV)pso->dhpdev;
193 /* x < 0 and y < 0 indicates we must hide the cursor */
194 VGADDI_HideCursor(ppdev);
198 ppdev->xyCursor.x = x;
199 ppdev->xyCursor.y = y;
201 VGADDI_ShowCursor(ppdev);
203 /* Give feedback on the new cursor rectangle */
204 /*if (prcl != NULL) ComputePointerRect(ppdev, prcl);*/
209 DrvSetPointerShape(PSURFOBJ pso,
220 PPDEV ppdev = (PPDEV)pso->dhpdev;
221 ULONG NewWidth, NewHeight;
225 NewWidth = psoMask->lDelta << 3;
226 NewHeight = (psoMask->cjBits / psoMask->lDelta) / 2;
228 /* Hide the cursor */
229 if(ppdev->pPointerAttributes->Enable != 0)
231 VGADDI_HideCursor(ppdev);
234 /* Reallocate the space for the cursor if necessary. */
235 if (ppdev->pPointerAttributes->Width != NewWidth ||
236 ppdev->pPointerAttributes->Height != NewHeight)
238 ULONG PointerAttributesSize;
239 PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes;
242 /* Determine the size of the pointer attributes */
243 PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) +
244 ((NewWidth * NewHeight * 2) >> 3);
246 /* Allocate memory for pointer attributes */
247 NewPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG);
248 *NewPointerAttributes = *ppdev->pPointerAttributes;
249 NewPointerAttributes->Width = NewWidth;
250 NewPointerAttributes->Height = NewHeight;
251 NewPointerAttributes->WidthInBytes = NewWidth >> 3;
252 EngFreeMem(ppdev->pPointerAttributes);
253 ppdev->pPointerAttributes = NewPointerAttributes;
255 /* Reallocate the space for the saved bits. */
256 VGADDI_FreeSavedScreenBits(ImageBehindCursor);
257 SavedMemSize = ((((NewWidth + 7) & ~0x7) + 16) * NewHeight) >> 3;
258 ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize);
261 /* Copy the new cursor in. */
262 for (i = 0; i < (NewHeight * 2); i++)
264 Src = (PUCHAR)psoMask->pvBits;
265 Src += (i * (NewWidth >> 3));
266 Dest = (PUCHAR)ppdev->pPointerAttributes->Pixels;
269 Dest += (((NewHeight * 3) - i - 1) * (NewWidth >> 3));
273 Dest += ((NewHeight - i - 1) * (NewWidth >> 3));
275 memcpy(Dest, Src, NewWidth >> 3);
278 /* Set the new cursor position */
279 ppdev->xyCursor.x = x;
280 ppdev->xyCursor.y = y;
282 /* Show the cursor */
283 VGADDI_ShowCursor(ppdev);
285 return SPS_ACCEPT_EXCLUDE;
289 VGADDI_HideCursor(PPDEV ppdev)
291 ULONG i, j, cx, cy, bitpos;
294 /* Display what was behind cursor */
295 SizeX = ((oldx + ppdev->pPointerAttributes->Width) + 7) & ~0x7;
296 SizeX -= (oldx & ~0x7);
297 VGADDI_BltFromSavedScreenBits(oldx & ~0x7,
301 ppdev->pPointerAttributes->Height);
303 ppdev->pPointerAttributes->Enable = 0;
307 VGADDI_ShowCursor(PPDEV ppdev)
313 if (ppdev->pPointerAttributes->Enable != 0)
315 VGADDI_HideCursor(ppdev);
318 /* Capture pixels behind the cursor */
319 cx = ppdev->xyCursor.x;
320 cy = ppdev->xyCursor.y;
322 /* Used to repaint background */
323 SizeX = ((cx + ppdev->pPointerAttributes->Width) + 7) & ~0x7;
324 SizeX -= (cx & ~0x7);
326 VGADDI_BltToSavedScreenBits(ImageBehindCursor,
330 ppdev->pPointerAttributes->Height);
332 /* Display the cursor. */
333 XorMask = ppdev->pPointerAttributes->Pixels +
334 ppdev->pPointerAttributes->WidthInBytes *
335 ppdev->pPointerAttributes->Height;
336 VGADDI_BltPointerToVGA(ppdev->xyCursor.x,
338 ppdev->pPointerAttributes->Width,
339 ppdev->pPointerAttributes->Height,
340 ppdev->pPointerAttributes->Pixels,
342 VGADDI_BltPointerToVGA(ppdev->xyCursor.x,
344 ppdev->pPointerAttributes->Width,
345 ppdev->pPointerAttributes->Height,
349 /* Save the new cursor location. */
350 oldx = ppdev->xyCursor.x;
351 oldy = ppdev->xyCursor.y;
353 /* Mark the cursor as currently displayed. */
354 ppdev->pPointerAttributes->Enable = 1;