test/testgl2.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 11553 b89649d1a7a5
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
     1 /*
     2   Copyright (C) 1997-2017 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 
   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
   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 */