1#ifndef _GLCVIEWPORTARRAYTESTS_HPP
2#define _GLCVIEWPORTARRAYTESTS_HPP
3/*-------------------------------------------------------------------------
4 * OpenGL Conformance Test Suite
5 * -----------------------------
6 *
7 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
24 */ /*-------------------------------------------------------------------*/
25
26/**
27 * \file  glcViewportArrayTests.hpp
28 * \brief Declares test classes for "Viewport Array" functionality.
29 */ /*-------------------------------------------------------------------*/
30
31#include "glcTestCase.hpp"
32#include "glwDefs.hpp"
33
34#include "esextcTestCaseBase.hpp"
35
36namespace tcu
37{
38class MessageBuilder;
39} /* namespace tcu */
40
41namespace glcts
42{
43namespace ViewportArray
44{
45
46class Utils
47{
48public:
49	enum SHADER_STAGES
50	{
51		COMPUTE_SHADER = 0,
52		VERTEX_SHADER,
53		TESS_CTRL_SHADER,
54		TESS_EVAL_SHADER,
55		GEOMETRY_SHADER,
56		FRAGMENT_SHADER,
57
58		/* */
59		SHADER_STAGES_MAX
60	};
61
62	/* Public types */
63	struct buffer
64	{
65		buffer(deqp::Context& context);
66		~buffer();
67
68		void bind() const;
69
70		void bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size);
71
72		void generate(glw::GLenum target);
73		void* map(glw::GLenum access) const;
74		void unmap() const;
75
76		void update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage);
77
78		glw::GLuint m_id;
79
80	private:
81		deqp::Context& m_context;
82		glw::GLenum	m_target;
83	};
84
85	struct framebuffer
86	{
87		framebuffer(deqp::Context& context);
88		~framebuffer();
89
90		void attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
91
92		void bind();
93		void clear(glw::GLenum mask);
94
95		void clearColor(glw::GLfloat red, glw::GLfloat green, glw::GLfloat blue, glw::GLfloat alpha);
96
97		void generate();
98
99		glw::GLuint m_id;
100
101	private:
102		deqp::Context& m_context;
103	};
104
105	class shaderCompilationException : public std::exception
106	{
107	public:
108		shaderCompilationException(const glw::GLchar* source, const glw::GLchar* message);
109
110		virtual ~shaderCompilationException() throw()
111		{
112		}
113
114		virtual const char* what() const throw();
115
116		std::string m_shader_source;
117		std::string m_error_message;
118	};
119
120	class programLinkageException : public std::exception
121	{
122	public:
123		programLinkageException(const glw::GLchar* error_message);
124
125		virtual ~programLinkageException() throw()
126		{
127		}
128
129		virtual const char* what() const throw();
130
131		std::string m_error_message;
132	};
133
134	/** Store information about program object
135	 *
136	 **/
137	struct program
138	{
139		program(deqp::Context& context);
140		~program();
141
142		void build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
143				   const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
144				   const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
145				   const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable = false);
146
147		void compile(glw::GLuint shader_id, const glw::GLchar* source) const;
148
149		glw::GLint getAttribLocation(const glw::GLchar* name) const;
150
151		glw::GLuint getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const;
152
153		glw::GLint getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const;
154
155		glw::GLint getUniformLocation(const glw::GLchar* uniform_name) const;
156
157		void link() const;
158		void remove();
159		void use() const;
160
161		/* */
162		static void printShaderSource(const glw::GLchar* source, tcu::MessageBuilder& log);
163
164		static const glw::GLenum ARB_COMPUTE_SHADER;
165
166		glw::GLuint m_compute_shader_id;
167		glw::GLuint m_fragment_shader_id;
168		glw::GLuint m_geometry_shader_id;
169		glw::GLuint m_program_object_id;
170		glw::GLuint m_tesselation_control_shader_id;
171		glw::GLuint m_tesselation_evaluation_shader_id;
172		glw::GLuint m_vertex_shader_id;
173
174	private:
175		deqp::Context& m_context;
176	};
177
178	struct texture
179	{
180		texture(deqp::Context& context);
181		~texture();
182
183		void bind() const;
184
185		void create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format);
186
187		void create(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum internal_format);
188
189		void get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const;
190
191		void release();
192
193		void update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
194					glw::GLvoid* data);
195
196		glw::GLuint m_id;
197		glw::GLuint m_width;
198		glw::GLuint m_height;
199		glw::GLuint m_depth;
200
201	private:
202		deqp::Context& m_context;
203		bool		   m_is_array;
204	};
205
206	struct vertexArray
207	{
208		vertexArray(deqp::Context& Context);
209		~vertexArray();
210
211		void generate();
212		void bind();
213
214		glw::GLuint m_id;
215
216	private:
217		deqp::Context& m_context;
218	};
219
220	class DepthFuncWrapper
221	{
222	public:
223		DepthFuncWrapper(deqp::Context& context) : m_gl(context.getRenderContext().getFunctions()){};
224		~DepthFuncWrapper(){};
225
226		void depthRangeArray(glw::GLuint first, glw::GLsizei count, const glw::GLfloat* v)
227		{
228			m_gl.depthRangeArrayfvOES(first, count, v);
229		}
230
231		void depthRangeArray(glw::GLuint first, glw::GLsizei count, const glw::GLdouble* v)
232		{
233			m_gl.depthRangeArrayv(first, count, v);
234		}
235
236		void depthRangeIndexed(glw::GLuint index, glw::GLfloat n, glw::GLfloat f)
237		{
238			m_gl.depthRangeIndexedfOES(index, n, f);
239		}
240
241		void depthRangeIndexed(glw::GLuint index, glw::GLdouble n, glw::GLdouble f)
242		{
243			m_gl.depthRangeIndexed(index, n, f);
244		}
245
246		void depthRange(glw::GLfloat near, glw::GLfloat far)
247		{
248			m_gl.depthRangef(near, far);
249		}
250
251		void depthRange(glw::GLdouble near, glw::GLdouble far)
252		{
253			m_gl.depthRange(near, far);
254		}
255
256		void getDepthi_v(glw::GLenum target, glw::GLuint index, glw::GLfloat* data)
257		{
258			m_gl.getFloati_v(target, index, data);
259		}
260
261		void getDepthi_v(glw::GLenum target, glw::GLuint index, glw::GLdouble* data)
262		{
263			m_gl.getDoublei_v(target, index, data);
264		}
265
266		const glw::Functions& getFunctions()
267		{
268			return m_gl;
269		}
270
271	private:
272		const glw::Functions& m_gl;
273	};
274};
275
276/** Implements test APIErrors, description follows:
277 *
278 *   Verify that API generate errors as specified. Check that:
279 *   * DepthRangeArrayv generates INVALID_VALUE when <first> + <count> is greater
280 *   than or equal to the value of MAX_VIEWPORTS;
281 *   * DepthRangeIndexed generates INVALID_VALUE when <index> is greater than or
282 *   equal to the value of MAX_VIEWPORTS;
283 *   * ViewportArrayv generates INVALID_VALUE when <first> + <count> is greater
284 *   than or equal to the value of MAX_VIEWPORTS;
285 *   * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when <index>
286 *   is greater than or equal to the value of MAX_VIEWPORTS;
287 *   * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate
288 *   INVALID_VALUE when <w> or <h> values are negative;
289 *   * ScissorArrayv generates INVALID_VALUE when <first> + <count> is greater
290 *   than or equal to the value of MAX_VIEWPORTS;
291 *   * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when <index> is
292 *   greater than or equal to the value of MAX_VIEWPORTS;
293 *   * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate
294 *   INVALID_VALUE when <width> or <height> values are negative;
295 *   * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when <cap> is
296 *   SCISSOR_TEST and <index> is greater than or equal to the
297 *   value of MAX_VIEWPORTS;
298 *   * GetIntegeri_v generates INVALID_VALUE when <target> is SCISSOR_BOX and
299 *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
300 *   * GetFloati_v generates INVALID_VALUE when <target> is VIEWPORT and <index>
301 *   is greater than or equal to the value of MAX_VIEWPORTS;
302 *   * GetDoublei_v generates INVALID_VALUE when <target> is DEPTH_RANGE and
303 *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
304 **/
305class APIErrors : public glcts::TestCaseBase
306{
307public:
308	/* Public methods */
309	APIErrors(deqp::Context& context, const glcts::ExtParameters& extParams);
310
311	virtual ~APIErrors()
312	{
313	}
314
315	/* Public methods inherited from TestCaseBase */
316	virtual IterateResult iterate(void);
317
318private:
319	template <typename T>
320	void depthRangeArrayHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result,
321							   T* data = NULL);
322
323	template <typename T>
324	void depthRangeIndexedHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result,
325								 T* data = NULL);
326
327	template <typename T>
328	void getDepthHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result,
329						T* data = NULL);
330
331	void checkGLError(glw::GLenum expected_error, const glw::GLchar* description, bool& out_result);
332};
333
334/** Implements test Queries, description follows:
335 *
336 *   Verify that:
337 *   * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of
338 *   the window into which GL is rendering;
339 *   * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1];
340 *   * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE;
341 *   * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either
342 *   zeros or match dimensions of the window into which GL is rendering;
343 *   * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least
344 *   as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE;
345 *   * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16;
346 *   * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0;
347 *   * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are
348 *   at least [-32768, 32767];
349 *   * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX
350 *   returned by GetIntegerv are located in the following set
351 *   { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX,
352 *   UNDEFINED_VERTEX };
353 **/
354class Queries : public glcts::TestCaseBase
355{
356public:
357	/* Public methods */
358	Queries(deqp::Context& context, const glcts::ExtParameters& extParams);
359
360	virtual ~Queries()
361	{
362	}
363
364	/* Public methods inherited from TestCase */
365	virtual tcu::TestNode::IterateResult iterate(void);
366
367private:
368	template <typename T>
369	void depthRangeInitialValuesHelper(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, bool& test_result,
370									   T* data = NULL);
371};
372
373/** Implements test ViewportAPI, description follows:
374 *
375 *   Verify that VIEWPORT can be set and queried.
376 *   Steps:
377 *   - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices;
378 *   - change location and dimensions of all indices at once with
379 *   ViewportArrayv;
380 *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
381 *   - for each index:
382 *     * modify with ViewportIndexedf,
383 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
384 *     * modify with ViewportIndexedfv,
385 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
386 *   - for each index:
387 *     * modify all indices before and after current one with ViewportArrayv,
388 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
389 *   - change location and dimensions of all indices at once with Viewport;
390 *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
391 **/
392class ViewportAPI : public glcts::TestCaseBase
393{
394public:
395	/* Public methods */
396	ViewportAPI(deqp::Context& context, const glcts::ExtParameters& extParams);
397
398	virtual ~ViewportAPI()
399	{
400	}
401
402	/* Public methods inherited from TestCase */
403	virtual tcu::TestNode::IterateResult iterate(void);
404
405private:
406	/* Private methods */
407	void compareViewports(std::vector<glw::GLfloat>& left, std::vector<glw::GLfloat>& right,
408						  const glw::GLchar* description, bool& out_result);
409
410	void getViewports(glw::GLint max_viewports, std::vector<glw::GLfloat>& out_data);
411
412	/* Private constants */
413	static const glw::GLuint m_n_elements;
414};
415
416/** Implements test ScissorAPI, description follows:
417 *
418 *   Verify that SCISSOR_BOX can be set and queried.
419 *   Steps:
420 *   - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices;
421 *   - change location and dimensions of all indices at once with
422 *   ScissorArrayv;
423 *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
424 *   - for each index:
425 *     * modify with ScissorIndexed,
426 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
427 *     * modify with ScissorIndexedv,
428 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
429 *   - for each index:
430 *     * modify all indices before and after current one with ScissorArrayv,
431 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
432 *   - change location and dimensions of all indices at once with Scissor;
433 *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
434 **/
435class ScissorAPI : public glcts::TestCaseBase
436{
437public:
438	/* Public methods */
439	ScissorAPI(deqp::Context& context, const glcts::ExtParameters& extParams);
440
441	virtual ~ScissorAPI()
442	{
443	}
444
445	/* Public methods inherited from TestCase */
446	virtual tcu::TestNode::IterateResult iterate(void);
447
448private:
449	/* Private methods */
450	void compareScissorBoxes(std::vector<glw::GLint>& left, std::vector<glw::GLint>& right,
451							 const glw::GLchar* description, bool& out_result);
452
453	void getScissorBoxes(glw::GLint max_viewports, std::vector<glw::GLint>& out_data);
454
455	/* Private constants */
456	static const glw::GLuint m_n_elements;
457};
458
459/** Implements test DepthRangeAPI, description follows:
460 *
461 *   Verify that DEPTH_RANGE can be set and queried.
462 *   Steps:
463 *   - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices;
464 *   - change values of all indices at once with DepthRangeArrayv;
465 *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
466 *   - for each index:
467 *     * modify with DepthRangeIndexed,
468 *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
469 *   - for each index:
470 *     * modify all indices before and after current one with DepthRangeArrayv,
471 *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
472 *   - change values of all indices at once with DepthRange;
473 *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
474 **/
475class DepthRangeAPI : public glcts::TestCaseBase
476{
477public:
478	/* Public methods */
479	DepthRangeAPI(deqp::Context& context, const glcts::ExtParameters& extParams);
480
481	virtual ~DepthRangeAPI()
482	{
483	}
484
485	/* Public methods inherited from TestCase */
486	virtual tcu::TestNode::IterateResult iterate(void);
487
488private:
489	/* Private methods */
490	template <typename T>
491	void compareDepthRanges(std::vector<T>& left, std::vector<T>& right, const glw::GLchar* description,
492							bool& out_result);
493
494	template <typename T>
495	void getDepthRanges(Utils::DepthFuncWrapper& depthFunc, glw::GLint max_viewports, std::vector<T>& out_data);
496
497	template <typename T>
498	bool iterateHelper(T* data = NULL);
499
500	/* Private constants */
501	static const glw::GLuint m_n_elements;
502};
503
504/** Implements test ScissorTestStateAPI, description follows:
505 *
506 *   Verify that state of SCISSOR_TEST can be set and queried.
507 *   Steps:
508 *   - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices;
509 *   - for each index:
510 *     * toggle SCISSOR_TEST,
511 *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
512 *   - for each index:
513 *     * toggle SCISSOR_TEST,
514 *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
515 *   - enable SCISSOR_TEST for all indices at once with Enable;
516 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
517 *   - disable SCISSOR_TEST for all indices at once with Disable;
518 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
519 *   - enable SCISSOR_TEST for all indices at once with Enable;
520 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
521 **/
522class ScissorTestStateAPI : public glcts::TestCaseBase
523{
524public:
525	/* Public methods */
526	ScissorTestStateAPI(deqp::Context& context, const glcts::ExtParameters& extParams);
527
528	virtual ~ScissorTestStateAPI()
529	{
530	}
531
532	/* Public methods inherited from TestCase */
533	virtual tcu::TestNode::IterateResult iterate(void);
534
535private:
536	/* Private methods */
537	void compareScissorTestStates(std::vector<glw::GLboolean>& left, std::vector<glw::GLboolean>& right,
538								  const glw::GLchar* description, bool& out_result);
539
540	void getScissorTestStates(glw::GLint max_viewports, std::vector<glw::GLboolean>& out_data);
541};
542
543class DrawTestBase : public glcts::TestCaseBase
544{
545public:
546	/* Public methods */
547	DrawTestBase(deqp::Context& context, const glcts::ExtParameters& extParams, const glw::GLchar* test_name,
548				 const glw::GLchar* test_description);
549
550	virtual ~DrawTestBase()
551	{
552	}
553
554	/* Public methods inherited from TestCase */
555	virtual tcu::TestNode::IterateResult iterate(void);
556
557protected:
558	/* Protected enums */
559	enum VIEWPORT_METHOD
560	{
561		VIEWPORTARRAYV = 0,
562		VIEWPORTINDEXEDF,
563		VIEWPORTINDEXEDF_V,
564	};
565	enum SCISSOR_METHOD
566	{
567		SCISSORARRAYV = 0,
568		SCISSORINDEXEDF,
569		SCISSORINDEXEDF_V,
570	};
571	enum DEPTH_RANGE_METHOD
572	{
573		DEPTHRANGEARRAYV = 0,
574		DEPTHRANGEINDEXED,
575	};
576	enum PROVOKING_VERTEX
577	{
578		FIRST,
579		LAST,
580	};
581	enum TEST_TYPE
582	{
583		VIEWPORT,
584		SCISSOR,
585		DEPTHRANGE,
586		PROVOKING,
587	};
588
589	/* Protected methods to be implemented by child class */
590	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
591
592	virtual void getClearSettings(bool& clear_depth_before_draw, glw::GLuint iteration_index,
593								  glw::GLfloat& depth_value);
594
595	virtual glw::GLuint getDrawCallsNumber();
596	virtual std::string getFragmentShader() = 0;
597	virtual std::string getGeometryShader() = 0;
598	virtual TEST_TYPE   getTestType();
599	virtual bool		isClearTest();
600
601	virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1);
602
603	virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index);
604
605	virtual void setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
606								  Utils::texture& texture_1);
607
608	virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index);
609
610	/* Methods available for child class */
611	bool checkRegionR32I(glw::GLuint x, glw::GLuint y, glw::GLint expected_value, glw::GLint* data);
612
613	bool checkRegionR32I(glw::GLuint x, glw::GLuint y, glw::GLuint width, glw::GLuint height, glw::GLint expected_value,
614						 glw::GLint* data);
615
616	void prepareTextureR32I(Utils::texture& texture);
617	void prepareTextureR32Ix4(Utils::texture& texture);
618	void prepareTextureArrayR32I(Utils::texture& texture);
619	void prepareTextureR32F(Utils::texture& texture);
620	void prepareTextureD32F(Utils::texture& texture);
621	void setup16x2Depths(DEPTH_RANGE_METHOD method);
622	void setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros);
623	void setup4x4Viewport(VIEWPORT_METHOD method);
624	void setup2x2Viewport(PROVOKING_VERTEX provoking);
625
626	/* Constants available to child class */
627	static const glw::GLuint m_depth;
628	static const glw::GLuint m_height;
629	static const glw::GLuint m_width;
630	static const glw::GLuint m_r32f_height;
631	static const glw::GLuint m_r32f_width;
632	static const glw::GLuint m_r32ix4_depth;
633
634private:
635	/* Private methods */
636	std::string getVertexShader();
637
638	template <typename T>
639	void setup16x2DepthsHelper(DEPTH_RANGE_METHOD method, T* data = NULL);
640};
641
642/** Implements test DrawToSingleLayerWithMultipleViewports, description follows:
643 *
644 *   Verify that multiple viewports can be used to draw to single image.
645 *   Steps:
646 *   - prepare 2D R32I 128x128 texture filled with value -1 and set it up as
647 *   COLOR_ATTACHMENT_0;
648 *   - prepare program that consist of:
649 *     * boilerplate vertex shader,
650 *     * geometry shader,
651 *     * fragment shaders;
652 *   Geometry shader should output a quad (-1,-1 : 1,1) made of
653 *   triangle_strip; gl_ViewportIndex and declared integer varying "color"
654 *   should be assigned the value of gl_InvocationID; Amount of geometry shader
655 *   invocations should be set to 16; Fragment shader should output value of
656 *   varying "color" to attachment 0.
657 *   - set up first 16 viewports with following code snippet:
658 *
659 *       index = 0;
660 *       for (y = 0; y < 4; ++y)
661 *         for (x = 0; x < 4; ++x)
662 *           ViewportIndexedf(index++,
663 *                            x * 32 x offset,
664 *                            y * 32 y offset,
665 *                            32     width   ,
666 *                            32     height  );
667 *   - draw single vertex;
668 *   - inspect contents of COLOR_ATTACHMENT_0;
669 *   - test pass if image is filled with the following pattern:
670 *
671 *       0  1  2  3
672 *       4  5  6  7
673 *       8  9  10 11
674 *       12 13 14 15;
675 *
676 *   Each area should be 32x32 pixels rectangle;
677 *   - repeat test with functions ViewportIndexedf_v and ViewportArrayv;
678 **/
679class DrawToSingleLayerWithMultipleViewports : public DrawTestBase
680{
681public:
682	/* Public methods */
683	DrawToSingleLayerWithMultipleViewports(deqp::Context& context, const glcts::ExtParameters& extParams);
684
685	virtual ~DrawToSingleLayerWithMultipleViewports()
686	{
687	}
688
689protected:
690	/* Protected methods inherited from DrawTestBase */
691	virtual std::string getFragmentShader();
692	virtual std::string getGeometryShader();
693};
694
695/** Implements test DynamicViewportIndex, description follows:
696 *
697 *   Verify that gl_ViewportIndex can be set in dynamic manner.
698 *   Modify DrawToSingleLayerWithMultipleViewports in the following aspects:
699 *   - geometry shader should declare unsigned integer uniform "index";
700 *   - geometry shader should assign a value of "index" to gl_ViewportIndex and
701 *   "color";
702 *   - amount of geometry shader invocations should be set to 1;
703 *   - 16 times:
704 *     * set "index" to unique value from range <0:15>;
705 *     * draw single vertex;
706 *     * verify that only area of viewport at "index" has been updated;
707 *   - test pass if correct pixels were modified in each draw;
708 **/
709class DynamicViewportIndex : public DrawTestBase
710{
711public:
712	/* Public methods */
713	DynamicViewportIndex(deqp::Context& context, const glcts::ExtParameters& extParams);
714
715	virtual ~DynamicViewportIndex()
716	{
717	}
718
719protected:
720	/* Protected methods inherited from DrawTestBase */
721	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
722
723	virtual std::string getFragmentShader();
724	virtual std::string getGeometryShader();
725	virtual glw::GLuint getDrawCallsNumber();
726
727	virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index);
728};
729
730/** Implements test DrawMulitpleViewportsWithSingleInvocation, description follows:
731 *
732 *   Verify that multiple viewports can be affected by single invocation of
733 *   geometry shader.
734 *   Modify DrawToSingleLayerWithMultipleViewports in the following aspects:
735 *   - geometry shader should output 16 quads, as separate primitives;
736 *   - instead of gl_InvocationID, geometry shader should use predefined values
737 *   from range <0:15>, unique per quad;
738 *   - amount of geometry shader invocations should be set to 1;
739 **/
740class DrawMulitpleViewportsWithSingleInvocation : public DrawTestBase
741{
742public:
743	/* Public methods */
744	DrawMulitpleViewportsWithSingleInvocation(deqp::Context& context, const glcts::ExtParameters& extParams);
745
746	virtual ~DrawMulitpleViewportsWithSingleInvocation()
747	{
748	}
749
750protected:
751	/* Protected methods inherited from DrawTestBase */
752	virtual std::string getFragmentShader();
753	virtual std::string getGeometryShader();
754};
755
756/** Implements test ViewportIndexSubroutine, description follows:
757 *
758 *   Verify that gl_ViewportIndex can be assigned by subroutine.
759 *   Depends on: ARB_shader_subroutine.
760 *   Modify DynamicViewportIndex in the following aspects:
761 *   - geometry shader should define two subroutines and single subroutine
762 *   uniform; First subroutine should assign value 4 to gl_ViewportIndex and
763 *   "color"; Second subroutine should assign value 5 to gl_ViewportIndex and
764 *   "color"; subroutine should be called once per emitted vertex;
765 *   - uniform "index" should be removed;
766 *   - viewport 4 should be configured to span over left half of image; viewport
767 *   5 should span over right half of image;
768 *   - set up first subroutine and draw single vertex;
769 *   - set up second subroutine and draw single vertex;
770 *   - test pass if left half of image is filled with value 4 and right one with
771 *   5;
772 **/
773class ViewportIndexSubroutine : public DrawTestBase
774{
775public:
776	/* Public methods */
777	ViewportIndexSubroutine(deqp::Context& context, const glcts::ExtParameters& extParams);
778
779	virtual ~ViewportIndexSubroutine()
780	{
781	}
782
783	/* Public methods inherited from TestCase/DrawTestBase */
784	virtual tcu::TestNode::IterateResult iterate(void);
785
786protected:
787	/* Protected methods inherited from DrawTestBase */
788	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
789
790	virtual std::string getFragmentShader();
791	virtual std::string getGeometryShader();
792	virtual glw::GLuint getDrawCallsNumber();
793
794	virtual void prepareUniforms(Utils::program& program, glw::GLuint draw_call_index);
795
796	virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index);
797};
798
799/** Implements test DrawMultipleLayers, description follows:
800 *
801 *   Verify that single viewport affects multiple layers in the same way.
802 *   Modify DynamicViewportIndex in the following aspects:
803 *   - texture should be 2D array with 16 layers;
804 *   - geometry shader should assign a value of gl_InvocationId to gl_Layer;
805 *   - amount of geometry shader invocations should be set to 16;
806 *   - verification should be applied to all 16 layers;
807 **/
808class DrawMultipleLayers : public DrawTestBase
809{
810public:
811	/* Public methods */
812	DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams);
813
814	DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams, const glw::GLchar* test_name,
815					   const glw::GLchar* test_description);
816
817	virtual ~DrawMultipleLayers()
818	{
819	}
820
821protected:
822	/* Protected methods inherited from DrawTestBase */
823	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
824
825	virtual std::string getFragmentShader();
826	virtual std::string getGeometryShader();
827
828	virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1);
829};
830
831/** Implements test Scissor, description follows:
832 *
833 *   Verify that scissor test is applied as expected.
834 *   Modify DrawMultipleLayers in the following aspects:
835 *   - set all viewports to location 0,0 and dimensions 128x128;
836 *   - set up first 16 scissor boxes with following code snippet:
837 *
838 *       index = 0;
839 *       for (y = 0; y < 4; ++y)
840 *         for (x = 0; x < 4; ++x)
841 *           ScissorIndexed(index++,
842 *                          x * 32 x offset,
843 *                          y * 32 y offset,
844 *                          32     width   ,
845 *                          32     height  );
846 *
847 *   - enable SCISSORT_TEST for first 16 indices;
848 *   - verification should be concerned with areas of the scissor boxes not
849 *   viewports;
850 *   - repeat test with functions ScissorIndexedv and ScissorArrayv;
851 **/
852class Scissor : public DrawMultipleLayers
853{
854public:
855	/* Public methods */
856	Scissor(deqp::Context& context, const glcts::ExtParameters& extParams);
857
858	virtual ~Scissor()
859	{
860	}
861
862protected:
863	/* Protected methods inherited from DrawTestBase */
864	virtual TEST_TYPE getTestType();
865};
866
867/** Implements test ScissorZeroDimension, description follows:
868 *
869 *   Verify that scissor test discard all fragments when width and height is set
870 *   to zero.
871 *   Modify Scissor to set up width and height of scissor boxes to 0.
872 *   Test pass if no pixel is modified.
873 **/
874class ScissorZeroDimension : public DrawMultipleLayers
875{
876public:
877	/* Public methods */
878	ScissorZeroDimension(deqp::Context& context, const glcts::ExtParameters& extParams);
879
880	virtual ~ScissorZeroDimension()
881	{
882	}
883
884protected:
885	/* Protected methods inherited from DrawTestBase */
886	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
887
888	virtual TEST_TYPE getTestType();
889
890	virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index);
891};
892
893/** Implements test ScissorClear, description follows:
894 *
895 *   Verify that Clear is affected only by settings of scissor test in first
896 *   viewport.
897 *   Steps:
898 *   - prepare 2D 128x128 R32I texture, filled with value -1 and set it as
899 *   COLOR_ATTACHMENT_0;
900 *   - configure first 16 viewports as in Scissor;
901 *   - enable SCISSOR_TEST for first 16 indices;
902 *   - clear framebuffer to (0, 0, 0, 0);
903 *   - inspect image;
904 *   - test pass if only area corresponding with first SCISSOR_BOX was filled
905 *   with 0, while rest of image remain filled with value -1;
906 **/
907class ScissorClear : public DrawMultipleLayers
908{
909public:
910	/* Public methods */
911	ScissorClear(deqp::Context& context, const glcts::ExtParameters& extParams);
912
913	virtual ~ScissorClear()
914	{
915	}
916
917protected:
918	/* Protected methods inherited from DrawTestBase */
919	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
920
921	virtual TEST_TYPE getTestType();
922	virtual bool	  isClearTest();
923};
924
925/** Implements test DepthRange, description follows:
926 *
927 *   Verify that depth range is applied as expected.
928 *   Steps:
929 *   - prepate 2D 16x2 R32F texture filled with value -1.0 and set it up as
930 *   COLOR_ATTACHMENT_0;
931 *   - prepare program that consist of:
932 *     * boilerplate vertex shader,
933 *     * geometry shader,
934 *     * fragment shader;
935 *   Geometry shader should emit two quads:
936 *     * -1,0 : 1,1 with z equal -1.0,
937 *     * -1,-1 : 1,0 with z equal 1.0,
938 *   made of triangle_strip; gl_ViewportIndex should be assigned an value of
939 *   gl_InvocationId; Amount of geometry shader invocations should be set to 16;
940 *   Fragment shader should output value of gl_FragCoord.z to attachment 0.
941 *   - set up first 16 viewports with the following code snippet:
942 *
943 *       const double step = 1.0 / 16.0;
944 *       for (index = 0; index < 16; ++index)
945 *       {
946 *           const double near = ((double) i) * step;
947 *           VieportIndexed   (i, (float) i, 0.0, 1.0, 2.0);
948 *           DepthRangeIndexed(i, near,      1.0 - near);
949 *       }
950 *
951 *   - draw single vertex;
952 *   - inspect contents of COLOR_ATTACHMENT_0;
953 *   - test pass if:
954 *     * top row of image is filled with increasing values, starting at 0 with
955 *     step 1/16;
956 *     * bottom row of image is filled with decreasing values, starting at 1 with
957 *     step 1/16;
958 *   - repeat test with function DepthRangeArrayv;
959 **/
960class DepthRange : public DrawTestBase
961{
962public:
963	/* Public methods */
964	DepthRange(deqp::Context& context, const glcts::ExtParameters& extParams);
965	virtual ~DepthRange()
966	{
967	}
968
969protected:
970	/* Protected methods inherited from DrawTestBase */
971	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
972
973	virtual std::string getFragmentShader();
974	virtual std::string getGeometryShader();
975	virtual TEST_TYPE   getTestType();
976
977	virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1);
978};
979
980/** Implements test DepthRangeDepthTest, description follows:
981 *
982 *   Verify that depth test work as expected with multiple viewports.
983 *   Modify DepthRange test in the following aspect:
984 *   - add second 2D 16x2 DEPTH_COMPONENT32F texture and set it up as
985 *   DEPTH_ATTACHMENT;
986 *   - enable DEPTH_TEST;
987 *   - DepthFunc should be set to LESS (initial value);
988 *   - 18 times:
989 *     * set ClearDepth to "i" * 1/16, starting at 0 up to 17/16,
990 *     * draw single vertex
991 *     * verify contents of color attachment;
992 *   - test pass when color attachment is filled only with values lower than
993 *   current ClearDepth value;
994 **/
995class DepthRangeDepthTest : public DrawTestBase
996{
997public:
998	/* Public methods */
999	DepthRangeDepthTest(deqp::Context& context, const glcts::ExtParameters& extParams);
1000
1001	virtual ~DepthRangeDepthTest()
1002	{
1003	}
1004
1005protected:
1006	/* Protected methods inherited from DrawTestBase */
1007	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
1008
1009	virtual void getClearSettings(bool& clear_depth_before_draw, glw::GLuint iteration_index,
1010								  glw::GLfloat& depth_value);
1011
1012	virtual glw::GLuint getDrawCallsNumber();
1013	virtual std::string getFragmentShader();
1014	virtual std::string getGeometryShader();
1015	virtual TEST_TYPE   getTestType();
1016
1017	virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1);
1018
1019	virtual void setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
1020								  Utils::texture& texture_1);
1021
1022	virtual void setupViewports(TEST_TYPE type, glw::GLuint iteration_index);
1023};
1024
1025/** Implements test ProvokingVertex, description follows:
1026 *
1027 *   Verify that provoking vertex work as expected.
1028 *   Steps:
1029 *   - prepare 2D array R32I 128x128x4 texture and configure it as
1030 *   COLOR_ATTACHMENT_0;
1031 *   - prepare program consisting of:
1032 *     * boilerplate vertex shader,
1033 *     * geometry shader,
1034 *     * fragment shader;
1035 *   Geometry shader should output a quad (-1,-1 : 1,1); Each vertex should
1036 *   receive different gl_ViewportIndex value, first vertex should be assigned an
1037 *   0, second 1, third 2, fourth 3; gl_Layer should be set in the same way as
1038 *   gl_ViewportIndex; Fragment shader should output integer of value 1;
1039 *   - configure first four viewports to form 2x2 grid, spanning whole image;
1040 *   - for each combination of LAYER_PROVOKING_VERTEX and
1041 *   VIEWPORT_INDEX_PROVOKING_VERTEX:
1042 *     * clear framebuffer to (0,0,0,0),
1043 *     * draw single vertex
1044 *     * inspect image;
1045 *   - test pass if correct area of correct layer is filled with value 1, while
1046 *   rest of image remains "clean";
1047 *   Notes:
1048 *   - for UNDEFINED_VERTEX any selection is correct;
1049 *   - for PROVOKING_VERTEX convention is selected by function ProvokingVertex;
1050 *   Test all possible combinations;
1051 **/
1052class ProvokingVertex : public DrawTestBase
1053{
1054public:
1055	/* Public methods */
1056	ProvokingVertex(deqp::Context& context, const glcts::ExtParameters& extParams);
1057
1058	virtual ~ProvokingVertex()
1059	{
1060	}
1061
1062protected:
1063	/* Protected methods inherited from DrawTestBase */
1064	virtual bool checkResults(Utils::texture& texture_0, Utils::texture& texture_1, glw::GLuint draw_call_index);
1065
1066	virtual std::string getFragmentShader();
1067	virtual std::string getGeometryShader();
1068	virtual TEST_TYPE   getTestType();
1069
1070	virtual void prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1);
1071};
1072} /* ViewportArray namespace */
1073
1074/** Group class for Shader Language 420Pack conformance tests */
1075class ViewportArrayTests : public glcts::TestCaseGroupBase
1076{
1077public:
1078	/* Public methods */
1079	ViewportArrayTests(deqp::Context& context, const glcts::ExtParameters& extParams);
1080
1081	virtual ~ViewportArrayTests(void)
1082	{
1083	}
1084
1085	virtual void init(void);
1086
1087private:
1088	/* Private methods */
1089	ViewportArrayTests(const ViewportArrayTests& other);
1090	ViewportArrayTests& operator=(const ViewportArrayTests& other);
1091};
1092
1093} // glcts
1094
1095#endif // _GLCVIEWPORTARRAYTESTS_HPP
1096