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 <ui/FramebufferNativeWindow.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
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)47 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
48 if (returnVal != EGL_TRUE) {
49 fprintf(stderr, "%s() returned %d\n", op, returnVal);
50 }
51
52 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
53 = eglGetError()) {
54 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
55 error);
56 }
57 }
58
checkGlError(const char * op)59 static void checkGlError(const char* op) {
60 for (GLint error = glGetError(); error; error
61 = glGetError()) {
62 fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
63 }
64 }
65
66 static const char gVertexShader[] = "attribute vec4 vPosition;\n"
67 "void main() {\n"
68 " gl_Position = vPosition;\n"
69 "}\n";
70
71 static const char gFragmentShader[] = "precision mediump float;\n"
72 "void main() {\n"
73 " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
74 "}\n";
75
loadShader(GLenum shaderType,const char * pSource)76 GLuint loadShader(GLenum shaderType, const char* pSource) {
77 GLuint shader = glCreateShader(shaderType);
78 if (shader) {
79 glShaderSource(shader, 1, &pSource, NULL);
80 glCompileShader(shader);
81 GLint compiled = 0;
82 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
83 if (!compiled) {
84 GLint infoLen = 0;
85 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
86 if (infoLen) {
87 char* buf = (char*) malloc(infoLen);
88 if (buf) {
89 glGetShaderInfoLog(shader, infoLen, NULL, buf);
90 fprintf(stderr, "Could not compile shader %d:\n%s\n",
91 shaderType, buf);
92 free(buf);
93 }
94 glDeleteShader(shader);
95 shader = 0;
96 }
97 }
98 }
99 return shader;
100 }
101
createProgram(const char * pVertexSource,const char * pFragmentSource)102 GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
103 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
104 if (!vertexShader) {
105 return 0;
106 }
107
108 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
109 if (!pixelShader) {
110 return 0;
111 }
112
113 GLuint program = glCreateProgram();
114 if (program) {
115 glAttachShader(program, vertexShader);
116 checkGlError("glAttachShader");
117 glAttachShader(program, pixelShader);
118 checkGlError("glAttachShader");
119 glLinkProgram(program);
120 GLint linkStatus = GL_FALSE;
121 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
122 if (linkStatus != GL_TRUE) {
123 GLint bufLength = 0;
124 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
125 if (bufLength) {
126 char* buf = (char*) malloc(bufLength);
127 if (buf) {
128 glGetProgramInfoLog(program, bufLength, NULL, buf);
129 fprintf(stderr, "Could not link program:\n%s\n", buf);
130 free(buf);
131 }
132 }
133 glDeleteProgram(program);
134 program = 0;
135 }
136 }
137 return program;
138 }
139
140 GLuint gProgram;
141 GLuint gvPositionHandle;
142
setupGraphics(int w,int h)143 bool setupGraphics(int w, int h) {
144 gProgram = createProgram(gVertexShader, gFragmentShader);
145 if (!gProgram) {
146 return false;
147 }
148 gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
149 checkGlError("glGetAttribLocation");
150 fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n",
151 gvPositionHandle);
152
153 glViewport(0, 0, w, h);
154 checkGlError("glViewport");
155 return true;
156 }
157
158 const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
159 0.5f, -0.5f };
160
renderFrame()161 void renderFrame() {
162 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
163 checkGlError("glClearColor");
164 glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
165 checkGlError("glClear");
166
167 glUseProgram(gProgram);
168 checkGlError("glUseProgram");
169
170 glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
171 checkGlError("glVertexAttribPointer");
172 glEnableVertexAttribArray(gvPositionHandle);
173 checkGlError("glEnableVertexAttribArray");
174 glDrawArrays(GL_TRIANGLES, 0, 3);
175 checkGlError("glDrawArrays");
176 }
177
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)178 void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
179
180 #define X(VAL) {VAL, #VAL}
181 struct {EGLint attribute; const char* name;} names[] = {
182 X(EGL_BUFFER_SIZE),
183 X(EGL_ALPHA_SIZE),
184 X(EGL_BLUE_SIZE),
185 X(EGL_GREEN_SIZE),
186 X(EGL_RED_SIZE),
187 X(EGL_DEPTH_SIZE),
188 X(EGL_STENCIL_SIZE),
189 X(EGL_CONFIG_CAVEAT),
190 X(EGL_CONFIG_ID),
191 X(EGL_LEVEL),
192 X(EGL_MAX_PBUFFER_HEIGHT),
193 X(EGL_MAX_PBUFFER_PIXELS),
194 X(EGL_MAX_PBUFFER_WIDTH),
195 X(EGL_NATIVE_RENDERABLE),
196 X(EGL_NATIVE_VISUAL_ID),
197 X(EGL_NATIVE_VISUAL_TYPE),
198 X(EGL_SAMPLES),
199 X(EGL_SAMPLE_BUFFERS),
200 X(EGL_SURFACE_TYPE),
201 X(EGL_TRANSPARENT_TYPE),
202 X(EGL_TRANSPARENT_RED_VALUE),
203 X(EGL_TRANSPARENT_GREEN_VALUE),
204 X(EGL_TRANSPARENT_BLUE_VALUE),
205 X(EGL_BIND_TO_TEXTURE_RGB),
206 X(EGL_BIND_TO_TEXTURE_RGBA),
207 X(EGL_MIN_SWAP_INTERVAL),
208 X(EGL_MAX_SWAP_INTERVAL),
209 X(EGL_LUMINANCE_SIZE),
210 X(EGL_ALPHA_MASK_SIZE),
211 X(EGL_COLOR_BUFFER_TYPE),
212 X(EGL_RENDERABLE_TYPE),
213 X(EGL_CONFORMANT),
214 };
215 #undef X
216
217 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
218 EGLint value = -1;
219 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
220 EGLint error = eglGetError();
221 if (returnVal && error == EGL_SUCCESS) {
222 printf(" %s: ", names[j].name);
223 printf("%d (0x%x)", value, value);
224 }
225 }
226 printf("\n");
227 }
228
printEGLConfigurations(EGLDisplay dpy)229 int printEGLConfigurations(EGLDisplay dpy) {
230 EGLint numConfig = 0;
231 EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
232 checkEglError("eglGetConfigs", returnVal);
233 if (!returnVal) {
234 return false;
235 }
236
237 printf("Number of EGL configuration: %d\n", numConfig);
238
239 EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
240 if (! configs) {
241 printf("Could not allocate configs.\n");
242 return false;
243 }
244
245 returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
246 checkEglError("eglGetConfigs", returnVal);
247 if (!returnVal) {
248 free(configs);
249 return false;
250 }
251
252 for(int i = 0; i < numConfig; i++) {
253 printf("Configuration %d\n", i);
254 printEGLConfiguration(dpy, configs[i]);
255 }
256
257 free(configs);
258 return true;
259 }
260
main(int argc,char ** argv)261 int main(int argc, char** argv) {
262 EGLBoolean returnValue;
263 EGLConfig myConfig = {0};
264
265 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
266 EGLint s_configAttribs[] = {
267 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
268 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
269 EGL_NONE };
270 EGLint majorVersion;
271 EGLint minorVersion;
272 EGLContext context;
273 EGLSurface surface;
274 EGLint w, h;
275
276 EGLDisplay dpy;
277
278 checkEglError("<init>");
279 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
280 checkEglError("eglGetDisplay");
281 if (dpy == EGL_NO_DISPLAY) {
282 printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
283 return 0;
284 }
285
286 returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
287 checkEglError("eglInitialize", returnValue);
288 fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
289 if (returnValue != EGL_TRUE) {
290 printf("eglInitialize failed\n");
291 return 0;
292 }
293
294 if (!printEGLConfigurations(dpy)) {
295 printf("printEGLConfigurations failed\n");
296 return 0;
297 }
298
299 checkEglError("printEGLConfigurations");
300
301 EGLNativeWindowType window = android_createDisplaySurface();
302 returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
303 if (returnValue) {
304 printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
305 return 0;
306 }
307
308 checkEglError("EGLUtils::selectConfigForNativeWindow");
309
310 printf("Chose this configuration:\n");
311 printEGLConfiguration(dpy, myConfig);
312
313 surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
314 checkEglError("eglCreateWindowSurface");
315 if (surface == EGL_NO_SURFACE) {
316 printf("gelCreateWindowSurface failed.\n");
317 return 0;
318 }
319
320 context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
321 checkEglError("eglCreateContext");
322 if (context == EGL_NO_CONTEXT) {
323 printf("eglCreateContext failed\n");
324 return 0;
325 }
326 returnValue = eglMakeCurrent(dpy, surface, surface, context);
327 checkEglError("eglMakeCurrent", returnValue);
328 if (returnValue != EGL_TRUE) {
329 return 0;
330 }
331 eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
332 checkEglError("eglQuerySurface");
333 eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
334 checkEglError("eglQuerySurface");
335 GLint dim = w < h ? w : h;
336
337 fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
338
339 printGLString("Version", GL_VERSION);
340 printGLString("Vendor", GL_VENDOR);
341 printGLString("Renderer", GL_RENDERER);
342 printGLString("Extensions", GL_EXTENSIONS);
343
344 if(!setupGraphics(w, h)) {
345 fprintf(stderr, "Could not set up graphics.\n");
346 return 0;
347 }
348
349 for (;;) {
350 renderFrame();
351 eglSwapBuffers(dpy, surface);
352 checkEglError("eglSwapBuffers");
353 }
354
355 return 0;
356 }
357