test/testrendertarget.c
author David Ludwig <dludwig@pobox.com>
Wed, 25 Dec 2013 21:39:48 -0500
changeset 8563 c0e68f3b6bbb
parent 7787 e6f3e8fc96ea
child 8149 681eb46b8ac4
permissions -rw-r--r--
WinRT: compiled the d3d11 renderer's shaders into SDL itself

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