13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 2.0 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Vertex texture tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es2fVertexTextureTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTexture.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuMatrix.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
32c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "tcuTexVerifierUtil.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
36c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "deMath.h"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string>
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <limits>
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glw.h"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4;
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Mat3;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::TextureTestUtil;
60c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketusing namespace glu::TextureTestUtil;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
62c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketusing glu::TextureTestUtil::TEXTURETYPE_2D;
63c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketusing glu::TextureTestUtil::TEXTURETYPE_CUBE;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles2
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The 2D case draws four images.
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int MAX_2D_RENDER_WIDTH		= 128*2;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int MAX_2D_RENDER_HEIGHT		= 128*2;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The cube map case draws four 3-by-2 image groups.
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int MAX_CUBE_RENDER_WIDTH		= 28*2*3;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int MAX_CUBE_RENDER_HEIGHT		= 28*2*2;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int GRID_SIZE_2D				= 127;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const int GRID_SIZE_CUBE				= 63;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Helpers for making texture coordinates "safe", i.e. move them further from coordinate bounary.
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Moves x towards the closest K+targetFraction, where K is an integer.
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// E.g. moveTowardsFraction(x, 0.5f) moves x away from integer boundaries.
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float moveTowardsFraction (float x, float targetFraction)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float strictness = 0.5f;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(0.0f < strictness && strictness <= 1.0f);
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inBounds(targetFraction, 0.0f, 1.0f));
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float y = x + 0.5f - targetFraction;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatFloor(y) + deFloatFrac(y)*(1.0f-strictness) + strictness*0.5f - 0.5f + targetFraction;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float safeCoord (float raw, int scale, float fraction)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float scaleFloat = (float)scale;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return moveTowardsFraction(raw*scaleFloat, fraction) / scaleFloat;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <int Size>
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vector<float, Size> safeCoords (const tcu::Vector<float, Size>& raw, const tcu::Vector<int, Size>& scale, const tcu::Vector<float, Size>& fraction)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vector<float, Size> result;
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < Size; i++)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		result[i] = safeCoord(raw[i], scale[i], fraction[i]);
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline Vec2 safe2DTexCoords (const Vec2& raw, const IVec2& textureSize)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return safeCoords(raw, textureSize, Vec2(0.5f));
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct Rect
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Rect	(int x_, int y_, int w_, int h_) : x(x_), y(y_), w(w_), h(h_) {}
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec2	pos		(void) const { return IVec2(x, y); }
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IVec2	size	(void) const { return IVec2(w, h); }
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		x;
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		y;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		w;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		h;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType> struct TexTypeTcuClass;
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeTcuClass<TEXTURETYPE_2D>			{ typedef tcu::Texture2D		t; };
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeTcuClass<TEXTURETYPE_CUBE>		{ typedef tcu::TextureCube		t; };
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType> struct TexTypeSizeDims;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeSizeDims<TEXTURETYPE_2D>			{ enum { V = 2 }; };
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeSizeDims<TEXTURETYPE_CUBE>		{ enum { V = 2 }; };
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType> struct TexTypeCoordDims;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeCoordDims<TEXTURETYPE_2D>			{ enum { V = 2 }; };
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct TexTypeCoordDims<TEXTURETYPE_CUBE>		{ enum { V = 3 }; };
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType> struct TexTypeSizeIVec		{ typedef tcu::Vector<int,		TexTypeSizeDims<TexType>::V>	t; };
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType> struct TexTypeCoordVec		{ typedef tcu::Vector<float,	TexTypeCoordDims<TexType>::V>	t; };
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType> struct TexTypeCoordParams;
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct
1473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTexTypeCoordParams<TEXTURETYPE_2D>
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2 scale;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2 bias;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_) : scale(scale_), bias(bias_) {}
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <> struct
1563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTexTypeCoordParams<TEXTURETYPE_CUBE>
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2			scale;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2			bias;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::CubeFace	face;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_, tcu::CubeFace face_) : scale(scale_), bias(bias_), face(face_) {}
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Quad grid class containing position and texture coordinate data.
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A quad grid of size S means a grid consisting of S*S quads (S rows and
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * S columns). The quads are rectangles with main axis aligned sides, and
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * each consists of two triangles. Note that although there are only
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * (S+1)*(S+1) distinct vertex positions, there are S*S*4 distinct vertices
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * because we want texture coordinates to be constant across the vertices
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * of a quad (to avoid interpolation issues), and thus each quad needs its
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * own 4 vertices.
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Pointers returned by get*Ptr() are suitable for gl calls such as
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * glVertexAttribPointer() (for position and tex coord) or glDrawElements()
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * (for indices).
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass PosTexCoordQuadGrid
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum { TEX_COORD_DIMS = TexTypeCoordDims <TexType>::V };
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename TexTypeCoordVec<TexType>::t	TexCoordVec;
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef typename TexTypeSizeIVec<TexType>::t	TexSizeIVec;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef TexTypeCoordParams<TexType>				TexCoordParams;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							PosTexCoordQuadGrid		(int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						getSize					(void) const { return m_gridSize; }
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec4					getQuadLDRU				(int col, int row) const; //!< Vec4(leftX, downY, rightX, upY)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const TexCoordVec&		getQuadTexCoord			(int col, int row) const;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						getNumIndices			(void) const { return m_gridSize*m_gridSize*3*2; }
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float*			getPositionPtr			(void) const { DE_STATIC_ASSERT(sizeof(Vec2) == 2*sizeof(float)); return (float*)&m_positions[0]; }
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float*			getTexCoordPtr			(void) const { DE_STATIC_ASSERT(sizeof(TexCoordVec) == TEX_COORD_DIMS*(int)sizeof(float)); return (float*)&m_texCoords[0]; }
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint16*			getIndexPtr				(void) const { return &m_indices[0]; }
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					initializeTexCoords		(const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_gridSize;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec2>			m_positions;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<TexCoordVec>		m_texCoords;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<deUint16>		m_indices;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
2113c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVec4 PosTexCoordQuadGrid<TexType>::getQuadLDRU (int col, int row) const
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int ndx00 = (row*m_gridSize + col) * 4;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int ndx11 = ndx00 + 3;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Vec4(m_positions[ndx00].x(),
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_positions[ndx00].y(),
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_positions[ndx11].x(),
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_positions[ndx11].y());
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst typename TexTypeCoordVec<TexType>::t& PosTexCoordQuadGrid<TexType>::getQuadTexCoord (int col, int row) const
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_texCoords[(row*m_gridSize + col) * 4];
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
2293c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPosTexCoordQuadGrid<TexType>::PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_gridSize(gridSize)
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_gridSize > 0 && m_gridSize*m_gridSize <= (int)std::numeric_limits<deUint16>::max() + 1);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float gridSizeFloat = (float)m_gridSize;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_positions.reserve(m_gridSize*m_gridSize*4);
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_indices.reserve(m_gridSize*m_gridSize*3*2);
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < m_gridSize; y++)
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < m_gridSize; x++)
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float fx0 = (float)(x+0) / gridSizeFloat;
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float fx1 = (float)(x+1) / gridSizeFloat;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float fy0 = (float)(y+0) / gridSizeFloat;
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		float fy1 = (float)(y+1) / gridSizeFloat;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2 quadVertices[4] = { Vec2(fx0, fy0), Vec2(fx1, fy0), Vec2(fx0, fy1), Vec2(fx1, fy1) };
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int firstNdx = (int)m_positions.size();
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < DE_LENGTH_OF_ARRAY(quadVertices); i++)
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_positions.push_back(safeCoords(quadVertices[i], renderSize, Vec2(0.0f)) * 2.0f - 1.0f);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25439ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 0));
25539ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 1));
25639ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 2));
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25839ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 1));
25939ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 3));
26039ecdeaaa1890f9116c38c84dbb3da7867abe4c4Jarkko Pöyry		m_indices.push_back(deUint16(firstNdx + 2));
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_texCoords.reserve(m_gridSize*m_gridSize*4);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initializeTexCoords(textureSize, texCoordParams, useSafeTexCoords);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_positions.size() == m_gridSize*m_gridSize*4);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_indices.size() == m_gridSize*m_gridSize*3*2);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)m_texCoords.size() == m_gridSize*m_gridSize*4);
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PosTexCoordQuadGrid<TEXTURETYPE_2D>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_texCoords.empty());
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float gridSizeFloat = (float)m_gridSize;
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < m_gridSize; y++)
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < m_gridSize; x++)
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vec2 rawCoord = Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) * texCoordParams.scale + texCoordParams.bias;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 4; i++)
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texCoords.push_back(useSafeTexCoords ? safe2DTexCoords(rawCoord, textureSize) : rawCoord);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <>
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PosTexCoordQuadGrid<TEXTURETYPE_CUBE>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_texCoords.empty());
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		gridSizeFloat	= (float)m_gridSize;
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<float>	texBoundaries;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeQuadTexCoordCube(texBoundaries, texCoordParams.face);
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3		coordA			= Vec3(texBoundaries[0], texBoundaries[1], texBoundaries[2]);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3		coordB			= Vec3(texBoundaries[3], texBoundaries[4], texBoundaries[5]);
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3		coordC			= Vec3(texBoundaries[6], texBoundaries[7], texBoundaries[8]);
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3		coordAB			= coordB - coordA;
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec3		coordAC			= coordC - coordA;
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < m_gridSize; y++)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < m_gridSize; x++)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 rawFaceCoord		= texCoordParams.scale * Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) + texCoordParams.bias;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2 safeFaceCoord	= useSafeTexCoords ? safe2DTexCoords(rawFaceCoord, textureSize) : rawFaceCoord;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec3 texCoord			= coordA + coordAC*safeFaceCoord.x() + coordAB*safeFaceCoord.y();
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 4; i++)
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texCoords.push_back(texCoord);
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isLevelNearest (deUint32 filter)
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return filter == GL_NEAREST || filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_NEAREST_MIPMAP_LINEAR;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline IVec2 getTextureSize (const glu::Texture2D& tex)
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2D& ref = tex.getRefTexture();
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return IVec2(ref.getWidth(), ref.getHeight());
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline IVec2 getTextureSize (const glu::TextureCube& tex)
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCube& ref = tex.getRefTexture();
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return IVec2(ref.getSize(), ref.getSize());
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setPixelColors (const vector<Vec4>& quadColors, const Rect& region, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst)
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int gridSize = grid.getSize();
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < gridSize; y++)
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < gridSize; x++)
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4	color	= quadColors[y*gridSize + x];
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4	ldru	= grid.getQuadLDRU(x, y) * 0.5f + 0.5f; // [-1, 1] -> [0, 1]
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	ix0		= deCeilFloatToInt32(ldru.x() * (float)region.w - 0.5f);
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	ix1		= deCeilFloatToInt32(ldru.z() * (float)region.w - 0.5f);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	iy0		= deCeilFloatToInt32(ldru.y() * (float)region.h - 0.5f);
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	iy1		= deCeilFloatToInt32(ldru.w() * (float)region.h - 0.5f);
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int iy = iy0; iy < iy1; iy++)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ix = ix0; ix < ix1; ix++)
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(deInBounds32(ix + region.x, 0, dst.getWidth()));
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(deInBounds32(iy + region.y, 0, dst.getHeight()));
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
354fb4796914bfb9f7bef4d75312b9bce592e169b4bJarkko Pöyry			dst.setPixel(ix + region.x, iy + region.y, tcu::RGBA(color));
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic 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); }
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic 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); }
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <TextureType TexType>
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeReference (const typename TexTypeTcuClass<TexType>::t& texture, float lod, const tcu::Sampler& sampler, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst, const Rect& dstRegion)
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		gridSize	= grid.getSize();
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec4>	quadColors	(gridSize*gridSize);
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < gridSize; y++)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < gridSize; x++)
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int										ndx		= y*gridSize + x;
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const typename TexTypeCoordVec<TexType>::t&		coord	= grid.getQuadTexCoord(x, y);
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		quadColors[ndx] = sample(texture, coord, lod, sampler);
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setPixelColors(quadColors, dstRegion, grid, dst);
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool compareImages (const glu::RenderContext& renderCtx, tcu::TestLog& log, const tcu::Surface& ref, const tcu::Surface& res)
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(renderCtx.getRenderTarget().getNumSamples() == 0);
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(15,15,15,15);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::pixelThresholdCompare(log, "Result", "Image compare result", ref, res, threshold, tcu::COMPARE_LOG_RESULT);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Vertex2DTextureCase : public TestCase
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Vertex2DTextureCase		(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~Vertex2DTextureCase	(void);
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init					(void);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit					(void);
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate					(void);
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef PosTexCoordQuadGrid<TEXTURETYPE_2D> Grid;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								Vertex2DTextureCase		(const Vertex2DTextureCase& other);
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vertex2DTextureCase&		operator=				(const Vertex2DTextureCase& other);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float						calculateLod			(const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						setupShaderInputs		(int textureNdx, float lod, const Grid& grid) const;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						renderCell				(int textureNdx, float lod, const Grid& grid) const;
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						computeReferenceCell	(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_minFilter;
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_magFilter;
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_wrapS;
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_wrapT;
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderProgram*	m_program;
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Texture2D*				m_textures[2];	// 2 textures, a gradient texture and a grid texture.
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4183c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertex2DTextureCase::Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_minFilter			(minFilter)
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_magFilter			(magFilter)
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_wrapS				(wrapS)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_wrapT				(wrapT)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program				(DE_NULL)
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures[0] = DE_NULL;
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures[1] = DE_NULL;
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertex2DTextureCase::~Vertex2DTextureCase(void)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vertex2DTextureCase::deinit();
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Vertex2DTextureCase::init (void)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const vertexShader =
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"attribute highp vec2 a_position;\n"
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"attribute highp vec2 a_texCoord;\n"
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform highp sampler2D u_texture;\n"
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform highp float u_lod;\n"
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"varying mediump vec4 v_color;\n"
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main()\n"
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	v_color = texture2DLod(u_texture, a_texCoord, u_lod);\n"
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const fragmentShader =
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"varying mediump vec4 v_color;\n"
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main()\n"
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_FragColor = v_color;\n"
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_context.getRenderTarget().getNumSamples() != 0)
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("MSAA config not supported by this test");
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program);
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if(!m_program->isOk())
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_program;
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint maxVertexTextures;
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (maxVertexTextures < 1)
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Failed to compile shader");
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Make the textures.
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute suitable power-of-two sizes (for mipmaps).
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texWidth		= 1 << deLog2Ceil32(MAX_2D_RENDER_WIDTH / 2);
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texHeight		= 1 << deLog2Ceil32(MAX_2D_RENDER_HEIGHT / 2);
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 2; i++)
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!m_textures[i]);
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[i] = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool						mipmaps		= (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight));
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						numLevels	= mipmaps ? deLog2Floor32(de::max(texWidth, texHeight))+1 : 1;
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4						cBias		= fmtInfo.valueMin;
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fill first with gradient texture.
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec4 gMax = Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[0]->getRefTexture().allocLevel(levelNdx);
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fill second with grid texture.
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 step		= 0x00ffffff / numLevels;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 rgb		= step*levelNdx;
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 colorA	= 0xff000000 | rgb;
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32 colorB	= 0xff000000 | ~rgb;
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[1]->getRefTexture().allocLevel(levelNdx);
515c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Upload.
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 2; i++)
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[i]->upload();
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception&)
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Clean up to save memory.
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Vertex2DTextureCase::deinit();
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Vertex2DTextureCase::deinit (void)
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 2; i++)
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_textures[i];
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_textures[i] = DE_NULL;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat Vertex2DTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2D&		refTexture	= m_textures[textureNdx]->getRefTexture();
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2					srcSize		= Vec2((float)refTexture.getWidth(), (float)refTexture.getHeight());
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2					sizeRatio	= texScale*srcSize / dstSize;
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note In this particular case dv/dx and du/dy are zero, simplifying the expression.
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertex2DTextureCase::IterateResult Vertex2DTextureCase::iterate (void)
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_RENDER_WIDTH);
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_RENDER_HEIGHT);
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random	rnd					(deStringHash(getName()));
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(m_program->getProgram());
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Divide viewport into 4 cells.
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int leftWidth		= viewportWidth / 2;
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int rightWidth	= viewportWidth - leftWidth;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int bottomHeight	= viewportHeight / 2;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int topHeight		= viewportHeight - bottomHeight;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Clear.
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClear(GL_COLOR_BUFFER_BIT);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Texture scaling and offsetting vectors.
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMinScale		(+1.8f, +1.8f);
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMinOffset		(-0.3f, -0.2f);
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMagScale		(+0.3f, +0.3f);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMagOffset		(+0.9f, +0.8f);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Surface for the reference image.
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface refImage(viewportWidth, viewportHeight);
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct Render
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Rect	region;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			textureNdx;
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec2	texCoordScale;
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec2	texCoordOffset;
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} renders[] =
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(0,				0,				leftWidth,	bottomHeight),	0, texMinScale, texMinOffset),
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(leftWidth,		0,				rightWidth,	bottomHeight),	0, texMagScale, texMagOffset),
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(0,				bottomHeight,	leftWidth,	topHeight),		1, texMinScale, texMinOffset),
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(leftWidth,		bottomHeight,	rightWidth,	topHeight),		1, texMagScale, texMagOffset)
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Render&	rend				= renders[renderNdx];
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		lod					= calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Grid		grid				(GRID_SIZE_2D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 TexTypeCoordParams<TEXTURETYPE_2D>(rend.texCoordScale, rend.texCoordOffset), useSafeTexCoords);
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			renderCell				(rend.textureNdx, lod, grid);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back rendered results.
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface resImage(viewportWidth, viewportHeight);
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(0);
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare and log.
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								isOk ? "Pass"				: "Image comparison failed");
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Vertex2DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32 programID = m_program->getProgram();
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// SETUP ATTRIBUTES.
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int positionLoc = glGetAttribLocation(programID, "a_position");
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (positionLoc != -1)
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glEnableVertexAttribArray(positionLoc);
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texCoordLoc != -1)
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glEnableVertexAttribArray(texCoordLoc);
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// SETUP UNIFORMS.
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int lodLoc = glGetUniformLocation(programID, "u_lod");
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (lodLoc != -1)
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glUniform1f(lodLoc, lod);
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glActiveTexture(GL_TEXTURE0);
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindTexture(GL_TEXTURE_2D, m_textures[textureNdx]->getGLTexture());
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texLoc = glGetUniformLocation(programID, "u_texture");
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texLoc != -1)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glUniform1i(texLoc, 0);
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Renders one sub-image with given parameters.
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Vertex2DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setupShaderInputs(textureNdx, lod, grid);
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Vertex2DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VertexCubeTextureCase : public TestCase
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								VertexCubeTextureCase	(Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~VertexCubeTextureCase	(void);
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						init					(void);
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						deinit					(void);
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult				iterate					(void);
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef PosTexCoordQuadGrid<TEXTURETYPE_CUBE> Grid;
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								VertexCubeTextureCase	(const VertexCubeTextureCase& other);
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexCubeTextureCase&		operator=				(const VertexCubeTextureCase& other);
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float						calculateLod			(const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						setupShaderInputs		(int textureNdx, float lod, const Grid& grid) const;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						renderCell				(int textureNdx, float lod, const Grid& grid) const;
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						computeReferenceCell	(int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_minFilter;
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_magFilter;
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_wrapS;
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				m_wrapT;
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderProgram*	m_program;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::TextureCube*			m_textures[2];	// 2 textures, a gradient texture and a grid texture.
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7213c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexCubeTextureCase::VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase				(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_minFilter			(minFilter)
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_magFilter			(magFilter)
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_wrapS				(wrapS)
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_wrapT				(wrapT)
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_program				(DE_NULL)
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures[0] = DE_NULL;
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_textures[1] = DE_NULL;
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexCubeTextureCase::~VertexCubeTextureCase(void)
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexCubeTextureCase::deinit();
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexCubeTextureCase::init (void)
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const vertexShader =
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"attribute highp vec2 a_position;\n"
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"attribute highp vec3 a_texCoord;\n"
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform highp samplerCube u_texture;\n"
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform highp float u_lod;\n"
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"varying mediump vec4 v_color;\n"
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main()\n"
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	v_color = textureCubeLod(u_texture, a_texCoord, u_lod);\n"
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* const fragmentShader =
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"varying mediump vec4 v_color;\n"
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main()\n"
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_FragColor = v_color;\n"
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_context.getRenderTarget().getNumSamples() != 0)
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("MSAA config not supported by this test");
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_program);
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if(!m_program->isOk())
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << *m_program;
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLint maxVertexTextures;
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (maxVertexTextures < 1)
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Failed to compile shader");
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Make the textures.
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute suitable power-of-two sizes (for mipmaps).
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texWidth		= 1 << deLog2Ceil32(MAX_CUBE_RENDER_WIDTH / 3 / 2);
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texHeight		= 1 << deLog2Ceil32(MAX_CUBE_RENDER_HEIGHT / 2 / 2);
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(texWidth == texHeight);
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_UNREF(texHeight);
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 2; i++)
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!m_textures[i]);
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[i] = new glu::TextureCube(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth);
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool						mipmaps		= deIsPowerOfTwo32(texWidth) != DE_FALSE;
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int						numLevels	= mipmaps ? deLog2Floor32(texWidth)+1 : 1;
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4						cBias		= fmtInfo.valueMin;
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec4						cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fill first with gradient texture.
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const Vec4 gradients[tcu::CUBEFACE_LAST][2] =
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4(-1.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4( 0.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4(-1.0f,  0.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4(-1.0f, -1.0f,  0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4(-1.0f, -1.0f, -1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ Vec4( 0.0f,  0.0f,  0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fill second with grid texture.
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32 step		= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32 rgb		= step*levelNdx*face;
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32 colorA	= 0xff000000 | rgb;
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32 colorB	= 0xff000000 | ~rgb;
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
832c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Upload.
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < 2; i++)
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_textures[i]->upload();
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception&)
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Clean up to save memory.
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VertexCubeTextureCase::deinit();
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexCubeTextureCase::deinit (void)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 2; i++)
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_textures[i];
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_textures[i] = DE_NULL;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_program;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = DE_NULL;
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat VertexCubeTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCube&		refTexture	= m_textures[textureNdx]->getRefTexture();
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2					srcSize		= Vec2((float)refTexture.getSize(), (float)refTexture.getSize());
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2					sizeRatio	= texScale*srcSize / dstSize;
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note In this particular case, dv/dx and du/dy are zero, simplifying the expression.
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8703c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexCubeTextureCase::IterateResult VertexCubeTextureCase::iterate (void)
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportWidth		= deMin32(m_context.getRenderTarget().getWidth(), MAX_CUBE_RENDER_WIDTH);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportHeight		= deMin32(m_context.getRenderTarget().getHeight(), MAX_CUBE_RENDER_HEIGHT);
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportXOffsetMax	= m_context.getRenderTarget().getWidth() - viewportWidth;
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportYOffsetMax	= m_context.getRenderTarget().getHeight() - viewportHeight;
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random	rnd					(deStringHash(getName()));
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportXOffset		= rnd.getInt(0, viewportXOffsetMax);
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	viewportYOffset		= rnd.getInt(0, viewportYOffsetMax);
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(m_program->getProgram());
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Divide viewport into 4 areas.
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int leftWidth		= viewportWidth / 2;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int rightWidth	= viewportWidth - leftWidth;
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int bottomHeight	= viewportHeight / 2;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int topHeight		= viewportHeight - bottomHeight;
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Clear.
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glClear(GL_COLOR_BUFFER_BIT);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Texture scaling and offsetting vectors.
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMinScale		(1.0f, 1.0f);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMinOffset		(0.0f, 0.0f);
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMagScale		(0.3f, 0.3f);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Vec2 texMagOffset		(0.5f, 0.3f);
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Surface for the reference image.
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface refImage(viewportWidth, viewportHeight);
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Each of the four areas is divided into 6 cells.
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int defCellWidth	= viewportWidth / 2 / 3;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int defCellHeight	= viewportHeight / 2 / 2;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < tcu::CUBEFACE_LAST; i++)
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	cellOffsetX			= defCellWidth * (i % 3);
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	cellOffsetY			= defCellHeight * (i / 3);
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool	isRightmostCell		= i == 2 || i == 5;
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool	isTopCell			= i >= 3;
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	leftCellWidth		= isRightmostCell	? leftWidth		- cellOffsetX : defCellWidth;
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	rightCellWidth		= isRightmostCell	? rightWidth	- cellOffsetX : defCellWidth;
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	bottomCellHeight	= isTopCell			? bottomHeight	- cellOffsetY : defCellHeight;
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	topCellHeight		= isTopCell			? topHeight		- cellOffsetY : defCellHeight;
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct Render
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Rect	region;
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int			textureNdx;
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec2	texCoordScale;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Vec2	texCoordOffset;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} renders[] =
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(cellOffsetX + 0,			cellOffsetY + 0,				leftCellWidth,	bottomCellHeight),	0, texMinScale, texMinOffset),
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(cellOffsetX + leftWidth,	cellOffsetY + 0,				rightCellWidth,	bottomCellHeight),	0, texMagScale, texMagOffset),
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(cellOffsetX + 0,			cellOffsetY + bottomHeight,		leftCellWidth,	topCellHeight),		1, texMinScale, texMinOffset),
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Render(Rect(cellOffsetX + leftWidth,	cellOffsetY + bottomHeight,		rightCellWidth,	topCellHeight),		1, texMagScale, texMagOffset)
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Render&	rend				= renders[renderNdx];
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		lod					= calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		useSafeTexCoords	= isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const Grid		grid				(GRID_SIZE_CUBE, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 TexTypeCoordParams<TEXTURETYPE_CUBE>(rend.texCoordScale, rend.texCoordOffset, (tcu::CubeFace)i), useSafeTexCoords);
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			renderCell				(rend.textureNdx, lod, grid);
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			computeReferenceCell	(rend.textureNdx, lod, grid, refImage, rend.region);
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back rendered results.
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface resImage(viewportWidth, viewportHeight);
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glUseProgram(0);
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Compare and log.
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								isOk ? "Pass"				: "Image comparison failed");
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexCubeTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32 programID = m_program->getProgram();
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// SETUP ATTRIBUTES.
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int positionLoc = glGetAttribLocation(programID, "a_position");
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (positionLoc != -1)
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glEnableVertexAttribArray(positionLoc);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texCoordLoc != -1)
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glEnableVertexAttribArray(texCoordLoc);
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// SETUP UNIFORMS.
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int lodLoc = glGetUniformLocation(programID, "u_lod");
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (lodLoc != -1)
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glUniform1f(lodLoc, lod);
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glActiveTexture(GL_TEXTURE0);
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glBindTexture(GL_TEXTURE_CUBE_MAP, m_textures[textureNdx]->getGLTexture());
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		m_wrapS);
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		m_wrapT);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	m_minFilter);
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	m_magFilter);
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int texLoc = glGetUniformLocation(programID, "u_texture");
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (texLoc != -1)
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glUniform1i(texLoc, 0);
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Renders one cube face with given parameters.
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexCubeTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setupShaderInputs(textureNdx, lod, grid);
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Computes reference for one cube face with given parameters.
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexCubeTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Sampler sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	computeReference(m_textures[textureNdx]->getRefTexture(), lod, sampler, grid, dst, dstRegion);
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexTextureTests::VertexTextureTests (Context& context)
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "vertex", "Vertex Texture Tests")
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10303c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexTextureTests::~VertexTextureTests(void)
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VertexTextureTests::init (void)
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// 2D and cube map groups, and their filtering and wrap sub-groups.
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const group2D				= new TestCaseGroup(m_context, "2d",			"2D Vertex Texture Tests");
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const groupCube				= new TestCaseGroup(m_context, "cube",			"Cube Map Vertex Texture Tests");
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const filteringGroup2D		= new TestCaseGroup(m_context, "filtering",		"2D Vertex Texture Filtering Tests");
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const wrapGroup2D			= new TestCaseGroup(m_context, "wrap",			"2D Vertex Texture Wrap Tests");
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const filteringGroupCube		= new TestCaseGroup(m_context, "filtering",		"Cube Map Vertex Texture Filtering Tests");
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestCaseGroup* const wrapGroupCube			= new TestCaseGroup(m_context, "wrap",			"Cube Map Vertex Texture Wrap Tests");
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group2D->addChild(filteringGroup2D);
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	group2D->addChild(wrapGroup2D);
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	groupCube->addChild(filteringGroupCube);
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	groupCube->addChild(wrapGroupCube);
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(group2D);
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addChild(groupCube);
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum			mode;
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} wrapModes[] =
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "clamp",		GL_CLAMP_TO_EDGE	},
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "repeat",		GL_REPEAT			},
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "mirror",		GL_MIRRORED_REPEAT	}
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum			mode;
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} minFilterModes[] =
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "nearest",				GL_NEAREST					},
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "linear",					GL_LINEAR					},
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "nearest_mipmap_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "linear_mipmap_nearest",	GL_LINEAR_MIPMAP_NEAREST	},
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "nearest_mipmap_linear",	GL_NEAREST_MIPMAP_LINEAR	},
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "linear_mipmap_linear",	GL_LINEAR_MIPMAP_LINEAR		}
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLenum			mode;
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} magFilterModes[] =
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "nearest",	GL_NEAREST	},
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "linear",		GL_LINEAR	}
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define FOR_EACH(ITERATOR, ARRAY, BODY)	\
1088dc795cd4f3d064cbbe2bf9899bf2088d206b7434Chih-Hung Hsieh	for (int (ITERATOR) = 0; (ITERATOR) < DE_LENGTH_OF_ARRAY(ARRAY); (ITERATOR)++)	\
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		BODY
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// 2D cases.
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(minFilter,		minFilterModes,
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(magFilter,		magFilterModes,
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapMode,		wrapModes,
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			filteringGroup2D->addChild(new Vertex2DTextureCase(m_context,
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   name.c_str(), "",
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   minFilterModes[minFilter].mode,
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   magFilterModes[magFilter].mode,
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   wrapModes[wrapMode].mode,
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															   wrapModes[wrapMode].mode));
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		})));
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapSMode,		wrapModes,
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapTMode,		wrapModes,
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wrapGroup2D->addChild(new Vertex2DTextureCase(m_context,
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  name.c_str(), "",
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  GL_LINEAR_MIPMAP_LINEAR,
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  GL_LINEAR,
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  wrapModes[wrapSMode].mode,
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  wrapModes[wrapTMode].mode));
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}));
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Cube map cases.
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(minFilter,		minFilterModes,
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(magFilter,		magFilterModes,
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapMode,		wrapModes,
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			filteringGroupCube->addChild(new VertexCubeTextureCase(m_context,
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   name.c_str(), "",
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   minFilterModes[minFilter].mode,
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   magFilterModes[magFilter].mode,
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   wrapModes[wrapMode].mode,
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																   wrapModes[wrapMode].mode));
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		})));
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapSMode,		wrapModes,
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FOR_EACH(wrapTMode,		wrapModes,
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wrapGroupCube->addChild(new VertexCubeTextureCase(m_context,
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  name.c_str(), "",
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  GL_LINEAR_MIPMAP_LINEAR,
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  GL_LINEAR,
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  wrapModes[wrapSMode].mode,
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															  wrapModes[wrapTMode].mode));
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}));
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles2
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1153