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 <ui/FramebufferNativeWindow.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(void);
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    if(!init_gl_surface())
102    {
103        printf("GL initialisation failed - exiting\n");
104        return 0;
105    }
106
107    init_scene();
108
109    create_texture();
110
111    printf("Start test...\n");
112
113    render(argc==2 ? atoi(argv[1]) : ITERATIONS);
114
115    free_gl_surface();
116
117    return 0;
118}
119
120int init_gl_surface(void)
121{
122    EGLint numConfigs = 1;
123    EGLConfig myConfig = {0};
124    EGLint attrib[] =
125    {
126            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
127            EGL_DEPTH_SIZE,     16,
128            EGL_NONE
129    };
130
131    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
132    {
133        printf("eglGetDisplay failed\n");
134        return 0;
135    }
136
137    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
138    {
139        printf("eglInitialize failed\n");
140        return 0;
141    }
142
143    EGLNativeWindowType window = android_createDisplaySurface();
144    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);
145
146    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
147            window, 0)) == EGL_NO_SURFACE )
148    {
149        printf("eglCreateWindowSurface failed\n");
150        return 0;
151    }
152
153    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
154    {
155        printf("eglCreateContext failed\n");
156        return 0;
157    }
158
159    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
160    {
161        printf("eglMakeCurrent failed\n");
162        return 0;
163    }
164
165    return 1;
166}
167
168void free_gl_surface(void)
169{
170    if (eglDisplay != EGL_NO_DISPLAY)
171    {
172        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
173                EGL_NO_SURFACE, EGL_NO_CONTEXT );
174        eglDestroyContext( eglDisplay, eglContext );
175        eglDestroySurface( eglDisplay, eglSurface );
176        eglTerminate( eglDisplay );
177        eglDisplay = EGL_NO_DISPLAY;
178    }
179}
180
181void init_scene(void)
182{
183    glDisable(GL_DITHER);
184    glEnable(GL_CULL_FACE);
185
186    float ratio = 320.0f / 480.0f;
187    glViewport(0, 0, 320, 480);
188
189    glMatrixMode(GL_PROJECTION);
190    glLoadIdentity();
191    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
192
193    glMatrixMode(GL_MODELVIEW);
194    glLoadIdentity();
195    gluLookAt(
196            0, 0, 3,  // eye
197            0, 0, 0,  // center
198            0, 1, 0); // up
199
200    glEnable(GL_TEXTURE_2D);
201    glEnableClientState(GL_VERTEX_ARRAY);
202    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
203}
204
205void create_texture(void)
206{
207    const unsigned int on = 0xff0000ff;
208    const unsigned int off = 0xffffffff;
209    const unsigned int pixels[] =
210    {
211            on, off, on, off, on, off, on, off,
212            off, on, off, on, off, on, off, on,
213            on, off, on, off, on, off, on, off,
214            off, on, off, on, off, on, off, on,
215            on, off, on, off, on, off, on, off,
216            off, on, off, on, off, on, off, on,
217            on, off, on, off, on, off, on, off,
218            off, on, off, on, off, on, off, on,
219    };
220    glGenTextures(1, &texture);
221    glBindTexture(GL_TEXTURE_2D, texture);
222    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
223    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
224    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
225    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
226}
227
228void render(int quads)
229{
230    int i, j;
231
232    const GLfloat vertices[] = {
233            -1,  -1,  0,
234             1,  -1,  0,
235             1,   1,  0,
236            -1,   1,  0
237    };
238
239    const GLfixed texCoords[] = {
240            0,            0,
241            FIXED_ONE,    0,
242            FIXED_ONE,    FIXED_ONE,
243            0,            FIXED_ONE
244    };
245
246    const GLushort quadIndices[] = { 0, 1, 2,  0, 2, 3 };
247
248
249    GLushort* indices = (GLushort*)malloc(quads*sizeof(quadIndices));
250    for (i=0 ; i<quads ; i++)
251        memcpy(indices+(sizeof(quadIndices)/sizeof(indices[0]))*i, quadIndices, sizeof(quadIndices));
252
253    glVertexPointer(3, GL_FLOAT, 0, vertices);
254    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
255
256    // make sure to do a couple eglSwapBuffers to make sure there are
257    // no problems with the very first ones (who knows)
258    glClearColor(0.4, 0.4, 0.4, 0.4);
259    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
260    eglSwapBuffers(eglDisplay, eglSurface);
261    glClearColor(0.6, 0.6, 0.6, 0.6);
262    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
263    eglSwapBuffers(eglDisplay, eglSurface);
264    glClearColor(1.0, 1.0, 1.0, 1.0);
265
266    for (j=0 ; j<10 ; j++) {
267        printf("loop %d / 10 (%d quads / loop)\n", j, quads);
268
269        int nelem = sizeof(quadIndices)/sizeof(quadIndices[0]);
270        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
271        glDrawElements(GL_TRIANGLES, nelem*quads, GL_UNSIGNED_SHORT, indices);
272        eglSwapBuffers(eglDisplay, eglSurface);
273    }
274
275    free(indices);
276}
277
278