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 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 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 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 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 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 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 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 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 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 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