/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 2.0 Module * ------------------------------------------------- * * Copyright 2014 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. * *//*! * \file * \brief Texture format performance tests. *//*--------------------------------------------------------------------*/ #include "es2pTextureCases.hpp" #include "glsShaderPerformanceCase.hpp" #include "tcuTextureUtil.hpp" #include "tcuRenderTarget.hpp" #include "gluTexture.hpp" #include "gluStrUtil.hpp" #include "deStringUtil.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" namespace deqp { namespace gles2 { namespace Performance { using namespace gls; using namespace glw; // GL types using tcu::Vec2; using tcu::Vec3; using tcu::Vec4; using tcu::IVec4; using std::string; using std::vector; using tcu::TestLog; Texture2DRenderCase::Texture2DRenderCase (Context& context, const char* name, const char* description, deUint32 format, deUint32 dataType, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, const tcu::Mat3& coordTransform, int numTextures, bool powerOfTwo) : ShaderPerformanceCase (context.getTestContext(), context.getRenderContext(), name, description, CASETYPE_FRAGMENT) , m_format (format) , m_dataType (dataType) , m_wrapS (wrapS) , m_wrapT (wrapT) , m_minFilter (minFilter) , m_magFilter (magFilter) , m_coordTransform (coordTransform) , m_numTextures (numTextures) , m_powerOfTwo (powerOfTwo) { } Texture2DRenderCase::~Texture2DRenderCase (void) { for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) delete *i; m_textures.clear(); } static inline int roundDownToPowerOfTwo (int val) { DE_ASSERT(val >= 0); int l0 = deClz32(val); return val & ~((1<<(31-l0))-1); } void Texture2DRenderCase::init (void) { TestLog& log = m_testCtx.getLog(); int width = m_renderCtx.getRenderTarget().getWidth(); int height = m_renderCtx.getRenderTarget().getHeight(); if (m_powerOfTwo) { width = roundDownToPowerOfTwo(width); height = roundDownToPowerOfTwo(height); } bool mipmaps = m_minFilter == GL_NEAREST_MIPMAP_NEAREST || m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_NEAREST || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; DE_ASSERT(m_powerOfTwo || (!mipmaps && m_wrapS == GL_CLAMP_TO_EDGE && m_wrapT == GL_CLAMP_TO_EDGE)); Vec2 p00 = (m_coordTransform * Vec3(0.0f, 0.0f, 1.0f)).swizzle(0,1); Vec2 p10 = (m_coordTransform * Vec3(1.0f, 0.0f, 1.0f)).swizzle(0,1); Vec2 p01 = (m_coordTransform * Vec3(0.0f, 1.0f, 1.0f)).swizzle(0,1); Vec2 p11 = (m_coordTransform * Vec3(1.0f, 1.0f, 1.0f)).swizzle(0,1); m_attributes.push_back(AttribSpec("a_coords", Vec4(p00.x(), p00.y(), 0.0f, 0.0f), Vec4(p10.x(), p10.y(), 0.0f, 0.0f), Vec4(p01.x(), p01.y(), 0.0f, 0.0f), Vec4(p11.x(), p11.y(), 0.0f, 0.0f))); log << TestLog::Message << "Size: " << width << "x" << height << TestLog::EndMessage; log << TestLog::Message << "Format: " <<glu::getPixelFormatName(m_format) << " " << glu::getTypeName(m_dataType) << TestLog::EndMessage; log << TestLog::Message << "Coords: " << p00 << ", " << p10 << ", " << p01 << ", " << p11 << TestLog::EndMessage; log << TestLog::Message << "Wrap: " << glu::getTextureWrapModeStr(m_wrapS) << " / " << glu::getTextureWrapModeStr(m_wrapT) << TestLog::EndMessage; log << TestLog::Message << "Filter: " << glu::getTextureFilterStr(m_minFilter) << " / " << glu::getTextureFilterStr(m_magFilter) << TestLog::EndMessage; log << TestLog::Message << "Mipmaps: " << (mipmaps ? "true" : "false") << TestLog::EndMessage; log << TestLog::Message << "Using additive blending." << TestLog::EndMessage; // Use same viewport size as texture size. setViewportSize(width, height); m_vertShaderSource = "attribute highp vec4 a_position;\n" "attribute mediump vec2 a_coords;\n" "varying mediump vec2 v_coords;\n" "void main (void)\n" "{\n" " gl_Position = a_position;\n" " v_coords = a_coords;\n" "}\n"; std::ostringstream fragSrc; fragSrc << "varying mediump vec2 v_coords;\n"; for (int texNdx = 0; texNdx < m_numTextures; texNdx++) fragSrc << "uniform sampler2D u_sampler" << texNdx << ";\n"; fragSrc << "void main (void)\n" << "{\n"; for (int texNdx = 0; texNdx < m_numTextures; texNdx++) fragSrc << "\t" << (texNdx == 0 ? "lowp vec4 r = " : "r += ") << "texture2D(u_sampler" << texNdx << ", v_coords);\n"; fragSrc << " gl_FragColor = r;\n" << "}\n"; m_fragShaderSource = fragSrc.str(); m_textures.reserve(m_numTextures); for (int texNdx = 0; texNdx < m_numTextures; texNdx++) { static const IVec4 swizzles[] = { IVec4(0,1,2,3), IVec4(1,2,3,0), IVec4(2,3,0,1), IVec4(3,0,1,2), IVec4(3,2,1,0), IVec4(2,1,0,3), IVec4(1,0,3,2), IVec4(0,3,2,1) }; const IVec4& sw = swizzles[texNdx % DE_LENGTH_OF_ARRAY(swizzles)]; glu::Texture2D* texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, width, height); m_textures.push_back(texture); // Fill levels. int numLevels = mipmaps ? texture->getRefTexture().getNumLevels() : 1; for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) { texture->getRefTexture().allocLevel(levelNdx); tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(levelNdx), Vec4(0.0f, 0.0f, 0.0f, 0.0f).swizzle(sw[0], sw[1], sw[2], sw[3]), Vec4(1.0f, 1.0f, 1.0f, 1.0f).swizzle(sw[0], sw[1], sw[2], sw[3])); } texture->upload(); } ShaderPerformanceCase::init(); } void Texture2DRenderCase::deinit (void) { for (vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) delete *i; m_textures.clear(); ShaderPerformanceCase::deinit(); } void Texture2DRenderCase::setupProgram (deUint32 program) { const glw::Functions& gl = m_renderCtx.getFunctions(); for (int texNdx = 0; texNdx < m_numTextures; texNdx++) { int samplerLoc = gl.getUniformLocation(program, (string("u_sampler") + de::toString(texNdx)).c_str()); gl.uniform1i(samplerLoc, texNdx); } } void Texture2DRenderCase::setupRenderState (void) { const glw::Functions& gl = m_renderCtx.getFunctions(); // Setup additive blending. gl.enable(GL_BLEND); gl.blendFunc(GL_ONE, GL_ONE); gl.blendEquation(GL_FUNC_ADD); // Setup textures. for (int texNdx = 0; texNdx < m_numTextures; texNdx++) { gl.activeTexture(GL_TEXTURE0 + texNdx); gl.bindTexture(GL_TEXTURE_2D, m_textures[texNdx]->getGLTexture()); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); } } } // Performance } // gles2 } // deqp