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 32using namespace android; 33 34static 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 47static 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 52static 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 64static 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 71static const char gVertexShader[] = "attribute vec4 vPosition;\n" 72 "void main() {\n" 73 " gl_Position = vPosition;\n" 74 "}\n"; 75 76static 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 81GLuint 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 107GLuint 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 145GLuint gProgram; 146GLuint gvPositionHandle; 147 148bool 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 163const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 164 0.5f, -0.5f }; 165 166void 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 183void 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 234int 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 266int 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