gl_code.cpp revision 63bcb5f8e2d2c1d054b09a5ab9f989644cfeb9b1
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) fprintf(out, "%s, %f, %f\r\n", str, mpps, dc60); 128} 129 130static const char gVertexShader[] = 131 "attribute vec4 a_pos;\n" 132 "attribute vec4 a_color;\n" 133 "attribute vec2 a_tex0;\n" 134 "attribute vec2 a_tex1;\n" 135 "varying vec4 v_color;\n" 136 "varying vec2 v_tex0;\n" 137 "varying vec2 v_tex1;\n" 138 139 "void main() {\n" 140 " v_color = a_color;\n" 141 " v_tex0 = a_tex0;\n" 142 " v_tex1 = a_tex1;\n" 143 " gl_Position = a_pos;\n" 144 "}\n"; 145 146static const char gShaderPrefix[] = 147 "precision mediump float;\n" 148 "uniform vec4 u_color;\n" 149 "uniform vec4 u_0;\n" 150 "uniform vec4 u_1;\n" 151 "uniform vec4 u_2;\n" 152 "uniform vec4 u_3;\n" 153 "varying vec4 v_color;\n" 154 "varying vec2 v_tex0;\n" 155 "varying vec2 v_tex1;\n" 156 "uniform sampler2D u_tex0;\n" 157 "uniform sampler2D u_tex1;\n" 158 "void main() {\n"; 159 160static const char gShaderPostfix[] = 161 " gl_FragColor = c;\n" 162 "}\n"; 163 164 165static char * append(char *d, const char *s) { 166 size_t len = strlen(s); 167 memcpy(d, s, len); 168 return d + len; 169} 170 171static char * genShader( 172 bool useVarColor, 173 int texCount, 174 bool modulateFirstTex, 175 int extraMath) 176{ 177 char *str = (char *)calloc(16 * 1024, 1); 178 char *tmp = append(str, gShaderPrefix); 179 180 if (modulateFirstTex || !texCount) { 181 if (useVarColor) { 182 tmp = append(tmp, " vec4 c = v_color;\n"); 183 } else { 184 tmp = append(tmp, " vec4 c = u_color;\n"); 185 } 186 } else { 187 tmp = append(tmp, " vec4 c = texture2D(u_tex0, v_tex0);\n"); 188 } 189 190 if (modulateFirstTex && texCount) { 191 tmp = append(tmp, " c *= texture2D(u_tex0, v_tex0);\n"); 192 } 193 if (texCount > 1) { 194 tmp = append(tmp, " c *= texture2D(u_tex1, v_tex1);\n"); 195 } 196 197 if (extraMath > 0) { 198 tmp = append(tmp, " c *= u_0;\n"); 199 } 200 if (extraMath > 1) { 201 tmp = append(tmp, " c *= u_1;\n"); 202 } 203 if (extraMath > 2) { 204 tmp = append(tmp, " c *= u_2;\n"); 205 } 206 if (extraMath > 3) { 207 tmp = append(tmp, " c *= u_3;\n"); 208 } 209 210 211 tmp = append(tmp, gShaderPostfix); 212 tmp[0] = 0; 213 214 //LOGI("%s", str); 215 return str; 216} 217 218static void setupVA() { 219 static const float vtx[] = { 220 -2.0f,-1.0f, 221 1.0f,-1.0f, 222 -2.0f, 1.0f, 223 1.0f, 1.0f }; 224 static const float color[] = { 225 1.0f,0.0f,1.0f,1.0f, 226 0.0f,0.0f,1.0f,1.0f, 227 1.0f,1.0f,0.0f,1.0f, 228 1.0f,1.0f,1.0f,1.0f }; 229 static const float tex0[] = { 230 0.0f,0.0f, 231 1.0f,0.0f, 232 1.0f,1.0f, 233 0.0f,1.0f }; 234 static const float tex1[] = { 235 1.0f,0.0f, 236 1.0f,1.0f, 237 0.0f,1.0f, 238 0.0f,0.0f }; 239 240 glEnableVertexAttribArray(A_POS); 241 glEnableVertexAttribArray(A_COLOR); 242 glEnableVertexAttribArray(A_TEX0); 243 glEnableVertexAttribArray(A_TEX1); 244 245 glVertexAttribPointer(A_POS, 2, GL_FLOAT, false, 8, vtx); 246 glVertexAttribPointer(A_COLOR, 4, GL_FLOAT, false, 16, color); 247 glVertexAttribPointer(A_TEX0, 2, GL_FLOAT, false, 8, tex0); 248 glVertexAttribPointer(A_TEX1, 2, GL_FLOAT, false, 8, tex1); 249} 250 251////////////////////////// 252 253// Width and height of the screen 254 255uint32_t w; 256uint32_t h; 257 258// 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. 259 260int stateClock; 261const int doLoopStates = 2; 262const int doSingleTestStates = 2; 263bool done; 264 265// Saves the parameters of the test (so we can print them out when we finish the timing.) 266 267char saveBuf[1024]; 268 269static void doLoop(uint32_t w, uint32_t h, const char *str) { 270 int doLoopState = stateClock % doLoopStates; 271 // LOGI("doLoop %d\n", doLoopState); 272 switch(doLoopState) { 273 case 0: 274 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 275 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 276 break; 277 case 1: 278 strcpy(saveBuf, str); 279 startTimer(); 280 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 281 for (int ct=0; ct < 100; ct++) { 282 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 283 } 284 break; 285 } 286} 287 288static void doSingleTest(uint32_t w, uint32_t h, 289 bool useVarColor, 290 int texCount, 291 bool modulateFirstTex, 292 int extraMath, 293 int tex0, int tex1) { 294 int doSingleTestState = (stateClock / doLoopStates) % doSingleTestStates; 295 // LOGI("doSingleTest %d\n", doSingleTestState); 296 switch (doSingleTestState) { 297 case 0: { 298 char *pgmTxt = genShader(useVarColor, texCount, modulateFirstTex, extraMath); 299 int pgm = createProgram(gVertexShader, pgmTxt); 300 if (!pgm) { 301 LOGE("error running test\n"); 302 return; 303 } 304 int loc = glGetUniformLocation(pgm, "u_tex0"); 305 //LOGI("loc = %i \n", loc); 306 if (loc >= 0) glUniform1i(loc, 0); 307 loc = glGetUniformLocation(pgm, "u_tex1"); 308 if (loc >= 0) glUniform1i(loc, 1); 309 310 loc = glGetUniformLocation(pgm, "u_color"); 311 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 312 313 loc = glGetUniformLocation(pgm, "u_0"); 314 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 315 316 loc = glGetUniformLocation(pgm, "u_1"); 317 if (loc >= 0) glUniform4f(loc, 0.7f, 0.8f, 0.6f, 0.8f); 318 319 loc = glGetUniformLocation(pgm, "u_2"); 320 if (loc >= 0) glUniform4f(loc, 0.9f, 0.6f, 0.7f, 1.0f); 321 322 loc = glGetUniformLocation(pgm, "u_3"); 323 if (loc >= 0) glUniform4f(loc, 0.88f, 0.2f, 0.4f, 0.2f); 324 325 glActiveTexture(GL_TEXTURE0); 326 glBindTexture(GL_TEXTURE_2D, tex0); 327 glActiveTexture(GL_TEXTURE1); 328 glBindTexture(GL_TEXTURE_2D, tex1); 329 glActiveTexture(GL_TEXTURE0); 330 331 332 glBlendFunc(GL_ONE, GL_ONE); 333 glDisable(GL_BLEND); 334 char str2[1024]; 335 sprintf(str2, "%i, %i, %i, %i, %i, 0", 336 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 337 doLoop(w, h, str2); 338 } 339 break; 340 case 1: { 341 char str2[1024]; 342 glEnable(GL_BLEND); 343 sprintf(str2, "%i, %i, %i, %i, %i, 1", 344 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 345 doLoop(w, h, str2); 346 } 347 break; 348 } 349} 350 351void genTextures() { 352 uint32_t *m = (uint32_t *)malloc(1024*1024*4); 353 for (int y=0; y < 1024; y++){ 354 for (int x=0; x < 1024; x++){ 355 m[y*1024 + x] = 0xff0000ff | ((x & 0xff) << 8) | (y << 16); 356 } 357 } 358 glBindTexture(GL_TEXTURE_2D, 1); 359 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 364 365 for (int y=0; y < 16; y++){ 366 for (int x=0; x < 16; x++){ 367 m[y*16 + x] = 0xff0000ff | (x<<12) | (y<<20); 368 } 369 } 370 glBindTexture(GL_TEXTURE_2D, 2); 371 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 376 377} 378 379void doTest(uint32_t w, uint32_t h) { 380 int testState = stateClock / (doLoopStates * doSingleTestStates); 381 int texCount; 382 int extraMath; 383 int testSubState; 384 if ( testState < 5 * 2) { 385 texCount = 0; // Only 10 tests for texCout 0 386 extraMath = testState / 2; 387 testSubState = testState % 2; 388 } else { 389 texCount = 1 + (testState - 10) / (5 * 8); 390 extraMath = testState / 8; 391 testSubState = testState % 8; 392 } 393 if (texCount >= 3) { 394 LOGI("done\n"); 395 if (out) { 396 fclose(out); 397 out = NULL; 398 } 399 done = true; 400 exit(0); 401 return; 402 } 403 404 405 // LOGI("doTest %d %d %d\n", texCount, extraMath, testSubState); 406 407 switch(testSubState) { 408 case 0: 409 doSingleTest(w, h, false, texCount, false, extraMath, 1, 1); 410 break; 411 case 1: 412 doSingleTest(w, h, true, texCount, false, extraMath, 1, 1); 413 break; 414 case 2: 415 doSingleTest(w, h, false, texCount, true, extraMath, 1, 1); 416 break; 417 case 3: 418 doSingleTest(w, h, true, texCount, true, extraMath, 1, 1); 419 break; 420 421 case 4: 422 doSingleTest(w, h, false, texCount, false, extraMath, 2, 2); 423 break; 424 case 5: 425 doSingleTest(w, h, true, texCount, false, extraMath, 2, 2); 426 break; 427 case 6: 428 doSingleTest(w, h, false, texCount, true, extraMath, 2, 2); 429 break; 430 case 7: 431 doSingleTest(w, h, true, texCount, true, extraMath, 2, 2); 432 break; 433 } 434} 435 436extern "C" { 437 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height); 438 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj); 439}; 440 441JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height) 442{ 443 w = width; 444 h = height; 445 stateClock = 0; 446 done = false; 447 setupVA(); 448 genTextures(); 449 const char* fileName = "/sdcard/glperf.csv"; 450 LOGI("Writing to: %s\n",fileName); 451 out = fopen(fileName, "w"); 452 if (out == NULL) { 453 LOGE("Could not open: %s\n", fileName); 454 } 455 456 LOGI("\nvarColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\n"); 457 if (out) fprintf(out,"\nvarColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\r\n"); 458} 459 460JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj) 461{ 462 if (! done) { 463 if (stateClock > 0 && ((stateClock & 1) == 0)) { 464 endTimer(saveBuf, w, h, 1, 100); 465 } 466 doTest(w, h); 467 stateClock++; 468 } else { 469 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 470 } 471} 472