1 #ifndef _GL3CCLIPDISTANCE_HPP
2 #define _GL3CCLIPDISTANCE_HPP
3 /*-------------------------------------------------------------------------
4 * OpenGL Conformance Test Suite
5 * -----------------------------
6 *
7 * Copyright (c) 2015-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 */ /*!
28 * \file gl3cClipDistance.hpp
29 * \brief Conformance tests for Clip Distance feature functionality.
30 */ /*-------------------------------------------------------------------*/
31
32 #include "glcTestCase.hpp"
33 #include "gluDefs.hpp"
34 #include "glwDefs.hpp"
35 #include "tcuDefs.hpp"
36
37 /* Includes. */
38 #include <cstring>
39 #include <map>
40 #include <typeinfo>
41 #include <vector>
42
43 #include "glwEnums.hpp"
44 #include "glwFunctions.hpp"
45
46 namespace gl3cts
47 {
48 namespace ClipDistance
49 {
50 namespace Utility
51 {
52 /** @class Program
53 *
54 * @brief GLSL program encapsulation class.
55 */
56 class Program
57 {
58 public:
59 /* Public type definitions */
60
61 /** @struct CompilationStatus
62 *
63 * @brief GLSL shader encapsulation class.
64 */
65 struct CompilationStatus
66 {
67 glw::GLuint shader_id;
68 glw::GLint shader_compilation_status;
69 std::string shader_log;
70 };
71
72 /** @struct CompilationStatus
73 *
74 * @brief GLSL shader encapsulation class.
75 */
76 struct LinkageStatus
77 {
78 glw::GLuint program_id;
79 glw::GLint program_linkage_status;
80 std::string program_linkage_log;
81 };
82
83 /* Public member variables */
84 Program(const glw::Functions &gl, const std::string &vertex_shader_code, const std::string &fragment_shader_code,
85 std::vector<std::string> transform_feedback_varyings = std::vector<std::string>());
86
87 ~Program();
88
89 const CompilationStatus &VertexShaderStatus() const;
90 const CompilationStatus &FragmentShaderStatus() const;
91 const LinkageStatus &ProgramStatus() const;
92
93 void UseProgram() const;
94
95 private:
96 /* Private member variables */
97 CompilationStatus m_vertex_shader_status;
98 CompilationStatus m_fragment_shader_status;
99 LinkageStatus m_program_status;
100
101 const glw::Functions &m_gl;
102
103 /* Private member functions */
104 CompilationStatus compileShader(const glw::GLenum shader_type, const glw::GLchar *const *shader_code);
105
106 LinkageStatus linkShaders(const CompilationStatus &vertex_shader, const CompilationStatus &fragment_shader,
107 std::vector<std::string> &transform_feedback_varyings);
108 };
109 /* Program class */
110
111 /** @class Framebuffer
112 *
113 * @brief OpenGL's Framebuffer encapsulation class.
114 *
115 * @note Created framebuffer is red-color-only and float type.
116 */
117 class Framebuffer
118 {
119 public:
120 Framebuffer(const glw::Functions &gl, const glw::GLsizei size_x, const glw::GLsizei size_y);
121 ~Framebuffer();
122
123 bool isValid();
124 void bind();
125 std::vector<glw::GLfloat> readPixels();
126 void clear();
127
128 private:
129 const glw::Functions &m_gl;
130 const glw::GLsizei m_size_x;
131 const glw::GLsizei m_size_y;
132 glw::GLuint m_framebuffer_id;
133 glw::GLuint m_renderbuffer_id;
134 };
135 /* Framebuffer class */
136
137 /** @class Vertex Array Object
138 *
139 * @brief OpenGL's Vertex Array Object encapsulation class.
140 */
141 class VertexArrayObject
142 {
143 public:
144 VertexArrayObject(const glw::Functions &gl, const glw::GLenum primitive_type); // create empty vao
145 ~VertexArrayObject();
146
147 void bind();
148 void draw(glw::GLuint first, glw::GLuint count);
149 void drawWithTransformFeedback(glw::GLuint first, glw::GLuint count, bool discard_rasterizer);
150
151 private:
152 const glw::Functions &m_gl;
153 glw::GLuint m_vertex_array_object_id;
154 glw::GLenum m_primitive_type;
155 };
156 /* VertexArrayObject class */
157
158 /** @class Vertex Buffer Object
159 *
160 * @brief OpenGL's Vertex Buffer Object encapsulation template class.
161 *
162 * @note Input data type is a template parameter.
163 */
164 template <class T>
165 class VertexBufferObject
166 {
167 public:
168 VertexBufferObject(const glw::Functions &gl, const glw::GLenum target, std::vector<T> data);
169 ~VertexBufferObject();
170
171 bool bind();
172 bool useAsShaderInput(Program program, std::string input_attribute_name, glw::GLint number_of_components);
173 std::vector<T> readBuffer();
174
175 private:
176 const glw::Functions &m_gl;
177 glw::GLuint m_vertex_buffer_object_id;
178 glw::GLenum m_target;
179 glw::GLsizei m_size;
180
181 std::vector<glw::GLint> m_enabled_arrays;
182 };
183 /* VertexBufferObject template class */
184
185 std::string preprocessCode(std::string source, std::string key, std::string value);
186 std::string itoa(glw::GLint i);
187 } // namespace Utility
188
189 /** @class Tests
190 *
191 * @brief Clip distance test group.
192 */
193 class Tests : public deqp::TestCaseGroup
194 {
195 public:
196 /* Public member functions */
197 Tests(deqp::Context &context);
198
199 void init();
200
201 private:
202 /* Private member functions */
203 Tests(const Tests &other);
204 Tests &operator=(const Tests &other);
205 };
206
207 /** @class CoverageTest
208 *
209 * @brief Clip distance API Coverage test cases.
210 */
211 class CoverageTest : public deqp::TestCase
212 {
213 public:
214 /* Public member functions */
215 CoverageTest(deqp::Context &context);
216
217 virtual tcu::TestNode::IterateResult iterate();
218
219 private:
220 /* Private member functions */
221 CoverageTest(const CoverageTest &other);
222 CoverageTest &operator=(const CoverageTest &other);
223
224 bool MaxClipDistancesValueTest(const glw::Functions &gl);
225 bool EnableDisableTest(const glw::Functions &gl);
226 bool MaxClipDistancesValueInVertexShaderTest(const glw::Functions &gl);
227 bool MaxClipDistancesValueInFragmentShaderTest(const glw::Functions &gl);
228 bool ClipDistancesValuePassing(const glw::Functions &gl);
229
230 /* Private member variables */
231 glw::GLint m_gl_max_clip_distances_value;
232
233 /* Private static constants */
234 static const glw::GLchar *m_vertex_shader_code_case_0;
235 static const glw::GLchar *m_fragment_shader_code_case_0;
236
237 static const glw::GLchar *m_vertex_shader_code_case_1;
238 static const glw::GLchar *m_fragment_shader_code_case_1;
239
240 static const glw::GLchar *m_vertex_shader_code_case_2;
241 static const glw::GLchar *m_fragment_shader_code_case_2;
242 };
243
244 /** @class FunctionalTest
245 *
246 * @brief Clip distance Functional test cases.
247 */
248 class FunctionalTest : public deqp::TestCase
249 {
250 public:
251 /* Public member functions */
252 FunctionalTest(deqp::Context &context);
253
254 virtual void init();
255 virtual tcu::TestNode::IterateResult iterate();
256
257 private:
258 /* Private member functions */
259 FunctionalTest(const FunctionalTest &other);
260 FunctionalTest &operator=(const FunctionalTest &other);
261
262 std::string prepareVertexShaderCode(bool explicit_redeclaration, bool dynamic_setter, glw::GLuint clip_count,
263 glw::GLuint clip_function, glw::GLenum primitive_type);
264
265 gl3cts::ClipDistance::Utility::VertexBufferObject<glw::GLfloat> *prepareGeometry(const glw::Functions &gl,
266 const glw::GLenum primitive_type);
267
268 bool checkResults(glw::GLenum primitive_type, glw::GLuint clip_function, std::vector<glw::GLfloat> &results);
269
270 /* Private member variables */
271 glw::GLint m_gl_max_clip_distances_value;
272
273 /* Private static constants */
274 static const glw::GLchar *m_vertex_shader_code;
275 static const glw::GLchar *m_fragment_shader_code;
276 static const glw::GLchar *m_dynamic_array_setter;
277 static const glw::GLchar *m_static_array_setter;
278 static const glw::GLchar *m_explicit_redeclaration;
279 static const glw::GLchar *m_clip_function[];
280 static const glw::GLuint m_clip_function_count;
281
282 static const glw::GLenum m_primitive_types[];
283 static const glw::GLenum m_primitive_indices[];
284 static const glw::GLuint m_primitive_types_count;
285
286 static const glw::GLfloat m_expected_integral[];
287 };
288
289 /** @class NegativeTest
290 *
291 * @brief Clip distance API Negative test cases.
292 */
293 class NegativeTest : public deqp::TestCase
294 {
295 public:
296 /* Public member functions */
297 NegativeTest(deqp::Context &context);
298
299 virtual tcu::TestNode::IterateResult iterate();
300
301 private:
302 /* Private member functions */
303 NegativeTest(const NegativeTest &other);
304 NegativeTest &operator=(const NegativeTest &other);
305
306 bool testClipVertexBuildingErrors(const glw::Functions &gl);
307 bool testMaxClipDistancesBuildingErrors(const glw::Functions &gl);
308 bool testClipDistancesRedeclarationBuildingErrors(const glw::Functions &gl);
309
310 /* Private static constants */
311 static const glw::GLchar *m_vertex_shader_code_case_0;
312 static const glw::GLchar *m_vertex_shader_code_case_1;
313 static const glw::GLchar *m_vertex_shader_code_case_2;
314 static const glw::GLchar *m_fragment_shader_code;
315 };
316 } // namespace ClipDistance
317 } // namespace gl3cts
318
319 /* Template classes' implementation */
320
321 /** @brief Vertex Buffer Object constructor.
322 *
323 * @note It silently binds VAO to OpenGL.
324 *
325 * @param [in] gl OpenGL functions access.
326 * @param [in] target Binding target of the VBO.
327 * @param [in] data Data of the buffer (may be empty).
328 */
329 template <class T>
VertexBufferObject(const glw::Functions & gl,const glw::GLenum target,std::vector<T> data)330 gl3cts::ClipDistance::Utility::VertexBufferObject<T>::VertexBufferObject(const glw::Functions &gl,
331 const glw::GLenum target, std::vector<T> data)
332 : m_gl(gl)
333 , m_vertex_buffer_object_id(0)
334 , m_target(target)
335 , m_size(0)
336 {
337 m_gl.genBuffers(1, &m_vertex_buffer_object_id);
338 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenBuffers call failed.");
339
340 if (m_vertex_buffer_object_id)
341 {
342 m_size = (glw::GLsizei)(sizeof(T) * data.size());
343
344 bind();
345
346 m_gl.bufferData(m_target, m_size, &data[0], GL_STATIC_DRAW);
347 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBufferData call failed.");
348 }
349 }
350
351 /** @brief Vertex Buffer Object destructor. */
352 template <class T>
~VertexBufferObject()353 gl3cts::ClipDistance::Utility::VertexBufferObject<T>::~VertexBufferObject()
354 {
355 m_gl.deleteBuffers(1, &m_vertex_buffer_object_id); /* Delete silently unbinds the buffer. */
356 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers call failed.");
357
358 for (std::vector<glw::GLint>::iterator i_enabled_array = m_enabled_arrays.begin();
359 i_enabled_array != m_enabled_arrays.end(); ++i_enabled_array)
360 {
361 m_gl.disableVertexAttribArray(*i_enabled_array);
362 }
363 }
364
365 /** @brief Bind Vertex Buffer Object to its target.
366 *
367 * @note It binds also to indexed binding point for GL_TRANSFORM_FEEDBACK_BUFFER target.
368 */
369 template <class T>
bind()370 bool gl3cts::ClipDistance::Utility::VertexBufferObject<T>::bind()
371 {
372 if (m_vertex_buffer_object_id)
373 {
374 m_gl.bindBuffer(m_target, m_vertex_buffer_object_id);
375 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer call failed.");
376
377 if (m_target == GL_TRANSFORM_FEEDBACK_BUFFER)
378 {
379 m_gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_vertex_buffer_object_id);
380 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBufferBase call failed.");
381 }
382
383 return true;
384 }
385
386 return false;
387 }
388
389 /** @brief Use VBO as attribute vertex array.
390 *
391 * @note It silently binds VBO.
392 *
393 * @param [in] program GLSL Program to which VBO shall be bound.
394 * @param [in] input_attribute_name Name of GLSL asttribute.
395 * @param [in] number_of_components Number of attribute's components.
396 *
397 * @return True on success, false otherwise.
398 */
399 template <class T>
useAsShaderInput(Program program,std::string input_attribute_name,glw::GLint number_of_components)400 bool gl3cts::ClipDistance::Utility::VertexBufferObject<T>::useAsShaderInput(Program program,
401 std::string input_attribute_name,
402 glw::GLint number_of_components)
403 {
404 if (program.ProgramStatus().program_id)
405 {
406 glw::GLint location = m_gl.getAttribLocation(program.ProgramStatus().program_id, input_attribute_name.c_str());
407 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetAttribLocation call failed.");
408
409 if (location >= 0)
410 {
411 const std::type_info &buffer_type = typeid(T);
412 const std::type_info &float_type = typeid(glw::GLfloat);
413 const std::type_info &int_type = typeid(glw::GLint);
414
415 m_gl.enableVertexAttribArray(location);
416 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glEnableVertexAttribArray call failed.");
417 m_enabled_arrays.push_back(location);
418
419 bind();
420
421 if (buffer_type == float_type)
422 {
423 m_gl.vertexAttribPointer(location, number_of_components, GL_FLOAT, false, 0, NULL);
424 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribPointer call failed.");
425 }
426 else if (buffer_type == int_type)
427 {
428 m_gl.vertexAttribIPointer(location, number_of_components, GL_FLOAT, 0, NULL);
429 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glVertexAttribIPointer call failed.");
430 }
431 else
432 {
433 return false;
434 }
435
436 return true;
437 }
438 }
439
440 return false;
441 }
442
443 /** @brief Read VBO content (potentially set by transform feedback).
444 *
445 * @return Content of VBO.
446 */
447 template <class T>
readBuffer()448 std::vector<T> gl3cts::ClipDistance::Utility::VertexBufferObject<T>::readBuffer()
449 {
450 std::vector<T> buffer_data(m_size / sizeof(T));
451
452 bind();
453
454 glw::GLvoid *results = m_gl.mapBuffer(m_target, GL_READ_ONLY);
455
456 if (results)
457 {
458 memcpy(&buffer_data[0], results, m_size);
459 }
460
461 m_gl.unmapBuffer(m_target);
462
463 return buffer_data;
464 }
465 #endif // _GL3CCLIPDISTANCE_HPP
466