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 <ui/FramebufferNativeWindow.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(void);
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    if(!init_gl_surface())
198    {
199        printf("GL initialisation failed - exiting\n");
200        return 0;
201    }
202    init_scene();
203    create_texture();
204    printf("Running...\n");
205    while(true) {
206        render();
207    }
208    free_gl_surface();
209    return 0;
210}
211
212int init_gl_surface(void)
213{
214    EGLint numConfigs = 1;
215    EGLConfig myConfig = {0};
216    EGLint attrib[] =
217    {
218            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
219            EGL_NONE
220    };
221
222    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )
223    {
224        printf("eglGetDisplay failed\n");
225        return 0;
226    }
227
228    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )
229    {
230        printf("eglInitialize failed\n");
231        return 0;
232    }
233
234    if (! printEGLConfigurations(eglDisplay)) {
235        printf("printEGLConfigurations failed.\n");
236        return 0;
237    }
238
239    EGLNativeWindowType window = android_createDisplaySurface();
240    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);
241
242    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
243            window, 0)) == EGL_NO_SURFACE )
244    {
245        printf("eglCreateWindowSurface failed\n");
246        return 0;
247    }
248
249    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )
250    {
251        printf("eglCreateContext failed\n");
252        return 0;
253    }
254
255    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )
256    {
257        printf("eglMakeCurrent failed\n");
258        return 0;
259    }
260
261    int w, h;
262
263    eglQuerySurface(eglDisplay, eglSurface, EGL_WIDTH, &w);
264    checkEglError("eglQuerySurface");
265    eglQuerySurface(eglDisplay, eglSurface, EGL_HEIGHT, &h);
266    checkEglError("eglQuerySurface");
267    GLint dim = w < h ? w : h;
268
269    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
270
271    printGLString("Version", GL_VERSION);
272    printGLString("Vendor", GL_VENDOR);
273    printGLString("Renderer", GL_RENDERER);
274    printGLString("Extensions", GL_EXTENSIONS);
275
276    return 1;
277}
278
279void free_gl_surface(void)
280{
281    if (eglDisplay != EGL_NO_DISPLAY)
282    {
283        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
284                EGL_NO_SURFACE, EGL_NO_CONTEXT );
285        eglDestroyContext( eglDisplay, eglContext );
286        eglDestroySurface( eglDisplay, eglSurface );
287        eglTerminate( eglDisplay );
288        eglDisplay = EGL_NO_DISPLAY;
289    }
290}
291
292void init_scene(void)
293{
294    glDisable(GL_DITHER);
295    glEnable(GL_CULL_FACE);
296    float ratio = 320.0f / 480.0f;
297    glViewport(0, 0, 320, 480);
298    glMatrixMode(GL_PROJECTION);
299    glLoadIdentity();
300    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
301    glMatrixMode(GL_MODELVIEW);
302    glLoadIdentity();
303    gluLookAt(
304            0, 0, 3,  // eye
305            0, 0, 0,  // center
306            0, 1, 0); // up
307    glEnable(GL_TEXTURE_2D);
308    glEnableClientState(GL_VERTEX_ARRAY);
309    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
310}
311
312void create_texture(void)
313{
314    const unsigned int on = 0xff0000ff;
315    const unsigned int off = 0xffffffff;
316    const unsigned int pixels[] =
317    {
318            on, off, on, off, on, off, on, off,
319            off, on, off, on, off, on, off, on,
320            on, off, on, off, on, off, on, off,
321            off, on, off, on, off, on, off, on,
322            on, off, on, off, on, off, on, off,
323            off, on, off, on, off, on, off, on,
324            on, off, on, off, on, off, on, off,
325            off, on, off, on, off, on, off, on,
326    };
327
328    glGenTextures(1, &texture);
329    glBindTexture(GL_TEXTURE_2D, texture);
330    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
331    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
332    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
333    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
334}
335
336void render()
337{
338    int i, j;
339    int quads = 1;
340
341    const GLfloat vertices[] = {
342            -1,  -1,  0,
343             1,  -1,  0,
344             1,   1,  0,
345            -1,   1,  0
346    };
347
348    const GLfixed texCoords[] = {
349            0,            0,
350            FIXED_ONE,    0,
351            FIXED_ONE,    FIXED_ONE,
352            0,            FIXED_ONE
353    };
354
355    const GLushort indices[] = { 0, 1, 2,  0, 2, 3 };
356
357    glVertexPointer(3, GL_FLOAT, 0, vertices);
358    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
359    glClearColor(1.0, 1.0, 1.0, 1.0);
360    int nelem = sizeof(indices)/sizeof(indices[0]);
361    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
362    glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices);
363    eglSwapBuffers(eglDisplay, eglSurface);
364}
365