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. 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 94 ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, bool offscreen) : 95 Renderer(window, offscreen) { 96 } 97 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 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