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