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