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"
34 /* GLOBALS *******************************************************************/
36 static VOID
VGADDI_HideCursor(PPDEV ppdev
);
37 static VOID
VGADDI_ShowCursor(PPDEV ppdev
, PRECTL prcl
);
39 /* FUNCTIONS *****************************************************************/
42 VGADDI_BltPointerToVGA(LONG StartX
, LONG StartY
, ULONG SizeX
,
43 ULONG SizeY
, PUCHAR MaskBits
, ULONG MaskPitch
, ULONG MaskOp
)
45 ULONG DestX
, EndX
, DestY
, EndY
;
55 DestX
= StartX
< 0 ? 0 : StartX
;
56 DestY
= StartY
< 0 ? 0 : StartY
;
57 EndX
= StartX
+ SizeX
;
58 EndY
= StartY
+ SizeY
;
60 /* Set write mode zero. */
61 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 5);
62 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0);
64 /* Select raster op. */
65 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 3);
66 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, MaskOp
);
70 /* Disable writes to pixels outside of the destination rectangle. */
71 Mask
= (1 << (8 - (DestX
% 8))) - 1;
72 if ((EndX
- DestX
) < (8 - (DestX
% 8)))
74 Mask
&= ~((1 << (8 - (EndX
% 8))) - 1);
76 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
77 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, Mask
);
80 Video
= (PUCHAR
)vidmem
+ DestY
* 80 + (DestX
>> 3);
81 Src
= MaskBits
+ (SizeY
- (DestY
- StartY
)) * MaskPitch
;
82 for (i
= DestY
; i
< EndY
; i
++, Video
+= 80)
85 SrcValue
= (*Src
) >> (DestX
% 8);
86 (VOID
)READ_REGISTER_UCHAR(Video
);
87 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
91 /* Enable writes to all pixels. */
92 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
93 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
95 /* Have we finished. */
96 if ((EndX
- DestX
) < (8 - (DestX
% 8)))
101 /* Fill any whole rows of eight pixels. */
102 Left
= (DestX
+ 7) & ~0x7;
103 Length
= (EndX
>> 3) - (Left
>> 3);
110 for (i
= DestY
; i
< EndY
; i
++)
112 Video
= (PUCHAR
)vidmem
+ i
* 80 + (Left
>> 3);
113 Src
= MaskBits
+ (EndY
- i
- 1) * MaskPitch
+ ((DestX
- StartX
) >> 3);
114 for (j
= 0; j
< Length
; j
++, Video
++, Src
++)
118 SrcValue
= (Src
[0] << (8 - Bits
));
119 SrcValue
|= (Src
[1] >> Bits
);
125 (VOID
)READ_REGISTER_UCHAR(Video
);
126 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
130 /* Fill any pixels on the right which don't fall into a complete row. */
133 /* Disable writes to pixels outside the destination rectangle. */
134 Mask
= ~((1 << (8 - (EndX
% 8))) - 1);
135 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
136 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, Mask
);
138 Video
= (PUCHAR
)vidmem
+ DestY
* 80 + (EndX
>> 3);
139 Src
= MaskBits
+ (SizeY
- (DestY
- StartY
)) * MaskPitch
+ (SizeX
>> 3) - 1;
140 for (i
= DestY
; i
< EndY
; i
++, Video
+=80)
143 SrcValue
= (Src
[0] << (8 - Bits
));
144 (VOID
)READ_REGISTER_UCHAR(Video
);
145 WRITE_REGISTER_UCHAR(Video
, SrcValue
);
148 /* Restore the default write masks. */
149 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x8);
150 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
153 /* Set write mode two. */
154 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 5);
155 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 2);
157 /* Select raster op replace. */
158 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 3);
159 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0);
162 BOOL
InitPointer(PPDEV ppdev
)
164 ULONG CursorWidth
= 32, CursorHeight
= 32;
165 ULONG PointerAttributesSize
;
168 ppdev
->xyHotSpot
.x
= 0;
169 ppdev
->xyHotSpot
.y
= 0;
171 /* Determine the size of the pointer attributes */
172 PointerAttributesSize
= sizeof(VIDEO_POINTER_ATTRIBUTES
) +
173 ((CursorWidth
* CursorHeight
* 2) >> 3);
175 /* Allocate memory for pointer attributes */
176 ppdev
->pPointerAttributes
= EngAllocMem(0, PointerAttributesSize
, ALLOC_TAG
);
178 ppdev
->pPointerAttributes
->Flags
= 0; /* FIXME: Do this right */
179 ppdev
->pPointerAttributes
->Width
= CursorWidth
;
180 ppdev
->pPointerAttributes
->Height
= CursorHeight
;
181 ppdev
->pPointerAttributes
->WidthInBytes
= CursorWidth
>> 3;
182 ppdev
->pPointerAttributes
->Enable
= 0;
183 ppdev
->pPointerAttributes
->Column
= 0;
184 ppdev
->pPointerAttributes
->Row
= 0;
186 /* Allocate memory for the pixels behind the cursor */
187 SavedMemSize
= ((((CursorWidth
+ 7) & ~0x7) + 16) * CursorHeight
) >> 3;
188 ppdev
->ImageBehindCursor
= VGADDI_AllocSavedScreenBits(SavedMemSize
);
194 DrvMovePointer(IN SURFOBJ
* pso
,
199 PPDEV ppdev
= (PPDEV
)pso
->dhpdev
;
201 VGADDI_HideCursor(ppdev
);
205 ppdev
->pPointerAttributes
->Column
= x
;
206 ppdev
->pPointerAttributes
->Row
= y
;
208 VGADDI_ShowCursor(ppdev
, prcl
);
214 DrvSetPointerShape(SURFOBJ
* pso
,
225 PPDEV ppdev
= (PPDEV
)pso
->dhpdev
;
226 ULONG NewWidth
, NewHeight
;
235 /* Hide the cursor */
236 VGADDI_HideCursor(ppdev
);
238 NewWidth
= abs(psoMask
->lDelta
) << 3;
239 NewHeight
= (psoMask
->cjBits
/ abs(psoMask
->lDelta
)) / 2;
241 /* Reallocate the space for the cursor if necessary. */
242 if (ppdev
->pPointerAttributes
->Width
!= NewWidth
||
243 ppdev
->pPointerAttributes
->Height
!= NewHeight
)
245 ULONG PointerAttributesSize
;
246 PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes
;
249 /* Determine the size of the pointer attributes */
250 PointerAttributesSize
= sizeof(VIDEO_POINTER_ATTRIBUTES
) +
251 ((NewWidth
* NewHeight
* 2) >> 3);
253 /* Allocate memory for pointer attributes */
254 NewPointerAttributes
= EngAllocMem(0, PointerAttributesSize
, ALLOC_TAG
);
255 *NewPointerAttributes
= *ppdev
->pPointerAttributes
;
256 NewPointerAttributes
->Width
= NewWidth
;
257 NewPointerAttributes
->Height
= NewHeight
;
258 NewPointerAttributes
->WidthInBytes
= NewWidth
>> 3;
259 EngFreeMem(ppdev
->pPointerAttributes
);
260 ppdev
->pPointerAttributes
= NewPointerAttributes
;
262 /* Reallocate the space for the saved bits. */
263 VGADDI_FreeSavedScreenBits(ppdev
->ImageBehindCursor
);
264 SavedMemSize
= ((((NewWidth
+ 7) & ~0x7) + 16) * NewHeight
) >> 3;
265 ppdev
->ImageBehindCursor
= VGADDI_AllocSavedScreenBits(SavedMemSize
);
268 Src
= (PUCHAR
)psoMask
->pvScan0
;
269 /* Copy the new cursor in. */
270 for (i
= 0; i
< (NewHeight
* 2); i
++)
272 Dest
= (PUCHAR
)ppdev
->pPointerAttributes
->Pixels
;
275 Dest
+= (((NewHeight
* 3) - i
- 1) * (NewWidth
>> 3));
279 Dest
+= ((NewHeight
- i
- 1) * (NewWidth
>> 3));
281 memcpy(Dest
, Src
, NewWidth
>> 3);
282 Src
+= psoMask
->lDelta
;
285 /* Set the new cursor position */
286 ppdev
->xyHotSpot
.x
= xHot
;
287 ppdev
->xyHotSpot
.y
= yHot
;
291 ppdev
->pPointerAttributes
->Column
= x
;
292 ppdev
->pPointerAttributes
->Row
= y
;
294 /* show the cursor */
295 VGADDI_ShowCursor(ppdev
, prcl
);
298 return SPS_ACCEPT_EXCLUDE
;
302 VGADDI_ComputePointerRect(PPDEV ppdev
, LONG X
, LONG Y
, PRECTL Rect
)
306 SizeX
= min(((X
+ ppdev
->pPointerAttributes
->Width
) + 7) & ~0x7, ppdev
->sizeSurf
.cx
);
308 SizeY
= min(ppdev
->pPointerAttributes
->Height
, ppdev
->sizeSurf
.cy
- Y
);
310 Rect
->left
= max(X
, 0) & ~0x7;
311 Rect
->top
= max(Y
, 0);
312 Rect
->right
= Rect
->left
+ SizeX
;
313 Rect
->bottom
= Rect
->top
+ SizeY
;
317 VGADDI_HideCursor(PPDEV ppdev
)
319 if(ppdev
->pPointerAttributes
->Enable
)
324 ppdev
->pPointerAttributes
->Enable
= 0;
326 cx
= ppdev
->pPointerAttributes
->Column
- ppdev
->xyHotSpot
.x
;
327 cy
= ppdev
->pPointerAttributes
->Row
- ppdev
->xyHotSpot
.y
;
329 VGADDI_ComputePointerRect(ppdev
, cx
, cy
, &Rect
);
331 /* Display what was behind cursor */
332 VGADDI_BltFromSavedScreenBits(Rect
.left
,
334 ppdev
->ImageBehindCursor
,
335 Rect
.right
- Rect
.left
,
336 Rect
.bottom
- Rect
.top
);
341 VGADDI_ShowCursor(PPDEV ppdev
, PRECTL prcl
)
344 PUCHAR AndMask
, XorMask
;
348 if(ppdev
->pPointerAttributes
->Enable
)
352 /* Mark the cursor as currently displayed. */
353 ppdev
->pPointerAttributes
->Enable
= 1;
355 cx
= ppdev
->pPointerAttributes
->Column
- ppdev
->xyHotSpot
.x
;
356 cy
= ppdev
->pPointerAttributes
->Row
- ppdev
->xyHotSpot
.y
;
358 /* Capture pixels behind the cursor */
359 VGADDI_ComputePointerRect(ppdev
, cx
, cy
, &Rect
);
361 VGADDI_BltToSavedScreenBits(ppdev
->ImageBehindCursor
,
364 Rect
.right
- Rect
.left
,
365 Rect
.bottom
- Rect
.top
);
367 /* Display the cursor. */
368 SizeX
= min(ppdev
->pPointerAttributes
->Width
, ppdev
->sizeSurf
.cx
- cx
);
369 SizeY
= min(ppdev
->pPointerAttributes
->Height
, ppdev
->sizeSurf
.cy
- cy
);
370 AndMask
= ppdev
->pPointerAttributes
->Pixels
+
371 (ppdev
->pPointerAttributes
->Height
- SizeY
) * ppdev
->pPointerAttributes
->WidthInBytes
;
372 VGADDI_BltPointerToVGA(cx
,
377 ppdev
->pPointerAttributes
->WidthInBytes
,
380 ppdev
->pPointerAttributes
->WidthInBytes
*
381 ppdev
->pPointerAttributes
->Height
;
382 VGADDI_BltPointerToVGA(cx
,
387 ppdev
->pPointerAttributes
->WidthInBytes
,