src/test/SDL_test_common.c
author Ryan C. Gordon
Thu, 23 Feb 2017 22:38:04 -0500
changeset 10907 e64cf9261cc7
parent 10874 694f263fed30
child 11012 c2f18f1f7e97
permissions -rw-r--r--
cmake: add WASAPI audio target to the build (thanks, Martin!).

Fixes Bugzilla #3588.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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         SDL_Log("PresentVSync");
   471         break;
   472     case SDL_RENDERER_ACCELERATED:
   473         SDL_Log("Accelerated");
   474         break;
   475     default:
   476         SDL_Log("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         SDL_Log("Unknown");
   487         break;
   488     case SDL_PIXELFORMAT_INDEX1LSB:
   489         SDL_Log("Index1LSB");
   490         break;
   491     case SDL_PIXELFORMAT_INDEX1MSB:
   492         SDL_Log("Index1MSB");
   493         break;
   494     case SDL_PIXELFORMAT_INDEX4LSB:
   495         SDL_Log("Index4LSB");
   496         break;
   497     case SDL_PIXELFORMAT_INDEX4MSB:
   498         SDL_Log("Index4MSB");
   499         break;
   500     case SDL_PIXELFORMAT_INDEX8:
   501         SDL_Log("Index8");
   502         break;
   503     case SDL_PIXELFORMAT_RGB332:
   504         SDL_Log("RGB332");
   505         break;
   506     case SDL_PIXELFORMAT_RGB444:
   507         SDL_Log("RGB444");
   508         break;
   509     case SDL_PIXELFORMAT_RGB555:
   510         SDL_Log("RGB555");
   511         break;
   512     case SDL_PIXELFORMAT_BGR555:
   513         SDL_Log("BGR555");
   514         break;
   515     case SDL_PIXELFORMAT_ARGB4444:
   516         SDL_Log("ARGB4444");
   517         break;
   518     case SDL_PIXELFORMAT_ABGR4444:
   519         SDL_Log("ABGR4444");
   520         break;
   521     case SDL_PIXELFORMAT_ARGB1555:
   522         SDL_Log("ARGB1555");
   523         break;
   524     case SDL_PIXELFORMAT_ABGR1555:
   525         SDL_Log("ABGR1555");
   526         break;
   527     case SDL_PIXELFORMAT_RGB565:
   528         SDL_Log("RGB565");
   529         break;
   530     case SDL_PIXELFORMAT_BGR565:
   531         SDL_Log("BGR565");
   532         break;
   533     case SDL_PIXELFORMAT_RGB24:
   534         SDL_Log("RGB24");
   535         break;
   536     case SDL_PIXELFORMAT_BGR24:
   537         SDL_Log("BGR24");
   538         break;
   539     case SDL_PIXELFORMAT_RGB888:
   540         SDL_Log("RGB888");
   541         break;
   542     case SDL_PIXELFORMAT_BGR888:
   543         SDL_Log("BGR888");
   544         break;
   545     case SDL_PIXELFORMAT_ARGB8888:
   546         SDL_Log("ARGB8888");
   547         break;
   548     case SDL_PIXELFORMAT_RGBA8888:
   549         SDL_Log("RGBA8888");
   550         break;
   551     case SDL_PIXELFORMAT_ABGR8888:
   552         SDL_Log("ABGR8888");
   553         break;
   554     case SDL_PIXELFORMAT_BGRA8888:
   555         SDL_Log("BGRA8888");
   556         break;
   557     case SDL_PIXELFORMAT_ARGB2101010:
   558         SDL_Log("ARGB2101010");
   559         break;
   560     case SDL_PIXELFORMAT_YV12:
   561         SDL_Log("YV12");
   562         break;
   563     case SDL_PIXELFORMAT_IYUV:
   564         SDL_Log("IYUV");
   565         break;
   566     case SDL_PIXELFORMAT_YUY2:
   567         SDL_Log("YUY2");
   568         break;
   569     case SDL_PIXELFORMAT_UYVY:
   570         SDL_Log("UYVY");
   571         break;
   572     case SDL_PIXELFORMAT_YVYU:
   573         SDL_Log("YVYU");
   574         break;
   575     case SDL_PIXELFORMAT_NV12:
   576         SDL_Log("NV12");
   577         break;
   578     case SDL_PIXELFORMAT_NV21:
   579         SDL_Log("NV21");
   580         break;
   581     default:
   582         SDL_Log("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     SDL_Log("  Renderer %s:\n", info->name);
   593 
   594     SDL_Log("    Flags: 0x%8.8X", info->flags);
   595     SDL_Log(" (");
   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                 SDL_Log(" | ");
   602             }
   603             SDLTest_PrintRendererFlag(flag);
   604             ++count;
   605         }
   606     }
   607     SDL_Log(")\n");
   608 
   609     SDL_Log("    Texture formats (%d): ", info->num_texture_formats);
   610     for (i = 0; i < (int) info->num_texture_formats; ++i) {
   611         if (i > 0) {
   612             SDL_Log(", ");
   613         }
   614         SDLTest_PrintPixelFormat(info->texture_formats[i]);
   615     }
   616     SDL_Log("\n");
   617 
   618     if (info->max_texture_width || info->max_texture_height) {
   619         SDL_Log("    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         SDL_Log("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                 SDL_Log("No built-in video drivers\n");
   655             } else {
   656                 SDL_Log("Built-in video drivers:");
   657                 for (i = 0; i < n; ++i) {
   658                     if (i > 0) {
   659                         SDL_Log(",");
   660                     }
   661                     SDL_Log(" %s", SDL_GetVideoDriver(i));
   662                 }
   663                 SDL_Log("\n");
   664             }
   665         }
   666         if (SDL_VideoInit(state->videodriver) < 0) {
   667             SDL_Log("Couldn't initialize video driver: %s\n",
   668                     SDL_GetError());
   669             return SDL_FALSE;
   670         }
   671         if (state->verbose & VERBOSE_VIDEO) {
   672             SDL_Log("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             SDL_Log("Number of displays: %d\n", n);
   719             for (i = 0; i < n; ++i) {
   720                 SDL_Log("Display %d: %s\n", i, SDL_GetDisplayName(i));
   721 
   722                 SDL_zero(bounds);
   723                 SDL_GetDisplayBounds(i, &bounds);
   724                 SDL_Log("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                 SDL_Log("  Current mode: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
   730                         mode.w, mode.h, mode.refresh_rate, bpp,
   731                         SDL_GetPixelFormatName(mode.format));
   732                 if (Rmask || Gmask || Bmask) {
   733                     SDL_Log("      Red Mask   = 0x%.8x\n", Rmask);
   734                     SDL_Log("      Green Mask = 0x%.8x\n", Gmask);
   735                     SDL_Log("      Blue Mask  = 0x%.8x\n", Bmask);
   736                     if (Amask)
   737                         SDL_Log("      Alpha Mask = 0x%.8x\n", Amask);
   738                 }
   739 
   740                 /* Print available fullscreen video modes */
   741                 m = SDL_GetNumDisplayModes(i);
   742                 if (m == 0) {
   743                     SDL_Log("No available fullscreen video modes\n");
   744                 } else {
   745                     SDL_Log("  Fullscreen video modes:\n");
   746                     for (j = 0; j < m; ++j) {
   747                         SDL_GetDisplayMode(i, j, &mode);
   748                         SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
   749                                                    &Gmask, &Bmask, &Amask);
   750 						SDL_Log("    Mode %d: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
   751                                 j, mode.w, mode.h, mode.refresh_rate, bpp,
   752                                 SDL_GetPixelFormatName(mode.format));
   753                         if (Rmask || Gmask || Bmask) {
   754                             SDL_Log("        Red Mask   = 0x%.8x\n",
   755                                     Rmask);
   756                             SDL_Log("        Green Mask = 0x%.8x\n",
   757                                     Gmask);
   758                             SDL_Log("        Blue Mask  = 0x%.8x\n",
   759                                     Bmask);
   760                             if (Amask)
   761 								SDL_Log("        Alpha Mask = 0x%.8x\n",
   762                                         Amask);
   763                         }
   764                     }
   765                 }
   766 
   767 #if SDL_VIDEO_DRIVER_WINDOWS
   768 				/* Print the D3D9 adapter index */
   769 				adapterIndex = SDL_Direct3D9GetAdapterIndex( i );
   770 				SDL_Log("D3D9 Adapter Index: %d", adapterIndex);
   771 
   772 				/* Print the DXGI adapter and output indices */
   773 				SDL_DXGIGetOutputInfo(i, &adapterIndex, &outputIndex);
   774 				SDL_Log("DXGI Adapter Index: %d  Output Index: %d", adapterIndex, outputIndex);
   775 #endif
   776             }
   777         }
   778 
   779         if (state->verbose & VERBOSE_RENDER) {
   780             SDL_RendererInfo info;
   781 
   782             n = SDL_GetNumRenderDrivers();
   783             if (n == 0) {
   784                 SDL_Log("No built-in render drivers\n");
   785             } else {
   786                 SDL_Log("Built-in render drivers:\n");
   787                 for (i = 0; i < n; ++i) {
   788                     SDL_GetRenderDriverInfo(i, &info);
   789                     SDLTest_PrintRenderer(&info);
   790                 }
   791             }
   792         }
   793 
   794         SDL_zero(fullscreen_mode);
   795         switch (state->depth) {
   796         case 8:
   797             fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
   798             break;
   799         case 15:
   800             fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
   801             break;
   802         case 16:
   803             fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
   804             break;
   805         case 24:
   806             fullscreen_mode.format = SDL_PIXELFORMAT_RGB24;
   807             break;
   808         default:
   809             fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
   810             break;
   811         }
   812         fullscreen_mode.refresh_rate = state->refresh_rate;
   813 
   814         state->windows =
   815             (SDL_Window **) SDL_malloc(state->num_windows *
   816                                         sizeof(*state->windows));
   817         state->renderers =
   818             (SDL_Renderer **) SDL_malloc(state->num_windows *
   819                                         sizeof(*state->renderers));
   820         state->targets =
   821             (SDL_Texture **) SDL_malloc(state->num_windows *
   822                                         sizeof(*state->targets));
   823         if (!state->windows || !state->renderers) {
   824             SDL_Log("Out of memory!\n");
   825             return SDL_FALSE;
   826         }
   827         for (i = 0; i < state->num_windows; ++i) {
   828             char title[1024];
   829 
   830             if (state->num_windows > 1) {
   831                 SDL_snprintf(title, SDL_arraysize(title), "%s %d",
   832                              state->window_title, i + 1);
   833             } else {
   834                 SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
   835             }
   836             state->windows[i] =
   837                 SDL_CreateWindow(title, state->window_x, state->window_y,
   838                                  state->window_w, state->window_h,
   839                                  state->window_flags);
   840             if (!state->windows[i]) {
   841                 SDL_Log("Couldn't create window: %s\n",
   842                         SDL_GetError());
   843                 return SDL_FALSE;
   844             }
   845             if (state->window_minW || state->window_minH) {
   846                 SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
   847             }
   848             if (state->window_maxW || state->window_maxH) {
   849                 SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
   850             }
   851             SDL_GetWindowSize(state->windows[i], &w, &h);
   852             if (!(state->window_flags & SDL_WINDOW_RESIZABLE) &&
   853                 (w != state->window_w || h != state->window_h)) {
   854                 printf("Window requested size %dx%d, got %dx%d\n", state->window_w, state->window_h, w, h);
   855                 state->window_w = w;
   856                 state->window_h = h;
   857             }
   858             if (SDL_SetWindowDisplayMode(state->windows[i], &fullscreen_mode) < 0) {
   859                 SDL_Log("Can't set up fullscreen display mode: %s\n",
   860                         SDL_GetError());
   861                 return SDL_FALSE;
   862             }
   863 
   864             if (state->window_icon) {
   865                 SDL_Surface *icon = SDLTest_LoadIcon(state->window_icon);
   866                 if (icon) {
   867                     SDL_SetWindowIcon(state->windows[i], icon);
   868                     SDL_FreeSurface(icon);
   869                 }
   870             }
   871 
   872             SDL_ShowWindow(state->windows[i]);
   873 
   874             state->renderers[i] = NULL;
   875             state->targets[i] = NULL;
   876 
   877             if (!state->skip_renderer
   878                 && (state->renderdriver
   879                     || !(state->window_flags & SDL_WINDOW_OPENGL))) {
   880                 m = -1;
   881                 if (state->renderdriver) {
   882                     SDL_RendererInfo info;
   883                     n = SDL_GetNumRenderDrivers();
   884                     for (j = 0; j < n; ++j) {
   885                         SDL_GetRenderDriverInfo(j, &info);
   886                         if (SDL_strcasecmp(info.name, state->renderdriver) ==
   887                             0) {
   888                             m = j;
   889                             break;
   890                         }
   891                     }
   892                     if (m == -1) {
   893 						SDL_Log("Couldn't find render driver named %s",
   894                                 state->renderdriver);
   895                         return SDL_FALSE;
   896                     }
   897                 }
   898                 state->renderers[i] = SDL_CreateRenderer(state->windows[i],
   899                                             m, state->render_flags);
   900                 if (!state->renderers[i]) {
   901                     SDL_Log("Couldn't create renderer: %s\n",
   902                             SDL_GetError());
   903                     return SDL_FALSE;
   904                 }
   905                 if (state->logical_w && state->logical_h) {
   906                     SDL_RenderSetLogicalSize(state->renderers[i], state->logical_w, state->logical_h);
   907                 } else if (state->scale) {
   908                     SDL_RenderSetScale(state->renderers[i], state->scale, state->scale);
   909                 }
   910                 if (state->verbose & VERBOSE_RENDER) {
   911                     SDL_RendererInfo info;
   912 
   913                     SDL_Log("Current renderer:\n");
   914                     SDL_GetRendererInfo(state->renderers[i], &info);
   915                     SDLTest_PrintRenderer(&info);
   916                 }
   917             }
   918         }
   919     }
   920 
   921     if (state->flags & SDL_INIT_AUDIO) {
   922         if (state->verbose & VERBOSE_AUDIO) {
   923             n = SDL_GetNumAudioDrivers();
   924             if (n == 0) {
   925                 SDL_Log("No built-in audio drivers\n");
   926             } else {
   927                 SDL_Log("Built-in audio drivers:");
   928                 for (i = 0; i < n; ++i) {
   929                     if (i > 0) {
   930                         SDL_Log(",");
   931                     }
   932                     SDL_Log(" %s", SDL_GetAudioDriver(i));
   933                 }
   934                 SDL_Log("\n");
   935             }
   936         }
   937         if (SDL_AudioInit(state->audiodriver) < 0) {
   938             SDL_Log("Couldn't initialize audio driver: %s\n",
   939                     SDL_GetError());
   940             return SDL_FALSE;
   941         }
   942         if (state->verbose & VERBOSE_VIDEO) {
   943             SDL_Log("Audio driver: %s\n",
   944                     SDL_GetCurrentAudioDriver());
   945         }
   946 
   947         if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
   948             SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
   949             return SDL_FALSE;
   950         }
   951     }
   952 
   953     return SDL_TRUE;
   954 }
   955 
   956 static const char *
   957 ControllerAxisName(const SDL_GameControllerAxis axis)
   958 {
   959     switch (axis)
   960     {
   961 #define AXIS_CASE(ax) case SDL_CONTROLLER_AXIS_##ax: return #ax
   962         AXIS_CASE(INVALID);
   963         AXIS_CASE(LEFTX);
   964         AXIS_CASE(LEFTY);
   965         AXIS_CASE(RIGHTX);
   966         AXIS_CASE(RIGHTY);
   967         AXIS_CASE(TRIGGERLEFT);
   968         AXIS_CASE(TRIGGERRIGHT);
   969 #undef AXIS_CASE
   970 default: return "???";
   971     }
   972 }
   973 
   974 static const char *
   975 ControllerButtonName(const SDL_GameControllerButton button)
   976 {
   977     switch (button)
   978     {
   979 #define BUTTON_CASE(btn) case SDL_CONTROLLER_BUTTON_##btn: return #btn
   980         BUTTON_CASE(INVALID);
   981         BUTTON_CASE(A);
   982         BUTTON_CASE(B);
   983         BUTTON_CASE(X);
   984         BUTTON_CASE(Y);
   985         BUTTON_CASE(BACK);
   986         BUTTON_CASE(GUIDE);
   987         BUTTON_CASE(START);
   988         BUTTON_CASE(LEFTSTICK);
   989         BUTTON_CASE(RIGHTSTICK);
   990         BUTTON_CASE(LEFTSHOULDER);
   991         BUTTON_CASE(RIGHTSHOULDER);
   992         BUTTON_CASE(DPAD_UP);
   993         BUTTON_CASE(DPAD_DOWN);
   994         BUTTON_CASE(DPAD_LEFT);
   995         BUTTON_CASE(DPAD_RIGHT);
   996 #undef BUTTON_CASE
   997 default: return "???";
   998     }
   999 }
  1000 
  1001 static void
  1002 SDLTest_PrintEvent(SDL_Event * event)
  1003 {
  1004     if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
  1005         /* Mouse and finger motion are really spammy */
  1006         return;
  1007     }
  1008 
  1009     switch (event->type) {
  1010     case SDL_WINDOWEVENT:
  1011         switch (event->window.event) {
  1012         case SDL_WINDOWEVENT_SHOWN:
  1013             SDL_Log("SDL EVENT: Window %d shown", event->window.windowID);
  1014             break;
  1015         case SDL_WINDOWEVENT_HIDDEN:
  1016             SDL_Log("SDL EVENT: Window %d hidden", event->window.windowID);
  1017             break;
  1018         case SDL_WINDOWEVENT_EXPOSED:
  1019             SDL_Log("SDL EVENT: Window %d exposed", event->window.windowID);
  1020             break;
  1021         case SDL_WINDOWEVENT_MOVED:
  1022             SDL_Log("SDL EVENT: Window %d moved to %d,%d",
  1023                     event->window.windowID, event->window.data1,
  1024                     event->window.data2);
  1025             break;
  1026         case SDL_WINDOWEVENT_RESIZED:
  1027             SDL_Log("SDL EVENT: Window %d resized to %dx%d",
  1028                     event->window.windowID, event->window.data1,
  1029                     event->window.data2);
  1030             break;
  1031         case SDL_WINDOWEVENT_SIZE_CHANGED:
  1032             SDL_Log("SDL EVENT: Window %d changed size to %dx%d",
  1033                     event->window.windowID, event->window.data1,
  1034                     event->window.data2);
  1035             break;
  1036         case SDL_WINDOWEVENT_MINIMIZED:
  1037             SDL_Log("SDL EVENT: Window %d minimized", event->window.windowID);
  1038             break;
  1039         case SDL_WINDOWEVENT_MAXIMIZED:
  1040             SDL_Log("SDL EVENT: Window %d maximized", event->window.windowID);
  1041             break;
  1042         case SDL_WINDOWEVENT_RESTORED:
  1043             SDL_Log("SDL EVENT: Window %d restored", event->window.windowID);
  1044             break;
  1045         case SDL_WINDOWEVENT_ENTER:
  1046             SDL_Log("SDL EVENT: Mouse entered window %d",
  1047                     event->window.windowID);
  1048             break;
  1049         case SDL_WINDOWEVENT_LEAVE:
  1050             SDL_Log("SDL EVENT: Mouse left window %d", event->window.windowID);
  1051             break;
  1052         case SDL_WINDOWEVENT_FOCUS_GAINED:
  1053             SDL_Log("SDL EVENT: Window %d gained keyboard focus",
  1054                     event->window.windowID);
  1055             break;
  1056         case SDL_WINDOWEVENT_FOCUS_LOST:
  1057             SDL_Log("SDL EVENT: Window %d lost keyboard focus",
  1058                     event->window.windowID);
  1059             break;
  1060         case SDL_WINDOWEVENT_CLOSE:
  1061             SDL_Log("SDL EVENT: Window %d closed", event->window.windowID);
  1062             break;
  1063         case SDL_WINDOWEVENT_TAKE_FOCUS:
  1064             SDL_Log("SDL EVENT: Window %d take focus", event->window.windowID);
  1065             break;
  1066         case SDL_WINDOWEVENT_HIT_TEST:
  1067             SDL_Log("SDL EVENT: Window %d hit test", event->window.windowID);
  1068             break;
  1069         default:
  1070             SDL_Log("SDL EVENT: Window %d got unknown event %d",
  1071                     event->window.windowID, event->window.event);
  1072             break;
  1073         }
  1074         break;
  1075     case SDL_KEYDOWN:
  1076         SDL_Log("SDL EVENT: Keyboard: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
  1077                 event->key.windowID,
  1078                 event->key.keysym.scancode,
  1079                 SDL_GetScancodeName(event->key.keysym.scancode),
  1080                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
  1081         break;
  1082     case SDL_KEYUP:
  1083         SDL_Log("SDL EVENT: Keyboard: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
  1084                 event->key.windowID,
  1085                 event->key.keysym.scancode,
  1086                 SDL_GetScancodeName(event->key.keysym.scancode),
  1087                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
  1088         break;
  1089     case SDL_TEXTINPUT:
  1090         SDL_Log("SDL EVENT: Keyboard: text input \"%s\" in window %d",
  1091                 event->text.text, event->text.windowID);
  1092         break;
  1093     case SDL_MOUSEMOTION:
  1094         SDL_Log("SDL EVENT: Mouse: moved to %d,%d (%d,%d) in window %d",
  1095                 event->motion.x, event->motion.y,
  1096                 event->motion.xrel, event->motion.yrel,
  1097                 event->motion.windowID);
  1098         break;
  1099     case SDL_MOUSEBUTTONDOWN:
  1100         SDL_Log("SDL EVENT: Mouse: button %d pressed at %d,%d with click count %d in window %d",
  1101                 event->button.button, event->button.x, event->button.y, event->button.clicks,
  1102                 event->button.windowID);
  1103         break;
  1104     case SDL_MOUSEBUTTONUP:
  1105         SDL_Log("SDL EVENT: Mouse: button %d released at %d,%d with click count %d in window %d",
  1106                 event->button.button, event->button.x, event->button.y, event->button.clicks,
  1107                 event->button.windowID);
  1108         break;
  1109     case SDL_MOUSEWHEEL:
  1110         SDL_Log("SDL EVENT: Mouse: wheel scrolled %d in x and %d in y (reversed: %d) in window %d",
  1111                 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID);
  1112         break;
  1113     case SDL_JOYDEVICEADDED:
  1114         SDL_Log("SDL EVENT: Joystick index %d attached",
  1115             event->jdevice.which);
  1116         break;
  1117     case SDL_JOYDEVICEREMOVED:
  1118         SDL_Log("SDL EVENT: Joystick %d removed",
  1119             event->jdevice.which);
  1120         break;
  1121     case SDL_JOYBALLMOTION:
  1122         SDL_Log("SDL EVENT: Joystick %d: ball %d moved by %d,%d",
  1123                 event->jball.which, event->jball.ball, event->jball.xrel,
  1124                 event->jball.yrel);
  1125         break;
  1126     case SDL_JOYHATMOTION:
  1127         {
  1128             const char *position = "UNKNOWN";
  1129             switch (event->jhat.value) {
  1130             case SDL_HAT_CENTERED:
  1131                 position = "CENTER";
  1132                 break;
  1133             case SDL_HAT_UP:
  1134                 position = "UP";
  1135                 break;
  1136             case SDL_HAT_RIGHTUP:
  1137                 position = "RIGHTUP";
  1138                 break;
  1139             case SDL_HAT_RIGHT:
  1140                 position = "RIGHT";
  1141                 break;
  1142             case SDL_HAT_RIGHTDOWN:
  1143                 position = "RIGHTDOWN";
  1144                 break;
  1145             case SDL_HAT_DOWN:
  1146                 position = "DOWN";
  1147                 break;
  1148             case SDL_HAT_LEFTDOWN:
  1149                 position = "LEFTDOWN";
  1150                 break;
  1151             case SDL_HAT_LEFT:
  1152                 position = "LEFT";
  1153                 break;
  1154             case SDL_HAT_LEFTUP:
  1155                 position = "LEFTUP";
  1156                 break;
  1157             }
  1158             SDL_Log("SDL EVENT: Joystick %d: hat %d moved to %s", event->jhat.which,
  1159                 event->jhat.hat, position);
  1160         }
  1161         break;
  1162     case SDL_JOYBUTTONDOWN:
  1163         SDL_Log("SDL EVENT: Joystick %d: button %d pressed",
  1164                 event->jbutton.which, event->jbutton.button);
  1165         break;
  1166     case SDL_JOYBUTTONUP:
  1167         SDL_Log("SDL EVENT: Joystick %d: button %d released",
  1168                 event->jbutton.which, event->jbutton.button);
  1169         break;
  1170     case SDL_CONTROLLERDEVICEADDED:
  1171         SDL_Log("SDL EVENT: Controller index %d attached",
  1172             event->cdevice.which);
  1173         break;
  1174     case SDL_CONTROLLERDEVICEREMOVED:
  1175         SDL_Log("SDL EVENT: Controller %d removed",
  1176             event->cdevice.which);
  1177         break;
  1178     case SDL_CONTROLLERAXISMOTION:
  1179         SDL_Log("SDL EVENT: Controller %d axis %d ('%s') value: %d",
  1180             event->caxis.which,
  1181             event->caxis.axis,
  1182             ControllerAxisName((SDL_GameControllerAxis)event->caxis.axis),
  1183             event->caxis.value);
  1184         break;
  1185     case SDL_CONTROLLERBUTTONDOWN:
  1186         SDL_Log("SDL EVENT: Controller %d button %d ('%s') down",
  1187             event->cbutton.which, event->cbutton.button,
  1188             ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
  1189         break;
  1190     case SDL_CONTROLLERBUTTONUP:
  1191         SDL_Log("SDL EVENT: Controller %d button %d ('%s') up",
  1192             event->cbutton.which, event->cbutton.button,
  1193             ControllerButtonName((SDL_GameControllerButton)event->cbutton.button));
  1194         break;
  1195     case SDL_CLIPBOARDUPDATE:
  1196         SDL_Log("SDL EVENT: Clipboard updated");
  1197         break;
  1198 
  1199     case SDL_FINGERDOWN:
  1200     case SDL_FINGERUP:
  1201         SDL_Log("SDL EVENT: Finger: %s touch=%ld, finger=%ld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
  1202                 (event->type == SDL_FINGERDOWN) ? "down" : "up",
  1203                 (long) event->tfinger.touchId,
  1204                 (long) event->tfinger.fingerId,
  1205                 event->tfinger.x, event->tfinger.y,
  1206                 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
  1207         break;
  1208     case SDL_DOLLARGESTURE:
  1209         SDL_Log("SDL_EVENT: Dollar gesture detect: %ld", (long) event->dgesture.gestureId);
  1210         break;
  1211     case SDL_DOLLARRECORD:
  1212         SDL_Log("SDL_EVENT: Dollar gesture record: %ld", (long) event->dgesture.gestureId);
  1213         break;
  1214     case SDL_MULTIGESTURE:
  1215         SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers);
  1216         break;
  1217 
  1218     case SDL_RENDER_DEVICE_RESET:
  1219         SDL_Log("SDL EVENT: render device reset");
  1220         break;
  1221     case SDL_RENDER_TARGETS_RESET:
  1222         SDL_Log("SDL EVENT: render targets reset");
  1223         break;
  1224 
  1225     case SDL_QUIT:
  1226         SDL_Log("SDL EVENT: Quit requested");
  1227         break;
  1228     case SDL_USEREVENT:
  1229         SDL_Log("SDL EVENT: User event %d", event->user.code);
  1230         break;
  1231     default:
  1232         SDL_Log("Unknown event %04x", event->type);
  1233         break;
  1234     }
  1235 }
  1236 
  1237 static void
  1238 SDLTest_ScreenShot(SDL_Renderer *renderer)
  1239 {
  1240     SDL_Rect viewport;
  1241     SDL_Surface *surface;
  1242 
  1243     if (!renderer) {
  1244         return;
  1245     }
  1246 
  1247     SDL_RenderGetViewport(renderer, &viewport);
  1248     surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24,
  1249 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  1250                     0x00FF0000, 0x0000FF00, 0x000000FF,
  1251 #else
  1252                     0x000000FF, 0x0000FF00, 0x00FF0000,
  1253 #endif
  1254                     0x00000000);
  1255     if (!surface) {
  1256         SDL_Log("Couldn't create surface: %s\n", SDL_GetError());
  1257         return;
  1258     }
  1259 
  1260     if (SDL_RenderReadPixels(renderer, NULL, surface->format->format,
  1261                              surface->pixels, surface->pitch) < 0) {
  1262         SDL_Log("Couldn't read screen: %s\n", SDL_GetError());
  1263         SDL_free(surface);
  1264         return;
  1265     }
  1266 
  1267     if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
  1268         SDL_Log("Couldn't save screenshot.bmp: %s\n", SDL_GetError());
  1269         SDL_free(surface);
  1270         return;
  1271     }
  1272 }
  1273 
  1274 static void
  1275 FullscreenTo(int index, int windowId)
  1276 {
  1277     Uint32 flags;
  1278     struct SDL_Rect rect = { 0, 0, 0, 0 };
  1279     SDL_Window *window = SDL_GetWindowFromID(windowId);
  1280     if (!window) {
  1281         return;
  1282     }
  1283 
  1284     SDL_GetDisplayBounds( index, &rect );
  1285 
  1286     flags = SDL_GetWindowFlags(window);
  1287     if (flags & SDL_WINDOW_FULLSCREEN) {
  1288         SDL_SetWindowFullscreen( window, SDL_FALSE );
  1289         SDL_Delay( 15 );
  1290     }
  1291 
  1292     SDL_SetWindowPosition( window, rect.x, rect.y );
  1293     SDL_SetWindowFullscreen( window, SDL_TRUE );
  1294 }
  1295 
  1296 void
  1297 SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
  1298 {
  1299     int i;
  1300     static SDL_MouseMotionEvent lastEvent;
  1301 
  1302     if (state->verbose & VERBOSE_EVENT) {
  1303         SDLTest_PrintEvent(event);
  1304     }
  1305 
  1306     switch (event->type) {
  1307     case SDL_WINDOWEVENT:
  1308         switch (event->window.event) {
  1309         case SDL_WINDOWEVENT_CLOSE:
  1310             {
  1311                 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
  1312                 if (window) {
  1313                     for (i = 0; i < state->num_windows; ++i) {
  1314                         if (window == state->windows[i]) {
  1315                             if (state->targets[i]) {
  1316                                 SDL_DestroyTexture(state->targets[i]);
  1317                                 state->targets[i] = NULL;
  1318                             }
  1319                             if (state->renderers[i]) {
  1320                                 SDL_DestroyRenderer(state->renderers[i]);
  1321                                 state->renderers[i] = NULL;
  1322                             }
  1323                             SDL_DestroyWindow(state->windows[i]);
  1324                             state->windows[i] = NULL;
  1325                             break;
  1326                         }
  1327                     }
  1328                 }
  1329             }
  1330             break;
  1331         }
  1332         break;
  1333     case SDL_KEYDOWN: {
  1334         SDL_bool withControl = !!(event->key.keysym.mod & KMOD_CTRL);
  1335         SDL_bool withShift = !!(event->key.keysym.mod & KMOD_SHIFT);
  1336         SDL_bool withAlt = !!(event->key.keysym.mod & KMOD_ALT);
  1337 
  1338         switch (event->key.keysym.sym) {
  1339             /* Add hotkeys here */
  1340         case SDLK_PRINTSCREEN: {
  1341                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1342                 if (window) {
  1343                     for (i = 0; i < state->num_windows; ++i) {
  1344                         if (window == state->windows[i]) {
  1345                             SDLTest_ScreenShot(state->renderers[i]);
  1346                         }
  1347                     }
  1348                 }
  1349             }
  1350             break;
  1351         case SDLK_EQUALS:
  1352             if (withControl) {
  1353                 /* Ctrl-+ double the size of the window */
  1354                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1355                 if (window) {
  1356                     int w, h;
  1357                     SDL_GetWindowSize(window, &w, &h);
  1358                     SDL_SetWindowSize(window, w*2, h*2);
  1359                 }
  1360             }
  1361             break;
  1362         case SDLK_MINUS:
  1363             if (withControl) {
  1364                 /* Ctrl-- half the size of the window */
  1365                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1366                 if (window) {
  1367                     int w, h;
  1368                     SDL_GetWindowSize(window, &w, &h);
  1369                     SDL_SetWindowSize(window, w/2, h/2);
  1370                 }
  1371             }
  1372             break;
  1373         case SDLK_o:
  1374             if (withControl) {
  1375                 /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
  1376                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1377                 if (window) {
  1378                     float opacity;
  1379                     if (SDL_GetWindowOpacity(window, &opacity) == 0) {
  1380                         if (withShift) {
  1381                             opacity += 0.20f;
  1382                         } else {
  1383                             opacity -= 0.20f;
  1384                         }
  1385                         SDL_SetWindowOpacity(window, opacity);
  1386                     }
  1387                 }
  1388             }
  1389             break;
  1390 
  1391         case SDLK_c:
  1392             if (withControl) {
  1393                 /* Ctrl-C copy awesome text! */
  1394                 SDL_SetClipboardText("SDL rocks!\nYou know it!");
  1395                 printf("Copied text to clipboard\n");
  1396             }
  1397             if (withAlt) {
  1398                 /* Alt-C toggle a render clip rectangle */
  1399                 for (i = 0; i < state->num_windows; ++i) {
  1400                     int w, h;
  1401                     if (state->renderers[i]) {
  1402                         SDL_Rect clip;
  1403                         SDL_GetWindowSize(state->windows[i], &w, &h);
  1404                         SDL_RenderGetClipRect(state->renderers[i], &clip);
  1405                         if (SDL_RectEmpty(&clip)) {
  1406                             clip.x = w/4;
  1407                             clip.y = h/4;
  1408                             clip.w = w/2;
  1409                             clip.h = h/2;
  1410                             SDL_RenderSetClipRect(state->renderers[i], &clip);
  1411                         } else {
  1412                             SDL_RenderSetClipRect(state->renderers[i], NULL);
  1413                         }
  1414                     }
  1415                 }
  1416             }
  1417             if (withShift) {
  1418                 SDL_Window *current_win = SDL_GetKeyboardFocus();
  1419                 if (current_win) {
  1420                     const SDL_bool shouldCapture = (SDL_GetWindowFlags(current_win) & SDL_WINDOW_MOUSE_CAPTURE) == 0;
  1421                     const int rc = SDL_CaptureMouse(shouldCapture);
  1422                     SDL_Log("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", (rc == 0) ? "succeeded" : "failed");
  1423                 }
  1424             }
  1425             break;
  1426         case SDLK_v:
  1427             if (withControl) {
  1428                 /* Ctrl-V paste awesome text! */
  1429                 char *text = SDL_GetClipboardText();
  1430                 if (*text) {
  1431                     printf("Clipboard: %s\n", text);
  1432                 } else {
  1433                     printf("Clipboard is empty\n");
  1434                 }
  1435                 SDL_free(text);
  1436             }
  1437             break;
  1438         case SDLK_g:
  1439             if (withControl) {
  1440                 /* Ctrl-G toggle grab */
  1441                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1442                 if (window) {
  1443                     SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
  1444                 }
  1445             }
  1446             break;
  1447         case SDLK_m:
  1448             if (withControl) {
  1449                 /* Ctrl-M maximize */
  1450                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1451                 if (window) {
  1452                     Uint32 flags = SDL_GetWindowFlags(window);
  1453                     if (flags & SDL_WINDOW_MAXIMIZED) {
  1454                         SDL_RestoreWindow(window);
  1455                     } else {
  1456                         SDL_MaximizeWindow(window);
  1457                     }
  1458                 }
  1459             }
  1460             break;
  1461         case SDLK_r:
  1462             if (withControl) {
  1463                 /* Ctrl-R toggle mouse relative mode */
  1464                 SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE);
  1465             }
  1466             break;
  1467         case SDLK_z:
  1468             if (withControl) {
  1469                 /* Ctrl-Z minimize */
  1470                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1471                 if (window) {
  1472                     SDL_MinimizeWindow(window);
  1473                 }
  1474             }
  1475             break;
  1476         case SDLK_RETURN:
  1477             if (withControl) {
  1478                 /* Ctrl-Enter toggle fullscreen */
  1479                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1480                 if (window) {
  1481                     Uint32 flags = SDL_GetWindowFlags(window);
  1482                     if (flags & SDL_WINDOW_FULLSCREEN) {
  1483                         SDL_SetWindowFullscreen(window, SDL_FALSE);
  1484                     } else {
  1485                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
  1486                     }
  1487                 }
  1488             } else if (withAlt) {
  1489                 /* Alt-Enter toggle fullscreen desktop */
  1490                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1491                 if (window) {
  1492                     Uint32 flags = SDL_GetWindowFlags(window);
  1493                     if (flags & SDL_WINDOW_FULLSCREEN) {
  1494                         SDL_SetWindowFullscreen(window, SDL_FALSE);
  1495                     } else {
  1496                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
  1497                     }
  1498                 }
  1499             } else if (withShift) {
  1500                 /* Shift-Enter toggle fullscreen desktop / fullscreen */
  1501                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1502                 if (window) {
  1503                     Uint32 flags = SDL_GetWindowFlags(window);
  1504                     if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
  1505                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
  1506                     } else {
  1507                         SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
  1508                     }
  1509                 }
  1510             }
  1511 
  1512             break;
  1513         case SDLK_b:
  1514             if (withControl) {
  1515                 /* Ctrl-B toggle window border */
  1516                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1517                 if (window) {
  1518                     const Uint32 flags = SDL_GetWindowFlags(window);
  1519                     const SDL_bool b = ((flags & SDL_WINDOW_BORDERLESS) != 0) ? SDL_TRUE : SDL_FALSE;
  1520                     SDL_SetWindowBordered(window, b);
  1521                 }
  1522             }
  1523             break;
  1524         case SDLK_a:
  1525             if (withControl) {
  1526                 /* Ctrl-A reports absolute mouse position. */
  1527                 int x, y;
  1528                 const Uint32 mask = SDL_GetGlobalMouseState(&x, &y);
  1529                 SDL_Log("ABSOLUTE MOUSE: (%d, %d)%s%s%s%s%s\n", x, y,
  1530                         (mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
  1531                         (mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
  1532                         (mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
  1533                         (mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
  1534                         (mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
  1535             }
  1536             break;
  1537         case SDLK_0:
  1538             if (withControl) {
  1539                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1540                 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
  1541             }
  1542             break;
  1543         case SDLK_1:
  1544             if (withControl) {
  1545                 FullscreenTo(0, event->key.windowID);
  1546             }
  1547             break;
  1548         case SDLK_2:
  1549             if (withControl) {
  1550                 FullscreenTo(1, event->key.windowID);
  1551             }
  1552             break;
  1553         case SDLK_ESCAPE:
  1554             *done = 1;
  1555             break;
  1556         case SDLK_SPACE:
  1557         {
  1558             char message[256];
  1559             SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1560 
  1561             SDL_snprintf(message, sizeof(message), "(%i, %i), rel (%i, %i)\n", lastEvent.x, lastEvent.y, lastEvent.xrel, lastEvent.yrel);
  1562             SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Last mouse position", message, window);
  1563             break;
  1564         }
  1565         default:
  1566             break;
  1567         }
  1568         break;
  1569     }
  1570     case SDL_QUIT:
  1571         *done = 1;
  1572         break;
  1573     case SDL_MOUSEMOTION:
  1574         lastEvent = event->motion;
  1575         break;
  1576     }
  1577 }
  1578 
  1579 void
  1580 SDLTest_CommonQuit(SDLTest_CommonState * state)
  1581 {
  1582     int i;
  1583 
  1584     SDL_free(state->windows);
  1585     if (state->targets) {
  1586         for (i = 0; i < state->num_windows; ++i) {
  1587             if (state->targets[i]) {
  1588                 SDL_DestroyTexture(state->targets[i]);
  1589             }
  1590         }
  1591         SDL_free(state->targets);
  1592     }
  1593     if (state->renderers) {
  1594         for (i = 0; i < state->num_windows; ++i) {
  1595             if (state->renderers[i]) {
  1596                 SDL_DestroyRenderer(state->renderers[i]);
  1597             }
  1598         }
  1599         SDL_free(state->renderers);
  1600     }
  1601     if (state->flags & SDL_INIT_VIDEO) {
  1602         SDL_VideoQuit();
  1603     }
  1604     if (state->flags & SDL_INIT_AUDIO) {
  1605         SDL_AudioQuit();
  1606     }
  1607     SDL_free(state);
  1608     SDL_Quit();
  1609 }
  1610 
  1611 /* vi: set ts=4 sw=4 expandtab: */