test/testgles2.c
author Alex Baines <alex@abaines.me.uk>
Tue, 19 Aug 2014 23:31:50 +0100
changeset 9097 56d712662a82
parent 8841 b7f41b4a7929
child 9278 8900afb78a19
permissions -rw-r--r--
Add a SDL_IM_INTERNAL_EDITING event to make IMs like iBus render editing text in its own UI instead of sending TEXTEDITING events.
This is useful for applications that handle TEXTINPUT events but not TEXTEDITING events.
     1 /*
     2   Copyright (r) 1997-2014 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 #if defined(__IPHONEOS__) || defined(__ANDROID__) || defined(__NACL__)
    20 #define HAVE_OPENGLES2
    21 #endif
    22 
    23 #ifdef HAVE_OPENGLES2
    24 
    25 #include "SDL_opengles2.h"
    26 
    27 typedef struct GLES2_Context
    28 {
    29 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
    30 #include "../src/render/opengles2/SDL_gles2funcs.h"
    31 #undef SDL_PROC
    32 } GLES2_Context;
    33 
    34 
    35 static SDLTest_CommonState *state;
    36 static SDL_GLContext *context = NULL;
    37 static int depth = 16;
    38 static GLES2_Context ctx;
    39 
    40 static int LoadContext(GLES2_Context * data)
    41 {
    42 #if SDL_VIDEO_DRIVER_UIKIT
    43 #define __SDL_NOGETPROCADDR__
    44 #elif SDL_VIDEO_DRIVER_ANDROID
    45 #define __SDL_NOGETPROCADDR__
    46 #elif SDL_VIDEO_DRIVER_PANDORA
    47 #define __SDL_NOGETPROCADDR__
    48 #endif
    49 
    50 #if defined __SDL_NOGETPROCADDR__
    51 #define SDL_PROC(ret,func,params) data->func=func;
    52 #else
    53 #define SDL_PROC(ret,func,params) \
    54     do { \
    55         data->func = SDL_GL_GetProcAddress(#func); \
    56         if ( ! data->func ) { \
    57             return SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
    58         } \
    59     } while ( 0 );
    60 #endif /* _SDL_NOGETPROCADDR_ */
    61 
    62 #include "../src/render/opengles2/SDL_gles2funcs.h"
    63 #undef SDL_PROC
    64     return 0;
    65 }
    66 
    67 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    68 static void
    69 quit(int rc)
    70 {
    71     int i;
    72 
    73     if (context != NULL) {
    74         for (i = 0; i < state->num_windows; i++) {
    75             if (context[i]) {
    76                 SDL_GL_DeleteContext(context[i]);
    77             }
    78         }
    79 
    80         SDL_free(context);
    81     }
    82 
    83     SDLTest_CommonQuit(state);
    84     exit(rc);
    85 }
    86 
    87 #define GL_CHECK(x) \
    88         x; \
    89         { \
    90           GLenum glError = ctx.glGetError(); \
    91           if(glError != GL_NO_ERROR) { \
    92             SDL_Log("glGetError() = %i (0x%.8x) at line %i\n", glError, glError, __LINE__); \
    93             quit(1); \
    94           } \
    95         }
    96 
    97 /* 
    98  * Simulates desktop's glRotatef. The matrix is returned in column-major 
    99  * order. 
   100  */
   101 static void
   102 rotate_matrix(float angle, float x, float y, float z, float *r)
   103 {
   104     float radians, c, s, c1, u[3], length;
   105     int i, j;
   106 
   107     radians = (float)(angle * M_PI) / 180.0f;
   108 
   109     c = SDL_cosf(radians);
   110     s = SDL_sinf(radians);
   111 
   112     c1 = 1.0f - SDL_cosf(radians);
   113 
   114     length = (float)SDL_sqrt(x * x + y * y + z * z);
   115 
   116     u[0] = x / length;
   117     u[1] = y / length;
   118     u[2] = z / length;
   119 
   120     for (i = 0; i < 16; i++) {
   121         r[i] = 0.0;
   122     }
   123 
   124     r[15] = 1.0;
   125 
   126     for (i = 0; i < 3; i++) {
   127         r[i * 4 + (i + 1) % 3] = u[(i + 2) % 3] * s;
   128         r[i * 4 + (i + 2) % 3] = -u[(i + 1) % 3] * s;
   129     }
   130 
   131     for (i = 0; i < 3; i++) {
   132         for (j = 0; j < 3; j++) {
   133             r[i * 4 + j] += c1 * u[i] * u[j] + (i == j ? c : 0.0f);
   134         }
   135     }
   136 }
   137 
   138 /* 
   139  * Simulates gluPerspectiveMatrix 
   140  */
   141 static void 
   142 perspective_matrix(float fovy, float aspect, float znear, float zfar, float *r)
   143 {
   144     int i;
   145     float f;
   146 
   147     f = 1.0f/SDL_tanf(fovy * 0.5f);
   148 
   149     for (i = 0; i < 16; i++) {
   150         r[i] = 0.0;
   151     }
   152 
   153     r[0] = f / aspect;
   154     r[5] = f;
   155     r[10] = (znear + zfar) / (znear - zfar);
   156     r[11] = -1.0f;
   157     r[14] = (2.0f * znear * zfar) / (znear - zfar);
   158     r[15] = 0.0f;
   159 }
   160 
   161 /* 
   162  * Multiplies lhs by rhs and writes out to r. All matrices are 4x4 and column
   163  * major. In-place multiplication is supported.
   164  */
   165 static void
   166 multiply_matrix(float *lhs, float *rhs, float *r)
   167 {
   168 	int i, j, k;
   169     float tmp[16];
   170 
   171     for (i = 0; i < 4; i++) {
   172         for (j = 0; j < 4; j++) {
   173             tmp[j * 4 + i] = 0.0;
   174 
   175             for (k = 0; k < 4; k++) {
   176                 tmp[j * 4 + i] += lhs[k * 4 + i] * rhs[j * 4 + k];
   177             }
   178         }
   179     }
   180 
   181     for (i = 0; i < 16; i++) {
   182         r[i] = tmp[i];
   183     }
   184 }
   185 
   186 /* 
   187  * Create shader, load in source, compile, dump debug as necessary.
   188  *
   189  * shader: Pointer to return created shader ID.
   190  * source: Passed-in shader source code.
   191  * shader_type: Passed to GL, e.g. GL_VERTEX_SHADER.
   192  */
   193 void 
   194 process_shader(GLuint *shader, const char * source, GLint shader_type)
   195 {
   196     GLint status = GL_FALSE;
   197     const char *shaders[1] = { NULL };
   198     char buffer[1024];
   199     GLsizei length;
   200 
   201     /* Create shader and load into GL. */
   202     *shader = GL_CHECK(ctx.glCreateShader(shader_type));
   203 
   204     shaders[0] = source;
   205 
   206     GL_CHECK(ctx.glShaderSource(*shader, 1, shaders, NULL));
   207 
   208     /* Clean up shader source. */
   209     shaders[0] = NULL;
   210 
   211     /* Try compiling the shader. */
   212     GL_CHECK(ctx.glCompileShader(*shader));
   213     GL_CHECK(ctx.glGetShaderiv(*shader, GL_COMPILE_STATUS, &status));
   214 
   215     /* Dump debug info (source and log) if compilation failed. */
   216     if(status != GL_TRUE) {
   217         ctx.glGetProgramInfoLog(*shader, sizeof(buffer), &length, &buffer[0]);
   218         buffer[length] = '\0';
   219         SDL_Log("Shader compilation failed: %s", buffer);fflush(stderr);
   220         quit(-1);
   221     }
   222 }
   223 
   224 /* 3D data. Vertex range -0.5..0.5 in all axes.
   225 * Z -0.5 is near, 0.5 is far. */
   226 const float _vertices[] =
   227 {
   228     /* Front face. */
   229     /* Bottom left */
   230     -0.5,  0.5, -0.5,
   231     0.5, -0.5, -0.5,
   232     -0.5, -0.5, -0.5,
   233     /* Top right */
   234     -0.5,  0.5, -0.5,
   235     0.5,  0.5, -0.5,
   236     0.5, -0.5, -0.5,
   237     /* Left face */
   238     /* Bottom left */
   239     -0.5,  0.5,  0.5,
   240     -0.5, -0.5, -0.5,
   241     -0.5, -0.5,  0.5,
   242     /* Top right */
   243     -0.5,  0.5,  0.5,
   244     -0.5,  0.5, -0.5,
   245     -0.5, -0.5, -0.5,
   246     /* Top face */
   247     /* Bottom left */
   248     -0.5,  0.5,  0.5,
   249     0.5,  0.5, -0.5,
   250     -0.5,  0.5, -0.5,
   251     /* Top right */
   252     -0.5,  0.5,  0.5,
   253     0.5,  0.5,  0.5,
   254     0.5,  0.5, -0.5,
   255     /* Right face */
   256     /* Bottom left */
   257     0.5,  0.5, -0.5,
   258     0.5, -0.5,  0.5,
   259     0.5, -0.5, -0.5,
   260     /* Top right */
   261     0.5,  0.5, -0.5,
   262     0.5,  0.5,  0.5,
   263     0.5, -0.5,  0.5,
   264     /* Back face */
   265     /* Bottom left */
   266     0.5,  0.5,  0.5,
   267     -0.5, -0.5,  0.5,
   268     0.5, -0.5,  0.5,
   269     /* Top right */
   270     0.5,  0.5,  0.5,
   271     -0.5,  0.5,  0.5,
   272     -0.5, -0.5,  0.5,
   273     /* Bottom face */
   274     /* Bottom left */
   275     -0.5, -0.5, -0.5,
   276     0.5, -0.5,  0.5,
   277     -0.5, -0.5,  0.5,
   278     /* Top right */
   279     -0.5, -0.5, -0.5,
   280     0.5, -0.5, -0.5,
   281     0.5, -0.5,  0.5,
   282 };
   283 
   284 const float _colors[] =
   285 {
   286     /* Front face */
   287     /* Bottom left */
   288     1.0, 0.0, 0.0, /* red */
   289     0.0, 0.0, 1.0, /* blue */
   290     0.0, 1.0, 0.0, /* green */
   291     /* Top right */
   292     1.0, 0.0, 0.0, /* red */
   293     1.0, 1.0, 0.0, /* yellow */
   294     0.0, 0.0, 1.0, /* blue */
   295     /* Left face */
   296     /* Bottom left */
   297     1.0, 1.0, 1.0, /* white */
   298     0.0, 1.0, 0.0, /* green */
   299     0.0, 1.0, 1.0, /* cyan */
   300     /* Top right */
   301     1.0, 1.0, 1.0, /* white */
   302     1.0, 0.0, 0.0, /* red */
   303     0.0, 1.0, 0.0, /* green */
   304     /* Top face */
   305     /* Bottom left */
   306     1.0, 1.0, 1.0, /* white */
   307     1.0, 1.0, 0.0, /* yellow */
   308     1.0, 0.0, 0.0, /* red */
   309     /* Top right */
   310     1.0, 1.0, 1.0, /* white */
   311     0.0, 0.0, 0.0, /* black */
   312     1.0, 1.0, 0.0, /* yellow */
   313     /* Right face */
   314     /* Bottom left */
   315     1.0, 1.0, 0.0, /* yellow */
   316     1.0, 0.0, 1.0, /* magenta */
   317     0.0, 0.0, 1.0, /* blue */
   318     /* Top right */
   319     1.0, 1.0, 0.0, /* yellow */
   320     0.0, 0.0, 0.0, /* black */
   321     1.0, 0.0, 1.0, /* magenta */
   322     /* Back face */
   323     /* Bottom left */
   324     0.0, 0.0, 0.0, /* black */
   325     0.0, 1.0, 1.0, /* cyan */
   326     1.0, 0.0, 1.0, /* magenta */
   327     /* Top right */
   328     0.0, 0.0, 0.0, /* black */
   329     1.0, 1.0, 1.0, /* white */
   330     0.0, 1.0, 1.0, /* cyan */
   331     /* Bottom face */
   332     /* Bottom left */
   333     0.0, 1.0, 0.0, /* green */
   334     1.0, 0.0, 1.0, /* magenta */
   335     0.0, 1.0, 1.0, /* cyan */
   336     /* Top right */
   337     0.0, 1.0, 0.0, /* green */
   338     0.0, 0.0, 1.0, /* blue */
   339     1.0, 0.0, 1.0, /* magenta */
   340 };
   341 
   342 const char* _shader_vert_src = 
   343 " attribute vec4 av4position; "
   344 " attribute vec3 av3color; "
   345 " uniform mat4 mvp; "
   346 " varying vec3 vv3color; "
   347 " void main() { "
   348 "    vv3color = av3color; "
   349 "    gl_Position = mvp * av4position; "
   350 " } ";
   351 
   352 const char* _shader_frag_src = 
   353 " precision lowp float; "
   354 " varying vec3 vv3color; "
   355 " void main() { "
   356 "    gl_FragColor = vec4(vv3color, 1.0); "
   357 " } ";
   358 
   359 typedef struct shader_data
   360 {
   361     GLuint shader_program, shader_frag, shader_vert;
   362 
   363     GLint attr_position;
   364     GLint attr_color, attr_mvp;
   365 
   366     int angle_x, angle_y, angle_z;
   367 
   368 } shader_data;
   369 
   370 static void
   371 Render(unsigned int width, unsigned int height, shader_data* data)
   372 {
   373     float matrix_rotate[16], matrix_modelview[16], matrix_perspective[16], matrix_mvp[16];
   374 
   375     /* 
   376     * Do some rotation with Euler angles. It is not a fixed axis as
   377     * quaterions would be, but the effect is cool. 
   378     */
   379     rotate_matrix((float)data->angle_x, 1.0f, 0.0f, 0.0f, matrix_modelview);
   380     rotate_matrix((float)data->angle_y, 0.0f, 1.0f, 0.0f, matrix_rotate);
   381 
   382     multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
   383 
   384     rotate_matrix((float)data->angle_z, 0.0f, 1.0f, 0.0f, matrix_rotate);
   385 
   386     multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
   387 
   388     /* Pull the camera back from the cube */
   389     matrix_modelview[14] -= 2.5;
   390 
   391     perspective_matrix(45.0f, (float)width/height, 0.01f, 100.0f, matrix_perspective);
   392     multiply_matrix(matrix_perspective, matrix_modelview, matrix_mvp);
   393 
   394     GL_CHECK(ctx.glUniformMatrix4fv(data->attr_mvp, 1, GL_FALSE, matrix_mvp));
   395 
   396     data->angle_x += 3;
   397     data->angle_y += 2;
   398     data->angle_z += 1;
   399 
   400     if(data->angle_x >= 360) data->angle_x -= 360;
   401     if(data->angle_x < 0) data->angle_x += 360;
   402     if(data->angle_y >= 360) data->angle_y -= 360;
   403     if(data->angle_y < 0) data->angle_y += 360;
   404     if(data->angle_z >= 360) data->angle_z -= 360;
   405     if(data->angle_z < 0) data->angle_z += 360;
   406 
   407     GL_CHECK(ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
   408     GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36));
   409 }
   410 
   411 int
   412 main(int argc, char *argv[])
   413 {
   414     int fsaa, accel;
   415     int value;
   416     int i, done;
   417     SDL_DisplayMode mode;
   418     SDL_Event event;
   419     Uint32 then, now, frames;
   420     int status;
   421     shader_data *datas, *data;
   422 
   423     /* Initialize parameters */
   424     fsaa = 0;
   425     accel = 0;
   426 
   427     /* Initialize test framework */
   428     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   429     if (!state) {
   430         return 1;
   431     }
   432     for (i = 1; i < argc;) {
   433         int consumed;
   434 
   435         consumed = SDLTest_CommonArg(state, i);
   436         if (consumed == 0) {
   437             if (SDL_strcasecmp(argv[i], "--fsaa") == 0) {
   438                 ++fsaa;
   439                 consumed = 1;
   440             } else if (SDL_strcasecmp(argv[i], "--accel") == 0) {
   441                 ++accel;
   442                 consumed = 1;
   443             } else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) {
   444                 i++;
   445                 if (!argv[i]) {
   446                     consumed = -1;
   447                 } else {
   448                     depth = SDL_atoi(argv[i]);
   449                     consumed = 1;
   450                 }
   451             } else {
   452                 consumed = -1;
   453             }
   454         }
   455         if (consumed < 0) {
   456             SDL_Log ("Usage: %s %s [--fsaa] [--accel] [--zdepth %%d]\n", argv[0],
   457                     SDLTest_CommonUsage(state));
   458             quit(1);
   459         }
   460         i += consumed;
   461     }
   462 
   463     /* Set OpenGL parameters */
   464     state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
   465     state->gl_red_size = 5;
   466     state->gl_green_size = 5;
   467     state->gl_blue_size = 5;
   468     state->gl_depth_size = depth;
   469     state->gl_major_version = 2;
   470     state->gl_minor_version = 0;
   471     state->gl_profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
   472 
   473     if (fsaa) {
   474         state->gl_multisamplebuffers=1;
   475         state->gl_multisamplesamples=fsaa;
   476     }
   477     if (accel) {
   478         state->gl_accelerated=1;
   479     }
   480     if (!SDLTest_CommonInit(state)) {
   481         quit(2);
   482         return 0;
   483     }
   484 
   485     context = SDL_calloc(state->num_windows, sizeof(context));
   486     if (context == NULL) {
   487         SDL_Log("Out of memory!\n");
   488         quit(2);
   489     }
   490     
   491     /* Create OpenGL ES contexts */
   492     for (i = 0; i < state->num_windows; i++) {
   493         context[i] = SDL_GL_CreateContext(state->windows[i]);
   494         if (!context[i]) {
   495             SDL_Log("SDL_GL_CreateContext(): %s\n", SDL_GetError());
   496             quit(2);
   497         }
   498     }
   499 
   500     /* Important: call this *after* creating the context */
   501     if (LoadContext(&ctx) < 0) {
   502         SDL_Log("Could not load GLES2 functions\n");
   503         quit(2);
   504         return 0;
   505     }
   506 
   507 
   508 
   509     if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) {
   510         SDL_GL_SetSwapInterval(1);
   511     } else {
   512         SDL_GL_SetSwapInterval(0);
   513     }
   514 
   515     SDL_GetCurrentDisplayMode(0, &mode);
   516     SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
   517     SDL_Log("\n");
   518     SDL_Log("Vendor     : %s\n", ctx.glGetString(GL_VENDOR));
   519     SDL_Log("Renderer   : %s\n", ctx.glGetString(GL_RENDERER));
   520     SDL_Log("Version    : %s\n", ctx.glGetString(GL_VERSION));
   521     SDL_Log("Extensions : %s\n", ctx.glGetString(GL_EXTENSIONS));
   522     SDL_Log("\n");
   523 
   524     status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);
   525     if (!status) {
   526         SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value);
   527     } else {
   528         SDL_Log( "Failed to get SDL_GL_RED_SIZE: %s\n",
   529                 SDL_GetError());
   530     }
   531     status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value);
   532     if (!status) {
   533         SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value);
   534     } else {
   535         SDL_Log( "Failed to get SDL_GL_GREEN_SIZE: %s\n",
   536                 SDL_GetError());
   537     }
   538     status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value);
   539     if (!status) {
   540         SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value);
   541     } else {
   542         SDL_Log( "Failed to get SDL_GL_BLUE_SIZE: %s\n",
   543                 SDL_GetError());
   544     }
   545     status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value);
   546     if (!status) {
   547         SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", depth, value);
   548     } else {
   549         SDL_Log( "Failed to get SDL_GL_DEPTH_SIZE: %s\n",
   550                 SDL_GetError());
   551     }
   552     if (fsaa) {
   553         status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value);
   554         if (!status) {
   555             SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value);
   556         } else {
   557             SDL_Log( "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n",
   558                     SDL_GetError());
   559         }
   560         status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value);
   561         if (!status) {
   562             SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa,
   563                    value);
   564         } else {
   565             SDL_Log( "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n",
   566                     SDL_GetError());
   567         }
   568     }
   569     if (accel) {
   570         status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value);
   571         if (!status) {
   572             SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value);
   573         } else {
   574             SDL_Log( "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n",
   575                     SDL_GetError());
   576         }
   577     }
   578 
   579     datas = SDL_calloc(state->num_windows, sizeof(shader_data));
   580 
   581     /* Set rendering settings for each context */
   582     for (i = 0; i < state->num_windows; ++i) {
   583 
   584         status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   585         if (status) {
   586             SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   587 
   588             /* Continue for next window */
   589             continue;
   590         }
   591         ctx.glViewport(0, 0, state->window_w, state->window_h);
   592 
   593         data = &datas[i];
   594         data->angle_x = 0; data->angle_y = 0; data->angle_z = 0;
   595 
   596         /* Shader Initialization */
   597         process_shader(&data->shader_vert, _shader_vert_src, GL_VERTEX_SHADER);
   598         process_shader(&data->shader_frag, _shader_frag_src, GL_FRAGMENT_SHADER);
   599 
   600         /* Create shader_program (ready to attach shaders) */
   601         data->shader_program = GL_CHECK(ctx.glCreateProgram());
   602 
   603         /* Attach shaders and link shader_program */
   604         GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_vert));
   605         GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_frag));
   606         GL_CHECK(ctx.glLinkProgram(data->shader_program));
   607 
   608         /* Get attribute locations of non-fixed attributes like color and texture coordinates. */
   609         data->attr_position = GL_CHECK(ctx.glGetAttribLocation(data->shader_program, "av4position"));
   610         data->attr_color = GL_CHECK(ctx.glGetAttribLocation(data->shader_program, "av3color"));
   611 
   612         /* Get uniform locations */
   613         data->attr_mvp = GL_CHECK(ctx.glGetUniformLocation(data->shader_program, "mvp"));
   614 
   615         GL_CHECK(ctx.glUseProgram(data->shader_program));
   616 
   617         /* Enable attributes for position, color and texture coordinates etc. */
   618         GL_CHECK(ctx.glEnableVertexAttribArray(data->attr_position));
   619         GL_CHECK(ctx.glEnableVertexAttribArray(data->attr_color));
   620 
   621         /* Populate attributes for position, color and texture coordinates etc. */
   622         GL_CHECK(ctx.glVertexAttribPointer(data->attr_position, 3, GL_FLOAT, GL_FALSE, 0, _vertices));
   623         GL_CHECK(ctx.glVertexAttribPointer(data->attr_color, 3, GL_FLOAT, GL_FALSE, 0, _colors));
   624 
   625         GL_CHECK(ctx.glEnable(GL_CULL_FACE));
   626         GL_CHECK(ctx.glEnable(GL_DEPTH_TEST));
   627     }
   628 
   629     /* Main render loop */
   630     frames = 0;
   631     then = SDL_GetTicks();
   632     done = 0;
   633     while (!done) {
   634         /* Check for events */
   635         ++frames;
   636         while (SDL_PollEvent(&event) && !done) {
   637             switch (event.type) {
   638             case SDL_WINDOWEVENT:
   639                 switch (event.window.event) {
   640                     case SDL_WINDOWEVENT_RESIZED:
   641                         for (i = 0; i < state->num_windows; ++i) {
   642                             if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
   643                                 status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   644                                 if (status) {
   645                                     SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   646                                     break;
   647                                 }
   648                                 /* Change view port to the new window dimensions */
   649                                 ctx.glViewport(0, 0, event.window.data1, event.window.data2);
   650                                 /* Update window content */
   651                                 Render(event.window.data1, event.window.data2, &datas[i]);
   652                                 SDL_GL_SwapWindow(state->windows[i]);
   653                                 break;
   654                             }
   655                         }
   656                         break;
   657                 }
   658             }
   659             SDLTest_CommonEvent(state, &event, &done);
   660         }
   661         if (!done) {
   662           for (i = 0; i < state->num_windows; ++i) {
   663               status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
   664               if (status) {
   665                   SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
   666 
   667                   /* Continue for next window */
   668                   continue;
   669               }
   670               Render(state->window_w, state->window_h, &datas[i]);
   671               SDL_GL_SwapWindow(state->windows[i]);
   672           }
   673         }
   674     }
   675 
   676     /* Print out some timing information */
   677     now = SDL_GetTicks();
   678     if (now > then) {
   679         SDL_Log("%2.2f frames per second\n",
   680                ((double) frames * 1000) / (now - then));
   681     }
   682 #if !defined(__ANDROID__) && !defined(__NACL__)  
   683     quit(0);
   684 #endif    
   685     return 0;
   686 }
   687 
   688 #else /* HAVE_OPENGLES2 */
   689 
   690 int
   691 main(int argc, char *argv[])
   692 {
   693     SDL_Log("No OpenGL ES support on this system\n");
   694     return 1;
   695 }
   696 
   697 #endif /* HAVE_OPENGLES2 */
   698 
   699 /* vi: set ts=4 sw=4 expandtab: */