1e5c31af7Sopenharmony_ci#ifndef _ESEXTCTESSELLATIONSHADERVERTEXSPACING_HPP
2e5c31af7Sopenharmony_ci#define _ESEXTCTESSELLATIONSHADERVERTEXSPACING_HPP
3e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
4e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
5e5c31af7Sopenharmony_ci * -----------------------------
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc.
8e5c31af7Sopenharmony_ci *
9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci *
15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci * limitations under the License.
20e5c31af7Sopenharmony_ci *
21e5c31af7Sopenharmony_ci */ /*!
22e5c31af7Sopenharmony_ci * \file
23e5c31af7Sopenharmony_ci * \brief
24e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "../esextcTestCaseBase.hpp"
27e5c31af7Sopenharmony_ci#include "esextcTessellationShaderUtils.hpp"
28e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
29e5c31af7Sopenharmony_ci#include "tcuDefs.hpp"
30e5c31af7Sopenharmony_ci#include <deMath.h>
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_cinamespace glcts
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_ci/** Implementation of Test Case 25
35e5c31af7Sopenharmony_ci *
36e5c31af7Sopenharmony_ci *  Make sure that vertex spacing mode defined in a tessellation evaluation
37e5c31af7Sopenharmony_ci *  shader affects the tessellation primitive generator as per specification,
38e5c31af7Sopenharmony_ci *  to the limit enforced by implementation-dependent behaviour.
39e5c31af7Sopenharmony_ci *  Consider all three tessellation primitive generator modes (triangles,
40e5c31af7Sopenharmony_ci *  quads, isolines). TE stage should be run in point mode.
41e5c31af7Sopenharmony_ci *  Make sure that by default the tessellation primitive generator works in
42e5c31af7Sopenharmony_ci *  equal_spacing spacing mode.
43e5c31af7Sopenharmony_ci *  Make sure that negative inner levels are clamped as defined for active
44e5c31af7Sopenharmony_ci *  vertex spacing mode.
45e5c31af7Sopenharmony_ci *
46e5c31af7Sopenharmony_ci *  Technical details:
47e5c31af7Sopenharmony_ci *
48e5c31af7Sopenharmony_ci *  0. Consider the following set: {-1 (where valid), 1, MAX_TESS_GEN_LEVEL_EXT / 2,
49e5c31af7Sopenharmony_ci *     MAX_TESS_GEN_LEVEL_EXT}. All combinations of values from this set
50e5c31af7Sopenharmony_ci *     in regard to relevant inner/outer tessellation levels for all
51e5c31af7Sopenharmony_ci *     primitive generator modes should be checked by this test.
52e5c31af7Sopenharmony_ci *
53e5c31af7Sopenharmony_ci *  1. This test should capture vertices output by TE stage and verify their
54e5c31af7Sopenharmony_ci *     locations. If an edge is defined by function y = a * t + b (a, b
55e5c31af7Sopenharmony_ci *     computed from locations of edge start & end points), t should be
56e5c31af7Sopenharmony_ci *     calculated for each vertex that is a part of the edge considered.
57e5c31af7Sopenharmony_ci *  2. Test passes if t values are in agreement with the specification
58e5c31af7Sopenharmony_ci *     (assume epsilon 1e-5) and vertex spacing mode considered.
59e5c31af7Sopenharmony_ci *
60e5c31af7Sopenharmony_ci *  This test implementation skips configurations meeting all of the following
61e5c31af7Sopenharmony_ci *  properties:
62e5c31af7Sopenharmony_ci *
63e5c31af7Sopenharmony_ci *  - primitive mode:      QUADS
64e5c31af7Sopenharmony_ci *  - vertex spacing mode: FRACTIONAL ODD
65e5c31af7Sopenharmony_ci *  - inner tess level[0]: <= 1
66e5c31af7Sopenharmony_ci *  - inner tess level[1]: <= 1
67e5c31af7Sopenharmony_ci *
68e5c31af7Sopenharmony_ci *  These configurations are affected by a nuance described in greater
69e5c31af7Sopenharmony_ci *  detail in Khronos Bugzilla#11979, which this test cannot handle.
70e5c31af7Sopenharmony_ci **/
71e5c31af7Sopenharmony_ciclass TessellationShaderVertexSpacing : public TestCaseBase
72e5c31af7Sopenharmony_ci{
73e5c31af7Sopenharmony_cipublic:
74e5c31af7Sopenharmony_ci	/* Public methods */
75e5c31af7Sopenharmony_ci	TessellationShaderVertexSpacing(Context& context, const ExtParameters& extParams);
76e5c31af7Sopenharmony_ci
77e5c31af7Sopenharmony_ci	virtual ~TessellationShaderVertexSpacing(void)
78e5c31af7Sopenharmony_ci	{
79e5c31af7Sopenharmony_ci	}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	virtual void		  deinit(void);
82e5c31af7Sopenharmony_ci	void				  initTest(void);
83e5c31af7Sopenharmony_ci	virtual IterateResult iterate(void);
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ciprivate:
86e5c31af7Sopenharmony_ci	/* Private type definitions */
87e5c31af7Sopenharmony_ci	/** Stores properties of a single test run */
88e5c31af7Sopenharmony_ci	typedef struct _run
89e5c31af7Sopenharmony_ci	{
90e5c31af7Sopenharmony_ci		float								inner[2];
91e5c31af7Sopenharmony_ci		float								outer[4];
92e5c31af7Sopenharmony_ci		_tessellation_primitive_mode		primitive_mode;
93e5c31af7Sopenharmony_ci		_tessellation_shader_vertex_spacing vertex_spacing;
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci		std::vector<char> data;
96e5c31af7Sopenharmony_ci		float*			  data_cartesian; /* only used for 'triangles' case */
97e5c31af7Sopenharmony_ci		unsigned int	  n_vertices;
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci		/* Constructor. Resets all fields to default values */
100e5c31af7Sopenharmony_ci		_run()
101e5c31af7Sopenharmony_ci		{
102e5c31af7Sopenharmony_ci			memset(inner, 0, sizeof(inner));
103e5c31af7Sopenharmony_ci			memset(outer, 0, sizeof(outer));
104e5c31af7Sopenharmony_ci			data_cartesian	= 0;
105e5c31af7Sopenharmony_ci			n_vertices		= 0;
106e5c31af7Sopenharmony_ci			primitive_mode	= TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
107e5c31af7Sopenharmony_ci			vertex_spacing	= TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
108e5c31af7Sopenharmony_ci		}
109e5c31af7Sopenharmony_ci	} _run;
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci	/** Stores either barycentric or Cartesian coordinate data
112e5c31af7Sopenharmony_ci	 *  (depending on primitive mode of a test run this structure
113e5c31af7Sopenharmony_ci	 *  will be instantiated for)
114e5c31af7Sopenharmony_ci	 */
115e5c31af7Sopenharmony_ci	typedef struct _tess_coordinate
116e5c31af7Sopenharmony_ci	{
117e5c31af7Sopenharmony_ci		float u;
118e5c31af7Sopenharmony_ci		float v;
119e5c31af7Sopenharmony_ci		float w;
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci		/* Constructor. Resets all fields to 0 */
122e5c31af7Sopenharmony_ci		_tess_coordinate()
123e5c31af7Sopenharmony_ci		{
124e5c31af7Sopenharmony_ci			u = 0.0f;
125e5c31af7Sopenharmony_ci			v = 0.0f;
126e5c31af7Sopenharmony_ci			w = 0.0f;
127e5c31af7Sopenharmony_ci		}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci		/* Constructor.
130e5c31af7Sopenharmony_ci		 *
131e5c31af7Sopenharmony_ci		 * @param u Value to set for U component;
132e5c31af7Sopenharmony_ci		 * @param v Value to set for V component;
133e5c31af7Sopenharmony_ci		 * @param w Value to set for W component;
134e5c31af7Sopenharmony_ci		 */
135e5c31af7Sopenharmony_ci		_tess_coordinate(float _u, float _v, float _w)
136e5c31af7Sopenharmony_ci		{
137e5c31af7Sopenharmony_ci			this->u = _u;
138e5c31af7Sopenharmony_ci			this->v = _v;
139e5c31af7Sopenharmony_ci			this->w = _w;
140e5c31af7Sopenharmony_ci		}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci		/** Compares two barycentric/Cartesian coordinates, using test-wide epsilon.
143e5c31af7Sopenharmony_ci		 *
144e5c31af7Sopenharmony_ci		 *  @param in Coordinate to compare current instance against.
145e5c31af7Sopenharmony_ci		 *
146e5c31af7Sopenharmony_ci		 *  @return true if the coordinates are equal, false otherwise.
147e5c31af7Sopenharmony_ci		 **/
148e5c31af7Sopenharmony_ci		bool operator==(const _tess_coordinate& in) const;
149e5c31af7Sopenharmony_ci	} _tess_coordinate;
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci	/** Stores Cartesian coordinate data. */
152e5c31af7Sopenharmony_ci	typedef struct _tess_coordinate_cartesian
153e5c31af7Sopenharmony_ci	{
154e5c31af7Sopenharmony_ci		float x;
155e5c31af7Sopenharmony_ci		float y;
156e5c31af7Sopenharmony_ci
157e5c31af7Sopenharmony_ci		/* Constructor. Resets all values to 0 */
158e5c31af7Sopenharmony_ci		_tess_coordinate_cartesian()
159e5c31af7Sopenharmony_ci		{
160e5c31af7Sopenharmony_ci			x = 0.0f;
161e5c31af7Sopenharmony_ci			y = 0.0f;
162e5c31af7Sopenharmony_ci		}
163e5c31af7Sopenharmony_ci
164e5c31af7Sopenharmony_ci		/* Constructor.
165e5c31af7Sopenharmony_ci		 *
166e5c31af7Sopenharmony_ci		 * @param x Value to use for X component;
167e5c31af7Sopenharmony_ci		 * @param y Value to use for Y component;
168e5c31af7Sopenharmony_ci		 */
169e5c31af7Sopenharmony_ci		_tess_coordinate_cartesian(float _x, float _y)
170e5c31af7Sopenharmony_ci		{
171e5c31af7Sopenharmony_ci			this->x = _x;
172e5c31af7Sopenharmony_ci			this->y = _y;
173e5c31af7Sopenharmony_ci		}
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci		/** Compares two Cartesian coordinates, using test-wide epsilon.
176e5c31af7Sopenharmony_ci		 *
177e5c31af7Sopenharmony_ci		 *  @param in Coordinate to compare current instance against.
178e5c31af7Sopenharmony_ci		 *
179e5c31af7Sopenharmony_ci		 *  @return true if the coordinates are equal, false otherwise.
180e5c31af7Sopenharmony_ci		 **/
181e5c31af7Sopenharmony_ci		bool operator==(const _tess_coordinate_cartesian& in) const;
182e5c31af7Sopenharmony_ci	} _tess_coordinate_cartesian;
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	/** Stores information on:
185e5c31af7Sopenharmony_ci	 *
186e5c31af7Sopenharmony_ci	 *  - a delta between two coordinates;
187e5c31af7Sopenharmony_ci	 *  - amount of segments that had exactly that length.
188e5c31af7Sopenharmony_ci	 **/
189e5c31af7Sopenharmony_ci	typedef struct _tess_coordinate_delta
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		unsigned int counter;
192e5c31af7Sopenharmony_ci		float		 delta;
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci		/* Constructor. Resets all values to 0 */
195e5c31af7Sopenharmony_ci		_tess_coordinate_delta()
196e5c31af7Sopenharmony_ci		{
197e5c31af7Sopenharmony_ci			counter = 0;
198e5c31af7Sopenharmony_ci			delta   = 0.0f;
199e5c31af7Sopenharmony_ci		}
200e5c31af7Sopenharmony_ci	} _tess_coordinate_delta;
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ci	/** Vector of coordinate deltas */
203e5c31af7Sopenharmony_ci	typedef std::vector<_tess_coordinate_delta>		_tess_coordinate_deltas;
204e5c31af7Sopenharmony_ci	typedef _tess_coordinate_deltas::const_iterator _tess_coordinate_deltas_const_iterator;
205e5c31af7Sopenharmony_ci	typedef _tess_coordinate_deltas::iterator		_tess_coordinate_deltas_iterator;
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	/** Vector of Cartesian coordinates making up an edge. */
208e5c31af7Sopenharmony_ci	typedef std::vector<_tess_coordinate_cartesian> _tess_edge_points;
209e5c31af7Sopenharmony_ci	typedef _tess_edge_points::const_iterator		_tess_edge_points_const_iterator;
210e5c31af7Sopenharmony_ci	typedef _tess_edge_points::iterator				_tess_edge_points_iterator;
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci	/** Defines a single edge of a quad/triangle *or* a single isoline (depending
213e5c31af7Sopenharmony_ci	 *  on the primitive mode used for a test run, for which the edge is defined)
214e5c31af7Sopenharmony_ci	 */
215e5c31af7Sopenharmony_ci	typedef struct _tess_edge
216e5c31af7Sopenharmony_ci	{
217e5c31af7Sopenharmony_ci		_tess_edge_points points;
218e5c31af7Sopenharmony_ci		float			  edge_length;
219e5c31af7Sopenharmony_ci		float			  outermost_tess_level;
220e5c31af7Sopenharmony_ci		float			  tess_level;
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci		/* Constructor.
223e5c31af7Sopenharmony_ci		 *
224e5c31af7Sopenharmony_ci		 * @param in_tess_level  Tessellation level value specific to the edge.
225e5c31af7Sopenharmony_ci		 * @param in_edge_length Total Euclidean length of the edge.
226e5c31af7Sopenharmony_ci		 */
227e5c31af7Sopenharmony_ci		_tess_edge(const float& in_tess_level, const float& in_outermost_tess_level, const float& in_edge_length)
228e5c31af7Sopenharmony_ci			: edge_length(in_edge_length), outermost_tess_level(in_outermost_tess_level), tess_level(in_tess_level)
229e5c31af7Sopenharmony_ci		{
230e5c31af7Sopenharmony_ci		}
231e5c31af7Sopenharmony_ci	} _tess_edge;
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	/** Vector of edges */
234e5c31af7Sopenharmony_ci	typedef std::vector<_tess_edge>		_tess_edges;
235e5c31af7Sopenharmony_ci	typedef _tess_edges::const_iterator _tess_edges_const_iterator;
236e5c31af7Sopenharmony_ci	typedef _tess_edges::iterator		_tess_edges_iterator;
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci	/** Vector of test runs */
239e5c31af7Sopenharmony_ci	typedef std::vector<_run>	 _runs;
240e5c31af7Sopenharmony_ci	typedef _runs::const_iterator _runs_const_iterator;
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci	/** Comparator that is used to sort points relative to a certain origin. */
243e5c31af7Sopenharmony_ci	struct _comparator_relative_to_base_point
244e5c31af7Sopenharmony_ci	{
245e5c31af7Sopenharmony_ci		/* Constructor. Sets all fields to 0 */
246e5c31af7Sopenharmony_ci		_comparator_relative_to_base_point() : base_point(0, 0)
247e5c31af7Sopenharmony_ci		{
248e5c31af7Sopenharmony_ci		}
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci		/* Constructor.
251e5c31af7Sopenharmony_ci		 *
252e5c31af7Sopenharmony_ci		 * @param base_point Origin, against which all comparisons should be run against.
253e5c31af7Sopenharmony_ci		 */
254e5c31af7Sopenharmony_ci		_comparator_relative_to_base_point(const _tess_coordinate_cartesian& _base_point) : base_point(_base_point)
255e5c31af7Sopenharmony_ci		{
256e5c31af7Sopenharmony_ci		}
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_ci		/* Tells which of the user-provided points is closer to the instance-specific
259e5c31af7Sopenharmony_ci		 * "origin".
260e5c31af7Sopenharmony_ci		 *
261e5c31af7Sopenharmony_ci		 * @param a First point to use.
262e5c31af7Sopenharmony_ci		 * @param b Second point to use.
263e5c31af7Sopenharmony_ci		 *
264e5c31af7Sopenharmony_ci		 * @return true if point @param a is closer to the "origin", false otherwise.
265e5c31af7Sopenharmony_ci		 */
266e5c31af7Sopenharmony_ci		bool operator()(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b)
267e5c31af7Sopenharmony_ci		{
268e5c31af7Sopenharmony_ci			float distance_a_to_base =
269e5c31af7Sopenharmony_ci				deFloatSqrt((a.x - base_point.x) * (a.x - base_point.x) + (a.y - base_point.y) * (a.y - base_point.y));
270e5c31af7Sopenharmony_ci			float distance_b_to_base =
271e5c31af7Sopenharmony_ci				deFloatSqrt((b.x - base_point.x) * (b.x - base_point.x) + (b.y - base_point.y) * (b.y - base_point.y));
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci			return distance_a_to_base < distance_b_to_base;
274e5c31af7Sopenharmony_ci		}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci		_tess_coordinate_cartesian base_point;
277e5c31af7Sopenharmony_ci	};
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci	/** Comparator that is used to compare two tessellation coordinates using FP value
280e5c31af7Sopenharmony_ci	 *  equal operator.
281e5c31af7Sopenharmony_ci	 */
282e5c31af7Sopenharmony_ci	struct _comparator_exact_tess_coordinate_match
283e5c31af7Sopenharmony_ci	{
284e5c31af7Sopenharmony_ci		/* Constructor.
285e5c31af7Sopenharmony_ci		 *
286e5c31af7Sopenharmony_ci		 * @param in_base_coordinate Base tessellation coordinate to compare against.
287e5c31af7Sopenharmony_ci		 */
288e5c31af7Sopenharmony_ci		_comparator_exact_tess_coordinate_match(const _tess_coordinate_cartesian& in_base_coordinate)
289e5c31af7Sopenharmony_ci			: base_coordinate(in_base_coordinate)
290e5c31af7Sopenharmony_ci		{
291e5c31af7Sopenharmony_ci		}
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ci		/* Tells if the user-provided tessellation coordinate exactly matches the base tessellation
294e5c31af7Sopenharmony_ci		 * coordinate.
295e5c31af7Sopenharmony_ci		 *
296e5c31af7Sopenharmony_ci		 * @param value Tessellation coordinate to use for the operation.
297e5c31af7Sopenharmony_ci		 *
298e5c31af7Sopenharmony_ci		 * @return true if the coordinates are equal, false otherwise.
299e5c31af7Sopenharmony_ci		 */
300e5c31af7Sopenharmony_ci		bool operator()(const _tess_coordinate_cartesian& value)
301e5c31af7Sopenharmony_ci		{
302e5c31af7Sopenharmony_ci			return (value.x == base_coordinate.x) && (value.y == base_coordinate.y);
303e5c31af7Sopenharmony_ci		}
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ci		_tess_coordinate_cartesian base_coordinate;
306e5c31af7Sopenharmony_ci	};
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci	/* Private methods */
309e5c31af7Sopenharmony_ci	static bool compareEdgeByX(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b);
310e5c31af7Sopenharmony_ci	static bool compareEdgeByY(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b);
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ci	bool isPointOnLine(const _tess_coordinate_cartesian& line_v1, const _tess_coordinate_cartesian& line_v2,
313e5c31af7Sopenharmony_ci					   const _tess_coordinate_cartesian& point);
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci	_tess_edges getEdgesForIsolinesTessellation(const _run& run);
316e5c31af7Sopenharmony_ci	_tess_edges getEdgesForQuadsTessellation(const _run& run);
317e5c31af7Sopenharmony_ci	_tess_edges getEdgesForTrianglesTessellation(const _run& run);
318e5c31af7Sopenharmony_ci	void verifyEdges(const _tess_edges& edges, const _run& run);
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ci	/* Private variables */
321e5c31af7Sopenharmony_ci	glw::GLint				 m_gl_max_tess_gen_level_value;
322e5c31af7Sopenharmony_ci	glw::GLuint				 m_vao_id;
323e5c31af7Sopenharmony_ci	_runs					 m_runs;
324e5c31af7Sopenharmony_ci	TessellationShaderUtils* m_utils;
325e5c31af7Sopenharmony_ci};
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci} // namespace glcts
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci#endif // _ESEXTCTESSELLATIONSHADERVERTEXSPACING_HPP
330