testgl2.c (12691B)
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 #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 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", #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 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 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 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 int swap_interval = 0; 222 223 /* Enable standard application logging */ 224 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 225 226 /* Initialize parameters */ 227 fsaa = 0; 228 accel = -1; 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 if (SDL_strcasecmp(argv[i], "--fsaa") == 0 && i+1 < argc) { 241 fsaa = atoi(argv[i+1]); 242 consumed = 2; 243 } else if (SDL_strcasecmp(argv[i], "--accel") == 0 && i+1 < argc) { 244 accel = atoi(argv[i+1]); 245 consumed = 2; 246 } else { 247 consumed = -1; 248 } 249 } 250 if (consumed < 0) { 251 static const char *options[] = { "[--fsaa n]", "[--accel n]", NULL }; 252 SDLTest_CommonLogUsage(state, argv[0], options); 253 quit(1); 254 } 255 i += consumed; 256 } 257 258 /* Set OpenGL parameters */ 259 state->window_flags |= SDL_WINDOW_OPENGL; 260 state->gl_red_size = 5; 261 state->gl_green_size = 5; 262 state->gl_blue_size = 5; 263 state->gl_depth_size = 16; 264 state->gl_double_buffer = 1; 265 if (fsaa) { 266 state->gl_multisamplebuffers = 1; 267 state->gl_multisamplesamples = fsaa; 268 } 269 if (accel >= 0) { 270 state->gl_accelerated = accel; 271 } 272 273 if (!SDLTest_CommonInit(state)) { 274 quit(2); 275 } 276 277 /* Create OpenGL context */ 278 context = SDL_GL_CreateContext(state->windows[0]); 279 if (!context) { 280 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError()); 281 quit(2); 282 } 283 284 /* Important: call this *after* creating the context */ 285 if (LoadContext(&ctx) < 0) { 286 SDL_Log("Could not load GL functions\n"); 287 quit(2); 288 return 0; 289 } 290 291 if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) { 292 /* try late-swap-tearing first. If not supported, try normal vsync. */ 293 if (SDL_GL_SetSwapInterval(-1) == 0) { 294 swap_interval = -1; 295 } else { 296 SDL_GL_SetSwapInterval(1); 297 swap_interval = 1; 298 } 299 } else { 300 SDL_GL_SetSwapInterval(0); /* disable vsync. */ 301 swap_interval = 0; 302 } 303 304 SDL_GetCurrentDisplayMode(0, &mode); 305 SDL_Log("Screen BPP : %d\n", SDL_BITSPERPIXEL(mode.format)); 306 SDL_Log("Swap Interval : %d\n", SDL_GL_GetSwapInterval()); 307 SDL_GetWindowSize(state->windows[0], &dw, &dh); 308 SDL_Log("Window Size : %d,%d\n", dw, dh); 309 SDL_GL_GetDrawableSize(state->windows[0], &dw, &dh); 310 SDL_Log("Draw Size : %d,%d\n", dw, dh); 311 SDL_Log("\n"); 312 SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR)); 313 SDL_Log("Renderer : %s\n", ctx.glGetString(GL_RENDERER)); 314 SDL_Log("Version : %s\n", ctx.glGetString(GL_VERSION)); 315 SDL_Log("Extensions : %s\n", ctx.glGetString(GL_EXTENSIONS)); 316 SDL_Log("\n"); 317 318 status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); 319 if (!status) { 320 SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); 321 } else { 322 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError()); 323 } 324 status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); 325 if (!status) { 326 SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); 327 } else { 328 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError()); 329 } 330 status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); 331 if (!status) { 332 SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); 333 } else { 334 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError()); 335 } 336 status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); 337 if (!status) { 338 SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", 16, value); 339 } else { 340 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError()); 341 } 342 if (fsaa) { 343 status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); 344 if (!status) { 345 SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); 346 } else { 347 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n", 348 SDL_GetError()); 349 } 350 status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); 351 if (!status) { 352 SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, 353 value); 354 } else { 355 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n", 356 SDL_GetError()); 357 } 358 } 359 if (accel >= 0) { 360 status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); 361 if (!status) { 362 SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested %d, got %d\n", accel, 363 value); 364 } else { 365 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n", 366 SDL_GetError()); 367 } 368 } 369 370 /* Set rendering settings */ 371 ctx.glMatrixMode(GL_PROJECTION); 372 ctx.glLoadIdentity(); 373 ctx.glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0); 374 ctx.glMatrixMode(GL_MODELVIEW); 375 ctx.glLoadIdentity(); 376 ctx.glEnable(GL_DEPTH_TEST); 377 ctx.glDepthFunc(GL_LESS); 378 ctx.glShadeModel(GL_SMOOTH); 379 380 /* Main render loop */ 381 frames = 0; 382 then = SDL_GetTicks(); 383 done = 0; 384 while (!done) { 385 SDL_bool update_swap_interval = SDL_FALSE; 386 387 /* Check for events */ 388 ++frames; 389 while (SDL_PollEvent(&event)) { 390 SDLTest_CommonEvent(state, &event, &done); 391 if (event.type == SDL_KEYDOWN) { 392 if (event.key.keysym.sym == SDLK_o) { 393 swap_interval--; 394 update_swap_interval = SDL_TRUE; 395 } else if (event.key.keysym.sym == SDLK_p) { 396 swap_interval++; 397 update_swap_interval = SDL_TRUE; 398 } 399 } 400 } 401 402 if (update_swap_interval) { 403 SDL_Log("Swap interval to be set to %d\n", swap_interval); 404 } 405 406 for (i = 0; i < state->num_windows; ++i) { 407 int w, h; 408 if (state->windows[i] == NULL) 409 continue; 410 SDL_GL_MakeCurrent(state->windows[i], context); 411 if (update_swap_interval) { 412 SDL_GL_SetSwapInterval(swap_interval); 413 } 414 SDL_GL_GetDrawableSize(state->windows[i], &w, &h); 415 ctx.glViewport(0, 0, w, h); 416 Render(); 417 SDL_GL_SwapWindow(state->windows[i]); 418 } 419 } 420 421 /* Print out some timing information */ 422 now = SDL_GetTicks(); 423 if (now > then) { 424 SDL_Log("%2.2f frames per second\n", 425 ((double) frames * 1000) / (now - then)); 426 } 427 quit(0); 428 return 0; 429 } 430 431 #else /* HAVE_OPENGL */ 432 433 int 434 main(int argc, char *argv[]) 435 { 436 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No OpenGL support on this system\n"); 437 return 1; 438 } 439 440 #endif /* HAVE_OPENGL */