Mercurial > sdl-ios-xcode
annotate test/threadwin.c @ 1045:63b8e93a3a52
Release CPU when waiting
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Fri, 01 Apr 2005 15:19:26 +0000 |
parents | cb40b26523a5 |
children | be9c9c8f6d53 |
rev | line source |
---|---|
0 | 1 |
2 /* Test out the multi-threaded event handling functions */ | |
3 | |
4 #include <stdlib.h> | |
5 #include <stdio.h> | |
6 #include <string.h> | |
7 | |
8 #include "SDL.h" | |
9 #include "SDL_thread.h" | |
10 | |
11 /* Are we done yet? */ | |
12 static int done = 0; | |
13 | |
14 /* Is the cursor visible? */ | |
15 static int visible = 1; | |
16 | |
17 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp) | |
18 { | |
19 SDL_Surface *icon; | |
20 Uint8 *pixels; | |
21 Uint8 *mask; | |
22 int mlen, i; | |
23 | |
24 *maskp = NULL; | |
25 | |
26 /* Load the icon surface */ | |
27 icon = SDL_LoadBMP(file); | |
28 if ( icon == NULL ) { | |
29 fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError()); | |
30 return(NULL); | |
31 } | |
32 | |
33 /* Check width and height */ | |
34 if ( (icon->w%8) != 0 ) { | |
35 fprintf(stderr, "Icon width must be a multiple of 8!\n"); | |
36 SDL_FreeSurface(icon); | |
37 return(NULL); | |
38 } | |
39 if ( icon->format->palette == NULL ) { | |
40 fprintf(stderr, "Icon must have a palette!\n"); | |
41 SDL_FreeSurface(icon); | |
42 return(NULL); | |
43 } | |
44 | |
45 /* Set the colorkey */ | |
46 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels)); | |
47 | |
48 /* Create the mask */ | |
49 pixels = (Uint8 *)icon->pixels; | |
50 printf("Transparent pixel: (%d,%d,%d)\n", | |
51 icon->format->palette->colors[*pixels].r, | |
52 icon->format->palette->colors[*pixels].g, | |
53 icon->format->palette->colors[*pixels].b); | |
54 mlen = icon->w*icon->h; | |
55 mask = (Uint8 *)malloc(mlen/8); | |
56 if ( mask == NULL ) { | |
57 fprintf(stderr, "Out of memory!\n"); | |
58 SDL_FreeSurface(icon); | |
59 return(NULL); | |
60 } | |
61 memset(mask, 0, mlen/8); | |
62 for ( i=0; i<mlen; ) { | |
63 if ( pixels[i] != *pixels ) | |
64 mask[i/8] |= 0x01; | |
65 ++i; | |
66 if ( (i%8) != 0 ) | |
67 mask[i/8] <<= 1; | |
68 } | |
69 *maskp = mask; | |
70 return(icon); | |
71 } | |
72 | |
73 int FilterEvents(const SDL_Event *event) | |
74 { | |
75 static int reallyquit = 0; | |
76 | |
77 switch (event->type) { | |
78 | |
79 case SDL_ACTIVEEVENT: | |
80 /* See what happened */ | |
81 printf("App %s ", | |
82 event->active.gain ? "gained" : "lost"); | |
83 if ( event->active.state & SDL_APPACTIVE ) | |
84 printf("active "); | |
85 if ( event->active.state & SDL_APPMOUSEFOCUS ) | |
86 printf("mouse "); | |
87 if ( event->active.state & SDL_APPINPUTFOCUS ) | |
88 printf("input "); | |
89 printf("focus\n"); | |
90 | |
91 /* See if we are iconified or restored */ | |
92 if ( event->active.state & SDL_APPACTIVE ) { | |
93 printf("App has been %s\n", | |
94 event->active.gain ? | |
95 "restored" : "iconified"); | |
96 } | |
97 return(0); | |
98 | |
99 /* This is important! Queue it if we want to quit. */ | |
100 case SDL_QUIT: | |
101 if ( ! reallyquit ) { | |
102 reallyquit = 1; | |
103 printf("Quit requested\n"); | |
104 return(0); | |
105 } | |
106 printf("Quit demanded\n"); | |
107 return(1); | |
108 | |
109 /* Mouse and keyboard events go to threads */ | |
110 case SDL_MOUSEMOTION: | |
111 case SDL_MOUSEBUTTONDOWN: | |
112 case SDL_MOUSEBUTTONUP: | |
113 case SDL_KEYDOWN: | |
114 case SDL_KEYUP: | |
115 return(1); | |
116 | |
117 /* Drop all other events */ | |
118 default: | |
119 return(0); | |
120 } | |
121 } | |
122 | |
123 int HandleMouse(void *unused) | |
124 { | |
125 SDL_Event events[10]; | |
126 int i, found; | |
127 Uint32 mask; | |
128 | |
129 /* Handle mouse events here */ | |
130 mask = (SDL_MOUSEMOTIONMASK|SDL_MOUSEBUTTONDOWNMASK|SDL_MOUSEBUTTONUPMASK); | |
131 while ( ! done ) { | |
132 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask); | |
133 for ( i=0; i<found; ++i ) { | |
134 switch(events[i].type) { | |
135 /* We want to toggle visibility on buttonpress */ | |
136 case SDL_MOUSEBUTTONDOWN: | |
137 case SDL_MOUSEBUTTONUP: | |
138 if ( events[i].button.state == SDL_PRESSED ) { | |
139 visible = !visible; | |
140 SDL_ShowCursor(visible); | |
141 } | |
142 printf("Mouse button %d has been %s\n", | |
143 events[i].button.button, | |
144 (events[i].button.state == SDL_PRESSED) ? | |
145 "pressed" : "released"); | |
146 break; | |
147 /* Show relative mouse motion */ | |
148 case SDL_MOUSEMOTION: | |
149 printf("Mouse relative motion: {%d,%d}\n", | |
150 events[i].motion.xrel, events[i].motion.yrel); | |
151 break; | |
152 } | |
153 } | |
154 /* Give up some CPU to allow events to arrive */ | |
155 SDL_Delay(20); | |
156 } | |
157 return(0); | |
158 } | |
159 | |
160 int HandleKeyboard(void *unused) | |
161 { | |
162 SDL_Event events[10]; | |
163 int i, found; | |
164 Uint32 mask; | |
165 | |
166 /* Handle mouse events here */ | |
167 mask = (SDL_KEYDOWNMASK|SDL_KEYUPMASK); | |
168 while ( ! done ) { | |
169 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask); | |
170 for ( i=0; i<found; ++i ) { | |
171 switch(events[i].type) { | |
172 /* We want to toggle visibility on buttonpress */ | |
173 case SDL_KEYDOWN: | |
174 case SDL_KEYUP: | |
562
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
175 printf("Key '%c' has been %s\n", |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
176 events[i].key.keysym.unicode, |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
177 (events[i].key.state == SDL_PRESSED) ? |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
178 "pressed" : "released"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
179 |
0 | 180 /* Allow hitting <ESC> to quit the app */ |
181 if ( events[i].key.keysym.sym == SDLK_ESCAPE ) { | |
182 done = 1; | |
183 } | |
562
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
184 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
185 /* skip events now that aren't KEYUPs... */ |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
186 if (events[i].key.state == SDL_PRESSED) |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
187 break; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
188 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
189 if ( events[i].key.keysym.sym == SDLK_f ) { |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
190 int rc = 0; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
191 printf("attempting to toggle fullscreen...\n"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
192 rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
193 printf("SDL_WM_ToggleFullScreen returned %d.\n", rc); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
194 } |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
195 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
196 if ( events[i].key.keysym.sym == SDLK_g ) { |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
197 SDL_GrabMode m; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
198 m = SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON ? |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
199 SDL_GRAB_OFF : SDL_GRAB_ON; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
200 printf("attempting to toggle input grab to %s...\n", |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
201 m == SDL_GRAB_ON ? "ON" : "OFF"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
202 SDL_WM_GrabInput(m); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
203 printf("attempt finished.\n"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
204 } |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
205 |
0 | 206 break; |
207 } | |
208 } | |
209 /* Give up some CPU to allow events to arrive */ | |
210 SDL_Delay(20); | |
211 } | |
212 return(0); | |
213 } | |
214 | |
215 int main(int argc, char *argv[]) | |
216 { | |
217 SDL_Surface *screen; | |
218 SDL_Surface *icon; | |
219 Uint8 *icon_mask; | |
220 int i, parsed; | |
221 Uint8 *buffer; | |
222 SDL_Color palette[256]; | |
223 Uint32 init_flags; | |
224 Uint8 video_bpp; | |
225 Uint32 video_flags; | |
226 SDL_Thread *mouse_thread; | |
227 SDL_Thread *keybd_thread; | |
228 | |
229 /* Set the options, based on command line arguments */ | |
230 init_flags = SDL_INIT_VIDEO; | |
231 video_bpp = 8; | |
232 video_flags = SDL_SWSURFACE; | |
233 parsed = 1; | |
234 while ( parsed ) { | |
235 /* If the threaded option is enabled, and the SDL library hasn't | |
236 been compiled with threaded events enabled, then the mouse and | |
237 keyboard won't respond. | |
238 */ | |
239 if ( (argc >= 2) && (strcmp(argv[1], "-threaded") == 0) ) { | |
240 init_flags |= SDL_INIT_EVENTTHREAD; | |
241 argc -= 1; | |
242 argv += 1; | |
243 printf("Running with threaded events\n"); | |
244 } else | |
245 if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) { | |
246 video_flags |= SDL_FULLSCREEN; | |
247 argc -= 1; | |
248 argv += 1; | |
249 } else | |
250 if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) { | |
251 video_bpp = atoi(argv[2]); | |
252 argc -= 2; | |
253 argv += 2; | |
254 } else { | |
255 parsed = 0; | |
256 } | |
257 } | |
258 | |
259 /* Initialize SDL with the requested flags */ | |
260 if ( SDL_Init(init_flags) < 0 ) { | |
261 fprintf(stderr, | |
262 "Couldn't initialize SDL: %s\n", SDL_GetError()); | |
263 exit(1); | |
264 } | |
265 atexit(SDL_Quit); | |
266 | |
267 /* Set the icon -- this must be done before the first mode set */ | |
268 icon = LoadIconSurface("icon.bmp", &icon_mask); | |
269 if ( icon != NULL ) { | |
270 SDL_WM_SetIcon(icon, icon_mask); | |
271 } | |
272 if ( icon_mask != NULL ) | |
273 free(icon_mask); | |
274 | |
275 /* Initialize the display */ | |
276 screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags); | |
277 if ( screen == NULL ) { | |
278 fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n", | |
279 video_bpp, SDL_GetError()); | |
280 exit(1); | |
281 } | |
282 printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ? | |
283 "fullscreen" : "windowed"); | |
284 | |
285 /* Enable printable characters */ | |
286 SDL_EnableUNICODE(1); | |
287 | |
288 /* Set an event filter that discards everything but QUIT */ | |
289 SDL_SetEventFilter(FilterEvents); | |
290 | |
291 /* Create the event handling threads */ | |
292 mouse_thread = SDL_CreateThread(HandleMouse, NULL); | |
293 keybd_thread = SDL_CreateThread(HandleKeyboard, NULL); | |
294 | |
295 /* Set the surface pixels and refresh! */ | |
296 for ( i=0; i<256; ++i ) { | |
297 palette[i].r = 255-i; | |
298 palette[i].g = 255-i; | |
299 palette[i].b = 255-i; | |
300 } | |
301 SDL_SetColors(screen, palette, 0, 256); | |
302 if ( SDL_LockSurface(screen) < 0 ) { | |
303 fprintf(stderr, "Couldn't lock display surface: %s\n", | |
304 SDL_GetError()); | |
305 exit(2); | |
306 } | |
307 buffer = (Uint8 *)screen->pixels; | |
308 for ( i=0; i<screen->h; ++i ) { | |
309 memset(buffer,(i*255)/screen->h, | |
310 screen->w*screen->format->BytesPerPixel); | |
311 buffer += screen->pitch; | |
312 } | |
313 SDL_UnlockSurface(screen); | |
314 SDL_UpdateRect(screen, 0, 0, 0, 0); | |
315 | |
316 /* Loop, waiting for QUIT */ | |
317 while ( ! done ) { | |
318 if ( ! (init_flags & SDL_INIT_EVENTTHREAD) ) { | |
319 SDL_PumpEvents(); /* Needed when event thread is off */ | |
320 } | |
321 if ( SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK) ) { | |
322 done = 1; | |
323 } | |
324 /* Give up some CPU so the events can accumulate */ | |
325 SDL_Delay(20); | |
326 } | |
327 SDL_WaitThread(mouse_thread, NULL); | |
328 SDL_WaitThread(keybd_thread, NULL); | |
329 return(0); | |
330 } |