Mercurial > sdl-ios-xcode
annotate src/video/SDL_cursor.c @ 4216:5b99971a27b4 SDL-1.2
Fixed bug #698
Hans de Goede 2009-02-13 01:10:52 PST
Since the new "glitch free" version of pulseaudio (used in Fedora 10 amongst
others), the sound of SDL using apps (like a simple playmus call) has been
crackling.
While looking in to fixing this I noticed that the current pulseaudio code in
SDL uses pa_simple. However pa_simple uses a thread to pump pulseaudio events
and ipc, given that SDL already has its own thread for audio handling this is
clearly suboptimal, leading to unnecessary context switching IPC, etc. Also
pa_simple does not allow one to implement the WaitAudio() callback for SDL
audiodrivers properly.
Given that my work is mostly a rewrite (although some original pieces remain)
I'm attaching the new .c and .h file, as that is easier to review then the huge
diff.
Let me know if you also want the diff.
This new version has the following features:
-no longer use an additional thread next to the SDL sound thread
-do not crackle with glitch free audio
-when used with a newer pulse, which does glitch free audio, the total latency
is
the same as with the alsa driver
-proper WaitAudio() implementation, saving another mixlen worth of latency
-adds a WaitDone() implementation
This patch has been written in consultancy with Lennart Poetering (the
pulseaudio author) and has been reviewed by him for correct use of the pa API.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 21 Sep 2009 09:27:08 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library 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 GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1296
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
113
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
24 /* General cursor handling code for SDL */ | |
25 | |
26 #include "SDL_mutex.h" | |
27 #include "SDL_video.h" | |
28 #include "SDL_mouse.h" | |
29 #include "SDL_blit.h" | |
30 #include "SDL_sysvideo.h" | |
31 #include "SDL_cursor_c.h" | |
32 #include "SDL_pixels_c.h" | |
33 #include "default_cursor.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
34 #include "../events/SDL_sysevents.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
35 #include "../events/SDL_events_c.h" |
0 | 36 |
37 /* These are static for our cursor handling code */ | |
38 volatile int SDL_cursorstate = CURSOR_VISIBLE; | |
39 SDL_Cursor *SDL_cursor = NULL; | |
40 static SDL_Cursor *SDL_defcursor = NULL; | |
41 SDL_mutex *SDL_cursorlock = NULL; | |
42 | |
43 /* Public functions */ | |
44 void SDL_CursorQuit(void) | |
45 { | |
46 if ( SDL_cursor != NULL ) { | |
47 SDL_Cursor *cursor; | |
48 | |
49 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
50 if ( SDL_cursor != SDL_defcursor ) { | |
51 SDL_FreeCursor(SDL_cursor); | |
52 } | |
53 SDL_cursor = NULL; | |
54 if ( SDL_defcursor != NULL ) { | |
55 cursor = SDL_defcursor; | |
56 SDL_defcursor = NULL; | |
57 SDL_FreeCursor(cursor); | |
58 } | |
59 } | |
60 if ( SDL_cursorlock != NULL ) { | |
61 SDL_DestroyMutex(SDL_cursorlock); | |
62 SDL_cursorlock = NULL; | |
63 } | |
64 } | |
65 int SDL_CursorInit(Uint32 multithreaded) | |
66 { | |
67 /* We don't have mouse focus, and the cursor isn't drawn yet */ | |
1140
af8b0f9ac2f4
iPod Linux framebuffer support.
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
68 #ifndef IPOD |
0 | 69 SDL_cursorstate = CURSOR_VISIBLE; |
1140
af8b0f9ac2f4
iPod Linux framebuffer support.
Ryan C. Gordon <icculus@icculus.org>
parents:
769
diff
changeset
|
70 #endif |
0 | 71 |
72 /* Create the default cursor */ | |
73 if ( SDL_defcursor == NULL ) { | |
74 SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask, | |
75 DEFAULT_CWIDTH, DEFAULT_CHEIGHT, | |
76 DEFAULT_CHOTX, DEFAULT_CHOTY); | |
77 SDL_SetCursor(SDL_defcursor); | |
78 } | |
79 | |
80 /* Create a lock if necessary */ | |
81 if ( multithreaded ) { | |
82 SDL_cursorlock = SDL_CreateMutex(); | |
83 } | |
84 | |
85 /* That's it! */ | |
86 return(0); | |
87 } | |
88 | |
89 /* Multi-thread support for cursors */ | |
90 #ifndef SDL_LockCursor | |
91 void SDL_LockCursor(void) | |
92 { | |
93 if ( SDL_cursorlock ) { | |
94 SDL_mutexP(SDL_cursorlock); | |
95 } | |
96 } | |
97 #endif | |
98 #ifndef SDL_UnlockCursor | |
99 void SDL_UnlockCursor(void) | |
100 { | |
101 if ( SDL_cursorlock ) { | |
102 SDL_mutexV(SDL_cursorlock); | |
103 } | |
104 } | |
105 #endif | |
106 | |
107 /* Software cursor drawing support */ | |
108 SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, | |
109 int w, int h, int hot_x, int hot_y) | |
110 { | |
111 SDL_VideoDevice *video = current_video; | |
112 int savelen; | |
113 int i; | |
114 SDL_Cursor *cursor; | |
115 | |
116 /* Make sure the width is a multiple of 8 */ | |
117 w = ((w+7)&~7); | |
118 | |
119 /* Sanity check the hot spot */ | |
120 if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) { | |
121 SDL_SetError("Cursor hot spot doesn't lie within cursor"); | |
122 return(NULL); | |
123 } | |
124 | |
125 /* Allocate memory for the cursor */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
126 cursor = (SDL_Cursor *)SDL_malloc(sizeof *cursor); |
0 | 127 if ( cursor == NULL ) { |
128 SDL_OutOfMemory(); | |
129 return(NULL); | |
130 } | |
131 savelen = (w*4)*h; | |
132 cursor->area.x = 0; | |
133 cursor->area.y = 0; | |
134 cursor->area.w = w; | |
135 cursor->area.h = h; | |
136 cursor->hot_x = hot_x; | |
137 cursor->hot_y = hot_y; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
138 cursor->data = (Uint8 *)SDL_malloc((w/8)*h*2); |
0 | 139 cursor->mask = cursor->data+((w/8)*h); |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
140 cursor->save[0] = (Uint8 *)SDL_malloc(savelen*2); |
0 | 141 cursor->save[1] = cursor->save[0] + savelen; |
142 cursor->wm_cursor = NULL; | |
143 if ( ! cursor->data || ! cursor->save[0] ) { | |
144 SDL_FreeCursor(cursor); | |
145 SDL_OutOfMemory(); | |
146 return(NULL); | |
147 } | |
148 for ( i=((w/8)*h)-1; i>=0; --i ) { | |
149 cursor->data[i] = data[i]; | |
150 cursor->mask[i] = mask[i] | data[i]; | |
151 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
152 SDL_memset(cursor->save[0], 0, savelen*2); |
0 | 153 |
154 /* If the window manager gives us a good cursor, we're done! */ | |
155 if ( video->CreateWMCursor ) { | |
156 cursor->wm_cursor = video->CreateWMCursor(video, data, mask, | |
157 w, h, hot_x, hot_y); | |
158 } else { | |
159 cursor->wm_cursor = NULL; | |
160 } | |
161 return(cursor); | |
162 } | |
163 | |
164 /* SDL_SetCursor(NULL) can be used to force the cursor redraw, | |
165 if this is desired for any reason. This is used when setting | |
166 the video mode and when the SDL window gains the mouse focus. | |
167 */ | |
168 void SDL_SetCursor (SDL_Cursor *cursor) | |
169 { | |
170 SDL_VideoDevice *video = current_video; | |
171 SDL_VideoDevice *this = current_video; | |
172 | |
173 /* Make sure that the video subsystem has been initialized */ | |
174 if ( ! video ) { | |
175 return; | |
176 } | |
177 | |
178 /* Prevent the event thread from moving the mouse */ | |
179 SDL_LockCursor(); | |
180 | |
181 /* Set the new cursor */ | |
182 if ( cursor && (cursor != SDL_cursor) ) { | |
183 /* Erase the current mouse position */ | |
184 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
185 SDL_EraseCursor(SDL_VideoSurface); | |
186 } else if ( video->MoveWMCursor ) { | |
187 /* If the video driver is moving the cursor directly, | |
188 it needs to hide the old cursor before (possibly) | |
189 showing the new one. (But don't erase NULL cursor) | |
190 */ | |
3897
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
191 if ( SDL_cursor && video->ShowWMCursor ) { |
0 | 192 video->ShowWMCursor(this, NULL); |
193 } | |
194 } | |
195 SDL_cursor = cursor; | |
196 } | |
197 | |
198 /* Draw the new mouse cursor */ | |
199 if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) { | |
200 /* Use window manager cursor if possible */ | |
3897
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
201 int show_wm_cursor = 0; |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
202 if ( SDL_cursor->wm_cursor && video->ShowWMCursor ) { |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
203 show_wm_cursor = video->ShowWMCursor(this, SDL_cursor->wm_cursor); |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
204 } |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
205 if ( show_wm_cursor ) { |
0 | 206 SDL_cursorstate &= ~CURSOR_USINGSW; |
1296 | 207 } else { |
0 | 208 SDL_cursorstate |= CURSOR_USINGSW; |
209 if ( video->ShowWMCursor ) { | |
210 video->ShowWMCursor(this, NULL); | |
211 } | |
212 { int x, y; | |
213 SDL_GetMouseState(&x, &y); | |
214 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
215 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
216 } | |
217 SDL_DrawCursor(SDL_VideoSurface); | |
218 } | |
219 } else { | |
220 /* Erase window manager mouse (cursor not visible) */ | |
221 if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) { | |
222 SDL_EraseCursor(SDL_VideoSurface); | |
223 } else { | |
224 if ( video ) { | |
3897
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
225 if ( video->ShowWMCursor ) { |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
226 video->ShowWMCursor(this, NULL); |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
227 } |
0 | 228 } |
229 } | |
230 } | |
231 SDL_UnlockCursor(); | |
232 } | |
233 | |
234 SDL_Cursor * SDL_GetCursor (void) | |
235 { | |
236 return(SDL_cursor); | |
237 } | |
238 | |
239 void SDL_FreeCursor (SDL_Cursor *cursor) | |
240 { | |
241 if ( cursor ) { | |
242 if ( cursor == SDL_cursor ) { | |
243 SDL_SetCursor(SDL_defcursor); | |
244 } | |
245 if ( cursor != SDL_defcursor ) { | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
246 SDL_VideoDevice *video = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
247 SDL_VideoDevice *this = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
248 |
0 | 249 if ( cursor->data ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
250 SDL_free(cursor->data); |
0 | 251 } |
252 if ( cursor->save[0] ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
253 SDL_free(cursor->save[0]); |
0 | 254 } |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
255 if ( video && cursor->wm_cursor ) { |
3897
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
256 if ( video->FreeWMCursor ) { |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
257 video->FreeWMCursor(this, cursor->wm_cursor); |
37dab4a917c4
Check video driver mouse cursor pointers before using them
Patrice Mandin <patmandin@gmail.com>
parents:
1428
diff
changeset
|
258 } |
0 | 259 } |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
260 SDL_free(cursor); |
0 | 261 } |
262 } | |
263 } | |
264 | |
265 int SDL_ShowCursor (int toggle) | |
266 { | |
267 int showing; | |
268 | |
269 showing = (SDL_cursorstate & CURSOR_VISIBLE); | |
270 if ( toggle >= 0 ) { | |
271 SDL_LockCursor(); | |
272 if ( toggle ) { | |
273 SDL_cursorstate |= CURSOR_VISIBLE; | |
274 } else { | |
275 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
276 } | |
277 SDL_UnlockCursor(); | |
278 if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) { | |
279 SDL_VideoDevice *video = current_video; | |
280 SDL_VideoDevice *this = current_video; | |
281 | |
282 SDL_SetCursor(NULL); | |
283 if ( video && video->CheckMouseMode ) { | |
284 video->CheckMouseMode(this); | |
285 } | |
286 } | |
287 } else { | |
288 /* Query current state */ ; | |
289 } | |
290 return(showing ? 1 : 0); | |
291 } | |
292 | |
293 void SDL_WarpMouse (Uint16 x, Uint16 y) | |
294 { | |
295 SDL_VideoDevice *video = current_video; | |
296 SDL_VideoDevice *this = current_video; | |
297 | |
595
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
298 if ( !video || !SDL_PublicSurface ) { |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
299 SDL_SetError("A video mode must be set before warping mouse"); |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
300 return; |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
301 } |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
302 |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
303 /* If we have an offset video mode, offset the mouse coordinates */ |
1163
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
304 if (this->screen->pitch == 0) { |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
305 x += this->screen->offset / this->screen->format->BytesPerPixel; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
306 y += this->screen->offset; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
307 } else { |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
308 x += (this->screen->offset % this->screen->pitch) / |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
309 this->screen->format->BytesPerPixel; |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
310 y += (this->screen->offset / this->screen->pitch); |
96ef83467667
Prevent division-by-zero in WarpMouse if surface's pitch is zero (a GL surface?).
Ryan C. Gordon <icculus@icculus.org>
parents:
1140
diff
changeset
|
311 } |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
312 |
0 | 313 /* This generates a mouse motion event */ |
314 if ( video->WarpWMCursor ) { | |
315 video->WarpWMCursor(this, x, y); | |
316 } else { | |
317 SDL_PrivateMouseMotion(0, 0, x, y); | |
318 } | |
319 } | |
320 | |
321 void SDL_MoveCursor(int x, int y) | |
322 { | |
323 SDL_VideoDevice *video = current_video; | |
324 | |
325 /* Erase and update the current mouse position */ | |
326 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
327 /* Erase and redraw mouse cursor in new position */ | |
328 SDL_LockCursor(); | |
329 SDL_EraseCursor(SDL_VideoSurface); | |
330 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
331 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
332 SDL_DrawCursor(SDL_VideoSurface); | |
333 SDL_UnlockCursor(); | |
334 } else if ( video->MoveWMCursor ) { | |
335 video->MoveWMCursor(video, x, y); | |
336 } | |
337 } | |
338 | |
339 /* Keep track of the current cursor colors */ | |
340 static int palette_changed = 1; | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
341 static Uint8 pixels8[2]; |
0 | 342 |
343 void SDL_CursorPaletteChanged(void) | |
344 { | |
345 palette_changed = 1; | |
346 } | |
347 | |
348 void SDL_MouseRect(SDL_Rect *area) | |
349 { | |
350 int clip_diff; | |
351 | |
352 *area = SDL_cursor->area; | |
353 if ( area->x < 0 ) { | |
354 area->w += area->x; | |
355 area->x = 0; | |
356 } | |
357 if ( area->y < 0 ) { | |
358 area->h += area->y; | |
359 area->y = 0; | |
360 } | |
361 clip_diff = (area->x+area->w)-SDL_VideoSurface->w; | |
362 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
363 area->w = area->w < clip_diff ? 0 : area->w-clip_diff; |
0 | 364 } |
365 clip_diff = (area->y+area->h)-SDL_VideoSurface->h; | |
366 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
367 area->h = area->h < clip_diff ? 0 : area->h-clip_diff; |
0 | 368 } |
369 } | |
370 | |
371 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) | |
372 { | |
373 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; | |
374 int i, w, h; | |
375 Uint8 *data, datab; | |
376 Uint8 *mask, maskb; | |
377 | |
378 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
379 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
380 switch (screen->format->BytesPerPixel) { | |
381 | |
382 case 1: { | |
383 Uint8 *dst; | |
384 int dstskip; | |
385 | |
386 if ( palette_changed ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
387 pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); |
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
388 pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); |
0 | 389 palette_changed = 0; |
390 } | |
391 dst = (Uint8 *)screen->pixels + | |
392 (SDL_cursor->area.y+area->y)*screen->pitch + | |
393 SDL_cursor->area.x; | |
394 dstskip = screen->pitch-area->w; | |
395 | |
396 for ( h=area->h; h; h-- ) { | |
397 for ( w=area->w/8; w; w-- ) { | |
398 maskb = *mask++; | |
399 datab = *data++; | |
400 for ( i=0; i<8; ++i ) { | |
401 if ( maskb & 0x80 ) { | |
402 *dst = pixels8[datab>>7]; | |
403 } | |
404 maskb <<= 1; | |
405 datab <<= 1; | |
406 dst++; | |
407 } | |
408 } | |
409 dst += dstskip; | |
410 } | |
411 } | |
412 break; | |
413 | |
414 case 2: { | |
415 Uint16 *dst; | |
416 int dstskip; | |
417 | |
418 dst = (Uint16 *)screen->pixels + | |
419 (SDL_cursor->area.y+area->y)*screen->pitch/2 + | |
420 SDL_cursor->area.x; | |
421 dstskip = (screen->pitch/2)-area->w; | |
422 | |
423 for ( h=area->h; h; h-- ) { | |
424 for ( w=area->w/8; w; w-- ) { | |
425 maskb = *mask++; | |
426 datab = *data++; | |
427 for ( i=0; i<8; ++i ) { | |
428 if ( maskb & 0x80 ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
429 *dst = (Uint16)pixels[datab>>7]; |
0 | 430 } |
431 maskb <<= 1; | |
432 datab <<= 1; | |
433 dst++; | |
434 } | |
435 } | |
436 dst += dstskip; | |
437 } | |
438 } | |
439 break; | |
440 | |
441 case 3: { | |
442 Uint8 *dst; | |
443 int dstskip; | |
444 | |
445 dst = (Uint8 *)screen->pixels + | |
446 (SDL_cursor->area.y+area->y)*screen->pitch + | |
447 SDL_cursor->area.x*3; | |
448 dstskip = screen->pitch-area->w*3; | |
449 | |
450 for ( h=area->h; h; h-- ) { | |
451 for ( w=area->w/8; w; w-- ) { | |
452 maskb = *mask++; | |
453 datab = *data++; | |
454 for ( i=0; i<8; ++i ) { | |
455 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
456 SDL_memset(dst,pixels[datab>>7],3); |
0 | 457 } |
458 maskb <<= 1; | |
459 datab <<= 1; | |
460 dst += 3; | |
461 } | |
462 } | |
463 dst += dstskip; | |
464 } | |
465 } | |
466 break; | |
467 | |
468 case 4: { | |
469 Uint32 *dst; | |
470 int dstskip; | |
471 | |
472 dst = (Uint32 *)screen->pixels + | |
473 (SDL_cursor->area.y+area->y)*screen->pitch/4 + | |
474 SDL_cursor->area.x; | |
475 dstskip = (screen->pitch/4)-area->w; | |
476 | |
477 for ( h=area->h; h; h-- ) { | |
478 for ( w=area->w/8; w; w-- ) { | |
479 maskb = *mask++; | |
480 datab = *data++; | |
481 for ( i=0; i<8; ++i ) { | |
482 if ( maskb & 0x80 ) { | |
483 *dst = pixels[datab>>7]; | |
484 } | |
485 maskb <<= 1; | |
486 datab <<= 1; | |
487 dst++; | |
488 } | |
489 } | |
490 dst += dstskip; | |
491 } | |
492 } | |
493 break; | |
494 } | |
495 } | |
496 | |
497 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) | |
498 { | |
499 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; | |
500 int h; | |
501 int x, minx, maxx; | |
502 Uint8 *data, datab = 0; | |
503 Uint8 *mask, maskb = 0; | |
504 Uint8 *dst; | |
505 int dstbpp, dstskip; | |
506 | |
507 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
508 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
509 dstbpp = screen->format->BytesPerPixel; | |
510 dst = (Uint8 *)screen->pixels + | |
511 (SDL_cursor->area.y+area->y)*screen->pitch + | |
512 SDL_cursor->area.x*dstbpp; | |
513 dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; | |
514 | |
515 minx = area->x; | |
516 maxx = area->x+area->w; | |
517 if ( screen->format->BytesPerPixel == 1 ) { | |
518 if ( palette_changed ) { | |
1428
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
519 pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); |
5f52867ba65c
Update for Visual C++ 6.0
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
520 pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); |
0 | 521 palette_changed = 0; |
522 } | |
523 for ( h=area->h; h; h-- ) { | |
524 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
525 if ( (x%8) == 0 ) { | |
526 maskb = *mask++; | |
527 datab = *data++; | |
528 } | |
529 if ( (x >= minx) && (x < maxx) ) { | |
530 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
531 SDL_memset(dst, pixels8[datab>>7], dstbpp); |
0 | 532 } |
533 } | |
534 maskb <<= 1; | |
535 datab <<= 1; | |
536 dst += dstbpp; | |
537 } | |
538 dst += dstskip; | |
539 } | |
540 } else { | |
541 for ( h=area->h; h; h-- ) { | |
542 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
543 if ( (x%8) == 0 ) { | |
544 maskb = *mask++; | |
545 datab = *data++; | |
546 } | |
547 if ( (x >= minx) && (x < maxx) ) { | |
548 if ( maskb & 0x80 ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
549 SDL_memset(dst, pixels[datab>>7], dstbpp); |
0 | 550 } |
551 } | |
552 maskb <<= 1; | |
553 datab <<= 1; | |
554 dst += dstbpp; | |
555 } | |
556 dst += dstskip; | |
557 } | |
558 } | |
559 } | |
560 | |
561 /* This handles the ugly work of converting the saved cursor background from | |
562 the pixel format of the shadow surface to that of the video surface. | |
563 This is only necessary when blitting from a shadow surface of a different | |
564 pixel format than the video surface, and using a software rendered cursor. | |
565 */ | |
566 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) | |
567 { | |
568 SDL_BlitInfo info; | |
569 SDL_loblit RunBlit; | |
570 | |
571 /* Make sure we can steal the blit mapping */ | |
572 if ( screen->map->dst != SDL_VideoSurface ) { | |
573 return; | |
574 } | |
575 | |
576 /* Set up the blit information */ | |
577 info.s_pixels = SDL_cursor->save[1]; | |
578 info.s_width = w; | |
579 info.s_height = h; | |
580 info.s_skip = 0; | |
581 info.d_pixels = SDL_cursor->save[0]; | |
582 info.d_width = w; | |
583 info.d_height = h; | |
584 info.d_skip = 0; | |
585 info.aux_data = screen->map->sw_data->aux_data; | |
586 info.src = screen->format; | |
587 info.table = screen->map->table; | |
588 info.dst = SDL_VideoSurface->format; | |
589 RunBlit = screen->map->sw_data->blit; | |
590 | |
591 /* Run the actual software blit */ | |
592 RunBlit(&info); | |
593 } | |
594 | |
595 void SDL_DrawCursorNoLock(SDL_Surface *screen) | |
596 { | |
597 SDL_Rect area; | |
598 | |
599 /* Get the mouse rectangle, clipped to the screen */ | |
600 SDL_MouseRect(&area); | |
601 if ( (area.w == 0) || (area.h == 0) ) { | |
602 return; | |
603 } | |
604 | |
605 /* Copy mouse background */ | |
606 { int w, h, screenbpp; | |
607 Uint8 *src, *dst; | |
608 | |
609 /* Set up the copy pointers */ | |
610 screenbpp = screen->format->BytesPerPixel; | |
611 if ( (screen == SDL_VideoSurface) || | |
612 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
613 dst = SDL_cursor->save[0]; | |
614 } else { | |
615 dst = SDL_cursor->save[1]; | |
616 } | |
617 src = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
618 area.x * screenbpp; | |
619 | |
620 /* Perform the copy */ | |
621 w = area.w*screenbpp; | |
622 h = area.h; | |
623 while ( h-- ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
624 SDL_memcpy(dst, src, w); |
0 | 625 dst += w; |
626 src += screen->pitch; | |
627 } | |
628 } | |
629 | |
630 /* Draw the mouse cursor */ | |
631 area.x -= SDL_cursor->area.x; | |
632 area.y -= SDL_cursor->area.y; | |
633 if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { | |
634 SDL_DrawCursorFast(screen, &area); | |
635 } else { | |
636 SDL_DrawCursorSlow(screen, &area); | |
637 } | |
638 } | |
639 | |
640 void SDL_DrawCursor(SDL_Surface *screen) | |
641 { | |
642 /* Lock the screen if necessary */ | |
643 if ( screen == NULL ) { | |
644 return; | |
645 } | |
646 if ( SDL_MUSTLOCK(screen) ) { | |
647 if ( SDL_LockSurface(screen) < 0 ) { | |
648 return; | |
649 } | |
650 } | |
651 | |
652 SDL_DrawCursorNoLock(screen); | |
653 | |
654 /* Unlock the screen and update if necessary */ | |
655 if ( SDL_MUSTLOCK(screen) ) { | |
656 SDL_UnlockSurface(screen); | |
657 } | |
658 if ( (screen == SDL_VideoSurface) && | |
659 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
660 SDL_VideoDevice *video = current_video; | |
661 SDL_VideoDevice *this = current_video; | |
662 SDL_Rect area; | |
663 | |
664 SDL_MouseRect(&area); | |
665 | |
666 /* This can be called before a video mode is set */ | |
667 if ( video->UpdateRects ) { | |
668 video->UpdateRects(this, 1, &area); | |
669 } | |
670 } | |
671 } | |
672 | |
673 void SDL_EraseCursorNoLock(SDL_Surface *screen) | |
674 { | |
675 SDL_Rect area; | |
676 | |
677 /* Get the mouse rectangle, clipped to the screen */ | |
678 SDL_MouseRect(&area); | |
679 if ( (area.w == 0) || (area.h == 0) ) { | |
680 return; | |
681 } | |
682 | |
683 /* Copy mouse background */ | |
684 { int w, h, screenbpp; | |
685 Uint8 *src, *dst; | |
686 | |
687 /* Set up the copy pointers */ | |
688 screenbpp = screen->format->BytesPerPixel; | |
689 if ( (screen == SDL_VideoSurface) || | |
690 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
691 src = SDL_cursor->save[0]; | |
692 } else { | |
693 src = SDL_cursor->save[1]; | |
694 } | |
695 dst = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
696 area.x * screenbpp; | |
697 | |
698 /* Perform the copy */ | |
699 w = area.w*screenbpp; | |
700 h = area.h; | |
701 while ( h-- ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
702 SDL_memcpy(dst, src, w); |
0 | 703 src += w; |
704 dst += screen->pitch; | |
705 } | |
706 | |
707 /* Perform pixel conversion on cursor background */ | |
708 if ( src > SDL_cursor->save[1] ) { | |
709 SDL_ConvertCursorSave(screen, area.w, area.h); | |
710 } | |
711 } | |
712 } | |
713 | |
714 void SDL_EraseCursor(SDL_Surface *screen) | |
715 { | |
716 /* Lock the screen if necessary */ | |
717 if ( screen == NULL ) { | |
718 return; | |
719 } | |
720 if ( SDL_MUSTLOCK(screen) ) { | |
721 if ( SDL_LockSurface(screen) < 0 ) { | |
722 return; | |
723 } | |
724 } | |
725 | |
726 SDL_EraseCursorNoLock(screen); | |
727 | |
728 /* Unlock the screen and update if necessary */ | |
729 if ( SDL_MUSTLOCK(screen) ) { | |
730 SDL_UnlockSurface(screen); | |
731 } | |
732 if ( (screen == SDL_VideoSurface) && | |
733 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
734 SDL_VideoDevice *video = current_video; | |
735 SDL_VideoDevice *this = current_video; | |
736 SDL_Rect area; | |
737 | |
738 SDL_MouseRect(&area); | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
739 if ( video->UpdateRects ) { |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
740 video->UpdateRects(this, 1, &area); |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
741 } |
0 | 742 } |
743 } | |
744 | |
745 /* Reset the cursor on video mode change | |
746 FIXME: Keep track of all cursors, and reset them all. | |
747 */ | |
748 void SDL_ResetCursor(void) | |
749 { | |
750 int savelen; | |
751 | |
752 if ( SDL_cursor ) { | |
753 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; | |
754 SDL_cursor->area.x = 0; | |
755 SDL_cursor->area.y = 0; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
756 SDL_memset(SDL_cursor->save[0], 0, savelen); |
0 | 757 } |
758 } |