1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <time.h>
20 #include <sched.h>
21 #include <sys/resource.h>
22
23 #include <EGL/egl.h>
24 #include <GLES2/gl2.h>
25 #include <GLES2/gl2ext.h>
26
27 #include <utils/Timers.h>
28
29 #include <WindowSurface.h>
30 #include <EGLUtils.h>
31
32 using namespace android;
33
printGLString(const char * name,GLenum s)34 static void printGLString(const char *name, GLenum s) {
35 // fprintf(stderr, "printGLString %s, %d\n", name, s);
36 const char *v = (const char *) glGetString(s);
37 // int error = glGetError();
38 // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
39 // (unsigned int) v);
40 // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
41 // fprintf(stderr, "GL %s = %s\n", name, v);
42 // else
43 // fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
44 fprintf(stderr, "GL %s = %s\n", name, v);
45 }
46
printEGLString(EGLDisplay dpy,const char * name,GLenum s)47 static void printEGLString(EGLDisplay dpy, const char *name, GLenum s) {
48 const char *v = (const char *) eglQueryString(dpy, s);
49 fprintf(stderr, "GL %s = %s\n", name, v);
50 }
51
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)52 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
53 if (returnVal != EGL_TRUE) {
54 fprintf(stderr, "%s() returned %d\n", op, returnVal);
55 }
56
57 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
58 = eglGetError()) {
59 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
60 error);
61 }
62 }
63
checkGlError(const char * op)64 static void checkGlError(const char* op) {
65 for (GLint error = glGetError(); error; error
66 = glGetError()) {
67 fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
68 }
69 }
70
71 static const char gVertexShader[] = "attribute vec4 vPosition;\n"
72 "void main() {\n"
73 " gl_Position = vPosition;\n"
74 "}\n";
75
76 static const char gFragmentShader[] = "precision mediump float;\n"
77 "void main() {\n"
78 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
79 "}\n";
80
loadShader(GLenum shaderType,const char * pSource)81 GLuint loadShader(GLenum shaderType, const char* pSource) {
82 GLuint shader = glCreateShader(shaderType);
83 if (shader) {
84 glShaderSource(shader, 1, &pSource, NULL);
85 glCompileShader(shader);
86 GLint compiled = 0;
87 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
88 if (!compiled) {
89 GLint infoLen = 0;
90 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
91 if (infoLen) {
92 char* buf = (char*) malloc(infoLen);
93 if (buf) {
94 glGetShaderInfoLog(shader, infoLen, NULL, buf);
95 fprintf(stderr, "Could not compile shader %d:\n%s\n",
96 shaderType, buf);
97 free(buf);
98 }
99 glDeleteShader(shader);
100 shader = 0;
101 }
102 }
103 }
104 return shader;
105 }
106
createProgram(const char * pVertexSource,const char * pFragmentSource)107 GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
108 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
109 if (!vertexShader) {
110 return 0;
111 }
112
113 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
114 if (!pixelShader) {
115 return 0;
116 }
117
118 GLuint program = glCreateProgram();
119 if (program) {
120 glAttachShader(program, vertexShader);
121 checkGlError("glAttachShader");
122 glAttachShader(program, pixelShader);
123 checkGlError("glAttachShader");
124 glLinkProgram(program);
125 GLint linkStatus = GL_FALSE;
126 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
127 if (linkStatus != GL_TRUE) {
128 GLint bufLength = 0;
129 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
130 if (bufLength) {
131 char* buf = (char*) malloc(bufLength);
132 if (buf) {
133 glGetProgramInfoLog(program, bufLength, NULL, buf);
134 fprintf(stderr, "Could not link program:\n%s\n", buf);
135 free(buf);
136 }
137 }
138 glDeleteProgram(program);
139 program = 0;
140 }
141 }
142 return program;
143 }
144
145 GLuint gProgram;
146 GLuint gvPositionHandle;
147
setupGraphics(int w,int h)148 bool setupGraphics(int w, int h) {
149 gProgram = createProgram(gVertexShader, gFragmentShader);
150 if (!gProgram) {
151 return false;
152 }
153 gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
154 checkGlError("glGetAttribLocation");
155 fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n",
156 gvPositionHandle);
157
158 glViewport(0, 0, w, h);
159 checkGlError("glViewport");
160 return true;
161 }
162
163 const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
164 0.5f, -0.5f };
165
renderFrame()166 void renderFrame() {
167 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
168 checkGlError("glClearColor");
169 glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
170 checkGlError("glClear");
171
172 glUseProgram(gProgram);
173 checkGlError("glUseProgram");
174
175 glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
176 checkGlError("glVertexAttribPointer");
177 glEnableVertexAttribArray(gvPositionHandle);
178 checkGlError("glEnableVertexAttribArray");
179 glDrawArrays(GL_TRIANGLES, 0, 3);
180 checkGlError("glDrawArrays");
181 }
182
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)183 void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
184
185 #define X(VAL) {VAL, #VAL}
186 struct {EGLint attribute; const char* name;} names[] = {
187 X(EGL_BUFFER_SIZE),
188 X(EGL_ALPHA_SIZE),
189 X(EGL_BLUE_SIZE),
190 X(EGL_GREEN_SIZE),
191 X(EGL_RED_SIZE),
192 X(EGL_DEPTH_SIZE),
193 X(EGL_STENCIL_SIZE),
194 X(EGL_CONFIG_CAVEAT),
195 X(EGL_CONFIG_ID),
196 X(EGL_LEVEL),
197 X(EGL_MAX_PBUFFER_HEIGHT),
198 X(EGL_MAX_PBUFFER_PIXELS),
199 X(EGL_MAX_PBUFFER_WIDTH),
200 X(EGL_NATIVE_RENDERABLE),
201 X(EGL_NATIVE_VISUAL_ID),
202 X(EGL_NATIVE_VISUAL_TYPE),
203 X(EGL_SAMPLES),
204 X(EGL_SAMPLE_BUFFERS),
205 X(EGL_SURFACE_TYPE),
206 X(EGL_TRANSPARENT_TYPE),
207 X(EGL_TRANSPARENT_RED_VALUE),
208 X(EGL_TRANSPARENT_GREEN_VALUE),
209 X(EGL_TRANSPARENT_BLUE_VALUE),
210 X(EGL_BIND_TO_TEXTURE_RGB),
211 X(EGL_BIND_TO_TEXTURE_RGBA),
212 X(EGL_MIN_SWAP_INTERVAL),
213 X(EGL_MAX_SWAP_INTERVAL),
214 X(EGL_LUMINANCE_SIZE),
215 X(EGL_ALPHA_MASK_SIZE),
216 X(EGL_COLOR_BUFFER_TYPE),
217 X(EGL_RENDERABLE_TYPE),
218 X(EGL_CONFORMANT),
219 };
220 #undef X
221
222 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
223 EGLint value = -1;
224 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
225 EGLint error = eglGetError();
226 if (returnVal && error == EGL_SUCCESS) {
227 printf(" %s: ", names[j].name);
228 printf("%d (0x%x)", value, value);
229 }
230 }
231 printf("\n");
232 }
233
printEGLConfigurations(EGLDisplay dpy)234 int printEGLConfigurations(EGLDisplay dpy) {
235 EGLint numConfig = 0;
236 EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
237 checkEglError("eglGetConfigs", returnVal);
238 if (!returnVal) {
239 return false;
240 }
241
242 printf("Number of EGL configuration: %d\n", numConfig);
243
244 EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
245 if (! configs) {
246 printf("Could not allocate configs.\n");
247 return false;
248 }
249
250 returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
251 checkEglError("eglGetConfigs", returnVal);
252 if (!returnVal) {
253 free(configs);
254 return false;
255 }
256
257 for(int i = 0; i < numConfig; i++) {
258 printf("Configuration %d\n", i);
259 printEGLConfiguration(dpy, configs[i]);
260 }
261
262 free(configs);
263 return true;
264 }
265
main(int argc,char ** argv)266 int main(int argc, char** argv) {
267 EGLBoolean returnValue;
268 EGLConfig myConfig = {0};
269
270 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
271 EGLint s_configAttribs[] = {
272 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
273 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
274 EGL_NONE };
275 EGLint majorVersion;
276 EGLint minorVersion;
277 EGLContext context;
278 EGLSurface surface;
279 EGLint w, h;
280
281 EGLDisplay dpy;
282
283 checkEglError("<init>");
284 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
285 checkEglError("eglGetDisplay");
286 if (dpy == EGL_NO_DISPLAY) {
287 printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
288 return 0;
289 }
290
291 returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
292 checkEglError("eglInitialize", returnValue);
293 fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
294 if (returnValue != EGL_TRUE) {
295 printf("eglInitialize failed\n");
296 return 0;
297 }
298
299 if (!printEGLConfigurations(dpy)) {
300 printf("printEGLConfigurations failed\n");
301 return 0;
302 }
303
304 checkEglError("printEGLConfigurations");
305
306 WindowSurface windowSurface;
307 EGLNativeWindowType window = windowSurface.getSurface();
308 returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
309 if (returnValue) {
310 printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
311 return 0;
312 }
313
314 checkEglError("EGLUtils::selectConfigForNativeWindow");
315
316 printf("Chose this configuration:\n");
317 printEGLConfiguration(dpy, myConfig);
318
319 surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
320 checkEglError("eglCreateWindowSurface");
321 if (surface == EGL_NO_SURFACE) {
322 printf("gelCreateWindowSurface failed.\n");
323 return 0;
324 }
325
326 context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
327 checkEglError("eglCreateContext");
328 if (context == EGL_NO_CONTEXT) {
329 printf("eglCreateContext failed\n");
330 return 0;
331 }
332 returnValue = eglMakeCurrent(dpy, surface, surface, context);
333 checkEglError("eglMakeCurrent", returnValue);
334 if (returnValue != EGL_TRUE) {
335 return 0;
336 }
337 eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
338 checkEglError("eglQuerySurface");
339 eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
340 checkEglError("eglQuerySurface");
341 GLint dim = w < h ? w : h;
342
343 fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
344
345 printGLString("Version", GL_VERSION);
346 printGLString("Vendor", GL_VENDOR);
347 printGLString("Renderer", GL_RENDERER);
348 printGLString("Extensions", GL_EXTENSIONS);
349 printEGLString(dpy, "EGL Extensions", EGL_EXTENSIONS);
350
351 if(!setupGraphics(w, h)) {
352 fprintf(stderr, "Could not set up graphics.\n");
353 return 0;
354 }
355
356 for (;;) {
357 renderFrame();
358 eglSwapBuffers(dpy, surface);
359 checkEglError("eglSwapBuffers");
360 }
361
362 return 0;
363 }
364