fee249cb9bd5607be82ac0122b1009dbd1ad9bf0
[platform/upstream/SDL.git] / src / test / SDL_test_common.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21
22 /* Ported from original test\common.c file. */
23
24 #include "SDL_config.h"
25 #include "SDL_test.h"
26
27 #include <stdio.h>
28
29 #define VIDEO_USAGE \
30 "[--video driver] [--renderer driver] [--gldebug] [--info all|video|modes|render|event] [--log all|error|system|audio|video|render|input] [--display N] [--fullscreen | --fullscreen-desktop | --windows N] [--title title] [--icon icon.bmp] [--center | --position X,Y] [--geometry WxH] [--min-geometry WxH] [--max-geometry WxH] [--logical WxH] [--scale N] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab] [--allow-highdpi]"
31
32 #define AUDIO_USAGE \
33 "[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
34
35 SDLTest_CommonState *
36 SDLTest_CommonCreateState(char **argv, Uint32 flags)
37 {
38     SDLTest_CommonState *state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
39     if (!state) {
40         SDL_OutOfMemory();
41         return NULL;
42     }
43
44     /* Initialize some defaults */
45     state->argv = argv;
46     state->flags = flags;
47     state->window_title = argv[0];
48     state->window_flags = 0;
49     state->window_x = SDL_WINDOWPOS_UNDEFINED;
50     state->window_y = SDL_WINDOWPOS_UNDEFINED;
51     state->window_w = DEFAULT_WINDOW_WIDTH;
52     state->window_h = DEFAULT_WINDOW_HEIGHT;
53     state->num_windows = 1;
54     state->audiospec.freq = 22050;
55     state->audiospec.format = AUDIO_S16;
56     state->audiospec.channels = 2;
57     state->audiospec.samples = 2048;
58
59     /* Set some very sane GL defaults */
60     state->gl_red_size = 3;
61     state->gl_green_size = 3;
62     state->gl_blue_size = 2;
63     state->gl_alpha_size = 0;
64     state->gl_buffer_size = 0;
65     state->gl_depth_size = 16;
66     state->gl_stencil_size = 0;
67     state->gl_double_buffer = 1;
68     state->gl_accum_red_size = 0;
69     state->gl_accum_green_size = 0;
70     state->gl_accum_blue_size = 0;
71     state->gl_accum_alpha_size = 0;
72     state->gl_stereo = 0;
73     state->gl_multisamplebuffers = 0;
74     state->gl_multisamplesamples = 0;
75     state->gl_retained_backing = 1;
76     state->gl_accelerated = -1;
77     state->gl_debug = 0;
78
79     return state;
80 }
81
82 int
83 SDLTest_CommonArg(SDLTest_CommonState * state, int index)
84 {
85     char **argv = state->argv;
86
87     if (SDL_strcasecmp(argv[index], "--video") == 0) {
88         ++index;
89         if (!argv[index]) {
90             return -1;
91         }
92         state->videodriver = argv[index];
93         return 2;
94     }
95     if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
96         ++index;
97         if (!argv[index]) {
98             return -1;
99         }
100         state->renderdriver = argv[index];
101         return 2;
102     }
103     if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
104         state->gl_debug = 1;
105         return 1;
106     }
107     if (SDL_strcasecmp(argv[index], "--info") == 0) {
108         ++index;
109         if (!argv[index]) {
110             return -1;
111         }
112         if (SDL_strcasecmp(argv[index], "all") == 0) {
113             state->verbose |=
114                 (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
115                  VERBOSE_EVENT);
116             return 2;
117         }
118         if (SDL_strcasecmp(argv[index], "video") == 0) {
119             state->verbose |= VERBOSE_VIDEO;
120             return 2;
121         }
122         if (SDL_strcasecmp(argv[index], "modes") == 0) {
123             state->verbose |= VERBOSE_MODES;
124             return 2;
125         }
126         if (SDL_strcasecmp(argv[index], "render") == 0) {
127             state->verbose |= VERBOSE_RENDER;
128             return 2;
129         }
130         if (SDL_strcasecmp(argv[index], "event") == 0) {
131             state->verbose |= VERBOSE_EVENT;
132             return 2;
133         }
134         return -1;
135     }
136     if (SDL_strcasecmp(argv[index], "--log") == 0) {
137         ++index;
138         if (!argv[index]) {
139             return -1;
140         }
141         if (SDL_strcasecmp(argv[index], "all") == 0) {
142             SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
143             return 2;
144         }
145         if (SDL_strcasecmp(argv[index], "error") == 0) {
146             SDL_LogSetPriority(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_VERBOSE);
147             return 2;
148         }
149         if (SDL_strcasecmp(argv[index], "system") == 0) {
150             SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE);
151             return 2;
152         }
153         if (SDL_strcasecmp(argv[index], "audio") == 0) {
154             SDL_LogSetPriority(SDL_LOG_CATEGORY_AUDIO, SDL_LOG_PRIORITY_VERBOSE);
155             return 2;
156         }
157         if (SDL_strcasecmp(argv[index], "video") == 0) {
158             SDL_LogSetPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_VERBOSE);
159             return 2;
160         }
161         if (SDL_strcasecmp(argv[index], "render") == 0) {
162             SDL_LogSetPriority(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_VERBOSE);
163             return 2;
164         }
165         if (SDL_strcasecmp(argv[index], "input") == 0) {
166             SDL_LogSetPriority(SDL_LOG_CATEGORY_INPUT, SDL_LOG_PRIORITY_VERBOSE);
167             return 2;
168         }
169         return -1;
170     }
171     if (SDL_strcasecmp(argv[index], "--display") == 0) {
172         ++index;
173         if (!argv[index]) {
174             return -1;
175         }
176         state->display = SDL_atoi(argv[index]);
177         if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
178             state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
179             state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
180         }
181         if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
182             state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
183             state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
184         }
185         return 2;
186     }
187     if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
188         state->window_flags |= SDL_WINDOW_FULLSCREEN;
189         state->num_windows = 1;
190         return 1;
191     }
192     if (SDL_strcasecmp(argv[index], "--fullscreen-desktop") == 0) {
193         state->window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
194         state->num_windows = 1;
195         return 1;
196     }
197     if (SDL_strcasecmp(argv[index], "--allow-highdpi") == 0) {
198         state->window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
199         return 1;
200     }
201     if (SDL_strcasecmp(argv[index], "--windows") == 0) {
202         ++index;
203         if (!argv[index] || !SDL_isdigit(*argv[index])) {
204             return -1;
205         }
206         if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
207             state->num_windows = SDL_atoi(argv[index]);
208         }
209         return 2;
210     }
211     if (SDL_strcasecmp(argv[index], "--title") == 0) {
212         ++index;
213         if (!argv[index]) {
214             return -1;
215         }
216         state->window_title = argv[index];
217         return 2;
218     }
219     if (SDL_strcasecmp(argv[index], "--icon") == 0) {
220         ++index;
221         if (!argv[index]) {
222             return -1;
223         }
224         state->window_icon = argv[index];
225         return 2;
226     }
227     if (SDL_strcasecmp(argv[index], "--center") == 0) {
228         state->window_x = SDL_WINDOWPOS_CENTERED;
229         state->window_y = SDL_WINDOWPOS_CENTERED;
230         return 1;
231     }
232     if (SDL_strcasecmp(argv[index], "--position") == 0) {
233         char *x, *y;
234         ++index;
235         if (!argv[index]) {
236             return -1;
237         }
238         x = argv[index];
239         y = argv[index];
240         while (*y && *y != ',') {
241             ++y;
242         }
243         if (!*y) {
244             return -1;
245         }
246         *y++ = '\0';
247         state->window_x = SDL_atoi(x);
248         state->window_y = SDL_atoi(y);
249         return 2;
250     }
251     if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
252         char *w, *h;
253         ++index;
254         if (!argv[index]) {
255             return -1;
256         }
257         w = argv[index];
258         h = argv[index];
259         while (*h && *h != 'x') {
260             ++h;
261         }
262         if (!*h) {
263             return -1;
264         }
265         *h++ = '\0';
266         state->window_w = SDL_atoi(w);
267         state->window_h = SDL_atoi(h);
268         return 2;
269     }
270     if (SDL_strcasecmp(argv[index], "--min-geometry") == 0) {
271         char *w, *h;
272         ++index;
273         if (!argv[index]) {
274             return -1;
275         }
276         w = argv[index];
277         h = argv[index];
278         while (*h && *h != 'x') {
279             ++h;
280         }
281         if (!*h) {
282             return -1;
283         }
284         *h++ = '\0';
285         state->window_minW = SDL_atoi(w);
286         state->window_minH = SDL_atoi(h);
287         return 2;
288     }
289     if (SDL_strcasecmp(argv[index], "--max-geometry") == 0) {
290         char *w, *h;
291         ++index;
292         if (!argv[index]) {
293             return -1;
294         }
295         w = argv[index];
296         h = argv[index];
297         while (*h && *h != 'x') {
298             ++h;
299         }
300         if (!*h) {
301             return -1;
302         }
303         *h++ = '\0';
304         state->window_maxW = SDL_atoi(w);
305         state->window_maxH = SDL_atoi(h);
306         return 2;
307     }
308     if (SDL_strcasecmp(argv[index], "--logical") == 0) {
309         char *w, *h;
310         ++index;
311         if (!argv[index]) {
312             return -1;
313         }
314         w = argv[index];
315         h = argv[index];
316         while (*h && *h != 'x') {
317             ++h;
318         }
319         if (!*h) {
320             return -1;
321         }
322         *h++ = '\0';
323         state->logical_w = SDL_atoi(w);
324         state->logical_h = SDL_atoi(h);
325         return 2;
326     }
327     if (SDL_strcasecmp(argv[index], "--scale") == 0) {
328         ++index;
329         if (!argv[index]) {
330             return -1;
331         }
332         state->scale = (float)SDL_atof(argv[index]);
333         return 2;
334     }
335     if (SDL_strcasecmp(argv[index], "--depth") == 0) {
336         ++index;
337         if (!argv[index]) {
338             return -1;
339         }
340         state->depth = SDL_atoi(argv[index]);
341         return 2;
342     }
343     if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
344         ++index;
345         if (!argv[index]) {
346             return -1;
347         }
348         state->refresh_rate = SDL_atoi(argv[index]);
349         return 2;
350     }
351     if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
352         state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
353         return 1;
354     }
355     if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
356         state->window_flags |= SDL_WINDOW_BORDERLESS;
357         return 1;
358     }
359     if (SDL_strcasecmp(argv[index], "--resize") == 0) {
360         state->window_flags |= SDL_WINDOW_RESIZABLE;
361         return 1;
362     }
363     if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
364         state->window_flags |= SDL_WINDOW_MINIMIZED;
365         return 1;
366     }
367     if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
368         state->window_flags |= SDL_WINDOW_MAXIMIZED;
369         return 1;
370     }
371     if (SDL_strcasecmp(argv[index], "--grab") == 0) {
372         state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
373         return 1;
374     }
375     if (SDL_strcasecmp(argv[index], "--rate") == 0) {
376         ++index;
377         if (!argv[index]) {
378             return -1;
379         }
380         state->audiospec.freq = SDL_atoi(argv[index]);
381         return 2;
382     }
383     if (SDL_strcasecmp(argv[index], "--format") == 0) {
384         ++index;
385         if (!argv[index]) {
386             return -1;
387         }
388         if (SDL_strcasecmp(argv[index], "U8") == 0) {
389             state->audiospec.format = AUDIO_U8;
390             return 2;
391         }
392         if (SDL_strcasecmp(argv[index], "S8") == 0) {
393             state->audiospec.format = AUDIO_S8;
394             return 2;
395         }
396         if (SDL_strcasecmp(argv[index], "U16") == 0) {
397             state->audiospec.format = AUDIO_U16;
398             return 2;
399         }
400         if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
401             state->audiospec.format = AUDIO_U16LSB;
402             return 2;
403         }
404         if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
405             state->audiospec.format = AUDIO_U16MSB;
406             return 2;
407         }
408         if (SDL_strcasecmp(argv[index], "S16") == 0) {
409             state->audiospec.format = AUDIO_S16;
410             return 2;
411         }
412         if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
413             state->audiospec.format = AUDIO_S16LSB;
414             return 2;
415         }
416         if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
417             state->audiospec.format = AUDIO_S16MSB;
418             return 2;
419         }
420         return -1;
421     }
422     if (SDL_strcasecmp(argv[index], "--channels") == 0) {
423         ++index;
424         if (!argv[index]) {
425             return -1;
426         }
427         state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
428         return 2;
429     }
430     if (SDL_strcasecmp(argv[index], "--samples") == 0) {
431         ++index;
432         if (!argv[index]) {
433             return -1;
434         }
435         state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
436         return 2;
437     }
438     if ((SDL_strcasecmp(argv[index], "-h") == 0)
439         || (SDL_strcasecmp(argv[index], "--help") == 0)) {
440         /* Print the usage message */
441         return -1;
442     }
443     if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
444     /* Debug flag sent by Xcode */
445         return 2;
446     }
447     return 0;
448 }
449
450 const char *
451 SDLTest_CommonUsage(SDLTest_CommonState * state)
452 {
453     switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
454     case SDL_INIT_VIDEO:
455         return VIDEO_USAGE;
456     case SDL_INIT_AUDIO:
457         return AUDIO_USAGE;
458     case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
459         return VIDEO_USAGE " " AUDIO_USAGE;
460     default:
461         return "";
462     }
463 }
464
465 static void
466 SDLTest_PrintRendererFlag(Uint32 flag)
467 {
468     switch (flag) {
469     case SDL_RENDERER_PRESENTVSYNC:
470         fprintf(stderr, "PresentVSync");
471         break;
472     case SDL_RENDERER_ACCELERATED:
473         fprintf(stderr, "Accelerated");
474         break;
475     default:
476         fprintf(stderr, "0x%8.8x", flag);
477         break;
478     }
479 }
480
481 static void
482 SDLTest_PrintPixelFormat(Uint32 format)
483 {
484     switch (format) {
485     case SDL_PIXELFORMAT_UNKNOWN:
486         fprintf(stderr, "Unknwon");
487         break;
488     case SDL_PIXELFORMAT_INDEX1LSB:
489         fprintf(stderr, "Index1LSB");
490         break;
491     case SDL_PIXELFORMAT_INDEX1MSB:
492         fprintf(stderr, "Index1MSB");
493         break;
494     case SDL_PIXELFORMAT_INDEX4LSB:
495         fprintf(stderr, "Index4LSB");
496         break;
497     case SDL_PIXELFORMAT_INDEX4MSB:
498         fprintf(stderr, "Index4MSB");
499         break;
500     case SDL_PIXELFORMAT_INDEX8:
501         fprintf(stderr, "Index8");
502         break;
503     case SDL_PIXELFORMAT_RGB332:
504         fprintf(stderr, "RGB332");
505         break;
506     case SDL_PIXELFORMAT_RGB444:
507         fprintf(stderr, "RGB444");
508         break;
509     case SDL_PIXELFORMAT_RGB555:
510         fprintf(stderr, "RGB555");
511         break;
512     case SDL_PIXELFORMAT_BGR555:
513         fprintf(stderr, "BGR555");
514         break;
515     case SDL_PIXELFORMAT_ARGB4444:
516         fprintf(stderr, "ARGB4444");
517         break;
518     case SDL_PIXELFORMAT_ABGR4444:
519         fprintf(stderr, "ABGR4444");
520         break;
521     case SDL_PIXELFORMAT_ARGB1555:
522         fprintf(stderr, "ARGB1555");
523         break;
524     case SDL_PIXELFORMAT_ABGR1555:
525         fprintf(stderr, "ABGR1555");
526         break;
527     case SDL_PIXELFORMAT_RGB565:
528         fprintf(stderr, "RGB565");
529         break;
530     case SDL_PIXELFORMAT_BGR565:
531         fprintf(stderr, "BGR565");
532         break;
533     case SDL_PIXELFORMAT_RGB24:
534         fprintf(stderr, "RGB24");
535         break;
536     case SDL_PIXELFORMAT_BGR24:
537         fprintf(stderr, "BGR24");
538         break;
539     case SDL_PIXELFORMAT_RGB888:
540         fprintf(stderr, "RGB888");
541         break;
542     case SDL_PIXELFORMAT_BGR888:
543         fprintf(stderr, "BGR888");
544         break;
545     case SDL_PIXELFORMAT_ARGB8888:
546         fprintf(stderr, "ARGB8888");
547         break;
548     case SDL_PIXELFORMAT_RGBA8888:
549         fprintf(stderr, "RGBA8888");
550         break;
551     case SDL_PIXELFORMAT_ABGR8888:
552         fprintf(stderr, "ABGR8888");
553         break;
554     case SDL_PIXELFORMAT_BGRA8888:
555         fprintf(stderr, "BGRA8888");
556         break;
557     case SDL_PIXELFORMAT_ARGB2101010:
558         fprintf(stderr, "ARGB2101010");
559         break;
560     case SDL_PIXELFORMAT_YV12:
561         fprintf(stderr, "YV12");
562         break;
563     case SDL_PIXELFORMAT_IYUV:
564         fprintf(stderr, "IYUV");
565         break;
566     case SDL_PIXELFORMAT_YUY2:
567         fprintf(stderr, "YUY2");
568         break;
569     case SDL_PIXELFORMAT_UYVY:
570         fprintf(stderr, "UYVY");
571         break;
572     case SDL_PIXELFORMAT_YVYU:
573         fprintf(stderr, "YVYU");
574         break;
575     case SDL_PIXELFORMAT_NV12:
576         fprintf(stderr, "NV12");
577         break;
578     case SDL_PIXELFORMAT_NV21:
579         fprintf(stderr, "NV21");
580         break;
581     default:
582         fprintf(stderr, "0x%8.8x", format);
583         break;
584     }
585 }
586
587 static void
588 SDLTest_PrintRenderer(SDL_RendererInfo * info)
589 {
590     int i, count;
591
592     fprintf(stderr, "  Renderer %s:\n", info->name);
593
594     fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
595     fprintf(stderr, " (");
596     count = 0;
597     for (i = 0; i < sizeof(info->flags) * 8; ++i) {
598         Uint32 flag = (1 << i);
599         if (info->flags & flag) {
600             if (count > 0) {
601                 fprintf(stderr, " | ");
602             }
603             SDLTest_PrintRendererFlag(flag);
604             ++count;
605         }
606     }
607     fprintf(stderr, ")\n");
608
609     fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
610     for (i = 0; i < (int) info->num_texture_formats; ++i) {
611         if (i > 0) {
612             fprintf(stderr, ", ");
613         }
614         SDLTest_PrintPixelFormat(info->texture_formats[i]);
615     }
616     fprintf(stderr, "\n");
617
618     if (info->max_texture_width || info->max_texture_height) {
619         fprintf(stderr, "    Max Texture Size: %dx%d\n",
620                 info->max_texture_width, info->max_texture_height);
621     }
622 }
623
624 static SDL_Surface *
625 SDLTest_LoadIcon(const char *file)
626 {
627     SDL_Surface *icon;
628
629     /* Load the icon surface */
630     icon = SDL_LoadBMP(file);
631     if (icon == NULL) {
632         fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
633         return (NULL);
634     }
635
636     if (icon->format->palette) {
637         /* Set the colorkey */
638         SDL_SetColorKey(icon, 1, *((Uint8 *) icon->pixels));
639     }
640
641     return (icon);
642 }
643
644 SDL_bool
645 SDLTest_CommonInit(SDLTest_CommonState * state)
646 {
647     int i, j, m, n, w, h;
648     SDL_DisplayMode fullscreen_mode;
649
650     if (state->flags & SDL_INIT_VIDEO) {
651         if (state->verbose & VERBOSE_VIDEO) {
652             n = SDL_GetNumVideoDrivers();
653             if (n == 0) {
654                 fprintf(stderr, "No built-in video drivers\n");
655             } else {
656                 fprintf(stderr, "Built-in video drivers:");
657                 for (i = 0; i < n; ++i) {
658                     if (i > 0) {
659                         fprintf(stderr, ",");
660                     }
661                     fprintf(stderr, " %s", SDL_GetVideoDriver(i));
662                 }
663                 fprintf(stderr, "\n");
664             }
665         }
666         if (SDL_VideoInit(state->videodriver) < 0) {
667             fprintf(stderr, "Couldn't initialize video driver: %s\n",
668                     SDL_GetError());
669             return SDL_FALSE;
670         }
671         if (state->verbose & VERBOSE_VIDEO) {
672             fprintf(stderr, "Video driver: %s\n",
673                     SDL_GetCurrentVideoDriver());
674         }
675
676         /* Upload GL settings */
677         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, state->gl_red_size);
678         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, state->gl_green_size);
679         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, state->gl_blue_size);
680         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, state->gl_alpha_size);
681         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, state->gl_double_buffer);
682         SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, state->gl_buffer_size);
683         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, state->gl_depth_size);
684         SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, state->gl_stencil_size);
685         SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, state->gl_accum_red_size);
686         SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, state->gl_accum_green_size);
687         SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, state->gl_accum_blue_size);
688         SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, state->gl_accum_alpha_size);
689         SDL_GL_SetAttribute(SDL_GL_STEREO, state->gl_stereo);
690         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, state->gl_multisamplebuffers);
691         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, state->gl_multisamplesamples);
692         if (state->gl_accelerated >= 0) {
693             SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
694                                 state->gl_accelerated);
695         }
696         SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, state->gl_retained_backing);
697         if (state->gl_major_version) {
698             SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
699             SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
700         }
701         if (state->gl_debug) {
702             SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
703         }
704         if (state->gl_profile_mask) {
705             SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, state->gl_profile_mask);
706         }
707
708         if (state->verbose & VERBOSE_MODES) {
709             SDL_Rect bounds;
710             SDL_DisplayMode mode;
711             int bpp;
712             Uint32 Rmask, Gmask, Bmask, Amask;
713 #if SDL_VIDEO_DRIVER_WINDOWS
714                         int adapterIndex = 0;
715                         int outputIndex = 0;
716 #endif
717             n = SDL_GetNumVideoDisplays();
718             fprintf(stderr, "Number of displays: %d\n", n);
719             for (i = 0; i < n; ++i) {
720                 fprintf(stderr, "Display %d: %s\n", i, SDL_GetDisplayName(i));
721
722                 SDL_zero(bounds);
723                 SDL_GetDisplayBounds(i, &bounds);
724                 fprintf(stderr, "Bounds: %dx%d at %d,%d\n", bounds.w, bounds.h, bounds.x, bounds.y);
725
726                 SDL_GetDesktopDisplayMode(i, &mode);
727                 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
728                                            &Bmask, &Amask);
729                 fprintf(stderr,
730                         "  Current mode: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
731                         mode.w, mode.h, mode.refresh_rate, bpp,
732                         SDL_GetPixelFormatName(mode.format));
733                 if (Rmask || Gmask || Bmask) {
734                     fprintf(stderr, "      Red Mask   = 0x%.8x\n", Rmask);
735                     fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
736                     fprintf(stderr, "      Blue Mask  = 0x%.8x\n", Bmask);
737                     if (Amask)
738                         fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
739                 }
740
741                 /* Print available fullscreen video modes */
742                 m = SDL_GetNumDisplayModes(i);
743                 if (m == 0) {
744                     fprintf(stderr, "No available fullscreen video modes\n");
745                 } else {
746                     fprintf(stderr, "  Fullscreen video modes:\n");
747                     for (j = 0; j < m; ++j) {
748                         SDL_GetDisplayMode(i, j, &mode);
749                         SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
750                                                    &Gmask, &Bmask, &Amask);
751                         fprintf(stderr,
752                                 "    Mode %d: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
753                                 j, mode.w, mode.h, mode.refresh_rate, bpp,
754                                 SDL_GetPixelFormatName(mode.format));
755                         if (Rmask || Gmask || Bmask) {
756                             fprintf(stderr, "        Red Mask   = 0x%.8x\n",
757                                     Rmask);
758                             fprintf(stderr, "        Green Mask = 0x%.8x\n",
759                                     Gmask);
760                             fprintf(stderr, "        Blue Mask  = 0x%.8x\n",
761                                     Bmask);
762                             if (Amask)
763                                 fprintf(stderr,
764                                         "        Alpha Mask = 0x%.8x\n",
765                                         Amask);
766                         }
767                     }
768                 }
769
770 #if SDL_VIDEO_DRIVER_WINDOWS
771                                 /* Print the D3D9 adapter index */
772                                 adapterIndex = SDL_Direct3D9GetAdapterIndex( i );
773                                 fprintf( stderr, "D3D9 Adapter Index: %d", adapterIndex );
774
775                                 /* Print the DXGI adapter and output indices */
776                                 SDL_DXGIGetOutputInfo(i, &adapterIndex, &outputIndex);
777                                 fprintf( stderr, "DXGI Adapter Index: %d  Output Index: %d", adapterIndex, outputIndex );
778 #endif
779             }
780         }
781
782         if (state->verbose & VERBOSE_RENDER) {
783             SDL_RendererInfo info;
784
785             n = SDL_GetNumRenderDrivers();
786             if (n == 0) {
787                 fprintf(stderr, "No built-in render drivers\n");
788             } else {
789                 fprintf(stderr, "Built-in render drivers:\n");
790                 for (i = 0; i < n; ++i) {
791                     SDL_GetRenderDriverInfo(i, &info);
792                     SDLTest_PrintRenderer(&info);
793                 }
794             }
795         }
796
797         SDL_zero(fullscreen_mode);
798         switch (state->depth) {
799         case 8:
800             fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
801             break;
802         case 15:
803             fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
804             break;
805         case 16:
806             fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
807             break;
808         case 24:
809             fullscreen_mode.format = SDL_PIXELFORMAT_RGB24;
810             break;
811         default:
812             fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
813             break;
814         }
815         fullscreen_mode.refresh_rate = state->refresh_rate;
816
817         state->windows =
818             (SDL_Window **) SDL_malloc(state->num_windows *
819                                         sizeof(*state->windows));
820         state->renderers =
821             (SDL_Renderer **) SDL_malloc(state->num_windows *
822                                         sizeof(*state->renderers));
823         state->targets =
824             (SDL_Texture **) SDL_malloc(state->num_windows *
825                                         sizeof(*state->targets));
826         if (!state->windows || !state->renderers) {
827             fprintf(stderr, "Out of memory!\n");
828             return SDL_FALSE;
829         }
830         for (i = 0; i < state->num_windows; ++i) {
831             char title[1024];
832
833             if (state->num_windows > 1) {
834                 SDL_snprintf(title, SDL_arraysize(title), "%s %d",
835                              state->window_title, i + 1);
836             } else {
837                 SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
838             }
839             state->windows[i] =
840                 SDL_CreateWindow(title, state->window_x, state->window_y,
841                                  state->window_w, state->window_h,
842                                  state->window_flags);
843             if (!state->windows[i]) {
844                 fprintf(stderr, "Couldn't create window: %s\n",
845                         SDL_GetError());
846                 return SDL_FALSE;
847             }
848             if (state->window_minW || state->window_minH) {
849                 SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
850             }
851             if (state->window_maxW || state->window_maxH) {
852                 SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
853             }
854             SDL_GetWindowSize(state->windows[i], &w, &h);
855             if (!(state->window_flags & SDL_WINDOW_RESIZABLE) &&
856                 (w != state->window_w || h != state->window_h)) {
857                 printf("Window requested size %dx%d, got %dx%d\n", state->window_w, state->window_h, w, h);
858                 state->window_w = w;
859                 state->window_h = h;
860             }
861             if (SDL_SetWindowDisplayMode(state->windows[i], &fullscreen_mode) < 0) {
862                 fprintf(stderr, "Can't set up fullscreen display mode: %s\n",
863                         SDL_GetError());
864                 return SDL_FALSE;
865             }
866
867             if (state->window_icon) {
868                 SDL_Surface *icon = SDLTest_LoadIcon(state->window_icon);
869                 if (icon) {
870                     SDL_SetWindowIcon(state->windows[i], icon);
871                     SDL_FreeSurface(icon);
872                 }
873             }
874
875             SDL_ShowWindow(state->windows[i]);
876
877             state->renderers[i] = NULL;
878             state->targets[i] = NULL;
879
880             if (!state->skip_renderer
881                 && (state->renderdriver
882                     || !(state->window_flags & SDL_WINDOW_OPENGL))) {
883                 m = -1;
884                 if (state->renderdriver) {
885                     SDL_RendererInfo info;
886                     n = SDL_GetNumRenderDrivers();
887                     for (j = 0; j < n; ++j) {
888                         SDL_GetRenderDriverInfo(j, &info);
889                         if (SDL_strcasecmp(info.name, state->renderdriver) ==
890                             0) {
891                             m = j;
892                             break;
893                         }
894                     }
895                     if (m == -1) {
896                         fprintf(stderr,
897                                 "Couldn't find render driver named %s",
898                                 state->renderdriver);
899                         return SDL_FALSE;
900                     }
901                 }
902                 state->renderers[i] = SDL_CreateRenderer(state->windows[i],
903                                             m, state->render_flags);
904                 if (!state->renderers[i]) {
905                     fprintf(stderr, "Couldn't create renderer: %s\n",
906                             SDL_GetError());
907                     return SDL_FALSE;
908                 }
909                 if (state->logical_w && state->logical_h) {
910                     SDL_RenderSetLogicalSize(state->renderers[i], state->logical_w, state->logical_h);
911                 } else if (state->scale) {
912                     SDL_RenderSetScale(state->renderers[i], state->scale, state->scale);
913                 }
914                 if (state->verbose & VERBOSE_RENDER) {
915                     SDL_RendererInfo info;
916
917                     fprintf(stderr, "Current renderer:\n");
918                     SDL_GetRendererInfo(state->renderers[i], &info);
919                     SDLTest_PrintRenderer(&info);
920                 }
921             }
922         }
923     }
924
925     if (state->flags & SDL_INIT_AUDIO) {
926         if (state->verbose & VERBOSE_AUDIO) {
927             n = SDL_GetNumAudioDrivers();
928             if (n == 0) {
929                 fprintf(stderr, "No built-in audio drivers\n");
930             } else {
931                 fprintf(stderr, "Built-in audio drivers:");
932                 for (i = 0; i < n; ++i) {
933                     if (i > 0) {
934                         fprintf(stderr, ",");
935                     }
936                     fprintf(stderr, " %s", SDL_GetAudioDriver(i));
937                 }
938                 fprintf(stderr, "\n");
939             }
940         }
941         if (SDL_AudioInit(state->audiodriver) < 0) {
942             fprintf(stderr, "Couldn't initialize audio driver: %s\n",
943                     SDL_GetError());
944             return SDL_FALSE;
945         }
946         if (state->verbose & VERBOSE_VIDEO) {
947             fprintf(stderr, "Audio driver: %s\n",
948                     SDL_GetCurrentAudioDriver());
949         }
950
951         if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
952             fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
953             return SDL_FALSE;
954         }
955     }
956
957     return SDL_TRUE;
958 }
959
960 static const char *
961 ControllerAxisName(const SDL_GameControllerAxis axis)
962 {
963     switch (axis)
964     {
965 #define AXIS_CASE(ax) case SDL_CONTROLLER_AXIS_##ax: return #ax
966         AXIS_CASE(INVALID);
967         AXIS_CASE(LEFTX);
968         AXIS_CASE(LEFTY);
969         AXIS_CASE(RIGHTX);
970         AXIS_CASE(RIGHTY);
971         AXIS_CASE(TRIGGERLEFT);
972         AXIS_CASE(TRIGGERRIGHT);
973 #undef AXIS_CASE
974 default: return "???";
975     }
976 }
977
978 static const char *
979 ControllerButtonName(const SDL_GameControllerButton button)
980 {
981     switch (button)
982     {
983 #define BUTTON_CASE(btn) case SDL_CONTROLLER_BUTTON_##btn: return #btn
984         BUTTON_CASE(INVALID);
985         BUTTON_CASE(A);
986         BUTTON_CASE(B);
987         BUTTON_CASE(X);
988         BUTTON_CASE(Y);
989         BUTTON_CASE(BACK);
990         BUTTON_CASE(GUIDE);
991         BUTTON_CASE(START);
992         BUTTON_CASE(LEFTSTICK);
993         BUTTON_CASE(RIGHTSTICK);
994         BUTTON_CASE(LEFTSHOULDER);
995         BUTTON_CASE(RIGHTSHOULDER);
996         BUTTON_CASE(DPAD_UP);
997         BUTTON_CASE(DPAD_DOWN);
998         BUTTON_CASE(DPAD_LEFT);
999         BUTTON_CASE(DPAD_RIGHT);
1000 #undef BUTTON_CASE
1001 default: return "???";
1002     }
1003 }
1004
1005 static void
1006 SDLTest_PrintEvent(SDL_Event * event)
1007 {
1008     if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
1009         /* Mouse and finger motion are really spammy */
1010         return;
1011     }
1012
1013     switch (event->type) {
1014     case SDL_WINDOWEVENT:
1015         switch (event->window.event) {
1016         case SDL_WINDOWEVENT_SHOWN:
1017             SDL_Log("SDL EVENT: Window %d shown", event->window.windowID);
1018             break;
1019         case SDL_WINDOWEVENT_HIDDEN:
1020             SDL_Log("SDL EVENT: Window %d hidden", event->window.windowID);
1021             break;
1022         case SDL_WINDOWEVENT_EXPOSED:
1023             SDL_Log("SDL EVENT: Window %d exposed", event->window.windowID);
1024             break;
1025         case SDL_WINDOWEVENT_MOVED:
1026             SDL_Log("SDL EVENT: Window %d moved to %d,%d",
1027                     event->window.windowID, event->window.data1,
1028                     event->window.data2);
1029             break;
1030         case SDL_WINDOWEVENT_RESIZED:
1031             SDL_Log("SDL EVENT: Window %d resized to %dx%d",
1032                     event->window.windowID, event->window.data1,
1033                     event->window.data2);
1034             break;
1035         case SDL_WINDOWEVENT_SIZE_CHANGED:
1036             SDL_Log("SDL EVENT: Window %d changed size to %dx%d",
1037                     event->window.windowID, event->window.data1,
1038                     event->window.data2);
1039             break;
1040         case SDL_WINDOWEVENT_MINIMIZED:
1041             SDL_Log("SDL EVENT: Window %d minimized", event->window.windowID);
1042             break;
1043         case SDL_WINDOWEVENT_MAXIMIZED:
1044             SDL_Log("SDL EVENT: Window %d maximized", event->window.windowID);
1045             break;
1046         case SDL_WINDOWEVENT_RESTORED:
1047             SDL_Log("SDL EVENT: Window %d restored", event->window.windowID);
1048             break;
1049         case SDL_WINDOWEVENT_ENTER:
1050             SDL_Log("SDL EVENT: Mouse entered window %d",
1051                     event->window.windowID);
1052             break;
1053         case SDL_WINDOWEVENT_LEAVE:
1054             SDL_Log("SDL EVENT: Mouse left window %d", event->window.windowID);
1055             break;
1056         case SDL_WINDOWEVENT_FOCUS_GAINED:
1057             SDL_Log("SDL EVENT: Window %d gained keyboard focus",
1058                     event->window.windowID);
1059             break;
1060         case SDL_WINDOWEVENT_FOCUS_LOST:
1061             SDL_Log("SDL EVENT: Window %d lost keyboard focus",
1062                     event->window.windowID);
1063             break;
1064         case SDL_WINDOWEVENT_CLOSE:
1065             SDL_Log("SDL EVENT: Window %d closed", event->window.windowID);
1066             break;
1067         default:
1068             SDL_Log("SDL EVENT: Window %d got unknown event %d",
1069                     event->window.windowID, event->window.event);
1070             break;
1071         }
1072         break;
1073     case SDL_KEYDOWN:
1074         SDL_Log("SDL EVENT: Keyboard: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
1075                 event->key.windowID,
1076                 event->key.keysym.scancode,
1077                 SDL_GetScancodeName(event->key.keysym.scancode),
1078                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
1079         break;
1080     case SDL_KEYUP:
1081         SDL_Log("SDL EVENT: Keyboard: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
1082                 event->key.windowID,
1083                 event->key.keysym.scancode,
1084                 SDL_GetScancodeName(event->key.keysym.scancode),
1085                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
1086         break;
1087     case SDL_TEXTINPUT:
1088         SDL_Log("SDL EVENT: Keyboard: text input \"%s\" in window %d",
1089                 event->text.text, event->text.windowID);
1090         break;
1091     case SDL_MOUSEMOTION:
1092         SDL_Log("SDL EVENT: Mouse: moved to %d,%d (%d,%d) in window %d",
1093                 event->motion.x, event->motion.y,
1094                 event->motion.xrel, event->motion.yrel,
1095                 event->motion.windowID);
1096         break;
1097     case SDL_MOUSEBUTTONDOWN:
1098         SDL_Log("SDL EVENT: Mouse: button %d pressed at %d,%d with click count %d in window %d",
1099                 event->button.button, event->button.x, event->button.y, event->button.clicks,
1100                 event->button.windowID);
1101         break;
1102     case SDL_MOUSEBUTTONUP:
1103         SDL_Log("SDL EVENT: Mouse: button %d released at %d,%d with click count %d in window %d",
1104                 event->button.button, event->button.x, event->button.y, event->button.clicks,
1105                 event->button.windowID);
1106         break;
1107     case SDL_MOUSEWHEEL:
1108         SDL_Log("SDL EVENT: Mouse: wheel scrolled %d in x and %d in y (reversed: %d) in window %d",
1109                 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID);
1110         break;
1111     case SDL_JOYDEVICEADDED:
1112         SDL_Log("SDL EVENT: Joystick index %d attached",
1113             event->jdevice.which);
1114         break;
1115     case SDL_JOYDEVICEREMOVED:
1116         SDL_Log("SDL EVENT: Joystick %d removed",
1117             event->jdevice.which);
1118         break;
1119     case SDL_JOYBALLMOTION:
1120         SDL_Log("SDL EVENT: Joystick %d: ball %d moved by %d,%d",
1121                 event->jball.which, event->jball.ball, event->jball.xrel,
1122                 event->jball.yrel);
1123         break;
1124     case SDL_JOYHATMOTION:
1125         {
1126             const char *position = "UNKNOWN";
1127             switch (event->jhat.value) {
1128             case SDL_HAT_CENTERED:
1129                 position = "CENTER";
1130                 break;
1131             case SDL_HAT_UP:
1132                 position = "UP";
1133                 break;
1134             case SDL_HAT_RIGHTUP:
1135                 position = "RIGHTUP";
1136                 break;
1137             case SDL_HAT_RIGHT:
1138                 position = "RIGHT";
1139                 break;
1140             case SDL_HAT_RIGHTDOWN:
1141                 position = "RIGHTDOWN";
1142                 break;
1143             case SDL_HAT_DOWN:
1144                 position = "DOWN";
1145                 break;
1146             case SDL_HAT_LEFTDOWN:
1147                 position = "LEFTDOWN";
1148                 break;
1149             case SDL_HAT_LEFT:
1150                 position = "LEFT";
1151                 break;
1152             case SDL_HAT_LEFTUP:
1153                 position = "LEFTUP";
1154                 break;
1155             }
1156             SDL_Log("SDL EVENT: Joystick %d: hat %d moved to %s", event->jhat.which,
1157                 event->jhat.hat, position);
1158         }
1159         break;
1160     case SDL_JOYBUTTONDOWN:
1161         SDL_Log("SDL EVENT: Joystick %d: button %d pressed",
1162                 event->jbutton.which, event->jbutton.button);
1163         break;
1164     case SDL_JOYBUTTONUP:
1165         SDL_Log("SDL EVENT: Joystick %d: button %d released",
1166                 event->jbutton.which, event->jbutton.button);
1167         break;
1168     case SDL_CONTROLLERDEVICEADDED:
1169         SDL_Log("SDL EVENT: Controller index %d attached",
1170             event->cdevice.which);
1171         break;
1172     case SDL_CONTROLLERDEVICEREMOVED:
1173         SDL_Log("SDL EVENT: Controller %d removed",
1174             event->cdevice.which);
1175         break;
1176     case SDL_CONTROLLERAXISMOTION:
1177         SDL_Log("SDL EVENT: Controller %d axis %d ('%s') value: %d",
1178             event->caxis.which,
1179             event->caxis.axis,
1180             ControllerAxisName((SDL_GameControllerAxis)event->caxis.axis),
1181             event->caxis.value);
1182         break;
1183     case SDL_CONTROLLERBUTTONDOWN:
1184         SDL_Log("SDL EVENT: Controller %d button %d ('%s') down",
1185             event->cbutton.which, event->cbutton.button,
1186             ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
1187         break;
1188     case SDL_CONTROLLERBUTTONUP:
1189         SDL_Log("SDL EVENT: Controller %d button %d ('%s') up",
1190             event->cbutton.which, event->cbutton.button,
1191             ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
1192         break;
1193     case SDL_CLIPBOARDUPDATE:
1194         SDL_Log("SDL EVENT: Clipboard updated");
1195         break;
1196
1197     case SDL_FINGERDOWN:
1198     case SDL_FINGERUP:
1199         SDL_Log("SDL EVENT: Finger: %s touch=%ld, finger=%ld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
1200                 (event->type == SDL_FINGERDOWN) ? "down" : "up",
1201                 (long) event->tfinger.touchId,
1202                 (long) event->tfinger.fingerId,
1203                 event->tfinger.x, event->tfinger.y,
1204                 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
1205         break;
1206     case SDL_DOLLARGESTURE:
1207         SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
1208         break;
1209     case SDL_DOLLARRECORD:
1210         SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
1211         break;
1212     case SDL_MULTIGESTURE:
1213         SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers);
1214         break;
1215
1216     case SDL_RENDER_DEVICE_RESET:
1217         SDL_Log("SDL EVENT: render device reset");
1218         break;
1219     case SDL_RENDER_TARGETS_RESET:
1220         SDL_Log("SDL EVENT: render targets reset");
1221         break;
1222
1223     case SDL_QUIT:
1224         SDL_Log("SDL EVENT: Quit requested");
1225         break;
1226     case SDL_USEREVENT:
1227         SDL_Log("SDL EVENT: User event %d", event->user.code);
1228         break;
1229     default:
1230         SDL_Log("Unknown event %04x", event->type);
1231         break;
1232     }
1233 }
1234
1235 static void
1236 SDLTest_ScreenShot(SDL_Renderer *renderer)
1237 {
1238     SDL_Rect viewport;
1239     SDL_Surface *surface;
1240
1241     if (!renderer) {
1242         return;
1243     }
1244
1245     SDL_RenderGetViewport(renderer, &viewport);
1246     surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24,
1247 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1248                     0x00FF0000, 0x0000FF00, 0x000000FF,
1249 #else
1250                     0x000000FF, 0x0000FF00, 0x00FF0000,
1251 #endif
1252                     0x00000000);
1253     if (!surface) {
1254         fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
1255         return;
1256     }
1257
1258     if (SDL_RenderReadPixels(renderer, NULL, surface->format->format,
1259                              surface->pixels, surface->pitch) < 0) {
1260         fprintf(stderr, "Couldn't read screen: %s\n", SDL_GetError());
1261         SDL_free(surface);
1262         return;
1263     }
1264
1265     if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
1266         fprintf(stderr, "Couldn't save screenshot.bmp: %s\n", SDL_GetError());
1267         SDL_free(surface);
1268         return;
1269     }
1270 }
1271
1272 static void
1273 FullscreenTo(int index, int windowId)
1274 {
1275     Uint32 flags;
1276     struct SDL_Rect rect = { 0, 0, 0, 0 };
1277     SDL_Window *window = SDL_GetWindowFromID(windowId);
1278     if (!window) {
1279         return;
1280     }
1281
1282     SDL_GetDisplayBounds( index, &rect );
1283
1284     flags = SDL_GetWindowFlags(window);
1285     if (flags & SDL_WINDOW_FULLSCREEN) {
1286         SDL_SetWindowFullscreen( window, SDL_FALSE );
1287         SDL_Delay( 15 );
1288     }
1289
1290     SDL_SetWindowPosition( window, rect.x, rect.y );
1291     SDL_SetWindowFullscreen( window, SDL_TRUE );
1292 }
1293
1294 void
1295 SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
1296 {
1297     int i;
1298     static SDL_MouseMotionEvent lastEvent;
1299
1300     if (state->verbose & VERBOSE_EVENT) {
1301         SDLTest_PrintEvent(event);
1302     }
1303
1304     switch (event->type) {
1305     case SDL_WINDOWEVENT:
1306         switch (event->window.event) {
1307         case SDL_WINDOWEVENT_CLOSE:
1308             {
1309                 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
1310                 if (window) {
1311                     for (i = 0; i < state->num_windows; ++i) {
1312                         if (window == state->windows[i]) {
1313                             if (state->targets[i]) {
1314                                 SDL_DestroyTexture(state->targets[i]);
1315                                 state->targets[i] = NULL;
1316                             }
1317                             if (state->renderers[i]) {
1318                                 SDL_DestroyRenderer(state->renderers[i]);
1319                                 state->renderers[i] = NULL;
1320                             }
1321                             SDL_DestroyWindow(state->windows[i]);
1322                             state->windows[i] = NULL;
1323                             break;
1324                         }
1325                     }
1326                 }
1327             }
1328             break;
1329         }
1330         break;
1331     case SDL_KEYDOWN: {
1332         SDL_bool withControl = !!(event->key.keysym.mod & KMOD_CTRL);
1333         SDL_bool withShift = !!(event->key.keysym.mod & KMOD_SHIFT);
1334         SDL_bool withAlt = !!(event->key.keysym.mod & KMOD_ALT);
1335
1336         switch (event->key.keysym.sym) {
1337             /* Add hotkeys here */
1338         case SDLK_PRINTSCREEN: {
1339                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1340                 if (window) {
1341                     for (i = 0; i < state->num_windows; ++i) {
1342                         if (window == state->windows[i]) {
1343                             SDLTest_ScreenShot(state->renderers[i]);
1344                         }
1345                     }
1346                 }
1347             }
1348             break;
1349         case SDLK_EQUALS:
1350             if (withControl) {
1351                 /* Ctrl-+ double the size of the window */
1352                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1353                 if (window) {
1354                     int w, h;
1355                     SDL_GetWindowSize(window, &w, &h);
1356                     SDL_SetWindowSize(window, w*2, h*2);
1357                 }
1358             }
1359             break;
1360         case SDLK_MINUS:
1361             if (withControl) {
1362                 /* Ctrl-- half the size of the window */
1363                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1364                 if (window) {
1365                     int w, h;
1366                     SDL_GetWindowSize(window, &w, &h);
1367                     SDL_SetWindowSize(window, w/2, h/2);
1368                 }
1369             }
1370             break;
1371         case SDLK_c:
1372             if (withControl) {
1373                 /* Ctrl-C copy awesome text! */
1374                 SDL_SetClipboardText("SDL rocks!\nYou know it!");
1375                 printf("Copied text to clipboard\n");
1376             }
1377             if (withAlt) {
1378                 /* Alt-C toggle a render clip rectangle */
1379                 for (i = 0; i < state->num_windows; ++i) {
1380                     int w, h;
1381                     if (state->renderers[i]) {
1382                         SDL_Rect clip;
1383                         SDL_GetWindowSize(state->windows[i], &w, &h);
1384                         SDL_RenderGetClipRect(state->renderers[i], &clip);
1385                         if (SDL_RectEmpty(&clip)) {
1386                             clip.x = w/4;
1387                             clip.y = h/4;
1388                             clip.w = w/2;
1389                             clip.h = h/2;
1390                             SDL_RenderSetClipRect(state->renderers[i], &clip);
1391                         } else {
1392                             SDL_RenderSetClipRect(state->renderers[i], NULL);
1393                         }
1394                     }
1395                 }
1396             }
1397             if (withShift) {
1398                 SDL_Window *current_win = SDL_GetKeyboardFocus();
1399                 if (current_win) {
1400                     const SDL_bool shouldCapture = (SDL_GetWindowFlags(current_win) & SDL_WINDOW_MOUSE_CAPTURE) == 0;
1401                     const int rc = SDL_CaptureMouse(shouldCapture);
1402                     SDL_Log("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", (rc == 0) ? "succeeded" : "failed");
1403                 }
1404             }
1405             break;
1406         case SDLK_v:
1407             if (withControl) {
1408                 /* Ctrl-V paste awesome text! */
1409                 char *text = SDL_GetClipboardText();
1410                 if (*text) {
1411                     printf("Clipboard: %s\n", text);
1412                 } else {
1413                     printf("Clipboard is empty\n");
1414                 }
1415                 SDL_free(text);
1416             }
1417             break;
1418         case SDLK_g:
1419             if (withControl) {
1420                 /* Ctrl-G toggle grab */
1421                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1422                 if (window) {
1423                     SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
1424                 }
1425             }
1426             break;
1427         case SDLK_m:
1428             if (withControl) {
1429                 /* Ctrl-M maximize */
1430                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1431                 if (window) {
1432                     Uint32 flags = SDL_GetWindowFlags(window);
1433                     if (flags & SDL_WINDOW_MAXIMIZED) {
1434                         SDL_RestoreWindow(window);
1435                     } else {
1436                         SDL_MaximizeWindow(window);
1437                     }
1438                 }
1439             }
1440             break;
1441         case SDLK_r:
1442             if (withControl) {
1443                 /* Ctrl-R toggle mouse relative mode */
1444                 SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE);
1445             }
1446             break;
1447         case SDLK_z:
1448             if (withControl) {
1449                 /* Ctrl-Z minimize */
1450                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1451                 if (window) {
1452                     SDL_MinimizeWindow(window);
1453                 }
1454             }
1455             break;
1456         case SDLK_RETURN:
1457             if (withControl) {
1458                 /* Ctrl-Enter toggle fullscreen */
1459                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1460                 if (window) {
1461                     Uint32 flags = SDL_GetWindowFlags(window);
1462                     if (flags & SDL_WINDOW_FULLSCREEN) {
1463                         SDL_SetWindowFullscreen(window, SDL_FALSE);
1464                     } else {
1465                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
1466                     }
1467                 }
1468             } else if (withAlt) {
1469                 /* Alt-Enter toggle fullscreen desktop */
1470                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1471                 if (window) {
1472                     Uint32 flags = SDL_GetWindowFlags(window);
1473                     if (flags & SDL_WINDOW_FULLSCREEN) {
1474                         SDL_SetWindowFullscreen(window, SDL_FALSE);
1475                     } else {
1476                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1477                     }
1478                 }
1479             } else if (withShift) {
1480                 /* Shift-Enter toggle fullscreen desktop / fullscreen */
1481                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1482                 if (window) {
1483                     Uint32 flags = SDL_GetWindowFlags(window);
1484                     if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
1485                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
1486                     } else {
1487                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
1488                     }
1489                 }
1490             }
1491
1492             break;
1493         case SDLK_b:
1494             if (withControl) {
1495                 /* Ctrl-B toggle window border */
1496                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1497                 if (window) {
1498                     const Uint32 flags = SDL_GetWindowFlags(window);
1499                     const SDL_bool b = ((flags & SDL_WINDOW_BORDERLESS) != 0) ? SDL_TRUE : SDL_FALSE;
1500                     SDL_SetWindowBordered(window, b);
1501                 }
1502             }
1503             break;
1504         case SDLK_a:
1505             if (withControl) {
1506                 /* Ctrl-A reports absolute mouse position. */
1507                 int x, y;
1508                 const Uint32 mask = SDL_GetGlobalMouseState(&x, &y);
1509                 SDL_Log("ABSOLUTE MOUSE: (%d, %d)%s%s%s%s%s\n", x, y,
1510                         (mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
1511                         (mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
1512                         (mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
1513                         (mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
1514                         (mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
1515             }
1516             break;
1517         case SDLK_0:
1518             if (withControl) {
1519                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1520                 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
1521             }
1522             break;
1523         case SDLK_1:
1524             if (withControl) {
1525                 FullscreenTo(0, event->key.windowID);
1526             }
1527             break;
1528         case SDLK_2:
1529             if (withControl) {
1530                 FullscreenTo(1, event->key.windowID);
1531             }
1532             break;
1533         case SDLK_ESCAPE:
1534             *done = 1;
1535             break;
1536         case SDLK_SPACE:
1537         {
1538             char message[256];
1539             SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
1540
1541             SDL_snprintf(message, sizeof(message), "(%i, %i), rel (%i, %i)\n", lastEvent.x, lastEvent.y, lastEvent.xrel, lastEvent.yrel);
1542             SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Last mouse position", message, window);
1543             break;
1544         }
1545         default:
1546             break;
1547         }
1548         break;
1549     }
1550     case SDL_QUIT:
1551         *done = 1;
1552         break;
1553     case SDL_MOUSEMOTION:
1554         lastEvent = event->motion;
1555         break;
1556     }
1557 }
1558
1559 void
1560 SDLTest_CommonQuit(SDLTest_CommonState * state)
1561 {
1562     int i;
1563
1564     SDL_free(state->windows);
1565     if (state->targets) {
1566         for (i = 0; i < state->num_windows; ++i) {
1567             if (state->targets[i]) {
1568                 SDL_DestroyTexture(state->targets[i]);
1569             }
1570         }
1571         SDL_free(state->targets);
1572     }
1573     if (state->renderers) {
1574         for (i = 0; i < state->num_windows; ++i) {
1575             if (state->renderers[i]) {
1576                 SDL_DestroyRenderer(state->renderers[i]);
1577             }
1578         }
1579         SDL_free(state->renderers);
1580     }
1581     if (state->flags & SDL_INIT_VIDEO) {
1582         SDL_VideoQuit();
1583     }
1584     if (state->flags & SDL_INIT_AUDIO) {
1585         SDL_AudioQuit();
1586     }
1587     SDL_free(state);
1588     SDL_Quit();
1589 }
1590
1591 /* vi: set ts=4 sw=4 expandtab: */