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
296ef57d7b368ebbac5f2b27c36a9032fee1cda8b1Andy McFadden#include <WindowSurface.h>
306ef57d7b368ebbac5f2b27c36a9032fee1cda8b1Andy McFadden#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
4096ef57d7b368ebbac5f2b27c36a9032fee1cda8b1Andy McFadden    WindowSurface windowSurface;
4106ef57d7b368ebbac5f2b27c36a9032fee1cda8b1Andy McFadden    EGLNativeWindowType window = windowSurface.getSurface();
411868a0aff31a5cccd285117131219f572fbf07362Romain Guy    EGLint numConfigs = -1, n = 0;
412868a0aff31a5cccd285117131219f572fbf07362Romain Guy    eglChooseConfig(dpy, s_configAttribs, 0, 0, &numConfigs);
413868a0aff31a5cccd285117131219f572fbf07362Romain Guy    if (numConfigs) {
414868a0aff31a5cccd285117131219f572fbf07362Romain Guy        EGLConfig* const configs = new EGLConfig[numConfigs];
415868a0aff31a5cccd285117131219f572fbf07362Romain Guy        eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
416868a0aff31a5cccd285117131219f572fbf07362Romain Guy        myConfig = configs[0];
417868a0aff31a5cccd285117131219f572fbf07362Romain Guy        delete[] configs;
418868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
419868a0aff31a5cccd285117131219f572fbf07362Romain Guy
420868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("EGLUtils::selectConfigForNativeWindow");
421868a0aff31a5cccd285117131219f572fbf07362Romain Guy
422868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printf("Chose this configuration:\n");
423868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printEGLConfiguration(dpy, myConfig);
424868a0aff31a5cccd285117131219f572fbf07362Romain Guy
425868a0aff31a5cccd285117131219f572fbf07362Romain Guy    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
426868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("eglCreateWindowSurface");
427868a0aff31a5cccd285117131219f572fbf07362Romain Guy    if (surface == EGL_NO_SURFACE) {
428868a0aff31a5cccd285117131219f572fbf07362Romain Guy        printf("gelCreateWindowSurface failed.\n");
429868a0aff31a5cccd285117131219f572fbf07362Romain Guy        return 0;
430868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
431868a0aff31a5cccd285117131219f572fbf07362Romain Guy
432868a0aff31a5cccd285117131219f572fbf07362Romain Guy    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
433868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("eglCreateContext");
434868a0aff31a5cccd285117131219f572fbf07362Romain Guy    if (context == EGL_NO_CONTEXT) {
435868a0aff31a5cccd285117131219f572fbf07362Romain Guy        printf("eglCreateContext failed\n");
436868a0aff31a5cccd285117131219f572fbf07362Romain Guy        return 0;
437868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
438868a0aff31a5cccd285117131219f572fbf07362Romain Guy    returnValue = eglMakeCurrent(dpy, surface, surface, context);
439868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("eglMakeCurrent", returnValue);
440868a0aff31a5cccd285117131219f572fbf07362Romain Guy    if (returnValue != EGL_TRUE) {
441868a0aff31a5cccd285117131219f572fbf07362Romain Guy        return 0;
442868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
443868a0aff31a5cccd285117131219f572fbf07362Romain Guy    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
444868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("eglQuerySurface");
445868a0aff31a5cccd285117131219f572fbf07362Romain Guy    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
446868a0aff31a5cccd285117131219f572fbf07362Romain Guy    checkEglError("eglQuerySurface");
447868a0aff31a5cccd285117131219f572fbf07362Romain Guy    GLint dim = w < h ? w : h;
448868a0aff31a5cccd285117131219f572fbf07362Romain Guy
449868a0aff31a5cccd285117131219f572fbf07362Romain Guy    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
450868a0aff31a5cccd285117131219f572fbf07362Romain Guy
451868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printGLString("Version", GL_VERSION);
452868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printGLString("Vendor", GL_VENDOR);
453868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printGLString("Renderer", GL_RENDERER);
454868a0aff31a5cccd285117131219f572fbf07362Romain Guy    printGLString("Extensions", GL_EXTENSIONS);
455868a0aff31a5cccd285117131219f572fbf07362Romain Guy
456868a0aff31a5cccd285117131219f572fbf07362Romain Guy    if(!setupGraphics(w, h)) {
457868a0aff31a5cccd285117131219f572fbf07362Romain Guy        fprintf(stderr, "Could not set up graphics.\n");
458868a0aff31a5cccd285117131219f572fbf07362Romain Guy        return 0;
459868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
460868a0aff31a5cccd285117131219f572fbf07362Romain Guy
461868a0aff31a5cccd285117131219f572fbf07362Romain Guy    for (;;) {
462868a0aff31a5cccd285117131219f572fbf07362Romain Guy        renderFrame(w, h);
463868a0aff31a5cccd285117131219f572fbf07362Romain Guy        eglSwapBuffers(dpy, surface);
464868a0aff31a5cccd285117131219f572fbf07362Romain Guy        checkEglError("eglSwapBuffers");
465868a0aff31a5cccd285117131219f572fbf07362Romain Guy    }
466868a0aff31a5cccd285117131219f572fbf07362Romain Guy
467868a0aff31a5cccd285117131219f572fbf07362Romain Guy    return 0;
468868a0aff31a5cccd285117131219f572fbf07362Romain Guy}
469