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