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 <ui/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_PRESERVED_RESOURCES), 199 X(EGL_SAMPLES), 200 X(EGL_SAMPLE_BUFFERS), 201 X(EGL_SURFACE_TYPE), 202 X(EGL_TRANSPARENT_TYPE), 203 X(EGL_TRANSPARENT_RED_VALUE), 204 X(EGL_TRANSPARENT_GREEN_VALUE), 205 X(EGL_TRANSPARENT_BLUE_VALUE), 206 X(EGL_BIND_TO_TEXTURE_RGB), 207 X(EGL_BIND_TO_TEXTURE_RGBA), 208 X(EGL_MIN_SWAP_INTERVAL), 209 X(EGL_MAX_SWAP_INTERVAL), 210 X(EGL_LUMINANCE_SIZE), 211 X(EGL_ALPHA_MASK_SIZE), 212 X(EGL_COLOR_BUFFER_TYPE), 213 X(EGL_RENDERABLE_TYPE), 214 X(EGL_CONFORMANT), 215 }; 216 #undef X 217 218 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 219 EGLint value = -1; 220 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 221 EGLint error = eglGetError(); 222 if (returnVal && error == EGL_SUCCESS) { 223 printf(" %s: ", names[j].name); 224 printf("%d (0x%x)", value, value); 225 } 226 } 227 printf("\n"); 228 } 229 230 int printEGLConfigurations(EGLDisplay dpy) { 231 EGLint numConfig = 0; 232 EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); 233 checkEglError("eglGetConfigs", returnVal); 234 if (!returnVal) { 235 return false; 236 } 237 238 printf("Number of EGL configuration: %d\n", numConfig); 239 240 EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig); 241 if (! configs) { 242 printf("Could not allocate configs.\n"); 243 return false; 244 } 245 246 returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig); 247 checkEglError("eglGetConfigs", returnVal); 248 if (!returnVal) { 249 free(configs); 250 return false; 251 } 252 253 for(int i = 0; i < numConfig; i++) { 254 printf("Configuration %d\n", i); 255 printEGLConfiguration(dpy, configs[i]); 256 } 257 258 free(configs); 259 return true; 260 } 261 262 int main(int argc, char** argv) { 263 EGLBoolean returnValue; 264 EGLConfig myConfig = {0}; 265 266 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 267 EGLint s_configAttribs[] = { 268 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 269 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 270 EGL_NONE }; 271 EGLint majorVersion; 272 EGLint minorVersion; 273 EGLContext context; 274 EGLSurface surface; 275 EGLint w, h; 276 277 EGLDisplay dpy; 278 279 checkEglError("<init>"); 280 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 281 checkEglError("eglGetDisplay"); 282 if (dpy == EGL_NO_DISPLAY) { 283 printf("eglGetDisplay returned EGL_NO_DISPLAY.\n"); 284 return 0; 285 } 286 287 returnValue = eglInitialize(dpy, &majorVersion, &minorVersion); 288 checkEglError("eglInitialize", returnValue); 289 fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion); 290 if (returnValue != EGL_TRUE) { 291 printf("eglInitialize failed\n"); 292 return 0; 293 } 294 295 if (!printEGLConfigurations(dpy)) { 296 printf("printEGLConfigurations failed\n"); 297 return 0; 298 } 299 300 checkEglError("printEGLConfigurations"); 301 302 EGLNativeWindowType window = android_createDisplaySurface(); 303 returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig); 304 if (returnValue) { 305 printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue); 306 return 0; 307 } 308 309 checkEglError("EGLUtils::selectConfigForNativeWindow"); 310 311 printf("Chose this configuration:\n"); 312 printEGLConfiguration(dpy, myConfig); 313 314 surface = eglCreateWindowSurface(dpy, myConfig, window, NULL); 315 checkEglError("eglCreateWindowSurface"); 316 if (surface == EGL_NO_SURFACE) { 317 printf("gelCreateWindowSurface failed.\n"); 318 return 0; 319 } 320 321 context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs); 322 checkEglError("eglCreateContext"); 323 if (context == EGL_NO_CONTEXT) { 324 printf("eglCreateContext failed\n"); 325 return 0; 326 } 327 returnValue = eglMakeCurrent(dpy, surface, surface, context); 328 checkEglError("eglMakeCurrent", returnValue); 329 if (returnValue != EGL_TRUE) { 330 return 0; 331 } 332 eglQuerySurface(dpy, surface, EGL_WIDTH, &w); 333 checkEglError("eglQuerySurface"); 334 eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); 335 checkEglError("eglQuerySurface"); 336 GLint dim = w < h ? w : h; 337 338 fprintf(stderr, "Window dimensions: %d x %d\n", w, h); 339 340 printGLString("Version", GL_VERSION); 341 printGLString("Vendor", GL_VENDOR); 342 printGLString("Renderer", GL_RENDERER); 343 printGLString("Extensions", GL_EXTENSIONS); 344 345 if(!setupGraphics(w, h)) { 346 fprintf(stderr, "Could not set up graphics.\n"); 347 return 0; 348 } 349 350 for (;;) { 351 renderFrame(); 352 eglSwapBuffers(dpy, surface); 353 checkEglError("eglSwapBuffers"); 354 } 355 356 return 0; 357 } 358