1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*-------------------------------------------------------------------------
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * drawElements Quality Program OpenGL ES 3.0 Module
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * -------------------------------------------------
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Copyright 2014 The Android Open Source Project
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License");
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * you may not use this file except in compliance with the License.
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * You may obtain a copy of the License at
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *      http://www.apache.org/licenses/LICENSE-2.0
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS,
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * See the License for the specific language governing permissions and
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * limitations under the License.
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *//*!
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * \file
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * \brief Texture unit usage tests.
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * \todo [2012-07-12 nuutti] Come up with a good way to make these tests faster.
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *//*--------------------------------------------------------------------*/
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "es3fTextureUnitTests.hpp"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "glsTextureTestUtil.hpp"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gluTextureUtil.hpp"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gluContextInfo.hpp"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gluTextureUtil.hpp"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tcuTextureUtil.hpp"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tcuImageCompare.hpp"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tcuMatrix.hpp"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tcuRenderTarget.hpp"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "sglrContextUtil.hpp"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "sglrReferenceContext.hpp"
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "sglrGLContext.hpp"
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "deRandom.hpp"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "deStringUtil.hpp"
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "glwEnums.hpp"
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "glwFunctions.hpp"
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::Vec2;
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::Vec3;
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::Vec4;
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::IVec2;
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::IVec3;
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::Mat3;
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing tcu::Mat4;
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing std::vector;
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing std::string;
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing namespace glw; // GL types
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace deqp
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
58103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliususing namespace gls::TextureTestUtil;
59103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusnamespace gles3
61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace Functional
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int VIEWPORT_WIDTH				= 128;
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int VIEWPORT_HEIGHT			= 128;
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_WIDTH_2D			= 128;
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_HEIGHT_2D			= 128;
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// \note Cube map texture size is larger in order to make minifications possible - otherwise would need to display different faces at same time.
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_WIDTH_CUBE			= 256;
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_HEIGHT_CUBE		= 256;
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_WIDTH_2D_ARRAY		= 64;
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_HEIGHT_2D_ARRAY	= 64;
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_LAYERS_2D_ARRAY	= 4;
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_WIDTH_3D			= 32;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_HEIGHT_3D			= 32;
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int TEXTURE_DEPTH_3D			= 32;
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int GRID_CELL_SIZE				= 8;
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testSizedInternalFormats[] =
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA32F,
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA32I,
89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius	GL_RGBA32UI,
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA16F,
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA16I,
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA16UI,
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA8,
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA8I,
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA8UI,
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_SRGB8_ALPHA8,
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB10_A2,
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB10_A2UI,
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA4,
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB5_A1,
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGBA8_SNORM,
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB8,
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB565,
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R11F_G11F_B10F,
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB32F,
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB32I,
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB32UI,
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB16F,
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB16I,
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB16UI,
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB8_SNORM,
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB8I,
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB8UI,
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_SRGB8,
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RGB9_E5,
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG32F,
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG32I,
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG32UI,
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG16F,
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG16I,
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG16UI,
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG8,
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG8I,
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG8UI,
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_RG8_SNORM,
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R32F,
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R32I,
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R32UI,
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R16F,
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R16I,
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R16UI,
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R8,
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R8I,
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R8UI,
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_R8_SNORM
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testWrapModes[] =
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
14054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius	GL_CLAMP_TO_EDGE,
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_REPEAT,
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_MIRRORED_REPEAT,
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testMinFilters[] =
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST,
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_LINEAR,
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST_MIPMAP_NEAREST,
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_LINEAR_MIPMAP_NEAREST,
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST_MIPMAP_LINEAR,
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_LINEAR_MIPMAP_LINEAR
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testNonMipmapMinFilters[] =
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST,
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_LINEAR
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testNearestMinFilters[] =
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST,
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST_MIPMAP_NEAREST
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_testMagFilters[] =
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_NEAREST,
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_LINEAR
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const GLenum s_cubeFaceTargets[] =
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Extend a 3x3 transformation matrix to an equivalent 4x4 transformation matrix (i.e. 1.0 in right-down cell, 0.0's in other new cells).
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic Mat4 matExtend3To4 (const Mat3& mat)
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	Mat4 res;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int rowNdx = 0; rowNdx < 3; rowNdx++)
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		Vec3 row = mat.getRow(rowNdx);
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		res.setRow(rowNdx, Vec4(row.x(), row.y(), row.z(), 0.0f));
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	res.setRow(3, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return res;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic string generateMultiTexFragmentShader (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// The fragment shader calculates the average of a set of textures.
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string samplersStr;
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string matricesStr;
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string scalesStr;
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string biasesStr;
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string lookupsStr;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	string colorMultiplier = "(1.0/" + de::toString(numUnits) + ".0)";
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int ndx = 0; ndx < numUnits; ndx++)
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string ndxStr				= de::toString(ndx);
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string samplerName			= "u_sampler" + ndxStr;
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string transformationName	= "u_trans" + ndxStr;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string scaleName			= "u_texScale" + ndxStr;
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string biasName				= "u_texBias" + ndxStr;
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		samplersStr += string("") + "uniform highp " + glu::getDataTypeName(samplerTypes[ndx]) + " " + samplerName + ";\n";
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		matricesStr += "uniform highp mat4 " + transformationName + ";\n";
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		scalesStr += "uniform highp vec4 " + scaleName + ";\n";
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		biasesStr += "uniform highp vec4 " + biasName + ";\n";
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string lookupCoord = transformationName + "*vec4(v_coord, 1.0, 1.0)";
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (unitTypes[ndx] == GL_TEXTURE_2D)
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			lookupCoord = "vec2(" + lookupCoord + ")";
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			lookupCoord = "vec3(" + lookupCoord + ")";
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		lookupsStr += "\tcolor += " + colorMultiplier + "*(vec4(texture(" + samplerName + ", " + lookupCoord + "))*" + scaleName + " + " + biasName + ");\n";
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	return "#version 300 es\n"
2336d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru		   "layout(location = 0) out mediump vec4 o_color;\n" +
2346d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru		   samplersStr +
2356d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru		   matricesStr +
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   scalesStr +
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   biasesStr +
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "in highp vec2 v_coord;\n"
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "\n"
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "void main (void)\n"
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "{\n"
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "	mediump vec4 color = vec4(0.0);\n" +
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   lookupsStr +
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "	o_color = color;\n"
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   "}\n";
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic sglr::pdec::ShaderProgramDeclaration generateShaderProgramDeclaration (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	sglr::pdec::ShaderProgramDeclaration decl;
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int ndx = 0; ndx < numUnits; ++ndx)
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string samplerName			= "u_sampler" + de::toString(ndx);
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string transformationName	= "u_trans" + de::toString(ndx);
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string scaleName			= "u_texScale" + de::toString(ndx);
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string biasName				= "u_texBias" + de::toString(ndx);
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		decl << sglr::pdec::Uniform(samplerName, samplerTypes[ndx]);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		decl << sglr::pdec::Uniform(transformationName, glu::TYPE_FLOAT_MAT4);
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		decl << sglr::pdec::Uniform(scaleName, glu::TYPE_FLOAT_VEC4);
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		decl << sglr::pdec::Uniform(biasName, glu::TYPE_FLOAT_VEC4);
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::VertexSource("#version 300 es\n"
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "in highp vec4 a_position;\n"
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "in highp vec2 a_coord;\n"
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "out highp vec2 v_coord;\n"
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "\n"
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "void main (void)\n"
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "{\n"
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "	gl_Position = a_position;\n"
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "	v_coord = a_coord;\n"
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 "}\n");
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	decl << sglr::pdec::FragmentSource(generateMultiTexFragmentShader(numUnits, unitTypes, samplerTypes));
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return decl;
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Calculates values that will be used in calculateLod().
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic tcu::Vector<tcu::Vec2, 3> calculateLodDerivateParts (const Mat4& transformation)
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Calculate transformed coordinates of three screen corners.
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	Vec3 trans00 = (transformation * Vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	Vec3 trans01 = (transformation * Vec4(0.0f, 1.0f, 1.0f, 1.0f)).xyz();
29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	Vec3 trans10 = (transformation * Vec4(1.0f, 0.0f, 1.0f, 1.0f)).xyz();
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return tcu::Vector<tcu::Vec2, 3>(Vec2(trans10.x() - trans00.x(), trans01.x() - trans00.x()),
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 Vec2(trans10.y() - trans00.y(), trans01.y() - trans00.y()),
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									 Vec2(trans10.z() - trans00.z(), trans01.z() - trans00.z()));
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Calculates the maximum allowed lod from derivates
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic float calculateLodMax(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mu = de::max(de::abs(dudx), de::abs(dudy));
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return deFloatLog2(mu + mv + mw);
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Calculates the minimum allowed lod from derivates
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic float calculateLodMin(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mu = de::max(de::abs(dudx), de::abs(dudy));
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return deFloatLog2(de::max(mu, de::max(mv, mw)));
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass MultiTexShader : public sglr::ShaderProgram
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							MultiTexShader	(deUint32 randSeed,
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 int numUnits,
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 const vector<GLenum>& unitTypes,
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 const vector<glu::DataType>& samplerTypes,
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 const vector<Vec4>& texScales,
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 const vector<Vec4>& texBiases,
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru											 const vector<int>& num2dArrayLayers); // \note 2d array layer "coordinate" isn't normalized, so this is needed here.
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void					setUniforms		(sglr::Context& context, deUint32 program) const;
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void					makeSafeLods	(const vector<IVec3>& textureSizes, const IVec2& viewportSize); // Modifies texture coordinates so that LODs aren't too close to x.5 or 0.0 .
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void					shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void					shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int									m_numUnits;
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<GLenum>						m_unitTypes;		// 2d, cube map, 2d array or 3d.
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<Vec4>						m_texScales;
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<Vec4>						m_texBiases;
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<Mat4>						m_transformations;
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<tcu::Vector<tcu::Vec2, 3> >	m_lodDerivateParts;	// Parts of lod derivates; computed in init(), used in eval().
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruMultiTexShader::MultiTexShader (deUint32 randSeed,
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								int numUnits,
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								const vector<GLenum>& unitTypes,
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								const vector<glu::DataType>& samplerTypes,
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								const vector<Vec4>& texScales,
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								const vector<Vec4>& texBiases,
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								const vector<int>& num2dArrayLayers)
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		: sglr::ShaderProgram	(generateShaderProgramDeclaration(numUnits, unitTypes, samplerTypes))
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		, m_numUnits		(numUnits)
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		, m_unitTypes		(unitTypes)
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		, m_texScales		(texScales)
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		, m_texBiases		(texBiases)
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// 2d-to-cube-face transformations.
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho	// \note 2d coordinates range from 0 to 1 and cube face coordinates from -1 to 1, so scaling is done as well.
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho	static const float s_cubeTransforms[][3*3] =
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{  0.0f,  0.0f, -1.0f,
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f, -2.0f,  1.0f,
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   2.0f,  0.0f, -1.0f },
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{  0.0f,  0.0f,  1.0f,
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f, -2.0f,  1.0f,
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		  -2.0f,  0.0f,  1.0f },
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{  2.0f,  0.0f, -1.0f,
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f,  0.0f, -1.0f,
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f, -2.0f,  1.0f },
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{  2.0f,  0.0f, -1.0f,
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f,  0.0f,  1.0f,
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f,  2.0f, -1.0f },
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{ -2.0f,  0.0f,  1.0f,
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f, -2.0f,  1.0f,
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f,  0.0f, -1.0f },
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{  2.0f,  0.0f, -1.0f,
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f, -2.0f,  1.0f,
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		   0.0f,  0.0f,  1.0f }
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Generate transformation matrices.
40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	de::Random rnd(randSeed);
40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	m_transformations.reserve(m_numUnits);
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_lodDerivateParts.reserve(m_numUnits);
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int tex2dArrayNdx = 0; // Keep track of 2d texture array index.
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (m_unitTypes[unitNdx] == GL_TEXTURE_2D)
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float rotAngle				= rnd.getFloat(0.0f, 2.0f*DE_PI);
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float xScaleFactor			= rnd.getFloat(0.7f, 1.5f);
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float yScaleFactor			= rnd.getFloat(0.7f, 1.5f);
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float xShearAmount			= rnd.getFloat(0.0f, 0.5f);
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float yShearAmount			= rnd.getFloat(0.0f, 0.5f);
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float xTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float yTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			static const float tempOffsetData[3*3] = // For temporarily centering the coordinates to get nicer transformations.
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				1.0f,  0.0f, -0.5f,
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,  1.0f, -0.5f,
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,  0.0f,  1.0f
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float rotTransfData[3*3] =
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deFloatCos(rotAngle),	-deFloatSin(rotAngle),	0.0f,
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deFloatSin(rotAngle),	deFloatCos(rotAngle),	0.0f,
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,					0.0f,					1.0f
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float scaleTransfData[3*3] =
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				xScaleFactor,	0.0f,			0.0f,
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,			yScaleFactor,	0.0f,
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,			0.0f,			1.0f
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float xShearTransfData[3*3] =
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				1.0f,			xShearAmount,	0.0f,
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,			1.0f,			0.0f,
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,			0.0f,			1.0f
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float yShearTransfData[3*3] =
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				1.0f,			0.0f,			0.0f,
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				yShearAmount,	1.0f,			0.0f,
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,			0.0f,			1.0f
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float translationTransfData[3*3] =
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				1.0f,	0.0f,	xTranslationAmount,
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,	1.0f,	yTranslationAmount,
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				0.0f,	0.0f,	1.0f
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Mat4 transformation = matExtend3To4(Mat3(tempOffsetData) *
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												Mat3(translationTransfData) *
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												Mat3(rotTransfData) *
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												Mat3(scaleTransfData) *
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												Mat3(xShearTransfData) *
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												Mat3(yShearTransfData) *
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												(Mat3(tempOffsetData) * (-1.0f)));
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_transformations.push_back(transformation);
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else if (m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP)
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_STATIC_ASSERT((int)tcu::CUBEFACE_LAST == DE_LENGTH_OF_ARRAY(s_cubeTransforms));
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float planarTransData[3*3];
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// 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.
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (int i = 0; i < DE_LENGTH_OF_ARRAY(planarTransData); i++)
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (i == 0 || i == 4)
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					planarTransData[i] = rnd.getFloat(0.1f, 0.9f); // Two first diagonal cells control the scaling.
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else if (i == 8)
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					planarTransData[i] = 1.0f;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					planarTransData[i] = 0.0f;
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int		faceNdx			= rnd.getInt(0, (int)tcu::CUBEFACE_LAST - 1);
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Mat3	planarTrans		(planarTransData);												// Planar, face-agnostic transformation.
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Mat4	finalTrans		= matExtend3To4(Mat3(s_cubeTransforms[faceNdx]) * planarTrans);	// Final transformation from planar to cube map coordinates, including the transformation just generated.
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Mat4	planarTrans4x4	= matExtend3To4(planarTrans);
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_lodDerivateParts.push_back(calculateLodDerivateParts(planarTrans4x4));
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_transformations.push_back(finalTrans);
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_3D || m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY);
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			float transData[4*4];
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (int i = 0; i < 4*4; i++)
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				float sign = rnd.getBool() ? 1.0f : -1.0f;
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				transData[i] = rnd.getFloat(0.7f, 1.4f) * sign;
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Mat4 transformation(transData);
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY)
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				// Z direction: Translate by 0.5 and scale by layer amount.
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				float numLayers = (float)num2dArrayLayers[tex2dArrayNdx];
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				static const float zTranslationTransfData[4*4] =
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				{
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					1.0f, 0.0f, 0.0f, 0.0f,
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f, 1.0f, 0.0f, 0.0f,
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f, 0.0f, 1.0f, 0.5f,
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f, 0.0f, 0.0f, 1.0f
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				};
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				float zScaleTransfData[4*4] =
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				{
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					1.0f,		0.0f,		0.0f,		0.0f,
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f,		1.0f,		0.0f,		0.0f,
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f,		0.0f,		numLayers,	0.0f,
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					0.0f,		0.0f,		0.0f,		1.0f
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				};
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				transformation = transformation * Mat4(zScaleTransfData) * Mat4(zTranslationTransfData);
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				tex2dArrayNdx++;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_transformations.push_back(Mat4(transformation));
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultiTexShader::setUniforms (sglr::Context& ctx, deUint32 program) const
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ctx.useProgram(program);
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Sampler and matrix uniforms.
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int ndx = 0; ndx < m_numUnits; ndx++)
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string			ndxStr		= de::toString(ndx);
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ctx.uniform1i(ctx.getUniformLocation(program, ("u_sampler" + ndxStr).c_str()), ndx);
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ctx.uniformMatrix4fv(ctx.getUniformLocation(program, ("u_trans" + ndxStr).c_str()), 1, GL_FALSE, (GLfloat*)&m_transformations[ndx].getColumnMajorData()[0]);
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texScale" + ndxStr).c_str()), 1, m_texScales[ndx].getPtr());
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texBias" + ndxStr).c_str()), 1, m_texBiases[ndx].getPtr());
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultiTexShader::makeSafeLods (const vector<IVec3>& textureSizes, const IVec2& viewportSize)
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	DE_ASSERT((int)textureSizes.size() == m_numUnits);
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho	static const float shrinkScaleMat2dData[3*3] =
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.95f,	0.0f,	0.0f,
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.0f,	0.95f,	0.0f,
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.0f,	0.0f,	1.0f
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static const float shrinkScaleMat3dData[3*3] =
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.95f,	0.0f,	0.0f,
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.0f,	0.95f,	0.0f,
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		0.0f,	0.0f,	0.95f
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	Mat4 shrinkScaleMat2d = matExtend3To4(Mat3(shrinkScaleMat2dData));
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho	Mat4 shrinkScaleMat3d = matExtend3To4(Mat3(shrinkScaleMat3dData));
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	Vec2 screenDerivate(1.0f / (float)viewportSize.x(), 1.0f / (float)viewportSize.y());
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// 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.
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (;;)
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const float threshold = 0.1f;
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const float epsilon	= 0.01f;
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const float lodMax = calculateLodMax(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const float lodMin = calculateLodMin(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const deInt32 maxLevel = (lodMax + epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMax + epsilon + 0.5f) - 1);
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const deInt32 minLevel = (lodMin - epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMin - epsilon + 0.5f) - 1);
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (de::abs(lodMax) < threshold || (lodMax > 0.0f && de::abs(deFloatFrac(lodMax) - 0.5f) < threshold) ||
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				de::abs(lodMin) < threshold || (lodMin > 0.0f && de::abs(deFloatFrac(lodMin) - 0.5f) < threshold) ||
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				maxLevel != minLevel)
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_transformations[unitNdx] = (m_unitTypes[unitNdx] == GL_TEXTURE_3D ? shrinkScaleMat3d : shrinkScaleMat2d) * m_transformations[unitNdx];
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_lodDerivateParts[unitNdx] = calculateLodDerivateParts(m_transformations[unitNdx]);
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultiTexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rr::VertexPacket& packet = *(packets[packetNdx]);
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid MultiTexShader::shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	DE_ASSERT((int)m_transformations.size() == m_numUnits);
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	DE_ASSERT((int)m_lodDerivateParts.size() == m_numUnits);
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rr::FragmentPacket& packet				= packets[packetNdx];
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		const float			colorMultiplier		= 1.0f / (float)m_numUnits;
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		Vec4				outColors[4]		= { Vec4(0.0f), Vec4(0.0f), Vec4(0.0f), Vec4(0.0f) };
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::Vec4 texSamples[4];
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Read tex coords
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const tcu::Vec2 texCoords[4] =
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rr::readTriangleVarying<float>(packet, context, 0, 0).xy(),
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rr::readTriangleVarying<float>(packet, context, 0, 1).xy(),
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rr::readTriangleVarying<float>(packet, context, 0, 2).xy(),
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rr::readTriangleVarying<float>(packet, context, 0, 3).xy(),
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Transform
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::Vec3 coords3D[4] =
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(m_transformations[unitNdx] * Vec4(texCoords[0].x(), texCoords[0].y(), 1.0f, 1.0f)).xyz(),
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(m_transformations[unitNdx] * Vec4(texCoords[1].x(), texCoords[1].y(), 1.0f, 1.0f)).xyz(),
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(m_transformations[unitNdx] * Vec4(texCoords[2].x(), texCoords[2].y(), 1.0f, 1.0f)).xyz(),
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(m_transformations[unitNdx] * Vec4(texCoords[3].x(), texCoords[3].y(), 1.0f, 1.0f)).xyz(),
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// To 2D
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const tcu::Vec2 coords2D[4] =
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				coords3D[0].xy(),
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				coords3D[1].xy(),
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				coords3D[2].xy(),
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				coords3D[3].xy(),
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			};
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Sample
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			switch (m_unitTypes[unitNdx])
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D:			m_uniforms[4*unitNdx].sampler.tex2D->sample4(texSamples, coords2D);			break;
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_CUBE_MAP:	m_uniforms[4*unitNdx].sampler.texCube->sample4(texSamples, coords3D);		break;
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D_ARRAY:	m_uniforms[4*unitNdx].sampler.tex2DArray->sample4(texSamples, coords3D);	break;
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_3D:			m_uniforms[4*unitNdx].sampler.tex3D->sample4(texSamples, coords3D);			break;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				default:
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					DE_ASSERT(DE_FALSE);
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Add to sum
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				outColors[fragNdx] += colorMultiplier * (texSamples[fragNdx]*m_texScales[unitNdx] + m_texBiases[unitNdx]);
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// output
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColors[fragNdx]);
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TextureUnitCase : public TestCase
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	enum CaseType
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_ONLY_2D = 0,
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_ONLY_CUBE,
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_ONLY_2D_ARRAY,
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_ONLY_3D,
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_MIXED,
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		CASE_LAST
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								TextureUnitCase		(Context& context, const char* name, const char* desc, int numUnits /* \note If non-positive, use all units */, CaseType caseType, deUint32 randSeed);
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								~TextureUnitCase	(void);
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void						init				(void);
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void						deinit				(void);
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	IterateResult				iterate				(void);
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	struct TextureParameters
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum internalFormat;
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum wrapModeS;
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum wrapModeT;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum wrapModeR;
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum minFilter;
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLenum magFilter;
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru									TextureUnitCase			(const TextureUnitCase& other);
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	TextureUnitCase&				operator=				(const TextureUnitCase& other);
71750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void							upload2dTexture			(int texNdx, sglr::Context& context);
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void							uploadCubeTexture		(int texNdx, sglr::Context& context);
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void							upload2dArrayTexture	(int texNdx, sglr::Context& context);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void							upload3dTexture			(int texNdx, sglr::Context& context);
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	void							render					(sglr::Context& context);
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const int						m_numUnitsParam;
7268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius	const CaseType					m_caseType;
7278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius	const deUint32					m_randSeed;
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int								m_numTextures;	//!< \note Needed in addition to m_numUnits since same texture may be bound to many texture units.
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int								m_numUnits;		//!< = m_numUnitsParam > 0 ? m_numUnitsParam : implementationDefinedMaximum
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<GLenum>					m_textureTypes;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<TextureParameters>		m_textureParams;
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<tcu::Texture2D*>			m_textures2d;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<tcu::TextureCube*>		m_texturesCube;
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<tcu::Texture2DArray*>	m_textures2dArray;
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<tcu::Texture3D*>			m_textures3d;
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<int>						m_unitTextures;	//!< Which texture is used in a particular unit.
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<int>						m_ndxTexType;	//!< Index of a texture in m_textures2d, m_texturesCube, m_textures2dArray or m_textures3d, depending on texture type.
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	MultiTexShader*					m_shader;
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTextureUnitCase::TextureUnitCase (Context& context, const char* name, const char* desc, int numUnits, CaseType caseType, deUint32 randSeed)
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	: TestCase			(context, tcu::NODETYPE_SELF_VALIDATE, name, desc)
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	, m_numUnitsParam	(numUnits)
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	, m_caseType		(caseType)
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	, m_randSeed		(randSeed)
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	, m_shader			(DE_NULL)
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTextureUnitCase::~TextureUnitCase (void)
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	TextureUnitCase::deinit();
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::deinit (void)
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (vector<tcu::Texture2D*>::iterator i = m_textures2d.begin(); i != m_textures2d.end(); i++)
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		delete *i;
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_textures2d.clear();
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (vector<tcu::TextureCube*>::iterator i = m_texturesCube.begin(); i != m_texturesCube.end(); i++)
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		delete *i;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_texturesCube.clear();
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (vector<tcu::Texture2DArray*>::iterator i = m_textures2dArray.begin(); i != m_textures2dArray.end(); i++)
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		delete *i;
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_textures2dArray.clear();
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (vector<tcu::Texture3D*>::iterator i = m_textures3d.begin(); i != m_textures3d.end(); i++)
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		delete *i;
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_textures3d.clear();
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	delete m_shader;
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_shader = DE_NULL;
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::init (void)
78050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_numUnits = m_numUnitsParam > 0 ? m_numUnitsParam : m_context.getContextInfo().getInt(GL_MAX_TEXTURE_IMAGE_UNITS);
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Make the textures.
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	try
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tcu::TestLog&	log	= m_testCtx.getLog();
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		de::Random		rnd	(m_randSeed);
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rnd.getFloat() < 0.7f)
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_numTextures = m_numUnits;											// In most cases use one unit per texture.
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_numTextures = rnd.getInt(deMax32(1, m_numUnits - 2), m_numUnits);	// Sometimes assign same texture to multiple units.
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		log << tcu::TestLog::Message << ("Using " + de::toString(m_numUnits) + " texture unit(s) and " + de::toString(m_numTextures) + " texture(s)").c_str() << tcu::TestLog::EndMessage;
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_textureTypes.reserve(m_numTextures);
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_textureParams.reserve(m_numTextures);
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_ndxTexType.reserve(m_numTextures);
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Generate textures.
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			// Either fixed or randomized target types, and randomized parameters for every texture.
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			TextureParameters	params;
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_STATIC_ASSERT(CASE_ONLY_2D == 0 && CASE_MIXED + 1 == CASE_LAST);
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int						texType			= m_caseType == CASE_MIXED ? rnd.getInt(0, (int)CASE_MIXED - 1) : (int)m_caseType;
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					is2dTex			= texType == 0;
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					isCubeTex		= texType == 1;
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					is2dArrayTex	= texType == 2;
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					is3dTex			= texType == 3;
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_ASSERT(is2dTex || isCubeTex || is2dArrayTex || is3dTex);
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			GLenum					type			= is2dTex		? GL_TEXTURE_2D		: isCubeTex ? GL_TEXTURE_CUBE_MAP	: is2dArrayTex ? GL_TEXTURE_2D_ARRAY		: GL_TEXTURE_3D;
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const int				texWidth		= is2dTex		? TEXTURE_WIDTH_2D	: isCubeTex ? TEXTURE_WIDTH_CUBE	: is2dArrayTex ? TEXTURE_WIDTH_2D_ARRAY		: TEXTURE_WIDTH_3D;
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const int				texHeight		= is2dTex		? TEXTURE_HEIGHT_2D	: isCubeTex ? TEXTURE_HEIGHT_CUBE	: is2dArrayTex ? TEXTURE_HEIGHT_2D_ARRAY	: TEXTURE_HEIGHT_3D;
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const int				texDepth		= is3dTex ? TEXTURE_DEPTH_3D : 1;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const int				texLayers		= is2dArrayTex ? TEXTURE_LAYERS_2D_ARRAY : 1;
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					mipmaps			= (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight) && deIsPowerOfTwo32(texDepth));
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int						numLevels		= mipmaps ? deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth))+1 : 1;
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			params.internalFormat = s_testSizedInternalFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testSizedInternalFormats) - 1)];
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(params.internalFormat);
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			params.wrapModeS = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			params.wrapModeT = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			params.wrapModeR = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			params.magFilter = isFilterable ? s_testMagFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMagFilters) - 1)] : GL_NEAREST;
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (mipmaps)
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				params.minFilter = isFilterable ?
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					s_testMinFilters			[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMinFilters) - 1)] :
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					s_testNearestMinFilters		[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNearestMinFilters) - 1)];
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				params.minFilter = isFilterable ?
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					s_testNonMipmapMinFilters	[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNonMipmapMinFilters) - 1)] :
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					GL_NEAREST;
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_textureTypes.push_back(type);
8498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius			m_textureParams.push_back(params);
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Create new texture.
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::TextureFormat texFormat = glu::mapGLInternalFormat((deUint32)params.internalFormat);
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (is2dTex)
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_ndxTexType.push_back((int)m_textures2d.size()); // Remember the index this texture has in the 2d texture vector.
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_textures2d.push_back(new tcu::Texture2D(texFormat, texWidth, texHeight));
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else if (isCubeTex)
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_ndxTexType.push_back((int)m_texturesCube.size()); // Remember the index this texture has in the cube texture vector.
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				DE_ASSERT(texWidth == texHeight);
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_texturesCube.push_back(new tcu::TextureCube(texFormat, texWidth));
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else if (is2dArrayTex)
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_ndxTexType.push_back((int)m_textures2dArray.size()); // Remember the index this texture has in the 2d array texture vector.
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_textures2dArray.push_back(new tcu::Texture2DArray(texFormat, texWidth, texHeight, texLayers));
87050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			}
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_ndxTexType.push_back((int)m_textures3d.size()); // Remember the index this texture has in the 3d vector.
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				m_textures3d.push_back(new tcu::Texture3D(texFormat, texWidth, texHeight, texDepth));
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Vec4					cBias		= fmtInfo.valueMin;
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Fill with grid texture.
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int numFaces = isCubeTex ? (int)tcu::CUBEFACE_LAST : 1;
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (int face = 0; face < numFaces; face++)
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deUint32 rgb	= rnd.getUint32() & 0x00ffffff;
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deUint32 alpha	= 0xff000000;
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deUint32 colorA = alpha | rgb;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				deUint32 colorB = alpha | ((~rgb) & 0x00ffffff);
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				{
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (is2dTex)
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						m_textures2d.back()->allocLevel(levelNdx);
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					else if (isCubeTex)
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						m_texturesCube.back()->allocLevel((tcu::CubeFace)face, levelNdx);
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					else if (is2dArrayTex)
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						m_textures2dArray.back()->allocLevel(levelNdx);
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					else
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						m_textures3d.back()->allocLevel(levelNdx);
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					int curCellSize = deMax32(1, GRID_CELL_SIZE >> levelNdx); // \note Scale grid cell size for mipmaps.
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					tcu::PixelBufferAccess access = is2dTex			? m_textures2d.back()->getLevel(levelNdx)
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												  : isCubeTex		? m_texturesCube.back()->getLevelFace(levelNdx, (tcu::CubeFace)face)
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												  : is2dArrayTex	? m_textures2dArray.back()->getLevel(levelNdx)
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru												  :					  m_textures3d.back()->getLevel(levelNdx);
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					tcu::fillWithGrid(access, curCellSize, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias);
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
91350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			}
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Assign a texture index to each unit.
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_unitTextures.reserve(m_numUnits);
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// \note Every texture is used at least once.
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int i = 0; i < m_numTextures; i++)
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_unitTextures.push_back(i);
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Assign a random texture to remaining units.
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while ((int)m_unitTextures.size() < m_numUnits)
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			m_unitTextures.push_back(rnd.getInt(0, m_numTextures - 1));
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rnd.shuffle(m_unitTextures.begin(), m_unitTextures.end());
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Generate information for shader.
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<GLenum>			unitTypes;
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<Vec4>			texScales;
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<Vec4>			texBiases;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<glu::DataType>	samplerTypes;
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<int>				num2dArrayLayers;
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		unitTypes.reserve(m_numUnits);
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		texScales.reserve(m_numUnits);
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		texBiases.reserve(m_numUnits);
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		samplerTypes.reserve(m_numUnits);
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		num2dArrayLayers.reserve(m_numUnits);
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int i = 0; i < m_numUnits; i++)
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int						texNdx		= m_unitTextures[i];
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			GLenum					type		= m_textureTypes[texNdx];
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::TextureFormat		fmt			= glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat);
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(fmt);
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			unitTypes.push_back(type);
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (type == GL_TEXTURE_2D_ARRAY)
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				num2dArrayLayers.push_back(m_textures2dArray[m_ndxTexType[texNdx]]->getNumLayers());
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			texScales.push_back(fmtInfo.lookupScale);
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			texBiases.push_back(fmtInfo.lookupBias);
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			switch (type)
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D:			samplerTypes.push_back(glu::getSampler2DType(fmt));			break;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_CUBE_MAP:	samplerTypes.push_back(glu::getSamplerCubeType(fmt));		break;
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D_ARRAY:	samplerTypes.push_back(glu::getSampler2DArrayType(fmt));	break;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_3D:			samplerTypes.push_back(glu::getSampler3DType(fmt));			break;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				default:
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					DE_ASSERT(DE_FALSE);
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Create shader.
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(m_shader == DE_NULL);
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_shader = new MultiTexShader(rnd.getUint32(), m_numUnits, unitTypes, samplerTypes, texScales, texBiases, num2dArrayLayers);
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	catch (const std::exception&)
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Clean up to save memory.
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		TextureUnitCase::deinit();
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		throw;
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTextureUnitCase::IterateResult TextureUnitCase::iterate (void)
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	glu::RenderContext&			renderCtx			= m_context.getRenderContext();
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const tcu::RenderTarget&	renderTarget		= renderCtx.getRenderTarget();
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	tcu::TestLog&				log					= m_testCtx.getLog();
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	de::Random					rnd					(m_randSeed);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							viewportWidth		= deMin32(VIEWPORT_WIDTH, renderTarget.getWidth());
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							viewportHeight		= deMin32(VIEWPORT_HEIGHT, renderTarget.getHeight());
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							viewportX			= rnd.getInt(0, renderTarget.getWidth() - viewportWidth);
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							viewportY			= rnd.getInt(0, renderTarget.getHeight() - viewportHeight);
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	tcu::Surface				gles3Frame			(viewportWidth, viewportHeight);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	tcu::Surface				refFrame			(viewportWidth, viewportHeight);
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// First we do some tricks to make the LODs safer wrt. precision issues. See MultiTexShader::makeSafeLods().
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		vector<IVec3> texSizes;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		texSizes.reserve(m_numUnits);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int i = 0; i < m_numUnits; i++)
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int		texNdx			= m_unitTextures[i];
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int		texNdxInType	= m_ndxTexType[texNdx];
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			GLenum	type			= m_textureTypes[texNdx];
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			switch (type)
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D:			texSizes.push_back(IVec3(m_textures2d[texNdxInType]->getWidth(),		m_textures2d[texNdxInType]->getHeight(),		0));										break;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_CUBE_MAP:	texSizes.push_back(IVec3(m_texturesCube[texNdxInType]->getSize(),		m_texturesCube[texNdxInType]->getSize(),		0));										break;
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D_ARRAY:	texSizes.push_back(IVec3(m_textures2dArray[texNdxInType]->getWidth(),	m_textures2dArray[texNdxInType]->getHeight(),	0));										break;
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_3D:			texSizes.push_back(IVec3(m_textures3d[texNdxInType]->getWidth(),		m_textures3d[texNdxInType]->getHeight(),		m_textures3d[texNdxInType]->getDepth()));	break;
101650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho				default:
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					DE_ASSERT(DE_FALSE);
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		m_shader->makeSafeLods(texSizes, IVec2(viewportWidth, viewportHeight));
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Render using GLES3.
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS|sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(viewportX, viewportY, viewportWidth, viewportHeight));
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		render(context);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.readPixels(gles3Frame, 0, 0, viewportWidth, viewportHeight);
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Render reference image.
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, viewportWidth, viewportHeight);
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
103850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho		render(context);
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.readPixels(refFrame, 0, 0, viewportWidth, viewportHeight);
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Compare images.
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const float		threshold	= 0.001f;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	bool			isOk		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles3Frame, threshold, tcu::COMPARE_LOG_RESULT);
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Store test result.
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							isOk ? "Pass"				: "Image comparison failed");
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return STOP;
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::upload2dTexture (int texNdx, sglr::Context& context)
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int						ndx2d		= m_ndxTexType[texNdx];
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const tcu::Texture2D*	texture		= m_textures2d[ndx2d];
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	glu::TransferFormat		formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (texture->isLevelEmpty(levelNdx))
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tcu::ConstPixelBufferAccess		access	= texture->getLevel(levelNdx);
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int								width	= access.getWidth();
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int								height	= access.getHeight();
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.texImage2D(GL_TEXTURE_2D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d texture image data");
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::uploadCubeTexture (int texNdx, sglr::Context& context)
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							ndxCube		= m_ndxTexType[texNdx];
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const tcu::TextureCube*		texture		= m_texturesCube[ndxCube];
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			if (texture->isLevelEmpty((tcu::CubeFace)face, levelNdx))
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				continue;
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::ConstPixelBufferAccess		access	= texture->getLevelFace(levelNdx, (tcu::CubeFace)face);
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int								width	= access.getWidth();
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			int								height	= access.getHeight();
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			context.texImage2D(s_cubeFaceTargets[face], levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			GLU_EXPECT_NO_ERROR(context.getError(), "Set cube map image data");
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::upload2dArrayTexture (int texNdx, sglr::Context& context)
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							ndx2dArray	= m_ndxTexType[texNdx];
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const tcu::Texture2DArray*	texture		= m_textures2dArray[ndx2dArray];
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (texture->isLevelEmpty(levelNdx))
111650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			continue;
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							width	= access.getWidth();
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							height	= access.getHeight();
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							layers	= access.getDepth();
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_textureParams[texNdx].internalFormat, width, height, layers, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d array texture image data");
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::upload3dTexture (int texNdx, sglr::Context& context)
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int							ndx3d		= m_ndxTexType[texNdx];
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const tcu::Texture3D*		texture		= m_textures3d[ndx3d];
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (texture->isLevelEmpty(levelNdx))
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							width	= access.getWidth();
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							height	= access.getHeight();
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int							depth	= access.getDepth();
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.texImage3D(GL_TEXTURE_3D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, depth, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLU_EXPECT_NO_ERROR(context.getError(), "Set 3d texture image data");
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitCase::render (sglr::Context& context)
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Setup textures.
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	vector<deUint32>	textureGLNames;
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	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.
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	textureGLNames.resize(m_numTextures);
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.genTextures(m_numTextures, &textureGLNames[0]);
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GLU_EXPECT_NO_ERROR(context.getError(), "Generate textures");
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int texNdx = m_unitTextures[unitNdx];
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		// Bind texture to unit.
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.activeTexture(GL_TEXTURE0 + unitNdx);
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLU_EXPECT_NO_ERROR(context.getError(), "Set active texture");
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		context.bindTexture(m_textureTypes[texNdx], textureGLNames[texNdx]);
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		GLU_EXPECT_NO_ERROR(context.getError(), "Bind texture");
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (!isTextureSetUp[texNdx])
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			// Binding this texture for first time, so set parameters and data.
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_S, m_textureParams[texNdx].wrapModeS);
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_T, m_textureParams[texNdx].wrapModeT);
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (m_textureTypes[texNdx] == GL_TEXTURE_3D)
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_R, m_textureParams[texNdx].wrapModeR);
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MIN_FILTER, m_textureParams[texNdx].minFilter);
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MAG_FILTER, m_textureParams[texNdx].magFilter);
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			GLU_EXPECT_NO_ERROR(context.getError(), "Set texture parameters");
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			switch (m_textureTypes[texNdx])
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			{
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D:			upload2dTexture(texNdx, context);		break;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_CUBE_MAP:	uploadCubeTexture(texNdx, context);		break;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_2D_ARRAY:	upload2dArrayTexture(texNdx, context);	break;
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case GL_TEXTURE_3D:			upload3dTexture(texNdx, context);		break;
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				default:
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					DE_ASSERT(DE_FALSE);
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			isTextureSetUp[texNdx] = true; // Don't set up this texture's parameters and data again later.
120150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho		}
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GLU_EXPECT_NO_ERROR(context.getError(), "Set textures");
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Setup shader
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	deUint32 shaderID = context.createProgram(m_shader);
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Draw.
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m_shader->setUniforms(context, shaderID);
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GLU_EXPECT_NO_ERROR(context.getError(), "Draw");
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	// Delete previously generated texture names.
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	context.deleteTextures(m_numTextures, &textureGLNames[0]);
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	GLU_EXPECT_NO_ERROR(context.getError(), "Delete textures");
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTextureUnitTests::TextureUnitTests (Context& context)
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	: TestCaseGroup(context, "units", "Texture Unit Usage Tests")
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTextureUnitTests::~TextureUnitTests (void)
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TextureUnitTests::init (void)
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const int numTestsPerGroup = 10;
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static const int unitCounts[] =
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		2,
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		4,
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		8,
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		-1 // \note Negative stands for the implementation-specified maximum.
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	};
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (int unitCountNdx = 0; unitCountNdx < DE_LENGTH_OF_ARRAY(unitCounts); unitCountNdx++)
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int numUnits = unitCounts[unitCountNdx];
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		string countGroupName = (unitCounts[unitCountNdx] < 0 ? "all" : de::toString(numUnits)) + "_units";
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tcu::TestCaseGroup* countGroup = new tcu::TestCaseGroup(m_testCtx, countGroupName.c_str(), "");
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		addChild(countGroup);
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DE_STATIC_ASSERT((int)TextureUnitCase::CASE_ONLY_2D == 0);
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (int caseType = (int)TextureUnitCase::CASE_ONLY_2D; caseType < (int)TextureUnitCase::CASE_LAST; caseType++)
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		{
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const char* caseTypeGroupName = (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D		? "only_2d"
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_CUBE		? "only_cube"
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D_ARRAY	? "only_2d_array"
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_3D		? "only_3d"
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_MIXED			? "mixed"
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru										  : DE_NULL;
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			DE_ASSERT(caseTypeGroupName != DE_NULL);
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			tcu::TestCaseGroup* caseTypeGroup = new tcu::TestCaseGroup(m_testCtx, caseTypeGroupName, "");
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			countGroup->addChild(caseTypeGroup);
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (int testNdx = 0; testNdx < numTestsPerGroup; testNdx++)
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				caseTypeGroup->addChild(new TextureUnitCase(m_context, de::toString(testNdx).c_str(), "", numUnits, (TextureUnitCase::CaseType)caseType, deUint32Hash((deUint32)testNdx)));
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} // Functional
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} // gles3
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} // deqp
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru