19bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich// OpenGL ES 2.0 code
29bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
39bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <nativehelper/jni.h>
49bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#define LOG_TAG "GL2JNI gl_code.cpp"
59bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <utils/Log.h>
69bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
79bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <EGL/egl.h>
89bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <GLES2/gl2.h>
99bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <GLES2/gl2ext.h>
109bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
119bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <stdio.h>
129bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <stdlib.h>
139bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich#include <math.h>
149bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
159bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichstatic void printGLString(const char *name, GLenum s) {
169bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    const char *v = (const char *) glGetString(s);
17a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block    ALOGI("GL %s = %s\n", name, v);
189bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
199bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
209bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichstatic void checkGlError(const char* op) {
219bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    for (GLint error = glGetError(); error; error
229bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            = glGetError()) {
23a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block        ALOGI("after %s() glError (0x%x)\n", op, error);
249bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
259bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
269bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
279bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichstatic const char gVertexShader[] = "attribute vec4 vPosition;\n"
289bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "void main() {\n"
299bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "  gl_Position = vPosition;\n"
309bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "}\n";
319bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
329bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichstatic const char gFragmentShader[] = "precision mediump float;\n"
339bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "void main() {\n"
349bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
359bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    "}\n";
369bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
379bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichGLuint loadShader(GLenum shaderType, const char* pSource) {
389bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    GLuint shader = glCreateShader(shaderType);
399bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (shader) {
409bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glShaderSource(shader, 1, &pSource, NULL);
419bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glCompileShader(shader);
429bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        GLint compiled = 0;
439bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
449bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        if (!compiled) {
459bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            GLint infoLen = 0;
469bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
479bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            if (infoLen) {
489bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                char* buf = (char*) malloc(infoLen);
499bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                if (buf) {
509bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
51e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                    ALOGE("Could not compile shader %d:\n%s\n",
529bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                            shaderType, buf);
539bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                    free(buf);
549bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                }
559bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                glDeleteShader(shader);
569bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                shader = 0;
579bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            }
589bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        }
599bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
609bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    return shader;
619bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
629bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
639bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichGLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
649bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
659bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (!vertexShader) {
669bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        return 0;
679bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
689bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
699bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
709bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (!pixelShader) {
719bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        return 0;
729bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
739bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
749bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    GLuint program = glCreateProgram();
759bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (program) {
769bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glAttachShader(program, vertexShader);
779bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        checkGlError("glAttachShader");
789bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glAttachShader(program, pixelShader);
799bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        checkGlError("glAttachShader");
809bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glLinkProgram(program);
819bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        GLint linkStatus = GL_FALSE;
829bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
839bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        if (linkStatus != GL_TRUE) {
849bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            GLint bufLength = 0;
859bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
869bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            if (bufLength) {
879bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                char* buf = (char*) malloc(bufLength);
889bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                if (buf) {
899bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                    glGetProgramInfoLog(program, bufLength, NULL, buf);
90e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block                    ALOGE("Could not link program:\n%s\n", buf);
919bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                    free(buf);
929bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich                }
939bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            }
949bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            glDeleteProgram(program);
959bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            program = 0;
969bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        }
979bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
989bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    return program;
999bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
1009bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1019bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichGLuint gProgram;
1029bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichGLuint gvPositionHandle;
1039bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1049bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichbool setupGraphics(int w, int h) {
1059bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    printGLString("Version", GL_VERSION);
1069bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    printGLString("Vendor", GL_VENDOR);
1079bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    printGLString("Renderer", GL_RENDERER);
1089bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    printGLString("Extensions", GL_EXTENSIONS);
1099bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
110a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block    ALOGI("setupGraphics(%d, %d)", w, h);
1119bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    gProgram = createProgram(gVertexShader, gFragmentShader);
1129bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (!gProgram) {
113e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("Could not create program.");
1149bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        return false;
1159bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
1169bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
1179bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glGetAttribLocation");
118a19954ab377b46dbcb9cbe8a6ab6d458f2e32bcaSteve Block    ALOGI("glGetAttribLocation(\"vPosition\") = %d\n",
1199bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich            gvPositionHandle);
1209bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1219bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glViewport(0, 0, w, h);
1229bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glViewport");
1239bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    return true;
1249bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
1259bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1269bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichconst GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
1279bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        0.5f, -0.5f };
1289bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1299bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichvoid renderFrame() {
1309bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    static float grey;
1319bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    grey += 0.01f;
1329bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    if (grey > 1.0f) {
1339bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich        grey = 0.0f;
1349bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    }
1359bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glClearColor(grey, grey, grey, 1.0f);
1369bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glClearColor");
1379bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1389bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glClear");
1399bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1409bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glUseProgram(gProgram);
1419bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glUseProgram");
1429bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1439bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
1449bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glVertexAttribPointer");
1459bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glEnableVertexAttribArray(gvPositionHandle);
1469bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glEnableVertexAttribArray");
1479bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    glDrawArrays(GL_TRIANGLES, 0, 3);
1489bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    checkGlError("glDrawArrays");
1499bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
1509bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1519bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevichextern "C" {
1529bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * env, jobject obj, jint width, jint height);
1539bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj);
1549bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich};
1559bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1569bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichJNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * env, jobject obj, jint width, jint height)
1579bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich{
1589bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    setupGraphics(width, height);
1599bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
1609bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
1619bd30f05e890b213e97b838e04024d8cd232dbc0Jack PalevichJNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj)
1629bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich{
1639bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich    renderFrame();
1649bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich}
1659bd30f05e890b213e97b838e04024d8cd232dbc0Jack Palevich
166