test/testrendertarget.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 09 Dec 2019 16:52:11 -0800
changeset 13324 b46a94bb2ab0
parent 12758 3c6a6dad3487
permissions -rw-r--r--
Fixed rumble after Xbox controller initialization
When we initialize the controller it has an internal rumble sequence number, and if our rumble sequence number doesn't match that, rumble won't happen. To fix that we cycle through the range of sequence numbers, and at some point we'll match up with the controller's sequence number and it'll roll forward until it matches our next rumble sequence number.
     1 /*
     2   Copyright (C) 1997-2019 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_common.h"
    23 
    24 
    25 static SDLTest_CommonState *state;
    26 
    27 typedef struct {
    28     SDL_Window *window;
    29     SDL_Renderer *renderer;
    30     SDL_Texture *background;
    31     SDL_Texture *sprite;
    32     SDL_Rect sprite_rect;
    33     int scale_direction;
    34 } DrawState;
    35 
    36 DrawState *drawstates;
    37 int done;
    38 SDL_bool test_composite = SDL_FALSE;
    39 
    40 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    41 static void
    42 quit(int rc)
    43 {
    44     SDLTest_CommonQuit(state);
    45     exit(rc);
    46 }
    47 
    48 SDL_Texture *
    49 LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
    50 {
    51     SDL_Surface *temp;
    52     SDL_Texture *texture;
    53 
    54     /* Load the sprite image */
    55     temp = SDL_LoadBMP(file);
    56     if (temp == NULL) {
    57         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
    58         return NULL;
    59     }
    60 
    61     /* Set transparent pixel as the pixel at (0,0) */
    62     if (transparent) {
    63         if (temp->format->palette) {
    64             SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
    65         } else {
    66             switch (temp->format->BitsPerPixel) {
    67             case 15:
    68                 SDL_SetColorKey(temp, SDL_TRUE,
    69                                 (*(Uint16 *) temp->pixels) & 0x00007FFF);
    70                 break;
    71             case 16:
    72                 SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
    73                 break;
    74             case 24:
    75                 SDL_SetColorKey(temp, SDL_TRUE,
    76                                 (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
    77                 break;
    78             case 32:
    79                 SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
    80                 break;
    81             }
    82         }
    83     }
    84 
    85     /* Create textures from the image */
    86     texture = SDL_CreateTextureFromSurface(renderer, temp);
    87     if (!texture) {
    88         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
    89         SDL_FreeSurface(temp);
    90         return NULL;
    91     }
    92     SDL_FreeSurface(temp);
    93 
    94     /* We're ready to roll. :) */
    95     return texture;
    96 }
    97 
    98 SDL_bool
    99 DrawComposite(DrawState *s)
   100 {
   101     SDL_Rect viewport, R;
   102     SDL_Texture *target;
   103 
   104     static SDL_bool blend_tested = SDL_FALSE;
   105     if (!blend_tested) {
   106         SDL_Texture *A, *B;
   107         Uint32 P;
   108 
   109         A = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 1, 1);
   110         SDL_SetTextureBlendMode(A, SDL_BLENDMODE_BLEND);
   111 
   112         B = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 1, 1);
   113         SDL_SetTextureBlendMode(B, SDL_BLENDMODE_BLEND);
   114 
   115         SDL_SetRenderTarget(s->renderer, A);
   116         SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x80);
   117         SDL_RenderFillRect(s->renderer, NULL);
   118 
   119         SDL_SetRenderTarget(s->renderer, B);
   120         SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x00);
   121         SDL_RenderFillRect(s->renderer, NULL);
   122         SDL_RenderCopy(s->renderer, A, NULL, NULL);
   123         SDL_RenderReadPixels(s->renderer, NULL, SDL_PIXELFORMAT_ARGB8888, &P, sizeof(P));
   124 
   125         SDL_Log("Blended pixel: 0x%8.8X\n", P);
   126 
   127         SDL_DestroyTexture(A);
   128         SDL_DestroyTexture(B);
   129         blend_tested = SDL_TRUE;
   130     }
   131 
   132     SDL_RenderGetViewport(s->renderer, &viewport);
   133 
   134     target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
   135     SDL_SetTextureBlendMode(target, SDL_BLENDMODE_BLEND);
   136     SDL_SetRenderTarget(s->renderer, target);
   137 
   138     /* Draw the background.
   139        This is solid black so when the sprite is copied to it, any per-pixel alpha will be blended through.
   140      */
   141     SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x00);
   142     SDL_RenderFillRect(s->renderer, NULL);
   143 
   144     /* Scale and draw the sprite */
   145     s->sprite_rect.w += s->scale_direction;
   146     s->sprite_rect.h += s->scale_direction;
   147     if (s->scale_direction > 0) {
   148         if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
   149             s->scale_direction = -1;
   150         }
   151     } else {
   152         if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
   153             s->scale_direction = 1;
   154         }
   155     }
   156     s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
   157     s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
   158 
   159     SDL_RenderCopy(s->renderer, s->sprite, NULL, &s->sprite_rect);
   160 
   161     SDL_SetRenderTarget(s->renderer, NULL);
   162     SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
   163 
   164     SDL_SetRenderDrawBlendMode(s->renderer, SDL_BLENDMODE_BLEND);
   165     SDL_SetRenderDrawColor(s->renderer, 0xff, 0x00, 0x00, 0x80);
   166     R.x = 0;
   167     R.y = 0;
   168     R.w = 100;
   169     R.h = 100;
   170     SDL_RenderFillRect(s->renderer, &R);
   171     SDL_SetRenderDrawBlendMode(s->renderer, SDL_BLENDMODE_NONE);
   172 
   173     SDL_RenderCopy(s->renderer, target, NULL, NULL);
   174     SDL_DestroyTexture(target);
   175 
   176     /* Update the screen! */
   177     SDL_RenderPresent(s->renderer);
   178     return SDL_TRUE;
   179 }
   180 
   181 SDL_bool
   182 Draw(DrawState *s)
   183 {
   184     SDL_Rect viewport;
   185     SDL_Texture *target;
   186 
   187     SDL_RenderGetViewport(s->renderer, &viewport);
   188 
   189     target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
   190     if (!target) {
   191         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create render target texture: %s\n", SDL_GetError());
   192         return SDL_FALSE;
   193     }
   194     SDL_SetRenderTarget(s->renderer, target);
   195 
   196     /* Draw the background */
   197     SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
   198 
   199     /* Scale and draw the sprite */
   200     s->sprite_rect.w += s->scale_direction;
   201     s->sprite_rect.h += s->scale_direction;
   202     if (s->scale_direction > 0) {
   203         if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
   204             s->scale_direction = -1;
   205         }
   206     } else {
   207         if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
   208             s->scale_direction = 1;
   209         }
   210     }
   211     s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
   212     s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
   213 
   214     SDL_RenderCopy(s->renderer, s->sprite, NULL, &s->sprite_rect);
   215 
   216     SDL_SetRenderTarget(s->renderer, NULL);
   217     SDL_RenderCopy(s->renderer, target, NULL, NULL);
   218     SDL_DestroyTexture(target);
   219 
   220     /* Update the screen! */
   221     SDL_RenderPresent(s->renderer);
   222     return SDL_TRUE;
   223 }
   224 
   225 void
   226 loop()
   227 {
   228     int i;
   229     SDL_Event event;
   230 
   231     /* Check for events */
   232     while (SDL_PollEvent(&event)) {
   233         SDLTest_CommonEvent(state, &event, &done);
   234     }
   235     for (i = 0; i < state->num_windows; ++i) {
   236         if (state->windows[i] == NULL)
   237             continue;
   238         if (test_composite) {
   239             if (!DrawComposite(&drawstates[i])) done = 1;
   240         } else {
   241             if (!Draw(&drawstates[i])) done = 1;
   242         }
   243     }
   244 #ifdef __EMSCRIPTEN__
   245     if (done) {
   246         emscripten_cancel_main_loop();
   247     }
   248 #endif
   249 }
   250 
   251 int
   252 main(int argc, char *argv[])
   253 {
   254     int i;
   255     int frames;
   256     Uint32 then, now;
   257 
   258     /* Enable standard application logging */
   259     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   260 
   261     /* Initialize test framework */
   262     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   263     if (!state) {
   264         return 1;
   265     }
   266     for (i = 1; i < argc;) {
   267         int consumed;
   268 
   269         consumed = SDLTest_CommonArg(state, i);
   270         if (consumed == 0) {
   271             consumed = -1;
   272             if (SDL_strcasecmp(argv[i], "--composite") == 0) {
   273                 test_composite = SDL_TRUE;
   274                 consumed = 1;
   275             }
   276         }
   277         if (consumed < 0) {
   278             static const char *options[] = { "[--composite]", NULL };
   279             SDLTest_CommonLogUsage(state, argv[0], options);
   280             quit(1);
   281         }
   282         i += consumed;
   283     }
   284     if (!SDLTest_CommonInit(state)) {
   285         quit(2);
   286     }
   287 
   288     drawstates = SDL_stack_alloc(DrawState, state->num_windows);
   289     for (i = 0; i < state->num_windows; ++i) {
   290         DrawState *drawstate = &drawstates[i];
   291 
   292         drawstate->window = state->windows[i];
   293         drawstate->renderer = state->renderers[i];
   294         if (test_composite) {
   295             drawstate->sprite = LoadTexture(drawstate->renderer, "icon-alpha.bmp", SDL_TRUE);
   296         } else {
   297             drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
   298         }
   299         drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
   300         if (!drawstate->sprite || !drawstate->background) {
   301             quit(2);
   302         }
   303         SDL_QueryTexture(drawstate->sprite, NULL, NULL,
   304                          &drawstate->sprite_rect.w, &drawstate->sprite_rect.h);
   305         drawstate->scale_direction = 1;
   306     }
   307 
   308     /* Main render loop */
   309     frames = 0;
   310     then = SDL_GetTicks();
   311     done = 0;
   312 
   313 #ifdef __EMSCRIPTEN__
   314     emscripten_set_main_loop(loop, 0, 1);
   315 #else
   316     while (!done) {
   317         ++frames;
   318         loop();
   319     }
   320 #endif
   321 
   322     /* Print out some timing information */
   323     now = SDL_GetTicks();
   324     if (now > then) {
   325         double fps = ((double) frames * 1000) / (now - then);
   326         SDL_Log("%2.2f frames per second\n", fps);
   327     }
   328 
   329     SDL_stack_free(drawstates);
   330 
   331     quit(0);
   332     return 0;
   333 }
   334 
   335 /* vi: set ts=4 sw=4 expandtab: */