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