1// Simple OpenGL ES 1.x application showing how to initialize and draw something.
2
3#include <EGL/egl.h>
4
5#include <GLES/gl.h>
6#include <GLES/glext.h>
7
8#include <WindowSurface.h>
9#include <EGLUtils.h>
10
11#include <stdio.h>
12
13#include <stdlib.h>
14#include <math.h>
15
16using namespace android;
17
18EGLDisplay eglDisplay;
19EGLSurface eglSurface;
20EGLContext eglContext;
21GLuint texture;
22
23#define FIXED_ONE 0x10000
24#define ITERATIONS 50
25
26int init_gl_surface(const WindowSurface& windowSurface);
27void free_gl_surface(void);
28void init_scene(void);
29void render();
30void create_texture(void);
31int readTimer(void);
32
33static void printGLString(const char *name, GLenum s) {
34    const char *v = (const char *) glGetString(s);
35    fprintf(stderr, "GL %s = %s\n", name, v);
36}
37
38static void gluLookAt(float eyeX, float eyeY, float eyeZ,
39        float centerX, float centerY, float centerZ, float upX, float upY,
40        float upZ)
41{
42    // See the OpenGL GLUT documentation for gluLookAt for a description
43    // of the algorithm. We implement it in a straightforward way:
44
45    float fx = centerX - eyeX;
46    float fy = centerY - eyeY;
47    float fz = centerZ - eyeZ;
48
49    // Normalize f
50    float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
51    fx *= rlf;
52    fy *= rlf;
53    fz *= rlf;
54
55    // Normalize up
56    float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
57    upX *= rlup;
58    upY *= rlup;
59    upZ *= rlup;
60
61    // compute s = f x up (x means "cross product")
62
63    float sx = fy * upZ - fz * upY;
64    float sy = fz * upX - fx * upZ;
65    float sz = fx * upY - fy * upX;
66
67    // compute u = s x f
68    float ux = sy * fz - sz * fy;
69    float uy = sz * fx - sx * fz;
70    float uz = sx * fy - sy * fx;
71
72    float m[16] ;
73    m[0] = sx;
74    m[1] = ux;
75    m[2] = -fx;
76    m[3] = 0.0f;
77
78    m[4] = sy;
79    m[5] = uy;
80    m[6] = -fy;
81    m[7] = 0.0f;
82
83    m[8] = sz;
84    m[9] = uz;
85    m[10] = -fz;
86    m[11] = 0.0f;
87
88    m[12] = 0.0f;
89    m[13] = 0.0f;
90    m[14] = 0.0f;
91    m[15] = 1.0f;
92
93    glMultMatrixf(m);
94    glTranslatef(-eyeX, -eyeY, -eyeZ);
95}
96
97void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
98
99#define X(VAL) {VAL, #VAL}
100    struct {EGLint attribute; const char* name;} names[] = {
101    X(EGL_BUFFER_SIZE),
102    X(EGL_ALPHA_SIZE),
103    X(EGL_BLUE_SIZE),
104    X(EGL_GREEN_SIZE),
105    X(EGL_RED_SIZE),
106    X(EGL_DEPTH_SIZE),
107    X(EGL_STENCIL_SIZE),
108    X(EGL_CONFIG_CAVEAT),
109    X(EGL_CONFIG_ID),
110    X(EGL_LEVEL),
111    X(EGL_MAX_PBUFFER_HEIGHT),
112    X(EGL_MAX_PBUFFER_PIXELS),
113    X(EGL_MAX_PBUFFER_WIDTH),
114    X(EGL_NATIVE_RENDERABLE),
115    X(EGL_NATIVE_VISUAL_ID),
116    X(EGL_NATIVE_VISUAL_TYPE),
117    X(EGL_SAMPLES),
118    X(EGL_SAMPLE_BUFFERS),
119    X(EGL_SURFACE_TYPE),
120    X(EGL_TRANSPARENT_TYPE),
121    X(EGL_TRANSPARENT_RED_VALUE),
122    X(EGL_TRANSPARENT_GREEN_VALUE),
123    X(EGL_TRANSPARENT_BLUE_VALUE),
124    X(EGL_BIND_TO_TEXTURE_RGB),
125    X(EGL_BIND_TO_TEXTURE_RGBA),
126    X(EGL_MIN_SWAP_INTERVAL),
127    X(EGL_MAX_SWAP_INTERVAL),
128    X(EGL_LUMINANCE_SIZE),
129    X(EGL_ALPHA_MASK_SIZE),
130    X(EGL_COLOR_BUFFER_TYPE),
131    X(EGL_RENDERABLE_TYPE),
132    X(EGL_CONFORMANT),
133   };
134#undef X
135
136    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
137        EGLint value = -1;
138        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
139        EGLint error = eglGetError();
140        if (returnVal && error == EGL_SUCCESS) {
141            printf(" %s: ", names[j].name);
142            printf("%d (0x%x)", value, value);
143        }
144    }
145    printf("\n");
146}
147
148static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
149    if (returnVal != EGL_TRUE) {
150        fprintf(stderr, "%s() returned %d\n", op, returnVal);
151    }
152
153    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
154            = eglGetError()) {
155        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
156                error);
157    }
158}
159
160int printEGLConfigurations(EGLDisplay dpy) {
161    EGLint numConfig = 0;
162    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
163    checkEglError("eglGetConfigs", returnVal);
164    if (!returnVal) {
165        return false;
166    }
167
168    printf("Number of EGL configurations: %d\n", numConfig);
169
170    EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
171    if (! configs) {
172        printf("Could not allocate configs.\n");
173        return false;
174    }
175
176    returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
177    checkEglError("eglGetConfigs", returnVal);
178    if (!returnVal) {
179        free(configs);
180        return false;
181    }
182
183    for(int i = 0; i < numConfig; i++) {
184        printf("Configuration %d\n", i);
185        printEGLConfiguration(dpy, configs[i]);
186    }
187
188    free(configs);
189    return true;
190}
191
192int main(int argc, char **argv)
193{
194    int q;
195    int start, end;
196    printf("Initializing EGL...\n");
197    WindowSurface windowSurface;
198    if(!init_gl_surface(windowSurface))
199    {
200        printf("GL initialisation failed - exiting\n");
201        return 0;
202    }
203    init_scene();
204    create_texture();
205    printf("Running...\n");
206    while(true) {
207        render();
208    }
209    free_gl_surface();
210    return 0;
211}
212
213int init_gl_surface(const WindowSurface& windowSurface)
214{
215    EGLint numConfigs = 1;
216    EGLConfig myConfig = {0};
217    EGLint attrib[] =
218    {
219            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
220            EGL_NONE
221    };
222
223    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
224    {
225        printf("eglGetDisplay failed\n");
226        return 0;
227    }
228
229    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
230    {
231        printf("eglInitialize failed\n");
232        return 0;
233    }
234
235    if (! printEGLConfigurations(eglDisplay)) {
236        printf("printEGLConfigurations failed.\n");
237        return 0;
238    }
239
240    EGLNativeWindowType window = windowSurface.getSurface();
241    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);
242
243    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
244            window, 0)) == EGL_NO_SURFACE )
245    {
246        printf("eglCreateWindowSurface failed\n");
247        return 0;
248    }
249
250    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
251    {
252        printf("eglCreateContext failed\n");
253        return 0;
254    }
255
256    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
257    {
258        printf("eglMakeCurrent failed\n");
259        return 0;
260    }
261
262    int w, h;
263
264    eglQuerySurface(eglDisplay, eglSurface, EGL_WIDTH, &w);
265    checkEglError("eglQuerySurface");
266    eglQuerySurface(eglDisplay, eglSurface, EGL_HEIGHT, &h);
267    checkEglError("eglQuerySurface");
268    GLint dim = w < h ? w : h;
269
270    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
271
272    printGLString("Version", GL_VERSION);
273    printGLString("Vendor", GL_VENDOR);
274    printGLString("Renderer", GL_RENDERER);
275    printGLString("Extensions", GL_EXTENSIONS);
276
277    return 1;
278}
279
280void free_gl_surface(void)
281{
282    if (eglDisplay != EGL_NO_DISPLAY)
283    {
284        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
285                EGL_NO_SURFACE, EGL_NO_CONTEXT );
286        eglDestroyContext( eglDisplay, eglContext );
287        eglDestroySurface( eglDisplay, eglSurface );
288        eglTerminate( eglDisplay );
289        eglDisplay = EGL_NO_DISPLAY;
290    }
291}
292
293void init_scene(void)
294{
295    glDisable(GL_DITHER);
296    glEnable(GL_CULL_FACE);
297    float ratio = 320.0f / 480.0f;
298    glViewport(0, 0, 320, 480);
299    glMatrixMode(GL_PROJECTION);
300    glLoadIdentity();
301    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
302    glMatrixMode(GL_MODELVIEW);
303    glLoadIdentity();
304    gluLookAt(
305            0, 0, 3,  // eye
306            0, 0, 0,  // center
307            0, 1, 0); // up
308    glEnable(GL_TEXTURE_2D);
309    glEnableClientState(GL_VERTEX_ARRAY);
310    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
311}
312
313void create_texture(void)
314{
315    const unsigned int on = 0xff0000ff;
316    const unsigned int off = 0xffffffff;
317    const unsigned int pixels[] =
318    {
319            on, off, on, off, on, off, on, off,
320            off, on, off, on, off, on, off, on,
321            on, off, on, off, on, off, on, off,
322            off, on, off, on, off, on, off, on,
323            on, off, on, off, on, off, on, off,
324            off, on, off, on, off, on, off, on,
325            on, off, on, off, on, off, on, off,
326            off, on, off, on, off, on, off, on,
327    };
328
329    glGenTextures(1, &texture);
330    glBindTexture(GL_TEXTURE_2D, texture);
331    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
332    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
333    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
334    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
335}
336
337void render()
338{
339    int i, j;
340    int quads = 1;
341
342    const GLfloat vertices[] = {
343            -1,  -1,  0,
344             1,  -1,  0,
345             1,   1,  0,
346            -1,   1,  0
347    };
348
349    const GLfixed texCoords[] = {
350            0,            0,
351            FIXED_ONE,    0,
352            FIXED_ONE,    FIXED_ONE,
353            0,            FIXED_ONE
354    };
355
356    const GLushort indices[] = { 0, 1, 2,  0, 2, 3 };
357
358    glVertexPointer(3, GL_FLOAT, 0, vertices);
359    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
360    glClearColor(1.0, 1.0, 1.0, 1.0);
361    int nelem = sizeof(indices)/sizeof(indices[0]);
362    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
363    glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices);
364    eglSwapBuffers(eglDisplay, eglSurface);
365}
366