| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <time.h> |
| #include <sched.h> |
| #include <sys/resource.h> |
| |
| #include <EGL/egl.h> |
| #include <GLES2/gl2.h> |
| #include <GLES2/gl2ext.h> |
| |
| #include <utils/Timers.h> |
| |
| #include <ui/FramebufferNativeWindow.h> |
| #include <ui/EGLUtils.h> |
| |
| using namespace android; |
| |
| static void printGLString(const char *name, GLenum s) { |
| // fprintf(stderr, "printGLString %s, %d\n", name, s); |
| const char *v = (const char *) glGetString(s); |
| // int error = glGetError(); |
| // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error, |
| // (unsigned int) v); |
| // if ((v < (const char*) 0) || (v > (const char*) 0x10000)) |
| // fprintf(stderr, "GL %s = %s\n", name, v); |
| // else |
| // fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v); |
| fprintf(stderr, "GL %s = %s\n", name, v); |
| } |
| |
| static const char* eglErrorToString[] = { |
| "EGL_SUCCESS", // 0x3000 12288 |
| "EGL_NOT_INITIALIZED", |
| "EGL_BAD_ACCESS", // 0x3002 12290 |
| "EGL_BAD_ALLOC", "EGL_BAD_ATTRIBUTE", |
| "EGL_BAD_CONFIG", |
| "EGL_BAD_CONTEXT", // 0x3006 12294 |
| "EGL_BAD_CURRENT_SURFACE", "EGL_BAD_DISPLAY", "EGL_BAD_MATCH", |
| "EGL_BAD_NATIVE_PIXMAP", "EGL_BAD_NATIVE_WINDOW", "EGL_BAD_PARAMETER", // 0x300c 12300 |
| "EGL_BAD_SURFACE" }; |
| |
| static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { |
| if (returnVal != EGL_TRUE) { |
| fprintf(stderr, "%s() returned %d\n", op, returnVal); |
| } |
| |
| for (EGLint error = eglGetError(); error != EGL_SUCCESS; error |
| = eglGetError()) { |
| const char* errorString = "unknown"; |
| if (error >= EGL_SUCCESS && error <= EGL_BAD_SURFACE) { |
| errorString = eglErrorToString[error - EGL_SUCCESS]; |
| } |
| fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, errorString, |
| error); |
| } |
| } |
| |
| static void checkGlError(const char* op) { |
| for (GLint error = glGetError(); error; error |
| = glGetError()) { |
| fprintf(stderr, "after %s() glError (0x%x)\n", op, error); |
| } |
| } |
| |
| static const char gVertexShader[] = "attribute vec4 vPosition;\n" |
| "void main() {\n" |
| " gl_Position = vPosition;\n" |
| "}\n"; |
| |
| static const char gFragmentShader[] = "precision mediump float;\n" |
| "void main() {\n" |
| " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" |
| "}\n"; |
| |
| GLuint loadShader(GLenum shaderType, const char* pSource) { |
| GLuint shader = glCreateShader(shaderType); |
| if (shader) { |
| glShaderSource(shader, 1, &pSource, NULL); |
| glCompileShader(shader); |
| GLint compiled = 0; |
| glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); |
| if (!compiled) { |
| GLint infoLen = 0; |
| glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); |
| if (infoLen) { |
| char* buf = (char*) malloc(infoLen); |
| if (buf) { |
| glGetShaderInfoLog(shader, infoLen, NULL, buf); |
| fprintf(stderr, "Could not compile shader %d:\n%s\n", |
| shaderType, buf); |
| free(buf); |
| } |
| glDeleteShader(shader); |
| shader = 0; |
| } |
| } |
| } |
| return shader; |
| } |
| |
| GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { |
| GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); |
| if (!vertexShader) { |
| return 0; |
| } |
| |
| GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); |
| if (!pixelShader) { |
| return 0; |
| } |
| |
| GLuint program = glCreateProgram(); |
| if (program) { |
| glAttachShader(program, vertexShader); |
| checkGlError("glAttachShader"); |
| glAttachShader(program, pixelShader); |
| checkGlError("glAttachShader"); |
| glLinkProgram(program); |
| GLint linkStatus = GL_FALSE; |
| glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); |
| if (linkStatus != GL_TRUE) { |
| GLint bufLength = 0; |
| glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); |
| if (bufLength) { |
| char* buf = (char*) malloc(bufLength); |
| if (buf) { |
| glGetProgramInfoLog(program, bufLength, NULL, buf); |
| fprintf(stderr, "Could not link program:\n%s\n", buf); |
| free(buf); |
| } |
| } |
| glDeleteProgram(program); |
| program = 0; |
| } |
| } |
| return program; |
| } |
| |
| GLuint gProgram; |
| GLuint gvPositionHandle; |
| |
| bool setupGraphics(int w, int h) { |
| gProgram = createProgram(gVertexShader, gFragmentShader); |
| if (!gProgram) { |
| return false; |
| } |
| gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); |
| checkGlError("glGetAttribLocation"); |
| fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n", |
| gvPositionHandle); |
| |
| glViewport(0, 0, w, h); |
| checkGlError("glViewport"); |
| return true; |
| } |
| |
| const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, |
| 0.5f, -0.5f }; |
| |
| void renderFrame() { |
| glClearColor(0.0f, 0.0f, 1.0f, 1.0f); |
| checkGlError("glClearColor"); |
| glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); |
| checkGlError("glClear"); |
| |
| glUseProgram(gProgram); |
| checkGlError("glUseProgram"); |
| |
| glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); |
| checkGlError("glVertexAttribPointer"); |
| glEnableVertexAttribArray(gvPositionHandle); |
| checkGlError("glEnableVertexAttribArray"); |
| glDrawArrays(GL_TRIANGLES, 0, 3); |
| checkGlError("glDrawArrays"); |
| } |
| |
| int main(int argc, char** argv) { |
| EGLBoolean returnValue; |
| EGLConfig configs[2]; |
| EGLint config_count; |
| |
| EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; |
| EGLint s_configAttribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE, EGL_RED_SIZE, |
| 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 8, |
| EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; |
| |
| EGLint s_configAttribs2[] = |
| { |
| EGL_DEPTH_SIZE, 16, |
| EGL_NONE |
| }; |
| |
| EGLint majorVersion; |
| EGLint minorVersion; |
| EGLContext context; |
| EGLSurface surface; |
| EGLint w, h; |
| |
| EGLDisplay dpy; |
| |
| EGLNativeWindowType window = 0; |
| window = android_createDisplaySurface(); |
| |
| checkEglError("<init>"); |
| dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
| checkEglError("eglGetDisplay"); |
| if (dpy == EGL_NO_DISPLAY) { |
| printf("eglGetDisplay returned EGL_NO_DISPLAY.\n"); |
| return 0; |
| } |
| |
| returnValue = eglInitialize(dpy, &majorVersion, &minorVersion); |
| checkEglError("eglInitialize", returnValue); |
| fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion); |
| if (returnValue != EGL_TRUE) { |
| printf("eglInitialize failed\n"); |
| return 0; |
| } |
| |
| returnValue = eglGetConfigs(dpy, configs, 2, &config_count); |
| checkEglError("eglGetConfigs", returnValue); |
| fprintf(stderr, "Config count: %d\n", config_count); |
| for (int i = 0; i < config_count; i++) { |
| fprintf(stderr, "%d: 0x%08x\n", i, (unsigned int) configs[i]); |
| } |
| |
| #if 0 |
| EGLConfig config; |
| EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &config); |
| checkEglError("EGLUtils::selectConfigForNativeWindow"); |
| #else |
| int chooseConfigResult = eglChooseConfig(dpy, s_configAttribs2, configs, 2, |
| &config_count); |
| checkEglError("eglChooseConfig", chooseConfigResult); |
| if (chooseConfigResult != EGL_TRUE) { |
| printf("eglChooseConfig failed\n"); |
| return 0; |
| } |
| #endif |
| |
| surface = eglCreateWindowSurface(dpy, configs[0], window, NULL); |
| checkEglError("eglCreateWindowSurface"); |
| if (surface == EGL_NO_SURFACE) { |
| printf("gelCreateWindowSurface failed.\n"); |
| return 0; |
| } |
| EGLint gl2_0Attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; |
| |
| context = eglCreateContext(dpy, configs[0], EGL_NO_CONTEXT, context_attribs); |
| checkEglError("eglCreateContext"); |
| if (context == EGL_NO_CONTEXT) { |
| printf("eglCreateContext failed\n"); |
| return 0; |
| } |
| eglMakeCurrent(dpy, surface, surface, context); |
| checkEglError("eglMakeCurrent"); |
| eglQuerySurface(dpy, surface, EGL_WIDTH, &w); |
| checkEglError("eglQuerySurface"); |
| eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); |
| checkEglError("eglQuerySurface"); |
| GLint dim = w < h ? w : h; |
| |
| fprintf(stderr, "Window dimensions: %d x %d\n", w, h); |
| |
| printGLString("Version", GL_VERSION); |
| printGLString("Vendor", GL_VENDOR); |
| printGLString("Renderer", GL_RENDERER); |
| printGLString("Extensions", GL_EXTENSIONS); |
| |
| if(!setupGraphics(w, h)) { |
| fprintf(stderr, "Could not set up graphics.\n"); |
| return 0; |
| } |
| |
| for (;;) { |
| renderFrame(); |
| eglSwapBuffers(dpy, surface); |
| } |
| |
| return 0; |
| } |