1c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner/* 2c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * Copyright (C) 2009 The Android Open Source Project 3c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * 4c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * Licensed under the Apache License, Version 2.0 (the "License"); 5c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * you may not use this file except in compliance with the License. 6c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * You may obtain a copy of the License at 7c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * 8c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * http://www.apache.org/licenses/LICENSE-2.0 9c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * 10c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * Unless required by applicable law or agreed to in writing, software 11c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * distributed under the License is distributed on an "AS IS" BASIS, 12c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * See the License for the specific language governing permissions and 14c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner * limitations under the License. 15c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner */ 16c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 17c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner// OpenGL ES 2.0 code 18c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 19c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <jni.h> 20c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <android/log.h> 21c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 22c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <GLES2/gl2.h> 23c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <GLES2/gl2ext.h> 24c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 25c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <stdio.h> 26c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <stdlib.h> 27c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#include <math.h> 28c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 29c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#define LOG_TAG "libgl2jni" 30c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 31c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 32c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 33c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerstatic void printGLString(const char *name, GLenum s) { 34c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner const char *v = (const char *) glGetString(s); 35c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGI("GL %s = %s\n", name, v); 36c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 37c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 38c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerstatic void checkGlError(const char* op) { 39c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner for (GLint error = glGetError(); error; error 40c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner = glGetError()) { 41c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGI("after %s() glError (0x%x)\n", op, error); 42c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 43c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 44c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 45c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerstatic const char gVertexShader[] = 46c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "attribute vec4 vPosition;\n" 47c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "void main() {\n" 48c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner " gl_Position = vPosition;\n" 49c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "}\n"; 50c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 51c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerstatic const char gFragmentShader[] = 52c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "precision mediump float;\n" 53c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "void main() {\n" 54c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 55c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner "}\n"; 56c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 57c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerGLuint loadShader(GLenum shaderType, const char* pSource) { 58c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLuint shader = glCreateShader(shaderType); 59c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (shader) { 60c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glShaderSource(shader, 1, &pSource, NULL); 61c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glCompileShader(shader); 62c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLint compiled = 0; 63c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 64c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (!compiled) { 65c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLint infoLen = 0; 66c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 67c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (infoLen) { 68c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner char* buf = (char*) malloc(infoLen); 69c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (buf) { 70c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetShaderInfoLog(shader, infoLen, NULL, buf); 71c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGE("Could not compile shader %d:\n%s\n", 72c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner shaderType, buf); 73c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner free(buf); 74c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 75c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glDeleteShader(shader); 76c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner shader = 0; 77c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 78c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 79c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 80c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return shader; 81c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 82c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 83c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerGLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { 84c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); 85c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (!vertexShader) { 86c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return 0; 87c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 88c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 89c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); 90c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (!pixelShader) { 91c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return 0; 92c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 93c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 94c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLuint program = glCreateProgram(); 95c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (program) { 96c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glAttachShader(program, vertexShader); 97c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glAttachShader"); 98c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glAttachShader(program, pixelShader); 99c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glAttachShader"); 100c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glLinkProgram(program); 101c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLint linkStatus = GL_FALSE; 102c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 103c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (linkStatus != GL_TRUE) { 104c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner GLint bufLength = 0; 105c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); 106c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (bufLength) { 107c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner char* buf = (char*) malloc(bufLength); 108c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (buf) { 109c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glGetProgramInfoLog(program, bufLength, NULL, buf); 110c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGE("Could not link program:\n%s\n", buf); 111c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner free(buf); 112c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 113c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 114c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glDeleteProgram(program); 115c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner program = 0; 116c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 117c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 118c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return program; 119c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 120c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 121c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerGLuint gProgram; 122c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerGLuint gvPositionHandle; 123c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 124c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerbool setupGraphics(int w, int h) { 125c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner printGLString("Version", GL_VERSION); 126c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner printGLString("Vendor", GL_VENDOR); 127c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner printGLString("Renderer", GL_RENDERER); 128c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner printGLString("Extensions", GL_EXTENSIONS); 129c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 130c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGI("setupGraphics(%d, %d)", w, h); 131c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner gProgram = createProgram(gVertexShader, gFragmentShader); 132c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (!gProgram) { 133c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGE("Could not create program."); 134c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return false; 135c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 136c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); 137c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glGetAttribLocation"); 138c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner LOGI("glGetAttribLocation(\"vPosition\") = %d\n", 139c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner gvPositionHandle); 140c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 141c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glViewport(0, 0, w, h); 142c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glViewport"); 143c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner return true; 144c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 145c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 146c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerconst GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 147c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 0.5f, -0.5f }; 148c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 149c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnervoid renderFrame() { 150c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner static float grey; 151c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner grey += 0.01f; 152c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner if (grey > 1.0f) { 153c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner grey = 0.0f; 154c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner } 155c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glClearColor(grey, grey, grey, 1.0f); 156c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glClearColor"); 157c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 158c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glClear"); 159c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 160c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glUseProgram(gProgram); 161c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glUseProgram"); 162c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 163c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); 164c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glVertexAttribPointer"); 165c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glEnableVertexAttribArray(gvPositionHandle); 166c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glEnableVertexAttribArray"); 167c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner glDrawArrays(GL_TRIANGLES, 0, 3); 168c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner checkGlError("glDrawArrays"); 169c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 170c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 171c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turnerextern "C" { 172c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height); 173c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj); 174c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner}; 175c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 176c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerJNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) 177c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner{ 178c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner setupGraphics(width, height); 179c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 180c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner 181c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' TurnerJNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) 182c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner{ 183c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner renderFrame(); 184c817c5210e4207908b83faaf08a2c5b95251f871David 'Digit' Turner} 185