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 
16 using namespace android;
17 
18 #define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
19 
20 EGLDisplay eglDisplay;
21 EGLSurface eglSurface;
22 EGLContext eglContext;
23 GLuint texture;
24 
25 #define FIXED_ONE 0x10000
26 #define ITERATIONS 50
27 
28 int init_gl_surface(const WindowSurface& windowSurface);
29 void free_gl_surface(void);
30 void init_scene(void);
31 void render();
32 void create_texture(void);
33 int readTimer(void);
34 
printGLString(const char * name,GLenum s)35 static void printGLString(const char *name, GLenum s) {
36     const char *v = (const char *) glGetString(s);
37     fprintf(stderr, "GL %s = %s\n", name, v);
38 }
39 
gluLookAt(float eyeX,float eyeY,float eyeZ,float centerX,float centerY,float centerZ,float upX,float upY,float upZ)40 static void gluLookAt(float eyeX, float eyeY, float eyeZ,
41         float centerX, float centerY, float centerZ, float upX, float upY,
42         float upZ)
43 {
44     // See the OpenGL GLUT documentation for gluLookAt for a description
45     // of the algorithm. We implement it in a straightforward way:
46 
47     float fx = centerX - eyeX;
48     float fy = centerY - eyeY;
49     float fz = centerZ - eyeZ;
50 
51     // Normalize f
52     float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
53     fx *= rlf;
54     fy *= rlf;
55     fz *= rlf;
56 
57     // Normalize up
58     float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
59     upX *= rlup;
60     upY *= rlup;
61     upZ *= rlup;
62 
63     // compute s = f x up (x means "cross product")
64 
65     float sx = fy * upZ - fz * upY;
66     float sy = fz * upX - fx * upZ;
67     float sz = fx * upY - fy * upX;
68 
69     // compute u = s x f
70     float ux = sy * fz - sz * fy;
71     float uy = sz * fx - sx * fz;
72     float uz = sx * fy - sy * fx;
73 
74     float m[16] ;
75     m[0] = sx;
76     m[1] = ux;
77     m[2] = -fx;
78     m[3] = 0.0f;
79 
80     m[4] = sy;
81     m[5] = uy;
82     m[6] = -fy;
83     m[7] = 0.0f;
84 
85     m[8] = sz;
86     m[9] = uz;
87     m[10] = -fz;
88     m[11] = 0.0f;
89 
90     m[12] = 0.0f;
91     m[13] = 0.0f;
92     m[14] = 0.0f;
93     m[15] = 1.0f;
94 
95     glMultMatrixf(m);
96     glTranslatef(-eyeX, -eyeY, -eyeZ);
97 }
98 
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)99 void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
100 
101 #define X(VAL) {VAL, #VAL}
102     struct {EGLint attribute; const char* name;} names[] = {
103     X(EGL_BUFFER_SIZE),
104     X(EGL_ALPHA_SIZE),
105     X(EGL_BLUE_SIZE),
106     X(EGL_GREEN_SIZE),
107     X(EGL_RED_SIZE),
108     X(EGL_DEPTH_SIZE),
109     X(EGL_STENCIL_SIZE),
110     X(EGL_CONFIG_CAVEAT),
111     X(EGL_CONFIG_ID),
112     X(EGL_LEVEL),
113     X(EGL_MAX_PBUFFER_HEIGHT),
114     X(EGL_MAX_PBUFFER_PIXELS),
115     X(EGL_MAX_PBUFFER_WIDTH),
116     X(EGL_NATIVE_RENDERABLE),
117     X(EGL_NATIVE_VISUAL_ID),
118     X(EGL_NATIVE_VISUAL_TYPE),
119     X(EGL_SAMPLES),
120     X(EGL_SAMPLE_BUFFERS),
121     X(EGL_SURFACE_TYPE),
122     X(EGL_TRANSPARENT_TYPE),
123     X(EGL_TRANSPARENT_RED_VALUE),
124     X(EGL_TRANSPARENT_GREEN_VALUE),
125     X(EGL_TRANSPARENT_BLUE_VALUE),
126     X(EGL_BIND_TO_TEXTURE_RGB),
127     X(EGL_BIND_TO_TEXTURE_RGBA),
128     X(EGL_MIN_SWAP_INTERVAL),
129     X(EGL_MAX_SWAP_INTERVAL),
130     X(EGL_LUMINANCE_SIZE),
131     X(EGL_ALPHA_MASK_SIZE),
132     X(EGL_COLOR_BUFFER_TYPE),
133     X(EGL_RENDERABLE_TYPE),
134     X(EGL_CONFORMANT),
135    };
136 #undef X
137 
138     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
139         EGLint value = -1;
140         EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
141         EGLint error = eglGetError();
142         if (returnVal && error == EGL_SUCCESS) {
143             printf(" %s: ", names[j].name);
144             printf("%d (0x%x)", value, value);
145         }
146     }
147     printf("\n");
148 }
149 
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)150 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
151     if (returnVal != EGL_TRUE) {
152         fprintf(stderr, "%s() returned %d\n", op, returnVal);
153     }
154 
155     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
156             = eglGetError()) {
157         fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
158                 error);
159     }
160 }
161 
printEGLConfigurations(EGLDisplay dpy)162 int printEGLConfigurations(EGLDisplay dpy) {
163     EGLint numConfig = 0;
164     EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
165     checkEglError("eglGetConfigs", returnVal);
166     if (!returnVal) {
167         return false;
168     }
169 
170     printf("Number of EGL configurations: %d\n", numConfig);
171 
172     EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
173     if (! configs) {
174         printf("Could not allocate configs.\n");
175         return false;
176     }
177 
178     returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
179     checkEglError("eglGetConfigs", returnVal);
180     if (!returnVal) {
181         free(configs);
182         return false;
183     }
184 
185     for(int i = 0; i < numConfig; i++) {
186         printf("Configuration %d\n", i);
187         printEGLConfiguration(dpy, configs[i]);
188     }
189 
190     free(configs);
191     return true;
192 }
193 
main(int,char **)194 int main(int /*argc*/, char **/*argv*/)
195 {
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 
init_gl_surface(const WindowSurface & windowSurface)213 int init_gl_surface(const WindowSurface& windowSurface)
214 {
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 = windowSurface.getSurface();
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 
268     fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
269 
270     printGLString("Version", GL_VERSION);
271     printGLString("Vendor", GL_VENDOR);
272     printGLString("Renderer", GL_RENDERER);
273     printGLString("Extensions", GL_EXTENSIONS);
274 
275     return 1;
276 }
277 
free_gl_surface(void)278 void free_gl_surface(void)
279 {
280     if (eglDisplay != EGL_NO_DISPLAY)
281     {
282         eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,
283                 EGL_NO_SURFACE, EGL_NO_CONTEXT );
284         eglDestroyContext( eglDisplay, eglContext );
285         eglDestroySurface( eglDisplay, eglSurface );
286         eglTerminate( eglDisplay );
287         eglDisplay = EGL_NO_DISPLAY;
288     }
289 }
290 
init_scene(void)291 void init_scene(void)
292 {
293     glDisable(GL_DITHER);
294     glEnable(GL_CULL_FACE);
295     float ratio = 320.0f / 480.0f;
296     glViewport(0, 0, 320, 480);
297     glMatrixMode(GL_PROJECTION);
298     glLoadIdentity();
299     glFrustumf(-ratio, ratio, -1, 1, 1, 10);
300     glMatrixMode(GL_MODELVIEW);
301     glLoadIdentity();
302     gluLookAt(
303             0, 0, 3,  // eye
304             0, 0, 0,  // center
305             0, 1, 0); // up
306     glEnable(GL_TEXTURE_2D);
307     glEnableClientState(GL_VERTEX_ARRAY);
308     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
309 }
310 
create_texture(void)311 void create_texture(void)
312 {
313     const unsigned int on = 0xff0000ff;
314     const unsigned int off = 0xffffffff;
315     const unsigned int pixels[] =
316     {
317             on, off, on, off, on, off, on, off,
318             off, on, off, on, off, on, off, on,
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     };
326 
327     glGenTextures(1, &texture);
328     glBindTexture(GL_TEXTURE_2D, texture);
329     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
330     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
331     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
332     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
333 }
334 
setSurfaceMetadata(EGLDisplay dpy,EGLSurface surface)335 void setSurfaceMetadata(EGLDisplay dpy, EGLSurface surface) {
336     static EGLBoolean toggle = GL_FALSE;
337     if (EGLUtils::hasEglExtension(dpy, "EGL_EXT_surface_SMPTE2086_metadata")) {
338         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, METADATA_SCALE(0.640));
339         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, METADATA_SCALE(0.330));
340         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, METADATA_SCALE(0.290));
341         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, METADATA_SCALE(0.600));
342         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, METADATA_SCALE(0.150));
343         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, METADATA_SCALE(0.060));
344         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT, METADATA_SCALE(0.3127));
345         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, METADATA_SCALE(0.3290));
346         if (toggle) {
347             eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, METADATA_SCALE(350));
348         } else {
349             eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, METADATA_SCALE(300));
350         }
351         eglSurfaceAttrib(dpy, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, METADATA_SCALE(0.7));
352     }
353 
354     if (EGLUtils::hasEglExtension(dpy, "EGL_EXT_surface_CTA861_3_metadata")) {
355         if (toggle) {
356             eglSurfaceAttrib(dpy, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
357                              METADATA_SCALE(300));
358         } else {
359             eglSurfaceAttrib(dpy, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
360                              METADATA_SCALE(325));
361         }
362         eglSurfaceAttrib(dpy, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
363                          METADATA_SCALE(75));
364     }
365     toggle = !toggle;
366 }
367 
render()368 void render()
369 {
370     const GLfloat vertices[] = {
371             -1,  -1,  0,
372              1,  -1,  0,
373              1,   1,  0,
374             -1,   1,  0
375     };
376 
377     const GLfixed texCoords[] = {
378             0,            0,
379             FIXED_ONE,    0,
380             FIXED_ONE,    FIXED_ONE,
381             0,            FIXED_ONE
382     };
383 
384     const GLushort indices[] = { 0, 1, 2,  0, 2, 3 };
385 
386     glVertexPointer(3, GL_FLOAT, 0, vertices);
387     glTexCoordPointer(2, GL_FIXED, 0, texCoords);
388     glClearColor(1.0, 1.0, 1.0, 1.0);
389     int nelem = sizeof(indices)/sizeof(indices[0]);
390     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
391     glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices);
392     setSurfaceMetadata(eglDisplay, eglSurface);
393     eglSwapBuffers(eglDisplay, eglSurface);
394 }
395