gl2_basic.cpp revision d9872bf424ad327861ab98390319566b25571f76
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 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 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 59static 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 66static const char gVertexShader[] = "attribute vec4 vPosition;\n" 67 "void main() {\n" 68 " gl_Position = vPosition;\n" 69 "}\n"; 70 71static 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 76GLuint 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 102GLuint 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 140GLuint gProgram; 141GLuint gvPositionHandle; 142 143bool 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 158const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 159 0.5f, -0.5f }; 160 161void 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#if 0 179 180void PrintEGLConfig(EGLDisplay dpy, EGLConfig config) { 181 int attrib[] = {EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_ALPHA_SIZE, 182 EGL_DEPTH_SIZE, EGL_SURFACE_TYPE, EGL_RENDERABLE_TYPE 183 }; 184 for(size_t i = 0; i < sizeof(attrib)/sizeof(attrib[0]); i++) { 185 int value = 0; 186 int a = attrib[i]; 187 if (eglGetConfigAttrib(dpy, config, a, &value)) { 188 printf(" 0x%04x: %d", a, value); 189 } 190 } 191 printf("\n"); 192} 193 194#endif 195 196int printEGLConfigurations(EGLDisplay dpy) { 197 EGLint numConfig = 0; 198 EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); 199 checkEglError("eglGetConfigs", returnVal); 200 if (!returnVal) { 201 return false; 202 } 203 204 printf("Number of EGL configuration: %d\n", numConfig); 205 206 EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig); 207 if (! configs) { 208 printf("Could not allocate configs.\n"); 209 return false; 210 } 211 212 returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); 213 checkEglError("eglGetConfigs", returnVal); 214 if (!returnVal) { 215 free(configs); 216 return false; 217 } 218 219#define X(VAL) {VAL, #VAL} 220 struct {EGLint attribute; const char* name;} names[] = { 221 X(EGL_BUFFER_SIZE), 222 X(EGL_RED_SIZE), 223 X(EGL_GREEN_SIZE), 224 X(EGL_BLUE_SIZE), 225 X(EGL_ALPHA_SIZE), 226 X(EGL_CONFIG_CAVEAT), 227 X(EGL_CONFIG_ID), 228 X(EGL_DEPTH_SIZE), 229 X(EGL_LEVEL), 230 X(EGL_MAX_PBUFFER_WIDTH), 231 X(EGL_MAX_PBUFFER_HEIGHT), 232 X(EGL_MAX_PBUFFER_PIXELS), 233 X(EGL_NATIVE_RENDERABLE), 234 X(EGL_NATIVE_VISUAL_ID), 235 X(EGL_NATIVE_VISUAL_TYPE), 236 X(EGL_PRESERVED_RESOURCES), 237 X(EGL_SAMPLE_BUFFERS), 238 X(EGL_SAMPLES), 239 // X(EGL_STENCIL_BITS), 240 X(EGL_SURFACE_TYPE), 241 X(EGL_TRANSPARENT_TYPE), 242 // X(EGL_TRANSPARENT_RED), 243 // X(EGL_TRANSPARENT_GREEN), 244 // X(EGL_TRANSPARENT_BLUE) 245 }; 246#undef X 247 248 for(int i = 0; i < numConfig; i++) { 249 printf("Configuration %d\n", i); 250 EGLConfig config = configs[i]; 251 for (int j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 252 EGLint value = -1; 253 returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 254 if (returnVal) { 255 printf(" %s: %d (0x%x)", names[j].name, value, value); 256 } 257 } 258 printf("\n"); 259 } 260 261 free(configs); 262 return true; 263} 264 265int main(int argc, char** argv) { 266 EGLBoolean returnValue; 267 EGLConfig myConfig = {0}; 268 269 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 270 EGLint s_configAttribs[] = { 271 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT|EGL_WINDOW_BIT, 272 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 273 EGL_NONE }; 274 EGLint majorVersion; 275 EGLint minorVersion; 276 EGLContext context; 277 EGLSurface surface; 278 EGLint w, h; 279 280 EGLDisplay dpy; 281 282 checkEglError("<init>"); 283 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 284 checkEglError("eglGetDisplay"); 285 if (dpy == EGL_NO_DISPLAY) { 286 printf("eglGetDisplay returned EGL_NO_DISPLAY.\n"); 287 return 0; 288 } 289 290 returnValue = eglInitialize(dpy, &majorVersion, &minorVersion); 291 checkEglError("eglInitialize", returnValue); 292 fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion); 293 if (returnValue != EGL_TRUE) { 294 printf("eglInitialize failed\n"); 295 return 0; 296 } 297 298 if (!printEGLConfigurations(dpy)) { 299 printf("printEGLConfigurations failed\n"); 300 return 0; 301 } 302 303 EGLNativeWindowType window = android_createDisplaySurface(); 304 returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig); 305 if (returnValue) { 306 printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue); 307 return 0; 308 } 309 310 surface = eglCreateWindowSurface(dpy, myConfig, window, NULL); 311 checkEglError("eglCreateWindowSurface"); 312 if (surface == EGL_NO_SURFACE) { 313 printf("gelCreateWindowSurface failed.\n"); 314 return 0; 315 } 316 317 context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs); 318 checkEglError("eglCreateContext"); 319 if (context == EGL_NO_CONTEXT) { 320 printf("eglCreateContext failed\n"); 321 return 0; 322 } 323 returnValue = eglMakeCurrent(dpy, surface, surface, context); 324 checkEglError("eglMakeCurrent", returnValue); 325 if (returnValue != EGL_TRUE) { 326 return 0; 327 } 328 eglQuerySurface(dpy, surface, EGL_WIDTH, &w); 329 checkEglError("eglQuerySurface"); 330 eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); 331 checkEglError("eglQuerySurface"); 332 GLint dim = w < h ? w : h; 333 334 fprintf(stderr, "Window dimensions: %d x %d\n", w, h); 335 336 printGLString("Version", GL_VERSION); 337 printGLString("Vendor", GL_VENDOR); 338 printGLString("Renderer", GL_RENDERER); 339 printGLString("Extensions", GL_EXTENSIONS); 340 341 if(!setupGraphics(w, h)) { 342 fprintf(stderr, "Could not set up graphics.\n"); 343 return 0; 344 } 345 346 for (;;) { 347 renderFrame(); 348 eglSwapBuffers(dpy, surface); 349 checkEglError("eglSwapBuffers"); 350 } 351 352 return 0; 353} 354