test/common.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 03 Jun 2011 16:03:10 -0400
changeset 5547 4ccecd0901e2
parent 5535 96594ac5fd1a
child 6175 42c40787f382
permissions -rw-r--r--
Assert code's stdio interface was reading from the wrong variable.

Thanks to Frank Zago for the catch.
     1 /*
     2   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     3 
     4   This software is provided 'as-is', without any express or implied
     5   warranty.  In no event will the authors be held liable for any damages
     6   arising from the use of this software.
     7 
     8   Permission is granted to anyone to use this software for any purpose,
     9   including commercial applications, and to alter it and redistribute it
    10   freely.
    11 */
    12 
    13 /* A simple test program framework */
    14 
    15 #include <stdio.h>
    16 
    17 #include "common.h"
    18 
    19 #define VIDEO_USAGE \
    20 "[--video driver] [--renderer driver] [--info all|video|modes|render|event] [--log all|error|system|audio|video|render|input] [--display N] [--fullscreen | --windows N] [--title title] [--icon icon.bmp] [--center | --position X,Y] [--geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
    21 
    22 #define AUDIO_USAGE \
    23 "[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
    24 
    25 CommonState *
    26 CommonCreateState(char **argv, Uint32 flags)
    27 {
    28     CommonState *state = SDL_calloc(1, sizeof(*state));
    29     if (!state) {
    30         SDL_OutOfMemory();
    31         return NULL;
    32     }
    33 
    34     /* Initialize some defaults */
    35     state->argv = argv;
    36     state->flags = flags;
    37 #ifdef __NDS__
    38     state->window_title = "";
    39 #else
    40     state->window_title = argv[0];
    41 #endif
    42     state->window_flags = 0;
    43     state->window_x = SDL_WINDOWPOS_UNDEFINED;
    44     state->window_y = SDL_WINDOWPOS_UNDEFINED;
    45     state->window_w = DEFAULT_WINDOW_WIDTH;
    46     state->window_h = DEFAULT_WINDOW_HEIGHT;
    47     state->num_windows = 1;
    48     state->audiospec.freq = 22050;
    49     state->audiospec.format = AUDIO_S16;
    50     state->audiospec.channels = 2;
    51     state->audiospec.samples = 2048;
    52 
    53     /* Set some very sane GL defaults */
    54     state->gl_red_size = 3;
    55     state->gl_green_size = 3;
    56     state->gl_blue_size = 2;
    57     state->gl_alpha_size = 0;
    58     state->gl_buffer_size = 0;
    59     state->gl_depth_size = 16;
    60     state->gl_stencil_size = 0;
    61     state->gl_double_buffer = 1;
    62     state->gl_accum_red_size = 0;
    63     state->gl_accum_green_size = 0;
    64     state->gl_accum_blue_size = 0;
    65     state->gl_accum_alpha_size = 0;
    66     state->gl_stereo = 0;
    67     state->gl_multisamplebuffers = 0;
    68     state->gl_multisamplesamples = 0;
    69     state->gl_retained_backing = 1;
    70     state->gl_accelerated = -1;
    71 
    72     return state;
    73 }
    74 
    75 int
    76 CommonArg(CommonState * state, int index)
    77 {
    78     char **argv = state->argv;
    79 
    80 #ifdef __NDS__
    81     return 0;
    82 #endif
    83 
    84     if (SDL_strcasecmp(argv[index], "--video") == 0) {
    85         ++index;
    86         if (!argv[index]) {
    87             return -1;
    88         }
    89         state->videodriver = argv[index];
    90         return 2;
    91     }
    92     if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
    93         ++index;
    94         if (!argv[index]) {
    95             return -1;
    96         }
    97         state->renderdriver = argv[index];
    98         return 2;
    99     }
   100     if (SDL_strcasecmp(argv[index], "--info") == 0) {
   101         ++index;
   102         if (!argv[index]) {
   103             return -1;
   104         }
   105         if (SDL_strcasecmp(argv[index], "all") == 0) {
   106             state->verbose |=
   107                 (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
   108                  VERBOSE_EVENT);
   109             return 2;
   110         }
   111         if (SDL_strcasecmp(argv[index], "video") == 0) {
   112             state->verbose |= VERBOSE_VIDEO;
   113             return 2;
   114         }
   115         if (SDL_strcasecmp(argv[index], "modes") == 0) {
   116             state->verbose |= VERBOSE_MODES;
   117             return 2;
   118         }
   119         if (SDL_strcasecmp(argv[index], "render") == 0) {
   120             state->verbose |= VERBOSE_RENDER;
   121             return 2;
   122         }
   123         if (SDL_strcasecmp(argv[index], "event") == 0) {
   124             state->verbose |= VERBOSE_EVENT;
   125             return 2;
   126         }
   127         return -1;
   128     }
   129     if (SDL_strcasecmp(argv[index], "--log") == 0) {
   130         ++index;
   131         if (!argv[index]) {
   132             return -1;
   133         }
   134         if (SDL_strcasecmp(argv[index], "all") == 0) {
   135             SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
   136             return 2;
   137         }
   138         if (SDL_strcasecmp(argv[index], "error") == 0) {
   139             SDL_LogSetPriority(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_VERBOSE);
   140             return 2;
   141         }
   142         if (SDL_strcasecmp(argv[index], "system") == 0) {
   143             SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE);
   144             return 2;
   145         }
   146         if (SDL_strcasecmp(argv[index], "audio") == 0) {
   147             SDL_LogSetPriority(SDL_LOG_CATEGORY_AUDIO, SDL_LOG_PRIORITY_VERBOSE);
   148             return 2;
   149         }
   150         if (SDL_strcasecmp(argv[index], "video") == 0) {
   151             SDL_LogSetPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_VERBOSE);
   152             return 2;
   153         }
   154         if (SDL_strcasecmp(argv[index], "render") == 0) {
   155             SDL_LogSetPriority(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_VERBOSE);
   156             return 2;
   157         }
   158         if (SDL_strcasecmp(argv[index], "input") == 0) {
   159             SDL_LogSetPriority(SDL_LOG_CATEGORY_INPUT, SDL_LOG_PRIORITY_VERBOSE);
   160             return 2;
   161         }
   162         return -1;
   163     }
   164     if (SDL_strcasecmp(argv[index], "--display") == 0) {
   165         ++index;
   166         if (!argv[index]) {
   167             return -1;
   168         }
   169         state->display = SDL_atoi(argv[index]);
   170         if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
   171             state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
   172             state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
   173         }
   174         if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
   175             state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
   176             state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
   177         }
   178         return 2;
   179     }
   180     if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
   181         state->window_flags |= SDL_WINDOW_FULLSCREEN;
   182         state->num_windows = 1;
   183         return 1;
   184     }
   185     if (SDL_strcasecmp(argv[index], "--windows") == 0) {
   186         ++index;
   187         if (!argv[index] || !SDL_isdigit(*argv[index])) {
   188             return -1;
   189         }
   190         if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
   191             state->num_windows = SDL_atoi(argv[index]);
   192         }
   193         return 2;
   194     }
   195     if (SDL_strcasecmp(argv[index], "--title") == 0) {
   196         ++index;
   197         if (!argv[index]) {
   198             return -1;
   199         }
   200         state->window_title = argv[index];
   201         return 2;
   202     }
   203     if (SDL_strcasecmp(argv[index], "--icon") == 0) {
   204         ++index;
   205         if (!argv[index]) {
   206             return -1;
   207         }
   208         state->window_icon = argv[index];
   209         return 2;
   210     }
   211     if (SDL_strcasecmp(argv[index], "--center") == 0) {
   212         state->window_x = SDL_WINDOWPOS_CENTERED;
   213         state->window_y = SDL_WINDOWPOS_CENTERED;
   214         return 1;
   215     }
   216     if (SDL_strcasecmp(argv[index], "--position") == 0) {
   217         char *x, *y;
   218         ++index;
   219         if (!argv[index]) {
   220             return -1;
   221         }
   222         x = argv[index];
   223         y = argv[index];
   224         while (*y && *y != ',') {
   225             ++y;
   226         }
   227         if (!*y) {
   228             return -1;
   229         }
   230         *y++ = '\0';
   231         state->window_x = SDL_atoi(x);
   232         state->window_y = SDL_atoi(y);
   233         return 2;
   234     }
   235     if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
   236         char *w, *h;
   237         ++index;
   238         if (!argv[index]) {
   239             return -1;
   240         }
   241         w = argv[index];
   242         h = argv[index];
   243         while (*h && *h != 'x') {
   244             ++h;
   245         }
   246         if (!*h) {
   247             return -1;
   248         }
   249         *h++ = '\0';
   250         state->window_w = SDL_atoi(w);
   251         state->window_h = SDL_atoi(h);
   252         return 2;
   253     }
   254     if (SDL_strcasecmp(argv[index], "--depth") == 0) {
   255         ++index;
   256         if (!argv[index]) {
   257             return -1;
   258         }
   259         state->depth = SDL_atoi(argv[index]);
   260         return 2;
   261     }
   262     if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
   263         ++index;
   264         if (!argv[index]) {
   265             return -1;
   266         }
   267         state->refresh_rate = SDL_atoi(argv[index]);
   268         return 2;
   269     }
   270     if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
   271         state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
   272         return 1;
   273     }
   274     if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
   275         state->window_flags |= SDL_WINDOW_BORDERLESS;
   276         return 1;
   277     }
   278     if (SDL_strcasecmp(argv[index], "--resize") == 0) {
   279         state->window_flags |= SDL_WINDOW_RESIZABLE;
   280         return 1;
   281     }
   282     if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
   283         state->window_flags |= SDL_WINDOW_MINIMIZED;
   284         return 1;
   285     }
   286     if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
   287         state->window_flags |= SDL_WINDOW_MAXIMIZED;
   288         return 1;
   289     }
   290     if (SDL_strcasecmp(argv[index], "--grab") == 0) {
   291         state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
   292         return 1;
   293     }
   294     if (SDL_strcasecmp(argv[index], "--rate") == 0) {
   295         ++index;
   296         if (!argv[index]) {
   297             return -1;
   298         }
   299         state->audiospec.freq = SDL_atoi(argv[index]);
   300         return 2;
   301     }
   302     if (SDL_strcasecmp(argv[index], "--format") == 0) {
   303         ++index;
   304         if (!argv[index]) {
   305             return -1;
   306         }
   307         if (SDL_strcasecmp(argv[index], "U8") == 0) {
   308             state->audiospec.format = AUDIO_U8;
   309             return 2;
   310         }
   311         if (SDL_strcasecmp(argv[index], "S8") == 0) {
   312             state->audiospec.format = AUDIO_S8;
   313             return 2;
   314         }
   315         if (SDL_strcasecmp(argv[index], "U16") == 0) {
   316             state->audiospec.format = AUDIO_U16;
   317             return 2;
   318         }
   319         if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
   320             state->audiospec.format = AUDIO_U16LSB;
   321             return 2;
   322         }
   323         if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
   324             state->audiospec.format = AUDIO_U16MSB;
   325             return 2;
   326         }
   327         if (SDL_strcasecmp(argv[index], "S16") == 0) {
   328             state->audiospec.format = AUDIO_S16;
   329             return 2;
   330         }
   331         if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
   332             state->audiospec.format = AUDIO_S16LSB;
   333             return 2;
   334         }
   335         if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
   336             state->audiospec.format = AUDIO_S16MSB;
   337             return 2;
   338         }
   339         return -1;
   340     }
   341     if (SDL_strcasecmp(argv[index], "--channels") == 0) {
   342         ++index;
   343         if (!argv[index]) {
   344             return -1;
   345         }
   346         state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
   347         return 2;
   348     }
   349     if (SDL_strcasecmp(argv[index], "--samples") == 0) {
   350         ++index;
   351         if (!argv[index]) {
   352             return -1;
   353         }
   354         state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
   355         return 2;
   356     }
   357     if ((SDL_strcasecmp(argv[index], "-h") == 0)
   358         || (SDL_strcasecmp(argv[index], "--help") == 0)) {
   359         /* Print the usage message */
   360         return -1;
   361     }
   362     return 0;
   363 }
   364 
   365 const char *
   366 CommonUsage(CommonState * state)
   367 {
   368     switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
   369     case SDL_INIT_VIDEO:
   370         return VIDEO_USAGE;
   371     case SDL_INIT_AUDIO:
   372         return AUDIO_USAGE;
   373     case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
   374         return VIDEO_USAGE " " AUDIO_USAGE;
   375     default:
   376         return "";
   377     }
   378 }
   379 
   380 static void
   381 PrintRendererFlag(Uint32 flag)
   382 {
   383     switch (flag) {
   384     case SDL_RENDERER_PRESENTVSYNC:
   385         fprintf(stderr, "PresentVSync");
   386         break;
   387     case SDL_RENDERER_ACCELERATED:
   388         fprintf(stderr, "Accelerated");
   389         break;
   390     default:
   391         fprintf(stderr, "0x%8.8x", flag);
   392         break;
   393     }
   394 }
   395 
   396 static void
   397 PrintPixelFormat(Uint32 format)
   398 {
   399     switch (format) {
   400     case SDL_PIXELFORMAT_UNKNOWN:
   401         fprintf(stderr, "Unknwon");
   402         break;
   403     case SDL_PIXELFORMAT_INDEX1LSB:
   404         fprintf(stderr, "Index1LSB");
   405         break;
   406     case SDL_PIXELFORMAT_INDEX1MSB:
   407         fprintf(stderr, "Index1MSB");
   408         break;
   409     case SDL_PIXELFORMAT_INDEX4LSB:
   410         fprintf(stderr, "Index4LSB");
   411         break;
   412     case SDL_PIXELFORMAT_INDEX4MSB:
   413         fprintf(stderr, "Index4MSB");
   414         break;
   415     case SDL_PIXELFORMAT_INDEX8:
   416         fprintf(stderr, "Index8");
   417         break;
   418     case SDL_PIXELFORMAT_RGB332:
   419         fprintf(stderr, "RGB332");
   420         break;
   421     case SDL_PIXELFORMAT_RGB444:
   422         fprintf(stderr, "RGB444");
   423         break;
   424     case SDL_PIXELFORMAT_RGB555:
   425         fprintf(stderr, "RGB555");
   426         break;
   427     case SDL_PIXELFORMAT_BGR555:
   428         fprintf(stderr, "BGR555");
   429         break;
   430     case SDL_PIXELFORMAT_ARGB4444:
   431         fprintf(stderr, "ARGB4444");
   432         break;
   433     case SDL_PIXELFORMAT_ABGR4444:
   434         fprintf(stderr, "ABGR4444");
   435         break;
   436     case SDL_PIXELFORMAT_ARGB1555:
   437         fprintf(stderr, "ARGB1555");
   438         break;
   439     case SDL_PIXELFORMAT_ABGR1555:
   440         fprintf(stderr, "ABGR1555");
   441         break;
   442     case SDL_PIXELFORMAT_RGB565:
   443         fprintf(stderr, "RGB565");
   444         break;
   445     case SDL_PIXELFORMAT_BGR565:
   446         fprintf(stderr, "BGR565");
   447         break;
   448     case SDL_PIXELFORMAT_RGB24:
   449         fprintf(stderr, "RGB24");
   450         break;
   451     case SDL_PIXELFORMAT_BGR24:
   452         fprintf(stderr, "BGR24");
   453         break;
   454     case SDL_PIXELFORMAT_RGB888:
   455         fprintf(stderr, "RGB888");
   456         break;
   457     case SDL_PIXELFORMAT_BGR888:
   458         fprintf(stderr, "BGR888");
   459         break;
   460     case SDL_PIXELFORMAT_ARGB8888:
   461         fprintf(stderr, "ARGB8888");
   462         break;
   463     case SDL_PIXELFORMAT_RGBA8888:
   464         fprintf(stderr, "RGBA8888");
   465         break;
   466     case SDL_PIXELFORMAT_ABGR8888:
   467         fprintf(stderr, "ABGR8888");
   468         break;
   469     case SDL_PIXELFORMAT_BGRA8888:
   470         fprintf(stderr, "BGRA8888");
   471         break;
   472     case SDL_PIXELFORMAT_ARGB2101010:
   473         fprintf(stderr, "ARGB2101010");
   474         break;
   475     case SDL_PIXELFORMAT_YV12:
   476         fprintf(stderr, "YV12");
   477         break;
   478     case SDL_PIXELFORMAT_IYUV:
   479         fprintf(stderr, "IYUV");
   480         break;
   481     case SDL_PIXELFORMAT_YUY2:
   482         fprintf(stderr, "YUY2");
   483         break;
   484     case SDL_PIXELFORMAT_UYVY:
   485         fprintf(stderr, "UYVY");
   486         break;
   487     case SDL_PIXELFORMAT_YVYU:
   488         fprintf(stderr, "YVYU");
   489         break;
   490     default:
   491         fprintf(stderr, "0x%8.8x", format);
   492         break;
   493     }
   494 }
   495 
   496 static void
   497 PrintRenderer(SDL_RendererInfo * info)
   498 {
   499     int i, count;
   500 
   501     fprintf(stderr, "  Renderer %s:\n", info->name);
   502 
   503     fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
   504     fprintf(stderr, " (");
   505     count = 0;
   506     for (i = 0; i < sizeof(info->flags) * 8; ++i) {
   507         Uint32 flag = (1 << i);
   508         if (info->flags & flag) {
   509             if (count > 0) {
   510                 fprintf(stderr, " | ");
   511             }
   512             PrintRendererFlag(flag);
   513             ++count;
   514         }
   515     }
   516     fprintf(stderr, ")\n");
   517 
   518     fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
   519     for (i = 0; i < (int) info->num_texture_formats; ++i) {
   520         if (i > 0) {
   521             fprintf(stderr, ", ");
   522         }
   523         PrintPixelFormat(info->texture_formats[i]);
   524     }
   525     fprintf(stderr, "\n");
   526 
   527     if (info->max_texture_width || info->max_texture_height) {
   528         fprintf(stderr, "    Max Texture Size: %dx%d\n",
   529                 info->max_texture_width, info->max_texture_height);
   530     }
   531 }
   532 
   533 static SDL_Surface *
   534 LoadIcon(const char *file)
   535 {
   536     SDL_Surface *icon;
   537 
   538     /* Load the icon surface */
   539     icon = SDL_LoadBMP(file);
   540     if (icon == NULL) {
   541         fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
   542         return (NULL);
   543     }
   544 
   545     if (icon->format->palette == NULL) {
   546         fprintf(stderr, "Icon must have a palette!\n");
   547         SDL_FreeSurface(icon);
   548         return (NULL);
   549     }
   550 
   551     /* Set the colorkey */
   552     SDL_SetColorKey(icon, 1, *((Uint8 *) icon->pixels));
   553 
   554     return (icon);
   555 }
   556 
   557 SDL_bool
   558 CommonInit(CommonState * state)
   559 {
   560     int i, j, m, n;
   561     SDL_DisplayMode fullscreen_mode;
   562 
   563     if (state->flags & SDL_INIT_VIDEO) {
   564         if (state->verbose & VERBOSE_VIDEO) {
   565             n = SDL_GetNumVideoDrivers();
   566             if (n == 0) {
   567                 fprintf(stderr, "No built-in video drivers\n");
   568             } else {
   569                 fprintf(stderr, "Built-in video drivers:");
   570                 for (i = 0; i < n; ++i) {
   571                     if (i > 0) {
   572                         fprintf(stderr, ",");
   573                     }
   574                     fprintf(stderr, " %s", SDL_GetVideoDriver(i));
   575                 }
   576                 fprintf(stderr, "\n");
   577             }
   578         }
   579         if (SDL_VideoInit(state->videodriver) < 0) {
   580             fprintf(stderr, "Couldn't initialize video driver: %s\n",
   581                     SDL_GetError());
   582             return SDL_FALSE;
   583         }
   584         if (state->verbose & VERBOSE_VIDEO) {
   585             fprintf(stderr, "Video driver: %s\n",
   586                     SDL_GetCurrentVideoDriver());
   587         }
   588 
   589         /* Upload GL settings */
   590         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, state->gl_red_size);
   591         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, state->gl_green_size);
   592         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, state->gl_blue_size);
   593         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, state->gl_alpha_size);
   594         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, state->gl_double_buffer);
   595         SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, state->gl_buffer_size);
   596         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, state->gl_depth_size);
   597         SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, state->gl_stencil_size);
   598         SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, state->gl_accum_red_size);
   599         SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, state->gl_accum_green_size);
   600         SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, state->gl_accum_blue_size);
   601         SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, state->gl_accum_alpha_size);
   602         SDL_GL_SetAttribute(SDL_GL_STEREO, state->gl_stereo);
   603         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, state->gl_multisamplebuffers);
   604         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, state->gl_multisamplesamples);
   605         if (state->gl_accelerated >= 0) {
   606             SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
   607                                 state->gl_accelerated);
   608         }
   609         SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, state->gl_retained_backing);
   610         if (state->gl_major_version) {
   611             SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
   612             SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
   613         }
   614 
   615         if (state->verbose & VERBOSE_MODES) {
   616             SDL_DisplayMode mode;
   617             int bpp;
   618             Uint32 Rmask, Gmask, Bmask, Amask;
   619 
   620             n = SDL_GetNumVideoDisplays();
   621             fprintf(stderr, "Number of displays: %d\n", n);
   622             for (i = 0; i < n; ++i) {
   623                 fprintf(stderr, "Display %d:\n", i);
   624 
   625                 SDL_GetDesktopDisplayMode(i, &mode);
   626                 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
   627                                            &Bmask, &Amask);
   628                 fprintf(stderr,
   629                         "  Current mode: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
   630                         mode.w, mode.h, mode.refresh_rate, bpp,
   631                         SDL_GetPixelFormatName(mode.format));
   632                 if (Rmask || Gmask || Bmask) {
   633                     fprintf(stderr, "      Red Mask   = 0x%.8x\n", Rmask);
   634                     fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
   635                     fprintf(stderr, "      Blue Mask  = 0x%.8x\n", Bmask);
   636                     if (Amask)
   637                         fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
   638                 }
   639 
   640                 /* Print available fullscreen video modes */
   641                 m = SDL_GetNumDisplayModes(i);
   642                 if (m == 0) {
   643                     fprintf(stderr, "No available fullscreen video modes\n");
   644                 } else {
   645                     fprintf(stderr, "  Fullscreen video modes:\n");
   646                     for (j = 0; j < m; ++j) {
   647                         SDL_GetDisplayMode(i, j, &mode);
   648                         SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
   649                                                    &Gmask, &Bmask, &Amask);
   650                         fprintf(stderr,
   651                                 "    Mode %d: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
   652                                 j, mode.w, mode.h, mode.refresh_rate, bpp,
   653                                 SDL_GetPixelFormatName(mode.format));
   654                         if (Rmask || Gmask || Bmask) {
   655                             fprintf(stderr, "        Red Mask   = 0x%.8x\n",
   656                                     Rmask);
   657                             fprintf(stderr, "        Green Mask = 0x%.8x\n",
   658                                     Gmask);
   659                             fprintf(stderr, "        Blue Mask  = 0x%.8x\n",
   660                                     Bmask);
   661                             if (Amask)
   662                                 fprintf(stderr,
   663                                         "        Alpha Mask = 0x%.8x\n",
   664                                         Amask);
   665                         }
   666                     }
   667                 }
   668             }
   669         }
   670 
   671         if (state->verbose & VERBOSE_RENDER) {
   672             SDL_RendererInfo info;
   673 
   674             n = SDL_GetNumRenderDrivers();
   675             if (n == 0) {
   676                 fprintf(stderr, "No built-in render drivers\n");
   677             } else {
   678                 fprintf(stderr, "Built-in render drivers:\n");
   679                 for (i = 0; i < n; ++i) {
   680                     SDL_GetRenderDriverInfo(i, &info);
   681                     PrintRenderer(&info);
   682                 }
   683             }
   684         }
   685 
   686         SDL_zero(fullscreen_mode);
   687         switch (state->depth) {
   688         case 8:
   689             fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
   690             break;
   691         case 15:
   692             fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
   693             break;
   694         case 16:
   695             fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
   696             break;
   697         case 24:
   698             fullscreen_mode.format = SDL_PIXELFORMAT_RGB24;
   699             break;
   700         default:
   701             fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
   702             break;
   703         }
   704         fullscreen_mode.refresh_rate = state->refresh_rate;
   705 
   706         state->windows =
   707             (SDL_Window **) SDL_malloc(state->num_windows *
   708                                         sizeof(*state->windows));
   709         state->renderers =
   710             (SDL_Renderer **) SDL_malloc(state->num_windows *
   711                                         sizeof(*state->renderers));
   712         if (!state->windows || !state->renderers) {
   713             fprintf(stderr, "Out of memory!\n");
   714             return SDL_FALSE;
   715         }
   716         for (i = 0; i < state->num_windows; ++i) {
   717             char title[1024];
   718 
   719             if (state->num_windows > 1) {
   720                 SDL_snprintf(title, SDL_arraysize(title), "%s %d",
   721                              state->window_title, i + 1);
   722             } else {
   723                 SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
   724             }
   725             state->windows[i] =
   726                 SDL_CreateWindow(title, state->window_x, state->window_y,
   727                                  state->window_w, state->window_h,
   728                                  state->window_flags);
   729             if (!state->windows[i]) {
   730                 fprintf(stderr, "Couldn't create window: %s\n",
   731                         SDL_GetError());
   732                 return SDL_FALSE;
   733             }
   734             SDL_GetWindowSize(state->windows[i], &state->window_w, &state->window_h);
   735 
   736             if (SDL_SetWindowDisplayMode(state->windows[i], &fullscreen_mode) < 0) {
   737                 fprintf(stderr, "Can't set up fullscreen display mode: %s\n",
   738                         SDL_GetError());
   739                 return SDL_FALSE;
   740             }
   741 
   742             if (state->window_icon) {
   743                 SDL_Surface *icon = LoadIcon(state->window_icon);
   744                 if (icon) {
   745                     SDL_SetWindowIcon(state->windows[i], icon);
   746                     SDL_FreeSurface(icon);
   747                 }
   748             }
   749 
   750             SDL_ShowWindow(state->windows[i]);
   751 
   752             state->renderers[i] = NULL;
   753 
   754             if (!state->skip_renderer
   755                 && (state->renderdriver
   756                     || !(state->window_flags & SDL_WINDOW_OPENGL))) {
   757                 m = -1;
   758                 if (state->renderdriver) {
   759                     SDL_RendererInfo info;
   760                     n = SDL_GetNumRenderDrivers();
   761                     for (j = 0; j < n; ++j) {
   762                         SDL_GetRenderDriverInfo(j, &info);
   763                         if (SDL_strcasecmp(info.name, state->renderdriver) ==
   764                             0) {
   765                             m = j;
   766                             break;
   767                         }
   768                     }
   769                     if (m == n) {
   770                         fprintf(stderr,
   771                                 "Couldn't find render driver named %s",
   772                                 state->renderdriver);
   773                         return SDL_FALSE;
   774                     }
   775                 }
   776                 state->renderers[i] = SDL_CreateRenderer(state->windows[i],
   777                                             m, state->render_flags);
   778                 if (!state->renderers[i]) {
   779                     fprintf(stderr, "Couldn't create renderer: %s\n",
   780                             SDL_GetError());
   781                     return SDL_FALSE;
   782                 }
   783                 if (state->verbose & VERBOSE_RENDER) {
   784                     SDL_RendererInfo info;
   785 
   786                     fprintf(stderr, "Current renderer:\n");
   787                     SDL_GetRendererInfo(state->renderers[i], &info);
   788                     PrintRenderer(&info);
   789                 }
   790             }
   791         }
   792     }
   793 
   794     if (state->flags & SDL_INIT_AUDIO) {
   795         if (state->verbose & VERBOSE_AUDIO) {
   796             n = SDL_GetNumAudioDrivers();
   797             if (n == 0) {
   798                 fprintf(stderr, "No built-in audio drivers\n");
   799             } else {
   800                 fprintf(stderr, "Built-in audio drivers:");
   801                 for (i = 0; i < n; ++i) {
   802                     if (i > 0) {
   803                         fprintf(stderr, ",");
   804                     }
   805                     fprintf(stderr, " %s", SDL_GetAudioDriver(i));
   806                 }
   807                 fprintf(stderr, "\n");
   808             }
   809         }
   810         if (SDL_AudioInit(state->audiodriver) < 0) {
   811             fprintf(stderr, "Couldn't initialize audio driver: %s\n",
   812                     SDL_GetError());
   813             return SDL_FALSE;
   814         }
   815         if (state->verbose & VERBOSE_VIDEO) {
   816             fprintf(stderr, "Audio driver: %s\n",
   817                     SDL_GetCurrentAudioDriver());
   818         }
   819 
   820         if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
   821             fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
   822             return SDL_FALSE;
   823         }
   824     }
   825 
   826     return SDL_TRUE;
   827 }
   828 
   829 static void
   830 PrintEvent(SDL_Event * event)
   831 {
   832     if (event->type == SDL_MOUSEMOTION) {
   833         /* Mouse motion is really spammy */
   834         //return;
   835     }
   836 
   837     fprintf(stderr, "SDL EVENT: ");
   838     switch (event->type) {
   839     case SDL_WINDOWEVENT:
   840         switch (event->window.event) {
   841         case SDL_WINDOWEVENT_SHOWN:
   842             fprintf(stderr, "Window %d shown", event->window.windowID);
   843             break;
   844         case SDL_WINDOWEVENT_HIDDEN:
   845             fprintf(stderr, "Window %d hidden", event->window.windowID);
   846             break;
   847         case SDL_WINDOWEVENT_EXPOSED:
   848             fprintf(stderr, "Window %d exposed", event->window.windowID);
   849             break;
   850         case SDL_WINDOWEVENT_MOVED:
   851             fprintf(stderr, "Window %d moved to %d,%d",
   852                     event->window.windowID, event->window.data1,
   853                     event->window.data2);
   854             break;
   855         case SDL_WINDOWEVENT_RESIZED:
   856             fprintf(stderr, "Window %d resized to %dx%d",
   857                     event->window.windowID, event->window.data1,
   858                     event->window.data2);
   859             break;
   860         case SDL_WINDOWEVENT_MINIMIZED:
   861             fprintf(stderr, "Window %d minimized", event->window.windowID);
   862             break;
   863         case SDL_WINDOWEVENT_MAXIMIZED:
   864             fprintf(stderr, "Window %d maximized", event->window.windowID);
   865             break;
   866         case SDL_WINDOWEVENT_RESTORED:
   867             fprintf(stderr, "Window %d restored", event->window.windowID);
   868             break;
   869         case SDL_WINDOWEVENT_ENTER:
   870             fprintf(stderr, "Mouse entered window %d",
   871                     event->window.windowID);
   872             break;
   873         case SDL_WINDOWEVENT_LEAVE:
   874             fprintf(stderr, "Mouse left window %d", event->window.windowID);
   875             break;
   876         case SDL_WINDOWEVENT_FOCUS_GAINED:
   877             fprintf(stderr, "Window %d gained keyboard focus",
   878                     event->window.windowID);
   879             break;
   880         case SDL_WINDOWEVENT_FOCUS_LOST:
   881             fprintf(stderr, "Window %d lost keyboard focus",
   882                     event->window.windowID);
   883             break;
   884         case SDL_WINDOWEVENT_CLOSE:
   885             fprintf(stderr, "Window %d closed", event->window.windowID);
   886             break;
   887         default:
   888             fprintf(stderr, "Window %d got unknown event %d",
   889                     event->window.windowID, event->window.event);
   890             break;
   891         }
   892         break;
   893     case SDL_KEYDOWN:
   894         fprintf(stderr,
   895                 "Keyboard: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
   896                 event->key.windowID,
   897                 event->key.keysym.scancode,
   898                 SDL_GetScancodeName(event->key.keysym.scancode),
   899                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
   900         break;
   901     case SDL_KEYUP:
   902         fprintf(stderr,
   903                 "Keyboard: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
   904                 event->key.windowID,
   905                 event->key.keysym.scancode,
   906                 SDL_GetScancodeName(event->key.keysym.scancode),
   907                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
   908         break;
   909     case SDL_TEXTINPUT:
   910         fprintf(stderr, "Keyboard: text input \"%s\" in window %d",
   911                 event->text.text, event->text.windowID);
   912         break;
   913     case SDL_MOUSEMOTION:
   914         fprintf(stderr, "Mouse: moved to %d,%d (%d,%d) in window %d",
   915                 event->motion.x, event->motion.y,
   916                 event->motion.xrel, event->motion.yrel,
   917                 event->motion.windowID);
   918         break;
   919     case SDL_MOUSEBUTTONDOWN:
   920         fprintf(stderr, "Mouse: button %d pressed at %d,%d in window %d",
   921                 event->button.button, event->button.x, event->button.y,
   922                 event->button.windowID);
   923         break;
   924     case SDL_MOUSEBUTTONUP:
   925         fprintf(stderr, "Mouse: button %d released at %d,%d in window %d",
   926                 event->button.button, event->button.x, event->button.y,
   927                 event->button.windowID);
   928         break;
   929     case SDL_MOUSEWHEEL:
   930         fprintf(stderr,
   931                 "Mouse: wheel scrolled %d in x and %d in y in window %d",
   932                 event->wheel.x, event->wheel.y, event->wheel.windowID);
   933         break;
   934     case SDL_JOYBALLMOTION:
   935         fprintf(stderr, "Joystick %d: ball %d moved by %d,%d",
   936                 event->jball.which, event->jball.ball, event->jball.xrel,
   937                 event->jball.yrel);
   938         break;
   939     case SDL_JOYHATMOTION:
   940         fprintf(stderr, "Joystick %d: hat %d moved to ", event->jhat.which,
   941                 event->jhat.hat);
   942         switch (event->jhat.value) {
   943         case SDL_HAT_CENTERED:
   944             fprintf(stderr, "CENTER");
   945             break;
   946         case SDL_HAT_UP:
   947             fprintf(stderr, "UP");
   948             break;
   949         case SDL_HAT_RIGHTUP:
   950             fprintf(stderr, "RIGHTUP");
   951             break;
   952         case SDL_HAT_RIGHT:
   953             fprintf(stderr, "RIGHT");
   954             break;
   955         case SDL_HAT_RIGHTDOWN:
   956             fprintf(stderr, "RIGHTDOWN");
   957             break;
   958         case SDL_HAT_DOWN:
   959             fprintf(stderr, "DOWN");
   960             break;
   961         case SDL_HAT_LEFTDOWN:
   962             fprintf(stderr, "LEFTDOWN");
   963             break;
   964         case SDL_HAT_LEFT:
   965             fprintf(stderr, "LEFT");
   966             break;
   967         case SDL_HAT_LEFTUP:
   968             fprintf(stderr, "LEFTUP");
   969             break;
   970         default:
   971             fprintf(stderr, "UNKNOWN");
   972             break;
   973         }
   974         break;
   975     case SDL_JOYBUTTONDOWN:
   976         fprintf(stderr, "Joystick %d: button %d pressed",
   977                 event->jbutton.which, event->jbutton.button);
   978         break;
   979     case SDL_JOYBUTTONUP:
   980         fprintf(stderr, "Joystick %d: button %d released",
   981                 event->jbutton.which, event->jbutton.button);
   982         break;
   983     case SDL_CLIPBOARDUPDATE:
   984         fprintf(stderr, "Clipboard updated");
   985         break;
   986     case SDL_QUIT:
   987         fprintf(stderr, "Quit requested");
   988         break;
   989     case SDL_USEREVENT:
   990         fprintf(stderr, "User event %d", event->user.code);
   991         break;
   992     default:
   993         fprintf(stderr, "Unknown event %d", event->type);
   994         break;
   995     }
   996     fprintf(stderr, "\n");
   997 }
   998 
   999 static void
  1000 ScreenShot(SDL_Renderer *renderer)
  1001 {
  1002     SDL_Rect viewport;
  1003     SDL_Surface *surface;
  1004 
  1005     if (!renderer) {
  1006         return;
  1007     }
  1008 
  1009     SDL_RenderGetViewport(renderer, &viewport);
  1010     surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24,
  1011 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  1012                     0x00FF0000, 0x0000FF00, 0x000000FF,
  1013 #else
  1014                     0x000000FF, 0x0000FF00, 0x00FF0000,
  1015 #endif
  1016                     0x00000000);
  1017     if (!surface) {
  1018         fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
  1019         return;
  1020     }
  1021 
  1022     if (SDL_RenderReadPixels(renderer, NULL, surface->format->format,
  1023                              surface->pixels, surface->pitch) < 0) {
  1024         fprintf(stderr, "Couldn't read screen: %s\n", SDL_GetError());
  1025         return;
  1026     }
  1027 
  1028     if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
  1029         fprintf(stderr, "Couldn't save screenshot.bmp: %s\n", SDL_GetError());
  1030         return;
  1031     }
  1032 }
  1033 
  1034 void
  1035 CommonEvent(CommonState * state, SDL_Event * event, int *done)
  1036 {
  1037     int i;
  1038 
  1039     if (state->verbose & VERBOSE_EVENT) {
  1040         PrintEvent(event);
  1041     }
  1042 
  1043     switch (event->type) {
  1044     case SDL_WINDOWEVENT:
  1045         switch (event->window.event) {
  1046         case SDL_WINDOWEVENT_CLOSE:
  1047 			{
  1048                 SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
  1049                 if (window) {
  1050 					SDL_DestroyWindow(window);
  1051 				}
  1052 			}
  1053             break;
  1054         }
  1055         break;
  1056     case SDL_KEYDOWN:
  1057         switch (event->key.keysym.sym) {
  1058             /* Add hotkeys here */
  1059         case SDLK_PRINTSCREEN: {
  1060                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1061                 if (window) {
  1062                     for (i = 0; i < state->num_windows; ++i) {
  1063                         if (window == state->windows[i]) {
  1064                             ScreenShot(state->renderers[i]);
  1065                         }
  1066                     }
  1067                 }
  1068             }
  1069             break;
  1070         case SDLK_c:
  1071             if (event->key.keysym.mod & KMOD_CTRL) {
  1072                 /* Ctrl-C copy awesome text! */
  1073                 SDL_SetClipboardText("SDL rocks!\nYou know it!");
  1074                 printf("Copied text to clipboard\n");
  1075             }
  1076             break;
  1077         case SDLK_v:
  1078             if (event->key.keysym.mod & KMOD_CTRL) {
  1079                 /* Ctrl-V paste awesome text! */
  1080                 char *text = SDL_GetClipboardText();
  1081                 if (*text) {
  1082                     printf("Clipboard: %s\n", text);
  1083                 } else {
  1084                     printf("Clipboard is empty\n");
  1085                 }
  1086                 SDL_free(text);
  1087             }
  1088             break;
  1089         case SDLK_g:
  1090             if (event->key.keysym.mod & KMOD_CTRL) {
  1091                 /* Ctrl-G toggle grab */
  1092                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1093                 if (window) {
  1094                     SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window));
  1095                 }
  1096             }
  1097             break;
  1098         case SDLK_m:
  1099             if (event->key.keysym.mod & KMOD_CTRL) {
  1100                 /* Ctrl-M maximize */
  1101                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1102                 if (window) {
  1103                     Uint32 flags = SDL_GetWindowFlags(window);
  1104                     if (flags & SDL_WINDOW_MAXIMIZED) {
  1105                         SDL_RestoreWindow(window);
  1106                     } else {
  1107                         SDL_MaximizeWindow(window);
  1108                     }
  1109                 }
  1110             }
  1111             break;
  1112         case SDLK_r:
  1113             if (event->key.keysym.mod & KMOD_CTRL) {
  1114                 /* Ctrl-R toggle mouse relative mode */
  1115                 SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode());
  1116             }
  1117             break;
  1118         case SDLK_z:
  1119             if (event->key.keysym.mod & KMOD_CTRL) {
  1120                 /* Ctrl-Z minimize */
  1121                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1122                 if (window) {
  1123                     SDL_MinimizeWindow(window);
  1124                 }
  1125             }
  1126             break;
  1127         case SDLK_RETURN:
  1128             if (event->key.keysym.mod & KMOD_CTRL) {
  1129                 /* Ctrl-Enter toggle fullscreen */
  1130                 SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
  1131                 if (window) {
  1132                     Uint32 flags = SDL_GetWindowFlags(window);
  1133                     if (flags & SDL_WINDOW_FULLSCREEN) {
  1134                         SDL_SetWindowFullscreen(window, SDL_FALSE);
  1135                     } else {
  1136                         SDL_SetWindowFullscreen(window, SDL_TRUE);
  1137                     }
  1138                 }
  1139             }
  1140             break;
  1141         case SDLK_ESCAPE:
  1142             *done = 1;
  1143             break;
  1144         default:
  1145             break;
  1146         }
  1147         break;
  1148     case SDL_QUIT:
  1149         *done = 1;
  1150         break;
  1151     }
  1152 }
  1153 
  1154 void
  1155 CommonQuit(CommonState * state)
  1156 {
  1157     int i;
  1158 
  1159     if (state->windows) {
  1160         SDL_free(state->windows);
  1161     }
  1162     if (state->renderers) {
  1163         for (i = 0; i < state->num_windows; ++i) {
  1164             if (state->renderers[i]) {
  1165                 SDL_DestroyRenderer(state->renderers[i]);
  1166             }
  1167         }
  1168         SDL_free(state->renderers);
  1169     }
  1170     if (state->flags & SDL_INIT_VIDEO) {
  1171         SDL_VideoQuit();
  1172     }
  1173     if (state->flags & SDL_INIT_AUDIO) {
  1174         SDL_AudioQuit();
  1175     }
  1176     SDL_free(state);
  1177 }
  1178 
  1179 /* vi: set ts=4 sw=4 expandtab: */