gl_code.cpp revision 965b95468d8325388557003eec24bd70fd22640a
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 264static void doLoop(uint32_t w, uint32_t h, const char *str) { 265 int doLoopState = stateClock % doLoopStates; 266 // LOGI("doLoop %d\n", doLoopState); 267 switch(doLoopState) { 268 case 0: 269 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 270 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 271 break; 272 case 1: 273 strcpy(saveBuf, str); 274 startTimer(); 275 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 276 for (int ct=0; ct < 100; ct++) { 277 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 278 } 279 break; 280 } 281} 282 283static void doSingleTest(uint32_t w, uint32_t h, 284 bool useVarColor, 285 int texCount, 286 bool modulateFirstTex, 287 int extraMath, 288 int tex0, int tex1) { 289 int doSingleTestState = (stateClock / doLoopStates) % doSingleTestStates; 290 // LOGI("doSingleTest %d\n", doSingleTestState); 291 switch (doSingleTestState) { 292 case 0: { 293 char *pgmTxt = genShader(useVarColor, texCount, modulateFirstTex, extraMath); 294 int pgm = createProgram(gVertexShader, pgmTxt); 295 if (!pgm) { 296 LOGE("error running test\n"); 297 return; 298 } 299 int loc = glGetUniformLocation(pgm, "u_tex0"); 300 //LOGI("loc = %i \n", loc); 301 if (loc >= 0) glUniform1i(loc, 0); 302 loc = glGetUniformLocation(pgm, "u_tex1"); 303 if (loc >= 0) glUniform1i(loc, 1); 304 305 loc = glGetUniformLocation(pgm, "u_color"); 306 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 307 308 loc = glGetUniformLocation(pgm, "u_0"); 309 if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f); 310 311 loc = glGetUniformLocation(pgm, "u_1"); 312 if (loc >= 0) glUniform4f(loc, 0.7f, 0.8f, 0.6f, 0.8f); 313 314 loc = glGetUniformLocation(pgm, "u_2"); 315 if (loc >= 0) glUniform4f(loc, 0.9f, 0.6f, 0.7f, 1.0f); 316 317 loc = glGetUniformLocation(pgm, "u_3"); 318 if (loc >= 0) glUniform4f(loc, 0.88f, 0.2f, 0.4f, 0.2f); 319 320 glActiveTexture(GL_TEXTURE0); 321 glBindTexture(GL_TEXTURE_2D, tex0); 322 glActiveTexture(GL_TEXTURE1); 323 glBindTexture(GL_TEXTURE_2D, tex1); 324 glActiveTexture(GL_TEXTURE0); 325 326 327 glBlendFunc(GL_ONE, GL_ONE); 328 glDisable(GL_BLEND); 329 char str2[1024]; 330 sprintf(str2, "%i, %i, %i, %i, %i, 0", 331 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 332 doLoop(w, h, str2); 333 } 334 break; 335 case 1: { 336 char str2[1024]; 337 glEnable(GL_BLEND); 338 sprintf(str2, "%i, %i, %i, %i, %i, 1", 339 useVarColor, texCount, modulateFirstTex, extraMath, tex0); 340 doLoop(w, h, str2); 341 } 342 break; 343 } 344} 345 346void genTextures() { 347 uint32_t *m = (uint32_t *)malloc(1024*1024*4); 348 for (int y=0; y < 1024; y++){ 349 for (int x=0; x < 1024; x++){ 350 m[y*1024 + x] = 0xff0000ff | ((x & 0xff) << 8) | (y << 16); 351 } 352 } 353 glBindTexture(GL_TEXTURE_2D, 1); 354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 359 360 for (int y=0; y < 16; y++){ 361 for (int x=0; x < 16; x++){ 362 m[y*16 + x] = 0xff0000ff | (x<<12) | (y<<20); 363 } 364 } 365 glBindTexture(GL_TEXTURE_2D, 2); 366 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); 367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 371 372} 373 374void doTest(uint32_t w, uint32_t h) { 375 int testState = stateClock / (doLoopStates * doSingleTestStates); 376 int texCount; 377 int extraMath; 378 int testSubState; 379 if ( testState < 5 * 2) { 380 texCount = 0; // Only 10 tests for texCout 0 381 extraMath = testState / 2; 382 testSubState = testState % 2; 383 } else { 384 texCount = 1 + (testState - 10) / (5 * 8); 385 extraMath = testState / 8; 386 testSubState = testState % 8; 387 } 388 if (texCount >= 3) { 389 // LOGI("done\n"); 390 done = true; 391 return; 392 } 393 394 395 // LOGI("doTest %d %d %d\n", texCount, extraMath, testSubState); 396 397 switch(testSubState) { 398 case 0: 399 doSingleTest(w, h, false, texCount, false, extraMath, 1, 1); 400 break; 401 case 1: 402 doSingleTest(w, h, true, texCount, false, extraMath, 1, 1); 403 break; 404 case 2: 405 doSingleTest(w, h, false, texCount, true, extraMath, 1, 1); 406 break; 407 case 3: 408 doSingleTest(w, h, true, texCount, true, extraMath, 1, 1); 409 break; 410 411 case 4: 412 doSingleTest(w, h, false, texCount, false, extraMath, 2, 2); 413 break; 414 case 5: 415 doSingleTest(w, h, true, texCount, false, extraMath, 2, 2); 416 break; 417 case 6: 418 doSingleTest(w, h, false, texCount, true, extraMath, 2, 2); 419 break; 420 case 7: 421 doSingleTest(w, h, true, texCount, true, extraMath, 2, 2); 422 break; 423 } 424} 425 426extern "C" { 427 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height); 428 JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj); 429}; 430 431JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj, jint width, jint height) 432{ 433 w = width; 434 h = height; 435 stateClock = 0; 436 done = false; 437 setupVA(); 438 genTextures(); 439 440 LOGI("\nvarColor, texCount, modulate, extraMath, texSize, blend, Mpps, DC60\n"); 441} 442 443JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj) 444{ 445 if (! done) { 446 if (stateClock > 0 && ((stateClock & 1) == 0)) { 447 endTimer(saveBuf, w, h, 1, 100); 448 } 449 doTest(w, h); 450 stateClock++; 451 } else { 452 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 453 } 454} 455