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