/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ #include "ShaderPerfRenderer.h" #include #include #include static const float GOLDEN_RATIO = (1.0f + sqrt(5.0f)) / 2.0f; static const int SP_NUM_VERTICES = 6; static const float SP_VERTICES[SP_NUM_VERTICES * 3] = { 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f }; static const float SP_TEX_COORDS[SP_NUM_VERTICES * 2] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }; static const char* SP_VERTEX = "attribute vec4 a_Position;" "attribute vec2 a_TexCoord;" "varying vec2 v_TexCoord;" "void main() {" " v_TexCoord = a_TexCoord;" " gl_Position = a_Position;" "}"; static const char* SP_FRAGMENT_1 = "precision mediump float;" "uniform vec2 u_Seed;" "uniform sampler2D u_Texture;" "varying vec2 v_TexCoord;" "void main() {" " int count = "; //Add workload here static const char* SP_FRAGMENT_2 = " * 4;"//workload * 4 (4 is a tweaking number, bigger = more work) " vec2 z;" " z.x = 3.0 * (v_TexCoord.x - 0.5);" " z.y = 2.0 * (v_TexCoord.y - 0.5);" " float u = 0.0;" " for (int i = 0; i < count; i++) {" " float x = (z.x * z.x - z.y * z.y) + u_Seed.x;" " float y = (z.y * z.x + z.x * z.y) + u_Seed.y;" " if (((x * x + y * y) > 4.0) && (u == 0.0)) {" " u = float(i) / float(count);" " }" " z.x = x;" " z.y = y;" " }" " gl_FragColor = texture2D(u_Texture, vec2(u, 0.0));" "}"; // Copies the source array from 0 up to and including the '\0' character to the // destination array starting from the given start position. Unlike strcpy, this // returns the number of characters which were copied. static int charCopy(const char* source, char* dest, int destStart) { int srcAddr = 0; int destAddr = destStart; char current; do { current = source[srcAddr]; dest[destAddr] = current; srcAddr++; destAddr++; } while (current != '\0'); return destAddr - destStart; } ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, bool offscreen) : Renderer(window, offscreen) { } bool ShaderPerfRenderer::setUp(int workload) { SCOPED_TRACE(); if (!Renderer::setUp(workload)) { return false; } const int MAX_FRAGMENT_SHADER_SIZE = 1000; char* spFragment = new char[MAX_FRAGMENT_SHADER_SIZE]; // Add the first part. int index = charCopy(SP_FRAGMENT_1, spFragment, 0); // Add the count, overwriting the '\0' added by charCopy. spFragment[index - 1] = (char) (((int) '0') + workload); // Add the second part. index += charCopy(SP_FRAGMENT_2, spFragment, index); // Create program. mProgramId = GLUtils::createProgram(&SP_VERTEX, const_cast(&spFragment)); delete[] spFragment; if (mProgramId == 0) { return false; } // Bind attributes. mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture"); mSeedUniformHandle = glGetUniformLocation(mProgramId, "u_Seed"); mPositionHandle = glGetAttribLocation(mProgramId, "a_Position"); mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord"); const int SIZE = 256; uint32_t* m = new uint32_t[SIZE]; if (m != NULL) { uint32_t* d = m; for (int i = 0; i < SIZE; i++) { *d = 0xff000000 | ((i & 0xff) << 16); d++; } glGenTextures(1, &mTextureId); glBindTexture(GL_TEXTURE_2D, mTextureId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); } delete[] m; return true; } void ShaderPerfRenderer::drawWorkload() { SCOPED_TRACE(); glUseProgram(mProgramId); // Set the background clear color. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // No culling of back faces glDisable(GL_CULL_FACE); // Bind the texture. glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTextureId); glUniform1i(mTextureUniformHandle, 0); // Bind the seed. glUniform2f(mSeedUniformHandle, GOLDEN_RATIO - 2.0f, GOLDEN_RATIO - 1.0f); // Bind the vertices. glEnableVertexAttribArray(mPositionHandle); glEnableVertexAttribArray(mTexCoordHandle); glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, SP_VERTICES); glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, SP_TEX_COORDS); glDrawArrays(GL_TRIANGLES, 0, SP_NUM_VERTICES); }