gl2_basic.cpp revision 919583553781f1e1885fa17f76d54008ebeca3c1
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 const char* eglErrorToString[] = {
48        "EGL_SUCCESS", // 0x3000 12288
49        "EGL_NOT_INITIALIZED",
50        "EGL_BAD_ACCESS", // 0x3002 12290
51        "EGL_BAD_ALLOC", "EGL_BAD_ATTRIBUTE",
52        "EGL_BAD_CONFIG",
53        "EGL_BAD_CONTEXT", // 0x3006 12294
54        "EGL_BAD_CURRENT_SURFACE", "EGL_BAD_DISPLAY", "EGL_BAD_MATCH",
55        "EGL_BAD_NATIVE_PIXMAP", "EGL_BAD_NATIVE_WINDOW", "EGL_BAD_PARAMETER", // 0x300c 12300
56        "EGL_BAD_SURFACE" };
57
58static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
59    if (returnVal != EGL_TRUE) {
60        fprintf(stderr, "%s() returned %d\n", op, returnVal);
61    }
62
63    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
64            = eglGetError()) {
65        const char* errorString = "unknown";
66        if (error >= EGL_SUCCESS && error <= EGL_BAD_SURFACE) {
67            errorString = eglErrorToString[error - EGL_SUCCESS];
68        }
69        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, errorString,
70                error);
71    }
72}
73
74static void checkGlError(const char* op) {
75    for (GLint error = glGetError(); error; error
76            = glGetError()) {
77        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
78    }
79}
80
81static const char gVertexShader[] = "attribute vec4 vPosition;\n"
82    "void main() {\n"
83    "  gl_Position = vPosition;\n"
84    "}\n";
85
86static const char gFragmentShader[] = "precision mediump float;\n"
87    "void main() {\n"
88    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
89    "}\n";
90
91GLuint loadShader(GLenum shaderType, const char* pSource) {
92    GLuint shader = glCreateShader(shaderType);
93    if (shader) {
94        glShaderSource(shader, 1, &pSource, NULL);
95        glCompileShader(shader);
96        GLint compiled = 0;
97        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
98        if (!compiled) {
99            GLint infoLen = 0;
100            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
101            if (infoLen) {
102                char* buf = (char*) malloc(infoLen);
103                if (buf) {
104                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
105                    fprintf(stderr, "Could not compile shader %d:\n%s\n",
106                            shaderType, buf);
107                    free(buf);
108                }
109                glDeleteShader(shader);
110                shader = 0;
111            }
112        }
113    }
114    return shader;
115}
116
117GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
118    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
119    if (!vertexShader) {
120        return 0;
121    }
122
123    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
124    if (!pixelShader) {
125        return 0;
126    }
127
128    GLuint program = glCreateProgram();
129    if (program) {
130        glAttachShader(program, vertexShader);
131        checkGlError("glAttachShader");
132        glAttachShader(program, pixelShader);
133        checkGlError("glAttachShader");
134        glLinkProgram(program);
135        GLint linkStatus = GL_FALSE;
136        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
137        if (linkStatus != GL_TRUE) {
138            GLint bufLength = 0;
139            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
140            if (bufLength) {
141                char* buf = (char*) malloc(bufLength);
142                if (buf) {
143                    glGetProgramInfoLog(program, bufLength, NULL, buf);
144                    fprintf(stderr, "Could not link program:\n%s\n", buf);
145                    free(buf);
146                }
147            }
148            glDeleteProgram(program);
149            program = 0;
150        }
151    }
152    return program;
153}
154
155GLuint gProgram;
156GLuint gvPositionHandle;
157
158bool setupGraphics(int w, int h) {
159    gProgram = createProgram(gVertexShader, gFragmentShader);
160    if (!gProgram) {
161        return false;
162    }
163    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
164    checkGlError("glGetAttribLocation");
165    fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n",
166            gvPositionHandle);
167
168    glViewport(0, 0, w, h);
169    checkGlError("glViewport");
170    return true;
171}
172
173const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
174        0.5f, -0.5f };
175
176void renderFrame() {
177    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
178    checkGlError("glClearColor");
179    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
180    checkGlError("glClear");
181
182    glUseProgram(gProgram);
183    checkGlError("glUseProgram");
184
185    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
186    checkGlError("glVertexAttribPointer");
187    glEnableVertexAttribArray(gvPositionHandle);
188    checkGlError("glEnableVertexAttribArray");
189    glDrawArrays(GL_TRIANGLES, 0, 3);
190    checkGlError("glDrawArrays");
191}
192
193int main(int argc, char** argv) {
194    EGLBoolean returnValue;
195    EGLConfig configs[2];
196    EGLint config_count;
197
198    EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
199    EGLint s_configAttribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE, EGL_RED_SIZE,
200            5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 8,
201            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
202
203    EGLint s_configAttribs2[] =
204    {
205            EGL_DEPTH_SIZE,     16,
206            EGL_NONE
207    };
208
209    EGLint majorVersion;
210    EGLint minorVersion;
211    EGLContext context;
212    EGLSurface surface;
213    EGLint w, h;
214
215    EGLDisplay dpy;
216
217    EGLNativeWindowType window = 0;
218    window = android_createDisplaySurface();
219
220    checkEglError("<init>");
221    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
222    checkEglError("eglGetDisplay");
223    if (dpy == EGL_NO_DISPLAY) {
224        printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
225        return 0;
226    }
227
228    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
229    checkEglError("eglInitialize", returnValue);
230    fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
231    if (returnValue != EGL_TRUE) {
232        printf("eglInitialize failed\n");
233        return 0;
234    }
235
236    returnValue = eglGetConfigs(dpy, configs, 2, &config_count);
237    checkEglError("eglGetConfigs", returnValue);
238    fprintf(stderr, "Config count: %d\n", config_count);
239    for (int i = 0; i < config_count; i++) {
240        fprintf(stderr, "%d: 0x%08x\n", i, (unsigned int) configs[i]);
241    }
242
243#if 0
244    EGLConfig config;
245    EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &config);
246    checkEglError("EGLUtils::selectConfigForNativeWindow");
247#else
248    int chooseConfigResult = eglChooseConfig(dpy, s_configAttribs2, configs, 2,
249            &config_count);
250    checkEglError("eglChooseConfig", chooseConfigResult);
251    if (chooseConfigResult != EGL_TRUE) {
252        printf("eglChooseConfig failed\n");
253        return 0;
254    }
255#endif
256
257    surface = eglCreateWindowSurface(dpy, configs[0], window, NULL);
258    checkEglError("eglCreateWindowSurface");
259    if (surface == EGL_NO_SURFACE) {
260        printf("gelCreateWindowSurface failed.\n");
261        return 0;
262    }
263    EGLint gl2_0Attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
264
265    context = eglCreateContext(dpy, configs[0], EGL_NO_CONTEXT, context_attribs);
266    checkEglError("eglCreateContext");
267    if (context == EGL_NO_CONTEXT) {
268        printf("eglCreateContext failed\n");
269        return 0;
270    }
271    eglMakeCurrent(dpy, surface, surface, context);
272    checkEglError("eglMakeCurrent");
273    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
274    checkEglError("eglQuerySurface");
275    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
276    checkEglError("eglQuerySurface");
277    GLint dim = w < h ? w : h;
278
279    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
280
281    printGLString("Version", GL_VERSION);
282    printGLString("Vendor", GL_VENDOR);
283    printGLString("Renderer", GL_RENDERER);
284    printGLString("Extensions", GL_EXTENSIONS);
285
286    if(!setupGraphics(w, h)) {
287        fprintf(stderr, "Could not set up graphics.\n");
288        return 0;
289    }
290
291    for (;;) {
292        renderFrame();
293        eglSwapBuffers(dpy, surface);
294        checkEglError("eglSwapBuffers");
295    }
296
297    return 0;
298}
299