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);
80 for (i = 0; i < SizeY; i++, Video+=80, Src+=MaskPitch)
82 SrcValue = (*Src) >> (StartX % 8);
83 (VOID)READ_REGISTER_UCHAR(Video);
84 WRITE_REGISTER_UCHAR(Video, SrcValue);
88 /* Enable writes to all pixels. */
89 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
90 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
92 /* Have we finished. */
93 if ((EndX - StartX) < (8 - (StartX % 8)))
98 /* Fill any whole rows of eight pixels. */
99 Left = (StartX + 7) & ~0x7;
100 Length = (EndX >> 3) - (Left >> 3);
101 for (i = StartY; i < EndY; i++)
103 Video = (PUCHAR)vidmem + i * 80 + (Left >> 3);
104 Src = MaskBits + (i - StartY) * MaskPitch;
105 for (j = 0; j < Length; j++, Video++, Src++)
107 if ((StartX % 8) != 0)
109 SrcValue = (Src[0] << (8 - (StartX % 8)));
110 SrcValue |= (Src[1] >> (StartX % 8));
116 (VOID)READ_REGISTER_UCHAR(Video);
117 WRITE_REGISTER_UCHAR(Video, SrcValue);
121 /* Fill any pixels on the right which don't fall into a complete row. */
124 /* Disable writes to pixels outside the destination rectangle. */
125 Mask = ~((1 << (8 - (EndX % 8))) - 1);
126 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
127 WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
129 Video = (PUCHAR)vidmem + StartY * 80 + (EndX >> 3);
130 Src = MaskBits + (SizeX >> 3) - 1;
131 for (i = StartY; i < EndY; i++, Video+=80, Src+=MaskPitch)
133 SrcValue = (Src[0] << (8 - (StartX % 8)));
134 (VOID)READ_REGISTER_UCHAR(Video);
135 WRITE_REGISTER_UCHAR(Video, SrcValue);
138 /* Restore the default write masks. */
139 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
140 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
143 /* Set write mode two. */
144 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
145 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
147 /* Select raster op replace. */
148 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3);
149 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0);
152 BOOL InitPointer(PPDEV ppdev)
154 ULONG CursorWidth = 32, CursorHeight = 32;
155 ULONG PointerAttributesSize;
158 /* Determine the size of the pointer attributes */
159 PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) +
160 ((CursorWidth * CursorHeight * 2) >> 3);
162 /* Allocate memory for pointer attributes */
163 ppdev->pPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG);
165 ppdev->pPointerAttributes->Flags = 0; /* FIXME: Do this right */
166 ppdev->pPointerAttributes->Width = CursorWidth;
167 ppdev->pPointerAttributes->Height = CursorHeight;
168 ppdev->pPointerAttributes->WidthInBytes = CursorWidth >> 3;
169 ppdev->pPointerAttributes->Enable = 0;
170 ppdev->pPointerAttributes->Column = 0;
171 ppdev->pPointerAttributes->Row = 0;
173 /* Allocate memory for the pixels behind the cursor */
174 SavedMemSize = ((((CursorWidth + 7) & ~0x7) + 16) * CursorHeight) >> 3;
175 ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize);
182 DrvMovePointer(IN PSURFOBJ pso,
187 PPDEV ppdev = (PPDEV)pso->dhpdev;
191 /* x < 0 and y < 0 indicates we must hide the cursor */
192 VGADDI_HideCursor(ppdev);
196 ppdev->xyCursor.x = x;
197 ppdev->xyCursor.y = y;
199 VGADDI_ShowCursor(ppdev);
201 /* Give feedback on the new cursor rectangle */
202 /*if (prcl != NULL) ComputePointerRect(ppdev, prcl);*/
207 DrvSetPointerShape(PSURFOBJ pso,
218 PPDEV ppdev = (PPDEV)pso->dhpdev;
219 ULONG NewWidth, NewHeight;
223 NewWidth = psoMask->lDelta << 3;
224 NewHeight = (psoMask->cjBits / psoMask->lDelta) / 2;
226 /* Hide the cursor */
227 if(ppdev->pPointerAttributes->Enable != 0)
229 VGADDI_HideCursor(ppdev);
232 /* Reallocate the space for the cursor if necessary. */
233 if (ppdev->pPointerAttributes->Width != NewWidth ||
234 ppdev->pPointerAttributes->Height != NewHeight)
236 ULONG PointerAttributesSize;
237 PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes;
240 /* Determine the size of the pointer attributes */
241 PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) +
242 ((NewWidth * NewHeight * 2) >> 3);
244 /* Allocate memory for pointer attributes */
245 NewPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG);
246 *NewPointerAttributes = *ppdev->pPointerAttributes;
247 NewPointerAttributes->Width = NewWidth;
248 NewPointerAttributes->Height = NewHeight;
249 NewPointerAttributes->WidthInBytes = NewWidth >> 3;
250 EngFreeMem(ppdev->pPointerAttributes);
251 ppdev->pPointerAttributes = NewPointerAttributes;
253 /* Reallocate the space for the saved bits. */
254 VGADDI_FreeSavedScreenBits(ImageBehindCursor);
255 SavedMemSize = ((((NewWidth + 7) & ~0x7) + 16) * NewHeight) >> 3;
256 ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize);
259 /* Copy the new cursor in. */
260 for (i = 0; i < (NewHeight * 2); i++)
262 Src = (PUCHAR)psoMask->pvBits;
263 Src += (i * (NewWidth >> 3));
264 Dest = (PUCHAR)ppdev->pPointerAttributes->Pixels;
267 Dest += (((NewHeight * 3) - i - 1) * (NewWidth >> 3));
271 Dest += ((NewHeight - i - 1) * (NewWidth >> 3));
273 memcpy(Dest, Src, NewWidth >> 3);
276 /* Set the new cursor position */
277 ppdev->xyCursor.x = x;
278 ppdev->xyCursor.y = y;
280 /* Show the cursor */
281 VGADDI_ShowCursor(ppdev);
285 VGADDI_HideCursor(PPDEV ppdev)
287 ULONG i, j, cx, cy, bitpos;
290 /* Display what was behind cursor */
291 SizeX = ((oldx + ppdev->pPointerAttributes->Width) + 7) & ~0x7;
292 SizeX -= (oldx & ~0x7);
293 VGADDI_BltFromSavedScreenBits(oldx & ~0x7,
297 ppdev->pPointerAttributes->Height);
299 ppdev->pPointerAttributes->Enable = 0;
303 VGADDI_ShowCursor(PPDEV ppdev)
309 if (ppdev->pPointerAttributes->Enable != 0)
311 VGADDI_HideCursor(ppdev);
314 /* Capture pixels behind the cursor */
315 cx = ppdev->xyCursor.x;
316 cy = ppdev->xyCursor.y;
318 /* Used to repaint background */
319 SizeX = ((cx + ppdev->pPointerAttributes->Width) + 7) & ~0x7;
320 SizeX -= (cx & ~0x7);
322 VGADDI_BltToSavedScreenBits(ImageBehindCursor,
326 ppdev->pPointerAttributes->Height);
328 /* Display the cursor. */
329 AndMask = ppdev->pPointerAttributes->Pixels +
330 ppdev->pPointerAttributes->WidthInBytes *
331 ppdev->pPointerAttributes->Height;
332 VGADDI_BltPointerToVGA(ppdev->xyCursor.x,
334 ppdev->pPointerAttributes->Width,
335 ppdev->pPointerAttributes->Height,
338 VGADDI_BltPointerToVGA(ppdev->xyCursor.x,
340 ppdev->pPointerAttributes->Width,
341 ppdev->pPointerAttributes->Height,
342 ppdev->pPointerAttributes->Pixels,
345 /* Save the new cursor location. */
346 oldx = ppdev->xyCursor.x;
347 oldy = ppdev->xyCursor.y;
349 /* Mark the cursor as currently displayed. */
350 ppdev->pPointerAttributes->Enable = 1;