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