1e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/*-------------------------------------------------------------------------
2e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * drawElements Quality Program OpenGL ES 3.0 Module
3e9629bad30a9f478b336ab46b8e6e02f7f87af46Evan Chu * -------------------------------------------------
4e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *
5e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * Copyright 2014 The Android Open Source Project
6e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *
7e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
8e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * you may not use this file except in compliance with the License.
9e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * You may obtain a copy of the License at
10e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *
11e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
12e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *
13e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
14e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
15e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * See the License for the specific language governing permissions and
17e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * limitations under the License.
18e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *
195c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen *//*!
20e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * \file
21e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * \brief Transform feedback tests.
22e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project *//*--------------------------------------------------------------------*/
23e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
24e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "es3fTransformFeedbackTests.hpp"
25e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuTestLog.hpp"
26e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuSurface.hpp"
27e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuImageCompare.hpp"
28e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuVector.hpp"
29e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuFormatUtil.hpp"
30e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "tcuRenderTarget.hpp"
31e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluShaderUtil.hpp"
32e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluVarType.hpp"
33e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluVarTypeUtil.hpp"
34e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluPixelTransfer.hpp"
35e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluRenderContext.hpp"
36e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluShaderProgram.hpp"
37e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "gluObjectWrapper.hpp"
38e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "glwFunctions.hpp"
39e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "glwEnums.hpp"
40e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "deRandom.hpp"
41e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "deStringUtil.hpp"
42e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "deMemory.h"
43e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "deString.h"
44e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
45e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <set>
46e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <map>
47e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <algorithm>
48e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
49e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing std::string;
50e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing std::vector;
51e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing std::set;
52e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
53e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing std::map;
54e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing std::set;
55e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
56e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectusing tcu::TestLog;
57e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
58e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectnamespace deqp
59e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
60e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectnamespace gles3
61e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
62e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectnamespace Functional
63e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
64e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectnamespace TransformFeedback
65e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
66e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
67e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectenum
68e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
69e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	VIEWPORT_WIDTH			= 128,
70e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	VIEWPORT_HEIGHT			= 128,
71e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	BUFFER_GUARD_MULTIPLIER = 2		//!< stride*BUFFER_GUARD_MULTIPLIER bytes are added to the end of tf buffer and used to check for overruns.
72e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
73e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
74e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectenum Interpolation
75e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
76e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	INTERPOLATION_SMOOTH = 0,
77e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	INTERPOLATION_FLAT,
78e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	INTERPOLATION_CENTROID,
79e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
80e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	INTERPOLATION_LAST
81e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
82e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
83e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic const char* getInterpolationName (Interpolation interp)
84e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
85e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (interp)
86e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
87e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case INTERPOLATION_SMOOTH:		return "smooth";
88e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case INTERPOLATION_FLAT:		return "flat";
895c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case INTERPOLATION_CENTROID:	return "centroid";
90e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		default:
91e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			DE_ASSERT(false);
92e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return DE_NULL;
93e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
94e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
95e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
96e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct Varying
97e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
98e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						Varying				(const char* name_, const glu::VarType& type_, Interpolation interp_)
99e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							: name			(name_)
100e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							, type			(type_)
1015c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen							, interpolation	(interp_)
102e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						{
103e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						}
104e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
105e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string			name;				//!< Variable name.
106e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::VarType		type;				//!< Variable type.
107e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	Interpolation		interpolation;		//!< Interpolation mode (smooth, flat, centroid).
108e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
109e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
110e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct VaryingNameEquals
111e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
112e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					VaryingNameEquals	(const std::string& name_) : name(name_) {}
113e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool			operator()			(const Varying& var) const { return var.name == name; }
114e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
115e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string		name;
116e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
117e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
118e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct Attribute
119e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
120e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	Attribute (const std::string& name_, const glu::VarType& type_, int offset_)
121e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		: name		(name_)
122e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		, type		(type_)
123e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		, offset	(offset_)
124e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
125e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
126e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
127e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string			name;
128e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::VarType		type;
129e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int					offset;
130e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
131e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
132e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct AttributeNameEquals
133e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
134e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					AttributeNameEquals	(const std::string& name_) : name(name_) {}
135e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool			operator()			(const Attribute& attr) const { return attr.name == name; }
136e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
137e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string		name;
138e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
1395c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
1405c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenenstruct Output
141a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu{
142a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu	Output (void)
143a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu		: bufferNdx	(0)
144a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu		, offset	(0)
145a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu	{
146a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu	}
147a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu
148e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string					name;
149e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::VarType				type;
150e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int							bufferNdx;
151e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int							offset;
152e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<const Attribute*>	inputs;
153e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
154e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
155e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct DrawCall
156e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
157e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				DrawCall (int numElements_, bool tfEnabled_)
158e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					: numElements				(numElements_)
159e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					, transformFeedbackEnabled	(tfEnabled_)
160e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
161e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
162e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
163e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				DrawCall (void)
164e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					: numElements				(0)
165e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					, transformFeedbackEnabled	(false)
166e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
167e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
168e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
169e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int			numElements;
170e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool		transformFeedbackEnabled;
171e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
172e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
173e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstd::ostream& operator<< (std::ostream& str, const DrawCall& call)
174e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
175e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return str << "(" << call.numElements << ", " << (call.transformFeedbackEnabled ? "resumed" : "paused") << ")";
176e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
177e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
178e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectclass ProgramSpec
179e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
180e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectpublic:
181e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project									ProgramSpec						(void);
182e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project									~ProgramSpec					(void);
1835c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
184e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::StructType*				createStruct					(const char* name);
185e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	void							addVarying						(const char* name, const glu::VarType& type, Interpolation interp);
186e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	void							addTransformFeedbackVarying		(const char* name);
187e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
188e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const vector<glu::StructType*>&	getStructs						(void) const { return m_structs;	}
189e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const vector<Varying>&			getVaryings						(void) const { return m_varyings;	}
190e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const vector<string>&			getTransformFeedbackVaryings	(void) const { return m_transformFeedbackVaryings; }
191e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool							isPointSizeUsed					(void) const;
192e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
193e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectprivate:
194e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project									ProgramSpec						(const ProgramSpec& other);
195e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ProgramSpec&					operator=						(const ProgramSpec& other);
196e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
197e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<glu::StructType*>		m_structs;
198e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<Varying>					m_varyings;
199e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<string>					m_transformFeedbackVaryings;
200e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
201e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
202e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project// ProgramSpec
203e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
204e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source ProjectProgramSpec::ProgramSpec (void)
205e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
206e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
207e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
208e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source ProjectProgramSpec::~ProgramSpec (void)
209e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
210e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<glu::StructType*>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
211e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		delete *i;
212e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
213e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
214e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectglu::StructType* ProgramSpec::createStruct (const char* name)
215e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
216e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_structs.reserve(m_structs.size()+1);
217e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_structs.push_back(new glu::StructType(name));
218e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return m_structs.back();
219e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
220e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
221e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectvoid ProgramSpec::addVarying (const char* name, const glu::VarType& type, Interpolation interp)
222e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
223e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_varyings.push_back(Varying(name, type, interp));
224e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
225e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
226e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectvoid ProgramSpec::addTransformFeedbackVarying (const char* name)
227e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
228e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_transformFeedbackVaryings.push_back(name);
229e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
230e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
231e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectbool ProgramSpec::isPointSizeUsed (void) const
232e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
233e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return std::find(m_transformFeedbackVaryings.begin(), m_transformFeedbackVaryings.end(), "gl_PointSize") != m_transformFeedbackVaryings.end();
234e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
235e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
236e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic bool isProgramSupported (const glw::Functions& gl, const ProgramSpec& spec, deUint32 tfMode)
237e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
238e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int		maxVertexAttribs			= 0;
239e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int		maxTfInterleavedComponents	= 0;
240e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int		maxTfSeparateAttribs		= 0;
241e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int		maxTfSeparateComponents		= 0;
242e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
243e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS,								&maxVertexAttribs);
244e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,	&maxTfInterleavedComponents);
245e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,			&maxTfSeparateAttribs);
246e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,		&maxTfSeparateComponents);
247e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
248e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Check vertex attribs.
249e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int totalVertexAttribs	= 1 /* a_position */ + (spec.isPointSizeUsed() ? 1 : 0);
250e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
251e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
252e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type); vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
253e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			totalVertexAttribs += 1;
254e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
255e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
256e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (totalVertexAttribs > maxVertexAttribs)
257e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return false; // Vertex attribute count exceeded.
258e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
259e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Check varyings.
260e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int totalTfComponents	= 0;
261e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int totalTfAttribs		= 0;
262e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<string>::const_iterator iter = spec.getTransformFeedbackVaryings().begin(); iter != spec.getTransformFeedbackVaryings().end(); iter++)
263e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
264e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const string&	name			= *iter;
265e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				numComponents	= 0;
266e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
267e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (name == "gl_Position")
268e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			numComponents = 4;
269e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		else if (name == "gl_PointSize")
270e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			numComponents = 1;
271e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		else
272e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
273e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			string						varName		= glu::parseVariableName(name.c_str());
274e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const Varying&				varying		= *std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
275e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::TypeComponentVector	varPath;
276e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
277e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::parseTypePath(name.c_str(), varying.type, varPath);
278e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			numComponents = glu::getVarType(varying.type, varPath).getScalarSize();
279e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
280e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
281e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (tfMode == GL_SEPARATE_ATTRIBS && numComponents > maxTfSeparateComponents)
282e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return false; // Per-attribute component count exceeded.
283e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
284e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		totalTfComponents	+= numComponents;
285e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		totalTfAttribs		+= 1;
286e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
287e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
288e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (tfMode == GL_SEPARATE_ATTRIBS && totalTfAttribs > maxTfSeparateAttribs)
289e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return false;
290e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
291e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (tfMode == GL_INTERLEAVED_ATTRIBS && totalTfComponents > maxTfInterleavedComponents)
292e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return false;
293e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
294e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return true;
295e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
296e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
297e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project// Program
298e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
299e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic std::string getAttributeName (const char* varyingName, const glu::TypeComponentVector& path)
300e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
301e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::ostringstream str;
302e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
303e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	str << "a_" << (deStringBeginsWith(varyingName, "v_") ? varyingName+2 : varyingName);
304e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
305e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (glu::TypeComponentVector::const_iterator iter = path.begin(); iter != path.end(); iter++)
306e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
307e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const char* prefix = DE_NULL;
308e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
309e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		switch (iter->type)
310e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
311e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			case glu::VarTypeComponent::STRUCT_MEMBER:		prefix = "_m";	break;
312e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			case glu::VarTypeComponent::ARRAY_ELEMENT:		prefix = "_e";	break;
313e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			case glu::VarTypeComponent::MATRIX_COLUMN:		prefix = "_c";	break;
314e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			case glu::VarTypeComponent::VECTOR_COMPONENT:	prefix = "_s";	break;
315e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			default:
316e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				DE_ASSERT(false);
317e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
318e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
319e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		str << prefix << iter->index;
320e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
321e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
322e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return str.str();
323e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
324e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
325e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void genShaderSources (const ProgramSpec& spec, std::string& vertSource, std::string& fragSource, bool pointSizeRequired)
326e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
327e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::ostringstream	vtx;
328e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::ostringstream	frag;
329e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool				addPointSize	= spec.isPointSizeUsed();
330e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
331e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vtx << "#version 300 es\n"
332e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		<< "in highp vec4 a_position;\n";
333e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	frag << "#version 300 es\n"
334e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 << "layout(location = 0) out mediump vec4 o_color;\n"
335e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 << "uniform highp vec4 u_scale;\n"
336e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 << "uniform highp vec4 u_bias;\n";
337e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
338e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (addPointSize)
339e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		vtx << "in highp float a_pointSize;\n";
340e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
341e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Declare attributes.
342e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
343e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
344e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const char*			name	= var->name.c_str();
345e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const glu::VarType&	type	= var->type;
346e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
347e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type); vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
348e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
349e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::VarType	attribType	= glu::getVarType(type, vecIter.getPath());
350e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			string			attribName	= getAttributeName(name, vecIter.getPath());
351e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
352e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			vtx << "in " << glu::declare(attribType, attribName.c_str()) << ";\n";
353e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
354e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
355e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
356e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Declare vayrings.
357e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int ndx = 0; ndx < 2; ndx++)
358e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
359e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const char*			inout	= ndx ? "in" : "out";
360e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		std::ostringstream&	str		= ndx ? frag : vtx;
361e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
362e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// Declare structs that have type name.
363e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (vector<glu::StructType*>::const_iterator structIter = spec.getStructs().begin(); structIter != spec.getStructs().end(); structIter++)
364e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
365e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const glu::StructType* structPtr = *structIter;
366e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (structPtr->hasTypeName())
367e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				str << glu::declare(structPtr) << ";\n";
368e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
369e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
370e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
371e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			str << getInterpolationName(var->interpolation) << " " << inout << " " << glu::declare(var->type, var->name.c_str()) << ";\n";
372e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
373e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
374e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vtx << "\nvoid main (void)\n{\n"
375e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		<< "\tgl_Position = a_position;\n";
376e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	frag << "\nvoid main (void)\n{\n"
377e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 << "\thighp vec4 res = vec4(0.0);\n";
378c95c79ccb65d82a65b960919077d5c359cf28cedEvan Chu
379e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (addPointSize)
380e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		vtx << "\tgl_PointSize = a_pointSize;\n";
381e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	else if (pointSizeRequired)
382e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		vtx << "\tgl_PointSize = 1.0;\n";
383e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
384e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Generate assignments / usage.
385e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
386e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
387e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const char*			name	= var->name.c_str();
388e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const glu::VarType&	type	= var->type;
389e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
390e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type); vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
391e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
392e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::VarType	subType		= glu::getVarType(type, vecIter.getPath());
393e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			string			attribName	= getAttributeName(name, vecIter.getPath());
394e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
395e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			DE_ASSERT(subType.isBasicType() && glu::isDataTypeScalarOrVector(subType.getBasicType()));
396e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
397e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			// Vertex: assign from attribute.
398e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			vtx << "\t" << name << vecIter << " = " << attribName << ";\n";
399e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
400e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			// Fragment: add to res variable.
401e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int scalarSize = glu::getDataTypeScalarSize(subType.getBasicType());
402e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
403e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			frag << "\tres += ";
404e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (scalarSize == 1)		frag << "vec4(" << name << vecIter << ")";
405e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (scalarSize == 2)	frag << "vec2(" << name << vecIter << ").xxyy";
406e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (scalarSize == 3)	frag << "vec3(" << name << vecIter << ").xyzx";
407e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (scalarSize == 4)	frag << "vec4(" << name << vecIter << ")";
408e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
409e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			frag << ";\n";
410e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
411e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
412e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
413e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	frag << "\to_color = res * u_scale + u_bias;\n";
414e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
415e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vtx << "}\n";
416e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	frag << "}\n";
417e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
418e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vertSource = vtx.str();
419e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	fragSource = frag.str();
420e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
421e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
422e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic glu::ShaderProgram* createVertexCaptureProgram (const glu::RenderContext& context, const ProgramSpec& spec, deUint32 bufferMode, deUint32 primitiveType)
423e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
424e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string vertSource, fragSource;
425e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
426e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	genShaderSources(spec, vertSource, fragSource, primitiveType == GL_POINTS /* Is point size required? */);
427e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
428e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return new glu::ShaderProgram(context, glu::ProgramSources()
429e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project										   << glu::VertexSource(vertSource)
430e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project										   << glu::FragmentSource(fragSource)
431e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project										   << glu::TransformFeedbackVaryings<vector<string>::const_iterator>(spec.getTransformFeedbackVaryings().begin(), spec.getTransformFeedbackVaryings().end())
432e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project										   << glu::TransformFeedbackMode(bufferMode));
433e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
434e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
435e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project// Helpers.
436e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
437e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void computeInputLayout (vector<Attribute>& attributes, int& inputStride, const vector<Varying>& varyings, bool usePointSize)
438e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
439e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	inputStride = 0;
440e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
441e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Add position.
442e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	attributes.push_back(Attribute("a_position", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), inputStride));
443e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	inputStride += 4*sizeof(deUint32);
444e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
445e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (usePointSize)
446e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
447e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		attributes.push_back(Attribute("a_pointSize", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), inputStride));
448e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		inputStride += 1*sizeof(deUint32);
449e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
450e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
451e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Compute attribute vector.
452e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Varying>::const_iterator var = varyings.begin(); var != varyings.end(); var++)
453e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
454e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type); vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
455e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
456e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::VarType	type	= vecIter.getType();
457e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			string			name	= getAttributeName(var->name.c_str(), vecIter.getPath());
458e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
459e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			attributes.push_back(Attribute(name, type, inputStride));
460e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			inputStride += glu::getDataTypeScalarSize(type.getBasicType())*sizeof(deUint32);
461e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
462e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
463e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
464e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
465e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void computeTransformFeedbackOutputs (vector<Output>& transformFeedbackOutputs, const vector<Attribute>& attributes, const vector<Varying>& varyings, const vector<string>& transformFeedbackVaryings, deUint32 bufferMode)
466e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
467e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int accumulatedSize = 0;
468e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
469e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	transformFeedbackOutputs.resize(transformFeedbackVaryings.size());
470e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int varNdx = 0; varNdx < (int)transformFeedbackVaryings.size(); varNdx++)
471e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
472e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const string&	name		= transformFeedbackVaryings[varNdx];
473e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				bufNdx		= (bufferMode == GL_SEPARATE_ATTRIBS ? varNdx : 0);
474e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				offset		= (bufferMode == GL_SEPARATE_ATTRIBS ? 0 : accumulatedSize);
475e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		Output&			output		= transformFeedbackOutputs[varNdx];
476e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
477e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		output.name			= name;
478e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		output.bufferNdx	= bufNdx;
479e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		output.offset		= offset;
480e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
481e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (name == "gl_Position")
482e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
483e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const Attribute* posIn = &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position")));
484e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			output.type = posIn->type;
485e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			output.inputs.push_back(posIn);
486e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
487e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		else if (name == "gl_PointSize")
488e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
489e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const Attribute* sizeIn = &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize")));
490e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			output.type = sizeIn->type;
491e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			output.inputs.push_back(sizeIn);
492e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
493e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		else
494e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
495e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			string						varName		= glu::parseVariableName(name.c_str());
496e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const Varying&				varying		= *std::find_if(varyings.begin(), varyings.end(), VaryingNameEquals(varName));
497e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::TypeComponentVector	varPath;
498e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
499e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			glu::parseTypePath(name.c_str(), varying.type, varPath);
500e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
501e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			output.type = glu::getVarType(varying.type, varPath);
502e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
503e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			// Add all vectorized attributes as inputs.
504e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			for (glu::VectorTypeIterator iter = glu::VectorTypeIterator::begin(&output.type); iter != glu::VectorTypeIterator::end(&output.type); iter++)
505e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
506e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				// Full path.
507e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				glu::TypeComponentVector fullPath(varPath.size() + iter.getPath().size());
508e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
509e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				std::copy(varPath.begin(), varPath.end(), fullPath.begin());
510e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				std::copy(iter.getPath().begin(), iter.getPath().end(), fullPath.begin()+varPath.size());
511e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
512e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				string				attribName	= getAttributeName(varName.c_str(), fullPath);
513e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				const Attribute*	attrib		= &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals(attribName)));
514e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
515e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				output.inputs.push_back(attrib);
516e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
517e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
518e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
519e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		accumulatedSize += output.type.getScalarSize()*sizeof(deUint32);
520e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
521e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
522e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
523e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void genAttributeData (const Attribute& attrib, deUint8* basePtr, int stride, int numElements, de::Random& rnd)
524e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
525e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const int		elementSize	= (int)sizeof(deUint32);
526e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool			isFloat		= glu::isDataTypeFloatOrVec(attrib.type.getBasicType());
527e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool			isInt		= glu::isDataTypeIntOrIVec(attrib.type.getBasicType());
528e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool			isUint		= glu::isDataTypeIntOrIVec(attrib.type.getBasicType());
529e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::Precision	precision	= attrib.type.getPrecision();
530e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int				numComps	= glu::getDataTypeScalarSize(attrib.type.getBasicType());
531e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
532e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int elemNdx = 0; elemNdx < numElements; elemNdx++)
533c95c79ccb65d82a65b960919077d5c359cf28cedEvan Chu	{
534e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (int compNdx = 0; compNdx < numComps; compNdx++)
535e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
536e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int offset = attrib.offset+elemNdx*stride+compNdx*elementSize;
537e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (isFloat)
538e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
539e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				float* comp = (float*)(basePtr+offset);
540e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				switch (precision)
541e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
542e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_LOWP:		*comp = 0.0f + 0.25f*(float)rnd.getInt(0, 4);	break;
543e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_MEDIUMP:	*comp = rnd.getFloat(-1e3f, 1e3f);				break;
544e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_HIGHP:		*comp = rnd.getFloat(-1e5f, 1e5f);				break;
545e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					default:
546e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						DE_ASSERT(false);
547e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
548e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
549e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (isInt)
550e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
551e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				int* comp = (int*)(basePtr+offset);
552e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				switch (precision)
553e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
554e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_LOWP:		*comp = (int)(rnd.getUint32()&0xff) << 24 >> 24;	break;
555e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_MEDIUMP:	*comp = (int)(rnd.getUint32()&0xffff) << 16 >> 16;	break;
556e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_HIGHP:		*comp = (int)rnd.getUint32();						break;
557e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					default:
558e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						DE_ASSERT(false);
559e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
560e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
561e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (isUint)
562e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
563e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				deUint32* comp = (deUint32*)(basePtr+offset);
564e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				switch (precision)
565e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
566e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_LOWP:		*comp = rnd.getUint32()&0xff;	break;
567e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_MEDIUMP:	*comp = rnd.getUint32()&0xffff;	break;
568e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					case glu::PRECISION_HIGHP:		*comp = rnd.getUint32();		break;
569e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					default:
570e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						DE_ASSERT(false);
571e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
572e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
573e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
574e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
575e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
576e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
577e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void genInputData (const vector<Attribute>& attributes, int numInputs, int inputStride, deUint8* inputBasePtr, de::Random& rnd)
578e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
579e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Random positions.
580e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const Attribute& position = *std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position"));
581e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
582e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int ndx = 0; ndx < numInputs; ndx++)
583e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
584e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint8* ptr = inputBasePtr + position.offset + inputStride*ndx;
585e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		*((float*)(ptr+ 0)) = rnd.getFloat(-1.2f, 1.2f);
586e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		*((float*)(ptr+ 4)) = rnd.getFloat(-1.2f, 1.2f);
587e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		*((float*)(ptr+ 8)) = rnd.getFloat(-1.2f, 1.2f);
588e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		*((float*)(ptr+12)) = rnd.getFloat(0.1f, 2.0f);
589e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
590e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
591e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Point size.
592e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<Attribute>::const_iterator pointSizePos = std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize"));
593e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (pointSizePos != attributes.end())
594e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
595e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (int ndx = 0; ndx < numInputs; ndx++)
596e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
597e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			deUint8* ptr = inputBasePtr + pointSizePos->offset + inputStride*ndx;
598e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			*((float*)ptr) = rnd.getFloat(1.0f, 8.0f);
599e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
600e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
601e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
602e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Random data for rest of components.
603e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Attribute>::const_iterator attrib = attributes.begin(); attrib != attributes.end(); attrib++)
604e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
605e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (attrib->name == "a_position" || attrib->name == "a_pointSize")
606e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			continue;
607e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
608e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		genAttributeData(*attrib, inputBasePtr, inputStride, numInputs, rnd);
609e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
610e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
611e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
612e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic deUint32 getTransformFeedbackOutputCount (deUint32 primitiveType, int numElements)
613e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
614e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (primitiveType)
615e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
616e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLES:			return numElements - numElements%3;
617e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_STRIP:		return de::max(0, numElements-2)*3;
618e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_FAN:		return de::max(0, numElements-2)*3;
619e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINES:				return numElements - numElements%2;
620e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_STRIP:			return de::max(0, numElements-1)*2;
621e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_LOOP:			return numElements > 1 ? numElements*2 : 0;
622e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_POINTS:				return numElements;
623e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
624e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		default:
625e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			DE_ASSERT(false);
626e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return 0;
627e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
628e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
629e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
630e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic deUint32 getTransformFeedbackPrimitiveCount (deUint32 primitiveType, int numElements)
631e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
632e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (primitiveType)
633e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
634e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLES:			return numElements/3;
635e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_STRIP:		return de::max(0, numElements-2);
636e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_FAN:		return de::max(0, numElements-2);
637e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINES:				return numElements/2;
638e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_STRIP:			return de::max(0, numElements-1);
639e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_LOOP:			return numElements > 1 ? numElements : 0;
640e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_POINTS:				return numElements;
641e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
642e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		default:
643e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			DE_ASSERT(false);
644e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return 0;
645e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
646e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
647e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
648e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic deUint32 getTransformFeedbackPrimitiveMode (deUint32 primitiveType)
649e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
6505c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	switch (primitiveType)
6515c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	{
6525c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_TRIANGLES:
6535c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_TRIANGLE_STRIP:
6545c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_TRIANGLE_FAN:
6555c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			return GL_TRIANGLES;
6565c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
6575c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_LINES:
6585c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_LINE_LOOP:
6595c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_LINE_STRIP:
6605c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			return GL_LINES;
6615c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
6625c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		case GL_POINTS:
6635c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			return GL_POINTS;
6645c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
6655c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		default:
6665c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			DE_ASSERT(false);
6675c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			return 0;
668e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
669e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
670e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
671e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int getAttributeIndex (deUint32 primitiveType, int numInputs, int outNdx)
672e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
673e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (primitiveType)
674e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
675e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLES:			return outNdx;
676e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINES:				return outNdx;
677e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_POINTS:				return outNdx;
678e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
679e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_STRIP:
680e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
681e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int triNdx = outNdx/3;
682e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int vtxNdx = outNdx%3;
683e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return (triNdx%2 != 0 && vtxNdx < 2) ? (triNdx+1-vtxNdx) : (triNdx+vtxNdx);
684e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
685e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
686e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_TRIANGLE_FAN:
687e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return (outNdx%3 != 0) ? (outNdx/3 + outNdx%3) : 0;
688e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
689e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_STRIP:
690e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return outNdx/2 + outNdx%2;
691e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
692e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		case GL_LINE_LOOP:
693e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
694e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int inNdx = outNdx/2 + outNdx%2;
695e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return inNdx < numInputs ? inNdx : 0;
696e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
697e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
698e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		default:
699e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			DE_ASSERT(false);
700e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return 0;
701e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
702e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
703e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
704e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic bool compareTransformFeedbackOutput (tcu::TestLog& log, deUint32 primitiveType, const Output& output, int numInputs, const deUint8* inBasePtr, int inStride, const deUint8* outBasePtr, int outStride)
705e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
706e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool		isOk		= true;
707e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int			outOffset	= output.offset;
708e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
709e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int attrNdx = 0; attrNdx < (int)output.inputs.size(); attrNdx++)
710e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
711e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const Attribute&	attribute		= *output.inputs[attrNdx];
712e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glu::DataType		type			= attribute.type.getBasicType();
713e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int					numComponents	= glu::getDataTypeScalarSize(type);
714e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glu::Precision		precision		= attribute.type.getPrecision();
715e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glu::DataType		scalarType		= glu::getDataTypeScalarType(type);
716e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int					numOutputs		= getTransformFeedbackOutputCount(primitiveType, numInputs);
717e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
718e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (int outNdx = 0; outNdx < numOutputs; outNdx++)
719e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
720e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int inNdx = getAttributeIndex(primitiveType, numInputs, outNdx);
721e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
722e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			for (int compNdx = 0; compNdx < numComponents; compNdx++)
723e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
724e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				const deUint8*	inPtr	= inBasePtr + inStride*inNdx + attribute.offset + compNdx*sizeof(deUint32);
725e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				const deUint8*	outPtr	= outBasePtr + outStride*outNdx + outOffset + compNdx*sizeof(deUint32);
726e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				deUint32		inVal	= *(const deUint32*)inPtr;
727e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				deUint32		outVal	= *(const deUint32*)outPtr;
728e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				bool			isEqual	= false;
729e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
730e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				if (scalarType == glu::TYPE_FLOAT)
731e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
732e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					// ULP comparison is used for highp and mediump. Lowp uses threshold-comparison.
733e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					switch (precision)
734e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					{
735e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						case glu::PRECISION_HIGHP:		isEqual = de::abs((int)inVal - (int)outVal) < 2;				break;
736e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						case glu::PRECISION_MEDIUMP:	isEqual = de::abs((int)inVal - (int)outVal) < 2+(1<<13);		break;
737e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						case glu::PRECISION_LOWP:
738e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						{
739e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							float inF	= *(const float*)inPtr;
740e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							float outF	= *(const float*)outPtr;
741e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							isEqual = de::abs(inF - outF) < 0.1f;
742e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							break;
743e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						}
744e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						default:
745e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project							DE_ASSERT(false);
746e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					}
747e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
748e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				else
749e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					isEqual = (inVal == outVal); // Bit-exact match required for integer types.
750e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
751e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				if (!isEqual)
752e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
753e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					log << TestLog::Message << "Mismatch in " << output.name << " (" << attribute.name << "), output = " << outNdx << ", input = " << inNdx << ", component = " << compNdx << TestLog::EndMessage;
754e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					isOk = false;
755e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					break;
756e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
757e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
758e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
759e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (!isOk)
760e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				break;
761e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
762e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
763e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!isOk)
764e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			break;
765e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
766e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		outOffset += numComponents*sizeof(deUint32);
767e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
768e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
769e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return isOk;
770e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
771e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
772e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int computeTransformFeedbackPrimitiveCount (deUint32 primitiveType, const DrawCall* first, const DrawCall* end)
773e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
774e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int primCount = 0;
775e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
776e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (const DrawCall* call = first; call != end; ++call)
777e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
778e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (call->transformFeedbackEnabled)
779e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			primCount += getTransformFeedbackPrimitiveCount(primitiveType, call->numElements);
780e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
781e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
782e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return primCount;
783e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
784e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
785e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void writeBufferGuard (const glw::Functions& gl, deUint32 target, int bufferSize, int guardSize)
786e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
787e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	deUint8* ptr = (deUint8*)gl.mapBufferRange(target, bufferSize, guardSize, GL_MAP_WRITE_BIT);
788e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (ptr)
789e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deMemset(ptr, 0xcd, guardSize);
790e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.unmapBuffer(target);
791e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "guardband write");
792e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
793e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
794e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic bool verifyGuard (const deUint8* ptr, int guardSize)
795e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
796e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int ndx = 0; ndx < guardSize; ndx++)
797e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
798e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (ptr[ndx] != 0xcd)
799e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return false;
800e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
801e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return true;
802e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
803e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
804e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic void logTransformFeedbackVaryings (TestLog& log, const glw::Functions& gl, deUint32 program)
805e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
806e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int numTfVaryings	= 0;
807e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int	maxNameLen		= 0;
808e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
809e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &numTfVaryings);
810e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxNameLen);
811e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "Query TF varyings");
812e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
813e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_VARYINGS = " << numTfVaryings << TestLog::EndMessage;
814e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
815e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<char> nameBuf(maxNameLen+1);
816e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
817e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int ndx = 0; ndx < numTfVaryings; ndx++)
818e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
819e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glw::GLsizei	size	= 0;
820e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glw::GLenum		type	= 0;
821e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
822e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.getTransformFeedbackVarying(program, ndx, (glw::GLsizei)nameBuf.size(), DE_NULL, &size, &type, &nameBuf[0]);
823e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying()");
824e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
825e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const glu::DataType	dataType	= glu::getDataTypeFromGLType(type);
826e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const std::string	typeName	= dataType != glu::TYPE_LAST ? std::string(glu::getDataTypeName(dataType))
827e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project																	 : (std::string("unknown(") + tcu::toHex(type).toString() + ")");
828e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
829e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		log << TestLog::Message << (const char*)&nameBuf[0] << ": " << typeName << "[" << size << "]" << TestLog::EndMessage;
830e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
831e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
832e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
833e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectclass TransformFeedbackCase : public TestCase
834e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
835e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectpublic:
836e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project								TransformFeedbackCase		(Context& context, const char* name, const char* desc, deUint32 bufferMode, deUint32 primitiveType);
837e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project								~TransformFeedbackCase		(void);
838e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
839e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	void						init						(void);
840e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	void						deinit						(void);
841e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	IterateResult				iterate						(void);
842e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
843e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectprotected:
844e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ProgramSpec					m_progSpec;
845e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	deUint32					m_bufferMode;
846e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	deUint32					m_primitiveType;
847e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
848e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectprivate:
849e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project								TransformFeedbackCase		(const TransformFeedbackCase& other);
850e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	TransformFeedbackCase&		operator=					(const TransformFeedbackCase& other);
851e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
852e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool						runTest						(const DrawCall* first, const DrawCall* end, deUint32 seed);
853e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
854e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Derived from ProgramSpec in init()
855e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int							m_inputStride;
856e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<Attribute>			m_attributes;
857e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<Output>				m_transformFeedbackOutputs;
858e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<int>					m_bufferStrides;
859e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
860e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// GL state.
861e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::ShaderProgram*			m_program;
862e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::TransformFeedback*		m_transformFeedback;
863e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<deUint32>			m_outputBuffers;
864e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
865e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int							m_iterNdx;
866e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
867e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
868e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source ProjectTransformFeedbackCase::TransformFeedbackCase (Context& context, const char* name, const char* desc, deUint32 bufferMode, deUint32 primitiveType)
869e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	: TestCase				(context, name, desc)
870e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_bufferMode			(bufferMode)
871e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_primitiveType		(primitiveType)
872e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_inputStride			(0)
873e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_program				(DE_NULL)
874e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_transformFeedback	(DE_NULL)
875e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	, m_iterNdx				(0)
876e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
877e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
878e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
879e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source ProjectTransformFeedbackCase::~TransformFeedbackCase (void)
880e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
881e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	TransformFeedbackCase::deinit();
882e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
883e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
884e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic bool hasArraysInTFVaryings (const ProgramSpec& spec)
885e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
886e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<string>::const_iterator tfVar = spec.getTransformFeedbackVaryings().begin(); tfVar != spec.getTransformFeedbackVaryings().end(); ++tfVar)
887e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
888e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		string							varName	= glu::parseVariableName(tfVar->c_str());
889e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		vector<Varying>::const_iterator	varIter	= std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
890e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
891e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (varName == "gl_Position" || varName == "gl_PointSize")
892e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			continue;
893e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
894e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		DE_ASSERT(varIter != spec.getVaryings().end());
895e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
896e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (varIter->type.isArrayType())
897e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			return true;
898e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
899e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
900e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return false;
901e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
902a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu
903e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectvoid TransformFeedbackCase::init (void)
904e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
905e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	TestLog&				log	= m_testCtx.getLog();
906e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
907e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
908e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	DE_ASSERT(!m_program);
909e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_program = createVertexCaptureProgram(m_context.getRenderContext(), m_progSpec, m_bufferMode, m_primitiveType);
910a24be4f06674b2707b57904deaa0dff5a95823bdEvan Chu
911e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	log << *m_program;
9125c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	if (!m_program->isOk())
9135c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	{
9145c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		const bool linkFail = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk &&
9155c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen							  m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk &&
9165c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen							  !m_program->getProgramInfo().linkOk;
9175c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen
9185c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		if (linkFail)
9195c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen		{
9205c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			if (!isProgramSupported(gl, m_progSpec, m_bufferMode))
9215c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen				throw tcu::NotSupportedError("Implementation limits execeeded", "", __FILE__, __LINE__);
9225c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			else if (hasArraysInTFVaryings(m_progSpec))
9235c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen				throw tcu::NotSupportedError("Capturing arrays is not supported (undefined in specification)", "", __FILE__, __LINE__);
9245c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen			else
9255c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen				throw tcu::TestError("Link failed", "", __FILE__, __LINE__);
926e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
927e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		else
928e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			throw tcu::TestError("Compile failed", "", __FILE__, __LINE__);
929e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
930e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
9315c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	log << TestLog::Message << "Transform feedback varyings: " << tcu::formatArray(m_progSpec.getTransformFeedbackVaryings().begin(), m_progSpec.getTransformFeedbackVaryings().end()) << TestLog::EndMessage;
932e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
933e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Print out transform feedback points reported by GL.
934e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	log << TestLog::Message << "Transform feedback varyings reported by compiler:" << TestLog::EndMessage;
935e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	logTransformFeedbackVaryings(log, gl, m_program->getProgram());
936e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
937e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Compute input specification.
938e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	computeInputLayout(m_attributes, m_inputStride, m_progSpec.getVaryings(), m_progSpec.isPointSizeUsed());
939e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
940e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Build list of varyings used in transform feedback.
9415c65c3a0f42e174e47fecd4e569606003217ff4eMartijn Coenen	computeTransformFeedbackOutputs(m_transformFeedbackOutputs, m_attributes, m_progSpec.getVaryings(), m_progSpec.getTransformFeedbackVaryings(), m_bufferMode);
942e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	DE_ASSERT(!m_transformFeedbackOutputs.empty());
943e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
944e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Buffer strides.
945e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	DE_ASSERT(m_bufferStrides.empty());
946e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (m_bufferMode == GL_SEPARATE_ATTRIBS)
947e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
948e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin(); outIter != m_transformFeedbackOutputs.end(); outIter++)
949e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			m_bufferStrides.push_back(outIter->type.getScalarSize()*sizeof(deUint32));
950e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
951e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	else
952e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
953e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int totalSize = 0;
954e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin(); outIter != m_transformFeedbackOutputs.end(); outIter++)
955e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			totalSize += outIter->type.getScalarSize()*sizeof(deUint32);
956e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
957e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_bufferStrides.push_back(totalSize);
958e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
959e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
960e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// \note Actual storage is allocated in iterate().
961e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_outputBuffers.resize(m_bufferStrides.size());
962e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.genBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
963e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
964e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	DE_ASSERT(!m_transformFeedback);
965e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_transformFeedback = new glu::TransformFeedback(m_context.getRenderContext());
966e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
967e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "init");
968e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
969e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_iterNdx = 0;
970e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
971e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
972e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
97385b7e84f6cc61506c94e98844cac9ce50bbbe9dcEvan Chuvoid TransformFeedbackCase::deinit (void)
974e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
975e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
976e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
977e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!m_outputBuffers.empty())
978e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
979e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.deleteBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
980e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_outputBuffers.clear();
981e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
982e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
983e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	delete m_transformFeedback;
984e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_transformFeedback = DE_NULL;
985e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
986e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	delete m_program;
987e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_program = DE_NULL;
988e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
989e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Clean up state.
99085b7e84f6cc61506c94e98844cac9ce50bbbe9dcEvan Chu	m_attributes.clear();
99185b7e84f6cc61506c94e98844cac9ce50bbbe9dcEvan Chu	m_transformFeedbackOutputs.clear();
992e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_bufferStrides.clear();
993e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_inputStride = 0;
994e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
995e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
996e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source ProjectTransformFeedbackCase::IterateResult TransformFeedbackCase::iterate (void)
997e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
998e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Test cases.
999e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_elemCount1[]	= { DrawCall(1, true) };
1000e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_elemCount2[]	= { DrawCall(2, true) };
1001e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_elemCount3[]	= { DrawCall(3, true) };
1002e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_elemCount4[]	= { DrawCall(4, true) };
1003e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_elemCount123[]	= { DrawCall(123, true) };
1004e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_basicPause1[]	= { DrawCall(64, true), DrawCall(64, false), DrawCall(64, true) };
1005e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_basicPause2[]	= { DrawCall(13, true), DrawCall(5, true), DrawCall(17, false), DrawCall(3, true), DrawCall(7, false) };
1006e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_startPaused[]	= { DrawCall(123, false), DrawCall(123, true) };
1007e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_random1[]		= { DrawCall(65, true), DrawCall(135, false), DrawCall(74, true), DrawCall(16, false), DrawCall(226, false), DrawCall(9, true), DrawCall(174, false) };
1008e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const DrawCall s_random2[]		= { DrawCall(217, true), DrawCall(171, true), DrawCall(147, true), DrawCall(152, false), DrawCall(55, true) };
1009e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1010e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	static const struct
1011e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1012e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const DrawCall*		calls;
1013e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int					numCalls;
1014e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	} s_iterations[] =
1015e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1016e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#define ITER(ARR) { ARR, DE_LENGTH_OF_ARRAY(ARR) }
1017e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_elemCount1),
1018e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_elemCount2),
1019e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_elemCount3),
1020e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_elemCount4),
1021e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_elemCount123),
1022e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_basicPause1),
102385b7e84f6cc61506c94e98844cac9ce50bbbe9dcEvan Chu		ITER(s_basicPause2),
1024e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_startPaused),
1025e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_random1),
1026e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ITER(s_random2)
1027e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#undef ITER
1028e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	};
1029e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1030e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	TestLog&				log				= m_testCtx.getLog();
1031e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool					isOk			= true;
1032e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	deUint32				seed			= deStringHash(getName()) ^ deInt32Hash(m_iterNdx);
1033e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						numIterations	= DE_LENGTH_OF_ARRAY(s_iterations);
1034e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const DrawCall*			first			= s_iterations[m_iterNdx].calls;
1035e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const DrawCall*			end				= s_iterations[m_iterNdx].calls + s_iterations[m_iterNdx].numCalls;
1036e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1037e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string				sectionName		= std::string("Iteration") + de::toString(m_iterNdx+1);
1038e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	std::string				sectionDesc		= std::string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations);
1039e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tcu::ScopedLogSection	section			(log, sectionName, sectionDesc);
1040e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1041e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	log << TestLog::Message << "Testing " << s_iterations[m_iterNdx].numCalls << " draw calls, (element count, TF state): " << tcu::formatArray(first, end) << TestLog::EndMessage;
1042e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1043e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	isOk = runTest(first, end, seed);
1044e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1045e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!isOk)
1046e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
1047e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1048e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	m_iterNdx += 1;
1049e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return (isOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
1050e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
1051e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1052e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectbool TransformFeedbackCase::runTest (const DrawCall* first, const DrawCall* end, deUint32 seed)
1053e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
1054e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	TestLog&				log				= m_testCtx.getLog();
1055e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
1056e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	de::Random				rnd				(seed);
1057e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						numInputs		= 0;		//!< Sum of element counts in calls.
1058e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						numOutputs		= 0;		//!< Sum of output counts for calls that have transform feedback enabled.
1059e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						width			= m_context.getRenderContext().getRenderTarget().getWidth();
1060e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						height			= m_context.getRenderContext().getRenderTarget().getHeight();
1061e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						viewportW		= de::min((int)VIEWPORT_WIDTH, width);
1062e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						viewportH		= de::min((int)VIEWPORT_HEIGHT, height);
1063e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						viewportX		= rnd.getInt(0, width-viewportW);
1064e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int						viewportY		= rnd.getInt(0, height-viewportH);
1065e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tcu::Surface			frameWithTf		(viewportW, viewportH);
1066e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tcu::Surface			frameWithoutTf	(viewportW, viewportH);
1067e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::Query				primitiveQuery	(m_context.getRenderContext());
1068e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool					outputsOk		= true;
1069e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool					imagesOk		= true;
1070e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	bool					queryOk			= true;
1071e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1072e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Compute totals.
1073e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (const DrawCall* call = first; call != end; call++)
1074e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1075e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		numInputs	+= call->numElements;
1076e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		numOutputs	+= call->transformFeedbackEnabled ? getTransformFeedbackOutputCount(m_primitiveType, call->numElements) : 0;
1077e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1078e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1079e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Input data.
1080e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	vector<deUint8> inputData(m_inputStride*numInputs);
1081e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	genInputData(m_attributes, numInputs, m_inputStride, &inputData[0], rnd);
1082e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1083e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transformFeedback->get());
1084e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback()");
1085e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1086e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Allocate storage for transform feedback output buffers and bind to targets.
1087e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
1088e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1089e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint32		buffer		= m_outputBuffers[bufNdx];
1090e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				stride		= m_bufferStrides[bufNdx];
1091e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				target		= bufNdx;
1092e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				size		= stride*numOutputs;
1093e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				guardSize	= stride*BUFFER_GUARD_MULTIPLIER;
1094e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const deUint32	usage		= GL_DYNAMIC_READ;
1095e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1096e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1097e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size+guardSize, DE_NULL, usage);
1098e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		writeBufferGuard(gl, GL_TRANSFORM_FEEDBACK_BUFFER, size, guardSize);
1099e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1100e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// \todo [2012-07-30 pyry] glBindBufferRange()?
1101e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, target, buffer);
1102e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1103e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "transform feedback buffer setup");
1104e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1105e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1106e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Setup attributes.
1107e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (vector<Attribute>::const_iterator attrib = m_attributes.begin(); attrib != m_attributes.end(); attrib++)
1108e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1109e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				loc				= gl.getAttribLocation(m_program->getProgram(), attrib->name.c_str());
1110e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glu::DataType	scalarType		= glu::getDataTypeScalarType(attrib->type.getBasicType());
1111e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				numComponents	= glu::getDataTypeScalarSize(attrib->type.getBasicType());
1112e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const void*		ptr				= &inputData[0] + attrib->offset;
1113e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1114e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (loc >= 0)
1115e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1116e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			gl.enableVertexAttribArray(loc);
1117e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1118e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (scalarType == glu::TYPE_FLOAT)		gl.vertexAttribPointer	(loc, numComponents, GL_FLOAT, GL_FALSE, m_inputStride, ptr);
1119e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (scalarType == glu::TYPE_INT)	gl.vertexAttribIPointer	(loc, numComponents, GL_INT, m_inputStride, ptr);
1120e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			else if (scalarType == glu::TYPE_UINT)	gl.vertexAttribIPointer	(loc, numComponents, GL_UNSIGNED_INT, m_inputStride, ptr);
1121e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1122e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1123e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1124e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Setup viewport.
1125e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.viewport(viewportX, viewportY, viewportW, viewportH);
1126e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1127e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Setup program.
1128e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.useProgram(m_program->getProgram());
1129e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1130e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_scale"),	1, tcu::Vec4(0.01f).getPtr());
1131e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_bias"),		1, tcu::Vec4(0.5f).getPtr());
1132e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1133e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Enable query.
1134e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, *primitiveQuery);
1135e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
1136e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1137e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Draw.
1138e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1139e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int		offset		= 0;
1140e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		bool	tfEnabled	= true;
1141e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1142e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.clear(GL_COLOR_BUFFER_BIT);
1143e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1144e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.beginTransformFeedback(getTransformFeedbackPrimitiveMode(m_primitiveType));
1145e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1146e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (const DrawCall* call = first; call != end; call++)
1147e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1148e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			// Pause or resume transform feedback if necessary.
1149e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (call->transformFeedbackEnabled != tfEnabled)
1150e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
1151e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				if (call->transformFeedbackEnabled)
1152e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					gl.resumeTransformFeedback();
1153e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				else
1154e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					gl.pauseTransformFeedback();
1155e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				tfEnabled = call->transformFeedbackEnabled;
1156e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
1157e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1158e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			gl.drawArrays(m_primitiveType, offset, call->numElements);
1159e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			offset += call->numElements;
1160e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1161e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1162e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// Resume feedback before finishing it.
1163e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!tfEnabled)
1164e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			gl.resumeTransformFeedback();
1165e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1166e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.endTransformFeedback();
1167e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "render");
1168e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1169e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1170e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
1171e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
1172e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1173e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Check and log query status right after submit
1174e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1175e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint32 available = GL_FALSE;
117685b7e84f6cc61506c94e98844cac9ce50bbbe9dcEvan Chu		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
1177e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
1178e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1179e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN status after submit: " << (available != GL_FALSE ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;
1180e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1181e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1182e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Compare result buffers.
1183e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int bufferNdx = 0; bufferNdx < (int)m_outputBuffers.size(); bufferNdx++)
1184e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1185e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint32		buffer		= m_outputBuffers[bufferNdx];
1186e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				stride		= m_bufferStrides[bufferNdx];
1187e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				size		= stride*numOutputs;
1188e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int				guardSize	= stride*BUFFER_GUARD_MULTIPLIER;
1189e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const void*		bufPtr		= DE_NULL;
1190e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1191e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// Bind buffer for reading.
1192e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1193e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		bufPtr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size+guardSize, GL_MAP_READ_BIT);
1194e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "mapping buffer");
1195e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1196e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// Verify all output variables that are written to this buffer.
1197e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (vector<Output>::const_iterator out = m_transformFeedbackOutputs.begin(); out != m_transformFeedbackOutputs.end(); out++)
1198e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1199e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (out->bufferNdx != bufferNdx)
1200e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				continue;
1201e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1202e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int inputOffset		= 0;
1203e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			int	outputOffset	= 0;
1204e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1205e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			// Process all draw calls and check ones with transform feedback enabled.
1206e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			for (const DrawCall* call = first; call != end; call++)
1207e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			{
1208e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				if (call->transformFeedbackEnabled)
1209e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				{
1210e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					const deUint8*	inputPtr	= &inputData[0] + inputOffset*m_inputStride;
1211e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					const deUint8*	outputPtr	= (const deUint8*)bufPtr + outputOffset*stride;
1212e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1213e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					if (!compareTransformFeedbackOutput(log, m_primitiveType, *out, call->numElements, inputPtr, m_inputStride, outputPtr, stride))
1214e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					{
1215e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						outputsOk = false;
1216e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project						break;
1217e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project					}
1218e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				}
1219e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1220e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				inputOffset		+= call->numElements;
1221e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				outputOffset	+= call->transformFeedbackEnabled ? getTransformFeedbackOutputCount(m_primitiveType, call->numElements) : 0;
1222e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
1223e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1224e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1225e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		// Verify guardband.
1226e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!verifyGuard((const deUint8*)bufPtr + size, guardSize))
1227e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1228e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			log << TestLog::Message << "Error: Transform feedback buffer overrun detected" << TestLog::EndMessage;
1229e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			outputsOk = false;
1230e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1231e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1232e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1233e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1234e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1235e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Check status after mapping buffers.
1236e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1237e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const bool	mustBeReady		= !m_outputBuffers.empty(); // Mapping buffer forces synchronization.
1238e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		const int	expectedCount	= computeTransformFeedbackPrimitiveCount(m_primitiveType, first, end);
1239e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint32	available		= GL_FALSE;
1240e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		deUint32	numPrimitives	= 0;
1241e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1242e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
1243e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT, &numPrimitives);
1244e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
1245e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1246e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!mustBeReady && available == GL_FALSE)
1247e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1248e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			log << TestLog::Message << "ERROR: GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN result not available after mapping buffers!" << TestLog::EndMessage;
1249e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			queryOk = false;
1250e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1251e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1252e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = " << numPrimitives << TestLog::EndMessage;
1253e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1254e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if ((int)numPrimitives != expectedCount)
1255e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1256e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			log << TestLog::Message << "ERROR: Expected " << expectedCount << " primitives!" << TestLog::EndMessage;
1257e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			queryOk = false;
1258e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1259e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1260e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1261e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Clear transform feedback state.
1262e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1263e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
1264e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1265e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bindBuffer		(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1266e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.bindBufferBase	(GL_TRANSFORM_FEEDBACK_BUFFER, bufNdx, 0);
1267e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1268e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1269e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Read back rendered image.
1270e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithTf.getAccess());
1271e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1272e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Render without transform feedback.
1273e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1274e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		int offset = 0;
1275e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1276e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		gl.clear(GL_COLOR_BUFFER_BIT);
1277e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1278e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		for (const DrawCall* call = first; call != end; call++)
1279e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
1280e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			gl.drawArrays(m_primitiveType, offset, call->numElements);
1281e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			offset += call->numElements;
1282e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
1283e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1284e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		GLU_EXPECT_NO_ERROR(gl.getError(), "render");
1285e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithoutTf.getAccess());
1286e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1287e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1288e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	// Compare images with and without transform feedback.
1289e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	imagesOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", frameWithoutTf, frameWithTf, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_ON_ERROR);
1290e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1291e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (imagesOk)
1292e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_testCtx.getLog() << TestLog::Message << "Rendering result comparison between TF enabled and TF disabled passed." << TestLog::EndMessage;
1293e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	else
1294e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_testCtx.getLog() << TestLog::Message << "ERROR: Rendering result comparison between TF enabled and TF disabled failed!" << TestLog::EndMessage;
1295e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1296e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return outputsOk && imagesOk && queryOk;
1297e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
1298e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1299e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project// Test cases.
1300e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1301e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectclass PositionCase : public TransformFeedbackCase
1302e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
1303e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectpublic:
1304e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	PositionCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType)
1305e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1306e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	{
1307e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		m_progSpec.addTransformFeedbackVarying("gl_Position");
1308e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
1309e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
1310e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
1311class PointSizeCase : public TransformFeedbackCase
1312{
1313public:
1314	PointSizeCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType)
1315		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1316	{
1317		m_progSpec.addTransformFeedbackVarying("gl_PointSize");
1318	}
1319};
1320
1321class BasicTypeCase : public TransformFeedbackCase
1322{
1323public:
1324	BasicTypeCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
1325		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1326	{
1327		m_progSpec.addVarying("v_varA", glu::VarType(type, precision), interpolation);
1328		m_progSpec.addVarying("v_varB", glu::VarType(type, precision), interpolation);
1329
1330		m_progSpec.addTransformFeedbackVarying("v_varA");
1331		m_progSpec.addTransformFeedbackVarying("v_varB");
1332	}
1333};
1334
1335class BasicArrayCase : public TransformFeedbackCase
1336{
1337public:
1338	BasicArrayCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
1339		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1340	{
1341		if (glu::isDataTypeMatrix(type) || m_bufferMode == GL_SEPARATE_ATTRIBS)
1342		{
1343			// \note For matrix types we need to use reduced array sizes or otherwise we will exceed maximum attribute (16)
1344			//		 or transform feedback component count (64).
1345			//		 On separate attribs mode maximum component count per varying is 4.
1346			m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 1), interpolation);
1347			m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 2), interpolation);
1348		}
1349		else
1350		{
1351			m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
1352			m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
1353		}
1354
1355		m_progSpec.addTransformFeedbackVarying("v_varA");
1356		m_progSpec.addTransformFeedbackVarying("v_varB");
1357	}
1358};
1359
1360class ArrayElementCase : public TransformFeedbackCase
1361{
1362public:
1363	ArrayElementCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, glu::DataType type, glu::Precision precision, Interpolation interpolation)
1364		: TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1365	{
1366		m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
1367		m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
1368
1369		m_progSpec.addTransformFeedbackVarying("v_varA[1]");
1370		m_progSpec.addTransformFeedbackVarying("v_varB[0]");
1371		m_progSpec.addTransformFeedbackVarying("v_varB[3]");
1372	}
1373};
1374
1375class RandomCase : public TransformFeedbackCase
1376{
1377public:
1378	RandomCase (Context& context, const char* name, const char* desc, deUint32 bufferType, deUint32 primitiveType, deUint32 seed)
1379		: TransformFeedbackCase	(context, name, desc, bufferType, primitiveType)
1380		, m_seed				(seed)
1381	{
1382	}
1383
1384	void init (void)
1385	{
1386		// \note Hard-coded indices and hackery are used when indexing this, beware.
1387		static const glu::DataType typeCandidates[] =
1388		{
1389			glu::TYPE_FLOAT,
1390			glu::TYPE_FLOAT_VEC2,
1391			glu::TYPE_FLOAT_VEC3,
1392			glu::TYPE_FLOAT_VEC4,
1393			glu::TYPE_INT,
1394			glu::TYPE_INT_VEC2,
1395			glu::TYPE_INT_VEC3,
1396			glu::TYPE_INT_VEC4,
1397			glu::TYPE_UINT,
1398			glu::TYPE_UINT_VEC2,
1399			glu::TYPE_UINT_VEC3,
1400			glu::TYPE_UINT_VEC4,
1401
1402			glu::TYPE_FLOAT_MAT2,
1403			glu::TYPE_FLOAT_MAT2X3,
1404			glu::TYPE_FLOAT_MAT2X4,
1405
1406			glu::TYPE_FLOAT_MAT3X2,
1407			glu::TYPE_FLOAT_MAT3,
1408			glu::TYPE_FLOAT_MAT3X4,
1409
1410			glu::TYPE_FLOAT_MAT4X2,
1411			glu::TYPE_FLOAT_MAT4X3,
1412			glu::TYPE_FLOAT_MAT4
1413		};
1414
1415		static const glu::Precision precisions[] =
1416		{
1417			glu::PRECISION_LOWP,
1418			glu::PRECISION_MEDIUMP,
1419			glu::PRECISION_HIGHP
1420		};
1421
1422		static const Interpolation interpModes[] =
1423		{
1424			INTERPOLATION_FLAT,
1425			INTERPOLATION_SMOOTH,
1426			INTERPOLATION_CENTROID
1427		};
1428
1429		const int	maxAttributeVectors					= 16;
1430//		const int	maxTransformFeedbackComponents		= 64; // \note It is enough to limit attribute set size.
1431		bool		isSeparateMode						= m_bufferMode == GL_SEPARATE_ATTRIBS;
1432		int			maxTransformFeedbackVars			= isSeparateMode ? 4 : maxAttributeVectors;
1433		const float	arrayWeight							= 0.3f;
1434		const float	positionWeight						= 0.7f;
1435		const float	pointSizeWeight						= 0.1f;
1436		const float	captureFullArrayWeight				= 0.5f;
1437
1438		de::Random	rnd									(m_seed);
1439		bool		usePosition							= rnd.getFloat() < positionWeight;
1440		bool		usePointSize						= rnd.getFloat() < pointSizeWeight;
1441		int			numAttribVectorsToUse				= rnd.getInt(1, maxAttributeVectors - 1/*position*/ - (usePointSize ? 1 : 0));
1442
1443		int			numAttributeVectors					= 0;
1444		int			varNdx								= 0;
1445
1446		// Generate varyings.
1447		while (numAttributeVectors < numAttribVectorsToUse)
1448		{
1449			int						maxVecs		= isSeparateMode ? de::min(2 /*at most 2*mat2*/, numAttribVectorsToUse-numAttributeVectors) : numAttribVectorsToUse-numAttributeVectors;
1450			const glu::DataType*	begin		= &typeCandidates[0];
1451			const glu::DataType*	end			= begin + (maxVecs >= 4 ? 21 :
1452														   maxVecs >= 3 ? 18 :
1453														   maxVecs >= 2 ? (isSeparateMode ? 13 : 15) : 12);
1454
1455			glu::DataType			type		= rnd.choose<glu::DataType>(begin, end);
1456			glu::Precision			precision	= rnd.choose<glu::Precision>(&precisions[0], &precisions[0]+DE_LENGTH_OF_ARRAY(precisions));
1457			Interpolation			interp		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT
1458												? rnd.choose<Interpolation>(&interpModes[0], &interpModes[0]+DE_LENGTH_OF_ARRAY(interpModes))
1459												: INTERPOLATION_FLAT;
1460			int						numVecs		= glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : 1;
1461			int						numComps	= glu::getDataTypeScalarSize(type);
1462			int						maxArrayLen	= de::max(1, isSeparateMode ? 4/numComps : maxVecs/numVecs);
1463			bool					useArray	= rnd.getFloat() < arrayWeight;
1464			int						arrayLen	= useArray ? rnd.getInt(1, maxArrayLen) : 1;
1465			std::string				name		= "v_var" + de::toString(varNdx);
1466
1467			if (useArray)
1468				m_progSpec.addVarying(name.c_str(), glu::VarType(glu::VarType(type, precision), arrayLen), interp);
1469			else
1470				m_progSpec.addVarying(name.c_str(), glu::VarType(type, precision), interp);
1471
1472			numAttributeVectors	+= arrayLen*numVecs;
1473			varNdx				+= 1;
1474		}
1475
1476		// Generate transform feedback candidate set.
1477		vector<string> tfCandidates;
1478
1479		if (usePosition)	tfCandidates.push_back("gl_Position");
1480		if (usePointSize)	tfCandidates.push_back("gl_PointSize");
1481
1482		for (int ndx = 0; ndx < varNdx /* num varyings */; ndx++)
1483		{
1484			const Varying& var = m_progSpec.getVaryings()[ndx];
1485
1486			if (var.type.isArrayType())
1487			{
1488				const bool captureFull = rnd.getFloat() < captureFullArrayWeight;
1489
1490				if (captureFull)
1491					tfCandidates.push_back(var.name);
1492				else
1493				{
1494					const int numElem = var.type.getArraySize();
1495					for (int elemNdx = 0; elemNdx < numElem; elemNdx++)
1496						tfCandidates.push_back(var.name + "[" + de::toString(elemNdx) + "]");
1497				}
1498			}
1499			else
1500				tfCandidates.push_back(var.name);
1501		}
1502
1503		// Pick random selection.
1504		vector<string> tfVaryings(de::min((int)tfCandidates.size(), maxTransformFeedbackVars));
1505		rnd.choose(tfCandidates.begin(), tfCandidates.end(), tfVaryings.begin(), (int)tfVaryings.size());
1506		rnd.shuffle(tfVaryings.begin(), tfVaryings.end());
1507
1508		for (vector<string>::const_iterator var = tfVaryings.begin(); var != tfVaryings.end(); var++)
1509			m_progSpec.addTransformFeedbackVarying(var->c_str());
1510
1511		TransformFeedbackCase::init();
1512	}
1513
1514private:
1515	deUint32 m_seed;
1516};
1517
1518} // TransformFeedback
1519
1520using namespace TransformFeedback;
1521
1522TransformFeedbackTests::TransformFeedbackTests (Context& context)
1523	: TestCaseGroup(context, "transform_feedback", "Transform feedback tests")
1524{
1525}
1526
1527TransformFeedbackTests::~TransformFeedbackTests (void)
1528{
1529}
1530
1531void TransformFeedbackTests::init (void)
1532{
1533	static const struct
1534	{
1535		const char*		name;
1536		deUint32		mode;
1537	} bufferModes[] =
1538	{
1539		{ "separate",		GL_SEPARATE_ATTRIBS		},
1540		{ "interleaved",	GL_INTERLEAVED_ATTRIBS	}
1541	};
1542
1543	static const struct
1544	{
1545		const char*		name;
1546		deUint32		type;
1547	} primitiveTypes[] =
1548	{
1549		{ "points",			GL_POINTS			},
1550		{ "lines",			GL_LINES			},
1551		{ "triangles",		GL_TRIANGLES		}
1552
1553		// Not supported by GLES3.
1554//		{ "line_strip",		GL_LINE_STRIP		},
1555//		{ "line_loop",		GL_LINE_LOOP		},
1556//		{ "triangle_fan",	GL_TRIANGLE_FAN		},
1557//		{ "triangle_strip",	GL_TRIANGLE_STRIP	}
1558	};
1559
1560	static const glu::DataType basicTypes[] =
1561	{
1562		glu::TYPE_FLOAT,
1563		glu::TYPE_FLOAT_VEC2,
1564		glu::TYPE_FLOAT_VEC3,
1565		glu::TYPE_FLOAT_VEC4,
1566		glu::TYPE_FLOAT_MAT2,
1567		glu::TYPE_FLOAT_MAT2X3,
1568		glu::TYPE_FLOAT_MAT2X4,
1569		glu::TYPE_FLOAT_MAT3X2,
1570		glu::TYPE_FLOAT_MAT3,
1571		glu::TYPE_FLOAT_MAT3X4,
1572		glu::TYPE_FLOAT_MAT4X2,
1573		glu::TYPE_FLOAT_MAT4X3,
1574		glu::TYPE_FLOAT_MAT4,
1575		glu::TYPE_INT,
1576		glu::TYPE_INT_VEC2,
1577		glu::TYPE_INT_VEC3,
1578		glu::TYPE_INT_VEC4,
1579		glu::TYPE_UINT,
1580		glu::TYPE_UINT_VEC2,
1581		glu::TYPE_UINT_VEC3,
1582		glu::TYPE_UINT_VEC4
1583	};
1584
1585	static const glu::Precision precisions[] =
1586	{
1587		glu::PRECISION_LOWP,
1588		glu::PRECISION_MEDIUMP,
1589		glu::PRECISION_HIGHP
1590	};
1591
1592	static const struct
1593	{
1594		const char*		name;
1595		Interpolation	interp;
1596	} interpModes[] =
1597	{
1598		{ "smooth",		INTERPOLATION_SMOOTH	},
1599		{ "flat",		INTERPOLATION_FLAT		},
1600		{ "centroid",	INTERPOLATION_CENTROID	}
1601	};
1602
1603	// .position
1604	{
1605		tcu::TestCaseGroup* positionGroup = new tcu::TestCaseGroup(m_testCtx, "position", "gl_Position capture using transform feedback");
1606		addChild(positionGroup);
1607
1608		for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1609		{
1610			for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1611			{
1612				string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
1613				positionGroup->addChild(new PositionCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type));
1614			}
1615		}
1616	}
1617
1618	// .point_size
1619	{
1620		tcu::TestCaseGroup* pointSizeGroup = new tcu::TestCaseGroup(m_testCtx, "point_size", "gl_PointSize capture using transform feedback");
1621		addChild(pointSizeGroup);
1622
1623		for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1624		{
1625			for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1626			{
1627				string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
1628				pointSizeGroup->addChild(new PointSizeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type));
1629			}
1630		}
1631	}
1632
1633	// .basic_type
1634	{
1635		tcu::TestCaseGroup* basicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "basic_types", "Basic types in transform feedback");
1636		addChild(basicTypeGroup);
1637
1638		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1639		{
1640			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1641			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
1642			basicTypeGroup->addChild(modeGroup);
1643
1644			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1645			{
1646				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1647				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
1648				modeGroup->addChild(primitiveGroup);
1649
1650				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1651				{
1652					glu::DataType		type		= basicTypes[typeNdx];
1653					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1654
1655					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1656					{
1657						glu::Precision precision = precisions[precNdx];
1658
1659						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1660						primitiveGroup->addChild(new BasicTypeCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1661					}
1662				}
1663			}
1664		}
1665	}
1666
1667	// .array
1668	{
1669		tcu::TestCaseGroup* arrayGroup = new tcu::TestCaseGroup(m_testCtx, "array", "Capturing whole array in TF");
1670		addChild(arrayGroup);
1671
1672		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1673		{
1674			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1675			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
1676			arrayGroup->addChild(modeGroup);
1677
1678			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1679			{
1680				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1681				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
1682				modeGroup->addChild(primitiveGroup);
1683
1684				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1685				{
1686					glu::DataType		type		= basicTypes[typeNdx];
1687					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1688
1689					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1690					{
1691						glu::Precision precision = precisions[precNdx];
1692
1693						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1694						primitiveGroup->addChild(new BasicArrayCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1695					}
1696				}
1697			}
1698		}
1699	}
1700
1701	// .array_element
1702	{
1703		tcu::TestCaseGroup* arrayElemGroup = new tcu::TestCaseGroup(m_testCtx, "array_element", "Capturing single array element in TF");
1704		addChild(arrayElemGroup);
1705
1706		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1707		{
1708			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1709			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
1710			arrayElemGroup->addChild(modeGroup);
1711
1712			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1713			{
1714				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1715				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
1716				modeGroup->addChild(primitiveGroup);
1717
1718				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1719				{
1720					glu::DataType		type		= basicTypes[typeNdx];
1721					bool				isFloat		= glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1722
1723					for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1724					{
1725						glu::Precision precision = precisions[precNdx];
1726
1727						string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1728						primitiveGroup->addChild(new ArrayElementCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1729					}
1730				}
1731			}
1732		}
1733	}
1734
1735	// .interpolation
1736	{
1737		tcu::TestCaseGroup* interpolationGroup = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Different interpolation modes in transform feedback varyings");
1738		addChild(interpolationGroup);
1739
1740		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(interpModes); modeNdx++)
1741		{
1742			Interpolation		interp		= interpModes[modeNdx].interp;
1743			tcu::TestCaseGroup*	modeGroup	= new tcu::TestCaseGroup(m_testCtx, interpModes[modeNdx].name, "");
1744
1745			interpolationGroup->addChild(modeGroup);
1746
1747			for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1748			{
1749				glu::Precision precision = precisions[precNdx];
1750
1751				for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1752				{
1753					for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1754					{
1755						string name = string(glu::getPrecisionName(precision)) + "_vec4_" + primitiveTypes[primitiveType].name + "_" + bufferModes[bufferMode].name;
1756						modeGroup->addChild(new BasicTypeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode, primitiveTypes[primitiveType].type, glu::TYPE_FLOAT_VEC4, precision, interp));
1757					}
1758				}
1759			}
1760		}
1761	}
1762
1763	// .random
1764	{
1765		tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized transform feedback cases");
1766		addChild(randomGroup);
1767
1768		for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1769		{
1770			tcu::TestCaseGroup* modeGroup	= new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1771			deUint32			bufferMode	= bufferModes[bufferModeNdx].mode;
1772			randomGroup->addChild(modeGroup);
1773
1774			for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1775			{
1776				tcu::TestCaseGroup* primitiveGroup	= new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1777				deUint32			primitiveType	= primitiveTypes[primitiveTypeNdx].type;
1778				modeGroup->addChild(primitiveGroup);
1779
1780				for (int ndx = 0; ndx < 10; ndx++)
1781				{
1782					deUint32 seed = deInt32Hash(bufferMode) ^ deInt32Hash(primitiveType) ^ deInt32Hash(ndx);
1783					primitiveGroup->addChild(new RandomCase(m_context, de::toString(ndx+1).c_str(), "", bufferMode, primitiveType, seed));
1784				}
1785			}
1786		}
1787	}
1788}
1789
1790} // Functional
1791} // gles3
1792} // deqp
1793