1868a0aff31a5cccd285117131219f572fbf07362Romain Guy/* 2868a0aff31a5cccd285117131219f572fbf07362Romain Guy * Copyright (C) 2007 The Android Open Source Project 3868a0aff31a5cccd285117131219f572fbf07362Romain Guy * 4868a0aff31a5cccd285117131219f572fbf07362Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5868a0aff31a5cccd285117131219f572fbf07362Romain Guy * you may not use this file except in compliance with the License. 6868a0aff31a5cccd285117131219f572fbf07362Romain Guy * You may obtain a copy of the License at 7868a0aff31a5cccd285117131219f572fbf07362Romain Guy * 8868a0aff31a5cccd285117131219f572fbf07362Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9868a0aff31a5cccd285117131219f572fbf07362Romain Guy * 10868a0aff31a5cccd285117131219f572fbf07362Romain Guy * Unless required by applicable law or agreed to in writing, software 11868a0aff31a5cccd285117131219f572fbf07362Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12868a0aff31a5cccd285117131219f572fbf07362Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13868a0aff31a5cccd285117131219f572fbf07362Romain Guy * See the License for the specific language governing permissions and 14868a0aff31a5cccd285117131219f572fbf07362Romain Guy * limitations under the License. 15868a0aff31a5cccd285117131219f572fbf07362Romain Guy */ 16868a0aff31a5cccd285117131219f572fbf07362Romain Guy 17868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <stdlib.h> 18868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <stdio.h> 19868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <time.h> 20868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <sched.h> 21868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <sys/resource.h> 22868a0aff31a5cccd285117131219f572fbf07362Romain Guy 23868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <EGL/egl.h> 24868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <GLES2/gl2.h> 25868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <GLES2/gl2ext.h> 26868a0aff31a5cccd285117131219f572fbf07362Romain Guy 27868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <utils/Timers.h> 28868a0aff31a5cccd285117131219f572fbf07362Romain Guy 29868a0aff31a5cccd285117131219f572fbf07362Romain Guy#include <ui/FramebufferNativeWindow.h> 30870b8aa15cb5c722b5d8eb7726eaa5f1a7c23d69Mathias Agopian#include "EGLUtils.h" 31868a0aff31a5cccd285117131219f572fbf07362Romain Guy 32868a0aff31a5cccd285117131219f572fbf07362Romain Guyusing namespace android; 33868a0aff31a5cccd285117131219f572fbf07362Romain Guy 34868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic void printGLString(const char *name, GLenum s) { 35868a0aff31a5cccd285117131219f572fbf07362Romain Guy // fprintf(stderr, "printGLString %s, %d\n", name, s); 36868a0aff31a5cccd285117131219f572fbf07362Romain Guy const char *v = (const char *) glGetString(s); 37868a0aff31a5cccd285117131219f572fbf07362Romain Guy // int error = glGetError(); 38868a0aff31a5cccd285117131219f572fbf07362Romain Guy // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error, 39868a0aff31a5cccd285117131219f572fbf07362Romain Guy // (unsigned int) v); 40868a0aff31a5cccd285117131219f572fbf07362Romain Guy // if ((v < (const char*) 0) || (v > (const char*) 0x10000)) 41868a0aff31a5cccd285117131219f572fbf07362Romain Guy // fprintf(stderr, "GL %s = %s\n", name, v); 42868a0aff31a5cccd285117131219f572fbf07362Romain Guy // else 43868a0aff31a5cccd285117131219f572fbf07362Romain Guy // fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v); 44868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "GL %s = %s\n", name, v); 45868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 46868a0aff31a5cccd285117131219f572fbf07362Romain Guy 47868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 48868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (returnVal != EGL_TRUE) { 49868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "%s() returned %d\n", op, returnVal); 50868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 51868a0aff31a5cccd285117131219f572fbf07362Romain Guy 52868a0aff31a5cccd285117131219f572fbf07362Romain Guy for (EGLint error = eglGetError(); error != EGL_SUCCESS; error 53868a0aff31a5cccd285117131219f572fbf07362Romain Guy = eglGetError()) { 54868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), 55868a0aff31a5cccd285117131219f572fbf07362Romain Guy error); 56868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 57868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 58868a0aff31a5cccd285117131219f572fbf07362Romain Guy 59868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic void checkGlError(const char* op) { 60868a0aff31a5cccd285117131219f572fbf07362Romain Guy for (GLint error = glGetError(); error; error 61868a0aff31a5cccd285117131219f572fbf07362Romain Guy = glGetError()) { 62868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "after %s() glError (0x%x)\n", op, error); 63868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 64868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 65868a0aff31a5cccd285117131219f572fbf07362Romain Guy 66868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic const char gVertexShader[] = "attribute vec4 vPosition;\n" 67868a0aff31a5cccd285117131219f572fbf07362Romain Guy "void main() {\n" 68868a0aff31a5cccd285117131219f572fbf07362Romain Guy " gl_Position = vPosition;\n" 69868a0aff31a5cccd285117131219f572fbf07362Romain Guy "}\n"; 70868a0aff31a5cccd285117131219f572fbf07362Romain Guy 71868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic const char gFragmentShader[] = "precision mediump float;\n" 72868a0aff31a5cccd285117131219f572fbf07362Romain Guy "void main() {\n" 73868a0aff31a5cccd285117131219f572fbf07362Romain Guy " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.5);\n" 74868a0aff31a5cccd285117131219f572fbf07362Romain Guy "}\n"; 75868a0aff31a5cccd285117131219f572fbf07362Romain Guy 76868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint loadShader(GLenum shaderType, const char* pSource) { 77868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLuint shader = glCreateShader(shaderType); 78868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (shader) { 79868a0aff31a5cccd285117131219f572fbf07362Romain Guy glShaderSource(shader, 1, &pSource, NULL); 80868a0aff31a5cccd285117131219f572fbf07362Romain Guy glCompileShader(shader); 81868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLint compiled = 0; 82868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 83868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!compiled) { 84868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLint infoLen = 0; 85868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 86868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (infoLen) { 87868a0aff31a5cccd285117131219f572fbf07362Romain Guy char* buf = (char*) malloc(infoLen); 88868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (buf) { 89868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetShaderInfoLog(shader, infoLen, NULL, buf); 90868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "Could not compile shader %d:\n%s\n", 91868a0aff31a5cccd285117131219f572fbf07362Romain Guy shaderType, buf); 92868a0aff31a5cccd285117131219f572fbf07362Romain Guy free(buf); 93868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 94868a0aff31a5cccd285117131219f572fbf07362Romain Guy glDeleteShader(shader); 95868a0aff31a5cccd285117131219f572fbf07362Romain Guy shader = 0; 96868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 97868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 98868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 99868a0aff31a5cccd285117131219f572fbf07362Romain Guy return shader; 100868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 101868a0aff31a5cccd285117131219f572fbf07362Romain Guy 102868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { 103868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); 104868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!vertexShader) { 105868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 106868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 107868a0aff31a5cccd285117131219f572fbf07362Romain Guy 108868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); 109868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!pixelShader) { 110868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 111868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 112868a0aff31a5cccd285117131219f572fbf07362Romain Guy 113868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLuint program = glCreateProgram(); 114868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (program) { 115868a0aff31a5cccd285117131219f572fbf07362Romain Guy glAttachShader(program, vertexShader); 116868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glAttachShader"); 117868a0aff31a5cccd285117131219f572fbf07362Romain Guy glAttachShader(program, pixelShader); 118868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glAttachShader"); 119868a0aff31a5cccd285117131219f572fbf07362Romain Guy glLinkProgram(program); 120868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLint linkStatus = GL_FALSE; 121868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 122868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (linkStatus != GL_TRUE) { 123868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLint bufLength = 0; 124868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); 125868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (bufLength) { 126868a0aff31a5cccd285117131219f572fbf07362Romain Guy char* buf = (char*) malloc(bufLength); 127868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (buf) { 128868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGetProgramInfoLog(program, bufLength, NULL, buf); 129868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "Could not link program:\n%s\n", buf); 130868a0aff31a5cccd285117131219f572fbf07362Romain Guy free(buf); 131868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 132868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 133868a0aff31a5cccd285117131219f572fbf07362Romain Guy glDeleteProgram(program); 134868a0aff31a5cccd285117131219f572fbf07362Romain Guy program = 0; 135868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 136868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 137868a0aff31a5cccd285117131219f572fbf07362Romain Guy return program; 138868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 139868a0aff31a5cccd285117131219f572fbf07362Romain Guy 140868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gProgram; 141868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gTextureProgram; 142868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gvPositionHandle; 143868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gvTexturePositionHandle; 144868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gvTextureTexCoordsHandle; 145868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gvTextureSamplerHandle; 146868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gFbo; 147868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gTexture; 148868a0aff31a5cccd285117131219f572fbf07362Romain GuyGLuint gBufferTexture; 149868a0aff31a5cccd285117131219f572fbf07362Romain Guy 150868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic const char gSimpleVS[] = 151868a0aff31a5cccd285117131219f572fbf07362Romain Guy "attribute vec4 position;\n" 152868a0aff31a5cccd285117131219f572fbf07362Romain Guy "attribute vec2 texCoords;\n" 153868a0aff31a5cccd285117131219f572fbf07362Romain Guy "varying vec2 outTexCoords;\n" 154868a0aff31a5cccd285117131219f572fbf07362Romain Guy "\nvoid main(void) {\n" 155868a0aff31a5cccd285117131219f572fbf07362Romain Guy " outTexCoords = texCoords;\n" 156868a0aff31a5cccd285117131219f572fbf07362Romain Guy " gl_Position = position;\n" 157868a0aff31a5cccd285117131219f572fbf07362Romain Guy "}\n\n"; 158868a0aff31a5cccd285117131219f572fbf07362Romain Guystatic const char gSimpleFS[] = 159868a0aff31a5cccd285117131219f572fbf07362Romain Guy "precision mediump float;\n\n" 160868a0aff31a5cccd285117131219f572fbf07362Romain Guy "varying vec2 outTexCoords;\n" 161868a0aff31a5cccd285117131219f572fbf07362Romain Guy "uniform sampler2D texture;\n" 162868a0aff31a5cccd285117131219f572fbf07362Romain Guy "\nvoid main(void) {\n" 163868a0aff31a5cccd285117131219f572fbf07362Romain Guy " gl_FragColor = texture2D(texture, outTexCoords);\n" 164868a0aff31a5cccd285117131219f572fbf07362Romain Guy "}\n\n"; 165868a0aff31a5cccd285117131219f572fbf07362Romain Guy 166868a0aff31a5cccd285117131219f572fbf07362Romain Guybool setupGraphics(int w, int h) { 167868a0aff31a5cccd285117131219f572fbf07362Romain Guy gProgram = createProgram(gVertexShader, gFragmentShader); 168868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!gProgram) { 169868a0aff31a5cccd285117131219f572fbf07362Romain Guy return false; 170868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 171868a0aff31a5cccd285117131219f572fbf07362Romain Guy gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); 172868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glGetAttribLocation"); 173868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); 174868a0aff31a5cccd285117131219f572fbf07362Romain Guy 175868a0aff31a5cccd285117131219f572fbf07362Romain Guy gTextureProgram = createProgram(gSimpleVS, gSimpleFS); 176868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!gTextureProgram) { 177868a0aff31a5cccd285117131219f572fbf07362Romain Guy return false; 178868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 179868a0aff31a5cccd285117131219f572fbf07362Romain Guy gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position"); 180868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glGetAttribLocation"); 181868a0aff31a5cccd285117131219f572fbf07362Romain Guy gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords"); 182868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glGetAttribLocation"); 183868a0aff31a5cccd285117131219f572fbf07362Romain Guy gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture"); 184868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glGetAttribLocation"); 185868a0aff31a5cccd285117131219f572fbf07362Romain Guy 186868a0aff31a5cccd285117131219f572fbf07362Romain Guy glActiveTexture(GL_TEXTURE0); 187868a0aff31a5cccd285117131219f572fbf07362Romain Guy 188868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGenTextures(1, &gTexture); 189868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindTexture(GL_TEXTURE_2D, gTexture); 190868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 191868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 192868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 193868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 194868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 195868a0aff31a5cccd285117131219f572fbf07362Romain Guy 196868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGenTextures(1, &gBufferTexture); 197868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindTexture(GL_TEXTURE_2D, gBufferTexture); 198868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 199868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 200868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 201868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 202868a0aff31a5cccd285117131219f572fbf07362Romain Guy glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 203868a0aff31a5cccd285117131219f572fbf07362Romain Guy 204868a0aff31a5cccd285117131219f572fbf07362Romain Guy glGenFramebuffers(1, &gFbo); 205868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, gFbo); 206868a0aff31a5cccd285117131219f572fbf07362Romain Guy glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gTexture, 0); 207868a0aff31a5cccd285117131219f572fbf07362Romain Guy 208868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, 0); 209868a0aff31a5cccd285117131219f572fbf07362Romain Guy 210868a0aff31a5cccd285117131219f572fbf07362Romain Guy glViewport(0, 0, w, h); 211868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glViewport"); 212868a0aff31a5cccd285117131219f572fbf07362Romain Guy return true; 213868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 214868a0aff31a5cccd285117131219f572fbf07362Romain Guy 215868a0aff31a5cccd285117131219f572fbf07362Romain Guyconst GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 216868a0aff31a5cccd285117131219f572fbf07362Romain Guy 0.5f, -0.5f }; 217868a0aff31a5cccd285117131219f572fbf07362Romain Guy 218868a0aff31a5cccd285117131219f572fbf07362Romain Guyconst GLint FLOAT_SIZE_BYTES = 4; 219868a0aff31a5cccd285117131219f572fbf07362Romain Guyconst GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 220868a0aff31a5cccd285117131219f572fbf07362Romain Guyconst GLfloat gTriangleVerticesData[] = { 221868a0aff31a5cccd285117131219f572fbf07362Romain Guy // X, Y, Z, U, V 222868a0aff31a5cccd285117131219f572fbf07362Romain Guy -1.0f, -1.0f, 0, 0.f, 0.f, 223868a0aff31a5cccd285117131219f572fbf07362Romain Guy 1.0f, -1.0f, 0, 1.f, 0.f, 224868a0aff31a5cccd285117131219f572fbf07362Romain Guy -1.0f, 1.0f, 0, 0.f, 1.f, 225868a0aff31a5cccd285117131219f572fbf07362Romain Guy 1.0f, 1.0f, 0, 1.f, 1.f, 226868a0aff31a5cccd285117131219f572fbf07362Romain Guy}; 227868a0aff31a5cccd285117131219f572fbf07362Romain Guy 228868a0aff31a5cccd285117131219f572fbf07362Romain Guyvoid renderFrame(GLint w, GLint h) { 229868a0aff31a5cccd285117131219f572fbf07362Romain Guy glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 230868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glClearColor"); 231868a0aff31a5cccd285117131219f572fbf07362Romain Guy glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 232868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glClear"); 233868a0aff31a5cccd285117131219f572fbf07362Romain Guy 234868a0aff31a5cccd285117131219f572fbf07362Romain Guy // Bind FBO and draw into it 235868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, gFbo); 236868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glBindFramebuffer"); 237868a0aff31a5cccd285117131219f572fbf07362Romain Guy 238868a0aff31a5cccd285117131219f572fbf07362Romain Guy glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 239868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glClearColor"); 240868a0aff31a5cccd285117131219f572fbf07362Romain Guy glClear(GL_COLOR_BUFFER_BIT); 241868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glClear"); 242868a0aff31a5cccd285117131219f572fbf07362Romain Guy 243868a0aff31a5cccd285117131219f572fbf07362Romain Guy glUseProgram(gProgram); 244868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glUseProgram"); 245868a0aff31a5cccd285117131219f572fbf07362Romain Guy 246868a0aff31a5cccd285117131219f572fbf07362Romain Guy glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); 247868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glVertexAttribPointer"); 248868a0aff31a5cccd285117131219f572fbf07362Romain Guy glEnableVertexAttribArray(gvPositionHandle); 249868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glEnableVertexAttribArray"); 250868a0aff31a5cccd285117131219f572fbf07362Romain Guy glDrawArrays(GL_TRIANGLES, 0, 3); 251868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glDrawArrays"); 252868a0aff31a5cccd285117131219f572fbf07362Romain Guy 253868a0aff31a5cccd285117131219f572fbf07362Romain Guy // Copy content of FBO into a texture 254868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindTexture(GL_TEXTURE_2D, gBufferTexture); 255868a0aff31a5cccd285117131219f572fbf07362Romain Guy glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w / 2, h / 2); 256868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glCopyTexSubImage2D"); 257868a0aff31a5cccd285117131219f572fbf07362Romain Guy 258868a0aff31a5cccd285117131219f572fbf07362Romain Guy // Back to the display 259868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBindFramebuffer(GL_FRAMEBUFFER, 0); 260868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glBindFramebuffer"); 261868a0aff31a5cccd285117131219f572fbf07362Romain Guy 262868a0aff31a5cccd285117131219f572fbf07362Romain Guy // Draw copied content on the screen 263868a0aff31a5cccd285117131219f572fbf07362Romain Guy glUseProgram(gTextureProgram); 264868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glUseProgram"); 265868a0aff31a5cccd285117131219f572fbf07362Romain Guy 266868a0aff31a5cccd285117131219f572fbf07362Romain Guy glEnable(GL_BLEND); 267868a0aff31a5cccd285117131219f572fbf07362Romain Guy glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 268868a0aff31a5cccd285117131219f572fbf07362Romain Guy 269868a0aff31a5cccd285117131219f572fbf07362Romain Guy glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE, 270868a0aff31a5cccd285117131219f572fbf07362Romain Guy TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData); 271868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glVertexAttribPointer"); 272868a0aff31a5cccd285117131219f572fbf07362Romain Guy glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE, 273868a0aff31a5cccd285117131219f572fbf07362Romain Guy TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]); 274868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glVertexAttribPointer"); 275868a0aff31a5cccd285117131219f572fbf07362Romain Guy glEnableVertexAttribArray(gvTexturePositionHandle); 276868a0aff31a5cccd285117131219f572fbf07362Romain Guy glEnableVertexAttribArray(gvTextureTexCoordsHandle); 277868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glEnableVertexAttribArray"); 278868a0aff31a5cccd285117131219f572fbf07362Romain Guy glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 279868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkGlError("glDrawArrays"); 280868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 281868a0aff31a5cccd285117131219f572fbf07362Romain Guy 282868a0aff31a5cccd285117131219f572fbf07362Romain Guyvoid printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { 283868a0aff31a5cccd285117131219f572fbf07362Romain Guy 284868a0aff31a5cccd285117131219f572fbf07362Romain Guy#define X(VAL) {VAL, #VAL} 285868a0aff31a5cccd285117131219f572fbf07362Romain Guy struct {EGLint attribute; const char* name;} names[] = { 286868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_BUFFER_SIZE), 287868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_ALPHA_SIZE), 288868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_BLUE_SIZE), 289868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_GREEN_SIZE), 290868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_RED_SIZE), 291868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_DEPTH_SIZE), 292868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_STENCIL_SIZE), 293868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_CONFIG_CAVEAT), 294868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_CONFIG_ID), 295868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_LEVEL), 296868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_MAX_PBUFFER_HEIGHT), 297868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_MAX_PBUFFER_PIXELS), 298868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_MAX_PBUFFER_WIDTH), 299868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_NATIVE_RENDERABLE), 300868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_NATIVE_VISUAL_ID), 301868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_NATIVE_VISUAL_TYPE), 302868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_SAMPLES), 303868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_SAMPLE_BUFFERS), 304868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_SURFACE_TYPE), 305868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_TRANSPARENT_TYPE), 306868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_TRANSPARENT_RED_VALUE), 307868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_TRANSPARENT_GREEN_VALUE), 308868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_TRANSPARENT_BLUE_VALUE), 309868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_BIND_TO_TEXTURE_RGB), 310868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_BIND_TO_TEXTURE_RGBA), 311868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_MIN_SWAP_INTERVAL), 312868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_MAX_SWAP_INTERVAL), 313868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_LUMINANCE_SIZE), 314868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_ALPHA_MASK_SIZE), 315868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_COLOR_BUFFER_TYPE), 316868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_RENDERABLE_TYPE), 317868a0aff31a5cccd285117131219f572fbf07362Romain Guy X(EGL_CONFORMANT), 318868a0aff31a5cccd285117131219f572fbf07362Romain Guy }; 319868a0aff31a5cccd285117131219f572fbf07362Romain Guy#undef X 320868a0aff31a5cccd285117131219f572fbf07362Romain Guy 321868a0aff31a5cccd285117131219f572fbf07362Romain Guy for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 322868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint value = -1; 323868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 324868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint error = eglGetError(); 325868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (returnVal && error == EGL_SUCCESS) { 326868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf(" %s: ", names[j].name); 327868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("%d (0x%x)", value, value); 328868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 329868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 330868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("\n"); 331868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 332868a0aff31a5cccd285117131219f572fbf07362Romain Guy 333868a0aff31a5cccd285117131219f572fbf07362Romain Guyint printEGLConfigurations(EGLDisplay dpy) { 334868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint numConfig = 0; 335868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig); 336868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglGetConfigs", returnVal); 337868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!returnVal) { 338868a0aff31a5cccd285117131219f572fbf07362Romain Guy return false; 339868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 340868a0aff31a5cccd285117131219f572fbf07362Romain Guy 341868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("Number of EGL configuration: %d\n", numConfig); 342868a0aff31a5cccd285117131219f572fbf07362Romain Guy 343868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig); 344868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (! configs) { 345868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("Could not allocate configs.\n"); 346868a0aff31a5cccd285117131219f572fbf07362Romain Guy return false; 347868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 348868a0aff31a5cccd285117131219f572fbf07362Romain Guy 349868a0aff31a5cccd285117131219f572fbf07362Romain Guy returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig); 350868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglGetConfigs", returnVal); 351868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!returnVal) { 352868a0aff31a5cccd285117131219f572fbf07362Romain Guy free(configs); 353868a0aff31a5cccd285117131219f572fbf07362Romain Guy return false; 354868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 355868a0aff31a5cccd285117131219f572fbf07362Romain Guy 356868a0aff31a5cccd285117131219f572fbf07362Romain Guy for(int i = 0; i < numConfig; i++) { 357868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("Configuration %d\n", i); 358868a0aff31a5cccd285117131219f572fbf07362Romain Guy printEGLConfiguration(dpy, configs[i]); 359868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 360868a0aff31a5cccd285117131219f572fbf07362Romain Guy 361868a0aff31a5cccd285117131219f572fbf07362Romain Guy free(configs); 362868a0aff31a5cccd285117131219f572fbf07362Romain Guy return true; 363868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 364868a0aff31a5cccd285117131219f572fbf07362Romain Guy 365868a0aff31a5cccd285117131219f572fbf07362Romain Guyint main(int argc, char** argv) { 366868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLBoolean returnValue; 367868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLConfig myConfig = {0}; 368868a0aff31a5cccd285117131219f572fbf07362Romain Guy 369868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 370868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint s_configAttribs[] = { 371868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 372868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 373868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_RED_SIZE, 8, 374868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_GREEN_SIZE, 8, 375868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_BLUE_SIZE, 8, 376868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_ALPHA_SIZE, 8, 377868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGL_NONE }; 378868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint majorVersion; 379868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint minorVersion; 380868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLContext context; 381868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLSurface surface; 382868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint w, h; 383868a0aff31a5cccd285117131219f572fbf07362Romain Guy 384868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLDisplay dpy; 385868a0aff31a5cccd285117131219f572fbf07362Romain Guy 386868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("<init>"); 387868a0aff31a5cccd285117131219f572fbf07362Romain Guy dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 388868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglGetDisplay"); 389868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (dpy == EGL_NO_DISPLAY) { 390868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("eglGetDisplay returned EGL_NO_DISPLAY.\n"); 391868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 392868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 393868a0aff31a5cccd285117131219f572fbf07362Romain Guy 394868a0aff31a5cccd285117131219f572fbf07362Romain Guy returnValue = eglInitialize(dpy, &majorVersion, &minorVersion); 395868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglInitialize", returnValue); 396868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion); 397868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (returnValue != EGL_TRUE) { 398868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("eglInitialize failed\n"); 399868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 400868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 401868a0aff31a5cccd285117131219f572fbf07362Romain Guy 402868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (!printEGLConfigurations(dpy)) { 403868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("printEGLConfigurations failed\n"); 404868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 405868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 406868a0aff31a5cccd285117131219f572fbf07362Romain Guy 407868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("printEGLConfigurations"); 408868a0aff31a5cccd285117131219f572fbf07362Romain Guy 409868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLNativeWindowType window = android_createDisplaySurface(); 410868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLint numConfigs = -1, n = 0; 411868a0aff31a5cccd285117131219f572fbf07362Romain Guy eglChooseConfig(dpy, s_configAttribs, 0, 0, &numConfigs); 412868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (numConfigs) { 413868a0aff31a5cccd285117131219f572fbf07362Romain Guy EGLConfig* const configs = new EGLConfig[numConfigs]; 414868a0aff31a5cccd285117131219f572fbf07362Romain Guy eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n); 415868a0aff31a5cccd285117131219f572fbf07362Romain Guy myConfig = configs[0]; 416868a0aff31a5cccd285117131219f572fbf07362Romain Guy delete[] configs; 417868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 418868a0aff31a5cccd285117131219f572fbf07362Romain Guy 419868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("EGLUtils::selectConfigForNativeWindow"); 420868a0aff31a5cccd285117131219f572fbf07362Romain Guy 421868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("Chose this configuration:\n"); 422868a0aff31a5cccd285117131219f572fbf07362Romain Guy printEGLConfiguration(dpy, myConfig); 423868a0aff31a5cccd285117131219f572fbf07362Romain Guy 424868a0aff31a5cccd285117131219f572fbf07362Romain Guy surface = eglCreateWindowSurface(dpy, myConfig, window, NULL); 425868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglCreateWindowSurface"); 426868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (surface == EGL_NO_SURFACE) { 427868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("gelCreateWindowSurface failed.\n"); 428868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 429868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 430868a0aff31a5cccd285117131219f572fbf07362Romain Guy 431868a0aff31a5cccd285117131219f572fbf07362Romain Guy context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs); 432868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglCreateContext"); 433868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (context == EGL_NO_CONTEXT) { 434868a0aff31a5cccd285117131219f572fbf07362Romain Guy printf("eglCreateContext failed\n"); 435868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 436868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 437868a0aff31a5cccd285117131219f572fbf07362Romain Guy returnValue = eglMakeCurrent(dpy, surface, surface, context); 438868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglMakeCurrent", returnValue); 439868a0aff31a5cccd285117131219f572fbf07362Romain Guy if (returnValue != EGL_TRUE) { 440868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 441868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 442868a0aff31a5cccd285117131219f572fbf07362Romain Guy eglQuerySurface(dpy, surface, EGL_WIDTH, &w); 443868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglQuerySurface"); 444868a0aff31a5cccd285117131219f572fbf07362Romain Guy eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); 445868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglQuerySurface"); 446868a0aff31a5cccd285117131219f572fbf07362Romain Guy GLint dim = w < h ? w : h; 447868a0aff31a5cccd285117131219f572fbf07362Romain Guy 448868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "Window dimensions: %d x %d\n", w, h); 449868a0aff31a5cccd285117131219f572fbf07362Romain Guy 450868a0aff31a5cccd285117131219f572fbf07362Romain Guy printGLString("Version", GL_VERSION); 451868a0aff31a5cccd285117131219f572fbf07362Romain Guy printGLString("Vendor", GL_VENDOR); 452868a0aff31a5cccd285117131219f572fbf07362Romain Guy printGLString("Renderer", GL_RENDERER); 453868a0aff31a5cccd285117131219f572fbf07362Romain Guy printGLString("Extensions", GL_EXTENSIONS); 454868a0aff31a5cccd285117131219f572fbf07362Romain Guy 455868a0aff31a5cccd285117131219f572fbf07362Romain Guy if(!setupGraphics(w, h)) { 456868a0aff31a5cccd285117131219f572fbf07362Romain Guy fprintf(stderr, "Could not set up graphics.\n"); 457868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 458868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 459868a0aff31a5cccd285117131219f572fbf07362Romain Guy 460868a0aff31a5cccd285117131219f572fbf07362Romain Guy for (;;) { 461868a0aff31a5cccd285117131219f572fbf07362Romain Guy renderFrame(w, h); 462868a0aff31a5cccd285117131219f572fbf07362Romain Guy eglSwapBuffers(dpy, surface); 463868a0aff31a5cccd285117131219f572fbf07362Romain Guy checkEglError("eglSwapBuffers"); 464868a0aff31a5cccd285117131219f572fbf07362Romain Guy } 465868a0aff31a5cccd285117131219f572fbf07362Romain Guy 466868a0aff31a5cccd285117131219f572fbf07362Romain Guy return 0; 467868a0aff31a5cccd285117131219f572fbf07362Romain Guy} 468