test/testrendercopyex.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 05 Oct 2013 19:09:03 -0700
changeset 7787 e6f3e8fc96ea
parent 7678 286c42d7c5ed
child 8149 681eb46b8ac4
permissions -rw-r--r--
Fixed bug 2132 - Tests may use invalid SDL_window pointers when windows are closed

norfanin

Some of the tests keep using the pointers of a destroyed SDL_Window when the common event handling handled the close event. The event handler itself does not NULL the pointer after the destruction.

The attached patch adds a loop in the handler that will assign NULL to the destroyed window. It also adds checks to some of the tests so they skip those windows by checking for NULL.
gabomdq@6320
     1
/*
slouken@7517
     2
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
gabomdq@6320
     3
gabomdq@6320
     4
  This software is provided 'as-is', without any express or implied
gabomdq@6320
     5
  warranty.  In no event will the authors be held liable for any damages
gabomdq@6320
     6
  arising from the use of this software.
gabomdq@6320
     7
gabomdq@6320
     8
  Permission is granted to anyone to use this software for any purpose,
gabomdq@6320
     9
  including commercial applications, and to alter it and redistribute it
gabomdq@6320
    10
  freely.
gabomdq@6320
    11
*/
gabomdq@6320
    12
/* Simple program:  Move N sprites around on the screen as fast as possible */
gabomdq@6320
    13
gabomdq@6320
    14
#include <stdlib.h>
gabomdq@6320
    15
#include <stdio.h>
gabomdq@6320
    16
#include <time.h>
gabomdq@6320
    17
slouken@6785
    18
#include "SDL_test_common.h"
gabomdq@6320
    19
gabomdq@6320
    20
slouken@6785
    21
static SDLTest_CommonState *state;
gabomdq@6320
    22
gabomdq@6320
    23
typedef struct {
gabomdq@6320
    24
    SDL_Window *window;
gabomdq@6320
    25
    SDL_Renderer *renderer;
gabomdq@6320
    26
    SDL_Texture *background;
gabomdq@6320
    27
    SDL_Texture *sprite;
gabomdq@6320
    28
    SDL_Rect sprite_rect;
gabomdq@6320
    29
    int scale_direction;
gabomdq@6320
    30
} DrawState;
gabomdq@6320
    31
gabomdq@6320
    32
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
gabomdq@6320
    33
static void
gabomdq@6320
    34
quit(int rc)
gabomdq@6320
    35
{
slouken@6785
    36
    SDLTest_CommonQuit(state);
gabomdq@6320
    37
    exit(rc);
gabomdq@6320
    38
}
gabomdq@6320
    39
gabomdq@6320
    40
SDL_Texture *
gabomdq@6320
    41
LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
gabomdq@6320
    42
{
gabomdq@6320
    43
    SDL_Surface *temp;
gabomdq@6320
    44
    SDL_Texture *texture;
gabomdq@6320
    45
gabomdq@6320
    46
    /* Load the sprite image */
gabomdq@6320
    47
    temp = SDL_LoadBMP(file);
gabomdq@6320
    48
    if (temp == NULL) {
aschiffler@7639
    49
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
gabomdq@6320
    50
        return NULL;
gabomdq@6320
    51
    }
gabomdq@6320
    52
gabomdq@6320
    53
    /* Set transparent pixel as the pixel at (0,0) */
gabomdq@6320
    54
    if (transparent) {
gabomdq@6320
    55
        if (temp->format->palette) {
gabomdq@6320
    56
            SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
gabomdq@6320
    57
        } else {
gabomdq@6320
    58
            switch (temp->format->BitsPerPixel) {
gabomdq@6320
    59
            case 15:
gabomdq@6320
    60
                SDL_SetColorKey(temp, SDL_TRUE,
gabomdq@6320
    61
                                (*(Uint16 *) temp->pixels) & 0x00007FFF);
gabomdq@6320
    62
                break;
gabomdq@6320
    63
            case 16:
gabomdq@6320
    64
                SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
gabomdq@6320
    65
                break;
gabomdq@6320
    66
            case 24:
gabomdq@6320
    67
                SDL_SetColorKey(temp, SDL_TRUE,
gabomdq@6320
    68
                                (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
gabomdq@6320
    69
                break;
gabomdq@6320
    70
            case 32:
gabomdq@6320
    71
                SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
gabomdq@6320
    72
                break;
gabomdq@6320
    73
            }
gabomdq@6320
    74
        }
gabomdq@6320
    75
    }
gabomdq@6320
    76
gabomdq@6320
    77
    /* Create textures from the image */
gabomdq@6320
    78
    texture = SDL_CreateTextureFromSurface(renderer, temp);
gabomdq@6320
    79
    if (!texture) {
aschiffler@7639
    80
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
gabomdq@6320
    81
        SDL_FreeSurface(temp);
gabomdq@6320
    82
        return NULL;
gabomdq@6320
    83
    }
gabomdq@6320
    84
    SDL_FreeSurface(temp);
gabomdq@6320
    85
gabomdq@6320
    86
    /* We're ready to roll. :) */
gabomdq@6320
    87
    return texture;
gabomdq@6320
    88
}
gabomdq@6320
    89
gabomdq@6320
    90
void
gabomdq@6320
    91
Draw(DrawState *s)
gabomdq@6320
    92
{
gabomdq@6320
    93
    SDL_Rect viewport;
gabomdq@6320
    94
    SDL_Texture *target;
gabomdq@6320
    95
    SDL_Point *center=NULL;
gabomdq@6320
    96
    SDL_Point origin = {0,0};
gabomdq@6320
    97
gabomdq@6320
    98
    SDL_RenderGetViewport(s->renderer, &viewport);
gabomdq@6320
    99
gabomdq@6320
   100
    target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
gabomdq@6320
   101
    SDL_SetRenderTarget(s->renderer, target);
gabomdq@6320
   102
gabomdq@6320
   103
    /* Draw the background */
gabomdq@6320
   104
    SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
gabomdq@6320
   105
gabomdq@6320
   106
    /* Scale and draw the sprite */
gabomdq@6320
   107
    s->sprite_rect.w += s->scale_direction;
gabomdq@6320
   108
    s->sprite_rect.h += s->scale_direction;
gabomdq@6320
   109
    if (s->scale_direction > 0) {
gabomdq@6320
   110
        center = &origin;
gabomdq@6320
   111
        if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
gabomdq@6320
   112
            s->scale_direction = -1;
gabomdq@6320
   113
        }
gabomdq@6320
   114
    } else {
gabomdq@6320
   115
        if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
gabomdq@6320
   116
            s->scale_direction = 1;
gabomdq@6320
   117
        }
gabomdq@6320
   118
    }
gabomdq@6320
   119
    s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
gabomdq@6320
   120
    s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
gabomdq@6320
   121
gabomdq@6320
   122
    SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, s->scale_direction);
gabomdq@6320
   123
gabomdq@6320
   124
    SDL_SetRenderTarget(s->renderer, NULL);
gabomdq@6320
   125
    SDL_RenderCopy(s->renderer, target, NULL, NULL);
gabomdq@6320
   126
    SDL_DestroyTexture(target);
gabomdq@6320
   127
gabomdq@6320
   128
    /* Update the screen! */
gabomdq@6320
   129
    SDL_RenderPresent(s->renderer);
gabomdq@7678
   130
    /* SDL_Delay(10); */
gabomdq@6320
   131
}
gabomdq@6320
   132
gabomdq@6320
   133
int
gabomdq@6320
   134
main(int argc, char *argv[])
gabomdq@6320
   135
{
gabomdq@6320
   136
    DrawState *drawstates;
gabomdq@6320
   137
    int i, done;
gabomdq@6320
   138
    SDL_Event event;
gabomdq@6320
   139
    int frames;
gabomdq@6320
   140
    Uint32 then, now;
gabomdq@6320
   141
aschiffler@7639
   142
	/* Enable standard application logging */
aschiffler@7639
   143
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
aschiffler@7639
   144
gabomdq@6320
   145
    /* Initialize test framework */
slouken@6785
   146
    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
gabomdq@6320
   147
    if (!state) {
gabomdq@6320
   148
        return 1;
gabomdq@6320
   149
    }
gabomdq@6320
   150
    for (i = 1; i < argc;) {
gabomdq@6320
   151
        int consumed;
gabomdq@6320
   152
slouken@6785
   153
        consumed = SDLTest_CommonArg(state, i);
gabomdq@6320
   154
        if (consumed == 0) {
aschiffler@7639
   155
            SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state));
gabomdq@6320
   156
            return 1;
gabomdq@6320
   157
        }
gabomdq@6320
   158
        i += consumed;
gabomdq@6320
   159
    }
slouken@6785
   160
    if (!SDLTest_CommonInit(state)) {
gabomdq@6320
   161
        quit(2);
gabomdq@6320
   162
    }
gabomdq@6320
   163
gabomdq@6320
   164
    drawstates = SDL_stack_alloc(DrawState, state->num_windows);
gabomdq@6320
   165
    for (i = 0; i < state->num_windows; ++i) {
gabomdq@6320
   166
        DrawState *drawstate = &drawstates[i];
gabomdq@6320
   167
gabomdq@6320
   168
        drawstate->window = state->windows[i];
gabomdq@6320
   169
        drawstate->renderer = state->renderers[i];
gabomdq@6320
   170
        drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
gabomdq@6320
   171
        drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
gabomdq@6320
   172
        if (!drawstate->sprite || !drawstate->background) {
gabomdq@6320
   173
            quit(2);
gabomdq@6320
   174
        }
gabomdq@6320
   175
        SDL_QueryTexture(drawstate->sprite, NULL, NULL,
gabomdq@6320
   176
                         &drawstate->sprite_rect.w, &drawstate->sprite_rect.h);
gabomdq@6320
   177
        drawstate->scale_direction = 1;
gabomdq@6320
   178
    }
gabomdq@6320
   179
gabomdq@6320
   180
    /* Main render loop */
gabomdq@6320
   181
    frames = 0;
gabomdq@6320
   182
    then = SDL_GetTicks();
gabomdq@6320
   183
    done = 0;
gabomdq@6320
   184
    while (!done) {
gabomdq@6320
   185
        /* Check for events */
gabomdq@6320
   186
        ++frames;
gabomdq@6320
   187
        while (SDL_PollEvent(&event)) {
slouken@6785
   188
            SDLTest_CommonEvent(state, &event, &done);
gabomdq@6320
   189
        }
gabomdq@6320
   190
        for (i = 0; i < state->num_windows; ++i) {
slouken@7787
   191
            if (state->windows[i] == NULL)
slouken@7787
   192
                continue;
gabomdq@6320
   193
            Draw(&drawstates[i]);
gabomdq@6320
   194
        }
gabomdq@6320
   195
    }
gabomdq@6320
   196
gabomdq@6320
   197
    /* Print out some timing information */
gabomdq@6320
   198
    now = SDL_GetTicks();
gabomdq@6320
   199
    if (now > then) {
gabomdq@6320
   200
        double fps = ((double) frames * 1000) / (now - then);
aschiffler@7639
   201
        SDL_Log("%2.2f frames per second\n", fps);
gabomdq@6320
   202
    }
gabomdq@6320
   203
gabomdq@6320
   204
    SDL_stack_free(drawstates);
gabomdq@6320
   205
gabomdq@6320
   206
    quit(0);
gabomdq@6320
   207
    return 0;
gabomdq@6320
   208
}
gabomdq@6320
   209
gabomdq@6320
   210
/* vi: set ts=4 sw=4 expandtab: */