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