1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 2.0 Module 3e5c31af7Sopenharmony_ci * ------------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Texture unit usage tests. 22e5c31af7Sopenharmony_ci * 23e5c31af7Sopenharmony_ci * \todo [2012-07-12 nuutti] Come up with a good way to make these tests faster. 24e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "es2fTextureUnitTests.hpp" 27e5c31af7Sopenharmony_ci#include "glsTextureTestUtil.hpp" 28e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp" 29e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 30e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 31e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp" 32e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp" 33e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 34e5c31af7Sopenharmony_ci#include "sglrContextUtil.hpp" 35e5c31af7Sopenharmony_ci#include "sglrReferenceContext.hpp" 36e5c31af7Sopenharmony_ci#include "sglrGLContext.hpp" 37e5c31af7Sopenharmony_ci#include "deMath.h" 38e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 39e5c31af7Sopenharmony_ci#include "deRandom.hpp" 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 42e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 43e5c31af7Sopenharmony_ci 44e5c31af7Sopenharmony_ciusing tcu::Vec2; 45e5c31af7Sopenharmony_ciusing tcu::Vec3; 46e5c31af7Sopenharmony_ciusing tcu::Vec4; 47e5c31af7Sopenharmony_ciusing tcu::IVec2; 48e5c31af7Sopenharmony_ciusing tcu::Mat3; 49e5c31af7Sopenharmony_ciusing std::vector; 50e5c31af7Sopenharmony_ciusing std::string; 51e5c31af7Sopenharmony_ciusing namespace glw; // GL types 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_cinamespace deqp 54e5c31af7Sopenharmony_ci{ 55e5c31af7Sopenharmony_ci 56e5c31af7Sopenharmony_ciusing namespace gls::TextureTestUtil; 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_cinamespace gles2 59e5c31af7Sopenharmony_ci{ 60e5c31af7Sopenharmony_cinamespace Functional 61e5c31af7Sopenharmony_ci{ 62e5c31af7Sopenharmony_ci 63e5c31af7Sopenharmony_cistatic const int VIEWPORT_WIDTH = 128; 64e5c31af7Sopenharmony_cistatic const int VIEWPORT_HEIGHT = 128; 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_cistatic const int TEXTURE_WIDTH_2D = 128; 67e5c31af7Sopenharmony_cistatic const int TEXTURE_HEIGHT_2D = 128; 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci// \note Cube map texture size is larger in order to make minifications possible - otherwise would need to display different faces at same time. 70e5c31af7Sopenharmony_cistatic const int TEXTURE_WIDTH_CUBE = 256; 71e5c31af7Sopenharmony_cistatic const int TEXTURE_HEIGHT_CUBE = 256; 72e5c31af7Sopenharmony_ci 73e5c31af7Sopenharmony_cistatic const int GRID_CELL_SIZE = 8; 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_cistatic const GLenum s_testFormats[] = 76e5c31af7Sopenharmony_ci{ 77e5c31af7Sopenharmony_ci GL_RGB, 78e5c31af7Sopenharmony_ci GL_RGBA, 79e5c31af7Sopenharmony_ci GL_ALPHA, 80e5c31af7Sopenharmony_ci GL_LUMINANCE, 81e5c31af7Sopenharmony_ci GL_LUMINANCE_ALPHA 82e5c31af7Sopenharmony_ci}; 83e5c31af7Sopenharmony_ci 84e5c31af7Sopenharmony_cistatic const GLenum s_testDataTypes[] = 85e5c31af7Sopenharmony_ci{ 86e5c31af7Sopenharmony_ci GL_UNSIGNED_BYTE, 87e5c31af7Sopenharmony_ci GL_UNSIGNED_SHORT_5_6_5, 88e5c31af7Sopenharmony_ci GL_UNSIGNED_SHORT_4_4_4_4, 89e5c31af7Sopenharmony_ci GL_UNSIGNED_SHORT_5_5_5_1, 90e5c31af7Sopenharmony_ci}; 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_cistatic const GLenum s_testWrapModes[] = 93e5c31af7Sopenharmony_ci{ 94e5c31af7Sopenharmony_ci GL_CLAMP_TO_EDGE, 95e5c31af7Sopenharmony_ci GL_REPEAT, 96e5c31af7Sopenharmony_ci GL_MIRRORED_REPEAT, 97e5c31af7Sopenharmony_ci}; 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_cistatic const GLenum s_testMinFilters[] = 100e5c31af7Sopenharmony_ci{ 101e5c31af7Sopenharmony_ci GL_NEAREST, 102e5c31af7Sopenharmony_ci GL_LINEAR, 103e5c31af7Sopenharmony_ci GL_NEAREST_MIPMAP_NEAREST, 104e5c31af7Sopenharmony_ci GL_LINEAR_MIPMAP_NEAREST, 105e5c31af7Sopenharmony_ci GL_NEAREST_MIPMAP_LINEAR, 106e5c31af7Sopenharmony_ci GL_LINEAR_MIPMAP_LINEAR 107e5c31af7Sopenharmony_ci}; 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_cistatic const GLenum s_testNonMipmapMinFilters[] = 110e5c31af7Sopenharmony_ci{ 111e5c31af7Sopenharmony_ci GL_NEAREST, 112e5c31af7Sopenharmony_ci GL_LINEAR 113e5c31af7Sopenharmony_ci}; 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_cistatic const GLenum s_testMagFilters[] = 116e5c31af7Sopenharmony_ci{ 117e5c31af7Sopenharmony_ci GL_NEAREST, 118e5c31af7Sopenharmony_ci GL_LINEAR 119e5c31af7Sopenharmony_ci}; 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_cistatic const GLenum s_cubeFaceTargets[] = 122e5c31af7Sopenharmony_ci{ 123e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_X, 124e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 125e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 126e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 127e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 128e5c31af7Sopenharmony_ci GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 129e5c31af7Sopenharmony_ci}; 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_cistatic string generateMultiTexFragmentShader(int numUnits, const GLenum* unitTypes) 132e5c31af7Sopenharmony_ci{ 133e5c31af7Sopenharmony_ci // The fragment shader calculates the average of a set of textures. 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci string samplersStr; 136e5c31af7Sopenharmony_ci string matricesStr; 137e5c31af7Sopenharmony_ci string lookupsStr; 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci string colorMultiplier = "(1.0/" + de::toString(numUnits) + ".0)"; 140e5c31af7Sopenharmony_ci 141e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numUnits; ndx++) 142e5c31af7Sopenharmony_ci { 143e5c31af7Sopenharmony_ci string ndxStr = de::toString(ndx); 144e5c31af7Sopenharmony_ci string samplerName = "u_sampler" + ndxStr; 145e5c31af7Sopenharmony_ci string transformationName = "u_trans" + ndxStr; 146e5c31af7Sopenharmony_ci const char* samplerType = unitTypes[ndx] == GL_TEXTURE_2D ? "sampler2D" : "samplerCube"; 147e5c31af7Sopenharmony_ci const char* lookupFunc = unitTypes[ndx] == GL_TEXTURE_2D ? "texture2D" : "textureCube"; 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci samplersStr += string("") + "uniform mediump " + samplerType + " " + samplerName + ";\n"; 150e5c31af7Sopenharmony_ci matricesStr += "uniform mediump mat3 " + transformationName + ";\n"; 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci string lookupCoord = transformationName + "*vec3(v_coord, 1.0)"; 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci if (unitTypes[ndx] == GL_TEXTURE_2D) 155e5c31af7Sopenharmony_ci lookupCoord = "vec2(" + lookupCoord + ")"; 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci lookupsStr += "\tcolor += " + colorMultiplier + "*" + lookupFunc + "(" + samplerName + ", " + lookupCoord + ");\n"; 158e5c31af7Sopenharmony_ci } 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci return 161e5c31af7Sopenharmony_ci samplersStr + 162e5c31af7Sopenharmony_ci matricesStr + 163e5c31af7Sopenharmony_ci "varying mediump vec2 v_coord;\n" 164e5c31af7Sopenharmony_ci "\n" 165e5c31af7Sopenharmony_ci "void main (void)\n" 166e5c31af7Sopenharmony_ci "{\n" 167e5c31af7Sopenharmony_ci " mediump vec4 color = vec4(0.0);\n" + 168e5c31af7Sopenharmony_ci lookupsStr + 169e5c31af7Sopenharmony_ci " gl_FragColor = color;\n" 170e5c31af7Sopenharmony_ci "}\n"; 171e5c31af7Sopenharmony_ci} 172e5c31af7Sopenharmony_ci 173e5c31af7Sopenharmony_cistatic sglr::pdec::ShaderProgramDeclaration generateShaderProgramDeclaration (int numUnits, const GLenum* unitTypes) 174e5c31af7Sopenharmony_ci{ 175e5c31af7Sopenharmony_ci sglr::pdec::ShaderProgramDeclaration decl; 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT); 178e5c31af7Sopenharmony_ci decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT); 179e5c31af7Sopenharmony_ci decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT); 180e5c31af7Sopenharmony_ci decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT); 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numUnits; ++ndx) 183e5c31af7Sopenharmony_ci { 184e5c31af7Sopenharmony_ci string samplerName = "u_sampler" + de::toString(ndx); 185e5c31af7Sopenharmony_ci string transformationName = "u_trans" + de::toString(ndx); 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci decl << sglr::pdec::Uniform(samplerName, (unitTypes[ndx] == GL_TEXTURE_2D) ? (glu::TYPE_SAMPLER_2D) : (glu::TYPE_SAMPLER_CUBE)); 188e5c31af7Sopenharmony_ci decl << sglr::pdec::Uniform(transformationName, glu::TYPE_FLOAT_MAT3); 189e5c31af7Sopenharmony_ci } 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_ci decl << sglr::pdec::VertexSource("attribute highp vec4 a_position;\n" 192e5c31af7Sopenharmony_ci "attribute mediump vec2 a_coord;\n" 193e5c31af7Sopenharmony_ci "varying mediump vec2 v_coord;\n" 194e5c31af7Sopenharmony_ci "\n" 195e5c31af7Sopenharmony_ci "void main (void)\n" 196e5c31af7Sopenharmony_ci "{\n" 197e5c31af7Sopenharmony_ci " gl_Position = a_position;\n" 198e5c31af7Sopenharmony_ci " v_coord = a_coord;\n" 199e5c31af7Sopenharmony_ci "}\n"); 200e5c31af7Sopenharmony_ci decl << sglr::pdec::FragmentSource(generateMultiTexFragmentShader(numUnits, unitTypes)); 201e5c31af7Sopenharmony_ci 202e5c31af7Sopenharmony_ci return decl; 203e5c31af7Sopenharmony_ci} 204e5c31af7Sopenharmony_ci 205e5c31af7Sopenharmony_ci// Calculates values to be used in calculateLod(). 206e5c31af7Sopenharmony_cistatic Vec4 calculateLodDerivateParts(const Mat3& transformation) 207e5c31af7Sopenharmony_ci{ 208e5c31af7Sopenharmony_ci // Calculate transformed coordinates of three corners. 209e5c31af7Sopenharmony_ci Vec2 trans00 = (transformation * Vec3(0.0f, 0.0f, 1.0f)).xy(); 210e5c31af7Sopenharmony_ci Vec2 trans01 = (transformation * Vec3(0.0f, 1.0f, 1.0f)).xy(); 211e5c31af7Sopenharmony_ci Vec2 trans10 = (transformation * Vec3(1.0f, 0.0f, 1.0f)).xy(); 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci return Vec4(trans10.x() - trans00.x(), 214e5c31af7Sopenharmony_ci trans01.x() - trans00.x(), 215e5c31af7Sopenharmony_ci trans10.y() - trans00.y(), 216e5c31af7Sopenharmony_ci trans01.y() - trans00.y()); 217e5c31af7Sopenharmony_ci} 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci// Calculates the maximum allowed lod from derivates 220e5c31af7Sopenharmony_cistatic float calculateLodMax(const Vec4& derivateParts, const tcu::IVec2& textureSize, const Vec2& screenDerivate) 221e5c31af7Sopenharmony_ci{ 222e5c31af7Sopenharmony_ci float dudx = derivateParts.x() * (float)textureSize.x() * screenDerivate.x(); 223e5c31af7Sopenharmony_ci float dudy = derivateParts.y() * (float)textureSize.x() * screenDerivate.y(); 224e5c31af7Sopenharmony_ci float dvdx = derivateParts.z() * (float)textureSize.y() * screenDerivate.x(); 225e5c31af7Sopenharmony_ci float dvdy = derivateParts.w() * (float)textureSize.y() * screenDerivate.y(); 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci return deFloatLog2(de::max(de::abs(dudx), de::abs(dudy)) + de::max(de::abs(dvdx), de::abs(dvdy))); 228e5c31af7Sopenharmony_ci} 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ci// Calculates the minimum allowed lod from derivates 231e5c31af7Sopenharmony_cistatic float calculateLodMin(const Vec4& derivateParts, const tcu::IVec2& textureSize, const Vec2& screenDerivate) 232e5c31af7Sopenharmony_ci{ 233e5c31af7Sopenharmony_ci float dudx = derivateParts.x() * (float)textureSize.x() * screenDerivate.x(); 234e5c31af7Sopenharmony_ci float dudy = derivateParts.y() * (float)textureSize.x() * screenDerivate.y(); 235e5c31af7Sopenharmony_ci float dvdx = derivateParts.z() * (float)textureSize.y() * screenDerivate.x(); 236e5c31af7Sopenharmony_ci float dvdy = derivateParts.w() * (float)textureSize.y() * screenDerivate.y(); 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci return deFloatLog2(de::max(de::max(de::abs(dudx), de::abs(dudy)), de::max(de::abs(dvdx), de::abs(dvdy)))); 239e5c31af7Sopenharmony_ci} 240e5c31af7Sopenharmony_ci 241e5c31af7Sopenharmony_ciclass MultiTexShader : public sglr::ShaderProgram 242e5c31af7Sopenharmony_ci{ 243e5c31af7Sopenharmony_cipublic: 244e5c31af7Sopenharmony_ci MultiTexShader (deUint32 randSeed, int numUnits, const vector<GLenum>& unitTypes); 245e5c31af7Sopenharmony_ci 246e5c31af7Sopenharmony_ci void setUniforms (sglr::Context& context, deUint32 program) const; 247e5c31af7Sopenharmony_ci void makeSafeLods (const vector<IVec2>& textureSizes, const IVec2& viewportSize); // Modifies texture coordinates so that LODs aren't too close to x.5 or 0.0 . 248e5c31af7Sopenharmony_ci 249e5c31af7Sopenharmony_ciprivate: 250e5c31af7Sopenharmony_ci void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 251e5c31af7Sopenharmony_ci void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_ci int m_numUnits; 254e5c31af7Sopenharmony_ci vector<GLenum> m_unitTypes; // 2d or cube map. 255e5c31af7Sopenharmony_ci vector<Mat3> m_transformations; 256e5c31af7Sopenharmony_ci vector<Vec4> m_lodDerivateParts; // Parts of lod derivates; computed in init(), used in eval(). 257e5c31af7Sopenharmony_ci}; 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ciMultiTexShader::MultiTexShader (deUint32 randSeed, int numUnits, const vector<GLenum>& unitTypes) 260e5c31af7Sopenharmony_ci : sglr::ShaderProgram (generateShaderProgramDeclaration(numUnits, &unitTypes[0])) 261e5c31af7Sopenharmony_ci , m_numUnits (numUnits) 262e5c31af7Sopenharmony_ci , m_unitTypes (unitTypes) 263e5c31af7Sopenharmony_ci{ 264e5c31af7Sopenharmony_ci // 2d-to-cube-face transformations. 265e5c31af7Sopenharmony_ci // \note 2d coordinates range from 0 to 1 and cube face coordinates from -1 to 1, so scaling is done as well. 266e5c31af7Sopenharmony_ci static const float s_cubeTransforms[][3*3] = 267e5c31af7Sopenharmony_ci { 268e5c31af7Sopenharmony_ci // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1)) 269e5c31af7Sopenharmony_ci { 0.0f, 0.0f, -1.0f, 270e5c31af7Sopenharmony_ci 0.0f, -2.0f, 1.0f, 271e5c31af7Sopenharmony_ci 2.0f, 0.0f, -1.0f }, 272e5c31af7Sopenharmony_ci // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1)) 273e5c31af7Sopenharmony_ci { 0.0f, 0.0f, 1.0f, 274e5c31af7Sopenharmony_ci 0.0f, -2.0f, 1.0f, 275e5c31af7Sopenharmony_ci -2.0f, 0.0f, 1.0f }, 276e5c31af7Sopenharmony_ci // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1)) 277e5c31af7Sopenharmony_ci { 2.0f, 0.0f, -1.0f, 278e5c31af7Sopenharmony_ci 0.0f, 0.0f, -1.0f, 279e5c31af7Sopenharmony_ci 0.0f, -2.0f, 1.0f }, 280e5c31af7Sopenharmony_ci // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1)) 281e5c31af7Sopenharmony_ci { 2.0f, 0.0f, -1.0f, 282e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f, 283e5c31af7Sopenharmony_ci 0.0f, 2.0f, -1.0f }, 284e5c31af7Sopenharmony_ci // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1) 285e5c31af7Sopenharmony_ci { -2.0f, 0.0f, 1.0f, 286e5c31af7Sopenharmony_ci 0.0f, -2.0f, 1.0f, 287e5c31af7Sopenharmony_ci 0.0f, 0.0f, -1.0f }, 288e5c31af7Sopenharmony_ci // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1) 289e5c31af7Sopenharmony_ci { 2.0f, 0.0f, -1.0f, 290e5c31af7Sopenharmony_ci 0.0f, -2.0f, 1.0f, 291e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f } 292e5c31af7Sopenharmony_ci }; 293e5c31af7Sopenharmony_ci 294e5c31af7Sopenharmony_ci // Generate transformation matrices. 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci de::Random rnd(randSeed); 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_ci m_transformations.reserve(m_numUnits); 299e5c31af7Sopenharmony_ci m_lodDerivateParts.reserve(m_numUnits); 300e5c31af7Sopenharmony_ci 301e5c31af7Sopenharmony_ci DE_ASSERT((int)m_unitTypes.size() == m_numUnits); 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++) 304e5c31af7Sopenharmony_ci { 305e5c31af7Sopenharmony_ci if (m_unitTypes[unitNdx] == GL_TEXTURE_2D) 306e5c31af7Sopenharmony_ci { 307e5c31af7Sopenharmony_ci float rotAngle = rnd.getFloat(0.0f, 2.0f*DE_PI); 308e5c31af7Sopenharmony_ci float xScaleFactor = rnd.getFloat(0.7f, 1.5f); 309e5c31af7Sopenharmony_ci float yScaleFactor = rnd.getFloat(0.7f, 1.5f); 310e5c31af7Sopenharmony_ci float xShearAmount = rnd.getFloat(0.0f, 0.5f); 311e5c31af7Sopenharmony_ci float yShearAmount = rnd.getFloat(0.0f, 0.5f); 312e5c31af7Sopenharmony_ci float xTranslationAmount = rnd.getFloat(-0.5f, 0.5f); 313e5c31af7Sopenharmony_ci float yTranslationAmount = rnd.getFloat(-0.5f, 0.5f); 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci float tempOffsetData[3*3] = // For temporarily centering the coordinates to get nicer transformations. 316e5c31af7Sopenharmony_ci { 317e5c31af7Sopenharmony_ci 1.0f, 0.0f, -0.5f, 318e5c31af7Sopenharmony_ci 0.0f, 1.0f, -0.5f, 319e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 320e5c31af7Sopenharmony_ci }; 321e5c31af7Sopenharmony_ci float rotTransfData[3*3] = 322e5c31af7Sopenharmony_ci { 323e5c31af7Sopenharmony_ci deFloatCos(rotAngle), -deFloatSin(rotAngle), 0.0f, 324e5c31af7Sopenharmony_ci deFloatSin(rotAngle), deFloatCos(rotAngle), 0.0f, 325e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 326e5c31af7Sopenharmony_ci }; 327e5c31af7Sopenharmony_ci float scaleTransfData[3*3] = 328e5c31af7Sopenharmony_ci { 329e5c31af7Sopenharmony_ci xScaleFactor, 0.0f, 0.0f, 330e5c31af7Sopenharmony_ci 0.0f, yScaleFactor, 0.0f, 331e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 332e5c31af7Sopenharmony_ci }; 333e5c31af7Sopenharmony_ci float xShearTransfData[3*3] = 334e5c31af7Sopenharmony_ci { 335e5c31af7Sopenharmony_ci 1.0f, xShearAmount, 0.0f, 336e5c31af7Sopenharmony_ci 0.0f, 1.0f, 0.0f, 337e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 338e5c31af7Sopenharmony_ci }; 339e5c31af7Sopenharmony_ci float yShearTransfData[3*3] = 340e5c31af7Sopenharmony_ci { 341e5c31af7Sopenharmony_ci 1.0f, 0.0f, 0.0f, 342e5c31af7Sopenharmony_ci yShearAmount, 1.0f, 0.0f, 343e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 344e5c31af7Sopenharmony_ci }; 345e5c31af7Sopenharmony_ci float translationTransfData[3*3] = 346e5c31af7Sopenharmony_ci { 347e5c31af7Sopenharmony_ci 1.0f, 0.0f, xTranslationAmount, 348e5c31af7Sopenharmony_ci 0.0f, 1.0f, yTranslationAmount, 349e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 350e5c31af7Sopenharmony_ci }; 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci Mat3 transformation = 353e5c31af7Sopenharmony_ci Mat3(tempOffsetData) * 354e5c31af7Sopenharmony_ci Mat3(translationTransfData) * 355e5c31af7Sopenharmony_ci Mat3(rotTransfData) * 356e5c31af7Sopenharmony_ci Mat3(scaleTransfData) * 357e5c31af7Sopenharmony_ci Mat3(xShearTransfData) * 358e5c31af7Sopenharmony_ci Mat3(yShearTransfData) * 359e5c31af7Sopenharmony_ci (Mat3(tempOffsetData) * (-1.0f)); 360e5c31af7Sopenharmony_ci 361e5c31af7Sopenharmony_ci // Calculate parts of lod derivates. 362e5c31af7Sopenharmony_ci m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation)); 363e5c31af7Sopenharmony_ci 364e5c31af7Sopenharmony_ci m_transformations.push_back(transformation); 365e5c31af7Sopenharmony_ci } 366e5c31af7Sopenharmony_ci else 367e5c31af7Sopenharmony_ci { 368e5c31af7Sopenharmony_ci DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP); 369e5c31af7Sopenharmony_ci DE_STATIC_ASSERT((int)tcu::CUBEFACE_LAST == DE_LENGTH_OF_ARRAY(s_cubeTransforms)); 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci float planarTransData[3*3]; 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci // In case of a cube map, we only want to render one face, so the transformation needs to be restricted - only enlarging scaling is done. 374e5c31af7Sopenharmony_ci 375e5c31af7Sopenharmony_ci for (int i = 0; i < DE_LENGTH_OF_ARRAY(planarTransData); i++) 376e5c31af7Sopenharmony_ci { 377e5c31af7Sopenharmony_ci if (i == 0 || i == 4) 378e5c31af7Sopenharmony_ci planarTransData[i] = rnd.getFloat(0.1f, 0.9f); // Two first diagonal cells control the scaling. 379e5c31af7Sopenharmony_ci else if (i == 8) 380e5c31af7Sopenharmony_ci planarTransData[i] = 1.0f; 381e5c31af7Sopenharmony_ci else 382e5c31af7Sopenharmony_ci planarTransData[i] = 0.0f; 383e5c31af7Sopenharmony_ci } 384e5c31af7Sopenharmony_ci 385e5c31af7Sopenharmony_ci int faceNdx = rnd.getInt(0, (int)tcu::CUBEFACE_LAST - 1); 386e5c31af7Sopenharmony_ci Mat3 planarTrans (planarTransData); // Planar, face-agnostic transformation. 387e5c31af7Sopenharmony_ci Mat3 finalTrans = Mat3(s_cubeTransforms[faceNdx]) * planarTrans; // Final transformation from planar to cube map coordinates, including the transformation just generated. 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ci // Calculate parts of lod derivates. 390e5c31af7Sopenharmony_ci m_lodDerivateParts.push_back(calculateLodDerivateParts(planarTrans)); 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci m_transformations.push_back(finalTrans); 393e5c31af7Sopenharmony_ci } 394e5c31af7Sopenharmony_ci } 395e5c31af7Sopenharmony_ci} 396e5c31af7Sopenharmony_ci 397e5c31af7Sopenharmony_civoid MultiTexShader::setUniforms (sglr::Context& ctx, deUint32 program) const 398e5c31af7Sopenharmony_ci{ 399e5c31af7Sopenharmony_ci ctx.useProgram(program); 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_ci // Sampler and matrix uniforms. 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < m_numUnits; ndx++) 404e5c31af7Sopenharmony_ci { 405e5c31af7Sopenharmony_ci string ndxStr = de::toString(ndx); 406e5c31af7Sopenharmony_ci 407e5c31af7Sopenharmony_ci ctx.uniform1i(ctx.getUniformLocation(program, ("u_sampler" + ndxStr).c_str()), ndx); 408e5c31af7Sopenharmony_ci ctx.uniformMatrix3fv(ctx.getUniformLocation(program, ("u_trans" + ndxStr).c_str()), 1, GL_FALSE, (GLfloat*)&m_transformations[ndx].getColumnMajorData()[0]); 409e5c31af7Sopenharmony_ci } 410e5c31af7Sopenharmony_ci} 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_civoid MultiTexShader::makeSafeLods (const vector<IVec2>& textureSizes, const IVec2& viewportSize) 413e5c31af7Sopenharmony_ci{ 414e5c31af7Sopenharmony_ci DE_ASSERT((int)textureSizes.size() == m_numUnits); 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci static const float shrinkScaleMatData[3*3] = 417e5c31af7Sopenharmony_ci { 418e5c31af7Sopenharmony_ci 0.95f, 0.0f, 0.0f, 419e5c31af7Sopenharmony_ci 0.0f, 0.95f, 0.0f, 420e5c31af7Sopenharmony_ci 0.0f, 0.0f, 1.0f 421e5c31af7Sopenharmony_ci }; 422e5c31af7Sopenharmony_ci Mat3 shrinkScaleMat(shrinkScaleMatData); 423e5c31af7Sopenharmony_ci 424e5c31af7Sopenharmony_ci Vec2 screenDerivate(1.0f / (float)viewportSize.x(), 1.0f / (float)viewportSize.y()); 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++) 427e5c31af7Sopenharmony_ci { 428e5c31af7Sopenharmony_ci // As long as LOD is too close to 0.0 or is positive and too close to a something-and-a-half (0.5, 1.5, 2.5 etc) or allowed lod range could round to different levels, zoom in a little to get a safer LOD. 429e5c31af7Sopenharmony_ci for (;;) 430e5c31af7Sopenharmony_ci { 431e5c31af7Sopenharmony_ci const float threshold = 0.1f; 432e5c31af7Sopenharmony_ci const float epsilon = 0.01f; 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_ci const float lodMax = calculateLodMax(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate); 435e5c31af7Sopenharmony_ci const float lodMin = calculateLodMin(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate); 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_ci const deInt32 maxLevel = (lodMax + epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMax + epsilon + 0.5f) - 1); 438e5c31af7Sopenharmony_ci const deInt32 minLevel = (lodMin - epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMin - epsilon + 0.5f) - 1); 439e5c31af7Sopenharmony_ci 440e5c31af7Sopenharmony_ci if (de::abs(lodMax) < threshold || (lodMax > 0.0f && de::abs(deFloatFrac(lodMax) - 0.5f) < threshold) || 441e5c31af7Sopenharmony_ci de::abs(lodMin) < threshold || (lodMin > 0.0f && de::abs(deFloatFrac(lodMin) - 0.5f) < threshold) || 442e5c31af7Sopenharmony_ci maxLevel != minLevel) 443e5c31af7Sopenharmony_ci { 444e5c31af7Sopenharmony_ci m_transformations[unitNdx] = shrinkScaleMat * m_transformations[unitNdx]; 445e5c31af7Sopenharmony_ci m_lodDerivateParts[unitNdx] = calculateLodDerivateParts(m_transformations[unitNdx]); 446e5c31af7Sopenharmony_ci } 447e5c31af7Sopenharmony_ci else 448e5c31af7Sopenharmony_ci break; 449e5c31af7Sopenharmony_ci } 450e5c31af7Sopenharmony_ci } 451e5c31af7Sopenharmony_ci} 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_civoid MultiTexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 454e5c31af7Sopenharmony_ci{ 455e5c31af7Sopenharmony_ci for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 456e5c31af7Sopenharmony_ci { 457e5c31af7Sopenharmony_ci rr::VertexPacket& packet = *(packets[packetNdx]); 458e5c31af7Sopenharmony_ci 459e5c31af7Sopenharmony_ci packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); 460e5c31af7Sopenharmony_ci packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); 461e5c31af7Sopenharmony_ci } 462e5c31af7Sopenharmony_ci} 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_civoid MultiTexShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 465e5c31af7Sopenharmony_ci{ 466e5c31af7Sopenharmony_ci DE_ASSERT((int)m_unitTypes.size() == m_numUnits); 467e5c31af7Sopenharmony_ci DE_ASSERT((int)m_transformations.size() == m_numUnits); 468e5c31af7Sopenharmony_ci DE_ASSERT((int)m_lodDerivateParts.size() == m_numUnits); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 471e5c31af7Sopenharmony_ci { 472e5c31af7Sopenharmony_ci rr::FragmentPacket& packet = packets[packetNdx]; 473e5c31af7Sopenharmony_ci const float colorMultiplier = 1.0f / (float)m_numUnits; 474e5c31af7Sopenharmony_ci Vec4 outColors[4] = { Vec4(0.0f), Vec4(0.0f), Vec4(0.0f), Vec4(0.0f) }; 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_ci for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++) 477e5c31af7Sopenharmony_ci { 478e5c31af7Sopenharmony_ci tcu::Vec4 texSamples[4]; 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_ci // Read tex coords 481e5c31af7Sopenharmony_ci const tcu::Vec2 texCoords[4] = 482e5c31af7Sopenharmony_ci { 483e5c31af7Sopenharmony_ci rr::readTriangleVarying<float>(packet, context, 0, 0).xy(), 484e5c31af7Sopenharmony_ci rr::readTriangleVarying<float>(packet, context, 0, 1).xy(), 485e5c31af7Sopenharmony_ci rr::readTriangleVarying<float>(packet, context, 0, 2).xy(), 486e5c31af7Sopenharmony_ci rr::readTriangleVarying<float>(packet, context, 0, 3).xy(), 487e5c31af7Sopenharmony_ci }; 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci if (m_unitTypes[unitNdx] == GL_TEXTURE_2D) 490e5c31af7Sopenharmony_ci { 491e5c31af7Sopenharmony_ci // Transform 492e5c31af7Sopenharmony_ci const tcu::Vec2 transformedTexCoords[4] = 493e5c31af7Sopenharmony_ci { 494e5c31af7Sopenharmony_ci (m_transformations[unitNdx] * Vec3(texCoords[0].x(), texCoords[0].y(), 1.0f)).xy(), 495e5c31af7Sopenharmony_ci (m_transformations[unitNdx] * Vec3(texCoords[1].x(), texCoords[1].y(), 1.0f)).xy(), 496e5c31af7Sopenharmony_ci (m_transformations[unitNdx] * Vec3(texCoords[2].x(), texCoords[2].y(), 1.0f)).xy(), 497e5c31af7Sopenharmony_ci (m_transformations[unitNdx] * Vec3(texCoords[3].x(), texCoords[3].y(), 1.0f)).xy(), 498e5c31af7Sopenharmony_ci }; 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci // Sample 501e5c31af7Sopenharmony_ci m_uniforms[2*unitNdx].sampler.tex2D->sample4(texSamples, transformedTexCoords); 502e5c31af7Sopenharmony_ci } 503e5c31af7Sopenharmony_ci else 504e5c31af7Sopenharmony_ci { 505e5c31af7Sopenharmony_ci DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP); 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_ci // Transform 508e5c31af7Sopenharmony_ci const tcu::Vec3 transformedTexCoords[4] = 509e5c31af7Sopenharmony_ci { 510e5c31af7Sopenharmony_ci m_transformations[unitNdx] * Vec3(texCoords[0].x(), texCoords[0].y(), 1.0f), 511e5c31af7Sopenharmony_ci m_transformations[unitNdx] * Vec3(texCoords[1].x(), texCoords[1].y(), 1.0f), 512e5c31af7Sopenharmony_ci m_transformations[unitNdx] * Vec3(texCoords[2].x(), texCoords[2].y(), 1.0f), 513e5c31af7Sopenharmony_ci m_transformations[unitNdx] * Vec3(texCoords[3].x(), texCoords[3].y(), 1.0f), 514e5c31af7Sopenharmony_ci }; 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci // Sample 517e5c31af7Sopenharmony_ci m_uniforms[2*unitNdx].sampler.texCube->sample4(texSamples, transformedTexCoords); 518e5c31af7Sopenharmony_ci } 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ci // Add to sum 521e5c31af7Sopenharmony_ci for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 522e5c31af7Sopenharmony_ci outColors[fragNdx] += colorMultiplier * texSamples[fragNdx]; 523e5c31af7Sopenharmony_ci } 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci // output 526e5c31af7Sopenharmony_ci for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 527e5c31af7Sopenharmony_ci rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColors[fragNdx]); 528e5c31af7Sopenharmony_ci } 529e5c31af7Sopenharmony_ci} 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_ciclass TextureUnitCase : public TestCase 532e5c31af7Sopenharmony_ci{ 533e5c31af7Sopenharmony_cipublic: 534e5c31af7Sopenharmony_ci enum CaseType 535e5c31af7Sopenharmony_ci { 536e5c31af7Sopenharmony_ci CASE_ONLY_2D = 0, 537e5c31af7Sopenharmony_ci CASE_ONLY_CUBE, 538e5c31af7Sopenharmony_ci CASE_MIXED, 539e5c31af7Sopenharmony_ci 540e5c31af7Sopenharmony_ci CASE_LAST 541e5c31af7Sopenharmony_ci }; 542e5c31af7Sopenharmony_ci TextureUnitCase (Context& context, const char* name, const char* desc, int numUnits /* \note If non-positive, use all units */, CaseType caseType, deUint32 randSeed); 543e5c31af7Sopenharmony_ci ~TextureUnitCase (void); 544e5c31af7Sopenharmony_ci 545e5c31af7Sopenharmony_ci void init (void); 546e5c31af7Sopenharmony_ci void deinit (void); 547e5c31af7Sopenharmony_ci IterateResult iterate (void); 548e5c31af7Sopenharmony_ci 549e5c31af7Sopenharmony_ciprivate: 550e5c31af7Sopenharmony_ci struct TextureParameters 551e5c31af7Sopenharmony_ci { 552e5c31af7Sopenharmony_ci GLenum format; 553e5c31af7Sopenharmony_ci GLenum dataType; 554e5c31af7Sopenharmony_ci GLenum wrapModeS; 555e5c31af7Sopenharmony_ci GLenum wrapModeT; 556e5c31af7Sopenharmony_ci GLenum minFilter; 557e5c31af7Sopenharmony_ci GLenum magFilter; 558e5c31af7Sopenharmony_ci }; 559e5c31af7Sopenharmony_ci 560e5c31af7Sopenharmony_ci TextureUnitCase (const TextureUnitCase& other); 561e5c31af7Sopenharmony_ci TextureUnitCase& operator= (const TextureUnitCase& other); 562e5c31af7Sopenharmony_ci 563e5c31af7Sopenharmony_ci void render (sglr::Context& context); 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci const int m_numUnitsParam; 566e5c31af7Sopenharmony_ci const CaseType m_caseType; 567e5c31af7Sopenharmony_ci const deUint32 m_randSeed; 568e5c31af7Sopenharmony_ci 569e5c31af7Sopenharmony_ci int m_numTextures; //!< \note Needed in addition to m_numUnits since same texture may be bound to many texture units. 570e5c31af7Sopenharmony_ci int m_numUnits; //!< = m_numUnitsParam > 0 ? m_numUnitsParam : implementationDefinedMaximum 571e5c31af7Sopenharmony_ci 572e5c31af7Sopenharmony_ci vector<GLenum> m_textureTypes; 573e5c31af7Sopenharmony_ci vector<TextureParameters> m_textureParams; 574e5c31af7Sopenharmony_ci vector<tcu::Texture2D*> m_textures2d; 575e5c31af7Sopenharmony_ci vector<tcu::TextureCube*> m_texturesCube; 576e5c31af7Sopenharmony_ci vector<int> m_unitTextures; //!< Which texture is used in a particular unit. 577e5c31af7Sopenharmony_ci vector<int> m_ndx2dOrCube; //!< Index of a texture in either m_textures2d or m_texturesCube, depending on texture type. 578e5c31af7Sopenharmony_ci MultiTexShader* m_shader; 579e5c31af7Sopenharmony_ci}; 580e5c31af7Sopenharmony_ci 581e5c31af7Sopenharmony_ciTextureUnitCase::TextureUnitCase (Context& context, const char* name, const char* desc, int numUnits, CaseType caseType, deUint32 randSeed) 582e5c31af7Sopenharmony_ci : TestCase (context, tcu::NODETYPE_SELF_VALIDATE, name, desc) 583e5c31af7Sopenharmony_ci , m_numUnitsParam (numUnits) 584e5c31af7Sopenharmony_ci , m_caseType (caseType) 585e5c31af7Sopenharmony_ci , m_randSeed (randSeed) 586e5c31af7Sopenharmony_ci , m_numTextures (0) 587e5c31af7Sopenharmony_ci , m_numUnits (0) 588e5c31af7Sopenharmony_ci , m_shader (DE_NULL) 589e5c31af7Sopenharmony_ci{ 590e5c31af7Sopenharmony_ci} 591e5c31af7Sopenharmony_ci 592e5c31af7Sopenharmony_ciTextureUnitCase::~TextureUnitCase (void) 593e5c31af7Sopenharmony_ci{ 594e5c31af7Sopenharmony_ci TextureUnitCase::deinit(); 595e5c31af7Sopenharmony_ci} 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_civoid TextureUnitCase::deinit (void) 598e5c31af7Sopenharmony_ci{ 599e5c31af7Sopenharmony_ci for (vector<tcu::Texture2D*>::iterator i = m_textures2d.begin(); i != m_textures2d.end(); i++) 600e5c31af7Sopenharmony_ci delete *i; 601e5c31af7Sopenharmony_ci m_textures2d.clear(); 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_ci for (vector<tcu::TextureCube*>::iterator i = m_texturesCube.begin(); i != m_texturesCube.end(); i++) 604e5c31af7Sopenharmony_ci delete *i; 605e5c31af7Sopenharmony_ci m_texturesCube.clear(); 606e5c31af7Sopenharmony_ci 607e5c31af7Sopenharmony_ci delete m_shader; 608e5c31af7Sopenharmony_ci m_shader = DE_NULL; 609e5c31af7Sopenharmony_ci} 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_civoid TextureUnitCase::init (void) 612e5c31af7Sopenharmony_ci{ 613e5c31af7Sopenharmony_ci m_numUnits = m_numUnitsParam > 0 ? m_numUnitsParam : m_context.getContextInfo().getInt(GL_MAX_TEXTURE_IMAGE_UNITS); 614e5c31af7Sopenharmony_ci 615e5c31af7Sopenharmony_ci // Make the textures. 616e5c31af7Sopenharmony_ci 617e5c31af7Sopenharmony_ci try 618e5c31af7Sopenharmony_ci { 619e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 620e5c31af7Sopenharmony_ci de::Random rnd (m_randSeed); 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_ci if (rnd.getFloat() < 0.7f) 623e5c31af7Sopenharmony_ci m_numTextures = m_numUnits; // In most cases use one unit per texture. 624e5c31af7Sopenharmony_ci else 625e5c31af7Sopenharmony_ci m_numTextures = rnd.getInt(deMax32(1, m_numUnits - 2), m_numUnits); // Sometimes assign same texture to multiple units. 626e5c31af7Sopenharmony_ci 627e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << ("Using " + de::toString(m_numUnits) + " texture unit(s) and " + de::toString(m_numTextures) + " texture(s)").c_str() << tcu::TestLog::EndMessage; 628e5c31af7Sopenharmony_ci 629e5c31af7Sopenharmony_ci m_textureTypes.reserve(m_numTextures); 630e5c31af7Sopenharmony_ci m_textureParams.reserve(m_numTextures); 631e5c31af7Sopenharmony_ci m_ndx2dOrCube.reserve(m_numTextures); 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci // Generate textures. 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ci for (int texNdx = 0; texNdx < m_numTextures; texNdx++) 636e5c31af7Sopenharmony_ci { 637e5c31af7Sopenharmony_ci // Either fixed or randomized target types (2d or cube), and randomized parameters for every texture. 638e5c31af7Sopenharmony_ci 639e5c31af7Sopenharmony_ci TextureParameters params; 640e5c31af7Sopenharmony_ci bool is2d = m_caseType == CASE_ONLY_2D ? true : 641e5c31af7Sopenharmony_ci m_caseType == CASE_ONLY_CUBE ? false : 642e5c31af7Sopenharmony_ci rnd.getBool(); 643e5c31af7Sopenharmony_ci 644e5c31af7Sopenharmony_ci GLenum type = is2d ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP; 645e5c31af7Sopenharmony_ci const int texWidth = is2d ? TEXTURE_WIDTH_2D : TEXTURE_WIDTH_CUBE; 646e5c31af7Sopenharmony_ci const int texHeight = is2d ? TEXTURE_HEIGHT_2D : TEXTURE_HEIGHT_CUBE; 647e5c31af7Sopenharmony_ci bool mipmaps = (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight)); 648e5c31af7Sopenharmony_ci int numLevels = mipmaps ? deLog2Floor32(de::max(texWidth, texHeight))+1 : 1; 649e5c31af7Sopenharmony_ci 650e5c31af7Sopenharmony_ci params.wrapModeS = s_testWrapModes [rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)]; 651e5c31af7Sopenharmony_ci params.wrapModeT = s_testWrapModes [rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)]; 652e5c31af7Sopenharmony_ci params.magFilter = s_testMagFilters [rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMagFilters) - 1)]; 653e5c31af7Sopenharmony_ci params.dataType = s_testDataTypes [rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testDataTypes) - 1)]; 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_ci // Certain minification filters are only used when using mipmaps. 656e5c31af7Sopenharmony_ci if (mipmaps) 657e5c31af7Sopenharmony_ci params.minFilter = s_testMinFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMinFilters) - 1)]; 658e5c31af7Sopenharmony_ci else 659e5c31af7Sopenharmony_ci params.minFilter = s_testNonMipmapMinFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNonMipmapMinFilters) - 1)]; 660e5c31af7Sopenharmony_ci 661e5c31af7Sopenharmony_ci // Format may depend on data type. 662e5c31af7Sopenharmony_ci if (params.dataType == GL_UNSIGNED_SHORT_5_6_5) 663e5c31af7Sopenharmony_ci params.format = GL_RGB; 664e5c31af7Sopenharmony_ci else if (params.dataType == GL_UNSIGNED_SHORT_4_4_4_4 || params.dataType == GL_UNSIGNED_SHORT_5_5_5_1) 665e5c31af7Sopenharmony_ci params.format = GL_RGBA; 666e5c31af7Sopenharmony_ci else 667e5c31af7Sopenharmony_ci params.format = s_testFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testFormats) - 1)]; 668e5c31af7Sopenharmony_ci 669e5c31af7Sopenharmony_ci m_textureTypes.push_back(type); 670e5c31af7Sopenharmony_ci m_textureParams.push_back(params); 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci // Create new texture. 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci if (is2d) 675e5c31af7Sopenharmony_ci { 676e5c31af7Sopenharmony_ci m_ndx2dOrCube.push_back((int)m_textures2d.size()); // Remember the index this texture has in the 2d array. 677e5c31af7Sopenharmony_ci m_textures2d.push_back(new tcu::Texture2D(glu::mapGLTransferFormat(params.format, params.dataType), texWidth, texHeight, isES2Context(m_context.getRenderContext().getType()))); 678e5c31af7Sopenharmony_ci } 679e5c31af7Sopenharmony_ci else 680e5c31af7Sopenharmony_ci { 681e5c31af7Sopenharmony_ci m_ndx2dOrCube.push_back((int)m_texturesCube.size()); // Remember the index this texture has in the cube array. 682e5c31af7Sopenharmony_ci DE_ASSERT(texWidth == texHeight); 683e5c31af7Sopenharmony_ci m_texturesCube.push_back(new tcu::TextureCube(glu::mapGLTransferFormat(params.format, params.dataType), texWidth)); 684e5c31af7Sopenharmony_ci } 685e5c31af7Sopenharmony_ci 686e5c31af7Sopenharmony_ci tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(is2d ? m_textures2d.back()->getFormat() : m_texturesCube.back()->getFormat()); 687e5c31af7Sopenharmony_ci Vec4 cBias = fmtInfo.valueMin; 688e5c31af7Sopenharmony_ci Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 689e5c31af7Sopenharmony_ci 690e5c31af7Sopenharmony_ci // Fill with grid texture. 691e5c31af7Sopenharmony_ci 692e5c31af7Sopenharmony_ci int numFaces = is2d ? 1 : (int)tcu::CUBEFACE_LAST; 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ci for (int face = 0; face < numFaces; face++) 695e5c31af7Sopenharmony_ci { 696e5c31af7Sopenharmony_ci deUint32 rgb = rnd.getUint32() & 0x00ffffff; 697e5c31af7Sopenharmony_ci deUint32 alpha0 = 0xff000000; 698e5c31af7Sopenharmony_ci deUint32 alpha1 = 0xff000000; 699e5c31af7Sopenharmony_ci 700e5c31af7Sopenharmony_ci if (params.format == GL_ALPHA) // \note This needs alpha to be visible. 701e5c31af7Sopenharmony_ci { 702e5c31af7Sopenharmony_ci alpha0 &= rnd.getUint32(); 703e5c31af7Sopenharmony_ci alpha1 = ~alpha0; 704e5c31af7Sopenharmony_ci } 705e5c31af7Sopenharmony_ci 706e5c31af7Sopenharmony_ci deUint32 colorA = alpha0 | rgb; 707e5c31af7Sopenharmony_ci deUint32 colorB = alpha1 | ~rgb; 708e5c31af7Sopenharmony_ci 709e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 710e5c31af7Sopenharmony_ci { 711e5c31af7Sopenharmony_ci if (is2d) 712e5c31af7Sopenharmony_ci m_textures2d.back()->allocLevel(levelNdx); 713e5c31af7Sopenharmony_ci else 714e5c31af7Sopenharmony_ci m_texturesCube.back()->allocLevel((tcu::CubeFace)face, levelNdx); 715e5c31af7Sopenharmony_ci 716e5c31af7Sopenharmony_ci int curCellSize = deMax32(1, GRID_CELL_SIZE >> levelNdx); // \note Scale grid cell size for mipmaps. 717e5c31af7Sopenharmony_ci 718e5c31af7Sopenharmony_ci tcu::PixelBufferAccess access = is2d ? m_textures2d.back()->getLevel(levelNdx) : m_texturesCube.back()->getLevelFace(levelNdx, (tcu::CubeFace)face); 719e5c31af7Sopenharmony_ci tcu::fillWithGrid(access, curCellSize, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias); 720e5c31af7Sopenharmony_ci } 721e5c31af7Sopenharmony_ci } 722e5c31af7Sopenharmony_ci } 723e5c31af7Sopenharmony_ci 724e5c31af7Sopenharmony_ci // Assign a texture index to each unit. 725e5c31af7Sopenharmony_ci 726e5c31af7Sopenharmony_ci m_unitTextures.reserve(m_numUnits); 727e5c31af7Sopenharmony_ci 728e5c31af7Sopenharmony_ci // \note Every texture is used at least once. 729e5c31af7Sopenharmony_ci for (int i = 0; i < m_numTextures; i++) 730e5c31af7Sopenharmony_ci m_unitTextures.push_back(i); 731e5c31af7Sopenharmony_ci 732e5c31af7Sopenharmony_ci // Assign a random texture to remaining units. 733e5c31af7Sopenharmony_ci while ((int)m_unitTextures.size() < m_numUnits) 734e5c31af7Sopenharmony_ci m_unitTextures.push_back(rnd.getInt(0, m_numTextures - 1)); 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ci rnd.shuffle(m_unitTextures.begin(), m_unitTextures.end()); 737e5c31af7Sopenharmony_ci 738e5c31af7Sopenharmony_ci // Create shader. 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ci vector<GLenum> unitTypes; 741e5c31af7Sopenharmony_ci unitTypes.reserve(m_numUnits); 742e5c31af7Sopenharmony_ci for (int i = 0; i < m_numUnits; i++) 743e5c31af7Sopenharmony_ci unitTypes.push_back(m_textureTypes[m_unitTextures[i]]); 744e5c31af7Sopenharmony_ci 745e5c31af7Sopenharmony_ci DE_ASSERT(m_shader == DE_NULL); 746e5c31af7Sopenharmony_ci m_shader = new MultiTexShader(rnd.getUint32(), m_numUnits, unitTypes); 747e5c31af7Sopenharmony_ci } 748e5c31af7Sopenharmony_ci catch (const std::exception&) 749e5c31af7Sopenharmony_ci { 750e5c31af7Sopenharmony_ci // Clean up to save memory. 751e5c31af7Sopenharmony_ci TextureUnitCase::deinit(); 752e5c31af7Sopenharmony_ci throw; 753e5c31af7Sopenharmony_ci } 754e5c31af7Sopenharmony_ci} 755e5c31af7Sopenharmony_ci 756e5c31af7Sopenharmony_ciTextureUnitCase::IterateResult TextureUnitCase::iterate (void) 757e5c31af7Sopenharmony_ci{ 758e5c31af7Sopenharmony_ci glu::RenderContext& renderCtx = m_context.getRenderContext(); 759e5c31af7Sopenharmony_ci const tcu::RenderTarget& renderTarget = renderCtx.getRenderTarget(); 760e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 761e5c31af7Sopenharmony_ci de::Random rnd (m_randSeed); 762e5c31af7Sopenharmony_ci 763e5c31af7Sopenharmony_ci int viewportWidth = deMin32(VIEWPORT_WIDTH, renderTarget.getWidth()); 764e5c31af7Sopenharmony_ci int viewportHeight = deMin32(VIEWPORT_HEIGHT, renderTarget.getHeight()); 765e5c31af7Sopenharmony_ci int viewportX = rnd.getInt(0, renderTarget.getWidth() - viewportWidth); 766e5c31af7Sopenharmony_ci int viewportY = rnd.getInt(0, renderTarget.getHeight() - viewportHeight); 767e5c31af7Sopenharmony_ci 768e5c31af7Sopenharmony_ci tcu::Surface gles2Frame (viewportWidth, viewportHeight); 769e5c31af7Sopenharmony_ci tcu::Surface refFrame (viewportWidth, viewportHeight); 770e5c31af7Sopenharmony_ci 771e5c31af7Sopenharmony_ci { 772e5c31af7Sopenharmony_ci // First we do some tricks to make the LODs safer wrt. precision issues. See MultiTexShader::makeSafeLods(). 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci vector<IVec2> texSizes; 775e5c31af7Sopenharmony_ci texSizes.reserve(m_numUnits); 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci for (int i = 0; i < m_numUnits; i++) 778e5c31af7Sopenharmony_ci { 779e5c31af7Sopenharmony_ci int texNdx = m_unitTextures[i]; 780e5c31af7Sopenharmony_ci int texNdxInType = m_ndx2dOrCube[texNdx]; 781e5c31af7Sopenharmony_ci GLenum type = m_textureTypes[texNdx]; 782e5c31af7Sopenharmony_ci 783e5c31af7Sopenharmony_ci switch (type) 784e5c31af7Sopenharmony_ci { 785e5c31af7Sopenharmony_ci case GL_TEXTURE_2D: texSizes.push_back(IVec2(m_textures2d[texNdxInType]->getWidth(), m_textures2d[texNdxInType]->getHeight())); break; 786e5c31af7Sopenharmony_ci case GL_TEXTURE_CUBE_MAP: texSizes.push_back(IVec2(m_texturesCube[texNdxInType]->getSize(), m_texturesCube[texNdxInType]->getSize())); break; 787e5c31af7Sopenharmony_ci default: 788e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 789e5c31af7Sopenharmony_ci } 790e5c31af7Sopenharmony_ci } 791e5c31af7Sopenharmony_ci 792e5c31af7Sopenharmony_ci m_shader->makeSafeLods(texSizes, IVec2(viewportWidth, viewportHeight)); 793e5c31af7Sopenharmony_ci } 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci // Render using GLES2. 796e5c31af7Sopenharmony_ci { 797e5c31af7Sopenharmony_ci sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS|sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(viewportX, viewportY, viewportWidth, viewportHeight)); 798e5c31af7Sopenharmony_ci 799e5c31af7Sopenharmony_ci render(context); 800e5c31af7Sopenharmony_ci 801e5c31af7Sopenharmony_ci context.readPixels(gles2Frame, 0, 0, viewportWidth, viewportHeight); 802e5c31af7Sopenharmony_ci } 803e5c31af7Sopenharmony_ci 804e5c31af7Sopenharmony_ci // Render reference image. 805e5c31af7Sopenharmony_ci { 806e5c31af7Sopenharmony_ci sglr::ReferenceContextBuffers buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, viewportWidth, viewportHeight); 807e5c31af7Sopenharmony_ci sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 808e5c31af7Sopenharmony_ci 809e5c31af7Sopenharmony_ci render(context); 810e5c31af7Sopenharmony_ci 811e5c31af7Sopenharmony_ci context.readPixels(refFrame, 0, 0, viewportWidth, viewportHeight); 812e5c31af7Sopenharmony_ci } 813e5c31af7Sopenharmony_ci 814e5c31af7Sopenharmony_ci // Compare images. 815e5c31af7Sopenharmony_ci const float threshold = 0.001f; 816e5c31af7Sopenharmony_ci bool isOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT); 817e5c31af7Sopenharmony_ci 818e5c31af7Sopenharmony_ci // Store test result. 819e5c31af7Sopenharmony_ci m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 820e5c31af7Sopenharmony_ci isOk ? "Pass" : "Image comparison failed"); 821e5c31af7Sopenharmony_ci 822e5c31af7Sopenharmony_ci return STOP; 823e5c31af7Sopenharmony_ci} 824e5c31af7Sopenharmony_ci 825e5c31af7Sopenharmony_civoid TextureUnitCase::render (sglr::Context& context) 826e5c31af7Sopenharmony_ci{ 827e5c31af7Sopenharmony_ci // Setup textures. 828e5c31af7Sopenharmony_ci 829e5c31af7Sopenharmony_ci vector<deUint32> textureGLNames; 830e5c31af7Sopenharmony_ci vector<bool> isTextureSetUp(m_numTextures, false); // \note Same texture may be bound to multiple units, but we only want to set up parameters and data once per texture. 831e5c31af7Sopenharmony_ci 832e5c31af7Sopenharmony_ci textureGLNames.resize(m_numTextures); 833e5c31af7Sopenharmony_ci context.genTextures(m_numTextures, &textureGLNames[0]); 834e5c31af7Sopenharmony_ci 835e5c31af7Sopenharmony_ci for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++) 836e5c31af7Sopenharmony_ci { 837e5c31af7Sopenharmony_ci int texNdx = m_unitTextures[unitNdx]; 838e5c31af7Sopenharmony_ci 839e5c31af7Sopenharmony_ci // Bind texture to unit. 840e5c31af7Sopenharmony_ci context.activeTexture(GL_TEXTURE0 + unitNdx); 841e5c31af7Sopenharmony_ci context.bindTexture(m_textureTypes[texNdx], textureGLNames[texNdx]); 842e5c31af7Sopenharmony_ci 843e5c31af7Sopenharmony_ci if (!isTextureSetUp[texNdx]) 844e5c31af7Sopenharmony_ci { 845e5c31af7Sopenharmony_ci // Binding this texture for first time, so set parameters and data. 846e5c31af7Sopenharmony_ci 847e5c31af7Sopenharmony_ci context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_S, m_textureParams[texNdx].wrapModeS); 848e5c31af7Sopenharmony_ci context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_T, m_textureParams[texNdx].wrapModeT); 849e5c31af7Sopenharmony_ci context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MIN_FILTER, m_textureParams[texNdx].minFilter); 850e5c31af7Sopenharmony_ci context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MAG_FILTER, m_textureParams[texNdx].magFilter); 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_ci if (m_textureTypes[texNdx] == GL_TEXTURE_2D) 853e5c31af7Sopenharmony_ci { 854e5c31af7Sopenharmony_ci int ndx2d = m_ndx2dOrCube[texNdx]; 855e5c31af7Sopenharmony_ci const tcu::Texture2D* texture = m_textures2d[ndx2d]; 856e5c31af7Sopenharmony_ci bool mipmaps = (deIsPowerOfTwo32(texture->getWidth()) && deIsPowerOfTwo32(texture->getHeight())); 857e5c31af7Sopenharmony_ci int numLevels = mipmaps ? deLog2Floor32(de::max(texture->getWidth(), texture->getHeight()))+1 : 1; 858e5c31af7Sopenharmony_ci 859e5c31af7Sopenharmony_ci context.pixelStorei(GL_UNPACK_ALIGNMENT, 1); 860e5c31af7Sopenharmony_ci 861e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 862e5c31af7Sopenharmony_ci { 863e5c31af7Sopenharmony_ci tcu::ConstPixelBufferAccess access = texture->getLevel(levelNdx); 864e5c31af7Sopenharmony_ci int width = access.getWidth(); 865e5c31af7Sopenharmony_ci int height = access.getHeight(); 866e5c31af7Sopenharmony_ci 867e5c31af7Sopenharmony_ci DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width); 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci context.texImage2D(GL_TEXTURE_2D, levelNdx, m_textureParams[texNdx].format, width, height, 0, m_textureParams[texNdx].format, m_textureParams[texNdx].dataType, access.getDataPtr()); 870e5c31af7Sopenharmony_ci } 871e5c31af7Sopenharmony_ci } 872e5c31af7Sopenharmony_ci else 873e5c31af7Sopenharmony_ci { 874e5c31af7Sopenharmony_ci DE_ASSERT(m_textureTypes[texNdx] == GL_TEXTURE_CUBE_MAP); 875e5c31af7Sopenharmony_ci 876e5c31af7Sopenharmony_ci int ndxCube = m_ndx2dOrCube[texNdx]; 877e5c31af7Sopenharmony_ci const tcu::TextureCube* texture = m_texturesCube[ndxCube]; 878e5c31af7Sopenharmony_ci bool mipmaps = deIsPowerOfTwo32(texture->getSize()) != DE_FALSE; 879e5c31af7Sopenharmony_ci int numLevels = mipmaps ? deLog2Floor32(texture->getSize())+1 : 1; 880e5c31af7Sopenharmony_ci 881e5c31af7Sopenharmony_ci context.pixelStorei(GL_UNPACK_ALIGNMENT, 1); 882e5c31af7Sopenharmony_ci 883e5c31af7Sopenharmony_ci for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++) 884e5c31af7Sopenharmony_ci { 885e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 886e5c31af7Sopenharmony_ci { 887e5c31af7Sopenharmony_ci tcu::ConstPixelBufferAccess access = texture->getLevelFace(levelNdx, (tcu::CubeFace)face); 888e5c31af7Sopenharmony_ci int width = access.getWidth(); 889e5c31af7Sopenharmony_ci int height = access.getHeight(); 890e5c31af7Sopenharmony_ci 891e5c31af7Sopenharmony_ci DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width); 892e5c31af7Sopenharmony_ci 893e5c31af7Sopenharmony_ci context.texImage2D(s_cubeFaceTargets[face], levelNdx, m_textureParams[texNdx].format, width, height, 0, m_textureParams[texNdx].format, m_textureParams[texNdx].dataType, access.getDataPtr()); 894e5c31af7Sopenharmony_ci } 895e5c31af7Sopenharmony_ci } 896e5c31af7Sopenharmony_ci } 897e5c31af7Sopenharmony_ci 898e5c31af7Sopenharmony_ci isTextureSetUp[texNdx] = true; // Don't set up this texture's parameters and data again later. 899e5c31af7Sopenharmony_ci } 900e5c31af7Sopenharmony_ci } 901e5c31af7Sopenharmony_ci 902e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(context.getError(), "Set textures"); 903e5c31af7Sopenharmony_ci 904e5c31af7Sopenharmony_ci // Setup shader 905e5c31af7Sopenharmony_ci 906e5c31af7Sopenharmony_ci deUint32 shaderID = context.createProgram(m_shader); 907e5c31af7Sopenharmony_ci 908e5c31af7Sopenharmony_ci // Draw. 909e5c31af7Sopenharmony_ci 910e5c31af7Sopenharmony_ci context.clearColor(0.125f, 0.25f, 0.5f, 1.0f); 911e5c31af7Sopenharmony_ci context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 912e5c31af7Sopenharmony_ci m_shader->setUniforms(context, shaderID); 913e5c31af7Sopenharmony_ci sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 914e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(context.getError(), "Draw"); 915e5c31af7Sopenharmony_ci 916e5c31af7Sopenharmony_ci // Delete previously generated texture names. 917e5c31af7Sopenharmony_ci 918e5c31af7Sopenharmony_ci context.deleteTextures(m_numTextures, &textureGLNames[0]); 919e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(context.getError(), "Delete textures"); 920e5c31af7Sopenharmony_ci} 921e5c31af7Sopenharmony_ci 922e5c31af7Sopenharmony_ciTextureUnitTests::TextureUnitTests (Context& context) 923e5c31af7Sopenharmony_ci : TestCaseGroup(context, "units", "Texture Unit Usage Tests") 924e5c31af7Sopenharmony_ci{ 925e5c31af7Sopenharmony_ci} 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ciTextureUnitTests::~TextureUnitTests (void) 928e5c31af7Sopenharmony_ci{ 929e5c31af7Sopenharmony_ci} 930e5c31af7Sopenharmony_ci 931e5c31af7Sopenharmony_civoid TextureUnitTests::init (void) 932e5c31af7Sopenharmony_ci{ 933e5c31af7Sopenharmony_ci const int numTestsPerGroup = 10; 934e5c31af7Sopenharmony_ci 935e5c31af7Sopenharmony_ci static const int unitCounts[] = 936e5c31af7Sopenharmony_ci { 937e5c31af7Sopenharmony_ci 2, 938e5c31af7Sopenharmony_ci 4, 939e5c31af7Sopenharmony_ci 8, 940e5c31af7Sopenharmony_ci -1 // \note Negative stands for the implementation-specified maximum. 941e5c31af7Sopenharmony_ci }; 942e5c31af7Sopenharmony_ci 943e5c31af7Sopenharmony_ci for (int unitCountNdx = 0; unitCountNdx < DE_LENGTH_OF_ARRAY(unitCounts); unitCountNdx++) 944e5c31af7Sopenharmony_ci { 945e5c31af7Sopenharmony_ci int numUnits = unitCounts[unitCountNdx]; 946e5c31af7Sopenharmony_ci 947e5c31af7Sopenharmony_ci string countGroupName = (unitCounts[unitCountNdx] < 0 ? "all" : de::toString(numUnits)) + "_units"; 948e5c31af7Sopenharmony_ci 949e5c31af7Sopenharmony_ci tcu::TestCaseGroup* countGroup = new tcu::TestCaseGroup(m_testCtx, countGroupName.c_str(), ""); 950e5c31af7Sopenharmony_ci addChild(countGroup); 951e5c31af7Sopenharmony_ci 952e5c31af7Sopenharmony_ci DE_STATIC_ASSERT((int)TextureUnitCase::CASE_ONLY_2D == 0); 953e5c31af7Sopenharmony_ci 954e5c31af7Sopenharmony_ci for (int caseType = (int)TextureUnitCase::CASE_ONLY_2D; caseType < (int)TextureUnitCase::CASE_LAST; caseType++) 955e5c31af7Sopenharmony_ci { 956e5c31af7Sopenharmony_ci const char* caseTypeGroupName = (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D ? "only_2d" : 957e5c31af7Sopenharmony_ci (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_CUBE ? "only_cube" : 958e5c31af7Sopenharmony_ci (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_MIXED ? "mixed" : 959e5c31af7Sopenharmony_ci DE_NULL; 960e5c31af7Sopenharmony_ci DE_ASSERT(caseTypeGroupName != DE_NULL); 961e5c31af7Sopenharmony_ci 962e5c31af7Sopenharmony_ci tcu::TestCaseGroup* caseTypeGroup = new tcu::TestCaseGroup(m_testCtx, caseTypeGroupName, ""); 963e5c31af7Sopenharmony_ci countGroup->addChild(caseTypeGroup); 964e5c31af7Sopenharmony_ci 965e5c31af7Sopenharmony_ci for (int testNdx = 0; testNdx < numTestsPerGroup; testNdx++) 966e5c31af7Sopenharmony_ci caseTypeGroup->addChild(new TextureUnitCase(m_context, de::toString(testNdx).c_str(), "", numUnits, (TextureUnitCase::CaseType)caseType, (deUint32)deInt32Hash(testNdx))); 967e5c31af7Sopenharmony_ci } 968e5c31af7Sopenharmony_ci } 969e5c31af7Sopenharmony_ci} 970e5c31af7Sopenharmony_ci 971e5c31af7Sopenharmony_ci} // Functional 972e5c31af7Sopenharmony_ci} // gles2 973e5c31af7Sopenharmony_ci} // deqp 974