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