1// Calls glDrawElements() the number of times specified by
2// ITERATIONS. Should draw a checkerboard on the screen after
3// a few seconds.
4//
5// Ported from a Java version by Google.
6
7#include <EGL/egl.h>
8#include <GLES/gl.h>
9#include <GLES/glext.h>
10
11#include <WindowSurface.h>
12#include <EGLUtils.h>
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <math.h>
17
18using namespace android;
19
20EGLDisplay eglDisplay;
21EGLSurface eglSurface;
22EGLContext eglContext;
23GLuint texture;
24
25#define FIXED_ONE 0x10000
26#define ITERATIONS 50
27
28int init_gl_surface(const WindowSurface&);
29void free_gl_surface(void);
30void init_scene(void);
31void render(int quads);
32void create_texture(void);
33int readTimer(void);
34
35static void gluLookAt(float eyeX, float eyeY, float eyeZ,
36        float centerX, float centerY, float centerZ, float upX, float upY,
37        float upZ)
38{
39    // See the OpenGL GLUT documentation for gluLookAt for a description
40    // of the algorithm. We implement it in a straightforward way:
41
42    float fx = centerX - eyeX;
43    float fy = centerY - eyeY;
44    float fz = centerZ - eyeZ;
45
46    // Normalize f
47    float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
48    fx *= rlf;
49    fy *= rlf;
50    fz *= rlf;
51
52    // Normalize up
53    float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
54    upX *= rlup;
55    upY *= rlup;
56    upZ *= rlup;
57
58    // compute s = f x up (x means "cross product")
59
60    float sx = fy * upZ - fz * upY;
61    float sy = fz * upX - fx * upZ;
62    float sz = fx * upY - fy * upX;
63
64    // compute u = s x f
65    float ux = sy * fz - sz * fy;
66    float uy = sz * fx - sx * fz;
67    float uz = sx * fy - sy * fx;
68
69    float m[16] ;
70    m[0] = sx;
71    m[1] = ux;
72    m[2] = -fx;
73    m[3] = 0.0f;
74
75    m[4] = sy;
76    m[5] = uy;
77    m[6] = -fy;
78    m[7] = 0.0f;
79
80    m[8] = sz;
81    m[9] = uz;
82    m[10] = -fz;
83    m[11] = 0.0f;
84
85    m[12] = 0.0f;
86    m[13] = 0.0f;
87    m[14] = 0.0f;
88    m[15] = 1.0f;
89
90    glMultMatrixf(m);
91    glTranslatef(-eyeX, -eyeY, -eyeZ);
92}
93
94int main(int argc, char **argv)
95{
96    int q;
97    int start, end;
98
99    printf("Initializing EGL...\n");
100
101    WindowSurface windowSurface;
102    if(!init_gl_surface(windowSurface))
103    {
104        printf("GL initialisation failed - exiting\n");
105        return 0;
106    }
107
108    init_scene();
109
110    create_texture();
111
112    printf("Start test...\n");
113
114    render(argc==2 ? atoi(argv[1]) : ITERATIONS);
115
116    free_gl_surface();
117
118    return 0;
119}
120
121int init_gl_surface(const WindowSurface& windowSurface)
122{
123    EGLint numConfigs = 1;
124    EGLConfig myConfig = {0};
125    EGLint attrib[] =
126    {
127            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
128            EGL_DEPTH_SIZE,     16,
129            EGL_NONE
130    };
131
132    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
133    {
134        printf("eglGetDisplay failed\n");
135        return 0;
136    }
137
138    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
139    {
140        printf("eglInitialize failed\n");
141        return 0;
142    }
143
144    EGLNativeWindowType window = windowSurface.getSurface();
145    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);
146
147    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
148            window, 0)) == EGL_NO_SURFACE )
149    {
150        printf("eglCreateWindowSurface failed\n");
151        return 0;
152    }
153
154    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
155    {
156        printf("eglCreateContext failed\n");
157        return 0;
158    }
159
160    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
161    {
162        printf("eglMakeCurrent failed\n");
163        return 0;
164    }
165
166    return 1;
167}
168
169void free_gl_surface(void)
170{
171    if (eglDisplay != EGL_NO_DISPLAY)
172    {
173        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
174                EGL_NO_SURFACE, EGL_NO_CONTEXT );
175        eglDestroyContext( eglDisplay, eglContext );
176        eglDestroySurface( eglDisplay, eglSurface );
177        eglTerminate( eglDisplay );
178        eglDisplay = EGL_NO_DISPLAY;
179    }
180}
181
182void init_scene(void)
183{
184    glDisable(GL_DITHER);
185    glEnable(GL_CULL_FACE);
186
187    float ratio = 320.0f / 480.0f;
188    glViewport(0, 0, 320, 480);
189
190    glMatrixMode(GL_PROJECTION);
191    glLoadIdentity();
192    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
193
194    glMatrixMode(GL_MODELVIEW);
195    glLoadIdentity();
196    gluLookAt(
197            0, 0, 3,  // eye
198            0, 0, 0,  // center
199            0, 1, 0); // up
200
201    glEnable(GL_TEXTURE_2D);
202    glEnableClientState(GL_VERTEX_ARRAY);
203    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
204}
205
206void create_texture(void)
207{
208    const unsigned int on = 0xff0000ff;
209    const unsigned int off = 0xffffffff;
210    const unsigned int pixels[] =
211    {
212            on, off, on, off, on, off, on, off,
213            off, on, off, on, off, on, off, on,
214            on, off, on, off, on, off, on, off,
215            off, on, off, on, off, on, off, on,
216            on, off, on, off, on, off, on, off,
217            off, on, off, on, off, on, off, on,
218            on, off, on, off, on, off, on, off,
219            off, on, off, on, off, on, off, on,
220    };
221    glGenTextures(1, &texture);
222    glBindTexture(GL_TEXTURE_2D, texture);
223    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
224    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
225    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
226    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
227}
228
229void render(int quads)
230{
231    int i, j;
232
233    const GLfloat vertices[] = {
234            -1,  -1,  0,
235             1,  -1,  0,
236             1,   1,  0,
237            -1,   1,  0
238    };
239
240    const GLfixed texCoords[] = {
241            0,            0,
242            FIXED_ONE,    0,
243            FIXED_ONE,    FIXED_ONE,
244            0,            FIXED_ONE
245    };
246
247    const GLushort quadIndices[] = { 0, 1, 2,  0, 2, 3 };
248
249
250    GLushort* indices = (GLushort*)malloc(quads*sizeof(quadIndices));
251    for (i=0 ; i<quads ; i++)
252        memcpy(indices+(sizeof(quadIndices)/sizeof(indices[0]))*i, quadIndices, sizeof(quadIndices));
253
254    glVertexPointer(3, GL_FLOAT, 0, vertices);
255    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
256
257    // make sure to do a couple eglSwapBuffers to make sure there are
258    // no problems with the very first ones (who knows)
259    glClearColor(0.4, 0.4, 0.4, 0.4);
260    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
261    eglSwapBuffers(eglDisplay, eglSurface);
262    glClearColor(0.6, 0.6, 0.6, 0.6);
263    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
264    eglSwapBuffers(eglDisplay, eglSurface);
265    glClearColor(1.0, 1.0, 1.0, 1.0);
266
267    for (j=0 ; j<10 ; j++) {
268        printf("loop %d / 10 (%d quads / loop)\n", j, quads);
269
270        int nelem = sizeof(quadIndices)/sizeof(quadIndices[0]);
271        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
272        glDrawElements(GL_TRIANGLES, nelem*quads, GL_UNSIGNED_SHORT, indices);
273        eglSwapBuffers(eglDisplay, eglSurface);
274    }
275
276    free(indices);
277}
278
279