1 /* 2 * Copyright 2013 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 <jni.h> 18 #include <stdlib.h> 19 #include <time.h> 20 21 #include "gles3jni.h" 22 23 const Vertex QUAD[4] = { 24 // Square with diagonal < 2 so that it fits in a [-1 .. 1]^2 square 25 // regardless of rotation. 26 {{-0.7f, -0.7f}, {0x00, 0xFF, 0x00}}, 27 {{ 0.7f, -0.7f}, {0x00, 0x00, 0xFF}}, 28 {{-0.7f, 0.7f}, {0xFF, 0x00, 0x00}}, 29 {{ 0.7f, 0.7f}, {0xFF, 0xFF, 0xFF}}, 30 }; 31 32 bool checkGlError(const char* funcName) { 33 GLint err = glGetError(); 34 if (err != GL_NO_ERROR) { 35 ALOGE("GL error after %s(): 0x%08x\n", funcName, err); 36 return true; 37 } 38 return false; 39 } 40 41 GLuint createShader(GLenum shaderType, const char* src) { 42 GLuint shader = glCreateShader(shaderType); 43 if (!shader) { 44 checkGlError("glCreateShader"); 45 return 0; 46 } 47 glShaderSource(shader, 1, &src, NULL); 48 49 GLint compiled = GL_FALSE; 50 glCompileShader(shader); 51 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 52 if (!compiled) { 53 GLint infoLogLen = 0; 54 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen); 55 if (infoLogLen > 0) { 56 GLchar* infoLog = (GLchar*)malloc(infoLogLen); 57 if (infoLog) { 58 glGetShaderInfoLog(shader, infoLogLen, NULL, infoLog); 59 ALOGE("Could not compile %s shader:\n%s\n", 60 shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment", 61 infoLog); 62 free(infoLog); 63 } 64 } 65 glDeleteShader(shader); 66 return 0; 67 } 68 69 return shader; 70 } 71 72 GLuint createProgram(const char* vtxSrc, const char* fragSrc) { 73 GLuint vtxShader = 0; 74 GLuint fragShader = 0; 75 GLuint program = 0; 76 GLint linked = GL_FALSE; 77 78 vtxShader = createShader(GL_VERTEX_SHADER, vtxSrc); 79 if (!vtxShader) 80 goto exit; 81 82 fragShader = createShader(GL_FRAGMENT_SHADER, fragSrc); 83 if (!fragShader) 84 goto exit; 85 86 program = glCreateProgram(); 87 if (!program) { 88 checkGlError("glCreateProgram"); 89 goto exit; 90 } 91 glAttachShader(program, vtxShader); 92 glAttachShader(program, fragShader); 93 94 glLinkProgram(program); 95 glGetProgramiv(program, GL_LINK_STATUS, &linked); 96 if (!linked) { 97 ALOGE("Could not link program"); 98 GLint infoLogLen = 0; 99 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen); 100 if (infoLogLen) { 101 GLchar* infoLog = (GLchar*)malloc(infoLogLen); 102 if (infoLog) { 103 glGetProgramInfoLog(program, infoLogLen, NULL, infoLog); 104 ALOGE("Could not link program:\n%s\n", infoLog); 105 free(infoLog); 106 } 107 } 108 glDeleteProgram(program); 109 program = 0; 110 } 111 112 exit: 113 glDeleteShader(vtxShader); 114 glDeleteShader(fragShader); 115 return program; 116 } 117 118 static void printGlString(const char* name, GLenum s) { 119 const char* v = (const char*)glGetString(s); 120 ALOGV("GL %s: %s\n", name, v); 121 } 122 123 // ---------------------------------------------------------------------------- 124 125 Renderer::Renderer() 126 : mNumInstances(0), 127 mLastFrameNs(0) 128 { 129 memset(mScale, 0, sizeof(mScale)); 130 memset(mAngularVelocity, 0, sizeof(mAngularVelocity)); 131 memset(mAngles, 0, sizeof(mAngles)); 132 } 133 134 Renderer::~Renderer() { 135 } 136 137 void Renderer::resize(int w, int h) { 138 float* offsets = mapOffsetBuf(); 139 calcSceneParams(w, h, offsets); 140 unmapOffsetBuf(); 141 142 for (unsigned int i = 0; i < mNumInstances; i++) { 143 mAngles[i] = drand48() * TWO_PI; 144 mAngularVelocity[i] = MAX_ROT_SPEED * (2.0*drand48() - 1.0); 145 } 146 147 mLastFrameNs = 0; 148 149 glViewport(0, 0, w, h); 150 } 151 152 void Renderer::calcSceneParams(unsigned int w, unsigned int h, 153 float* offsets) { 154 // number of cells along the larger screen dimension 155 const float NCELLS_MAJOR = MAX_INSTANCES_PER_SIDE; 156 // cell size in scene space 157 const float CELL_SIZE = 2.0f / NCELLS_MAJOR; 158 159 // Calculations are done in "landscape", i.e. assuming dim[0] >= dim[1]. 160 // Only at the end are values put in the opposite order if h > w. 161 const float dim[2] = {fmaxf(w,h), fminf(w,h)}; 162 const float aspect[2] = {dim[0] / dim[1], dim[1] / dim[0]}; 163 const float scene2clip[2] = {1.0f, aspect[0]}; 164 const int ncells[2] = { 165 NCELLS_MAJOR, 166 (int)floorf(NCELLS_MAJOR * aspect[1]) 167 }; 168 169 float centers[2][MAX_INSTANCES_PER_SIDE]; 170 for (int d = 0; d < 2; d++) { 171 float offset = -ncells[d] / NCELLS_MAJOR; // -1.0 for d=0 172 for (int i = 0; i < ncells[d]; i++) { 173 centers[d][i] = scene2clip[d] * (CELL_SIZE*(i + 0.5f) + offset); 174 } 175 } 176 177 int major = w >= h ? 0 : 1; 178 int minor = w >= h ? 1 : 0; 179 // outer product of centers[0] and centers[1] 180 for (int i = 0; i < ncells[0]; i++) { 181 for (int j = 0; j < ncells[1]; j++) { 182 int idx = i*ncells[1] + j; 183 offsets[2*idx + major] = centers[0][i]; 184 offsets[2*idx + minor] = centers[1][j]; 185 } 186 } 187 188 mNumInstances = ncells[0] * ncells[1]; 189 mScale[major] = 0.5f * CELL_SIZE * scene2clip[0]; 190 mScale[minor] = 0.5f * CELL_SIZE * scene2clip[1]; 191 } 192 193 void Renderer::step() { 194 timespec now; 195 clock_gettime(CLOCK_MONOTONIC, &now); 196 uint64_t nowNs = now.tv_sec*1000000000ull + now.tv_nsec; 197 198 if (mLastFrameNs > 0) { 199 float dt = float(nowNs - mLastFrameNs) * 0.000000001f; 200 201 for (unsigned int i = 0; i < mNumInstances; i++) { 202 mAngles[i] += mAngularVelocity[i] * dt; 203 if (mAngles[i] >= TWO_PI) { 204 mAngles[i] -= TWO_PI; 205 } else if (mAngles[i] <= -TWO_PI) { 206 mAngles[i] += TWO_PI; 207 } 208 } 209 210 float* transforms = mapTransformBuf(); 211 for (unsigned int i = 0; i < mNumInstances; i++) { 212 float s = sinf(mAngles[i]); 213 float c = cosf(mAngles[i]); 214 transforms[4*i + 0] = c * mScale[0]; 215 transforms[4*i + 1] = s * mScale[1]; 216 transforms[4*i + 2] = -s * mScale[0]; 217 transforms[4*i + 3] = c * mScale[1]; 218 } 219 unmapTransformBuf(); 220 } 221 222 mLastFrameNs = nowNs; 223 } 224 225 void Renderer::render() { 226 step(); 227 228 glClearColor(0.2f, 0.2f, 0.3f, 1.0f); 229 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 230 draw(mNumInstances); 231 checkGlError("Renderer::render"); 232 } 233 234 // ---------------------------------------------------------------------------- 235 236 static Renderer* g_renderer = NULL; 237 238 extern "C" { 239 JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv* env, jobject obj); 240 JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_resize(JNIEnv* env, jobject obj, jint width, jint height); 241 JNIEXPORT void JNICALL Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv* env, jobject obj); 242 }; 243 244 #if !defined(DYNAMIC_ES3) 245 static GLboolean gl3stubInit() { 246 return GL_TRUE; 247 } 248 #endif 249 250 JNIEXPORT void JNICALL 251 Java_com_android_gles3jni_GLES3JNILib_init(JNIEnv* env, jobject obj) { 252 if (g_renderer) { 253 delete g_renderer; 254 g_renderer = NULL; 255 } 256 257 printGlString("Version", GL_VERSION); 258 printGlString("Vendor", GL_VENDOR); 259 printGlString("Renderer", GL_RENDERER); 260 printGlString("Extensions", GL_EXTENSIONS); 261 262 const char* versionStr = (const char*)glGetString(GL_VERSION); 263 if (strstr(versionStr, "OpenGL ES 3.") && gl3stubInit()) { 264 g_renderer = createES3Renderer(); 265 } else if (strstr(versionStr, "OpenGL ES 2.")) { 266 g_renderer = createES2Renderer(); 267 } else { 268 ALOGE("Unsupported OpenGL ES version"); 269 } 270 } 271 272 JNIEXPORT void JNICALL 273 Java_com_android_gles3jni_GLES3JNILib_resize(JNIEnv* env, jobject obj, jint width, jint height) { 274 if (g_renderer) { 275 g_renderer->resize(width, height); 276 } 277 } 278 279 JNIEXPORT void JNICALL 280 Java_com_android_gles3jni_GLES3JNILib_step(JNIEnv* env, jobject obj) { 281 if (g_renderer) { 282 g_renderer->render(); 283 } 284 } 285