gl_code.cpp revision eb69d2ae19c89553c142a7b716fe2ac72e32080a
1// OpenGL ES 2.0 code 2 3#include <nativehelper/jni.h> 4#define LOG_TAG "GLPerf gl_code.cpp" 5#include <utils/Log.h> 6 7#include <EGL/egl.h> 8#include <GLES2/gl2.h> 9#include <GLES2/gl2ext.h> 10#include <utils/Timers.h> 11 12#include <stdio.h> 13#include <stdlib.h> 14#include <math.h> 15 16static void printGLString(const char *name, GLenum s) { 17 const char *v = (const char *) glGetString(s); 18 LOGI("GL %s = %s\n", name, v); 19} 20 21static void checkGlError(const char* op) { 22 for (GLint error = glGetError(); error; error 23 = glGetError()) { 24 LOGI("after %s() glError (0x%x)\n", op, error); 25 } 26} 27 28GLuint loadShader(GLenum shaderType, const char* pSource) { 29 GLuint shader = glCreateShader(shaderType); 30 if (shader) { 31 glShaderSource(shader, 1, &pSource, NULL); 32 glCompileShader(shader); 33 GLint compiled = 0; 34 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 35 if (!compiled) { 36 GLint infoLen = 0; 37 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 38 if (infoLen) { 39 char* buf = (char*) malloc(infoLen); 40 if (buf) { 41 glGetShaderInfoLog(shader, infoLen, NULL, buf); 42 LOGE("Could not compile shader %d:\n%s\n", 43 shaderType, buf); 44 free(buf); 45 } 46 glDeleteShader(shader); 47 shader = 0; 48 } 49 } 50 } 51 return shader; 52} 53 54enum { 55 A_POS, 56 A_COLOR, 57 A_TEX0, 58 A_TEX1 59}; 60 61GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { 62 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); 63 if (!vertexShader) { 64 return 0; 65 } 66 67 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); 68 if (!pixelShader) { 69 return 0; 70 } 71 72 GLuint program = glCreateProgram(); 73 if (program) { 74 glAttachShader(program, vertexShader); 75 checkGlError("glAttachShader v"); 76 glAttachShader(program, pixelShader); 77 checkGlError("glAttachShader p"); 78 79 glBindAttribLocation(program, A_POS, "a_pos"); 80 glBindAttribLocation(program, A_COLOR, "a_color"); 81 glBindAttribLocation(program, A_TEX0, "a_tex0"); 82 glBindAttribLocation(program, A_TEX1, "a_tex1"); 83 glLinkProgram(program); 84 GLint linkStatus = GL_FALSE; 85 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 86 if (linkStatus != GL_TRUE) { 87 GLint bufLength = 0; 88 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); 89 if (bufLength) { 90 char* buf = (char*) malloc(bufLength); 91 if (buf) { 92 glGetProgramInfoLog(program, bufLength, NULL, buf); 93 LOGE("Could not link program:\n%s\n", buf); 94 free(buf); 95 } 96 } 97 glDeleteProgram(program); 98 program = 0; 99 } 100 } 101 checkGlError("createProgram"); 102 glUseProgram(program); 103 return program; 104} 105 106uint64_t getTime() { 107 struct timespec t; 108 clock_gettime(CLOCK_MONOTONIC, &t); 109 return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); 110} 111 112uint64_t gTime; 113void startTimer() { 114 gTime = getTime(); 115} 116 117void endTimer(const char *str, int w, int h, double dc, int count) { 118 uint64_t t2 = getTime(); 119 double delta = ((double)(t2 - gTime)) / 1000000000; 120 double pixels = dc * (w * h) * count; 121 double mpps = pixels / delta / 1000000; 122 double dc60 = pixels / delta / (w * h) / 60; 123 124 LOGI("%s, %f, %f\n", str, mpps, dc60); 125} 126 127static const char gVertexShader[] = 128 "attribute vec4 a_pos;\n" 129 "attribute vec4 a_color;\n" 130 "attribute vec2 a_tex0;\n" 131 "attribute vec2 a_tex1;\n" 132 "varying vec4 v_color;\n" 133 "varying vec2 v_tex0;\n" 134 "varying vec2 v_tex1;\n" 135 136 "void main() {\n" 137 " v_color = a_color;\n" 138 " v_tex0 = a_tex0;\n" 139 " v_tex1 = a_tex1;\n" 140 " gl_Position = a_pos;\n" 141 "}\n"; 142 143static const char gShaderPrefix[] = 144 "precision mediump float;\n" 145 "uniform vec4 u_color;\n" 146 "uniform vec4 u_0;\n" 147 "uniform vec4 u_1;\n" 148 "uniform vec4 u_2;\n" 149 "uniform vec4 u_3;\n" 150 "varying vec4 v_color;\n" 151 "varying vec2 v_tex0;\n" 152 "varying vec2 v_tex1;\n" 153 "uniform sampler2D u_tex0;\n" 154 "uniform sampler2D u_tex1;\n" 155 "void main() {\n"; 156 157static const char gShaderPostfix[] = 158 " gl_FragColor = c;\n" 159 "}\n"; 160 161 162static char * append(char *d, const char *s) { 163 size_t len = strlen(s); 164 memcpy(d, s, len); 165 return d + len; 166} 167 168static char * genShader( 169 bool useVarColor, 170 int texCount, 171 bool modulateFirstTex, 172 int extraMath) 173{ 174 char *str = (char *)calloc(16 * 1024, 1); 175 char *tmp = append(str, gShaderPrefix); 176 177 if (modulateFirstTex || !texCount) { 178 if (useVarColor) { 179 tmp = append(tmp, " vec4 c = v_color;\n"); 180 } else { 181 tmp = append(tmp, " vec4 c = u_color;\n"); 182 } 183 } else { 184 tmp = append(tmp, " vec4 c = texture2D(u_tex0, v_tex0);\n"); 185 } 186 187 if (modulateFirstTex && texCount) { 188 tmp = append(tmp, " c *= texture2D(u_tex0, v_tex0);\n"); 189 } 190 if (texCount > 1) { 191 tmp = append(tmp, " c *= texture2D(u_tex1, v_tex1);\n"); 192 } 193 194 if (extraMath > 0) { 195 tmp = append(tmp, " c *= u_0;\n"); 196 } 197 if (extraMath > 1) { 198 tmp = append(tmp, " c *= u_1;\n"); 199 } 200 if (extraMath > 2) { 201 tmp = append(tmp, " c *= u_2;\n"); 202 } 203 if (extraMath > 3) { 204 tmp = append(tmp, " c *= u_3;\n"); 205 } 206 207 208 tmp = append(tmp, gShaderPostfix); 209 tmp[0] = 0; 210 211 //LOGI("%s", str); 212 return str; 213} 214 215static void setupVA() { 216 static const float vtx[] = { 217 -2.0f,-1.0f, 218 1.0f,-1.0f, 219 -2.0f, 1.0f, 220 1.0f, 1.0f }; 221 static const float color[] = { 222 1.0f,0.0f,1.0f,1.0f, 223 0.0f,0.0f,1.0f,1.0f, 224 1.0f,1.0f,0.0f,1.0f, 225 1.0f,1.0f,1.0f,1.0f }; 226 static const float tex0[] = { 227 0.0f,0.0f, 228 1.0f,0.0f, 229 1.0f,1.0f, 230 0.0f,1.0f }; 231 static const float tex1[] = { 232 1.0f,0.0f, 233 1.0f,1.0f, 234 0.0f,1.0f, 235 0.0f,0.0f }; 236 237 glEnableVertexAttribArray(A_POS); 238 glEnableVertexAttribArray(A_COLOR); 239 glEnableVertexAttribArray(A_TEX0); 240 glEnableVertexAttribArray(A_TEX1); 241 242 glVertexAttribPointer(A_POS, 2, GL_FLOAT, false, 8, vtx); 243 glVertexAttribPointer(A_COLOR, 4, GL_FLOAT, false, 16, color); 244 glVertexAttribPointer(A_TEX0, 2, GL_FLOAT, false, 8, tex0); 245 glVertexAttribPointer(A_TEX1, 2, GL_FLOAT, false, 8, tex1); 246} 247 248////////////////////////// 249 250// Tells us what to draw next 251 252uint32_t w; 253uint32_t h; 254 255// The stateClock starts at zero and increments by 1 every time we draw a frame. It is used to control which phase of the test we are in. 256 257int stateClock; 258const int doLoopStates = 2; 259const int doSingleTestStates = 2; 260bool done; 261 262char saveBuf[1024]; 263 264void kickTimer() { 265 endTimer(saveBuf, w, h, 1, 100); 266} 267static void doLoop(uint32_t w, uint32_t h, const char *str) { 268 switch(stateClock % doLoopStates) { 269 case 0: 270 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 271 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 272 break; 273 case 1: 274 strcpy(saveBuf, str); 275 startTimer(); 276 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 277 for (int ct=0; ct < 100; ct++) { 278 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 279 } 280 break; 281 } 282} 283 284static void doSingleTest(uint32_t w, uint32_t h, 285 bool useVarColor, 286 int texCount, 287 bool modulateFirstTex, 288 int extraMath, 289 int tex0, int tex1) { 290 switch ((stateClock / doLoopStates) % doSingleTestStates) { 291 case 0: { 292 char *pgmTxt = genShader(useVarColor, texCount, modulateFirstTex, extraMath); 293 int pgm = createProgram(gVertexShader, pgmTxt); 294 if (!pgm) { 295 LOGE("error running test\n"); 296 return; 297 } 298 int loc = glGetUniformLocation(pgm, "u_tex0"); 299 //LOGI("loc = %i \n", loc); 300 if (loc >= 0) glUniform1i(loc, 0); 301 loc = glGetUniformLocation(pgm, "u_tex1"); 302 if (loc >= 0) glUniform1i(loc, 1); 303 304 loc = glGetUniformLocation(pgm, "u_color"); 305 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 306 307 loc = glGetUniformLocation(pgm, "u_0"); 308 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 309 310 loc = glGetUniformLocation(pgm, "u_1"); 311 if (loc >= 0) glUniform4f(loc, 0.7f, 0.8f, 0.6f, 0.8f); 312 313 loc = glGetUniformLocation(pgm, "u_2"); 314 if (loc >= 0) glUniform4f(loc, 0.9f, 0.6f, 0.7f, 1.0f); 315 316 loc = glGetUniformLocation(pgm, "u_3"); 317 if (loc >= 0) glUniform4f(loc, 0.88f, 0.2f, 0.4f, 0.2f); 318 319 glActiveTexture(GL_TEXTURE0); 320 glBindTexture(GL_TEXTURE_2D, tex0); 321 glActiveTexture(GL_TEXTURE1); 322 glBindTexture(GL_TEXTURE_2D, tex1); 323 glActiveTexture(GL_TEXTURE0); 324 325 326 glBlendFunc(GL_ONE, GL_ONE); 327 glDisable(GL_BLEND); 328 char str2[1024]; 329 sprintf(str2, "%i, %i, %i, %i, %i, 0", 330 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 331 doLoop(w, h, str2); 332 } 333 break; 334 case 1: { 335 char str2[1024]; 336 glEnable(GL_BLEND); 337 sprintf(str2, "%i, %i, %i, %i, %i, 1", 338 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 339 doLoop(w, h, str2); 340 } 341 break; 342 } 343} 344 345void genTextures() { 346 uint32_t *m = (uint32_t *)malloc(1024*1024*4); 347 for (int y=0; y < 1024; y++){ 348 for (int x=0; x < 1024; x++){ 349 m[y*1024 + x] = 0xff0000ff | ((x & 0xff) << 8) | (y << 16); 350 } 351 } 352 glBindTexture(GL_TEXTURE_2D, 1); 353 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 358 359 for (int y=0; y < 16; y++){ 360 for (int x=0; x < 16; x++){ 361 m[y*16 + x] = 0xff0000ff | (x<<12) | (y<<20); 362 } 363 } 364 glBindTexture(GL_TEXTURE_2D, 2); 365 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 370 371} 372 373void doTest(uint32_t w, uint32_t h) { 374 int testState = stateClock / (doLoopStates * doSingleTestStates); 375 int texCount; 376 int extraMath; 377 int testSubState; 378 if ( testState < 5 * 2) { 379 texCount = 0; // Only 10 tests for texCout 0 380 extraMath = testState / 2; 381 testSubState = testState % 2; 382 } else { 383 texCount = 1 + (testState - 10) / (5 * 8); 384 extraMath = testState / 8; 385 testSubState = testState % 8; 386 } 387 if (texCount >= 3) { 388 LOGI("done\n"); 389 done = true; 390 return; 391 } 392 393 switch(testSubState) { 394 case 0: 395 doSingleTest(w, h, false, texCount, false, extraMath, 1, 1); 396 break; 397 case 1: 398 doSingleTest(w, h, true, texCount, false, extraMath, 1, 1); 399 break; 400 case 2: 401 doSingleTest(w, h, false, texCount, true, extraMath, 1, 1); 402 break; 403 case 3: 404 doSingleTest(w, h, true, texCount, true, extraMath, 1, 1); 405 break; 406 407 case 4: 408 doSingleTest(w, h, false, texCount, false, extraMath, 2, 2); 409 break; 410 case 5: 411 doSingleTest(w, h, true, texCount, false, extraMath, 2, 2); 412 break; 413 case 6: 414 doSingleTest(w, h, false, texCount, true, extraMath, 2, 2); 415 break; 416 case 7: 417 doSingleTest(w, h, true, texCount, true, extraMath, 2, 2); 418 break; 419 } 420} 421 422extern "C" { 423 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height); 424 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj); 425}; 426 427JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height) 428{ 429 w = width; 430 h = height; 431 stateClock = 0; 432 done = false; 433 setupVA(); 434 genTextures(); 435 436 LOGI("\nvarColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\n"); 437} 438 439JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj) 440{ 441 if (! done) { 442 if (stateClock > 0) { 443 kickTimer(); 444 } 445 doTest(w, h); 446 stateClock++; 447 } 448} 449