aboutsummaryrefslogtreecommitdiff
path: root/tests/gles2_uniform_arrays.cpp
blob: 84e394dc86ba926356a17df05d76dffe82e0db0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "SDL/SDL_opengl.h"
#include "SDL/SDL.h"

#include <stdio.h>
#include <string.h>
#include <assert.h>

void RunTest(int testVariant)
{
    GLuint vs = 0;

    const char *vsCode = "#version 100\n"
        "attribute vec4 pos; void main() { gl_Position = pos; }";

    vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, &vsCode, NULL);
    glCompileShader(vs);

    GLuint ps = 0;

    const char *psCode = "#version 100\n"
        "precision lowp float;\n"
        "uniform vec3 color;\n"
        "uniform vec3 colors[3];\n"
        "void main() { gl_FragColor = vec4(color,1) + vec4(colors[0].r, colors[1].g, colors[2].b, 1); }";

    ps = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(ps, 1, &psCode, NULL);
    glCompileShader(ps);

    GLuint program = 0;
    program = glCreateProgram();
    glAttachShader(program, vs);
    glAttachShader(program, ps);
    glBindAttribLocation(program, 0, "pos");
    glLinkProgram(program);

    int color_loc = glGetUniformLocation(program, "color");
    assert(color_loc != -1);

    glUseProgram(program);
    float col[3] = { 0.2f, 0.2f, 0.2f };
    glUniform3fv(color_loc, 1, col);

    int loc = glGetUniformLocation(program, "colors");
    assert(loc != -1);
    // In previous Emscripten GL layer code, calling glGetUniformLocation would do extra caching operations that interacts how glUniform** after that will work, 
    // so to exhibit extra issues in old code (and to keep new code from regressing), must test both with and without excess glGetUniformLocation calls.
    if ((testVariant&1) != 0)
    {
        // Deliberately check in odd order to make sure any kind of lazy operations won't affect the indices we get.
        assert(glGetUniformLocation(program, "colors[2]") == loc+2);
        assert(glGetUniformLocation(program, "colors[0]") == loc);
        assert(glGetUniformLocation(program, "colors[3]") == -1);
        assert(glGetUniformLocation(program, "colors[1]") == loc+1);
        assert(glGetUniformLocation(program, "colors[]") == loc);
        assert(glGetUniformLocation(program, "colors[-100]") == -1);
        assert(glGetUniformLocation(program, "colors[bleh]") == -1);
    }

    float colors[4*3] = { 1,0,0, 0,0.5,0, 0,0,0.2, 1,1,1 };

    if ((testVariant&2)!=0)
    {
        glUniform3fv(loc+1, 3, colors+3); // Pass the actual colors (testing a nonzero location offset), but do a mistake by setting one index too many. Spec says this should be gracefully handled, and that excess elements are ignored.
        assert(glGetError() == GL_NO_ERROR);
        glUniform3fv(loc, 1, colors); // Set the first index as well.
        assert(glGetError() == GL_NO_ERROR);
    }
    else
    {
        glUniform3fv(loc, 4, colors); // Just directly set the full array.
        assert(glGetError() == GL_NO_ERROR);
    }

    assert(glGetError() == GL_NO_ERROR);

    GLuint vbo = 0;
    const GLfloat v[] = { -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1 };
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0);
    glEnableVertexAttribArray(0);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    unsigned char pixel[4];
    glReadPixels(1,1,1,1,GL_RGBA,GL_UNSIGNED_BYTE, pixel);
    //printf("%d,%d,%d,%d\n", pixel[0], pixel[1], pixel[2], pixel[3]);
    assert(pixel[0] == 255);
    assert(pixel[1] == 178);
    assert(pixel[2] == 102);
    assert(pixel[3] == 255);

    printf("OK: Case %d passed.\n", testVariant);
    // Lazy, don't clean up afterwards.
}

int main(int argc, char *argv[])
{
    SDL_Surface *screen;

    // Slightly different SDL initialization
    if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
    if ( !screen ) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    for(int i = 0; i < 4; ++i)
        RunTest(i);

    return 0;
}