test/testsprite2.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 05 Oct 2018 17:06:05 -0700
changeset 12299 d8683d6ff2f8
parent 11811 5d94cb6b24d3
child 12210 9f9dbcce30b3
permissions -rw-r--r--
Fixed bug 4296 - kmsdrm video driver leaks 1 bo in KMSDRM_GLES_SetupCrtc()

Icenowy Zheng

One front buffer is locked in GLES_SetupCrtc() and overrides the next_bo just locked in KMSDRM_GLES_SwapWindow, then the next_bo gets lost and is not released even when quitting the video.

It may leads to problems with GLES drivers that doesn't clean up GBM correctly if there's any bo left (e.g. the Mali Utgard r6p2 blob). In the case of Mali Utgard r6p2 blob, the DRM device file is still hold by the blob, and if you try to SDL_Quit to let another program to run (this is done by EmulationStation), the new program will fail to open DRM device.
     1 /*
     2   Copyright (C) 1997-2018 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 /* Simple program:  Move N sprites around on the screen as fast as possible */
    13 
    14 #include <stdlib.h>
    15 #include <stdio.h>
    16 #include <time.h>
    17 
    18 #ifdef __EMSCRIPTEN__
    19 #include <emscripten/emscripten.h>
    20 #endif
    21 
    22 #include "SDL_test.h"
    23 #include "SDL_test_common.h"
    24 
    25 #define NUM_SPRITES    100
    26 #define MAX_SPEED     1
    27 
    28 static SDLTest_CommonState *state;
    29 static int num_sprites;
    30 static SDL_Texture **sprites;
    31 static SDL_bool cycle_color;
    32 static SDL_bool cycle_alpha;
    33 static int cycle_direction = 1;
    34 static int current_alpha = 0;
    35 static int current_color = 0;
    36 static SDL_Rect *positions;
    37 static SDL_Rect *velocities;
    38 static int sprite_w, sprite_h;
    39 static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
    40 
    41 /* Number of iterations to move sprites - used for visual tests. */
    42 /* -1: infinite random moves (default); >=0: enables N deterministic moves */
    43 static int iterations = -1;
    44 
    45 int done;
    46 
    47 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    48 static void
    49 quit(int rc)
    50 {
    51     SDL_free(sprites);
    52     SDL_free(positions);
    53     SDL_free(velocities);
    54     SDLTest_CommonQuit(state);
    55     exit(rc);
    56 }
    57 
    58 int
    59 LoadSprite(const char *file)
    60 {
    61     int i;
    62     SDL_Surface *temp;
    63 
    64     /* Load the sprite image */
    65     temp = SDL_LoadBMP(file);
    66     if (temp == NULL) {
    67         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
    68         return (-1);
    69     }
    70     sprite_w = temp->w;
    71     sprite_h = temp->h;
    72 
    73     /* Set transparent pixel as the pixel at (0,0) */
    74     if (temp->format->palette) {
    75         SDL_SetColorKey(temp, 1, *(Uint8 *) temp->pixels);
    76     } else {
    77         switch (temp->format->BitsPerPixel) {
    78         case 15:
    79             SDL_SetColorKey(temp, 1, (*(Uint16 *) temp->pixels) & 0x00007FFF);
    80             break;
    81         case 16:
    82             SDL_SetColorKey(temp, 1, *(Uint16 *) temp->pixels);
    83             break;
    84         case 24:
    85             SDL_SetColorKey(temp, 1, (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
    86             break;
    87         case 32:
    88             SDL_SetColorKey(temp, 1, *(Uint32 *) temp->pixels);
    89             break;
    90         }
    91     }
    92 
    93     /* Create textures from the image */
    94     for (i = 0; i < state->num_windows; ++i) {
    95         SDL_Renderer *renderer = state->renderers[i];
    96         sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
    97         if (!sprites[i]) {
    98             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
    99             SDL_FreeSurface(temp);
   100             return (-1);
   101         }
   102         if (SDL_SetTextureBlendMode(sprites[i], blendMode) < 0) {
   103             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set blend mode: %s\n", SDL_GetError());
   104             SDL_FreeSurface(temp);
   105             SDL_DestroyTexture(sprites[i]);
   106             return (-1);
   107         }
   108     }
   109     SDL_FreeSurface(temp);
   110 
   111     /* We're ready to roll. :) */
   112     return (0);
   113 }
   114 
   115 void
   116 MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
   117 {
   118     int i;
   119     SDL_Rect viewport, temp;
   120     SDL_Rect *position, *velocity;
   121 
   122     /* Query the sizes */
   123     SDL_RenderGetViewport(renderer, &viewport);
   124 
   125     /* Cycle the color and alpha, if desired */
   126     if (cycle_color) {
   127         current_color += cycle_direction;
   128         if (current_color < 0) {
   129             current_color = 0;
   130             cycle_direction = -cycle_direction;
   131         }
   132         if (current_color > 255) {
   133             current_color = 255;
   134             cycle_direction = -cycle_direction;
   135         }
   136         SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
   137                                (Uint8) current_color);
   138     }
   139     if (cycle_alpha) {
   140         current_alpha += cycle_direction;
   141         if (current_alpha < 0) {
   142             current_alpha = 0;
   143             cycle_direction = -cycle_direction;
   144         }
   145         if (current_alpha > 255) {
   146             current_alpha = 255;
   147             cycle_direction = -cycle_direction;
   148         }
   149         SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
   150     }
   151 
   152     /* Draw a gray background */
   153     SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   154     SDL_RenderClear(renderer);
   155 
   156     /* Test points */
   157     SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
   158     SDL_RenderDrawPoint(renderer, 0, 0);
   159     SDL_RenderDrawPoint(renderer, viewport.w-1, 0);
   160     SDL_RenderDrawPoint(renderer, 0, viewport.h-1);
   161     SDL_RenderDrawPoint(renderer, viewport.w-1, viewport.h-1);
   162 
   163     /* Test horizontal and vertical lines */
   164     SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
   165     SDL_RenderDrawLine(renderer, 1, 0, viewport.w-2, 0);
   166     SDL_RenderDrawLine(renderer, 1, viewport.h-1, viewport.w-2, viewport.h-1);
   167     SDL_RenderDrawLine(renderer, 0, 1, 0, viewport.h-2);
   168     SDL_RenderDrawLine(renderer, viewport.w-1, 1, viewport.w-1, viewport.h-2);
   169 
   170     /* Test fill and copy */
   171     SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
   172     temp.x = 1;
   173     temp.y = 1;
   174     temp.w = sprite_w;
   175     temp.h = sprite_h;
   176     SDL_RenderFillRect(renderer, &temp);
   177     SDL_RenderCopy(renderer, sprite, NULL, &temp);
   178     temp.x = viewport.w-sprite_w-1;
   179     temp.y = 1;
   180     temp.w = sprite_w;
   181     temp.h = sprite_h;
   182     SDL_RenderFillRect(renderer, &temp);
   183     SDL_RenderCopy(renderer, sprite, NULL, &temp);
   184     temp.x = 1;
   185     temp.y = viewport.h-sprite_h-1;
   186     temp.w = sprite_w;
   187     temp.h = sprite_h;
   188     SDL_RenderFillRect(renderer, &temp);
   189     SDL_RenderCopy(renderer, sprite, NULL, &temp);
   190     temp.x = viewport.w-sprite_w-1;
   191     temp.y = viewport.h-sprite_h-1;
   192     temp.w = sprite_w;
   193     temp.h = sprite_h;
   194     SDL_RenderFillRect(renderer, &temp);
   195     SDL_RenderCopy(renderer, sprite, NULL, &temp);
   196 
   197     /* Test diagonal lines */
   198     SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
   199     SDL_RenderDrawLine(renderer, sprite_w, sprite_h,
   200                        viewport.w-sprite_w-2, viewport.h-sprite_h-2);
   201     SDL_RenderDrawLine(renderer, viewport.w-sprite_w-2, sprite_h,
   202                        sprite_w, viewport.h-sprite_h-2);
   203 
   204     /* Conditionally move the sprites, bounce at the wall */
   205     if (iterations == -1 || iterations > 0) {
   206         for (i = 0; i < num_sprites; ++i) {
   207             position = &positions[i];
   208             velocity = &velocities[i];
   209             position->x += velocity->x;
   210             if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) {
   211                 velocity->x = -velocity->x;
   212                 position->x += velocity->x;
   213             }
   214             position->y += velocity->y;
   215             if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) {
   216                 velocity->y = -velocity->y;
   217                 position->y += velocity->y;
   218             }
   219 
   220         }
   221         
   222         /* Countdown sprite-move iterations and disable color changes at iteration end - used for visual tests. */
   223         if (iterations > 0) {
   224             iterations--;
   225             if (iterations == 0) {
   226                 cycle_alpha = SDL_FALSE;
   227                 cycle_color = SDL_FALSE;
   228             }
   229         }
   230     }
   231 
   232     /* Draw sprites */
   233     for (i = 0; i < num_sprites; ++i) {
   234         position = &positions[i];
   235 
   236         /* Blit the sprite onto the screen */
   237         SDL_RenderCopy(renderer, sprite, NULL, position);
   238     }
   239 
   240     /* Update the screen! */
   241     SDL_RenderPresent(renderer);
   242 }
   243 
   244 void
   245 loop()
   246 {
   247     int i;
   248     SDL_Event event;
   249 
   250     /* Check for events */
   251     while (SDL_PollEvent(&event)) {
   252         SDLTest_CommonEvent(state, &event, &done);
   253     }
   254     for (i = 0; i < state->num_windows; ++i) {
   255         if (state->windows[i] == NULL)
   256             continue;
   257         MoveSprites(state->renderers[i], sprites[i]);
   258     }
   259 #ifdef __EMSCRIPTEN__
   260     if (done) {
   261         emscripten_cancel_main_loop();
   262     }
   263 #endif
   264 }
   265 
   266 int
   267 main(int argc, char *argv[])
   268 {
   269     int i;
   270     Uint32 then, now, frames;
   271     Uint64 seed;
   272     const char *icon = "icon.bmp";
   273 
   274     /* Initialize parameters */
   275     num_sprites = NUM_SPRITES;
   276 
   277     /* Initialize test framework */
   278     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   279     if (!state) {
   280         return 1;
   281     }
   282 
   283     for (i = 1; i < argc;) {
   284         int consumed;
   285 
   286         consumed = SDLTest_CommonArg(state, i);
   287         if (consumed == 0) {
   288             consumed = -1;
   289             if (SDL_strcasecmp(argv[i], "--blend") == 0) {
   290                 if (argv[i + 1]) {
   291                     if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
   292                         blendMode = SDL_BLENDMODE_NONE;
   293                         consumed = 2;
   294                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
   295                         blendMode = SDL_BLENDMODE_BLEND;
   296                         consumed = 2;
   297                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
   298                         blendMode = SDL_BLENDMODE_ADD;
   299                         consumed = 2;
   300                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
   301                         blendMode = SDL_BLENDMODE_MOD;
   302                         consumed = 2;
   303                     } else if (SDL_strcasecmp(argv[i + 1], "sub") == 0) {
   304                         blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
   305                         consumed = 2;
   306                     }
   307                 }
   308             } else if (SDL_strcasecmp(argv[i], "--iterations") == 0) {
   309                 if (argv[i + 1]) {
   310                     iterations = SDL_atoi(argv[i + 1]);
   311                     if (iterations < -1) iterations = -1;
   312                     consumed = 2;
   313                 }
   314             } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
   315                 cycle_color = SDL_TRUE;
   316                 consumed = 1;
   317             } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
   318                 cycle_alpha = SDL_TRUE;
   319                 consumed = 1;
   320             } else if (SDL_isdigit(*argv[i])) {
   321                 num_sprites = SDL_atoi(argv[i]);
   322                 consumed = 1;
   323             } else if (argv[i][0] != '-') {
   324                 icon = argv[i];
   325                 consumed = 1;
   326             }
   327         }
   328         if (consumed < 0) {
   329             SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha] [--iterations N] [num_sprites] [icon.bmp]\n",
   330                     argv[0], SDLTest_CommonUsage(state));
   331             quit(1);
   332         }
   333         i += consumed;
   334     }
   335     if (!SDLTest_CommonInit(state)) {
   336         quit(2);
   337     }
   338 
   339     /* Create the windows, initialize the renderers, and load the textures */
   340     sprites =
   341         (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites));
   342     if (!sprites) {
   343         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
   344         quit(2);
   345     }
   346     for (i = 0; i < state->num_windows; ++i) {
   347         SDL_Renderer *renderer = state->renderers[i];
   348         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   349         SDL_RenderClear(renderer);
   350     }
   351     if (LoadSprite(icon) < 0) {
   352         quit(2);
   353     }
   354 
   355     /* Allocate memory for the sprite info */
   356     positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   357     velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   358     if (!positions || !velocities) {
   359         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
   360         quit(2);
   361     }
   362 
   363     /* Position sprites and set their velocities using the fuzzer */ 
   364     if (iterations >= 0) {
   365         /* Deterministic seed - used for visual tests */
   366         seed = (Uint64)iterations;
   367     } else {
   368         /* Pseudo-random seed generated from the time */
   369         seed = (Uint64)time(NULL);
   370     }
   371     SDLTest_FuzzerInit(seed);
   372     for (i = 0; i < num_sprites; ++i) {
   373         positions[i].x = SDLTest_RandomIntegerInRange(0, state->window_w - sprite_w);
   374         positions[i].y = SDLTest_RandomIntegerInRange(0, state->window_h - sprite_h);
   375         positions[i].w = sprite_w;
   376         positions[i].h = sprite_h;
   377         velocities[i].x = 0;
   378         velocities[i].y = 0;
   379         while (!velocities[i].x && !velocities[i].y) {
   380             velocities[i].x = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
   381             velocities[i].y = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
   382         }
   383     }
   384 
   385     /* Main render loop */
   386     frames = 0;
   387     then = SDL_GetTicks();
   388     done = 0;
   389 
   390 #ifdef __EMSCRIPTEN__
   391     emscripten_set_main_loop(loop, 0, 1);
   392 #else
   393     while (!done) {
   394         ++frames;
   395         loop();
   396     }
   397 #endif
   398 
   399     /* Print out some timing information */
   400     now = SDL_GetTicks();
   401     if (now > then) {
   402         double fps = ((double) frames * 1000) / (now - then);
   403         SDL_Log("%2.2f frames per second\n", fps);
   404     }
   405     quit(0);
   406     return 0;
   407 }
   408 
   409 /* vi: set ts=4 sw=4 expandtab: */