1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Vertex texture tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es3fVertexTextureTests.hpp"
25e5c31af7Sopenharmony_ci#include "glsTextureTestUtil.hpp"
26e5c31af7Sopenharmony_ci#include "gluTexture.hpp"
27e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
28e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
29e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
30e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp"
31e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
32e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
33e5c31af7Sopenharmony_ci#include "deMath.h"
34e5c31af7Sopenharmony_ci#include "deRandom.hpp"
35e5c31af7Sopenharmony_ci#include "deString.h"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include <string>
38e5c31af7Sopenharmony_ci#include <vector>
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_ci#include <limits>
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#include "glw.h"
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ciusing tcu::TestLog;
45e5c31af7Sopenharmony_ciusing tcu::Vec2;
46e5c31af7Sopenharmony_ciusing tcu::Vec3;
47e5c31af7Sopenharmony_ciusing tcu::Vec4;
48e5c31af7Sopenharmony_ciusing tcu::IVec2;
49e5c31af7Sopenharmony_ciusing tcu::IVec3;
50e5c31af7Sopenharmony_ciusing tcu::IVec4;
51e5c31af7Sopenharmony_ciusing tcu::Mat3;
52e5c31af7Sopenharmony_ciusing std::string;
53e5c31af7Sopenharmony_ciusing std::vector;
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_cinamespace deqp
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ciusing namespace gls::TextureTestUtil;
59e5c31af7Sopenharmony_ciusing namespace glu::TextureTestUtil;
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ciusing glu::TextureTestUtil::TEXTURETYPE_2D;
62e5c31af7Sopenharmony_ciusing glu::TextureTestUtil::TEXTURETYPE_CUBE;
63e5c31af7Sopenharmony_ciusing glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY;
64e5c31af7Sopenharmony_ciusing glu::TextureTestUtil::TEXTURETYPE_3D;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_cinamespace gles3
67e5c31af7Sopenharmony_ci{
68e5c31af7Sopenharmony_cinamespace Functional
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_cistatic const int WIDTH_2D_ARRAY				= 128;
72e5c31af7Sopenharmony_cistatic const int HEIGHT_2D_ARRAY			= 128;
73e5c31af7Sopenharmony_cistatic const int LAYERS_2D_ARRAY			= 8;
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_cistatic const int WIDTH_3D					= 64;
76e5c31af7Sopenharmony_cistatic const int HEIGHT_3D					= 64;
77e5c31af7Sopenharmony_cistatic const int DEPTH_3D					= 64;
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci// The 2D case draws four images.
80e5c31af7Sopenharmony_cistatic const int MAX_2D_RENDER_WIDTH		= 128*2;
81e5c31af7Sopenharmony_cistatic const int MAX_2D_RENDER_HEIGHT		= 128*2;
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci// The cube map case draws four 3-by-2 image groups.
84e5c31af7Sopenharmony_cistatic const int MAX_CUBE_RENDER_WIDTH		= 28*2*3;
85e5c31af7Sopenharmony_cistatic const int MAX_CUBE_RENDER_HEIGHT		= 28*2*2;
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_cistatic const int MAX_2D_ARRAY_RENDER_WIDTH	= 128*2;
88e5c31af7Sopenharmony_cistatic const int MAX_2D_ARRAY_RENDER_HEIGHT	= 128*2;
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_cistatic const int MAX_3D_RENDER_WIDTH		= 128*2;
91e5c31af7Sopenharmony_cistatic const int MAX_3D_RENDER_HEIGHT		= 128*2;
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_cistatic const int GRID_SIZE_2D				= 127;
94e5c31af7Sopenharmony_cistatic const int GRID_SIZE_CUBE				= 63;
95e5c31af7Sopenharmony_cistatic const int GRID_SIZE_2D_ARRAY			= 127;
96e5c31af7Sopenharmony_cistatic const int GRID_SIZE_3D				= 127;
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci// Helpers for making texture coordinates "safe", i.e. move them further from coordinate bounary.
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci// Moves x towards the closest K+targetFraction, where K is an integer.
101e5c31af7Sopenharmony_ci// E.g. moveTowardsFraction(x, 0.5f) moves x away from integer boundaries.
102e5c31af7Sopenharmony_cistatic inline float moveTowardsFraction (float x, float targetFraction)
103e5c31af7Sopenharmony_ci{
104e5c31af7Sopenharmony_ci	const float strictness = 0.5f;
105e5c31af7Sopenharmony_ci	DE_ASSERT(0.0f < strictness && strictness <= 1.0f);
106e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(targetFraction, 0.0f, 1.0f));
107e5c31af7Sopenharmony_ci	const float y = x + 0.5f - targetFraction;
108e5c31af7Sopenharmony_ci	return deFloatFloor(y) + deFloatFrac(y)*(1.0f-strictness) + strictness*0.5f - 0.5f + targetFraction;
109e5c31af7Sopenharmony_ci}
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_cistatic inline float safeCoord (float raw, int scale, float fraction)
112e5c31af7Sopenharmony_ci{
113e5c31af7Sopenharmony_ci	const float scaleFloat = (float)scale;
114e5c31af7Sopenharmony_ci	return moveTowardsFraction(raw*scaleFloat, fraction) / scaleFloat;
115e5c31af7Sopenharmony_ci}
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_citemplate <int Size>
118e5c31af7Sopenharmony_cistatic inline tcu::Vector<float, Size> safeCoords (const tcu::Vector<float, Size>& raw, const tcu::Vector<int, Size>& scale, const tcu::Vector<float, Size>& fraction)
119e5c31af7Sopenharmony_ci{
120e5c31af7Sopenharmony_ci	tcu::Vector<float, Size> result;
121e5c31af7Sopenharmony_ci	for (int i = 0; i < Size; i++)
122e5c31af7Sopenharmony_ci		result[i] = safeCoord(raw[i], scale[i], fraction[i]);
123e5c31af7Sopenharmony_ci	return result;
124e5c31af7Sopenharmony_ci}
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_cistatic inline Vec2 safe2DTexCoords (const Vec2& raw, const IVec2& textureSize)
127e5c31af7Sopenharmony_ci{
128e5c31af7Sopenharmony_ci	return safeCoords(raw, textureSize, Vec2(0.5f));
129e5c31af7Sopenharmony_ci}
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_cistatic inline Vec3 safe2DArrayTexCoords (const Vec3& raw, const IVec3& textureSize)
132e5c31af7Sopenharmony_ci{
133e5c31af7Sopenharmony_ci	return safeCoords(raw, textureSize, Vec3(0.5f, 0.5f, 0.0f));
134e5c31af7Sopenharmony_ci}
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_cistatic inline Vec3 safe3DTexCoords (const Vec3& raw, const IVec3& textureSize)
137e5c31af7Sopenharmony_ci{
138e5c31af7Sopenharmony_ci	return safeCoords(raw, textureSize, Vec3(0.5f));
139e5c31af7Sopenharmony_ci}
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_cinamespace
142e5c31af7Sopenharmony_ci{
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_cistruct Rect
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci			Rect	(int x_, int y_, int w_, int h_) : x(x_), y(y_), w(w_), h(h_) {}
147e5c31af7Sopenharmony_ci	IVec2	pos		(void) const { return IVec2(x, y); }
148e5c31af7Sopenharmony_ci	IVec2	size	(void) const { return IVec2(w, h); }
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci	int		x;
151e5c31af7Sopenharmony_ci	int		y;
152e5c31af7Sopenharmony_ci	int		w;
153e5c31af7Sopenharmony_ci	int		h;
154e5c31af7Sopenharmony_ci};
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_citemplate <TextureType> struct TexTypeTcuClass;
157e5c31af7Sopenharmony_citemplate <> struct TexTypeTcuClass<TEXTURETYPE_2D>			{ typedef tcu::Texture2D		t; };
158e5c31af7Sopenharmony_citemplate <> struct TexTypeTcuClass<TEXTURETYPE_CUBE>		{ typedef tcu::TextureCube		t; };
159e5c31af7Sopenharmony_citemplate <> struct TexTypeTcuClass<TEXTURETYPE_2D_ARRAY>	{ typedef tcu::Texture2DArray	t; };
160e5c31af7Sopenharmony_citemplate <> struct TexTypeTcuClass<TEXTURETYPE_3D>			{ typedef tcu::Texture3D		t; };
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_citemplate <TextureType> struct TexTypeSizeDims;
163e5c31af7Sopenharmony_citemplate <> struct TexTypeSizeDims<TEXTURETYPE_2D>			{ enum { V = 2 }; };
164e5c31af7Sopenharmony_citemplate <> struct TexTypeSizeDims<TEXTURETYPE_CUBE>		{ enum { V = 2 }; };
165e5c31af7Sopenharmony_citemplate <> struct TexTypeSizeDims<TEXTURETYPE_2D_ARRAY>	{ enum { V = 3 }; };
166e5c31af7Sopenharmony_citemplate <> struct TexTypeSizeDims<TEXTURETYPE_3D>			{ enum { V = 3 }; };
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_citemplate <TextureType> struct TexTypeCoordDims;
169e5c31af7Sopenharmony_citemplate <> struct TexTypeCoordDims<TEXTURETYPE_2D>			{ enum { V = 2 }; };
170e5c31af7Sopenharmony_citemplate <> struct TexTypeCoordDims<TEXTURETYPE_CUBE>		{ enum { V = 3 }; };
171e5c31af7Sopenharmony_citemplate <> struct TexTypeCoordDims<TEXTURETYPE_2D_ARRAY>	{ enum { V = 3 }; };
172e5c31af7Sopenharmony_citemplate <> struct TexTypeCoordDims<TEXTURETYPE_3D>			{ enum { V = 3 }; };
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_citemplate <TextureType TexType> struct TexTypeSizeIVec		{ typedef tcu::Vector<int,		TexTypeSizeDims<TexType>::V>	t; };
175e5c31af7Sopenharmony_citemplate <TextureType TexType> struct TexTypeCoordVec		{ typedef tcu::Vector<float,	TexTypeCoordDims<TexType>::V>	t; };
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_citemplate <TextureType> struct TexTypeCoordParams;
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_citemplate <> struct
180e5c31af7Sopenharmony_ciTexTypeCoordParams<TEXTURETYPE_2D>
181e5c31af7Sopenharmony_ci{
182e5c31af7Sopenharmony_ci	Vec2 scale;
183e5c31af7Sopenharmony_ci	Vec2 bias;
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_) : scale(scale_), bias(bias_) {}
186e5c31af7Sopenharmony_ci};
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_citemplate <> struct
189e5c31af7Sopenharmony_ciTexTypeCoordParams<TEXTURETYPE_CUBE>
190e5c31af7Sopenharmony_ci{
191e5c31af7Sopenharmony_ci	Vec2			scale;
192e5c31af7Sopenharmony_ci	Vec2			bias;
193e5c31af7Sopenharmony_ci	tcu::CubeFace	face;
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci	TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_, tcu::CubeFace face_) : scale(scale_), bias(bias_), face(face_) {}
196e5c31af7Sopenharmony_ci};
197e5c31af7Sopenharmony_ci
198e5c31af7Sopenharmony_citemplate <> struct
199e5c31af7Sopenharmony_ciTexTypeCoordParams<TEXTURETYPE_2D_ARRAY>
200e5c31af7Sopenharmony_ci{
201e5c31af7Sopenharmony_ci	Mat3 transform;
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_ci	TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
204e5c31af7Sopenharmony_ci};
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_citemplate <> struct
207e5c31af7Sopenharmony_ciTexTypeCoordParams<TEXTURETYPE_3D>
208e5c31af7Sopenharmony_ci{
209e5c31af7Sopenharmony_ci	Mat3 transform;
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci	TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
212e5c31af7Sopenharmony_ci};
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
215e5c31af7Sopenharmony_ci * \brief Quad grid class containing position and texture coordinate data.
216e5c31af7Sopenharmony_ci *
217e5c31af7Sopenharmony_ci * A quad grid of size S means a grid consisting of S*S quads (S rows and
218e5c31af7Sopenharmony_ci * S columns). The quads are rectangles with main axis aligned sides, and
219e5c31af7Sopenharmony_ci * each consists of two triangles. Note that although there are only
220e5c31af7Sopenharmony_ci * (S+1)*(S+1) distinct vertex positions, there are S*S*4 distinct vertices
221e5c31af7Sopenharmony_ci * because we want texture coordinates to be constant across the vertices
222e5c31af7Sopenharmony_ci * of a quad (to avoid interpolation issues), and thus each quad needs its
223e5c31af7Sopenharmony_ci * own 4 vertices.
224e5c31af7Sopenharmony_ci *
225e5c31af7Sopenharmony_ci * Pointers returned by get*Ptr() are suitable for gl calls such as
226e5c31af7Sopenharmony_ci * glVertexAttribPointer() (for position and tex coord) or glDrawElements()
227e5c31af7Sopenharmony_ci * (for indices).
228e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
229e5c31af7Sopenharmony_citemplate <TextureType TexType>
230e5c31af7Sopenharmony_ciclass PosTexCoordQuadGrid
231e5c31af7Sopenharmony_ci{
232e5c31af7Sopenharmony_ciprivate:
233e5c31af7Sopenharmony_ci	enum { TEX_COORD_DIMS = TexTypeCoordDims <TexType>::V };
234e5c31af7Sopenharmony_ci	typedef typename TexTypeCoordVec<TexType>::t	TexCoordVec;
235e5c31af7Sopenharmony_ci	typedef typename TexTypeSizeIVec<TexType>::t	TexSizeIVec;
236e5c31af7Sopenharmony_ci	typedef TexTypeCoordParams<TexType>				TexCoordParams;
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_cipublic:
239e5c31af7Sopenharmony_ci							PosTexCoordQuadGrid		(int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_ci	int						getSize					(void) const { return m_gridSize; }
242e5c31af7Sopenharmony_ci	Vec4					getQuadLDRU				(int col, int row) const; //!< Vec4(leftX, downY, rightX, upY)
243e5c31af7Sopenharmony_ci	const TexCoordVec&		getQuadTexCoord			(int col, int row) const;
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci	int						getNumIndices			(void) const { return m_gridSize*m_gridSize*3*2; }
246e5c31af7Sopenharmony_ci	const float*			getPositionPtr			(void) const { DE_STATIC_ASSERT(sizeof(Vec2) == 2*sizeof(float)); return (float*)&m_positions[0]; }
247e5c31af7Sopenharmony_ci	const float*			getTexCoordPtr			(void) const { DE_STATIC_ASSERT(sizeof(TexCoordVec) == TEX_COORD_DIMS*(int)sizeof(float)); return (float*)&m_texCoords[0]; }
248e5c31af7Sopenharmony_ci	const deUint16*			getIndexPtr				(void) const { return &m_indices[0]; }
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ciprivate:
251e5c31af7Sopenharmony_ci	void					initializeTexCoords		(const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	const int				m_gridSize;
254e5c31af7Sopenharmony_ci	vector<Vec2>			m_positions;
255e5c31af7Sopenharmony_ci	vector<TexCoordVec>		m_texCoords;
256e5c31af7Sopenharmony_ci	vector<deUint16>		m_indices;
257e5c31af7Sopenharmony_ci};
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_citemplate <TextureType TexType>
260e5c31af7Sopenharmony_ciVec4 PosTexCoordQuadGrid<TexType>::getQuadLDRU (int col, int row) const
261e5c31af7Sopenharmony_ci{
262e5c31af7Sopenharmony_ci	int ndx00 = (row*m_gridSize + col) * 4;
263e5c31af7Sopenharmony_ci	int ndx11 = ndx00 + 3;
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci	return Vec4(m_positions[ndx00].x(),
266e5c31af7Sopenharmony_ci				m_positions[ndx00].y(),
267e5c31af7Sopenharmony_ci				m_positions[ndx11].x(),
268e5c31af7Sopenharmony_ci				m_positions[ndx11].y());
269e5c31af7Sopenharmony_ci}
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_citemplate <TextureType TexType>
272e5c31af7Sopenharmony_ciconst typename TexTypeCoordVec<TexType>::t& PosTexCoordQuadGrid<TexType>::getQuadTexCoord (int col, int row) const
273e5c31af7Sopenharmony_ci{
274e5c31af7Sopenharmony_ci	return m_texCoords[(row*m_gridSize + col) * 4];
275e5c31af7Sopenharmony_ci}
276e5c31af7Sopenharmony_ci
277e5c31af7Sopenharmony_citemplate <TextureType TexType>
278e5c31af7Sopenharmony_ciPosTexCoordQuadGrid<TexType>::PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
279e5c31af7Sopenharmony_ci	: m_gridSize(gridSize)
280e5c31af7Sopenharmony_ci{
281e5c31af7Sopenharmony_ci	DE_ASSERT(m_gridSize > 0 && m_gridSize*m_gridSize <= (int)std::numeric_limits<deUint16>::max() + 1);
282e5c31af7Sopenharmony_ci
283e5c31af7Sopenharmony_ci	const float gridSizeFloat = (float)m_gridSize;
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	m_positions.reserve(m_gridSize*m_gridSize*4);
286e5c31af7Sopenharmony_ci	m_indices.reserve(m_gridSize*m_gridSize*3*2);
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci	for (int y = 0; y < m_gridSize; y++)
289e5c31af7Sopenharmony_ci	for (int x = 0; x < m_gridSize; x++)
290e5c31af7Sopenharmony_ci	{
291e5c31af7Sopenharmony_ci		float fx0 = (float)(x+0) / gridSizeFloat;
292e5c31af7Sopenharmony_ci		float fx1 = (float)(x+1) / gridSizeFloat;
293e5c31af7Sopenharmony_ci		float fy0 = (float)(y+0) / gridSizeFloat;
294e5c31af7Sopenharmony_ci		float fy1 = (float)(y+1) / gridSizeFloat;
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci		Vec2 quadVertices[4] = { Vec2(fx0, fy0), Vec2(fx1, fy0), Vec2(fx0, fy1), Vec2(fx1, fy1) };
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci		int firstNdx = (int)m_positions.size();
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_ci		for (int i = 0; i < DE_LENGTH_OF_ARRAY(quadVertices); i++)
301e5c31af7Sopenharmony_ci			m_positions.push_back(safeCoords(quadVertices[i], renderSize, Vec2(0.0f)) * 2.0f - 1.0f);
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 0));
304e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 1));
305e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 2));
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 1));
308e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 3));
309e5c31af7Sopenharmony_ci		m_indices.push_back(deUint16(firstNdx + 2));
310e5c31af7Sopenharmony_ci	}
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ci	m_texCoords.reserve(m_gridSize*m_gridSize*4);
313e5c31af7Sopenharmony_ci	initializeTexCoords(textureSize, texCoordParams, useSafeTexCoords);
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci	DE_ASSERT((int)m_positions.size() == m_gridSize*m_gridSize*4);
316e5c31af7Sopenharmony_ci	DE_ASSERT((int)m_indices.size() == m_gridSize*m_gridSize*3*2);
317e5c31af7Sopenharmony_ci	DE_ASSERT((int)m_texCoords.size() == m_gridSize*m_gridSize*4);
318e5c31af7Sopenharmony_ci}
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_citemplate <>
321e5c31af7Sopenharmony_civoid PosTexCoordQuadGrid<TEXTURETYPE_2D>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
322e5c31af7Sopenharmony_ci{
323e5c31af7Sopenharmony_ci	DE_ASSERT(m_texCoords.empty());
324e5c31af7Sopenharmony_ci
325e5c31af7Sopenharmony_ci	const float gridSizeFloat = (float)m_gridSize;
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	for (int y = 0; y < m_gridSize; y++)
328e5c31af7Sopenharmony_ci	for (int x = 0; x < m_gridSize; x++)
329e5c31af7Sopenharmony_ci	{
330e5c31af7Sopenharmony_ci		Vec2 rawCoord = Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) * texCoordParams.scale + texCoordParams.bias;
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
333e5c31af7Sopenharmony_ci			m_texCoords.push_back(useSafeTexCoords ? safe2DTexCoords(rawCoord, textureSize) : rawCoord);
334e5c31af7Sopenharmony_ci	}
335e5c31af7Sopenharmony_ci}
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_citemplate <>
338e5c31af7Sopenharmony_civoid PosTexCoordQuadGrid<TEXTURETYPE_CUBE>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
339e5c31af7Sopenharmony_ci{
340e5c31af7Sopenharmony_ci	DE_ASSERT(m_texCoords.empty());
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_ci	const float		gridSizeFloat	= (float)m_gridSize;
343e5c31af7Sopenharmony_ci	vector<float>	texBoundaries;
344e5c31af7Sopenharmony_ci	computeQuadTexCoordCube(texBoundaries, texCoordParams.face);
345e5c31af7Sopenharmony_ci	const Vec3		coordA			= Vec3(texBoundaries[0], texBoundaries[1], texBoundaries[2]);
346e5c31af7Sopenharmony_ci	const Vec3		coordB			= Vec3(texBoundaries[3], texBoundaries[4], texBoundaries[5]);
347e5c31af7Sopenharmony_ci	const Vec3		coordC			= Vec3(texBoundaries[6], texBoundaries[7], texBoundaries[8]);
348e5c31af7Sopenharmony_ci	const Vec3		coordAB			= coordB - coordA;
349e5c31af7Sopenharmony_ci	const Vec3		coordAC			= coordC - coordA;
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_ci	for (int y = 0; y < m_gridSize; y++)
352e5c31af7Sopenharmony_ci	for (int x = 0; x < m_gridSize; x++)
353e5c31af7Sopenharmony_ci	{
354e5c31af7Sopenharmony_ci		const Vec2 rawFaceCoord		= texCoordParams.scale * Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) + texCoordParams.bias;
355e5c31af7Sopenharmony_ci		const Vec2 safeFaceCoord	= useSafeTexCoords ? safe2DTexCoords(rawFaceCoord, textureSize) : rawFaceCoord;
356e5c31af7Sopenharmony_ci		const Vec3 texCoord			= coordA + coordAC*safeFaceCoord.x() + coordAB*safeFaceCoord.y();
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
359e5c31af7Sopenharmony_ci			m_texCoords.push_back(texCoord);
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci}
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_citemplate <>
364e5c31af7Sopenharmony_civoid PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
365e5c31af7Sopenharmony_ci{
366e5c31af7Sopenharmony_ci	DE_ASSERT(m_texCoords.empty());
367e5c31af7Sopenharmony_ci
368e5c31af7Sopenharmony_ci	const float gridSizeFloat = (float)m_gridSize;
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci	for (int y = 0; y < m_gridSize; y++)
371e5c31af7Sopenharmony_ci	for (int x = 0; x < m_gridSize; x++)
372e5c31af7Sopenharmony_ci	{
373e5c31af7Sopenharmony_ci		const Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
376e5c31af7Sopenharmony_ci			m_texCoords.push_back(useSafeTexCoords ? safe2DArrayTexCoords(rawCoord, textureSize) : rawCoord);
377e5c31af7Sopenharmony_ci	}
378e5c31af7Sopenharmony_ci}
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_citemplate <>
381e5c31af7Sopenharmony_civoid PosTexCoordQuadGrid<TEXTURETYPE_3D>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
382e5c31af7Sopenharmony_ci{
383e5c31af7Sopenharmony_ci	DE_ASSERT(m_texCoords.empty());
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_ci	const float gridSizeFloat = (float)m_gridSize;
386e5c31af7Sopenharmony_ci
387e5c31af7Sopenharmony_ci	for (int y = 0; y < m_gridSize; y++)
388e5c31af7Sopenharmony_ci	for (int x = 0; x < m_gridSize; x++)
389e5c31af7Sopenharmony_ci	{
390e5c31af7Sopenharmony_ci		Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
393e5c31af7Sopenharmony_ci			m_texCoords.push_back(useSafeTexCoords ? safe3DTexCoords(rawCoord, textureSize) : rawCoord);
394e5c31af7Sopenharmony_ci	}
395e5c31af7Sopenharmony_ci}
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci} // anonymous
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_cistatic inline bool isLevelNearest (deUint32 filter)
400e5c31af7Sopenharmony_ci{
401e5c31af7Sopenharmony_ci	return filter == GL_NEAREST || filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_NEAREST_MIPMAP_LINEAR;
402e5c31af7Sopenharmony_ci}
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_cistatic inline IVec2 getTextureSize (const glu::Texture2D& tex)
405e5c31af7Sopenharmony_ci{
406e5c31af7Sopenharmony_ci	const tcu::Texture2D& ref = tex.getRefTexture();
407e5c31af7Sopenharmony_ci	return IVec2(ref.getWidth(), ref.getHeight());
408e5c31af7Sopenharmony_ci}
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_cistatic inline IVec2 getTextureSize (const glu::TextureCube& tex)
411e5c31af7Sopenharmony_ci{
412e5c31af7Sopenharmony_ci	const tcu::TextureCube& ref = tex.getRefTexture();
413e5c31af7Sopenharmony_ci	return IVec2(ref.getSize(), ref.getSize());
414e5c31af7Sopenharmony_ci}
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_cistatic inline IVec3 getTextureSize (const glu::Texture2DArray& tex)
417e5c31af7Sopenharmony_ci{
418e5c31af7Sopenharmony_ci	const tcu::Texture2DArray& ref = tex.getRefTexture();
419e5c31af7Sopenharmony_ci	return IVec3(ref.getWidth(), ref.getHeight(), ref.getNumLayers());
420e5c31af7Sopenharmony_ci}
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_cistatic inline IVec3 getTextureSize (const glu::Texture3D& tex)
423e5c31af7Sopenharmony_ci{
424e5c31af7Sopenharmony_ci	const tcu::Texture3D& ref = tex.getRefTexture();
425e5c31af7Sopenharmony_ci	return IVec3(ref.getWidth(), ref.getHeight(), ref.getDepth());
426e5c31af7Sopenharmony_ci}
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_citemplate <TextureType TexType>
429e5c31af7Sopenharmony_cistatic void setPixelColors (const vector<Vec4>& quadColors, const Rect& region, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst)
430e5c31af7Sopenharmony_ci{
431e5c31af7Sopenharmony_ci	const int gridSize = grid.getSize();
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci	for (int y = 0; y < gridSize; y++)
434e5c31af7Sopenharmony_ci	for (int x = 0; x < gridSize; x++)
435e5c31af7Sopenharmony_ci	{
436e5c31af7Sopenharmony_ci		const Vec4	color	= quadColors[y*gridSize + x];
437e5c31af7Sopenharmony_ci		const Vec4	ldru	= grid.getQuadLDRU(x, y) * 0.5f + 0.5f; // [-1, 1] -> [0, 1]
438e5c31af7Sopenharmony_ci		const int	ix0		= deCeilFloatToInt32(ldru.x() * (float)region.w - 0.5f);
439e5c31af7Sopenharmony_ci		const int	ix1		= deCeilFloatToInt32(ldru.z() * (float)region.w - 0.5f);
440e5c31af7Sopenharmony_ci		const int	iy0		= deCeilFloatToInt32(ldru.y() * (float)region.h - 0.5f);
441e5c31af7Sopenharmony_ci		const int	iy1		= deCeilFloatToInt32(ldru.w() * (float)region.h - 0.5f);
442e5c31af7Sopenharmony_ci
443e5c31af7Sopenharmony_ci		for (int iy = iy0; iy < iy1; iy++)
444e5c31af7Sopenharmony_ci		for (int ix = ix0; ix < ix1; ix++)
445e5c31af7Sopenharmony_ci		{
446e5c31af7Sopenharmony_ci			DE_ASSERT(deInBounds32(ix + region.x, 0, dst.getWidth()));
447e5c31af7Sopenharmony_ci			DE_ASSERT(deInBounds32(iy + region.y, 0, dst.getHeight()));
448e5c31af7Sopenharmony_ci
449e5c31af7Sopenharmony_ci			dst.setPixel(ix + region.x, iy + region.y, tcu::RGBA(color));
450e5c31af7Sopenharmony_ci		}
451e5c31af7Sopenharmony_ci	}
452e5c31af7Sopenharmony_ci}
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_cistatic inline Vec4 sample (const tcu::Texture2D&		tex, const Vec2& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), lod); }
455e5c31af7Sopenharmony_cistatic inline Vec4 sample (const tcu::TextureCube&		tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
456e5c31af7Sopenharmony_cistatic inline Vec4 sample (const tcu::Texture2DArray&	tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
457e5c31af7Sopenharmony_cistatic inline Vec4 sample (const tcu::Texture3D&		tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_citemplate <TextureType TexType>
460e5c31af7Sopenharmony_civoid computeReference (const typename TexTypeTcuClass<TexType>::t& texture, float lod, const tcu::Sampler& sampler, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst, const Rect& dstRegion)
461e5c31af7Sopenharmony_ci{
462e5c31af7Sopenharmony_ci	const int		gridSize	= grid.getSize();
463e5c31af7Sopenharmony_ci	vector<Vec4>	quadColors	(gridSize*gridSize);
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	for (int y = 0; y < gridSize; y++)
466e5c31af7Sopenharmony_ci	for (int x = 0; x < gridSize; x++)
467e5c31af7Sopenharmony_ci	{
468e5c31af7Sopenharmony_ci		const int										ndx		= y*gridSize + x;
469e5c31af7Sopenharmony_ci		const typename TexTypeCoordVec<TexType>::t&		coord	= grid.getQuadTexCoord(x, y);
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci		quadColors[ndx] = sample(texture, coord, lod, sampler);
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci	setPixelColors(quadColors, dstRegion, grid, dst);
475e5c31af7Sopenharmony_ci}
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_cistatic bool compareImages (const glu::RenderContext& renderCtx, tcu::TestLog& log, const tcu::Surface& ref, const tcu::Surface& res)
478e5c31af7Sopenharmony_ci{
479e5c31af7Sopenharmony_ci	DE_ASSERT(renderCtx.getRenderTarget().getNumSamples() == 0);
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(15,15,15,15);
482e5c31af7Sopenharmony_ci	return tcu::pixelThresholdCompare(log, "Result", "Image compare result", ref, res, threshold, tcu::COMPARE_LOG_RESULT);
483e5c31af7Sopenharmony_ci}
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_ciclass Vertex2DTextureCase : public TestCase
486e5c31af7Sopenharmony_ci{
487e5c31af7Sopenharmony_cipublic:
488e5c31af7Sopenharmony_ci								Vertex2DTextureCase		(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
489e5c31af7Sopenharmony_ci								~Vertex2DTextureCase	(void);
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci	void						init					(void);
492e5c31af7Sopenharmony_ci	void						deinit					(void);
493e5c31af7Sopenharmony_ci	IterateResult				iterate					(void);
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ciprivate:
496e5c31af7Sopenharmony_ci	typedef PosTexCoordQuadGrid<TEXTURETYPE_2D> Grid;
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci								Vertex2DTextureCase		(const Vertex2DTextureCase& other);
499e5c31af7Sopenharmony_ci	Vertex2DTextureCase&		operator=				(const Vertex2DTextureCase& other);
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci	float						calculateLod			(const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
502e5c31af7Sopenharmony_ci	void						setupShaderInputs		(int textureNdx, float lod, const Grid& grid) const;
503e5c31af7Sopenharmony_ci	void						renderCell				(int textureNdx, float lod, const Grid& grid) const;
504e5c31af7Sopenharmony_ci	void						computeReferenceCell	(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci	const deUint32				m_minFilter;
507e5c31af7Sopenharmony_ci	const deUint32				m_magFilter;
508e5c31af7Sopenharmony_ci	const deUint32				m_wrapS;
509e5c31af7Sopenharmony_ci	const deUint32				m_wrapT;
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci	const glu::ShaderProgram*	m_program;
512e5c31af7Sopenharmony_ci	glu::Texture2D*				m_textures[2];	// 2 textures, a gradient texture and a grid texture.
513e5c31af7Sopenharmony_ci};
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ciVertex2DTextureCase::Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
516e5c31af7Sopenharmony_ci	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
517e5c31af7Sopenharmony_ci	, m_minFilter			(minFilter)
518e5c31af7Sopenharmony_ci	, m_magFilter			(magFilter)
519e5c31af7Sopenharmony_ci	, m_wrapS				(wrapS)
520e5c31af7Sopenharmony_ci	, m_wrapT				(wrapT)
521e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
522e5c31af7Sopenharmony_ci{
523e5c31af7Sopenharmony_ci	m_textures[0] = DE_NULL;
524e5c31af7Sopenharmony_ci	m_textures[1] = DE_NULL;
525e5c31af7Sopenharmony_ci}
526e5c31af7Sopenharmony_ci
527e5c31af7Sopenharmony_ciVertex2DTextureCase::~Vertex2DTextureCase(void)
528e5c31af7Sopenharmony_ci{
529e5c31af7Sopenharmony_ci	Vertex2DTextureCase::deinit();
530e5c31af7Sopenharmony_ci}
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_civoid Vertex2DTextureCase::init (void)
533e5c31af7Sopenharmony_ci{
534e5c31af7Sopenharmony_ci	const char* const vertexShader =
535e5c31af7Sopenharmony_ci		"#version 300 es\n"
536e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
537e5c31af7Sopenharmony_ci		"in highp vec2 a_texCoord;\n"
538e5c31af7Sopenharmony_ci		"uniform highp sampler2D u_texture;\n"
539e5c31af7Sopenharmony_ci		"uniform highp float u_lod;\n"
540e5c31af7Sopenharmony_ci		"out mediump vec4 v_color;\n"
541e5c31af7Sopenharmony_ci		"\n"
542e5c31af7Sopenharmony_ci		"void main()\n"
543e5c31af7Sopenharmony_ci		"{\n"
544e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
545e5c31af7Sopenharmony_ci		"	v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
546e5c31af7Sopenharmony_ci		"}\n";
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci	const char* const fragmentShader =
549e5c31af7Sopenharmony_ci		"#version 300 es\n"
550e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
551e5c31af7Sopenharmony_ci		"in mediump vec4 v_color;\n"
552e5c31af7Sopenharmony_ci		"\n"
553e5c31af7Sopenharmony_ci		"void main()\n"
554e5c31af7Sopenharmony_ci		"{\n"
555e5c31af7Sopenharmony_ci		"	dEQP_FragColor = v_color;\n"
556e5c31af7Sopenharmony_ci		"}\n";
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	if (m_context.getRenderTarget().getNumSamples() != 0)
559e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("MSAA config not supported by this test");
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
562e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ci	if(!m_program->isOk())
565e5c31af7Sopenharmony_ci	{
566e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ci		GLint maxVertexTextures;
569e5c31af7Sopenharmony_ci		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
570e5c31af7Sopenharmony_ci
571e5c31af7Sopenharmony_ci		if (maxVertexTextures < 1)
572e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
573e5c31af7Sopenharmony_ci		else
574e5c31af7Sopenharmony_ci			TCU_FAIL("Failed to compile shader");
575e5c31af7Sopenharmony_ci	}
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ci	// Make the textures.
578e5c31af7Sopenharmony_ci	try
579e5c31af7Sopenharmony_ci	{
580e5c31af7Sopenharmony_ci		// Compute suitable power-of-two sizes (for mipmaps).
581e5c31af7Sopenharmony_ci		const int texWidth		= 1 << deLog2Ceil32(MAX_2D_RENDER_WIDTH / 2);
582e5c31af7Sopenharmony_ci		const int texHeight		= 1 << deLog2Ceil32(MAX_2D_RENDER_HEIGHT / 2);
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
585e5c31af7Sopenharmony_ci		{
586e5c31af7Sopenharmony_ci			DE_ASSERT(!m_textures[i]);
587e5c31af7Sopenharmony_ci			m_textures[i] = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
588e5c31af7Sopenharmony_ci		}
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_ci		const bool						mipmaps		= (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight));
591e5c31af7Sopenharmony_ci		const int						numLevels	= mipmaps ? deLog2Floor32(de::max(texWidth, texHeight))+1 : 1;
592e5c31af7Sopenharmony_ci		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
593e5c31af7Sopenharmony_ci		const Vec4						cBias		= fmtInfo.valueMin;
594e5c31af7Sopenharmony_ci		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci		// Fill first with gradient texture.
597e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
598e5c31af7Sopenharmony_ci		{
599e5c31af7Sopenharmony_ci			const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
600e5c31af7Sopenharmony_ci			const Vec4 gMax = Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_ci			m_textures[0]->getRefTexture().allocLevel(levelNdx);
603e5c31af7Sopenharmony_ci			tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
604e5c31af7Sopenharmony_ci		}
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci		// Fill second with grid texture.
607e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
608e5c31af7Sopenharmony_ci		{
609e5c31af7Sopenharmony_ci			const deUint32 step		= 0x00ffffff / numLevels;
610e5c31af7Sopenharmony_ci			const deUint32 rgb		= step*levelNdx;
611e5c31af7Sopenharmony_ci			const deUint32 colorA	= 0xff000000 | rgb;
612e5c31af7Sopenharmony_ci			const deUint32 colorB	= 0xff000000 | ~rgb;
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci			m_textures[1]->getRefTexture().allocLevel(levelNdx);
615e5c31af7Sopenharmony_ci			tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
616e5c31af7Sopenharmony_ci		}
617e5c31af7Sopenharmony_ci
618e5c31af7Sopenharmony_ci		// Upload.
619e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
620e5c31af7Sopenharmony_ci			m_textures[i]->upload();
621e5c31af7Sopenharmony_ci	}
622e5c31af7Sopenharmony_ci	catch (const std::exception&)
623e5c31af7Sopenharmony_ci	{
624e5c31af7Sopenharmony_ci		// Clean up to save memory.
625e5c31af7Sopenharmony_ci		Vertex2DTextureCase::deinit();
626e5c31af7Sopenharmony_ci		throw;
627e5c31af7Sopenharmony_ci	}
628e5c31af7Sopenharmony_ci}
629e5c31af7Sopenharmony_ci
630e5c31af7Sopenharmony_civoid Vertex2DTextureCase::deinit (void)
631e5c31af7Sopenharmony_ci{
632e5c31af7Sopenharmony_ci	for (int i = 0; i < 2; i++)
633e5c31af7Sopenharmony_ci	{
634e5c31af7Sopenharmony_ci		delete m_textures[i];
635e5c31af7Sopenharmony_ci		m_textures[i] = DE_NULL;
636e5c31af7Sopenharmony_ci	}
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_ci	delete m_program;
639e5c31af7Sopenharmony_ci	m_program = DE_NULL;
640e5c31af7Sopenharmony_ci}
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_cifloat Vertex2DTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
643e5c31af7Sopenharmony_ci{
644e5c31af7Sopenharmony_ci	const tcu::Texture2D&		refTexture	= m_textures[textureNdx]->getRefTexture();
645e5c31af7Sopenharmony_ci	const Vec2					srcSize		= Vec2((float)refTexture.getWidth(), (float)refTexture.getHeight());
646e5c31af7Sopenharmony_ci	const Vec2					sizeRatio	= texScale*srcSize / dstSize;
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci	// \note In this particular case dv/dx and du/dy are zero, simplifying the expression.
649e5c31af7Sopenharmony_ci	return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
650e5c31af7Sopenharmony_ci}
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ciVertex2DTextureCase::IterateResult Vertex2DTextureCase::iterate (void)
653e5c31af7Sopenharmony_ci{
654e5c31af7Sopenharmony_ci	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_RENDER_WIDTH);
655e5c31af7Sopenharmony_ci	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_RENDER_HEIGHT);
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_ci	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
658e5c31af7Sopenharmony_ci	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
659e5c31af7Sopenharmony_ci
660e5c31af7Sopenharmony_ci	de::Random	rnd					(deStringHash(getName()));
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ci	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
663e5c31af7Sopenharmony_ci	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci	glUseProgram(m_program->getProgram());
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci	// Divide viewport into 4 cells.
668e5c31af7Sopenharmony_ci	const int leftWidth		= viewportWidth / 2;
669e5c31af7Sopenharmony_ci	const int rightWidth	= viewportWidth - leftWidth;
670e5c31af7Sopenharmony_ci	const int bottomHeight	= viewportHeight / 2;
671e5c31af7Sopenharmony_ci	const int topHeight		= viewportHeight - bottomHeight;
672e5c31af7Sopenharmony_ci
673e5c31af7Sopenharmony_ci	// Clear.
674e5c31af7Sopenharmony_ci	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
675e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT);
676e5c31af7Sopenharmony_ci
677e5c31af7Sopenharmony_ci	// Texture scaling and offsetting vectors.
678e5c31af7Sopenharmony_ci	const Vec2 texMinScale		(+1.8f, +1.8f);
679e5c31af7Sopenharmony_ci	const Vec2 texMinOffset		(-0.3f, -0.2f);
680e5c31af7Sopenharmony_ci	const Vec2 texMagScale		(+0.3f, +0.3f);
681e5c31af7Sopenharmony_ci	const Vec2 texMagOffset		(+0.9f, +0.8f);
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ci	// Surface for the reference image.
684e5c31af7Sopenharmony_ci	tcu::Surface refImage(viewportWidth, viewportHeight);
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci	{
687e5c31af7Sopenharmony_ci		const struct Render
688e5c31af7Sopenharmony_ci		{
689e5c31af7Sopenharmony_ci			const Rect	region;
690e5c31af7Sopenharmony_ci			int			textureNdx;
691e5c31af7Sopenharmony_ci			const Vec2	texCoordScale;
692e5c31af7Sopenharmony_ci			const Vec2	texCoordOffset;
693e5c31af7Sopenharmony_ci			Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
694e5c31af7Sopenharmony_ci		} renders[] =
695e5c31af7Sopenharmony_ci		{
696e5c31af7Sopenharmony_ci			Render(Rect(0,				0,				leftWidth,	bottomHeight),	0, texMinScale, texMinOffset),
697e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		0,				rightWidth,	bottomHeight),	0, texMagScale, texMagOffset),
698e5c31af7Sopenharmony_ci			Render(Rect(0,				bottomHeight,	leftWidth,	topHeight),		1, texMinScale, texMinOffset),
699e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		bottomHeight,	rightWidth,	topHeight),		1, texMagScale, texMagOffset)
700e5c31af7Sopenharmony_ci		};
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
703e5c31af7Sopenharmony_ci		{
704e5c31af7Sopenharmony_ci			const Render&	rend				= renders[renderNdx];
705e5c31af7Sopenharmony_ci			const float		lod					= calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
706e5c31af7Sopenharmony_ci			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
707e5c31af7Sopenharmony_ci			const Grid		grid				(GRID_SIZE_2D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
708e5c31af7Sopenharmony_ci												 TexTypeCoordParams<TEXTURETYPE_2D>(rend.texCoordScale, rend.texCoordOffset), useSafeTexCoords);
709e5c31af7Sopenharmony_ci
710e5c31af7Sopenharmony_ci			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
711e5c31af7Sopenharmony_ci			renderCell				(rend.textureNdx, lod, grid);
712e5c31af7Sopenharmony_ci			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
713e5c31af7Sopenharmony_ci		}
714e5c31af7Sopenharmony_ci	}
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ci	// Read back rendered results.
717e5c31af7Sopenharmony_ci	tcu::Surface resImage(viewportWidth, viewportHeight);
718e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
719e5c31af7Sopenharmony_ci
720e5c31af7Sopenharmony_ci	glUseProgram(0);
721e5c31af7Sopenharmony_ci
722e5c31af7Sopenharmony_ci	// Compare and log.
723e5c31af7Sopenharmony_ci	{
724e5c31af7Sopenharmony_ci		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
725e5c31af7Sopenharmony_ci
726e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
727e5c31af7Sopenharmony_ci								isOk ? "Pass"				: "Image comparison failed");
728e5c31af7Sopenharmony_ci	}
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci	return STOP;
731e5c31af7Sopenharmony_ci}
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_civoid Vertex2DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
734e5c31af7Sopenharmony_ci{
735e5c31af7Sopenharmony_ci	const deUint32 programID = m_program->getProgram();
736e5c31af7Sopenharmony_ci
737e5c31af7Sopenharmony_ci	// SETUP ATTRIBUTES.
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ci	{
740e5c31af7Sopenharmony_ci		const int positionLoc = glGetAttribLocation(programID, "a_position");
741e5c31af7Sopenharmony_ci		if (positionLoc != -1)
742e5c31af7Sopenharmony_ci		{
743e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(positionLoc);
744e5c31af7Sopenharmony_ci			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
745e5c31af7Sopenharmony_ci		}
746e5c31af7Sopenharmony_ci	}
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci	{
749e5c31af7Sopenharmony_ci		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
750e5c31af7Sopenharmony_ci		if (texCoordLoc != -1)
751e5c31af7Sopenharmony_ci		{
752e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(texCoordLoc);
753e5c31af7Sopenharmony_ci			glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
754e5c31af7Sopenharmony_ci		}
755e5c31af7Sopenharmony_ci	}
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	// SETUP UNIFORMS.
758e5c31af7Sopenharmony_ci
759e5c31af7Sopenharmony_ci	{
760e5c31af7Sopenharmony_ci		const int lodLoc = glGetUniformLocation(programID, "u_lod");
761e5c31af7Sopenharmony_ci		if (lodLoc != -1)
762e5c31af7Sopenharmony_ci			glUniform1f(lodLoc, lod);
763e5c31af7Sopenharmony_ci	}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	glActiveTexture(GL_TEXTURE0);
766e5c31af7Sopenharmony_ci	glBindTexture(GL_TEXTURE_2D, m_textures[textureNdx]->getGLTexture());
767e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
768e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
769e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
770e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_ci	{
773e5c31af7Sopenharmony_ci		const int texLoc = glGetUniformLocation(programID, "u_texture");
774e5c31af7Sopenharmony_ci		if (texLoc != -1)
775e5c31af7Sopenharmony_ci			glUniform1i(texLoc, 0);
776e5c31af7Sopenharmony_ci	}
777e5c31af7Sopenharmony_ci}
778e5c31af7Sopenharmony_ci
779e5c31af7Sopenharmony_ci// Renders one sub-image with given parameters.
780e5c31af7Sopenharmony_civoid Vertex2DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
781e5c31af7Sopenharmony_ci{
782e5c31af7Sopenharmony_ci	setupShaderInputs(textureNdx, lod, grid);
783e5c31af7Sopenharmony_ci	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
784e5c31af7Sopenharmony_ci}
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_civoid Vertex2DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
787e5c31af7Sopenharmony_ci{
788e5c31af7Sopenharmony_ci	computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
789e5c31af7Sopenharmony_ci}
790e5c31af7Sopenharmony_ci
791e5c31af7Sopenharmony_ciclass VertexCubeTextureCase : public TestCase
792e5c31af7Sopenharmony_ci{
793e5c31af7Sopenharmony_cipublic:
794e5c31af7Sopenharmony_ci								VertexCubeTextureCase	(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
795e5c31af7Sopenharmony_ci								~VertexCubeTextureCase	(void);
796e5c31af7Sopenharmony_ci
797e5c31af7Sopenharmony_ci	void						init					(void);
798e5c31af7Sopenharmony_ci	void						deinit					(void);
799e5c31af7Sopenharmony_ci	IterateResult				iterate					(void);
800e5c31af7Sopenharmony_ci
801e5c31af7Sopenharmony_ciprivate:
802e5c31af7Sopenharmony_ci	typedef PosTexCoordQuadGrid<TEXTURETYPE_CUBE> Grid;
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_ci								VertexCubeTextureCase	(const VertexCubeTextureCase& other);
805e5c31af7Sopenharmony_ci	VertexCubeTextureCase&		operator=				(const VertexCubeTextureCase& other);
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci	float						calculateLod			(const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
808e5c31af7Sopenharmony_ci	void						setupShaderInputs		(int textureNdx, float lod, const Grid& grid) const;
809e5c31af7Sopenharmony_ci	void						renderCell				(int textureNdx, float lod, const Grid& grid) const;
810e5c31af7Sopenharmony_ci	void						computeReferenceCell	(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
811e5c31af7Sopenharmony_ci
812e5c31af7Sopenharmony_ci	const deUint32				m_minFilter;
813e5c31af7Sopenharmony_ci	const deUint32				m_magFilter;
814e5c31af7Sopenharmony_ci	const deUint32				m_wrapS;
815e5c31af7Sopenharmony_ci	const deUint32				m_wrapT;
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci	const glu::ShaderProgram*	m_program;
818e5c31af7Sopenharmony_ci	glu::TextureCube*			m_textures[2];	// 2 textures, a gradient texture and a grid texture.
819e5c31af7Sopenharmony_ci};
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ciVertexCubeTextureCase::VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
822e5c31af7Sopenharmony_ci	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
823e5c31af7Sopenharmony_ci	, m_minFilter			(minFilter)
824e5c31af7Sopenharmony_ci	, m_magFilter			(magFilter)
825e5c31af7Sopenharmony_ci	, m_wrapS				(wrapS)
826e5c31af7Sopenharmony_ci	, m_wrapT				(wrapT)
827e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
828e5c31af7Sopenharmony_ci{
829e5c31af7Sopenharmony_ci	m_textures[0] = DE_NULL;
830e5c31af7Sopenharmony_ci	m_textures[1] = DE_NULL;
831e5c31af7Sopenharmony_ci}
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_ciVertexCubeTextureCase::~VertexCubeTextureCase(void)
834e5c31af7Sopenharmony_ci{
835e5c31af7Sopenharmony_ci	VertexCubeTextureCase::deinit();
836e5c31af7Sopenharmony_ci}
837e5c31af7Sopenharmony_ci
838e5c31af7Sopenharmony_civoid VertexCubeTextureCase::init (void)
839e5c31af7Sopenharmony_ci{
840e5c31af7Sopenharmony_ci	const char* const vertexShader =
841e5c31af7Sopenharmony_ci		"#version 300 es\n"
842e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
843e5c31af7Sopenharmony_ci		"in highp vec3 a_texCoord;\n"
844e5c31af7Sopenharmony_ci		"uniform highp samplerCube u_texture;\n"
845e5c31af7Sopenharmony_ci		"uniform highp float u_lod;\n"
846e5c31af7Sopenharmony_ci		"out mediump vec4 v_color;\n"
847e5c31af7Sopenharmony_ci		"\n"
848e5c31af7Sopenharmony_ci		"void main()\n"
849e5c31af7Sopenharmony_ci		"{\n"
850e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
851e5c31af7Sopenharmony_ci		"	v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
852e5c31af7Sopenharmony_ci		"}\n";
853e5c31af7Sopenharmony_ci
854e5c31af7Sopenharmony_ci	const char* const fragmentShader =
855e5c31af7Sopenharmony_ci		"#version 300 es\n"
856e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
857e5c31af7Sopenharmony_ci		"in mediump vec4 v_color;\n"
858e5c31af7Sopenharmony_ci		"\n"
859e5c31af7Sopenharmony_ci		"void main()\n"
860e5c31af7Sopenharmony_ci		"{\n"
861e5c31af7Sopenharmony_ci		"	dEQP_FragColor = v_color;\n"
862e5c31af7Sopenharmony_ci		"}\n";
863e5c31af7Sopenharmony_ci
864e5c31af7Sopenharmony_ci	if (m_context.getRenderTarget().getNumSamples() != 0)
865e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("MSAA config not supported by this test");
866e5c31af7Sopenharmony_ci
867e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
868e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
869e5c31af7Sopenharmony_ci
870e5c31af7Sopenharmony_ci	if(!m_program->isOk())
871e5c31af7Sopenharmony_ci	{
872e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
873e5c31af7Sopenharmony_ci
874e5c31af7Sopenharmony_ci		GLint maxVertexTextures;
875e5c31af7Sopenharmony_ci		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci		if (maxVertexTextures < 1)
878e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
879e5c31af7Sopenharmony_ci		else
880e5c31af7Sopenharmony_ci			TCU_FAIL("Failed to compile shader");
881e5c31af7Sopenharmony_ci	}
882e5c31af7Sopenharmony_ci
883e5c31af7Sopenharmony_ci	// Make the textures.
884e5c31af7Sopenharmony_ci	try
885e5c31af7Sopenharmony_ci	{
886e5c31af7Sopenharmony_ci		// Compute suitable power-of-two sizes (for mipmaps).
887e5c31af7Sopenharmony_ci		const int texWidth		= 1 << deLog2Ceil32(MAX_CUBE_RENDER_WIDTH / 3 / 2);
888e5c31af7Sopenharmony_ci		const int texHeight		= 1 << deLog2Ceil32(MAX_CUBE_RENDER_HEIGHT / 2 / 2);
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_ci		DE_ASSERT(texWidth == texHeight);
891e5c31af7Sopenharmony_ci		DE_UNREF(texHeight);
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
894e5c31af7Sopenharmony_ci		{
895e5c31af7Sopenharmony_ci			DE_ASSERT(!m_textures[i]);
896e5c31af7Sopenharmony_ci			m_textures[i] = new glu::TextureCube(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth);
897e5c31af7Sopenharmony_ci		}
898e5c31af7Sopenharmony_ci
899e5c31af7Sopenharmony_ci		const bool						mipmaps		= deIsPowerOfTwo32(texWidth) != DE_FALSE;
900e5c31af7Sopenharmony_ci		const int						numLevels	= mipmaps ? deLog2Floor32(texWidth)+1 : 1;
901e5c31af7Sopenharmony_ci		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
902e5c31af7Sopenharmony_ci		const Vec4						cBias		= fmtInfo.valueMin;
903e5c31af7Sopenharmony_ci		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
904e5c31af7Sopenharmony_ci
905e5c31af7Sopenharmony_ci		// Fill first with gradient texture.
906e5c31af7Sopenharmony_ci		static const Vec4 gradients[tcu::CUBEFACE_LAST][2] =
907e5c31af7Sopenharmony_ci		{
908e5c31af7Sopenharmony_ci			{ Vec4(-1.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
909e5c31af7Sopenharmony_ci			{ Vec4( 0.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
910e5c31af7Sopenharmony_ci			{ Vec4(-1.0f,  0.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
911e5c31af7Sopenharmony_ci			{ Vec4(-1.0f, -1.0f,  0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
912e5c31af7Sopenharmony_ci			{ Vec4(-1.0f, -1.0f, -1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
913e5c31af7Sopenharmony_ci			{ Vec4( 0.0f,  0.0f,  0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
914e5c31af7Sopenharmony_ci		};
915e5c31af7Sopenharmony_ci		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
916e5c31af7Sopenharmony_ci		{
917e5c31af7Sopenharmony_ci			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
918e5c31af7Sopenharmony_ci			{
919e5c31af7Sopenharmony_ci				m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
920e5c31af7Sopenharmony_ci				tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
921e5c31af7Sopenharmony_ci			}
922e5c31af7Sopenharmony_ci		}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci		// Fill second with grid texture.
925e5c31af7Sopenharmony_ci		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
926e5c31af7Sopenharmony_ci		{
927e5c31af7Sopenharmony_ci			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
928e5c31af7Sopenharmony_ci			{
929e5c31af7Sopenharmony_ci				const deUint32 step		= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
930e5c31af7Sopenharmony_ci				const deUint32 rgb		= step*levelNdx*face;
931e5c31af7Sopenharmony_ci				const deUint32 colorA	= 0xff000000 | rgb;
932e5c31af7Sopenharmony_ci				const deUint32 colorB	= 0xff000000 | ~rgb;
933e5c31af7Sopenharmony_ci
934e5c31af7Sopenharmony_ci				m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
935e5c31af7Sopenharmony_ci				tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
936e5c31af7Sopenharmony_ci			}
937e5c31af7Sopenharmony_ci		}
938e5c31af7Sopenharmony_ci
939e5c31af7Sopenharmony_ci		// Upload.
940e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
941e5c31af7Sopenharmony_ci			m_textures[i]->upload();
942e5c31af7Sopenharmony_ci	}
943e5c31af7Sopenharmony_ci	catch (const std::exception&)
944e5c31af7Sopenharmony_ci	{
945e5c31af7Sopenharmony_ci		// Clean up to save memory.
946e5c31af7Sopenharmony_ci		VertexCubeTextureCase::deinit();
947e5c31af7Sopenharmony_ci		throw;
948e5c31af7Sopenharmony_ci	}
949e5c31af7Sopenharmony_ci}
950e5c31af7Sopenharmony_ci
951e5c31af7Sopenharmony_civoid VertexCubeTextureCase::deinit (void)
952e5c31af7Sopenharmony_ci{
953e5c31af7Sopenharmony_ci	for (int i = 0; i < 2; i++)
954e5c31af7Sopenharmony_ci	{
955e5c31af7Sopenharmony_ci		delete m_textures[i];
956e5c31af7Sopenharmony_ci		m_textures[i] = DE_NULL;
957e5c31af7Sopenharmony_ci	}
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_ci	delete m_program;
960e5c31af7Sopenharmony_ci	m_program = DE_NULL;
961e5c31af7Sopenharmony_ci}
962e5c31af7Sopenharmony_ci
963e5c31af7Sopenharmony_cifloat VertexCubeTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
964e5c31af7Sopenharmony_ci{
965e5c31af7Sopenharmony_ci	const tcu::TextureCube&		refTexture	= m_textures[textureNdx]->getRefTexture();
966e5c31af7Sopenharmony_ci	const Vec2					srcSize		= Vec2((float)refTexture.getSize(), (float)refTexture.getSize());
967e5c31af7Sopenharmony_ci	const Vec2					sizeRatio	= texScale*srcSize / dstSize;
968e5c31af7Sopenharmony_ci
969e5c31af7Sopenharmony_ci	// \note In this particular case, dv/dx and du/dy are zero, simplifying the expression.
970e5c31af7Sopenharmony_ci	return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
971e5c31af7Sopenharmony_ci}
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_ciVertexCubeTextureCase::IterateResult VertexCubeTextureCase::iterate (void)
974e5c31af7Sopenharmony_ci{
975e5c31af7Sopenharmony_ci	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_CUBE_RENDER_WIDTH);
976e5c31af7Sopenharmony_ci	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_CUBE_RENDER_HEIGHT);
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ci	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
979e5c31af7Sopenharmony_ci	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
980e5c31af7Sopenharmony_ci
981e5c31af7Sopenharmony_ci	de::Random	rnd					(deStringHash(getName()));
982e5c31af7Sopenharmony_ci
983e5c31af7Sopenharmony_ci	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
984e5c31af7Sopenharmony_ci	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
985e5c31af7Sopenharmony_ci
986e5c31af7Sopenharmony_ci	glUseProgram(m_program->getProgram());
987e5c31af7Sopenharmony_ci
988e5c31af7Sopenharmony_ci	// Divide viewport into 4 areas.
989e5c31af7Sopenharmony_ci	const int leftWidth		= viewportWidth / 2;
990e5c31af7Sopenharmony_ci	const int rightWidth	= viewportWidth - leftWidth;
991e5c31af7Sopenharmony_ci	const int bottomHeight	= viewportHeight / 2;
992e5c31af7Sopenharmony_ci	const int topHeight		= viewportHeight - bottomHeight;
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ci	// Clear.
995e5c31af7Sopenharmony_ci	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
996e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT);
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ci	// Texture scaling and offsetting vectors.
999e5c31af7Sopenharmony_ci	const Vec2 texMinScale		(1.0f, 1.0f);
1000e5c31af7Sopenharmony_ci	const Vec2 texMinOffset		(0.0f, 0.0f);
1001e5c31af7Sopenharmony_ci	const Vec2 texMagScale		(0.3f, 0.3f);
1002e5c31af7Sopenharmony_ci	const Vec2 texMagOffset		(0.5f, 0.3f);
1003e5c31af7Sopenharmony_ci
1004e5c31af7Sopenharmony_ci	// Surface for the reference image.
1005e5c31af7Sopenharmony_ci	tcu::Surface refImage(viewportWidth, viewportHeight);
1006e5c31af7Sopenharmony_ci
1007e5c31af7Sopenharmony_ci	// Each of the four areas is divided into 6 cells.
1008e5c31af7Sopenharmony_ci	const int defCellWidth	= viewportWidth / 2 / 3;
1009e5c31af7Sopenharmony_ci	const int defCellHeight	= viewportHeight / 2 / 2;
1010e5c31af7Sopenharmony_ci
1011e5c31af7Sopenharmony_ci	for (int i = 0; i < tcu::CUBEFACE_LAST; i++)
1012e5c31af7Sopenharmony_ci	{
1013e5c31af7Sopenharmony_ci		const int	cellOffsetX			= defCellWidth * (i % 3);
1014e5c31af7Sopenharmony_ci		const int	cellOffsetY			= defCellHeight * (i / 3);
1015e5c31af7Sopenharmony_ci		const bool	isRightmostCell		= i == 2 || i == 5;
1016e5c31af7Sopenharmony_ci		const bool	isTopCell			= i >= 3;
1017e5c31af7Sopenharmony_ci		const int	leftCellWidth		= isRightmostCell	? leftWidth		- cellOffsetX : defCellWidth;
1018e5c31af7Sopenharmony_ci		const int	rightCellWidth		= isRightmostCell	? rightWidth	- cellOffsetX : defCellWidth;
1019e5c31af7Sopenharmony_ci		const int	bottomCellHeight	= isTopCell			? bottomHeight	- cellOffsetY : defCellHeight;
1020e5c31af7Sopenharmony_ci		const int	topCellHeight		= isTopCell			? topHeight		- cellOffsetY : defCellHeight;
1021e5c31af7Sopenharmony_ci
1022e5c31af7Sopenharmony_ci		const struct Render
1023e5c31af7Sopenharmony_ci		{
1024e5c31af7Sopenharmony_ci			const Rect	region;
1025e5c31af7Sopenharmony_ci			int			textureNdx;
1026e5c31af7Sopenharmony_ci			const Vec2	texCoordScale;
1027e5c31af7Sopenharmony_ci			const Vec2	texCoordOffset;
1028e5c31af7Sopenharmony_ci			Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
1029e5c31af7Sopenharmony_ci		} renders[] =
1030e5c31af7Sopenharmony_ci		{
1031e5c31af7Sopenharmony_ci			Render(Rect(cellOffsetX + 0,			cellOffsetY + 0,				leftCellWidth,	bottomCellHeight),	0, texMinScale, texMinOffset),
1032e5c31af7Sopenharmony_ci			Render(Rect(cellOffsetX + leftWidth,	cellOffsetY + 0,				rightCellWidth,	bottomCellHeight),	0, texMagScale, texMagOffset),
1033e5c31af7Sopenharmony_ci			Render(Rect(cellOffsetX + 0,			cellOffsetY + bottomHeight,		leftCellWidth,	topCellHeight),		1, texMinScale, texMinOffset),
1034e5c31af7Sopenharmony_ci			Render(Rect(cellOffsetX + leftWidth,	cellOffsetY + bottomHeight,		rightCellWidth,	topCellHeight),		1, texMagScale, texMagOffset)
1035e5c31af7Sopenharmony_ci		};
1036e5c31af7Sopenharmony_ci
1037e5c31af7Sopenharmony_ci		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1038e5c31af7Sopenharmony_ci		{
1039e5c31af7Sopenharmony_ci			const Render&	rend				= renders[renderNdx];
1040e5c31af7Sopenharmony_ci			const float		lod					= calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
1041e5c31af7Sopenharmony_ci			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1042e5c31af7Sopenharmony_ci			const Grid		grid				(GRID_SIZE_CUBE, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1043e5c31af7Sopenharmony_ci												 TexTypeCoordParams<TEXTURETYPE_CUBE>(rend.texCoordScale, rend.texCoordOffset, (tcu::CubeFace)i), useSafeTexCoords);
1044e5c31af7Sopenharmony_ci
1045e5c31af7Sopenharmony_ci			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1046e5c31af7Sopenharmony_ci			renderCell				(rend.textureNdx, lod, grid);
1047e5c31af7Sopenharmony_ci			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
1048e5c31af7Sopenharmony_ci		}
1049e5c31af7Sopenharmony_ci	}
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci	// Read back rendered results.
1052e5c31af7Sopenharmony_ci	tcu::Surface resImage(viewportWidth, viewportHeight);
1053e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_ci	glUseProgram(0);
1056e5c31af7Sopenharmony_ci
1057e5c31af7Sopenharmony_ci	// Compare and log.
1058e5c31af7Sopenharmony_ci	{
1059e5c31af7Sopenharmony_ci		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1060e5c31af7Sopenharmony_ci
1061e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
1062e5c31af7Sopenharmony_ci								isOk ? "Pass"				: "Image comparison failed");
1063e5c31af7Sopenharmony_ci	}
1064e5c31af7Sopenharmony_ci
1065e5c31af7Sopenharmony_ci	return STOP;
1066e5c31af7Sopenharmony_ci}
1067e5c31af7Sopenharmony_ci
1068e5c31af7Sopenharmony_civoid VertexCubeTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1069e5c31af7Sopenharmony_ci{
1070e5c31af7Sopenharmony_ci	const deUint32 programID = m_program->getProgram();
1071e5c31af7Sopenharmony_ci
1072e5c31af7Sopenharmony_ci	// SETUP ATTRIBUTES.
1073e5c31af7Sopenharmony_ci
1074e5c31af7Sopenharmony_ci	{
1075e5c31af7Sopenharmony_ci		const int positionLoc = glGetAttribLocation(programID, "a_position");
1076e5c31af7Sopenharmony_ci		if (positionLoc != -1)
1077e5c31af7Sopenharmony_ci		{
1078e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(positionLoc);
1079e5c31af7Sopenharmony_ci			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1080e5c31af7Sopenharmony_ci		}
1081e5c31af7Sopenharmony_ci	}
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_ci	{
1084e5c31af7Sopenharmony_ci		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1085e5c31af7Sopenharmony_ci		if (texCoordLoc != -1)
1086e5c31af7Sopenharmony_ci		{
1087e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(texCoordLoc);
1088e5c31af7Sopenharmony_ci			glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1089e5c31af7Sopenharmony_ci		}
1090e5c31af7Sopenharmony_ci	}
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_ci	// SETUP UNIFORMS.
1093e5c31af7Sopenharmony_ci
1094e5c31af7Sopenharmony_ci	{
1095e5c31af7Sopenharmony_ci		const int lodLoc = glGetUniformLocation(programID, "u_lod");
1096e5c31af7Sopenharmony_ci		if (lodLoc != -1)
1097e5c31af7Sopenharmony_ci			glUniform1f(lodLoc, lod);
1098e5c31af7Sopenharmony_ci	}
1099e5c31af7Sopenharmony_ci
1100e5c31af7Sopenharmony_ci	glActiveTexture(GL_TEXTURE0);
1101e5c31af7Sopenharmony_ci	glBindTexture(GL_TEXTURE_CUBE_MAP, m_textures[textureNdx]->getGLTexture());
1102e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		m_wrapS);
1103e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		m_wrapT);
1104e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	m_minFilter);
1105e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	m_magFilter);
1106e5c31af7Sopenharmony_ci
1107e5c31af7Sopenharmony_ci	{
1108e5c31af7Sopenharmony_ci		const int texLoc = glGetUniformLocation(programID, "u_texture");
1109e5c31af7Sopenharmony_ci		if (texLoc != -1)
1110e5c31af7Sopenharmony_ci			glUniform1i(texLoc, 0);
1111e5c31af7Sopenharmony_ci	}
1112e5c31af7Sopenharmony_ci}
1113e5c31af7Sopenharmony_ci
1114e5c31af7Sopenharmony_ci// Renders one cube face with given parameters.
1115e5c31af7Sopenharmony_civoid VertexCubeTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1116e5c31af7Sopenharmony_ci{
1117e5c31af7Sopenharmony_ci	setupShaderInputs(textureNdx, lod, grid);
1118e5c31af7Sopenharmony_ci	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1119e5c31af7Sopenharmony_ci}
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_ci// Computes reference for one cube face with given parameters.
1122e5c31af7Sopenharmony_civoid VertexCubeTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1123e5c31af7Sopenharmony_ci{
1124e5c31af7Sopenharmony_ci	tcu::Sampler sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
1125e5c31af7Sopenharmony_ci	sampler.seamlessCubeMap = true;
1126e5c31af7Sopenharmony_ci	computeReference(m_textures[textureNdx]->getRefTexture(), lod, sampler, grid, dst, dstRegion);
1127e5c31af7Sopenharmony_ci}
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ciclass Vertex2DArrayTextureCase : public TestCase
1130e5c31af7Sopenharmony_ci{
1131e5c31af7Sopenharmony_cipublic:
1132e5c31af7Sopenharmony_ci								Vertex2DArrayTextureCase	(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
1133e5c31af7Sopenharmony_ci								~Vertex2DArrayTextureCase	(void);
1134e5c31af7Sopenharmony_ci
1135e5c31af7Sopenharmony_ci	void						init						(void);
1136e5c31af7Sopenharmony_ci	void						deinit						(void);
1137e5c31af7Sopenharmony_ci	IterateResult				iterate						(void);
1138e5c31af7Sopenharmony_ci
1139e5c31af7Sopenharmony_ciprivate:
1140e5c31af7Sopenharmony_ci	typedef PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY> Grid;
1141e5c31af7Sopenharmony_ci
1142e5c31af7Sopenharmony_ci								Vertex2DArrayTextureCase	(const Vertex2DArrayTextureCase& other);
1143e5c31af7Sopenharmony_ci	Vertex2DArrayTextureCase&	operator=					(const Vertex2DArrayTextureCase& other);
1144e5c31af7Sopenharmony_ci
1145e5c31af7Sopenharmony_ci	float						calculateLod				(const Mat3& transf, const Vec2& dstSize, int textureNdx) const;
1146e5c31af7Sopenharmony_ci	void						setupShaderInputs			(int textureNdx, float lod, const Grid& grid) const;
1147e5c31af7Sopenharmony_ci	void						renderCell					(int textureNdx, float lod, const Grid& grid) const;
1148e5c31af7Sopenharmony_ci	void						computeReferenceCell		(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
1149e5c31af7Sopenharmony_ci
1150e5c31af7Sopenharmony_ci	const deUint32				m_minFilter;
1151e5c31af7Sopenharmony_ci	const deUint32				m_magFilter;
1152e5c31af7Sopenharmony_ci	const deUint32				m_wrapS;
1153e5c31af7Sopenharmony_ci	const deUint32				m_wrapT;
1154e5c31af7Sopenharmony_ci
1155e5c31af7Sopenharmony_ci	const glu::ShaderProgram*	m_program;
1156e5c31af7Sopenharmony_ci	glu::Texture2DArray*		m_textures[2];	// 2 textures, a gradient texture and a grid texture.
1157e5c31af7Sopenharmony_ci};
1158e5c31af7Sopenharmony_ci
1159e5c31af7Sopenharmony_ciVertex2DArrayTextureCase::Vertex2DArrayTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
1160e5c31af7Sopenharmony_ci	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
1161e5c31af7Sopenharmony_ci	, m_minFilter			(minFilter)
1162e5c31af7Sopenharmony_ci	, m_magFilter			(magFilter)
1163e5c31af7Sopenharmony_ci	, m_wrapS				(wrapS)
1164e5c31af7Sopenharmony_ci	, m_wrapT				(wrapT)
1165e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
1166e5c31af7Sopenharmony_ci{
1167e5c31af7Sopenharmony_ci	m_textures[0] = DE_NULL;
1168e5c31af7Sopenharmony_ci	m_textures[1] = DE_NULL;
1169e5c31af7Sopenharmony_ci}
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ciVertex2DArrayTextureCase::~Vertex2DArrayTextureCase(void)
1172e5c31af7Sopenharmony_ci{
1173e5c31af7Sopenharmony_ci	Vertex2DArrayTextureCase::deinit();
1174e5c31af7Sopenharmony_ci}
1175e5c31af7Sopenharmony_ci
1176e5c31af7Sopenharmony_civoid Vertex2DArrayTextureCase::init (void)
1177e5c31af7Sopenharmony_ci{
1178e5c31af7Sopenharmony_ci	const char* const vertexShaderSource =
1179e5c31af7Sopenharmony_ci		"#version 300 es\n"
1180e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
1181e5c31af7Sopenharmony_ci		"in highp vec3 a_texCoord;\n"
1182e5c31af7Sopenharmony_ci		"uniform highp sampler2DArray u_texture;\n"
1183e5c31af7Sopenharmony_ci		"uniform highp float u_lod;\n"
1184e5c31af7Sopenharmony_ci		"out mediump vec4 v_color;\n"
1185e5c31af7Sopenharmony_ci		"\n"
1186e5c31af7Sopenharmony_ci		"void main()\n"
1187e5c31af7Sopenharmony_ci		"{\n"
1188e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
1189e5c31af7Sopenharmony_ci		"	v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1190e5c31af7Sopenharmony_ci		"}\n";
1191e5c31af7Sopenharmony_ci
1192e5c31af7Sopenharmony_ci	const char* const fragmentShaderSource =
1193e5c31af7Sopenharmony_ci		"#version 300 es\n"
1194e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1195e5c31af7Sopenharmony_ci		"in mediump vec4 v_color;\n"
1196e5c31af7Sopenharmony_ci		"\n"
1197e5c31af7Sopenharmony_ci		"void main()\n"
1198e5c31af7Sopenharmony_ci		"{\n"
1199e5c31af7Sopenharmony_ci		"	dEQP_FragColor = v_color;\n"
1200e5c31af7Sopenharmony_ci		"}\n";
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ci	if (m_context.getRenderTarget().getNumSamples() != 0)
1203e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("MSAA config not supported by this test");
1204e5c31af7Sopenharmony_ci
1205e5c31af7Sopenharmony_ci	// Create shader.
1206e5c31af7Sopenharmony_ci
1207e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
1208e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1209e5c31af7Sopenharmony_ci
1210e5c31af7Sopenharmony_ci	if(!m_program->isOk())
1211e5c31af7Sopenharmony_ci	{
1212e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci		GLint maxVertexTextures;
1215e5c31af7Sopenharmony_ci		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_ci		if (maxVertexTextures < 1)
1218e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1219e5c31af7Sopenharmony_ci		else
1220e5c31af7Sopenharmony_ci			TCU_FAIL("Failed to compile shader");
1221e5c31af7Sopenharmony_ci	}
1222e5c31af7Sopenharmony_ci
1223e5c31af7Sopenharmony_ci	// Make the textures.
1224e5c31af7Sopenharmony_ci
1225e5c31af7Sopenharmony_ci	try
1226e5c31af7Sopenharmony_ci	{
1227e5c31af7Sopenharmony_ci		const int texWidth	= WIDTH_2D_ARRAY;
1228e5c31af7Sopenharmony_ci		const int texHeight	= HEIGHT_2D_ARRAY;
1229e5c31af7Sopenharmony_ci		const int texLayers	= LAYERS_2D_ARRAY;
1230e5c31af7Sopenharmony_ci
1231e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
1232e5c31af7Sopenharmony_ci		{
1233e5c31af7Sopenharmony_ci			DE_ASSERT(!m_textures[i]);
1234e5c31af7Sopenharmony_ci			m_textures[i] = new glu::Texture2DArray(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texLayers);
1235e5c31af7Sopenharmony_ci		}
1236e5c31af7Sopenharmony_ci
1237e5c31af7Sopenharmony_ci		const int						numLevels	= deLog2Floor32(de::max(texWidth, texHeight)) + 1;
1238e5c31af7Sopenharmony_ci		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
1239e5c31af7Sopenharmony_ci		const Vec4						cBias		= fmtInfo.valueMin;
1240e5c31af7Sopenharmony_ci		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
1241e5c31af7Sopenharmony_ci
1242e5c31af7Sopenharmony_ci		// Fill first with gradient texture.
1243e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1244e5c31af7Sopenharmony_ci		{
1245e5c31af7Sopenharmony_ci			const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1246e5c31af7Sopenharmony_ci			const Vec4 gMax = Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_ci			m_textures[0]->getRefTexture().allocLevel(levelNdx);
1249e5c31af7Sopenharmony_ci			tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1250e5c31af7Sopenharmony_ci		}
1251e5c31af7Sopenharmony_ci
1252e5c31af7Sopenharmony_ci		// Fill second with grid texture.
1253e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1254e5c31af7Sopenharmony_ci		{
1255e5c31af7Sopenharmony_ci			const deUint32 step		= 0x00ffffff / numLevels;
1256e5c31af7Sopenharmony_ci			const deUint32 rgb		= step*levelNdx;
1257e5c31af7Sopenharmony_ci			const deUint32 colorA	= 0xff000000 | rgb;
1258e5c31af7Sopenharmony_ci			const deUint32 colorB	= 0xff000000 | ~rgb;
1259e5c31af7Sopenharmony_ci
1260e5c31af7Sopenharmony_ci			m_textures[1]->getRefTexture().allocLevel(levelNdx);
1261e5c31af7Sopenharmony_ci			tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1262e5c31af7Sopenharmony_ci		}
1263e5c31af7Sopenharmony_ci
1264e5c31af7Sopenharmony_ci		// Upload.
1265e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
1266e5c31af7Sopenharmony_ci			m_textures[i]->upload();
1267e5c31af7Sopenharmony_ci	}
1268e5c31af7Sopenharmony_ci	catch (const std::exception&)
1269e5c31af7Sopenharmony_ci	{
1270e5c31af7Sopenharmony_ci		// Clean up to save memory.
1271e5c31af7Sopenharmony_ci		Vertex2DArrayTextureCase::deinit();
1272e5c31af7Sopenharmony_ci		throw;
1273e5c31af7Sopenharmony_ci	}
1274e5c31af7Sopenharmony_ci}
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_civoid Vertex2DArrayTextureCase::deinit (void)
1277e5c31af7Sopenharmony_ci{
1278e5c31af7Sopenharmony_ci	for (int i = 0; i < 2; i++)
1279e5c31af7Sopenharmony_ci	{
1280e5c31af7Sopenharmony_ci		delete m_textures[i];
1281e5c31af7Sopenharmony_ci		m_textures[i] = DE_NULL;
1282e5c31af7Sopenharmony_ci	}
1283e5c31af7Sopenharmony_ci
1284e5c31af7Sopenharmony_ci	delete m_program;
1285e5c31af7Sopenharmony_ci	m_program = DE_NULL;
1286e5c31af7Sopenharmony_ci}
1287e5c31af7Sopenharmony_ci
1288e5c31af7Sopenharmony_cifloat Vertex2DArrayTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
1289e5c31af7Sopenharmony_ci{
1290e5c31af7Sopenharmony_ci	const tcu::Texture2DArray&	refTexture	= m_textures[textureNdx]->getRefTexture();
1291e5c31af7Sopenharmony_ci	const int					texWidth	= refTexture.getWidth();
1292e5c31af7Sopenharmony_ci	const int					texHeight	= refTexture.getHeight();
1293e5c31af7Sopenharmony_ci
1294e5c31af7Sopenharmony_ci	// Calculate transformed coordinates of three screen corners.
1295e5c31af7Sopenharmony_ci	const Vec2					trans00		= (transf * Vec3(0.0f, 0.0f, 1.0f)).xy();
1296e5c31af7Sopenharmony_ci	const Vec2					trans01		= (transf * Vec3(0.0f, 1.0f, 1.0f)).xy();
1297e5c31af7Sopenharmony_ci	const Vec2					trans10		= (transf * Vec3(1.0f, 0.0f, 1.0f)).xy();
1298e5c31af7Sopenharmony_ci
1299e5c31af7Sopenharmony_ci	// Derivates.
1300e5c31af7Sopenharmony_ci	const float dudx = (trans10.x() - trans00.x()) * (float)texWidth / dstSize.x();
1301e5c31af7Sopenharmony_ci	const float dudy = (trans01.x() - trans00.x()) * (float)texWidth / dstSize.y();
1302e5c31af7Sopenharmony_ci	const float dvdx = (trans10.y() - trans00.y()) * (float)texHeight / dstSize.x();
1303e5c31af7Sopenharmony_ci	const float dvdy = (trans01.y() - trans00.y()) * (float)texHeight / dstSize.y();
1304e5c31af7Sopenharmony_ci
1305e5c31af7Sopenharmony_ci	return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx, dudy*dudy + dvdy*dvdy)));
1306e5c31af7Sopenharmony_ci}
1307e5c31af7Sopenharmony_ci
1308e5c31af7Sopenharmony_ciVertex2DArrayTextureCase::IterateResult Vertex2DArrayTextureCase::iterate (void)
1309e5c31af7Sopenharmony_ci{
1310e5c31af7Sopenharmony_ci	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_ARRAY_RENDER_WIDTH);
1311e5c31af7Sopenharmony_ci	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_ARRAY_RENDER_HEIGHT);
1312e5c31af7Sopenharmony_ci
1313e5c31af7Sopenharmony_ci	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
1314e5c31af7Sopenharmony_ci	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
1315e5c31af7Sopenharmony_ci
1316e5c31af7Sopenharmony_ci	de::Random	rnd					(deStringHash(getName()));
1317e5c31af7Sopenharmony_ci
1318e5c31af7Sopenharmony_ci	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
1319e5c31af7Sopenharmony_ci	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci	glUseProgram(m_program->getProgram());
1322e5c31af7Sopenharmony_ci
1323e5c31af7Sopenharmony_ci	// Divide viewport into 4 cells.
1324e5c31af7Sopenharmony_ci	const int leftWidth		= viewportWidth / 2;
1325e5c31af7Sopenharmony_ci	const int rightWidth	= viewportWidth - leftWidth;
1326e5c31af7Sopenharmony_ci	const int bottomHeight	= viewportHeight / 2;
1327e5c31af7Sopenharmony_ci	const int topHeight		= viewportHeight - bottomHeight;
1328e5c31af7Sopenharmony_ci
1329e5c31af7Sopenharmony_ci	// Clear.
1330e5c31af7Sopenharmony_ci	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1331e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT);
1332e5c31af7Sopenharmony_ci
1333e5c31af7Sopenharmony_ci	// Shear by layer count to get all layers visible.
1334e5c31af7Sopenharmony_ci	static const float layerShearTransfData[] =
1335e5c31af7Sopenharmony_ci	{
1336e5c31af7Sopenharmony_ci		1.0f,					0.0f, 0.0f,
1337e5c31af7Sopenharmony_ci		0.0f,					1.0f, 0.0f,
1338e5c31af7Sopenharmony_ci		(float)LAYERS_2D_ARRAY, 0.0f, 0.0f
1339e5c31af7Sopenharmony_ci	};
1340e5c31af7Sopenharmony_ci
1341e5c31af7Sopenharmony_ci	// Minification and magnification transformations.
1342e5c31af7Sopenharmony_ci	static const float texMinTransfData[] =
1343e5c31af7Sopenharmony_ci	{
1344e5c31af7Sopenharmony_ci		2.1f,  0.0f, -0.3f,
1345e5c31af7Sopenharmony_ci		0.0f,  2.1f, -0.3f,
1346e5c31af7Sopenharmony_ci		0.0f,  0.0f,  1.0f
1347e5c31af7Sopenharmony_ci	};
1348e5c31af7Sopenharmony_ci	static const float texMagTransfData[] =
1349e5c31af7Sopenharmony_ci	{
1350e5c31af7Sopenharmony_ci		0.4f,  0.0f,  0.8f,
1351e5c31af7Sopenharmony_ci		0.0f,  0.4f,  0.8f,
1352e5c31af7Sopenharmony_ci		0.0f,  0.0f,  1.0f
1353e5c31af7Sopenharmony_ci	};
1354e5c31af7Sopenharmony_ci
1355e5c31af7Sopenharmony_ci	// Transformation matrices for minification and magnification.
1356e5c31af7Sopenharmony_ci	const Mat3 texMinTransf = Mat3(layerShearTransfData) * Mat3(texMinTransfData);
1357e5c31af7Sopenharmony_ci	const Mat3 texMagTransf = Mat3(layerShearTransfData) * Mat3(texMagTransfData);
1358e5c31af7Sopenharmony_ci
1359e5c31af7Sopenharmony_ci	// Surface for the reference image.
1360e5c31af7Sopenharmony_ci	tcu::Surface refImage(viewportWidth, viewportHeight);
1361e5c31af7Sopenharmony_ci
1362e5c31af7Sopenharmony_ci	{
1363e5c31af7Sopenharmony_ci		const struct Render
1364e5c31af7Sopenharmony_ci		{
1365e5c31af7Sopenharmony_ci			const Rect	region;
1366e5c31af7Sopenharmony_ci			int			textureNdx;
1367e5c31af7Sopenharmony_ci			const Mat3	texTransform;
1368e5c31af7Sopenharmony_ci			Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
1369e5c31af7Sopenharmony_ci		} renders[] =
1370e5c31af7Sopenharmony_ci		{
1371e5c31af7Sopenharmony_ci			Render(Rect(0,				0,				leftWidth,	bottomHeight),	0, texMinTransf),
1372e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		0,				rightWidth,	bottomHeight),	0, texMagTransf),
1373e5c31af7Sopenharmony_ci			Render(Rect(0,				bottomHeight,	leftWidth,	topHeight),		1, texMinTransf),
1374e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		bottomHeight,	rightWidth,	topHeight),		1, texMagTransf)
1375e5c31af7Sopenharmony_ci		};
1376e5c31af7Sopenharmony_ci
1377e5c31af7Sopenharmony_ci		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1378e5c31af7Sopenharmony_ci		{
1379e5c31af7Sopenharmony_ci			const Render&	rend				= renders[renderNdx];
1380e5c31af7Sopenharmony_ci			const float		lod					= calculateLod(rend.texTransform, rend.region.size().asFloat(), rend.textureNdx);
1381e5c31af7Sopenharmony_ci			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1382e5c31af7Sopenharmony_ci			const Grid		grid				(GRID_SIZE_2D_ARRAY, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1383e5c31af7Sopenharmony_ci												 TexTypeCoordParams<TEXTURETYPE_2D_ARRAY>(rend.texTransform), useSafeTexCoords);
1384e5c31af7Sopenharmony_ci
1385e5c31af7Sopenharmony_ci			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1386e5c31af7Sopenharmony_ci			renderCell				(rend.textureNdx, lod, grid);
1387e5c31af7Sopenharmony_ci			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
1388e5c31af7Sopenharmony_ci		}
1389e5c31af7Sopenharmony_ci	}
1390e5c31af7Sopenharmony_ci
1391e5c31af7Sopenharmony_ci	// Read back rendered results.
1392e5c31af7Sopenharmony_ci	tcu::Surface resImage(viewportWidth, viewportHeight);
1393e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1394e5c31af7Sopenharmony_ci
1395e5c31af7Sopenharmony_ci	glUseProgram(0);
1396e5c31af7Sopenharmony_ci
1397e5c31af7Sopenharmony_ci	// Compare and log.
1398e5c31af7Sopenharmony_ci	{
1399e5c31af7Sopenharmony_ci		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1400e5c31af7Sopenharmony_ci
1401e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
1402e5c31af7Sopenharmony_ci								isOk ? "Pass"				: "Image comparison failed");
1403e5c31af7Sopenharmony_ci	}
1404e5c31af7Sopenharmony_ci
1405e5c31af7Sopenharmony_ci	return STOP;
1406e5c31af7Sopenharmony_ci}
1407e5c31af7Sopenharmony_ci
1408e5c31af7Sopenharmony_civoid Vertex2DArrayTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1409e5c31af7Sopenharmony_ci{
1410e5c31af7Sopenharmony_ci	const deUint32 programID = m_program->getProgram();
1411e5c31af7Sopenharmony_ci
1412e5c31af7Sopenharmony_ci	// SETUP ATTRIBUTES.
1413e5c31af7Sopenharmony_ci
1414e5c31af7Sopenharmony_ci	{
1415e5c31af7Sopenharmony_ci		const int positionLoc = glGetAttribLocation(programID, "a_position");
1416e5c31af7Sopenharmony_ci		if (positionLoc != -1)
1417e5c31af7Sopenharmony_ci		{
1418e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(positionLoc);
1419e5c31af7Sopenharmony_ci			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1420e5c31af7Sopenharmony_ci		}
1421e5c31af7Sopenharmony_ci	}
1422e5c31af7Sopenharmony_ci
1423e5c31af7Sopenharmony_ci	{
1424e5c31af7Sopenharmony_ci		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1425e5c31af7Sopenharmony_ci		if (texCoordLoc != -1)
1426e5c31af7Sopenharmony_ci		{
1427e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(texCoordLoc);
1428e5c31af7Sopenharmony_ci			glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1429e5c31af7Sopenharmony_ci		}
1430e5c31af7Sopenharmony_ci	}
1431e5c31af7Sopenharmony_ci
1432e5c31af7Sopenharmony_ci	// SETUP UNIFORMS.
1433e5c31af7Sopenharmony_ci
1434e5c31af7Sopenharmony_ci	{
1435e5c31af7Sopenharmony_ci		const int lodLoc = glGetUniformLocation(programID, "u_lod");
1436e5c31af7Sopenharmony_ci		if (lodLoc != -1)
1437e5c31af7Sopenharmony_ci			glUniform1f(lodLoc, lod);
1438e5c31af7Sopenharmony_ci	}
1439e5c31af7Sopenharmony_ci
1440e5c31af7Sopenharmony_ci	glActiveTexture(GL_TEXTURE0);
1441e5c31af7Sopenharmony_ci	glBindTexture(GL_TEXTURE_2D_ARRAY, m_textures[textureNdx]->getGLTexture());
1442e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S,		m_wrapS);
1443e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T,		m_wrapT);
1444e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,	m_minFilter);
1445e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER,	m_magFilter);
1446e5c31af7Sopenharmony_ci
1447e5c31af7Sopenharmony_ci	{
1448e5c31af7Sopenharmony_ci		const int texLoc = glGetUniformLocation(programID, "u_texture");
1449e5c31af7Sopenharmony_ci		if (texLoc != -1)
1450e5c31af7Sopenharmony_ci			glUniform1i(texLoc, 0);
1451e5c31af7Sopenharmony_ci	}
1452e5c31af7Sopenharmony_ci}
1453e5c31af7Sopenharmony_ci
1454e5c31af7Sopenharmony_ci// Renders one sub-image with given parameters.
1455e5c31af7Sopenharmony_civoid Vertex2DArrayTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1456e5c31af7Sopenharmony_ci{
1457e5c31af7Sopenharmony_ci	setupShaderInputs(textureNdx, lod, grid);
1458e5c31af7Sopenharmony_ci	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1459e5c31af7Sopenharmony_ci}
1460e5c31af7Sopenharmony_ci
1461e5c31af7Sopenharmony_ci// Computes reference for one sub-image with given parameters.
1462e5c31af7Sopenharmony_civoid Vertex2DArrayTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1463e5c31af7Sopenharmony_ci{
1464e5c31af7Sopenharmony_ci	computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
1465e5c31af7Sopenharmony_ci}
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_ciclass Vertex3DTextureCase : public TestCase
1468e5c31af7Sopenharmony_ci{
1469e5c31af7Sopenharmony_cipublic:
1470e5c31af7Sopenharmony_ci								Vertex3DTextureCase		(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR);
1471e5c31af7Sopenharmony_ci								~Vertex3DTextureCase	(void);
1472e5c31af7Sopenharmony_ci
1473e5c31af7Sopenharmony_ci	void						init					(void);
1474e5c31af7Sopenharmony_ci	void						deinit					(void);
1475e5c31af7Sopenharmony_ci	IterateResult				iterate					(void);
1476e5c31af7Sopenharmony_ci
1477e5c31af7Sopenharmony_ciprivate:
1478e5c31af7Sopenharmony_ci	typedef PosTexCoordQuadGrid<TEXTURETYPE_3D> Grid;
1479e5c31af7Sopenharmony_ci
1480e5c31af7Sopenharmony_ci								Vertex3DTextureCase		(const Vertex3DTextureCase& other);
1481e5c31af7Sopenharmony_ci	Vertex3DTextureCase&		operator=				(const Vertex3DTextureCase& other);
1482e5c31af7Sopenharmony_ci
1483e5c31af7Sopenharmony_ci	float						calculateLod			(const Mat3& transf, const Vec2& dstSize, int textureNdx) const;
1484e5c31af7Sopenharmony_ci	void						setupShaderInputs		(int textureNdx, float lod, const Grid& grid) const;
1485e5c31af7Sopenharmony_ci	void						renderCell				(int textureNdx, float lod, const Grid& grid) const;
1486e5c31af7Sopenharmony_ci	void						computeReferenceCell	(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
1487e5c31af7Sopenharmony_ci
1488e5c31af7Sopenharmony_ci	const deUint32				m_minFilter;
1489e5c31af7Sopenharmony_ci	const deUint32				m_magFilter;
1490e5c31af7Sopenharmony_ci	const deUint32				m_wrapS;
1491e5c31af7Sopenharmony_ci	const deUint32				m_wrapT;
1492e5c31af7Sopenharmony_ci	const deUint32				m_wrapR;
1493e5c31af7Sopenharmony_ci
1494e5c31af7Sopenharmony_ci	const glu::ShaderProgram*	m_program;
1495e5c31af7Sopenharmony_ci	glu::Texture3D*				m_textures[2];	// 2 textures, a gradient texture and a grid texture.
1496e5c31af7Sopenharmony_ci};
1497e5c31af7Sopenharmony_ci
1498e5c31af7Sopenharmony_ciVertex3DTextureCase::Vertex3DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR)
1499e5c31af7Sopenharmony_ci	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
1500e5c31af7Sopenharmony_ci	, m_minFilter			(minFilter)
1501e5c31af7Sopenharmony_ci	, m_magFilter			(magFilter)
1502e5c31af7Sopenharmony_ci	, m_wrapS				(wrapS)
1503e5c31af7Sopenharmony_ci	, m_wrapT				(wrapT)
1504e5c31af7Sopenharmony_ci	, m_wrapR				(wrapR)
1505e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
1506e5c31af7Sopenharmony_ci{
1507e5c31af7Sopenharmony_ci	m_textures[0] = DE_NULL;
1508e5c31af7Sopenharmony_ci	m_textures[1] = DE_NULL;
1509e5c31af7Sopenharmony_ci}
1510e5c31af7Sopenharmony_ci
1511e5c31af7Sopenharmony_ciVertex3DTextureCase::~Vertex3DTextureCase(void)
1512e5c31af7Sopenharmony_ci{
1513e5c31af7Sopenharmony_ci	Vertex3DTextureCase::deinit();
1514e5c31af7Sopenharmony_ci}
1515e5c31af7Sopenharmony_ci
1516e5c31af7Sopenharmony_civoid Vertex3DTextureCase::init (void)
1517e5c31af7Sopenharmony_ci{
1518e5c31af7Sopenharmony_ci	const char* const vertexShaderSource =
1519e5c31af7Sopenharmony_ci		"#version 300 es\n"
1520e5c31af7Sopenharmony_ci		"in highp vec2 a_position;\n"
1521e5c31af7Sopenharmony_ci		"in highp vec3 a_texCoord;\n"
1522e5c31af7Sopenharmony_ci		"uniform highp sampler3D u_texture;\n"
1523e5c31af7Sopenharmony_ci		"uniform highp float u_lod;\n"
1524e5c31af7Sopenharmony_ci		"out mediump vec4 v_color;\n"
1525e5c31af7Sopenharmony_ci		"\n"
1526e5c31af7Sopenharmony_ci		"void main()\n"
1527e5c31af7Sopenharmony_ci		"{\n"
1528e5c31af7Sopenharmony_ci		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
1529e5c31af7Sopenharmony_ci		"	v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1530e5c31af7Sopenharmony_ci		"}\n";
1531e5c31af7Sopenharmony_ci
1532e5c31af7Sopenharmony_ci	const char* const fragmentShaderSource =
1533e5c31af7Sopenharmony_ci		"#version 300 es\n"
1534e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1535e5c31af7Sopenharmony_ci		"in mediump vec4 v_color;\n"
1536e5c31af7Sopenharmony_ci		"\n"
1537e5c31af7Sopenharmony_ci		"void main()\n"
1538e5c31af7Sopenharmony_ci		"{\n"
1539e5c31af7Sopenharmony_ci		"	dEQP_FragColor = v_color;\n"
1540e5c31af7Sopenharmony_ci		"}\n";
1541e5c31af7Sopenharmony_ci
1542e5c31af7Sopenharmony_ci	if (m_context.getRenderTarget().getNumSamples() != 0)
1543e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("MSAA config not supported by this test");
1544e5c31af7Sopenharmony_ci
1545e5c31af7Sopenharmony_ci	// Create shader.
1546e5c31af7Sopenharmony_ci
1547e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
1548e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1549e5c31af7Sopenharmony_ci
1550e5c31af7Sopenharmony_ci	if(!m_program->isOk())
1551e5c31af7Sopenharmony_ci	{
1552e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
1553e5c31af7Sopenharmony_ci
1554e5c31af7Sopenharmony_ci		GLint maxVertexTextures;
1555e5c31af7Sopenharmony_ci		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1556e5c31af7Sopenharmony_ci
1557e5c31af7Sopenharmony_ci		if (maxVertexTextures < 1)
1558e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1559e5c31af7Sopenharmony_ci		else
1560e5c31af7Sopenharmony_ci			TCU_FAIL("Failed to compile shader");
1561e5c31af7Sopenharmony_ci	}
1562e5c31af7Sopenharmony_ci
1563e5c31af7Sopenharmony_ci	// Make the textures.
1564e5c31af7Sopenharmony_ci
1565e5c31af7Sopenharmony_ci	try
1566e5c31af7Sopenharmony_ci	{
1567e5c31af7Sopenharmony_ci		const int texWidth	= WIDTH_3D;
1568e5c31af7Sopenharmony_ci		const int texHeight	= HEIGHT_3D;
1569e5c31af7Sopenharmony_ci		const int texDepth	= DEPTH_3D;
1570e5c31af7Sopenharmony_ci
1571e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
1572e5c31af7Sopenharmony_ci		{
1573e5c31af7Sopenharmony_ci			DE_ASSERT(!m_textures[i]);
1574e5c31af7Sopenharmony_ci			m_textures[i] = new glu::Texture3D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texDepth);
1575e5c31af7Sopenharmony_ci		}
1576e5c31af7Sopenharmony_ci
1577e5c31af7Sopenharmony_ci		const int						numLevels	= deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth)) + 1;
1578e5c31af7Sopenharmony_ci		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
1579e5c31af7Sopenharmony_ci		const Vec4						cBias		= fmtInfo.valueMin;
1580e5c31af7Sopenharmony_ci		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
1581e5c31af7Sopenharmony_ci
1582e5c31af7Sopenharmony_ci		// Fill first with gradient texture.
1583e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1584e5c31af7Sopenharmony_ci		{
1585e5c31af7Sopenharmony_ci			const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1586e5c31af7Sopenharmony_ci			const Vec4 gMax = Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_ci			m_textures[0]->getRefTexture().allocLevel(levelNdx);
1589e5c31af7Sopenharmony_ci			tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1590e5c31af7Sopenharmony_ci		}
1591e5c31af7Sopenharmony_ci
1592e5c31af7Sopenharmony_ci		// Fill second with grid texture.
1593e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1594e5c31af7Sopenharmony_ci		{
1595e5c31af7Sopenharmony_ci			const deUint32 step		= 0x00ffffff / numLevels;
1596e5c31af7Sopenharmony_ci			const deUint32 rgb		= step*levelNdx;
1597e5c31af7Sopenharmony_ci			const deUint32 colorA	= 0xff000000 | rgb;
1598e5c31af7Sopenharmony_ci			const deUint32 colorB	= 0xff000000 | ~rgb;
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci			m_textures[1]->getRefTexture().allocLevel(levelNdx);
1601e5c31af7Sopenharmony_ci			tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1602e5c31af7Sopenharmony_ci		}
1603e5c31af7Sopenharmony_ci
1604e5c31af7Sopenharmony_ci		// Upload.
1605e5c31af7Sopenharmony_ci		for (int i = 0; i < 2; i++)
1606e5c31af7Sopenharmony_ci			m_textures[i]->upload();
1607e5c31af7Sopenharmony_ci	}
1608e5c31af7Sopenharmony_ci	catch (const std::exception&)
1609e5c31af7Sopenharmony_ci	{
1610e5c31af7Sopenharmony_ci		// Clean up to save memory.
1611e5c31af7Sopenharmony_ci		Vertex3DTextureCase::deinit();
1612e5c31af7Sopenharmony_ci		throw;
1613e5c31af7Sopenharmony_ci	}
1614e5c31af7Sopenharmony_ci}
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_civoid Vertex3DTextureCase::deinit (void)
1617e5c31af7Sopenharmony_ci{
1618e5c31af7Sopenharmony_ci	for (int i = 0; i < 2; i++)
1619e5c31af7Sopenharmony_ci	{
1620e5c31af7Sopenharmony_ci		delete m_textures[i];
1621e5c31af7Sopenharmony_ci		m_textures[i] = DE_NULL;
1622e5c31af7Sopenharmony_ci	}
1623e5c31af7Sopenharmony_ci
1624e5c31af7Sopenharmony_ci	delete m_program;
1625e5c31af7Sopenharmony_ci	m_program = DE_NULL;
1626e5c31af7Sopenharmony_ci}
1627e5c31af7Sopenharmony_ci
1628e5c31af7Sopenharmony_cifloat Vertex3DTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
1629e5c31af7Sopenharmony_ci{
1630e5c31af7Sopenharmony_ci	const tcu::Texture3D&	refTexture	= m_textures[textureNdx]->getRefTexture();
1631e5c31af7Sopenharmony_ci	const int				srcWidth	= refTexture.getWidth();
1632e5c31af7Sopenharmony_ci	const int				srcHeight	= refTexture.getHeight();
1633e5c31af7Sopenharmony_ci	const int				srcDepth	= refTexture.getDepth();
1634e5c31af7Sopenharmony_ci
1635e5c31af7Sopenharmony_ci	// Calculate transformed coordinates of three screen corners.
1636e5c31af7Sopenharmony_ci	const Vec3				trans00		= transf * Vec3(0.0f, 0.0f, 1.0f);
1637e5c31af7Sopenharmony_ci	const Vec3				trans01		= transf * Vec3(0.0f, 1.0f, 1.0f);
1638e5c31af7Sopenharmony_ci	const Vec3				trans10		= transf * Vec3(1.0f, 0.0f, 1.0f);
1639e5c31af7Sopenharmony_ci
1640e5c31af7Sopenharmony_ci	// Derivates.
1641e5c31af7Sopenharmony_ci	const float dudx = (trans10.x() - trans00.x()) * (float)srcWidth / dstSize.x();
1642e5c31af7Sopenharmony_ci	const float dudy = (trans01.x() - trans00.x()) * (float)srcWidth / dstSize.y();
1643e5c31af7Sopenharmony_ci	const float dvdx = (trans10.y() - trans00.y()) * (float)srcHeight / dstSize.x();
1644e5c31af7Sopenharmony_ci	const float dvdy = (trans01.y() - trans00.y()) * (float)srcHeight / dstSize.y();
1645e5c31af7Sopenharmony_ci	const float dwdx = (trans10.z() - trans00.z()) * (float)srcDepth / dstSize.x();
1646e5c31af7Sopenharmony_ci	const float dwdy = (trans01.z() - trans00.z()) * (float)srcDepth / dstSize.y();
1647e5c31af7Sopenharmony_ci
1648e5c31af7Sopenharmony_ci	return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx + dwdx*dwdx, dudy*dudy + dvdy*dvdy + dwdy*dwdy)));
1649e5c31af7Sopenharmony_ci}
1650e5c31af7Sopenharmony_ci
1651e5c31af7Sopenharmony_ciVertex3DTextureCase::IterateResult Vertex3DTextureCase::iterate (void)
1652e5c31af7Sopenharmony_ci{
1653e5c31af7Sopenharmony_ci	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_3D_RENDER_WIDTH);
1654e5c31af7Sopenharmony_ci	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_3D_RENDER_HEIGHT);
1655e5c31af7Sopenharmony_ci
1656e5c31af7Sopenharmony_ci	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
1657e5c31af7Sopenharmony_ci	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
1658e5c31af7Sopenharmony_ci
1659e5c31af7Sopenharmony_ci	de::Random	rnd					(deStringHash(getName()));
1660e5c31af7Sopenharmony_ci
1661e5c31af7Sopenharmony_ci	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
1662e5c31af7Sopenharmony_ci	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
1663e5c31af7Sopenharmony_ci
1664e5c31af7Sopenharmony_ci	glUseProgram(m_program->getProgram());
1665e5c31af7Sopenharmony_ci
1666e5c31af7Sopenharmony_ci	// Divide viewport into 4 cells.
1667e5c31af7Sopenharmony_ci	const int leftWidth		= viewportWidth / 2;
1668e5c31af7Sopenharmony_ci	const int rightWidth		= viewportWidth - leftWidth;
1669e5c31af7Sopenharmony_ci	const int bottomHeight	= viewportHeight / 2;
1670e5c31af7Sopenharmony_ci	const int topHeight		= viewportHeight - bottomHeight;
1671e5c31af7Sopenharmony_ci
1672e5c31af7Sopenharmony_ci	// Clear.
1673e5c31af7Sopenharmony_ci	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1674e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT);
1675e5c31af7Sopenharmony_ci
1676e5c31af7Sopenharmony_ci	// Shear to get all slices visible.
1677e5c31af7Sopenharmony_ci	static const float depthShearTransfData[] =
1678e5c31af7Sopenharmony_ci	{
1679e5c31af7Sopenharmony_ci		1.0f, 0.0f, 0.0f,
1680e5c31af7Sopenharmony_ci		0.0f, 1.0f, 0.0f,
1681e5c31af7Sopenharmony_ci		1.0f, 1.0f, 0.0f
1682e5c31af7Sopenharmony_ci	};
1683e5c31af7Sopenharmony_ci
1684e5c31af7Sopenharmony_ci	// Minification and magnification transformations.
1685e5c31af7Sopenharmony_ci	static const float texMinTransfData[] =
1686e5c31af7Sopenharmony_ci	{
1687e5c31af7Sopenharmony_ci		2.2f,  0.0f, -0.3f,
1688e5c31af7Sopenharmony_ci		0.0f,  2.2f, -0.3f,
1689e5c31af7Sopenharmony_ci		0.0f,  0.0f,  1.0f
1690e5c31af7Sopenharmony_ci	};
1691e5c31af7Sopenharmony_ci	static const float texMagTransfData[] =
1692e5c31af7Sopenharmony_ci	{
1693e5c31af7Sopenharmony_ci		0.4f,  0.0f,  0.8f,
1694e5c31af7Sopenharmony_ci		0.0f,  0.4f,  0.8f,
1695e5c31af7Sopenharmony_ci		0.0f,  0.0f,  1.0f
1696e5c31af7Sopenharmony_ci	};
1697e5c31af7Sopenharmony_ci
1698e5c31af7Sopenharmony_ci	// Transformation matrices for minification and magnification.
1699e5c31af7Sopenharmony_ci	const Mat3 texMinTransf = Mat3(depthShearTransfData) * Mat3(texMinTransfData);
1700e5c31af7Sopenharmony_ci	const Mat3 texMagTransf = Mat3(depthShearTransfData) * Mat3(texMagTransfData);
1701e5c31af7Sopenharmony_ci
1702e5c31af7Sopenharmony_ci	// Surface for the reference image.
1703e5c31af7Sopenharmony_ci	tcu::Surface refImage(viewportWidth, viewportHeight);
1704e5c31af7Sopenharmony_ci
1705e5c31af7Sopenharmony_ci	{
1706e5c31af7Sopenharmony_ci		const struct Render
1707e5c31af7Sopenharmony_ci		{
1708e5c31af7Sopenharmony_ci			const Rect	region;
1709e5c31af7Sopenharmony_ci			int			textureNdx;
1710e5c31af7Sopenharmony_ci			const Mat3		texTransform;
1711e5c31af7Sopenharmony_ci			Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
1712e5c31af7Sopenharmony_ci		} renders[] =
1713e5c31af7Sopenharmony_ci		{
1714e5c31af7Sopenharmony_ci			Render(Rect(0,				0,				leftWidth,	bottomHeight),	0, texMinTransf),
1715e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		0,				rightWidth,	bottomHeight),	0, texMagTransf),
1716e5c31af7Sopenharmony_ci			Render(Rect(0,				bottomHeight,	leftWidth,	topHeight),		1, texMinTransf),
1717e5c31af7Sopenharmony_ci			Render(Rect(leftWidth,		bottomHeight,	rightWidth,	topHeight),		1, texMagTransf)
1718e5c31af7Sopenharmony_ci		};
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1721e5c31af7Sopenharmony_ci		{
1722e5c31af7Sopenharmony_ci			const Render&	rend				= renders[renderNdx];
1723e5c31af7Sopenharmony_ci			const float		lod					= calculateLod(rend.texTransform, rend.region.size().asFloat(), rend.textureNdx);
1724e5c31af7Sopenharmony_ci			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1725e5c31af7Sopenharmony_ci			const Grid		grid				(GRID_SIZE_3D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1726e5c31af7Sopenharmony_ci												 TexTypeCoordParams<TEXTURETYPE_3D>(rend.texTransform), useSafeTexCoords);
1727e5c31af7Sopenharmony_ci
1728e5c31af7Sopenharmony_ci			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1729e5c31af7Sopenharmony_ci			renderCell				(rend.textureNdx, lod, grid);
1730e5c31af7Sopenharmony_ci			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
1731e5c31af7Sopenharmony_ci		}
1732e5c31af7Sopenharmony_ci	}
1733e5c31af7Sopenharmony_ci
1734e5c31af7Sopenharmony_ci	// Read back rendered results.
1735e5c31af7Sopenharmony_ci	tcu::Surface resImage(viewportWidth, viewportHeight);
1736e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1737e5c31af7Sopenharmony_ci
1738e5c31af7Sopenharmony_ci	glUseProgram(0);
1739e5c31af7Sopenharmony_ci
1740e5c31af7Sopenharmony_ci	// Compare and log.
1741e5c31af7Sopenharmony_ci	{
1742e5c31af7Sopenharmony_ci		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1743e5c31af7Sopenharmony_ci
1744e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
1745e5c31af7Sopenharmony_ci								isOk ? "Pass"				: "Image comparison failed");
1746e5c31af7Sopenharmony_ci	}
1747e5c31af7Sopenharmony_ci
1748e5c31af7Sopenharmony_ci	return STOP;
1749e5c31af7Sopenharmony_ci}
1750e5c31af7Sopenharmony_ci
1751e5c31af7Sopenharmony_civoid Vertex3DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1752e5c31af7Sopenharmony_ci{
1753e5c31af7Sopenharmony_ci	const deUint32 programID = m_program->getProgram();
1754e5c31af7Sopenharmony_ci
1755e5c31af7Sopenharmony_ci	// SETUP ATTRIBUTES.
1756e5c31af7Sopenharmony_ci
1757e5c31af7Sopenharmony_ci	{
1758e5c31af7Sopenharmony_ci		const int positionLoc = glGetAttribLocation(programID, "a_position");
1759e5c31af7Sopenharmony_ci		if (positionLoc != -1)
1760e5c31af7Sopenharmony_ci		{
1761e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(positionLoc);
1762e5c31af7Sopenharmony_ci			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1763e5c31af7Sopenharmony_ci		}
1764e5c31af7Sopenharmony_ci	}
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci	{
1767e5c31af7Sopenharmony_ci		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1768e5c31af7Sopenharmony_ci		if (texCoordLoc != -1)
1769e5c31af7Sopenharmony_ci		{
1770e5c31af7Sopenharmony_ci			glEnableVertexAttribArray(texCoordLoc);
1771e5c31af7Sopenharmony_ci			glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1772e5c31af7Sopenharmony_ci		}
1773e5c31af7Sopenharmony_ci	}
1774e5c31af7Sopenharmony_ci
1775e5c31af7Sopenharmony_ci	// SETUP UNIFORMS.
1776e5c31af7Sopenharmony_ci
1777e5c31af7Sopenharmony_ci	{
1778e5c31af7Sopenharmony_ci		const int lodLoc = glGetUniformLocation(programID, "u_lod");
1779e5c31af7Sopenharmony_ci		if (lodLoc != -1)
1780e5c31af7Sopenharmony_ci			glUniform1f(lodLoc, lod);
1781e5c31af7Sopenharmony_ci	}
1782e5c31af7Sopenharmony_ci
1783e5c31af7Sopenharmony_ci	glActiveTexture(GL_TEXTURE0);
1784e5c31af7Sopenharmony_ci	glBindTexture(GL_TEXTURE_3D, m_textures[textureNdx]->getGLTexture());
1785e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		m_wrapS);
1786e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		m_wrapT);
1787e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		m_wrapR);
1788e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
1789e5c31af7Sopenharmony_ci	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
1790e5c31af7Sopenharmony_ci
1791e5c31af7Sopenharmony_ci	{
1792e5c31af7Sopenharmony_ci		const int texLoc = glGetUniformLocation(programID, "u_texture");
1793e5c31af7Sopenharmony_ci		if (texLoc != -1)
1794e5c31af7Sopenharmony_ci			glUniform1i(texLoc, 0);
1795e5c31af7Sopenharmony_ci	}
1796e5c31af7Sopenharmony_ci}
1797e5c31af7Sopenharmony_ci
1798e5c31af7Sopenharmony_ci// Renders one sub-image with given parameters.
1799e5c31af7Sopenharmony_civoid Vertex3DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1800e5c31af7Sopenharmony_ci{
1801e5c31af7Sopenharmony_ci	setupShaderInputs(textureNdx, lod, grid);
1802e5c31af7Sopenharmony_ci	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1803e5c31af7Sopenharmony_ci}
1804e5c31af7Sopenharmony_ci
1805e5c31af7Sopenharmony_ci// Computes reference for one sub-image with given parameters.
1806e5c31af7Sopenharmony_civoid Vertex3DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1807e5c31af7Sopenharmony_ci{
1808e5c31af7Sopenharmony_ci	computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, m_magFilter), grid, dst, dstRegion);
1809e5c31af7Sopenharmony_ci}
1810e5c31af7Sopenharmony_ci
1811e5c31af7Sopenharmony_ciVertexTextureTests::VertexTextureTests (Context& context)
1812e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "vertex", "Vertex Texture Tests")
1813e5c31af7Sopenharmony_ci{
1814e5c31af7Sopenharmony_ci}
1815e5c31af7Sopenharmony_ci
1816e5c31af7Sopenharmony_ciVertexTextureTests::~VertexTextureTests(void)
1817e5c31af7Sopenharmony_ci{
1818e5c31af7Sopenharmony_ci}
1819e5c31af7Sopenharmony_ci
1820e5c31af7Sopenharmony_civoid VertexTextureTests::init (void)
1821e5c31af7Sopenharmony_ci{
1822e5c31af7Sopenharmony_ci	// 2D and cube map groups, and their filtering and wrap sub-groups.
1823e5c31af7Sopenharmony_ci	TestCaseGroup* const group2D				= new TestCaseGroup(m_context, "2d",			"2D Vertex Texture Tests");
1824e5c31af7Sopenharmony_ci	TestCaseGroup* const groupCube				= new TestCaseGroup(m_context, "cube",			"Cube Map Vertex Texture Tests");
1825e5c31af7Sopenharmony_ci	TestCaseGroup* const group2DArray			= new TestCaseGroup(m_context, "2d_array",		"2D Array Vertex Texture Tests");
1826e5c31af7Sopenharmony_ci	TestCaseGroup* const group3D				= new TestCaseGroup(m_context, "3d",			"3D Vertex Texture Tests");
1827e5c31af7Sopenharmony_ci	TestCaseGroup* const filteringGroup2D		= new TestCaseGroup(m_context, "filtering",		"2D Vertex Texture Filtering Tests");
1828e5c31af7Sopenharmony_ci	TestCaseGroup* const wrapGroup2D			= new TestCaseGroup(m_context, "wrap",			"2D Vertex Texture Wrap Tests");
1829e5c31af7Sopenharmony_ci	TestCaseGroup* const filteringGroupCube		= new TestCaseGroup(m_context, "filtering",		"Cube Map Vertex Texture Filtering Tests");
1830e5c31af7Sopenharmony_ci	TestCaseGroup* const wrapGroupCube			= new TestCaseGroup(m_context, "wrap",			"Cube Map Vertex Texture Wrap Tests");
1831e5c31af7Sopenharmony_ci	TestCaseGroup* const filteringGroup2DArray	= new TestCaseGroup(m_context, "filtering",		"2D Array Vertex Texture Filtering Tests");
1832e5c31af7Sopenharmony_ci	TestCaseGroup* const wrapGroup2DArray		= new TestCaseGroup(m_context, "wrap",			"2D Array Vertex Texture Wrap Tests");
1833e5c31af7Sopenharmony_ci	TestCaseGroup* const filteringGroup3D		= new TestCaseGroup(m_context, "filtering",		"3D Vertex Texture Filtering Tests");
1834e5c31af7Sopenharmony_ci	TestCaseGroup* const wrapGroup3D			= new TestCaseGroup(m_context, "wrap",			"3D Vertex Texture Wrap Tests");
1835e5c31af7Sopenharmony_ci
1836e5c31af7Sopenharmony_ci	group2D->addChild(filteringGroup2D);
1837e5c31af7Sopenharmony_ci	group2D->addChild(wrapGroup2D);
1838e5c31af7Sopenharmony_ci	groupCube->addChild(filteringGroupCube);
1839e5c31af7Sopenharmony_ci	groupCube->addChild(wrapGroupCube);
1840e5c31af7Sopenharmony_ci	group2DArray->addChild(filteringGroup2DArray);
1841e5c31af7Sopenharmony_ci	group2DArray->addChild(wrapGroup2DArray);
1842e5c31af7Sopenharmony_ci	group3D->addChild(filteringGroup3D);
1843e5c31af7Sopenharmony_ci	group3D->addChild(wrapGroup3D);
1844e5c31af7Sopenharmony_ci
1845e5c31af7Sopenharmony_ci	addChild(group2D);
1846e5c31af7Sopenharmony_ci	addChild(groupCube);
1847e5c31af7Sopenharmony_ci	addChild(group2DArray);
1848e5c31af7Sopenharmony_ci	addChild(group3D);
1849e5c31af7Sopenharmony_ci
1850e5c31af7Sopenharmony_ci	static const struct
1851e5c31af7Sopenharmony_ci	{
1852e5c31af7Sopenharmony_ci		const char*		name;
1853e5c31af7Sopenharmony_ci		GLenum			mode;
1854e5c31af7Sopenharmony_ci	} wrapModes[] =
1855e5c31af7Sopenharmony_ci	{
1856e5c31af7Sopenharmony_ci		{ "clamp",		GL_CLAMP_TO_EDGE	},
1857e5c31af7Sopenharmony_ci		{ "repeat",		GL_REPEAT			},
1858e5c31af7Sopenharmony_ci		{ "mirror",		GL_MIRRORED_REPEAT	}
1859e5c31af7Sopenharmony_ci	};
1860e5c31af7Sopenharmony_ci
1861e5c31af7Sopenharmony_ci	static const struct
1862e5c31af7Sopenharmony_ci	{
1863e5c31af7Sopenharmony_ci		const char*		name;
1864e5c31af7Sopenharmony_ci		GLenum			mode;
1865e5c31af7Sopenharmony_ci	} minFilterModes[] =
1866e5c31af7Sopenharmony_ci	{
1867e5c31af7Sopenharmony_ci		{ "nearest",				GL_NEAREST					},
1868e5c31af7Sopenharmony_ci		{ "linear",					GL_LINEAR					},
1869e5c31af7Sopenharmony_ci		{ "nearest_mipmap_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
1870e5c31af7Sopenharmony_ci		{ "linear_mipmap_nearest",	GL_LINEAR_MIPMAP_NEAREST	},
1871e5c31af7Sopenharmony_ci		{ "nearest_mipmap_linear",	GL_NEAREST_MIPMAP_LINEAR	},
1872e5c31af7Sopenharmony_ci		{ "linear_mipmap_linear",	GL_LINEAR_MIPMAP_LINEAR		}
1873e5c31af7Sopenharmony_ci	};
1874e5c31af7Sopenharmony_ci
1875e5c31af7Sopenharmony_ci	static const struct
1876e5c31af7Sopenharmony_ci	{
1877e5c31af7Sopenharmony_ci		const char*		name;
1878e5c31af7Sopenharmony_ci		GLenum			mode;
1879e5c31af7Sopenharmony_ci	} magFilterModes[] =
1880e5c31af7Sopenharmony_ci	{
1881e5c31af7Sopenharmony_ci		{ "nearest",	GL_NEAREST	},
1882e5c31af7Sopenharmony_ci		{ "linear",		GL_LINEAR	}
1883e5c31af7Sopenharmony_ci	};
1884e5c31af7Sopenharmony_ci
1885e5c31af7Sopenharmony_ci#define FOR_EACH(ITERATOR, ARRAY, BODY)	\
1886e5c31af7Sopenharmony_ci	for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++)	\
1887e5c31af7Sopenharmony_ci		BODY
1888e5c31af7Sopenharmony_ci
1889e5c31af7Sopenharmony_ci	// 2D cases.
1890e5c31af7Sopenharmony_ci
1891e5c31af7Sopenharmony_ci	FOR_EACH(minFilter,		minFilterModes,
1892e5c31af7Sopenharmony_ci	FOR_EACH(magFilter,		magFilterModes,
1893e5c31af7Sopenharmony_ci	FOR_EACH(wrapMode,		wrapModes,
1894e5c31af7Sopenharmony_ci		{
1895e5c31af7Sopenharmony_ci			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1896e5c31af7Sopenharmony_ci
1897e5c31af7Sopenharmony_ci			filteringGroup2D->addChild(new Vertex2DTextureCase(m_context,
1898e5c31af7Sopenharmony_ci															   name.c_str(), "",
1899e5c31af7Sopenharmony_ci															   minFilterModes[minFilter].mode,
1900e5c31af7Sopenharmony_ci															   magFilterModes[magFilter].mode,
1901e5c31af7Sopenharmony_ci															   wrapModes[wrapMode].mode,
1902e5c31af7Sopenharmony_ci															   wrapModes[wrapMode].mode));
1903e5c31af7Sopenharmony_ci		})))
1904e5c31af7Sopenharmony_ci
1905e5c31af7Sopenharmony_ci	FOR_EACH(wrapSMode,		wrapModes,
1906e5c31af7Sopenharmony_ci	FOR_EACH(wrapTMode,		wrapModes,
1907e5c31af7Sopenharmony_ci		{
1908e5c31af7Sopenharmony_ci			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1909e5c31af7Sopenharmony_ci
1910e5c31af7Sopenharmony_ci			wrapGroup2D->addChild(new Vertex2DTextureCase(m_context,
1911e5c31af7Sopenharmony_ci														  name.c_str(), "",
1912e5c31af7Sopenharmony_ci														  GL_LINEAR_MIPMAP_LINEAR,
1913e5c31af7Sopenharmony_ci														  GL_LINEAR,
1914e5c31af7Sopenharmony_ci														  wrapModes[wrapSMode].mode,
1915e5c31af7Sopenharmony_ci														  wrapModes[wrapTMode].mode));
1916e5c31af7Sopenharmony_ci		}))
1917e5c31af7Sopenharmony_ci
1918e5c31af7Sopenharmony_ci	// Cube map cases.
1919e5c31af7Sopenharmony_ci
1920e5c31af7Sopenharmony_ci	FOR_EACH(minFilter,		minFilterModes,
1921e5c31af7Sopenharmony_ci	FOR_EACH(magFilter,		magFilterModes,
1922e5c31af7Sopenharmony_ci	FOR_EACH(wrapMode,		wrapModes,
1923e5c31af7Sopenharmony_ci		{
1924e5c31af7Sopenharmony_ci			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1925e5c31af7Sopenharmony_ci
1926e5c31af7Sopenharmony_ci			filteringGroupCube->addChild(new VertexCubeTextureCase(m_context,
1927e5c31af7Sopenharmony_ci																   name.c_str(), "",
1928e5c31af7Sopenharmony_ci																   minFilterModes[minFilter].mode,
1929e5c31af7Sopenharmony_ci																   magFilterModes[magFilter].mode,
1930e5c31af7Sopenharmony_ci																   wrapModes[wrapMode].mode,
1931e5c31af7Sopenharmony_ci																   wrapModes[wrapMode].mode));
1932e5c31af7Sopenharmony_ci		})))
1933e5c31af7Sopenharmony_ci
1934e5c31af7Sopenharmony_ci	FOR_EACH(wrapSMode,		wrapModes,
1935e5c31af7Sopenharmony_ci	FOR_EACH(wrapTMode,		wrapModes,
1936e5c31af7Sopenharmony_ci		{
1937e5c31af7Sopenharmony_ci			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1938e5c31af7Sopenharmony_ci
1939e5c31af7Sopenharmony_ci			wrapGroupCube->addChild(new VertexCubeTextureCase(m_context,
1940e5c31af7Sopenharmony_ci															  name.c_str(), "",
1941e5c31af7Sopenharmony_ci															  GL_LINEAR_MIPMAP_LINEAR,
1942e5c31af7Sopenharmony_ci															  GL_LINEAR,
1943e5c31af7Sopenharmony_ci															  wrapModes[wrapSMode].mode,
1944e5c31af7Sopenharmony_ci															  wrapModes[wrapTMode].mode));
1945e5c31af7Sopenharmony_ci		}))
1946e5c31af7Sopenharmony_ci
1947e5c31af7Sopenharmony_ci	// 2D array cases.
1948e5c31af7Sopenharmony_ci
1949e5c31af7Sopenharmony_ci	FOR_EACH(minFilter,		minFilterModes,
1950e5c31af7Sopenharmony_ci	FOR_EACH(magFilter,		magFilterModes,
1951e5c31af7Sopenharmony_ci	FOR_EACH(wrapMode,		wrapModes,
1952e5c31af7Sopenharmony_ci		{
1953e5c31af7Sopenharmony_ci			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1954e5c31af7Sopenharmony_ci
1955e5c31af7Sopenharmony_ci			filteringGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1956e5c31af7Sopenharmony_ci																		 name.c_str(), "",
1957e5c31af7Sopenharmony_ci																		 minFilterModes[minFilter].mode,
1958e5c31af7Sopenharmony_ci																		 magFilterModes[magFilter].mode,
1959e5c31af7Sopenharmony_ci																		 wrapModes[wrapMode].mode,
1960e5c31af7Sopenharmony_ci																		 wrapModes[wrapMode].mode));
1961e5c31af7Sopenharmony_ci		})))
1962e5c31af7Sopenharmony_ci
1963e5c31af7Sopenharmony_ci	FOR_EACH(wrapSMode,		wrapModes,
1964e5c31af7Sopenharmony_ci	FOR_EACH(wrapTMode,		wrapModes,
1965e5c31af7Sopenharmony_ci		{
1966e5c31af7Sopenharmony_ci			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1967e5c31af7Sopenharmony_ci
1968e5c31af7Sopenharmony_ci			wrapGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1969e5c31af7Sopenharmony_ci																	name.c_str(), "",
1970e5c31af7Sopenharmony_ci																	GL_LINEAR_MIPMAP_LINEAR,
1971e5c31af7Sopenharmony_ci																	GL_LINEAR,
1972e5c31af7Sopenharmony_ci																	wrapModes[wrapSMode].mode,
1973e5c31af7Sopenharmony_ci																	wrapModes[wrapTMode].mode));
1974e5c31af7Sopenharmony_ci		}))
1975e5c31af7Sopenharmony_ci
1976e5c31af7Sopenharmony_ci	// 3D cases.
1977e5c31af7Sopenharmony_ci
1978e5c31af7Sopenharmony_ci	FOR_EACH(minFilter,		minFilterModes,
1979e5c31af7Sopenharmony_ci	FOR_EACH(magFilter,		magFilterModes,
1980e5c31af7Sopenharmony_ci	FOR_EACH(wrapMode,		wrapModes,
1981e5c31af7Sopenharmony_ci		{
1982e5c31af7Sopenharmony_ci			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1983e5c31af7Sopenharmony_ci
1984e5c31af7Sopenharmony_ci			filteringGroup3D->addChild(new Vertex3DTextureCase(m_context,
1985e5c31af7Sopenharmony_ci															   name.c_str(), "",
1986e5c31af7Sopenharmony_ci															   minFilterModes[minFilter].mode,
1987e5c31af7Sopenharmony_ci															   magFilterModes[magFilter].mode,
1988e5c31af7Sopenharmony_ci															   wrapModes[wrapMode].mode,
1989e5c31af7Sopenharmony_ci															   wrapModes[wrapMode].mode,
1990e5c31af7Sopenharmony_ci															   wrapModes[wrapMode].mode));
1991e5c31af7Sopenharmony_ci		})))
1992e5c31af7Sopenharmony_ci
1993e5c31af7Sopenharmony_ci	FOR_EACH(wrapSMode,		wrapModes,
1994e5c31af7Sopenharmony_ci	FOR_EACH(wrapTMode,		wrapModes,
1995e5c31af7Sopenharmony_ci	FOR_EACH(wrapRMode,		wrapModes,
1996e5c31af7Sopenharmony_ci		{
1997e5c31af7Sopenharmony_ci			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name + "_" + wrapModes[wrapRMode].name;
1998e5c31af7Sopenharmony_ci
1999e5c31af7Sopenharmony_ci			wrapGroup3D->addChild(new Vertex3DTextureCase(m_context,
2000e5c31af7Sopenharmony_ci														  name.c_str(), "",
2001e5c31af7Sopenharmony_ci														  GL_LINEAR_MIPMAP_LINEAR,
2002e5c31af7Sopenharmony_ci														  GL_LINEAR,
2003e5c31af7Sopenharmony_ci														  wrapModes[wrapSMode].mode,
2004e5c31af7Sopenharmony_ci														  wrapModes[wrapTMode].mode,
2005e5c31af7Sopenharmony_ci														  wrapModes[wrapRMode].mode));
2006e5c31af7Sopenharmony_ci		})))
2007e5c31af7Sopenharmony_ci}
2008e5c31af7Sopenharmony_ci
2009e5c31af7Sopenharmony_ci} // Functional
2010e5c31af7Sopenharmony_ci} // gles3
2011e5c31af7Sopenharmony_ci} // deqp
2012