gl_code.cpp revision 92a9ae4a02682a9e195f3e3a68d2c7293c018173
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 if ( testState < 5 * 2) { 388 texCount = 0; // Only 10 tests for texCout 0 389 extraMath = testState / 2; 390 testSubState = testState % 2; 391 } else { 392 texCount = 1 + (testState - 10) / (5 * 8); 393 extraMath = testState / 8; 394 testSubState = testState % 8; 395 } 396 if (texCount >= 3) { 397 LOGI("done\n"); 398 if (out) { 399 fclose(out); 400 out = NULL; 401 } 402 done = true; 403 return; 404 } 405 406 407 // LOGI("doTest %d %d %d\n", texCount, extraMath, testSubState); 408 409 switch(testSubState) { 410 case 0: 411 doSingleTest(w, h, false, texCount, false, extraMath, 1, 1); 412 break; 413 case 1: 414 doSingleTest(w, h, true, texCount, false, extraMath, 1, 1); 415 break; 416 case 2: 417 doSingleTest(w, h, false, texCount, true, extraMath, 1, 1); 418 break; 419 case 3: 420 doSingleTest(w, h, true, texCount, true, extraMath, 1, 1); 421 break; 422 423 case 4: 424 doSingleTest(w, h, false, texCount, false, extraMath, 2, 2); 425 break; 426 case 5: 427 doSingleTest(w, h, true, texCount, false, extraMath, 2, 2); 428 break; 429 case 6: 430 doSingleTest(w, h, false, texCount, true, extraMath, 2, 2); 431 break; 432 case 7: 433 doSingleTest(w, h, true, texCount, true, extraMath, 2, 2); 434 break; 435 } 436} 437 438extern "C" { 439 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height); 440 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj); 441}; 442 443JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height) 444{ 445 if (!done) { 446 w = width; 447 h = height; 448 stateClock = 0; 449 done = false; 450 setupVA(); 451 genTextures(); 452 const char* fileName = "/sdcard/glperf.csv"; 453 if (out != NULL) { 454 LOGI("Closing partially written output.n"); 455 fclose(out); 456 out = NULL; 457 } 458 LOGI("Writing to: %s\n",fileName); 459 out = fopen(fileName, "w"); 460 if (out == NULL) { 461 LOGE("Could not open: %s\n", fileName); 462 } 463 464 LOGI("\nvarColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\n"); 465 if (out) fprintf(out,"varColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\r\n"); 466 } 467} 468 469JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj) 470{ 471 if (! done) { 472 if (stateClock > 0 && ((stateClock & 1) == 0)) { 473 endTimer(saveBuf, w, h, 1, 100); 474 } 475 doTest(w, h); 476 stateClock++; 477 } else { 478 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 479 } 480} 481