1#ifndef _GLSVERTEXARRAYTESTS_HPP
2#define _GLSVERTEXARRAYTESTS_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL (ES) Module
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Vertex array and buffer tests
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuTestCase.hpp"
27#include "tcuVector.hpp"
28#include "tcuSurface.hpp"
29#include "gluRenderContext.hpp"
30#include "gluCallLogWrapper.hpp"
31#include "tcuTestLog.hpp"
32#include "gluShaderProgram.hpp"
33#include "deFloat16.h"
34#include "tcuFloat.hpp"
35#include "tcuPixelFormat.hpp"
36#include "sglrContext.hpp"
37
38namespace sglr
39{
40
41class ReferenceContextBuffers;
42class ReferenceContext;
43class Context;
44
45} // sglr
46
47namespace deqp
48{
49namespace gls
50{
51
52class Array
53{
54public:
55	enum Target
56	{
57		// \note [mika] Are these actualy used somewhere?
58		TARGET_ELEMENT_ARRAY = 0,
59		TARGET_ARRAY,
60
61		TARGET_LAST
62	};
63
64	enum InputType
65	{
66		INPUTTYPE_FLOAT = 0,
67		INPUTTYPE_FIXED,
68		INPUTTYPE_DOUBLE,
69
70		INPUTTYPE_BYTE,
71		INPUTTYPE_SHORT,
72
73		INPUTTYPE_UNSIGNED_BYTE,
74		INPUTTYPE_UNSIGNED_SHORT,
75
76		INPUTTYPE_INT,
77		INPUTTYPE_UNSIGNED_INT,
78		INPUTTYPE_HALF,
79		INPUTTYPE_UNSIGNED_INT_2_10_10_10,
80		INPUTTYPE_INT_2_10_10_10,
81
82		INPUTTYPE_LAST
83	};
84
85	enum OutputType
86	{
87		OUTPUTTYPE_FLOAT = 0,
88		OUTPUTTYPE_VEC2,
89		OUTPUTTYPE_VEC3,
90		OUTPUTTYPE_VEC4,
91
92		OUTPUTTYPE_INT,
93		OUTPUTTYPE_UINT,
94
95		OUTPUTTYPE_IVEC2,
96		OUTPUTTYPE_IVEC3,
97		OUTPUTTYPE_IVEC4,
98
99		OUTPUTTYPE_UVEC2,
100		OUTPUTTYPE_UVEC3,
101		OUTPUTTYPE_UVEC4,
102
103		OUTPUTTYPE_LAST
104	};
105
106	enum Usage
107	{
108		USAGE_DYNAMIC_DRAW = 0,
109		USAGE_STATIC_DRAW,
110		USAGE_STREAM_DRAW,
111
112		USAGE_STREAM_READ,
113		USAGE_STREAM_COPY,
114
115		USAGE_STATIC_READ,
116		USAGE_STATIC_COPY,
117
118		USAGE_DYNAMIC_READ,
119		USAGE_DYNAMIC_COPY,
120
121		USAGE_LAST
122	};
123
124	enum Storage
125	{
126		STORAGE_USER = 0,
127		STORAGE_BUFFER,
128
129		STORAGE_LAST
130	};
131
132	enum Primitive
133	{
134		PRIMITIVE_POINTS = 0,
135		PRIMITIVE_TRIANGLES,
136		PRIMITIVE_TRIANGLE_FAN,
137		PRIMITIVE_TRIANGLE_STRIP,
138
139		PRIMITIVE_LAST
140	};
141
142	static std::string	targetToString		(Target target);
143	static std::string	inputTypeToString	(InputType type);
144	static std::string	outputTypeToString	(OutputType type);
145	static std::string	usageTypeToString	(Usage usage);
146	static std::string	storageToString		(Storage storage);
147	static std::string	primitiveToString	(Primitive primitive);
148	static int			inputTypeSize		(InputType type);
149
150	virtual				~Array				(void) {}
151	virtual void		data				(Target target, int size, const char* data, Usage usage) = 0;
152	virtual void		subdata				(Target target, int offset, int size, const char* data) = 0;
153	virtual void		bind				(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride) = 0;
154	virtual void		unBind				(void) = 0;
155
156	virtual bool		isBound				(void) const = 0;
157	virtual int			getComponentCount	(void) const = 0;
158	virtual Target		getTarget			(void) const = 0;
159	virtual InputType	getInputType		(void) const = 0;
160	virtual OutputType	getOutputType		(void) const = 0;
161	virtual Storage		getStorageType		(void) const = 0;
162	virtual bool		getNormalized		(void) const = 0;
163	virtual int			getStride			(void) const = 0;
164	virtual int			getAttribNdx		(void) const = 0;
165	virtual void		setAttribNdx		(int attribNdx) = 0;
166};
167
168class ContextArray : public Array
169{
170public:
171								ContextArray		(Storage storage, sglr::Context& context);
172	virtual						~ContextArray		(void);
173	virtual void				data				(Target target, int size, const char* data, Usage usage);
174	virtual void				subdata				(Target target, int offset, int size, const char* data);
175	virtual void				bind				(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride);
176	virtual void				bindIndexArray		(Array::Target storage);
177	virtual void				unBind				(void) { m_bound = false; }
178	virtual bool				isBound				(void) const { return m_bound; }
179
180	virtual int					getComponentCount	(void) const { return m_componentCount; }
181	virtual Array::Target		getTarget			(void) const { return m_target; }
182	virtual Array::InputType	getInputType		(void) const { return m_inputType; }
183	virtual Array::OutputType	getOutputType		(void) const { return m_outputType; }
184	virtual Array::Storage		getStorageType		(void) const { return m_storage; }
185	virtual bool				getNormalized		(void) const { return m_normalize; }
186	virtual int					getStride			(void) const { return m_stride; }
187	virtual int					getAttribNdx		(void) const { return m_attribNdx; }
188	virtual void				setAttribNdx		(int attribNdx) { m_attribNdx = attribNdx; }
189
190	void						glBind				(deUint32 loc);
191	static deUint32				targetToGL			(Array::Target target);
192	static deUint32				usageToGL			(Array::Usage usage);
193	static deUint32				inputTypeToGL		(Array::InputType type);
194	static std::string			outputTypeToGLType	(Array::OutputType type);
195	static deUint32				primitiveToGL		(Array::Primitive primitive);
196
197private:
198	Storage						m_storage;
199	sglr::Context&				m_ctx;
200	deUint32					m_glBuffer;
201
202	bool						m_bound;
203	int							m_attribNdx;
204	int							m_size;
205	char*						m_data;
206	int							m_componentCount;
207	Array::Target				m_target;
208	Array::InputType			m_inputType;
209	Array::OutputType			m_outputType;
210	bool						m_normalize;
211	int							m_stride;
212	int							m_offset;
213};
214
215class ContextArrayPack
216{
217public:
218								ContextArrayPack	(glu::RenderContext& renderCtx, sglr::Context& drawContext);
219	virtual						~ContextArrayPack	(void);
220	virtual Array*				getArray			(int i);
221	virtual int					getArrayCount		(void);
222	virtual	void				newArray			(Array::Storage storage);
223	virtual void				render 				(Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale);
224
225	const tcu::Surface&			getSurface			(void) const { return m_screen; }
226private:
227	void 						updateProgram		(void);
228	glu::RenderContext&			m_renderCtx;
229	sglr::Context&				m_ctx;
230
231	std::vector<ContextArray*>	m_arrays;
232	sglr::ShaderProgram*		m_program;
233	tcu::Surface				m_screen;
234};
235
236class GLValue
237{
238public:
239
240	template<class Type>
241	class WrappedType
242	{
243	public:
244		static WrappedType<Type>	create			(Type value)							{ WrappedType<Type> v; v.m_value = value; return v; }
245		inline Type					getValue		(void) const							{ return m_value; }
246
247		inline WrappedType<Type>	operator+		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value + other.getValue()); }
248		inline WrappedType<Type>	operator*		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value * other.getValue()); }
249		inline WrappedType<Type>	operator/		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value / other.getValue()); }
250		inline WrappedType<Type>	operator-		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value - other.getValue()); }
251
252		inline WrappedType<Type>&	operator+=		(const WrappedType<Type>& other)		{ m_value += other.getValue(); return *this; }
253		inline WrappedType<Type>&	operator*=		(const WrappedType<Type>& other)		{ m_value *= other.getValue(); return *this; }
254		inline WrappedType<Type>&	operator/=		(const WrappedType<Type>& other)		{ m_value /= other.getValue(); return *this; }
255		inline WrappedType<Type>&	operator-=		(const WrappedType<Type>& other)		{ m_value -= other.getValue(); return *this; }
256
257		inline bool					operator==		(const WrappedType<Type>& other) const	{ return m_value == other.m_value; }
258		inline bool					operator!=		(const WrappedType<Type>& other) const	{ return m_value != other.m_value; }
259		inline bool					operator<		(const WrappedType<Type>& other) const	{ return m_value < other.m_value; }
260		inline bool					operator>		(const WrappedType<Type>& other) const	{ return m_value > other.m_value; }
261		inline bool					operator<=		(const WrappedType<Type>& other) const	{ return m_value <= other.m_value; }
262		inline bool					operator>=		(const WrappedType<Type>& other) const	{ return m_value >= other.m_value; }
263
264		inline 						operator Type	(void) const							{ return m_value; }
265		template<class T>
266		inline T					to				(void) const							{ return (T)m_value; }
267	private:
268		Type	m_value;
269	};
270
271	typedef WrappedType<deInt16>	Short;
272	typedef WrappedType<deUint16>	Ushort;
273
274	typedef WrappedType<deInt8>		Byte;
275	typedef WrappedType<deUint8>	Ubyte;
276
277	typedef WrappedType<float>		Float;
278	typedef WrappedType<double>		Double;
279
280	typedef WrappedType<deInt32>	Int;
281	typedef WrappedType<deUint32>	Uint;
282
283	class Half
284	{
285	public:
286		static Half			create			(float value)				{ Half h; h.m_value = floatToHalf(value); return h; }
287		inline deFloat16	getValue		(void) const				{ return m_value; }
288
289		inline Half			operator+		(const Half& other) const	{ return create(halfToFloat(m_value) + halfToFloat(other.getValue())); }
290		inline Half			operator*		(const Half& other) const	{ return create(halfToFloat(m_value) * halfToFloat(other.getValue())); }
291		inline Half			operator/		(const Half& other) const	{ return create(halfToFloat(m_value) / halfToFloat(other.getValue())); }
292		inline Half			operator-		(const Half& other) const	{ return create(halfToFloat(m_value) - halfToFloat(other.getValue())); }
293
294		inline Half&		operator+=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; }
295		inline Half&		operator*=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; }
296		inline Half&		operator/=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; }
297		inline Half&		operator-=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; }
298
299		inline bool			operator==		(const Half& other) const	{ return m_value == other.m_value; }
300		inline bool			operator!=		(const Half& other) const	{ return m_value != other.m_value; }
301		inline bool			operator<		(const Half& other) const	{ return halfToFloat(m_value) < halfToFloat(other.m_value); }
302		inline bool			operator>		(const Half& other) const	{ return halfToFloat(m_value) > halfToFloat(other.m_value); }
303		inline bool			operator<=		(const Half& other) const	{ return halfToFloat(m_value) <= halfToFloat(other.m_value); }
304		inline bool			operator>=		(const Half& other) const	{ return halfToFloat(m_value) >= halfToFloat(other.m_value); }
305
306		template<class T>
307		inline T			to				(void) const				{ return (T)halfToFloat(m_value); }
308
309		inline static deFloat16	floatToHalf		(float f);
310		inline static float		halfToFloat		(deFloat16 h);
311	private:
312		deFloat16 m_value;
313	};
314
315	class Fixed
316	{
317	public:
318		static Fixed		create			(deInt32 value)				{ Fixed v; v.m_value = value; return v; }
319		inline deInt32		getValue		(void) const				{ return m_value; }
320
321		inline Fixed		operator+		(const Fixed& other) const	{ return create(m_value + other.getValue()); }
322		inline Fixed		operator*		(const Fixed& other) const	{ return create(m_value * other.getValue()); }
323		inline Fixed		operator/		(const Fixed& other) const	{ return create(m_value / other.getValue()); }
324		inline Fixed		operator-		(const Fixed& other) const	{ return create(m_value - other.getValue()); }
325
326		inline Fixed&		operator+=		(const Fixed& other)		{ m_value += other.getValue(); return *this; }
327		inline Fixed&		operator*=		(const Fixed& other)		{ m_value *= other.getValue(); return *this; }
328		inline Fixed&		operator/=		(const Fixed& other)		{ m_value /= other.getValue(); return *this; }
329		inline Fixed&		operator-=		(const Fixed& other)		{ m_value -= other.getValue(); return *this; }
330
331		inline bool			operator==		(const Fixed& other) const	{ return m_value == other.m_value; }
332		inline bool			operator!=		(const Fixed& other) const	{ return m_value != other.m_value; }
333		inline bool			operator<		(const Fixed& other) const	{ return m_value < other.m_value; }
334		inline bool			operator>		(const Fixed& other) const	{ return m_value > other.m_value; }
335		inline bool			operator<=		(const Fixed& other) const	{ return m_value <= other.m_value; }
336		inline bool			operator>=		(const Fixed& other) const	{ return m_value >= other.m_value; }
337
338		inline 				operator deInt32 (void) const				{ return m_value; }
339		template<class T>
340		inline T			to				(void) const				{ return (T)m_value; }
341	private:
342		deInt32				m_value;
343	};
344
345	// \todo [mika] This is pretty messy
346						GLValue			(void)			: type(Array::INPUTTYPE_LAST) {}
347	explicit			GLValue			(Float value)	: type(Array::INPUTTYPE_FLOAT),				fl(value)	{}
348	explicit			GLValue			(Fixed value)	: type(Array::INPUTTYPE_FIXED),				fi(value)	{}
349	explicit			GLValue			(Byte value)	: type(Array::INPUTTYPE_BYTE),				b(value)	{}
350	explicit			GLValue			(Ubyte value)	: type(Array::INPUTTYPE_UNSIGNED_BYTE),		ub(value)	{}
351	explicit			GLValue			(Short value)	: type(Array::INPUTTYPE_SHORT),				s(value)	{}
352	explicit			GLValue			(Ushort value)	: type(Array::INPUTTYPE_UNSIGNED_SHORT),	us(value)	{}
353	explicit			GLValue			(Int value)		: type(Array::INPUTTYPE_INT),				i(value)	{}
354	explicit			GLValue			(Uint value)	: type(Array::INPUTTYPE_UNSIGNED_INT),		ui(value)	{}
355	explicit			GLValue			(Half value)	: type(Array::INPUTTYPE_HALF),				h(value)	{}
356	explicit			GLValue			(Double value)	: type(Array::INPUTTYPE_DOUBLE),			d(value)	{}
357
358	float				toFloat			(void) const;
359
360	static GLValue		getMaxValue		(Array::InputType type);
361	static GLValue		getMinValue		(Array::InputType type);
362
363	Array::InputType	type;
364
365	union
366	{
367		Float		fl;
368		Fixed		fi;
369		Double		d;
370		Byte		b;
371		Ubyte		ub;
372		Short		s;
373		Ushort		us;
374		Int			i;
375		Uint		ui;
376		Half		h;
377	};
378};
379
380class VertexArrayTest : public tcu::TestCase
381{
382public:
383									VertexArrayTest		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc);
384	virtual							~VertexArrayTest	(void);
385	virtual void					init				(void);
386	virtual void					deinit				(void);
387
388protected:
389									VertexArrayTest		(const VertexArrayTest& other);
390	VertexArrayTest&				operator=			(const VertexArrayTest& other);
391
392	void							compare				(void);
393
394	glu::RenderContext&				m_renderCtx;
395
396	sglr::ReferenceContextBuffers*	m_refBuffers;
397	sglr::ReferenceContext*			m_refContext;
398	sglr::Context*					m_glesContext;
399
400	ContextArrayPack*				m_glArrayPack;
401	ContextArrayPack*				m_rrArrayPack;
402	bool							m_isOk;
403
404	int								m_maxDiffRed;
405	int								m_maxDiffGreen;
406	int								m_maxDiffBlue;
407};
408
409class MultiVertexArrayTest : public VertexArrayTest
410{
411public:
412	class Spec
413	{
414	public:
415		class ArraySpec
416		{
417		public:
418								ArraySpec	(Array::InputType inputType, Array::OutputType outputType, Array::Storage storage, Array::Usage usage, int componetCount, int offset, int stride, bool normalize, GLValue min, GLValue max);
419
420			Array::InputType	inputType;
421			Array::OutputType	outputType;
422			Array::Storage		storage;
423			Array::Usage		usage;
424			int 				componentCount;
425			int					offset;
426			int					stride;
427			bool				normalize;
428			GLValue				min;
429			GLValue				max;
430		};
431
432		std::string 			getName		(void) const;
433		std::string				getDesc		(void) const;
434
435		Array::Primitive		primitive;
436		int						drawCount;			//!<Number of primitives to draw
437		int						first;
438
439		std::vector<ArraySpec>	arrays;
440	};
441
442							MultiVertexArrayTest	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc);
443	virtual					~MultiVertexArrayTest	(void);
444	virtual IterateResult	iterate					(void);
445
446private:
447	bool					isUnalignedBufferOffsetTest		(void) const;
448	bool					isUnalignedBufferStrideTest		(void) const;
449
450	Spec					m_spec;
451	int						m_iteration;
452};
453
454inline deFloat16 GLValue::Half::floatToHalf (float f)
455{
456	// No denorm support.
457	tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f);
458	DE_ASSERT(!v.isNaN() && !v.isInf());
459	return v.bits();
460}
461
462inline float GLValue::Half::halfToFloat (deFloat16 h)
463{
464	return tcu::Float16((deUint16)h).asFloat();
465}
466
467} // gls
468} // deqp
469
470#endif // _GLSVERTEXARRAYTESTS_HPP
471