1 /*
2 Copyright (C) 1997-2016 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 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <math.h>
16
17 #include "SDL_test_common.h"
18
19 #ifdef __MACOS__
20 #define HAVE_OPENGL
21 #endif
22
23 #ifdef HAVE_OPENGL
24
25 #include "SDL_opengl.h"
26
27 typedef struct GL_Context
28 {
29 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
30 #include "../src/render/opengl/SDL_glfuncs.h"
31 #undef SDL_PROC
32 } GL_Context;
33
34
35 /* Undefine this if you want a flat cube instead of a rainbow cube */
36 #define SHADED_CUBE
37
38 static SDLTest_CommonState *state;
39 static SDL_GLContext context;
40 static GL_Context ctx;
41
LoadContext(GL_Context * data)42 static int LoadContext(GL_Context * data)
43 {
44 #if SDL_VIDEO_DRIVER_UIKIT
45 #define __SDL_NOGETPROCADDR__
46 #elif SDL_VIDEO_DRIVER_ANDROID
47 #define __SDL_NOGETPROCADDR__
48 #elif SDL_VIDEO_DRIVER_PANDORA
49 #define __SDL_NOGETPROCADDR__
50 #endif
51
52 #if defined __SDL_NOGETPROCADDR__
53 #define SDL_PROC(ret,func,params) data->func=func;
54 #else
55 #define SDL_PROC(ret,func,params) \
56 do { \
57 data->func = SDL_GL_GetProcAddress(#func); \
58 if ( ! data->func ) { \
59 return SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
60 } \
61 } while ( 0 );
62 #endif /* __SDL_NOGETPROCADDR__ */
63
64 #include "../src/render/opengl/SDL_glfuncs.h"
65 #undef SDL_PROC
66 return 0;
67 }
68
69
70 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
71 static void
quit(int rc)72 quit(int rc)
73 {
74 if (context) {
75 /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
76 SDL_GL_DeleteContext(context);
77 }
78 SDLTest_CommonQuit(state);
79 exit(rc);
80 }
81
82 static void
Render()83 Render()
84 {
85 static float color[8][3] = {
86 {1.0, 1.0, 0.0},
87 {1.0, 0.0, 0.0},
88 {0.0, 0.0, 0.0},
89 {0.0, 1.0, 0.0},
90 {0.0, 1.0, 1.0},
91 {1.0, 1.0, 1.0},
92 {1.0, 0.0, 1.0},
93 {0.0, 0.0, 1.0}
94 };
95 static float cube[8][3] = {
96 {0.5, 0.5, -0.5},
97 {0.5, -0.5, -0.5},
98 {-0.5, -0.5, -0.5},
99 {-0.5, 0.5, -0.5},
100 {-0.5, 0.5, 0.5},
101 {0.5, 0.5, 0.5},
102 {0.5, -0.5, 0.5},
103 {-0.5, -0.5, 0.5}
104 };
105
106 /* Do our drawing, too. */
107 ctx.glClearColor(0.0, 0.0, 0.0, 1.0);
108 ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
109
110 ctx.glBegin(GL_QUADS);
111
112 #ifdef SHADED_CUBE
113 ctx.glColor3fv(color[0]);
114 ctx.glVertex3fv(cube[0]);
115 ctx.glColor3fv(color[1]);
116 ctx.glVertex3fv(cube[1]);
117 ctx.glColor3fv(color[2]);
118 ctx.glVertex3fv(cube[2]);
119 ctx.glColor3fv(color[3]);
120 ctx.glVertex3fv(cube[3]);
121
122 ctx.glColor3fv(color[3]);
123 ctx.glVertex3fv(cube[3]);
124 ctx.glColor3fv(color[4]);
125 ctx.glVertex3fv(cube[4]);
126 ctx.glColor3fv(color[7]);
127 ctx.glVertex3fv(cube[7]);
128 ctx.glColor3fv(color[2]);
129 ctx.glVertex3fv(cube[2]);
130
131 ctx.glColor3fv(color[0]);
132 ctx.glVertex3fv(cube[0]);
133 ctx.glColor3fv(color[5]);
134 ctx.glVertex3fv(cube[5]);
135 ctx.glColor3fv(color[6]);
136 ctx.glVertex3fv(cube[6]);
137 ctx.glColor3fv(color[1]);
138 ctx.glVertex3fv(cube[1]);
139
140 ctx.glColor3fv(color[5]);
141 ctx.glVertex3fv(cube[5]);
142 ctx.glColor3fv(color[4]);
143 ctx.glVertex3fv(cube[4]);
144 ctx.glColor3fv(color[7]);
145 ctx.glVertex3fv(cube[7]);
146 ctx.glColor3fv(color[6]);
147 ctx.glVertex3fv(cube[6]);
148
149 ctx.glColor3fv(color[5]);
150 ctx.glVertex3fv(cube[5]);
151 ctx.glColor3fv(color[0]);
152 ctx.glVertex3fv(cube[0]);
153 ctx.glColor3fv(color[3]);
154 ctx.glVertex3fv(cube[3]);
155 ctx.glColor3fv(color[4]);
156 ctx.glVertex3fv(cube[4]);
157
158 ctx.glColor3fv(color[6]);
159 ctx.glVertex3fv(cube[6]);
160 ctx.glColor3fv(color[1]);
161 ctx.glVertex3fv(cube[1]);
162 ctx.glColor3fv(color[2]);
163 ctx.glVertex3fv(cube[2]);
164 ctx.glColor3fv(color[7]);
165 ctx.glVertex3fv(cube[7]);
166 #else /* flat cube */
167 ctx.glColor3f(1.0, 0.0, 0.0);
168 ctx.glVertex3fv(cube[0]);
169 ctx.glVertex3fv(cube[1]);
170 ctx.glVertex3fv(cube[2]);
171 ctx.glVertex3fv(cube[3]);
172
173 ctx.glColor3f(0.0, 1.0, 0.0);
174 ctx.glVertex3fv(cube[3]);
175 ctx.glVertex3fv(cube[4]);
176 ctx.glVertex3fv(cube[7]);
177 ctx.glVertex3fv(cube[2]);
178
179 ctx.glColor3f(0.0, 0.0, 1.0);
180 ctx.glVertex3fv(cube[0]);
181 ctx.glVertex3fv(cube[5]);
182 ctx.glVertex3fv(cube[6]);
183 ctx.glVertex3fv(cube[1]);
184
185 ctx.glColor3f(0.0, 1.0, 1.0);
186 ctx.glVertex3fv(cube[5]);
187 ctx.glVertex3fv(cube[4]);
188 ctx.glVertex3fv(cube[7]);
189 ctx.glVertex3fv(cube[6]);
190
191 ctx.glColor3f(1.0, 1.0, 0.0);
192 ctx.glVertex3fv(cube[5]);
193 ctx.glVertex3fv(cube[0]);
194 ctx.glVertex3fv(cube[3]);
195 ctx.glVertex3fv(cube[4]);
196
197 ctx.glColor3f(1.0, 0.0, 1.0);
198 ctx.glVertex3fv(cube[6]);
199 ctx.glVertex3fv(cube[1]);
200 ctx.glVertex3fv(cube[2]);
201 ctx.glVertex3fv(cube[7]);
202 #endif /* SHADED_CUBE */
203
204 ctx.glEnd();
205
206 ctx.glMatrixMode(GL_MODELVIEW);
207 ctx.glRotatef(5.0, 1.0, 1.0, 1.0);
208 }
209
210 int
main(int argc,char * argv[])211 main(int argc, char *argv[])
212 {
213 int fsaa, accel;
214 int value;
215 int i, done;
216 SDL_DisplayMode mode;
217 SDL_Event event;
218 Uint32 then, now, frames;
219 int status;
220 int dw, dh;
221
222 /* Enable standard application logging */
223 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
224
225 /* Initialize parameters */
226 fsaa = 0;
227 accel = -1;
228
229 /* Initialize test framework */
230 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
231 if (!state) {
232 return 1;
233 }
234 for (i = 1; i < argc;) {
235 int consumed;
236
237 consumed = SDLTest_CommonArg(state, i);
238 if (consumed == 0) {
239 if (SDL_strcasecmp(argv[i], "--fsaa") == 0 && i+1 < argc) {
240 fsaa = atoi(argv[i+1]);
241 consumed = 2;
242 } else if (SDL_strcasecmp(argv[i], "--accel") == 0 && i+1 < argc) {
243 accel = atoi(argv[i+1]);
244 consumed = 2;
245 } else {
246 consumed = -1;
247 }
248 }
249 if (consumed < 0) {
250 SDL_Log("Usage: %s %s [--fsaa n] [--accel n]\n", argv[0],
251 SDLTest_CommonUsage(state));
252 quit(1);
253 }
254 i += consumed;
255 }
256
257 /* Set OpenGL parameters */
258 state->window_flags |= SDL_WINDOW_OPENGL;
259 state->gl_red_size = 5;
260 state->gl_green_size = 5;
261 state->gl_blue_size = 5;
262 state->gl_depth_size = 16;
263 state->gl_double_buffer = 1;
264 if (fsaa) {
265 state->gl_multisamplebuffers = 1;
266 state->gl_multisamplesamples = fsaa;
267 }
268 if (accel >= 0) {
269 state->gl_accelerated = accel;
270 }
271
272 if (!SDLTest_CommonInit(state)) {
273 quit(2);
274 }
275
276 /* Create OpenGL context */
277 context = SDL_GL_CreateContext(state->windows[0]);
278 if (!context) {
279 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError());
280 quit(2);
281 }
282
283 /* Important: call this *after* creating the context */
284 if (LoadContext(&ctx) < 0) {
285 SDL_Log("Could not load GL functions\n");
286 quit(2);
287 return 0;
288 }
289
290 if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) {
291 /* try late-swap-tearing first. If not supported, try normal vsync. */
292 if (SDL_GL_SetSwapInterval(-1) == -1) {
293 SDL_GL_SetSwapInterval(1);
294 }
295 } else {
296 SDL_GL_SetSwapInterval(0); /* disable vsync. */
297 }
298
299 SDL_GetCurrentDisplayMode(0, &mode);
300 SDL_Log("Screen BPP : %d\n", SDL_BITSPERPIXEL(mode.format));
301 SDL_Log("Swap Interval : %d\n", SDL_GL_GetSwapInterval());
302 SDL_GetWindowSize(state->windows[0], &dw, &dh);
303 SDL_Log("Window Size : %d,%d\n", dw, dh);
304 SDL_GL_GetDrawableSize(state->windows[0], &dw, &dh);
305 SDL_Log("Draw Size : %d,%d\n", dw, dh);
306 SDL_Log("\n");
307 SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR));
308 SDL_Log("Renderer : %s\n", ctx.glGetString(GL_RENDERER));
309 SDL_Log("Version : %s\n", ctx.glGetString(GL_VERSION));
310 SDL_Log("Extensions : %s\n", ctx.glGetString(GL_EXTENSIONS));
311 SDL_Log("\n");
312
313 status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);
314 if (!status) {
315 SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value);
316 } else {
317 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError());
318 }
319 status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value);
320 if (!status) {
321 SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value);
322 } else {
323 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError());
324 }
325 status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value);
326 if (!status) {
327 SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value);
328 } else {
329 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError());
330 }
331 status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value);
332 if (!status) {
333 SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value);
334 } else {
335 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError());
336 }
337 if (fsaa) {
338 status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value);
339 if (!status) {
340 SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value);
341 } else {
342 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n",
343 SDL_GetError());
344 }
345 status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value);
346 if (!status) {
347 SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa,
348 value);
349 } else {
350 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n",
351 SDL_GetError());
352 }
353 }
354 if (accel >= 0) {
355 status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value);
356 if (!status) {
357 SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested %d, got %d\n", accel,
358 value);
359 } else {
360 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n",
361 SDL_GetError());
362 }
363 }
364
365 /* Set rendering settings */
366 ctx.glMatrixMode(GL_PROJECTION);
367 ctx.glLoadIdentity();
368 ctx.glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0);
369 ctx.glMatrixMode(GL_MODELVIEW);
370 ctx.glLoadIdentity();
371 ctx.glEnable(GL_DEPTH_TEST);
372 ctx.glDepthFunc(GL_LESS);
373 ctx.glShadeModel(GL_SMOOTH);
374
375 /* Main render loop */
376 frames = 0;
377 then = SDL_GetTicks();
378 done = 0;
379 while (!done) {
380 /* Check for events */
381 ++frames;
382 while (SDL_PollEvent(&event)) {
383 SDLTest_CommonEvent(state, &event, &done);
384 }
385 for (i = 0; i < state->num_windows; ++i) {
386 int w, h;
387 if (state->windows[i] == NULL)
388 continue;
389 SDL_GL_MakeCurrent(state->windows[i], context);
390 SDL_GL_GetDrawableSize(state->windows[i], &w, &h);
391 ctx.glViewport(0, 0, w, h);
392 Render();
393 SDL_GL_SwapWindow(state->windows[i]);
394 }
395 }
396
397 /* Print out some timing information */
398 now = SDL_GetTicks();
399 if (now > then) {
400 SDL_Log("%2.2f frames per second\n",
401 ((double) frames * 1000) / (now - then));
402 }
403 quit(0);
404 return 0;
405 }
406
407 #else /* HAVE_OPENGL */
408
409 int
main(int argc,char * argv[])410 main(int argc, char *argv[])
411 {
412 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No OpenGL support on this system\n");
413 return 1;
414 }
415
416 #endif /* HAVE_OPENGL */
417