filltest.cpp revision a5c381fd51deb4bdd8fea3141ad00925f2e2cfb6
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <time.h>
20#include <sched.h>
21#include <sys/resource.h>
22#include <string.h>
23
24#include <GLES2/gl2.h>
25#include <GLES2/gl2ext.h>
26#include <utils/Timers.h>
27#include <EGL/egl.h>
28
29
30using namespace android;
31
32static void checkGlError(const char* op) {
33    for (GLint error = glGetError(); error; error
34            = glGetError()) {
35        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
36    }
37}
38
39GLuint loadShader(GLenum shaderType, const char* pSource) {
40    GLuint shader = glCreateShader(shaderType);
41    if (shader) {
42        glShaderSource(shader, 1, &pSource, NULL);
43        glCompileShader(shader);
44        GLint compiled = 0;
45        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
46        if (!compiled) {
47            GLint infoLen = 0;
48            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
49            if (infoLen) {
50                char* buf = (char*) malloc(infoLen);
51                if (buf) {
52                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
53                    fprintf(stderr, "Could not compile shader %d:\n%s\n",
54                            shaderType, buf);
55                    free(buf);
56                }
57                glDeleteShader(shader);
58                shader = 0;
59            }
60        }
61    }
62    return shader;
63}
64
65enum {
66    A_POS,
67    A_COLOR,
68    A_TEX0,
69    A_TEX1
70};
71
72GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
73    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
74    if (!vertexShader) {
75        return 0;
76    }
77
78    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
79    if (!pixelShader) {
80        return 0;
81    }
82
83    GLuint program = glCreateProgram();
84    if (program) {
85        glAttachShader(program, vertexShader);
86        checkGlError("glAttachShader v");
87        glAttachShader(program, pixelShader);
88        checkGlError("glAttachShader p");
89
90        glBindAttribLocation(program, A_POS, "a_pos");
91        glBindAttribLocation(program, A_COLOR, "a_color");
92        glBindAttribLocation(program, A_TEX0, "a_tex0");
93        glBindAttribLocation(program, A_TEX1, "a_tex1");
94        glLinkProgram(program);
95        GLint linkStatus = GL_FALSE;
96        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
97        if (linkStatus != GL_TRUE) {
98            GLint bufLength = 0;
99            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
100            if (bufLength) {
101                char* buf = (char*) malloc(bufLength);
102                if (buf) {
103                    glGetProgramInfoLog(program, bufLength, NULL, buf);
104                    printf("Could not link program:\n%s\n", buf);
105                    free(buf);
106                }
107            }
108            glDeleteProgram(program);
109            program = 0;
110        }
111    }
112    checkGlError("createProgram");
113    glUseProgram(program);
114    return program;
115}
116
117uint64_t getTime() {
118    struct timespec t;
119    clock_gettime(CLOCK_MONOTONIC, &t);
120    return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
121}
122
123uint64_t gTime;
124void startTimer() {
125    gTime = getTime();
126}
127
128void endTimer(const char *str, int w, int h, double dc, int count) {
129    uint64_t t2 = getTime();
130    double delta = ((double)(t2 - gTime)) / 1000000000;
131    double pixels = dc * (w * h) * count;
132    double mpps = pixels / delta / 1000000;
133    double dc60 = pixels / delta / (w * h) / 60;
134
135    printf("test %s, Mpps %f, dc = %f\n", str, mpps, dc60);
136}
137
138static const char gVertexShader[] =
139    "attribute vec4 a_pos;\n"
140    "attribute vec4 a_color;\n"
141    "attribute vec2 a_tex0;\n"
142    "attribute vec2 a_tex1;\n"
143    "varying vec4 v_color;\n"
144    "varying vec2 v_tex0;\n"
145    "varying vec2 v_tex1;\n"
146
147    "void main() {\n"
148    "    v_color = a_color;\n"
149    "    v_tex0 = a_tex0;\n"
150    "    v_tex1 = a_tex1;\n"
151    "    gl_Position = a_pos;\n"
152    "}\n";
153
154static const char gShaderPrefix[] =
155    "precision mediump float;\n"
156    "uniform vec4 u_color;\n"
157    "uniform vec4 u_0;\n"
158    "uniform vec4 u_1;\n"
159    "uniform vec4 u_2;\n"
160    "uniform vec4 u_3;\n"
161    "varying vec4 v_color;\n"
162    "varying vec2 v_tex0;\n"
163    "varying vec2 v_tex1;\n"
164    "uniform sampler2D u_tex0;\n"
165    "uniform sampler2D u_tex1;\n"
166    "void main() {\n";
167
168static const char gShaderPostfix[] =
169    "  gl_FragColor = c;\n"
170    "}\n";
171
172
173static char * append(char *d, const char *s) {
174    size_t len = strlen(s);
175    memcpy(d, s, len);
176    return d + len;
177}
178
179static char * genShader(
180    bool useVarColor,
181    int texCount,
182    bool modulateFirstTex,
183    int extraMath)
184{
185    char *str = (char *)calloc(16 * 1024, 1);
186    char *tmp = append(str, gShaderPrefix);
187
188    if (modulateFirstTex || !texCount) {
189        if (useVarColor) {
190            tmp = append(tmp, "  vec4 c = v_color;\n");
191        } else {
192            tmp = append(tmp, "  vec4 c = u_color;\n");
193        }
194    } else {
195        tmp = append(tmp, "  vec4 c = texture2D(u_tex0, v_tex0);\n");
196    }
197
198    if (modulateFirstTex && texCount) {
199        tmp = append(tmp, "  c *= texture2D(u_tex0, v_tex0);\n");
200    }
201    if (texCount > 1) {
202        tmp = append(tmp, "  c *= texture2D(u_tex1, v_tex1);\n");
203    }
204
205    if (extraMath > 0) {
206        tmp = append(tmp, "  c *= u_0;\n");
207    }
208    if (extraMath > 1) {
209        tmp = append(tmp, "  c *= u_1;\n");
210    }
211    if (extraMath > 2) {
212        tmp = append(tmp, "  c *= u_2;\n");
213    }
214    if (extraMath > 3) {
215        tmp = append(tmp, "  c *= u_3;\n");
216    }
217
218
219    tmp = append(tmp, gShaderPostfix);
220    tmp[0] = 0;
221
222    //printf("%s", str);
223    return str;
224}
225
226static void setupVA() {
227    static const float vtx[] = {
228        -2.0f,-1.0f,
229         1.0f,-1.0f,
230        -2.0f, 1.0f,
231         1.0f, 1.0f };
232    static const float color[] = {
233        1.0f,0.0f,1.0f,1.0f,
234        0.0f,0.0f,1.0f,1.0f,
235        1.0f,1.0f,0.0f,1.0f,
236        1.0f,1.0f,1.0f,1.0f };
237    static const float tex0[] = {
238        0.0f,0.0f,
239        1.0f,0.0f,
240        1.0f,1.0f,
241        0.0f,1.0f };
242    static const float tex1[] = {
243        1.0f,0.0f,
244        1.0f,1.0f,
245        0.0f,1.0f,
246        0.0f,0.0f };
247
248    glEnableVertexAttribArray(A_POS);
249    glEnableVertexAttribArray(A_COLOR);
250    glEnableVertexAttribArray(A_TEX0);
251    glEnableVertexAttribArray(A_TEX1);
252
253    glVertexAttribPointer(A_POS, 2, GL_FLOAT, false, 8, vtx);
254    glVertexAttribPointer(A_COLOR, 4, GL_FLOAT, false, 16, color);
255    glVertexAttribPointer(A_TEX0, 2, GL_FLOAT, false, 8, tex0);
256    glVertexAttribPointer(A_TEX1, 2, GL_FLOAT, false, 8, tex1);
257}
258
259//////////////////////////
260
261void ptSwap();
262
263static void doLoop(uint32_t w, uint32_t h, const char *str) {
264    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
265    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
266    ptSwap();
267    glFinish();
268
269    startTimer();
270    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
271    for (int ct=0; ct < 100; ct++) {
272        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
273    }
274    ptSwap();
275    glFinish();
276    endTimer(str, w, h, 1, 100);
277}
278
279static void doSingleTest(uint32_t w, uint32_t h,
280                         bool useVarColor,
281                         int texCount,
282                         bool modulateFirstTex,
283                         int extraMath,
284                         int tex0, int tex1) {
285    char *pgmTxt = genShader(useVarColor, texCount, modulateFirstTex, extraMath);
286    int pgm = createProgram(gVertexShader, pgmTxt);
287    if (!pgm) {
288        printf("error running test\n");
289        return;
290    }
291    int loc = glGetUniformLocation(pgm, "u_tex0");
292    //printf("loc = %i \n", loc);
293    if (loc >= 0) glUniform1i(loc, 0);
294    loc = glGetUniformLocation(pgm, "u_tex1");
295    if (loc >= 0) glUniform1i(loc, 1);
296
297    loc = glGetUniformLocation(pgm, "u_color");
298    if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f);
299
300    loc = glGetUniformLocation(pgm, "u_0");
301    if (loc >= 0) glUniform4f(loc, 1.f, 0.4f, 0.6f, 0.8f);
302
303    loc = glGetUniformLocation(pgm, "u_1");
304    if (loc >= 0) glUniform4f(loc, 0.7f, 0.8f, 0.6f, 0.8f);
305
306    loc = glGetUniformLocation(pgm, "u_2");
307    if (loc >= 0) glUniform4f(loc, 0.9f, 0.6f, 0.7f, 1.0f);
308
309    loc = glGetUniformLocation(pgm, "u_3");
310    if (loc >= 0) glUniform4f(loc, 0.88f, 0.2f, 0.4f, 0.2f);
311
312    glActiveTexture(GL_TEXTURE0);
313    glBindTexture(GL_TEXTURE_2D, tex0);
314    glActiveTexture(GL_TEXTURE1);
315    glBindTexture(GL_TEXTURE_2D, tex1);
316    glActiveTexture(GL_TEXTURE0);
317
318    char str2[1024];
319
320    glBlendFunc(GL_ONE, GL_ONE);
321    glDisable(GL_BLEND);
322    sprintf(str2, "Test varColor=%i, texCount=%i, modulate=%i, extraMath=%i, texSize=%i, blend=0",
323            useVarColor, texCount, modulateFirstTex, extraMath, tex0);
324    doLoop(w, h, str2);
325
326    glEnable(GL_BLEND);
327    sprintf(str2, "Test varColor=%i, texCount=%i, modulate=%i, extraMath=%i, texSize=%i, blend=1",
328            useVarColor, texCount, modulateFirstTex, extraMath, tex0);
329    doLoop(w, h, str2);
330}
331
332void genTextures() {
333    uint32_t *m = (uint32_t *)malloc(1024*1024*4);
334    for (int y=0; y < 1024; y++){
335        for (int x=0; x < 1024; x++){
336            m[y*1024 + x] = 0xff0000ff | ((x & 0xff) << 8) | (y << 16);
337        }
338    }
339    glBindTexture(GL_TEXTURE_2D, 1);
340    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
341    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
342    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
343    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
344    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
345
346    for (int y=0; y < 16; y++){
347        for (int x=0; x < 16; x++){
348            m[y*16 + x] = 0xff0000ff | (x<<12) | (y<<20);
349        }
350    }
351    glBindTexture(GL_TEXTURE_2D, 2);
352    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
353    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
354    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
355    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
356    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
357
358}
359
360bool doTest(uint32_t w, uint32_t h) {
361    setupVA();
362    genTextures();
363
364    for (int texCount = 0; texCount < 3; texCount++) {
365        for (int extraMath = 0; extraMath < 5; extraMath++) {
366
367            doSingleTest(w, h, false, texCount, false, extraMath, 1, 1);
368            doSingleTest(w, h, true, texCount, false, extraMath, 1, 1);
369            if (texCount) {
370                doSingleTest(w, h, false, texCount, true, extraMath, 1, 1);
371                doSingleTest(w, h, true, texCount, true, extraMath, 1, 1);
372
373                doSingleTest(w, h, false, texCount, false, extraMath, 2, 2);
374                doSingleTest(w, h, true, texCount, false, extraMath, 2, 2);
375                doSingleTest(w, h, false, texCount, true, extraMath, 2, 2);
376                doSingleTest(w, h, true, texCount, true, extraMath, 2, 2);
377            }
378        }
379    }
380
381    exit(0);
382    return true;
383}
384