1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 #include "ShaderPerfRenderer.h"
15 #include <graphics/GLUtils.h>
16 
17 #include <math.h>
18 
19 #include <Trace.h>
20 
21 static const float GOLDEN_RATIO = (1.0f + sqrt(5.0f)) / 2.0f;
22 
23 static const int SP_NUM_VERTICES = 6;
24 
25 static const float SP_VERTICES[SP_NUM_VERTICES * 3] = {
26         1.0f, 1.0f, -1.0f,
27         -1.0f, 1.0f, -1.0f,
28         -1.0f, -1.0f, -1.0f,
29         -1.0f, -1.0f, -1.0f,
30         1.0f, -1.0f, -1.0f,
31         1.0f, 1.0f, -1.0f };
32 
33 static const float SP_TEX_COORDS[SP_NUM_VERTICES * 2] = {
34         1.0f, 1.0f,
35         0.0f, 1.0f,
36         0.0f, 0.0f,
37         0.0f, 0.0f,
38         1.0f, 0.0f,
39         1.0f, 1.0f };
40 
41 static const char* SP_VERTEX =
42         "attribute vec4 a_Position;"
43         "attribute vec2 a_TexCoord;"
44         "varying vec2 v_TexCoord;"
45         "void main() {"
46         "  v_TexCoord = a_TexCoord;"
47         "  gl_Position = a_Position;"
48         "}";
49 
50 static const char* SP_FRAGMENT_1 =
51         "precision mediump float;"
52         "uniform vec2 u_Seed;"
53         "uniform sampler2D u_Texture;"
54         "varying vec2 v_TexCoord;"
55         "void main() {"
56         "  int count = ";
57 
58 //Add workload here
59 
60 static const char* SP_FRAGMENT_2 =
61         " * 4;"//workload * 4 (4 is a tweaking number, bigger = more work)
62         "  vec2 z;"
63         "  z.x = 3.0 * (v_TexCoord.x - 0.5);"
64         "  z.y = 2.0 * (v_TexCoord.y - 0.5);"
65         "  float u = 0.0;"
66         "  for (int i = 0; i < count; i++) {"
67         "    float x = (z.x * z.x - z.y * z.y) + u_Seed.x;"
68         "    float y = (z.y * z.x + z.x * z.y) + u_Seed.y;"
69         "    if (((x * x + y * y) > 4.0) && (u == 0.0)) {"
70         "      u = float(i) / float(count);"
71         "    }"
72         "    z.x = x;"
73         "    z.y = y;"
74         "  }"
75         "  gl_FragColor = texture2D(u_Texture, vec2(u, 0.0));"
76         "}";
77 
78 // Copies the source array from 0 up to and including the '\0' character to the
79 // destination array starting from the given start position. Unlike strcpy, this
80 // returns the number of characters which were copied.
charCopy(const char * source,char * dest,int destStart)81 static int charCopy(const char* source, char* dest, int destStart) {
82     int srcAddr = 0;
83     int destAddr = destStart;
84     char current;
85     do {
86         current = source[srcAddr];
87         dest[destAddr] = current;
88         srcAddr++;
89         destAddr++;
90     } while (current != '\0');
91     return destAddr - destStart;
92 }
93 
ShaderPerfRenderer(ANativeWindow * window,bool offscreen)94 ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, bool offscreen) :
95         Renderer(window, offscreen) {
96 }
97 
setUp(int workload)98 bool ShaderPerfRenderer::setUp(int workload) {
99     SCOPED_TRACE();
100     if (!Renderer::setUp(workload)) {
101         return false;
102     }
103 
104     const int MAX_FRAGMENT_SHADER_SIZE = 1000;
105     char* spFragment = new char[MAX_FRAGMENT_SHADER_SIZE];
106     // Add the first part.
107     int index = charCopy(SP_FRAGMENT_1, spFragment, 0);
108     // Add the count, overwriting the '\0' added by charCopy.
109     spFragment[index - 1] = (char) (((int) '0') + workload);
110     // Add the second part.
111     index += charCopy(SP_FRAGMENT_2, spFragment, index);
112     // Create program.
113     mProgramId = GLUtils::createProgram(&SP_VERTEX, const_cast<const char**>(&spFragment));
114     delete[] spFragment;
115     if (mProgramId == 0) {
116         return false;
117     }
118     // Bind attributes.
119     mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
120     mSeedUniformHandle = glGetUniformLocation(mProgramId, "u_Seed");
121     mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
122     mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
123 
124     const int SIZE = 256;
125     uint32_t* m = new uint32_t[SIZE];
126     if (m != NULL) {
127         uint32_t* d = m;
128         for (int i = 0; i < SIZE; i++) {
129             *d = 0xff000000 | ((i & 0xff) << 16);
130             d++;
131         }
132         glGenTextures(1, &mTextureId);
133         glBindTexture(GL_TEXTURE_2D, mTextureId);
134         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
135         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
136         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
137         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
138     }
139     delete[] m;
140 
141     return true;
142 }
143 
drawWorkload()144 void ShaderPerfRenderer::drawWorkload() {
145     SCOPED_TRACE();
146     glUseProgram(mProgramId);
147     // Set the background clear color.
148     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
149     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
150 
151     // No culling of back faces
152     glDisable(GL_CULL_FACE);
153 
154     // Bind the texture.
155     glActiveTexture(GL_TEXTURE0);
156     glBindTexture(GL_TEXTURE_2D, mTextureId);
157     glUniform1i(mTextureUniformHandle, 0);
158 
159     // Bind the seed.
160     glUniform2f(mSeedUniformHandle, GOLDEN_RATIO - 2.0f, GOLDEN_RATIO - 1.0f);
161 
162     // Bind the vertices.
163     glEnableVertexAttribArray(mPositionHandle);
164     glEnableVertexAttribArray(mTexCoordHandle);
165     glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, SP_VERTICES);
166     glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, SP_TEX_COORDS);
167 
168     glDrawArrays(GL_TRIANGLES, 0, SP_NUM_VERTICES);
169 }
170