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