sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

testrendertarget.c (9757B)


      1 /*
      2   Copyright (C) 1997-2020 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: */