xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl3cTransformFeedbackTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  */ /*!
26  * \file  gl3cTransformFeedback.cpp
27  * \brief Transform Feedback Test Suite Implementation
28  */ /*-------------------------------------------------------------------*/
29 
30 /* Includes. */
31 #include "gl3cTransformFeedbackTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "gluRenderContext.hpp"
35 #include "gluStrUtil.hpp"
36 #include "tcuTestLog.hpp"
37 
38 #include <algorithm>
39 #include <climits>
40 #include <cmath>
41 #include <cstdlib>
42 #include <sstream>
43 
44 /* Stringify macro. */
45 #define _STR(s) STR(s)
46 #define STR(s) #s
47 
48 /* Unused attribute / variable MACRO.
49  Some methods of clesses' heirs do not need all function parameters.
50  This triggers warnings on GCC platform. This macro will silence them.
51  */
52 #ifdef __GNUC__
53 #define UNUSED __attribute__((__unused__))
54 #else
55 #define UNUSED
56 #endif
57 
58 /* compatibility profile or context with GL_ARB_compatibility supports GL_QUAD_STRIP and GL_POLYGON */
59 #ifndef GL_QUAD_STRIP
60 #define GL_QUAD_STRIP 0x0008
61 #endif
62 #ifndef GL_POLYGON
63 #define GL_POLYGON 0x0009
64 #endif
65 
Tests(deqp::Context & context)66 gl3cts::TransformFeedback::Tests::Tests(deqp::Context &context)
67     : TestCaseGroup(context, "transform_feedback", "Transform Feedback Test Suite")
68 {
69     addChild(new TransformFeedback::APIErrors(m_context));
70     addChild(new TransformFeedback::LinkingErrors(m_context));
71     addChild(new TransformFeedback::Limits(m_context));
72     addChild(new TransformFeedback::CaptureVertexInterleaved(m_context, "capture_vertex_interleaved_test",
73                                                              "Transform Feedback Capture Vertex Interleaved Test"));
74     addChild(new TransformFeedback::CaptureGeometryInterleaved(m_context, "capture_geometry_interleaved_test",
75                                                                "Transform Feedback Capture Geometry Interleaved Test"));
76     addChild(new TransformFeedback::CaptureVertexSeparate(m_context, "capture_vertex_separate_test",
77                                                           "Transform Feedback Capture Vertex Separate Test"));
78     addChild(new TransformFeedback::CaptureGeometrySeparate(m_context, "capture_geometry_separate_test",
79                                                             "Transform Feedback Capture Geometry Separate Test"));
80     addChild(new TransformFeedback::CheckGetXFBVarying(m_context, "get_xfb_varying",
81                                                        "Transform Feedback Varying Getters Test"));
82     addChild(new TransformFeedback::QueryVertexInterleaved(m_context, "query_vertex_interleaved_test",
83                                                            "Transform Feedback Query Vertex Interleaved Test"));
84     addChild(new TransformFeedback::QueryGeometryInterleaved(m_context, "query_geometry_interleaved_test",
85                                                              "Transform Feedback Query Geometry Interleaved Test"));
86     addChild(new TransformFeedback::QueryVertexSeparate(m_context, "query_vertex_separate_test",
87                                                         "Transform Feedback Query Vertex Separate Test"));
88     addChild(new TransformFeedback::QueryGeometrySeparate(m_context, "query_geometry_separate_test",
89                                                           "Transform Feedback Query Geometry Separate Test"));
90     addChild(new TransformFeedback::DiscardVertex(m_context, "discard_vertex_test",
91                                                   "Transform Feedback Discard Vertex Test"));
92     addChild(new TransformFeedback::DiscardGeometry(m_context, "discard_geometry_test",
93                                                     "Transform Feedback Discard Geometry Test"));
94     addChild(new TransformFeedback::DrawXFB(m_context, "draw_xfb_test", "Transform Feedback Draw Test"));
95     addChild(new TransformFeedback::DrawXFBFeedback(m_context, "draw_xfb_feedbackk_test",
96                                                     "Transform Feedback Draw Feedback Test"));
97     addChild(
98         new TransformFeedback::DrawXFBStream(m_context, "draw_xfb_stream_test", "Transform Feedback Draw Stream Test"));
99     addChild(new TransformFeedback::CaptureSpecialInterleaved(m_context, "capture_special_interleaved_test",
100                                                               "Transform Feedback Capture Special Test"));
101     addChild(new TransformFeedback::DrawXFBInstanced(m_context, "draw_xfb_instanced_test",
102                                                      "Transform Feedback Draw Instanced Test"));
103     addChild(new TransformFeedback::DrawXFBStreamInstanced(m_context, "draw_xfb_stream_instanced_test",
104                                                            "Transform Feedback Draw Stream Instanced Test"));
105 }
106 
~Tests(void)107 gl3cts::TransformFeedback::Tests::~Tests(void)
108 {
109 }
110 
init(void)111 void gl3cts::TransformFeedback::Tests::init(void)
112 {
113 }
114 
APIErrors(deqp::Context & context)115 gl3cts::TransformFeedback::APIErrors::APIErrors(deqp::Context &context)
116     : deqp::TestCase(context, "api_errors_test", "Transform Feedback API Errors Test")
117     , m_context(context)
118     , m_buffer_0(0)
119     , m_buffer_1(0)
120     , m_vertex_array_object(0)
121     , m_transform_feedback_object_0(0)
122     , m_transform_feedback_object_1(0)
123     , m_query_object(0)
124     , m_program_id_with_input_output(0)
125     , m_program_id_with_output(0)
126     , m_program_id_without_output(0)
127     , m_program_id_with_geometry_shader(0)
128     , m_program_id_with_tessellation_shaders(0)
129     , m_glBindBufferOffsetEXT(DE_NULL)
130     , m_glGetIntegerIndexedvEXT(DE_NULL)
131     , m_glGetBooleanIndexedvEXT(DE_NULL)
132 {
133 }
134 
~APIErrors(void)135 gl3cts::TransformFeedback::APIErrors::~APIErrors(void)
136 {
137 }
138 
iterate(void)139 tcu::TestNode::IterateResult gl3cts::TransformFeedback::APIErrors::iterate(void)
140 {
141     /* Functions handler */
142     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
143 
144     /* Initializations. */
145     bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
146     bool is_at_least_gl_33 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 3)));
147     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
148     bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
149 
150     bool is_ext_tf_1         = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
151     bool is_arb_tf_2         = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
152     bool is_arb_tf_3         = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
153     bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
154 
155     if (is_ext_tf_1)
156     {
157         /* Extension query. */
158         m_glBindBufferOffsetEXT =
159             (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
160         m_glGetIntegerIndexedvEXT =
161             (GetIntegerIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetIntegerIndexedvEXT");
162         m_glGetBooleanIndexedvEXT =
163             (GetBooleanIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetBooleanIndexedvEXT");
164     }
165 
166     if (is_at_least_gl_40 || is_arb_tf_2)
167     {
168         /* Create transform feedback objects. */
169         gl.genTransformFeedbacks(1, &m_transform_feedback_object_0);
170 
171         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
172     }
173 
174     if (is_at_least_gl_40 || is_arb_tf_3)
175     {
176         /* Create query object. */
177         gl.genQueries(1, &m_query_object);
178 
179         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
180     }
181 
182     if (is_at_least_gl_42 || is_arb_tf_instanced)
183     {
184         /* Create transform feedback objects. */
185         gl.genTransformFeedbacks(1, &m_transform_feedback_object_1);
186 
187         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
188     }
189 
190     /* Default result. */
191     bool is_ok      = true;
192     bool test_error = false;
193 
194     /* Entities setup. */
195     try
196     {
197         /* VAO setup. */
198         gl.genVertexArrays(1, &m_vertex_array_object);
199         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
200 
201         gl.bindVertexArray(m_vertex_array_object);
202         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
203 
204         /* Buffer setup. */
205         gl.genBuffers(1, &m_buffer_0);
206         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
207 
208         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_0);
209         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
210 
211         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_STATIC_DRAW);
212         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
213 
214         gl.genBuffers(1, &m_buffer_1);
215         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
216 
217         gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_1);
218         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
219 
220         gl.bufferData(GL_ARRAY_BUFFER, m_buffer_1_size, m_buffer_1_data, GL_STATIC_DRAW);
221         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
222 
223         /* Programs setup. */
224 
225         m_program_id_with_input_output = gl3cts::TransformFeedback::Utilities::buildProgram(
226             gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_input_output,
227             s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
228 
229         m_program_id_with_output = gl3cts::TransformFeedback::Utilities::buildProgram(
230             gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_output, s_fragment_shader,
231             &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS, true);
232 
233         m_program_id_without_output = gl3cts::TransformFeedback::Utilities::buildProgram(
234             gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_without_output,
235             s_fragment_shader, NULL, 0, GL_SEPARATE_ATTRIBS);
236 
237         is_ok = is_ok && m_program_id_with_input_output && m_program_id_with_output && m_program_id_without_output;
238 
239         if (is_at_least_gl_33)
240         {
241             m_program_id_with_geometry_shader = gl3cts::TransformFeedback::Utilities::buildProgram(
242                 gl, m_context.getTestContext().getLog(), m_geometry_shader, NULL, NULL, s_vertex_shader_without_output,
243                 s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
244 
245             is_ok = is_ok && m_program_id_with_geometry_shader;
246         }
247 
248         if (is_at_least_gl_40)
249         {
250             m_program_id_with_tessellation_shaders = gl3cts::TransformFeedback::Utilities::buildProgram(
251                 gl, m_context.getTestContext().getLog(), NULL, m_tessellation_control_shader,
252                 m_tessellation_evaluation_shader, s_vertex_shader_without_output, s_fragment_shader, &m_varying_name, 1,
253                 GL_INTERLEAVED_ATTRIBS);
254             is_ok = is_ok && m_program_id_with_tessellation_shaders;
255         }
256     }
257     catch (...)
258     {
259         is_ok      = false;
260         test_error = true;
261     }
262 
263     /* Iterating tests. */
264     try
265     {
266         if (is_at_least_gl_30 || is_ext_tf_1)
267         {
268             is_ok = is_ok && testExtension1();
269         }
270 
271         if (is_at_least_gl_40 || is_arb_tf_2)
272         {
273             is_ok = is_ok && testExtension2();
274         }
275 
276         if (is_at_least_gl_40 || is_arb_tf_3)
277         {
278             is_ok = is_ok && testExtension3();
279         }
280 
281         if (is_at_least_gl_42 || is_arb_tf_instanced)
282         {
283             is_ok = is_ok && testInstanced();
284         }
285     }
286     catch (...)
287     {
288         is_ok      = false;
289         test_error = true;
290     }
291 
292     /* Deinitialization. */
293     if (m_vertex_array_object)
294     {
295         gl.deleteVertexArrays(1, &m_vertex_array_object);
296 
297         m_vertex_array_object = 0;
298     }
299 
300     if (m_buffer_0)
301     {
302         gl.deleteBuffers(1, &m_buffer_0); // silently unbinds
303 
304         m_buffer_0 = 0;
305     }
306 
307     if (m_buffer_1)
308     {
309         gl.deleteBuffers(1, &m_buffer_1); // silently unbinds
310 
311         m_buffer_1 = 0;
312     }
313 
314     if (m_transform_feedback_object_0)
315     {
316         gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
317 
318         m_transform_feedback_object_0 = 0;
319     }
320 
321     if (m_transform_feedback_object_1)
322     {
323         gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_1);
324 
325         m_transform_feedback_object_1 = 0;
326     }
327 
328     if (m_query_object)
329     {
330         gl.deleteQueries(1, &m_query_object);
331 
332         m_query_object = 0;
333     }
334 
335     if (m_program_id_with_input_output)
336     {
337         gl.deleteProgram(m_program_id_with_input_output);
338 
339         m_program_id_with_input_output = 0;
340     }
341 
342     if (m_program_id_with_output)
343     {
344         gl.deleteProgram(m_program_id_with_output);
345 
346         m_program_id_with_output = 0;
347     }
348 
349     if (m_program_id_without_output)
350     {
351         gl.deleteProgram(m_program_id_without_output);
352 
353         m_program_id_without_output = 0;
354     }
355 
356     if (m_program_id_with_geometry_shader)
357     {
358         gl.deleteProgram(m_program_id_with_geometry_shader);
359 
360         m_program_id_with_geometry_shader = 0;
361     }
362 
363     if (m_program_id_with_tessellation_shaders)
364     {
365         gl.deleteProgram(m_program_id_with_tessellation_shaders);
366 
367         m_program_id_with_tessellation_shaders = 0;
368     }
369 
370     /* Result's setup. */
371     if (is_ok)
372     {
373         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
374     }
375     else
376     {
377         if (test_error)
378         {
379             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
380         }
381         else
382         {
383             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
384         }
385     }
386 
387     return STOP;
388 }
389 
testExtension1(void)390 bool gl3cts::TransformFeedback::APIErrors::testExtension1(void)
391 {
392     /* Functions handler */
393     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
394 
395     /*  INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and
396      BindBufferBase when <index> is greater or equal to
397      MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; */
398 
399     glw::GLint index_count = 0;
400 
401     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &index_count);
402 
403     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
404 
405     if (index_count == 0)
406     {
407         m_context.getTestContext().getLog()
408             << tcu::TestLog::Message << "glGetIntegerv did not returned any value." << tcu::TestLog::EndMessage;
409         throw 0;
410     }
411 
412     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 16);
413 
414     if (GL_INVALID_VALUE != gl.getError())
415     {
416         m_context.getTestContext().getLog() << tcu::TestLog::Message
417                                             << "INVALID_VALUE was not generated by BindBufferRange "
418                                                "when <index> was greater or equal to "
419                                                "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
420                                             << tcu::TestLog::EndMessage;
421         return false;
422     }
423 
424     if (DE_NULL != m_glBindBufferOffsetEXT)
425     {
426         m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0);
427 
428         if (GL_INVALID_VALUE != gl.getError())
429         {
430             m_context.getTestContext().getLog() << tcu::TestLog::Message
431                                                 << "INVALID_VALUE was not generated by BindBufferOffset "
432                                                    "when <index> was greater or equal to "
433                                                    "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
434                                                 << tcu::TestLog::EndMessage;
435             return false;
436         }
437     }
438 
439     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0);
440 
441     if (GL_INVALID_VALUE != gl.getError())
442     {
443         m_context.getTestContext().getLog() << tcu::TestLog::Message
444                                             << "INVALID_VALUE was not generated by "
445                                                "BindBufferBase when <index> was greater or equal to "
446                                                "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
447                                             << tcu::TestLog::EndMessage;
448         return false;
449     }
450 
451     /*  INVALID_VALUE is generated by BindBufferRange when <size> is less or equal to zero; */
452 
453     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 0);
454 
455     if (GL_INVALID_VALUE != gl.getError())
456     {
457         m_context.getTestContext().getLog()
458             << tcu::TestLog::Message
459             << "INVALID_VALUE was not generated by BindBufferRange when <size> was less or equal to zero."
460             << tcu::TestLog::EndMessage;
461         return false;
462     }
463 
464     /*  INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
465      when <offset> is not word-aligned; */
466 
467     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3, 4);
468 
469     if (GL_INVALID_VALUE != gl.getError())
470     {
471         m_context.getTestContext().getLog()
472             << tcu::TestLog::Message
473             << "INVALID_VALUE was not generated by BindBufferRange when <offset> was not word-aligned."
474             << tcu::TestLog::EndMessage;
475         return false;
476     }
477 
478     if (DE_NULL != m_glBindBufferOffsetEXT)
479     {
480         m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3);
481 
482         if (GL_INVALID_VALUE != gl.getError())
483         {
484             m_context.getTestContext().getLog()
485                 << tcu::TestLog::Message
486                 << "INVALID_VALUE was not generated by BindBufferOffset when <offset> was not word-aligned."
487                 << tcu::TestLog::EndMessage;
488             return false;
489         }
490     }
491 
492     /*  INVALID_VALUE is generated by BindBufferRange when <size> is not word-aligned; */
493 
494     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 3);
495 
496     if (GL_INVALID_VALUE != gl.getError())
497     {
498         m_context.getTestContext().getLog()
499             << tcu::TestLog::Message
500             << "INVALID_VALUE was not generated by BindBufferRange when <size> was not word-aligned."
501             << tcu::TestLog::EndMessage;
502         return false;
503     }
504 
505     /*  INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and
506      BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform
507      feedback is active; */
508 
509     gl.useProgram(m_program_id_with_output);
510 
511     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
512 
513     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
514 
515     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
516 
517     gl.beginTransformFeedback(GL_POINTS);
518 
519     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
520 
521     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0, 16);
522 
523     if (GL_INVALID_OPERATION != gl.getError())
524     {
525         m_context.getTestContext().getLog() << tcu::TestLog::Message
526                                             << "INVALID_OPERATION was not generated by BindBufferRange "
527                                                "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
528                                                "feedback was active."
529                                             << tcu::TestLog::EndMessage;
530 
531         gl.endTransformFeedback();
532 
533         return false;
534     }
535 
536     if (DE_NULL != m_glBindBufferOffsetEXT)
537     {
538         m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0);
539 
540         if (GL_INVALID_OPERATION != gl.getError())
541         {
542             m_context.getTestContext().getLog() << tcu::TestLog::Message
543                                                 << "INVALID_OPERATION was not generated by BindBufferOffset "
544                                                    "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
545                                                    "feedback was active."
546                                                 << tcu::TestLog::EndMessage;
547 
548             gl.endTransformFeedback();
549 
550             return false;
551         }
552     }
553 
554     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
555 
556     if (GL_INVALID_OPERATION != gl.getError())
557     {
558         m_context.getTestContext().getLog()
559             << tcu::TestLog::Message
560             << "INVALID_OPERATION was not generated by "
561                "BindBufferBase when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
562                "feedback was active."
563             << tcu::TestLog::EndMessage;
564 
565         gl.endTransformFeedback();
566 
567         return false;
568     }
569 
570     gl.endTransformFeedback();
571 
572     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
573 
574     /*  INVALID_OPERATION is generated by UseProgram when transform feedback is
575      active; */
576 
577     gl.beginTransformFeedback(GL_POINTS);
578 
579     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
580 
581     gl.useProgram(0);
582 
583     if (GL_INVALID_OPERATION != gl.getError())
584     {
585         m_context.getTestContext().getLog()
586             << tcu::TestLog::Message
587             << "INVALID_OPERATION was not generated by UseProgram when transform feedback was active."
588             << tcu::TestLog::EndMessage;
589 
590         gl.endTransformFeedback();
591 
592         return false;
593     }
594 
595     gl.endTransformFeedback();
596 
597     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
598 
599     /*  INVALID_OPERATION is generated by LinkProgram when <program> is currently
600      active and transform feedback is active; */
601 
602     gl.useProgram(m_program_id_with_output);
603 
604     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
605 
606     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
607 
608     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
609 
610     gl.beginTransformFeedback(GL_POINTS);
611 
612     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
613 
614     gl.linkProgram(m_program_id_with_output);
615 
616     if (GL_INVALID_OPERATION != gl.getError())
617     {
618         m_context.getTestContext().getLog() << tcu::TestLog::Message
619                                             << "INVALID_OPERATION was not generated by LinkProgram when <program> was "
620                                                "currently active and transform feedback was active."
621                                             << tcu::TestLog::EndMessage;
622 
623         gl.endTransformFeedback();
624 
625         return false;
626     }
627 
628     gl.endTransformFeedback();
629 
630     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
631 
632     /*  INVALID_OPERATION is generated by BeginTransformFeedback when transform
633      feedback is active; */
634 
635     gl.useProgram(m_program_id_with_output);
636 
637     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
638 
639     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
640 
641     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
642 
643     gl.beginTransformFeedback(GL_POINTS);
644 
645     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
646 
647     gl.beginTransformFeedback(GL_POINTS);
648 
649     if (GL_INVALID_OPERATION != gl.getError())
650     {
651         m_context.getTestContext().getLog()
652             << tcu::TestLog::Message
653             << "INVALID_OPERATION was not generated by BeginTransformFeedback when transform feedback was active."
654             << tcu::TestLog::EndMessage;
655 
656         gl.endTransformFeedback();
657 
658         return false;
659     }
660 
661     gl.endTransformFeedback();
662 
663     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
664 
665     /*  INVALID_OPERATION is generated by EndTransformFeedback when transform
666      feedback is inactive; */
667 
668     gl.endTransformFeedback();
669 
670     if (GL_INVALID_OPERATION != gl.getError())
671     {
672         m_context.getTestContext().getLog()
673             << tcu::TestLog::Message
674             << "INVALID_OPERATION was not generated by EndTransformFeedback when transform feedback was inactive."
675             << tcu::TestLog::EndMessage;
676 
677         return false;
678     }
679 
680     /*  INVALID_OPERATION is generated by draw command when generated primitives
681      type does not match <primitiveMode>; */
682 
683     gl.useProgram(m_program_id_with_output);
684 
685     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
686 
687     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
688 
689     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
690 
691     gl.beginTransformFeedback(GL_POINTS);
692 
693     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
694 
695     gl.drawArrays(GL_LINES, 0, 2);
696 
697     if (GL_INVALID_OPERATION != gl.getError())
698     {
699         m_context.getTestContext().getLog() << tcu::TestLog::Message
700                                             << "INVALID_OPERATION was not generated by draw command when generated "
701                                                "primitives type does not match <primitiveMode>."
702                                             << tcu::TestLog::EndMessage;
703 
704         gl.endTransformFeedback();
705 
706         return false;
707     }
708 
709     gl.endTransformFeedback();
710 
711     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
712 
713     /*  INVALID_OPERATION is generated by BeginTransformFeedback when any binding
714      point used by XFB does not have buffer bound; */
715 
716     gl.useProgram(m_program_id_with_output);
717 
718     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
719 
720     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
721 
722     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
723 
724     gl.beginTransformFeedback(GL_POINTS);
725 
726     if (GL_INVALID_OPERATION != gl.getError())
727     {
728         m_context.getTestContext().getLog() << tcu::TestLog::Message
729                                             << "INVALID_OPERATION was not generated by BeginTransformFeedback when any "
730                                                "binding point used by XFB does not have buffer bound."
731                                             << tcu::TestLog::EndMessage;
732 
733         return false;
734     }
735 
736     /*  INVALID_OPERATION is generated by BeginTransformFeedback when no program
737      is active; */
738 
739     gl.useProgram(0);
740 
741     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
742 
743     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
744 
745     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
746 
747     gl.beginTransformFeedback(GL_POINTS);
748 
749     if (GL_INVALID_OPERATION != gl.getError())
750     {
751         m_context.getTestContext().getLog()
752             << tcu::TestLog::Message
753             << "INVALID_OPERATION was not generated by BeginTransformFeedback when no program was active."
754             << tcu::TestLog::EndMessage;
755 
756         gl.endTransformFeedback();
757 
758         return false;
759     }
760 
761     /*  INVALID_OPERATION is generated by BeginTransformFeedback when no variable
762      are specified to be captured in the active program; */
763 
764     gl.useProgram(m_program_id_without_output);
765 
766     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
767 
768     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
769 
770     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
771 
772     gl.beginTransformFeedback(GL_POINTS);
773 
774     if (GL_INVALID_OPERATION != gl.getError())
775     {
776         m_context.getTestContext().getLog()
777             << tcu::TestLog::Message
778             << "INVALID_OPERATION was not generated by BeginTransformFeedback when no variable "
779                "are specified to be captured in the active program."
780             << tcu::TestLog::EndMessage;
781 
782         gl.endTransformFeedback();
783 
784         return false;
785     }
786 
787     /*  INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is
788      not id of the program object; */
789 
790     unsigned short int invalid_name = 1;
791 
792     while (gl.isProgram(invalid_name) || gl.isShader(invalid_name))
793     {
794         ++invalid_name;
795 
796         /* Make sure that this loop ends someday, bad day. */
797         if (invalid_name == USHRT_MAX)
798         {
799             m_context.getTestContext().getLog()
800                 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
801             throw 0;
802         }
803     }
804 
805     gl.transformFeedbackVaryings((glw::GLuint)invalid_name, 1, &m_varying_name, GL_INTERLEAVED_ATTRIBS);
806 
807     if (GL_INVALID_VALUE != gl.getError())
808     {
809         m_context.getTestContext().getLog() << tcu::TestLog::Message
810                                             << "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
811                                                "<program> was not id of the program object."
812                                             << tcu::TestLog::EndMessage;
813         return false;
814     }
815 
816     /*  INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode>
817      is SEPARATE_ATTRIBS and <count> is exceeds limits; */
818 
819     glw::GLint max_separate_attribs = 0;
820 
821     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_separate_attribs);
822 
823     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
824 
825     if (max_separate_attribs == 0)
826     {
827         m_context.getTestContext().getLog()
828             << tcu::TestLog::Message
829             << "INVALID_VALUE was not generated by TransformFeedbackVaryings when <bufferMode>"
830                " was SEPARATE_ATTRIBS and <count> was exceeds limits."
831             << tcu::TestLog::EndMessage;
832         throw 0;
833     }
834 
835     glw::GLint more_than_max_separate_attribs = max_separate_attribs + 1;
836 
837     glw::GLchar **attrib = new glw::GLchar *[more_than_max_separate_attribs];
838 
839     for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
840     {
841         std::string new_attrib = "a" + gl3cts::TransformFeedback::Utilities::itoa(i);
842 
843         size_t new_attrib_size = new_attrib.size();
844 
845         attrib[i] = new glw::GLchar[new_attrib_size + 1];
846 
847         memset(attrib[i], 0, new_attrib_size + 1);
848 
849         memcpy(attrib[i], new_attrib.c_str(), new_attrib_size);
850     }
851 
852     gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_separate_attribs, attrib, GL_SEPARATE_ATTRIBS);
853 
854     for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
855     {
856         delete[] attrib[i];
857     }
858 
859     delete[] attrib;
860 
861     if (GL_INVALID_VALUE != gl.getError())
862     {
863         m_context.getTestContext().getLog() << tcu::TestLog::Message
864                                             << "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
865                                                "<bufferMode> was SEPARATE_ATTRIBS and <count> exceeded limits."
866                                             << tcu::TestLog::EndMessage;
867         return false;
868     }
869 
870     /*  INVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is
871      greater than or equal to TRANSFORM_FEEDBACK_VARYINGS; */
872 
873     glw::GLint transform_feedback_varyings = 0;
874 
875     gl.getProgramiv(m_program_id_with_output, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings);
876 
877     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
878 
879     if (transform_feedback_varyings == 0)
880     {
881         m_context.getTestContext().getLog()
882             << tcu::TestLog::Message << "glGetProgramiv failed to return GL_TRANSFORM_FEEDBACK_VARYINGS."
883             << tcu::TestLog::EndMessage;
884         throw 0;
885     }
886 
887     glw::GLchar tmp_buffer[256];
888 
889     glw::GLsizei tmp_size = 0;
890 
891     glw::GLenum tmp_type = GL_NONE;
892 
893     gl.getTransformFeedbackVarying(m_program_id_with_output, transform_feedback_varyings, sizeof(tmp_buffer), NULL,
894                                    &tmp_size, &tmp_type, tmp_buffer);
895 
896     if (GL_INVALID_VALUE != gl.getError())
897     {
898         m_context.getTestContext().getLog() << tcu::TestLog::Message
899                                             << "INVALID_VALUE was not generated by GetTransformFeedbackVarying when "
900                                                "<index> was greater than or equal to TRANSFORM_FEEDBACK_VARYINGS."
901                                             << tcu::TestLog::EndMessage;
902         return false;
903     }
904 
905     /*  INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the
906      limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the
907      following:
908      * TRANSFORM_FEEDBACK_BUFFER_BINDING,
909      * TRANSFORM_FEEDBACK_BUFFER_START,
910      * TRANSFORM_FEEDBACK_BUFFER_SIZE; */
911 
912     if (DE_NULL != m_glGetIntegerIndexedvEXT)
913     {
914         glw::GLint tmp_int_value;
915 
916         m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs, &tmp_int_value);
917 
918         if (GL_INVALID_VALUE != gl.getError())
919         {
920             m_context.getTestContext().getLog()
921                 << tcu::TestLog::Message
922                 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
923                    "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
924                    "TRANSFORM_FEEDBACK_BUFFER_BINDING."
925                 << tcu::TestLog::EndMessage;
926             return false;
927         }
928 
929         m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_START, more_than_max_separate_attribs, &tmp_int_value);
930 
931         if (GL_INVALID_VALUE != gl.getError())
932         {
933             m_context.getTestContext().getLog()
934                 << tcu::TestLog::Message
935                 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
936                    "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
937                    "GL_TRANSFORM_FEEDBACK_BUFFER_START."
938                 << tcu::TestLog::EndMessage;
939             return false;
940         }
941 
942         m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, more_than_max_separate_attribs, &tmp_int_value);
943 
944         if (GL_INVALID_VALUE != gl.getError())
945         {
946             m_context.getTestContext().getLog()
947                 << tcu::TestLog::Message
948                 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
949                    "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
950                    "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE."
951                 << tcu::TestLog::EndMessage;
952             return false;
953         }
954     }
955 
956     /*  INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the
957      limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is
958      TRANSFORM_FEEDBACK_BUFFER_BINDING. */
959 
960     if (DE_NULL != m_glGetBooleanIndexedvEXT)
961     {
962         glw::GLboolean tmp_bool_value;
963 
964         m_glGetBooleanIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs,
965                                   &tmp_bool_value);
966 
967         if (GL_INVALID_VALUE != gl.getError())
968         {
969             m_context.getTestContext().getLog()
970                 << tcu::TestLog::Message
971                 << "INVALID_VALUE was not generated by GetBooleanIndexedv when <index> exceeds the "
972                    "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
973                    "TRANSFORM_FEEDBACK_BUFFER_BINDING."
974                 << tcu::TestLog::EndMessage;
975             return false;
976         }
977     }
978 
979     return true;
980 }
981 
testExtension2(void)982 bool gl3cts::TransformFeedback::APIErrors::testExtension2(void)
983 {
984     /* Functions handler */
985     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
986 
987     /*  Bind Transform Feedback Object */
988     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
989 
990     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
991 
992     /*  INVALID_OPERATION is generated by PauseTransformFeedback if current
993      transform feedback is not active or paused; */
994 
995     gl.pauseTransformFeedback();
996 
997     if (GL_INVALID_OPERATION != gl.getError())
998     {
999         m_context.getTestContext().getLog() << tcu::TestLog::Message
1000                                             << "INVALID_OPERATION is not generated by PauseTransformFeedback if "
1001                                                "current transform feedback is not active or paused."
1002                                             << tcu::TestLog::EndMessage;
1003 
1004         return false;
1005     }
1006 
1007     /*  INVALID_OPERATION is generated by ResumeTransformFeedback if current
1008      transform feedback is not active; */
1009 
1010     gl.resumeTransformFeedback();
1011 
1012     if (GL_INVALID_OPERATION != gl.getError())
1013     {
1014         m_context.getTestContext().getLog() << tcu::TestLog::Message
1015                                             << "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1016                                                "current transform feedback is not active."
1017                                             << tcu::TestLog::EndMessage;
1018 
1019         return false;
1020     }
1021 
1022     /*  Prepare program and buffer. */
1023     gl.useProgram(m_program_id_with_output);
1024 
1025     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1026 
1027     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1028 
1029     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
1030 
1031     /*  INVALID_OPERATION is generated by DrawTransformFeedback when
1032      EndTransformFeedback was never called for the object named <id>. */
1033     gl.drawTransformFeedback(GL_POINTS, m_transform_feedback_object_0);
1034 
1035     if (GL_INVALID_OPERATION != gl.getError())
1036     {
1037         m_context.getTestContext().getLog() << tcu::TestLog::Message
1038                                             << "INVALID_OPERATION is not generated by DrawTransformFeedback when "
1039                                                "EndTransformFeedback was never called for the object named <id>."
1040                                             << tcu::TestLog::EndMessage;
1041 
1042         return false;
1043     }
1044 
1045     /*  Make Transform Feedback Active */
1046     gl.beginTransformFeedback(GL_POINTS);
1047 
1048     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1049 
1050     /*  INVALID_OPERATION is generated by BindTransformFeedback if current
1051      transform feedback is active and not paused; */
1052 
1053     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1054 
1055     if (GL_INVALID_OPERATION != gl.getError())
1056     {
1057         gl.endTransformFeedback();
1058 
1059         m_context.getTestContext().getLog() << tcu::TestLog::Message
1060                                             << "INVALID_OPERATION is not generated by BindTransformFeedback if current "
1061                                                "transform feedback is active and not paused."
1062                                             << tcu::TestLog::EndMessage;
1063 
1064         return false;
1065     }
1066 
1067     /*  INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids>
1068      is active; */
1069 
1070     gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
1071 
1072     if (GL_INVALID_OPERATION != gl.getError())
1073     {
1074         gl.endTransformFeedback();
1075 
1076         m_context.getTestContext().getLog()
1077             << tcu::TestLog::Message
1078             << "INVALID_OPERATION is not generated by DeleteTransformFeedbacks if any of <ids> is active."
1079             << tcu::TestLog::EndMessage;
1080 
1081         return false;
1082     }
1083 
1084     /*  INVALID_OPERATION is generated by ResumeTransformFeedback if current
1085      transform feedback is not not paused; */
1086 
1087     gl.resumeTransformFeedback();
1088 
1089     if (GL_INVALID_OPERATION != gl.getError())
1090     {
1091         gl.endTransformFeedback();
1092 
1093         m_context.getTestContext().getLog() << tcu::TestLog::Message
1094                                             << "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1095                                                "current transform feedback is not not paused."
1096                                             << tcu::TestLog::EndMessage;
1097 
1098         return false;
1099     }
1100 
1101     /*  pause transform feedback */
1102 
1103     gl.pauseTransformFeedback();
1104 
1105     GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1106 
1107     /*  No error is generated by draw command when transform feedback is paused
1108      and primitive modes do not match; */
1109 
1110     gl.drawArrays(GL_LINES, 0, 2);
1111 
1112     if (GL_NO_ERROR != gl.getError())
1113     {
1114         gl.endTransformFeedback();
1115 
1116         m_context.getTestContext().getLog() << tcu::TestLog::Message
1117                                             << "No error is not generated by draw command when transform feedback is "
1118                                                "paused and primitive modes do not match."
1119                                             << tcu::TestLog::EndMessage;
1120 
1121         return false;
1122     }
1123 
1124     /*  INVALID_OPERATION is generated by LinkProgram when <program> is used by
1125      some transform feedback object that is currently not active; */
1126 
1127     gl.linkProgram(m_program_id_with_output);
1128 
1129     if (GL_INVALID_OPERATION != gl.getError())
1130     {
1131         m_context.getTestContext().getLog() << tcu::TestLog::Message
1132                                             << "INVALID_OPERATION was not generated by LinkProgram when <program> was "
1133                                                "used by some transform feedback object that is currently not active."
1134                                             << tcu::TestLog::EndMessage;
1135 
1136         gl.endTransformFeedback();
1137 
1138         return false;
1139     }
1140 
1141     /*  No error is generated by UseProgram when transform feedback is paused; */
1142 
1143     gl.useProgram(0);
1144 
1145     if (GL_NO_ERROR != gl.getError())
1146     {
1147         gl.endTransformFeedback();
1148 
1149         m_context.getTestContext().getLog()
1150             << tcu::TestLog::Message << "glUseProgram unexpectedly failed when transform feedback is paused."
1151             << tcu::TestLog::EndMessage;
1152 
1153         return false;
1154     }
1155 
1156     gl.useProgram(m_program_id_with_output);
1157 
1158     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1159 
1160     /*  End Transform Feedback and make draw. */
1161 
1162     gl.endTransformFeedback();
1163     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1164 
1165     /*  INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of
1166      transform feedback object; */
1167 
1168     unsigned short int invalid_name = 1;
1169 
1170     while (gl.isTransformFeedback(invalid_name))
1171     {
1172         ++invalid_name;
1173 
1174         /* Make sure that this loop ends someday, bad day. */
1175         if (invalid_name == USHRT_MAX)
1176         {
1177             m_context.getTestContext().getLog()
1178                 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1179             throw 0;
1180         }
1181     }
1182 
1183     gl.drawTransformFeedback(GL_POINTS, (glw::GLuint)invalid_name);
1184 
1185     if (GL_INVALID_VALUE != gl.getError())
1186     {
1187         gl.endTransformFeedback();
1188 
1189         m_context.getTestContext().getLog()
1190             << tcu::TestLog::Message << "glUseProgram unexpectedly failed when transform feedback is paused."
1191             << tcu::TestLog::EndMessage;
1192 
1193         return false;
1194     }
1195 
1196     return true;
1197 }
1198 
testExtension3(void)1199 bool gl3cts::TransformFeedback::APIErrors::testExtension3(void)
1200 {
1201     /* Functions handler */
1202     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1203 
1204     /*  INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1205      GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and
1206      <index> exceeds limits of MAX_VERTEX_STREAMS
1207 
1208      INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1209      GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds
1210      limits of MAX_VERTEX_STREAMS */
1211 
1212     glw::GLint max_vertex_streams = 0;
1213 
1214     gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1215 
1216     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1217 
1218     if (max_vertex_streams == 0)
1219     {
1220         /* Nothing returned. */
1221         throw 0;
1222     }
1223 
1224     ++max_vertex_streams;
1225 
1226     static const glw::GLenum target[]      = {GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_PRIMITIVES_GENERATED};
1227     static const glw::GLchar *target_str[] = {STR(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
1228                                               STR(GL_PRIMITIVES_GENERATED)};
1229     static const glw::GLuint target_count  = sizeof(target) / sizeof(target[0]);
1230 
1231     for (glw::GLuint i = 0; i < target_count; ++i)
1232     {
1233         gl.beginQueryIndexed(target[i], max_vertex_streams, m_query_object);
1234 
1235         if (GL_INVALID_VALUE != gl.getError())
1236         {
1237             m_context.getTestContext().getLog()
1238                 << tcu::TestLog::Message
1239                 << "INVALID_VALUE was not generated by BeginQueryIndexed, EndQueryIndexed and"
1240                    "GetQueryIndexediv when <target> was "
1241                 << target_str[i]
1242                 << " and "
1243                    "<index> exceeded limits of MAX_VERTEX_STREAMS."
1244                 << tcu::TestLog::EndMessage;
1245             return false;
1246         }
1247 
1248         gl.endQueryIndexed(target[i], max_vertex_streams);
1249 
1250         if (GL_INVALID_VALUE != gl.getError())
1251         {
1252             m_context.getTestContext().getLog() << tcu::TestLog::Message
1253                                                 << "INVALID_VALUE was not generated by EndQueryIndexed "
1254                                                    "when <target> was "
1255                                                 << target_str[i]
1256                                                 << " and "
1257                                                    "<index> exceeded limits of MAX_VERTEX_STREAMS."
1258                                                 << tcu::TestLog::EndMessage;
1259             return false;
1260         }
1261 
1262         glw::GLint param = 0;
1263 
1264         gl.getQueryIndexediv(target[i], max_vertex_streams, GL_QUERY_COUNTER_BITS, &param);
1265 
1266         if (GL_INVALID_VALUE != gl.getError())
1267         {
1268             m_context.getTestContext().getLog() << tcu::TestLog::Message
1269                                                 << "INVALID_VALUE was not generated by "
1270                                                    "GetQueryIndexediv when <target> was "
1271                                                 << target_str[i]
1272                                                 << " and "
1273                                                    "<index> exceeded limits of MAX_VERTEX_STREAMS."
1274                                                 << tcu::TestLog::EndMessage;
1275             return false;
1276         }
1277     }
1278 
1279     /*  INVALID_OPERATION is generated by EndQueryIndexed when name of active
1280      query at <index> of <target> is zero */
1281 
1282     gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
1283 
1284     if (GL_INVALID_OPERATION != gl.getError())
1285     {
1286         m_context.getTestContext().getLog()
1287             << tcu::TestLog::Message
1288             << "INVALID_OPERATION was not generated by EndQueryIndexed when name of active "
1289                "query at <index> of <target> is zero"
1290             << tcu::TestLog::EndMessage;
1291         return false;
1292     }
1293 
1294     /*  INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream>
1295      exceeds limits of MAX_VERTEX_STREAMS */
1296 
1297     gl.drawTransformFeedbackStream(GL_POINTS, m_transform_feedback_object_0, max_vertex_streams);
1298 
1299     if (GL_INVALID_VALUE != gl.getError())
1300     {
1301         m_context.getTestContext().getLog()
1302             << tcu::TestLog::Message
1303             << "INVALID_VALUE was not generated by DrawTransformFeedbackStream when <stream> "
1304                "exceeded limits of MAX_VERTEX_STREAMS"
1305             << tcu::TestLog::EndMessage;
1306         return false;
1307     }
1308 
1309     /*  INVALID_OPERATION is generated by TransformFeedbackVaryings when
1310      <varyings> contains any of the special names while <bufferMode> is not
1311      INTERLEAVED_ATTRIBS */
1312 
1313     static const glw::GLchar *tf_varying_names[]    = {"gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
1314                                                        "gl_SkipComponents3", "gl_SkipComponents4"};
1315     static const glw::GLuint tf_varying_names_count = sizeof(tf_varying_names) / sizeof(tf_varying_names[0]);
1316 
1317     for (glw::GLuint i = 0; i < tf_varying_names_count; ++i)
1318     {
1319         gl.transformFeedbackVaryings(m_program_id_with_output, 1, &tf_varying_names[i], GL_SEPARATE_ATTRIBS);
1320 
1321         if (GL_INVALID_OPERATION != gl.getError())
1322         {
1323             m_context.getTestContext().getLog()
1324                 << tcu::TestLog::Message
1325                 << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1326                    "<varyings> contained any of the special names while <bufferMode> was "
1327                    "GL_SEPARATE_ATTRIBS."
1328                 << tcu::TestLog::EndMessage;
1329             return false;
1330         }
1331     }
1332 
1333     /*  INVALID_OPERATION is generated by TransformFeedbackVaryings when
1334      <varyings> contains more "gl_NextBuffer" entries than allowed limit of
1335      MAX_TRANSFORM_FEEDBACK_BUFFERS */
1336 
1337     glw::GLint max_transform_feedback_buffers = 0;
1338 
1339     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
1340 
1341     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1342 
1343     if (max_transform_feedback_buffers == 0)
1344     {
1345         /* Nothing returned. */
1346         throw 0;
1347     }
1348 
1349     glw::GLint more_than_max_transform_feedback_buffers = max_transform_feedback_buffers + 1;
1350 
1351     const glw::GLchar **tf_next_buffer_varying_names =
1352         new const glw::GLchar *[more_than_max_transform_feedback_buffers];
1353 
1354     if (DE_NULL == tf_next_buffer_varying_names)
1355     {
1356         /* Allocation error. */
1357         throw 0;
1358     }
1359 
1360     for (glw::GLint i = 0; i < more_than_max_transform_feedback_buffers; ++i)
1361     {
1362         tf_next_buffer_varying_names[i] = tf_varying_names[0];
1363     }
1364 
1365     gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_transform_feedback_buffers,
1366                                  tf_next_buffer_varying_names, GL_INTERLEAVED_ATTRIBS);
1367 
1368     delete[] tf_next_buffer_varying_names;
1369 
1370     if (GL_INVALID_OPERATION != gl.getError())
1371     {
1372         m_context.getTestContext().getLog()
1373             << tcu::TestLog::Message
1374             << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1375                "<varyings> contained more \"gl_NextBuffer\" entries than allowed limit of "
1376                "MAX_TRANSFORM_FEEDBACK_BUFFER."
1377             << tcu::TestLog::EndMessage;
1378         return false;
1379     }
1380 
1381     return true;
1382 }
1383 
testInstanced(void)1384 bool gl3cts::TransformFeedback::APIErrors::testInstanced(void)
1385 {
1386     /* Functions handler */
1387     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1388 
1389     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
1390     bool is_tessellation   = m_context.getContextInfo().isExtensionSupported("GL_ARB_tessellation_shader");
1391     bool is_compatibility =
1392         glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::compatibility(3, 2)) ||
1393         glu::hasExtension(gl, glu::ApiType::core(3, 1), "GL_ARB_compatibility");
1394 
1395     bool has_patches = is_at_least_gl_40 || is_tessellation;
1396 
1397     /*  INVALID_ENUM is generated by DrawTransformFeedbackInstanced and
1398      DrawTransformFeedbackStreamInstanced if <mode> is invalid */
1399 
1400     glw::GLenum _supported_mode[] = {GL_POINTS,
1401                                      GL_LINE_STRIP,
1402                                      GL_LINE_LOOP,
1403                                      GL_LINES,
1404                                      GL_LINE_STRIP_ADJACENCY,
1405                                      GL_LINES_ADJACENCY,
1406                                      GL_TRIANGLE_STRIP,
1407                                      GL_TRIANGLE_FAN,
1408                                      GL_TRIANGLES,
1409                                      GL_TRIANGLE_STRIP_ADJACENCY,
1410                                      GL_TRIANGLES_ADJACENCY,
1411                                      GL_QUADS,
1412                                      GL_PATCHES};
1413 
1414     std::set<glw::GLenum> supported_mode(_supported_mode, _supported_mode +
1415                                                               sizeof(_supported_mode) / sizeof(_supported_mode[0]) -
1416                                                               (has_patches ? 0 : 1));
1417 
1418     if (is_compatibility)
1419     {
1420         /* compatibility profile or context with GL_ARB_compatibility supports GL_QUAD_STRIP and GL_POLYGON */
1421         supported_mode.insert(GL_QUAD_STRIP);
1422         supported_mode.insert(GL_POLYGON);
1423     }
1424 
1425     int mode = 0;
1426 
1427     while (supported_mode.find(mode) != supported_mode.end())
1428     {
1429         mode++;
1430     }
1431 
1432     gl.drawTransformFeedbackInstanced(mode, m_transform_feedback_object_0, 1);
1433 
1434     if (GL_INVALID_ENUM != gl.getError())
1435     {
1436         m_context.getTestContext().getLog() << tcu::TestLog::Message
1437                                             << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1438                                                "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1439                                             << tcu::TestLog::EndMessage;
1440         return false;
1441     }
1442 
1443     gl.drawTransformFeedbackStreamInstanced(mode, m_transform_feedback_object_0, 0, 1);
1444 
1445     if (GL_INVALID_ENUM != gl.getError())
1446     {
1447         m_context.getTestContext().getLog() << tcu::TestLog::Message
1448                                             << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1449                                                "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1450                                             << tcu::TestLog::EndMessage;
1451         return false;
1452     }
1453 
1454     if (m_program_id_with_geometry_shader != 0)
1455     {
1456         /*  INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1457         DrawTransformFeedbackStreamInstanced if <mode> does not match geometry
1458         shader */
1459 
1460         gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1461 
1462         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1463 
1464         gl.useProgram(m_program_id_with_geometry_shader);
1465 
1466         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1467 
1468         gl.bindVertexArray(m_vertex_array_object);
1469 
1470         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1471 
1472         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1473 
1474         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1475 
1476         gl.beginTransformFeedback(GL_POINTS);
1477 
1478         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1479 
1480         gl.drawArrays(GL_POINTS, 0, 1);
1481 
1482         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1483 
1484         gl.endTransformFeedback();
1485 
1486         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1487 
1488         gl.drawTransformFeedbackInstanced(GL_LINES, m_transform_feedback_object_0, 1);
1489 
1490         if (GL_INVALID_OPERATION != gl.getError())
1491         {
1492             m_context.getTestContext().getLog()
1493                 << tcu::TestLog::Message
1494                 << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1495                    "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1496                 << tcu::TestLog::EndMessage;
1497             return false;
1498         }
1499 
1500         gl.drawTransformFeedbackStreamInstanced(GL_LINES, m_transform_feedback_object_0, 0, 1);
1501 
1502         if (GL_INVALID_OPERATION != gl.getError())
1503         {
1504             m_context.getTestContext().getLog()
1505                 << tcu::TestLog::Message
1506                 << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1507                    "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1508                 << tcu::TestLog::EndMessage;
1509             return false;
1510         }
1511     }
1512 
1513     /* All of the below tests concern themselves with GL_PATCHES and
1514      * tessellation shaders */
1515     if (m_program_id_with_tessellation_shaders == 0)
1516     {
1517         return true;
1518     }
1519 
1520     /*  INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1521      DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation */
1522 
1523     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1524 
1525     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1526 
1527     gl.useProgram(m_program_id_with_tessellation_shaders);
1528 
1529     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1530 
1531     gl.bindVertexArray(m_vertex_array_object);
1532 
1533     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1534 
1535     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1536 
1537     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1538 
1539     gl.beginTransformFeedback(GL_LINES);
1540 
1541     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1542 
1543     gl.drawArrays(GL_PATCHES, 0, 2);
1544 
1545     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1546 
1547     gl.endTransformFeedback();
1548 
1549     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1550 
1551     gl.drawTransformFeedbackInstanced(GL_POINTS, m_transform_feedback_object_0, 1);
1552 
1553     if (GL_INVALID_OPERATION != gl.getError())
1554     {
1555         m_context.getTestContext().getLog()
1556             << tcu::TestLog::Message
1557             << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1558                "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1559             << tcu::TestLog::EndMessage;
1560         return false;
1561     }
1562 
1563     gl.drawTransformFeedbackStreamInstanced(GL_POINTS, m_transform_feedback_object_0, 0, 1);
1564 
1565     if (GL_INVALID_OPERATION != gl.getError())
1566     {
1567         m_context.getTestContext().getLog()
1568             << tcu::TestLog::Message
1569             << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1570                "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1571             << tcu::TestLog::EndMessage;
1572         return false;
1573     }
1574 
1575     /*  INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if
1576      <stream> is greater than or equal to MAX_VERTEX_STREAMS */
1577 
1578     glw::GLint max_vertex_streams = 0;
1579 
1580     gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1581 
1582     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1583 
1584     if (max_vertex_streams == 0)
1585     {
1586         /* Failed to query GL_MAX_VERTEX_STREAMS. */
1587         throw 0;
1588     }
1589 
1590     glw::GLint more_than_max_vertex_streams = max_vertex_streams + 1;
1591 
1592     gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_0, more_than_max_vertex_streams, 1);
1593 
1594     if (GL_INVALID_VALUE != gl.getError())
1595     {
1596         m_context.getTestContext().getLog()
1597             << tcu::TestLog::Message
1598             << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1599                "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1600             << tcu::TestLog::EndMessage;
1601         return false;
1602     }
1603 
1604     /*  INVALID_VALUE is generated by DrawTransformFeedbackInstanced and
1605      DrawTransformFeedbackStreamInstanced if <id> is not name of transform
1606      feedback object */
1607 
1608     unsigned short int invalid_name = 1;
1609 
1610     while (gl.isTransformFeedback(invalid_name))
1611     {
1612         ++invalid_name;
1613 
1614         /* Make sure that this loop ends someday, bad day. */
1615         if (invalid_name == USHRT_MAX)
1616         {
1617             m_context.getTestContext().getLog()
1618                 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1619             throw 0;
1620         }
1621     }
1622 
1623     gl.drawTransformFeedbackInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 1);
1624 
1625     if (GL_INVALID_VALUE != gl.getError())
1626     {
1627         gl.endTransformFeedback();
1628 
1629         return false;
1630     }
1631 
1632     gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 0, 1);
1633 
1634     if (GL_INVALID_VALUE != gl.getError())
1635     {
1636         gl.endTransformFeedback();
1637 
1638         return false;
1639     }
1640 
1641     /*  INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced
1642      if EndTransformFeedback was never called for the object named <id>.
1643      return true */
1644 
1645     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_1);
1646 
1647     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1648 
1649     gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_1, 0, 1);
1650 
1651     if (GL_INVALID_OPERATION != gl.getError())
1652     {
1653         m_context.getTestContext().getLog()
1654             << tcu::TestLog::Message
1655             << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1656                "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1657             << tcu::TestLog::EndMessage;
1658 
1659         return false;
1660     }
1661 
1662     return true;
1663 }
1664 
1665 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::m_tessellation_control_shader =
1666     "#version 400\n"
1667     "\n"
1668     "layout (vertices = 2 ) out;\n"
1669     "\n"
1670     "void main()\n"
1671     "{\n"
1672     "    gl_TessLevelOuter[1]                = 3.0;\n"
1673     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1674     "}\n";
1675 
1676 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::m_tessellation_evaluation_shader =
1677     "#version 400\n"
1678     "\n"
1679     "layout(isolines, equal_spacing, ccw) in;\n"
1680     "\n"
1681     "out float result;\n"
1682     "\n"
1683     "void main()\n"
1684     "{\n"
1685     "    result      = 0.5;\n"
1686     "    gl_Position = gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position;\n"
1687     "}\n";
1688 
1689 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::m_geometry_shader =
1690     "#version 150\n"
1691     "\n"
1692     "layout(points) in;\n"
1693     "layout(points, max_vertices = 2) out;\n"
1694     "\n"
1695     "out float result;\n"
1696     "\n"
1697     "void main()\n"
1698     "{\n"
1699     "    gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, 0.0, 0.0);\n"
1700     "    result = 0.0;\n"
1701     "    EmitVertex();\n"
1702     "\n"
1703     "    gl_Position = gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0);\n"
1704     "    result = 1.0;\n"
1705     "    EmitVertex();\n"
1706     "}\n";
1707 
1708 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_output =
1709     "#version 130\n"
1710     "\n"
1711     "out float result;\n"
1712     "\n"
1713     "void main()\n"
1714     "{\n"
1715     "    result      = float(gl_VertexID);\n"
1716     "    gl_Position = vec4(1.0);\n"
1717     "}\n";
1718 
1719 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_input_output =
1720     "#version 130\n"
1721     "\n"
1722     "in float v_input;\n"
1723     "\n"
1724     "out float result;\n"
1725     "\n"
1726     "void main()\n"
1727     "{\n"
1728     "    result      = float(gl_VertexID);\n"
1729     "    gl_Position = vec4(v_input);\n"
1730     "}\n";
1731 
1732 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::s_vertex_shader_without_output =
1733     "#version 130\n"
1734     "\n"
1735     "void main()\n"
1736     "{\n"
1737     "    gl_Position = vec4(1.0);\n"
1738     "}\n";
1739 
1740 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::s_fragment_shader = "#version 130\n"
1741                                                                              "\n"
1742                                                                              "out vec4 color;\n"
1743                                                                              "\n"
1744                                                                              "void main()\n"
1745                                                                              "{\n"
1746                                                                              "    color = vec4(1.0);\n"
1747                                                                              "}\n";
1748 
1749 const glw::GLchar *gl3cts::TransformFeedback::APIErrors::m_varying_name = "result";
1750 
1751 const glw::GLfloat gl3cts::TransformFeedback::APIErrors::m_buffer_1_data[] = {3.14159265359f, 2.7182818f};
1752 
1753 const glw::GLsizei gl3cts::TransformFeedback::APIErrors::m_buffer_1_size =
1754     sizeof(gl3cts::TransformFeedback::APIErrors::m_buffer_1_data);
1755 
1756 /*-----------------------------------------------------------------------------------------------*/
1757 
LinkingErrors(deqp::Context & context)1758 gl3cts::TransformFeedback::LinkingErrors::LinkingErrors(deqp::Context &context)
1759     : deqp::TestCase(context, "linking_errors_test", "Transform Feedback Linking Errors Test")
1760     , m_context(context)
1761 {
1762     /* Left intentionally blank. */
1763 }
1764 
~LinkingErrors(void)1765 gl3cts::TransformFeedback::LinkingErrors::~LinkingErrors(void)
1766 {
1767 }
1768 
iterate(void)1769 tcu::TestNode::IterateResult gl3cts::TransformFeedback::LinkingErrors::iterate(void)
1770 {
1771     bool is_ok      = true;
1772     bool test_error = false;
1773 
1774     try
1775     {
1776         is_ok = is_ok && testNoVertexNoGeometry();
1777         is_ok = is_ok && testInvalidVarying();
1778         is_ok = is_ok && testRepeatedVarying();
1779         is_ok = is_ok && testTooManyVaryings();
1780     }
1781     catch (...)
1782     {
1783         is_ok      = false;
1784         test_error = true;
1785     }
1786 
1787     /* Result's setup. */
1788     if (is_ok)
1789     {
1790         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1791     }
1792     else
1793     {
1794         if (test_error)
1795         {
1796             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1797         }
1798         else
1799         {
1800             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1801         }
1802     }
1803 
1804     return STOP;
1805 }
1806 
testNoVertexNoGeometry(void)1807 bool gl3cts::TransformFeedback::LinkingErrors::testNoVertexNoGeometry(void)
1808 {
1809     /* Functions handler */
1810     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1811 
1812     /*  Check if link process fails under the following conditions:
1813      <count> specified by TransformFeedbackVaryings is non-zero and program has
1814      neither vertex nor geometry shader; */
1815 
1816     glw::GLint linking_status = 1;
1817 
1818     glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1819         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, NULL, s_fragment_shader,
1820         &s_valid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1821 
1822     if ((GL_FALSE != linking_status) || program)
1823     {
1824         m_context.getTestContext().getLog() << tcu::TestLog::Message
1825                                             << "Linking unexpectedly succeded when Transform Feedback varying was "
1826                                                "specified but program had neither vertex nor geometry shader stages."
1827                                             << tcu::TestLog::EndMessage;
1828 
1829         if (program)
1830         {
1831             gl.deleteProgram(program);
1832         }
1833 
1834         return false;
1835     }
1836 
1837     /* Log success. */
1838     m_context.getTestContext().getLog() << tcu::TestLog::Message
1839                                         << "Linking failed as expected when Transform Feedback varying was specified "
1840                                            "but program had neither vertex nor geometry shader stages."
1841                                         << tcu::TestLog::EndMessage;
1842 
1843     return true;
1844 }
1845 
testInvalidVarying(void)1846 bool gl3cts::TransformFeedback::LinkingErrors::testInvalidVarying(void)
1847 {
1848     /* Functions handler */
1849     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1850 
1851     /*  Check if link process fails under the following conditions:
1852      <varyings> specified by TransformFeedbackVaryings contains name of
1853      variable that is not available for capture; */
1854 
1855     std::string vertex_shader(s_vertex_shader_template);
1856 
1857     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1858         vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "in float data;\n");
1859     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", "");
1860 
1861     glw::GLint linking_status = 1;
1862 
1863     glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1864         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1865         &s_invalid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1866 
1867     if ((GL_FALSE != linking_status) || program)
1868     {
1869         m_context.getTestContext().getLog()
1870             << tcu::TestLog::Message
1871             << "Linking unexpectedly succeded when Transform Feedback varying was specified with name of variable ("
1872             << s_invalid_transform_feedback_varying << ") that is not available for capture."
1873             << tcu::TestLog::EndMessage;
1874 
1875         if (program)
1876         {
1877             gl.deleteProgram(program);
1878         }
1879 
1880         return false;
1881     }
1882 
1883     /* Log success. */
1884     m_context.getTestContext().getLog()
1885         << tcu::TestLog::Message
1886         << "Linking failed as expected when Transform Feedback varying was specified with name of variable ("
1887         << s_invalid_transform_feedback_varying << ") that is not available for capture." << tcu::TestLog::EndMessage;
1888 
1889     return true;
1890 }
1891 
testRepeatedVarying(void)1892 bool gl3cts::TransformFeedback::LinkingErrors::testRepeatedVarying(void)
1893 {
1894     /* Functions handler */
1895     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1896 
1897     /*  Check if link process fails under the following conditions:
1898      <varyings> specified by TransformFeedbackVaryings contains name of
1899      variable more than once; */
1900 
1901     std::string vertex_shader(s_vertex_shader_template);
1902 
1903     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1904         vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "out float result;\n");
1905     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
1906                                                                          "    result = 0.577215664901532;\n");
1907 
1908     glw::GLint linking_status = 1;
1909 
1910     glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1911         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1912         s_repeated_transform_feedback_varying, s_repeated_transform_feedback_varying_count, GL_INTERLEAVED_ATTRIBS,
1913         false, &linking_status);
1914 
1915     if ((GL_FALSE != linking_status) || program)
1916     {
1917         m_context.getTestContext().getLog()
1918             << tcu::TestLog::Message
1919             << "Linking unexpectedly succeded when Transform Feedback varying was specified twice."
1920             << tcu::TestLog::EndMessage;
1921 
1922         if (program)
1923         {
1924             gl.deleteProgram(program);
1925         }
1926 
1927         return false;
1928     }
1929 
1930     /* Log success. */
1931     m_context.getTestContext().getLog()
1932         << tcu::TestLog::Message << "Linking failed as expected when Transform Feedback varying was specified twice."
1933         << tcu::TestLog::EndMessage;
1934 
1935     return true;
1936 }
1937 
testTooManyVaryings(void)1938 bool gl3cts::TransformFeedback::LinkingErrors::testTooManyVaryings(void)
1939 {
1940     /* Functions handler */
1941     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1942 
1943     /*  Check if link process fails under the following conditions:
1944      number of components specified to capture exceeds limits
1945      MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or
1946      MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. */
1947 
1948     /* Fetching limits. */
1949     glw::GLint max_transform_feedback_separate_components    = 0;
1950     glw::GLint max_transform_feedback_interleaved_components = 0;
1951 
1952     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
1953 
1954     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1955 
1956     if (max_transform_feedback_separate_components == 0)
1957     {
1958         throw 0;
1959     }
1960 
1961     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
1962 
1963     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1964 
1965     if (max_transform_feedback_interleaved_components == 0)
1966     {
1967         throw 0;
1968     }
1969 
1970     glw::GLint more_than_max_transform_feedback_components =
1971         deMax32(max_transform_feedback_separate_components, max_transform_feedback_interleaved_components) + 1;
1972 
1973     /* Preparing source code. */
1974     std::string vertex_shader(s_vertex_shader_template);
1975     std::string transform_feedback_variable_declarations("");
1976     std::string transform_feedback_variable_setters("");
1977     std::vector<std::string> transform_feedback_varyings(more_than_max_transform_feedback_components);
1978     std::vector<const glw::GLchar *> transform_feedback_varyings_c(more_than_max_transform_feedback_components);
1979 
1980     for (glw::GLint i = 0; i < more_than_max_transform_feedback_components; ++i)
1981     {
1982         std::string varying = "result_";
1983         varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
1984 
1985         transform_feedback_varyings[i] = varying;
1986 
1987         transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
1988 
1989         transform_feedback_variable_declarations.append("out float ");
1990         transform_feedback_variable_declarations.append(varying);
1991         transform_feedback_variable_declarations.append(";\n");
1992 
1993         transform_feedback_variable_setters.append("    ");
1994         transform_feedback_variable_setters.append(varying);
1995         transform_feedback_variable_setters.append(" = ");
1996         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * i));
1997         transform_feedback_variable_setters.append(".0;\n");
1998     }
1999 
2000     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2001         vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
2002     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
2003                                                                          transform_feedback_variable_setters);
2004 
2005     glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
2006         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
2007         &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_INTERLEAVED_ATTRIBS);
2008 
2009     /* Note: we check for program as not only linking shall fail, but also glTransformFeedbackVaryings shall return an error. */
2010 
2011     if (program)
2012     {
2013         m_context.getTestContext().getLog() << tcu::TestLog::Message
2014                                             << "Linking unexpectedly succeded when too many Transform Feedback varying "
2015                                                "were specified in INTERLEAVED mode."
2016                                             << tcu::TestLog::EndMessage;
2017 
2018         if (program)
2019         {
2020             gl.deleteProgram(program);
2021         }
2022 
2023         return false;
2024     }
2025 
2026     program = gl3cts::TransformFeedback::Utilities::buildProgram(
2027         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
2028         &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_SEPARATE_ATTRIBS);
2029 
2030     if (program)
2031     {
2032         m_context.getTestContext().getLog() << tcu::TestLog::Message
2033                                             << "Linking unexpectedly succeded when too many Transform Feedback "
2034                                                "varyings were specified in SEPARATE mode."
2035                                             << tcu::TestLog::EndMessage;
2036 
2037         if (program)
2038         {
2039             gl.deleteProgram(program);
2040         }
2041 
2042         return false;
2043     }
2044 
2045     /* Log success. */
2046     m_context.getTestContext().getLog()
2047         << tcu::TestLog::Message
2048         << "Linking failed as expected when too many Transform Feedback varyings were specified."
2049         << tcu::TestLog::EndMessage;
2050 
2051     return true;
2052 }
2053 
2054 const glw::GLchar *gl3cts::TransformFeedback::LinkingErrors::s_fragment_shader = "#version 130\n"
2055                                                                                  "\n"
2056                                                                                  "out vec4 color;\n"
2057                                                                                  "\n"
2058                                                                                  "void main()\n"
2059                                                                                  "{\n"
2060                                                                                  "    color = vec4(1.0);\n"
2061                                                                                  "}\n";
2062 
2063 const glw::GLchar *gl3cts::TransformFeedback::LinkingErrors::s_vertex_shader_template =
2064     "#version 130\n"
2065     "\n"
2066     "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2067     "\n"
2068     "void main()\n"
2069     "{\n"
2070     "TEMPLATE_OUTPUT_SETTERS"
2071     "\n"
2072     "    gl_Position = vec4(1.618033988749);\n"
2073     "}\n";
2074 
2075 const glw::GLchar *gl3cts::TransformFeedback::LinkingErrors::s_valid_transform_feedback_varying = "result";
2076 
2077 const glw::GLchar *gl3cts::TransformFeedback::LinkingErrors::s_invalid_transform_feedback_varying = "data";
2078 
2079 const glw::GLchar *gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying[] = {"result",
2080                                                                                                         "result"};
2081 
2082 const glw::GLsizei gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying_count =
2083     sizeof(s_repeated_transform_feedback_varying) / sizeof(s_repeated_transform_feedback_varying[0]);
2084 
2085 /*-----------------------------------------------------------------------------------------------*/
2086 
2087 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_interleaved_components = 64;
2088 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_attribs       = 4;
2089 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_components    = 4;
2090 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_buffers                = 4;
2091 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_vertex_streams                            = 1;
2092 
Limits(deqp::Context & context)2093 gl3cts::TransformFeedback::Limits::Limits(deqp::Context &context)
2094     : deqp::TestCase(context, "limits_test", "Transform Feedback Limits Test")
2095     , m_context(context)
2096 {
2097 }
2098 
~Limits(void)2099 gl3cts::TransformFeedback::Limits::~Limits(void)
2100 {
2101 }
2102 
iterate(void)2103 tcu::TestNode::IterateResult gl3cts::TransformFeedback::Limits::iterate(void)
2104 {
2105     /* Initializations. */
2106     bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2107     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
2108 
2109     bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2110     bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
2111 
2112     bool is_ok      = true;
2113     bool test_error = false;
2114 
2115     /* Tests. */
2116     try
2117     {
2118         if (is_at_least_gl_30 || is_ext_tf_1)
2119         {
2120             is_ok = is_ok && test_max_transform_feedback_interleaved_components();
2121             is_ok = is_ok && test_max_transform_feedback_separate_attribs();
2122             is_ok = is_ok && test_max_transform_feedback_separate_components();
2123         }
2124 
2125         if (is_at_least_gl_40 || is_arb_tf_3)
2126         {
2127             is_ok = is_ok && test_max_transform_feedback_buffers();
2128             is_ok = is_ok && test_max_vertex_streams();
2129         }
2130     }
2131     catch (...)
2132     {
2133         is_ok      = false;
2134         test_error = true;
2135     }
2136 
2137     /* Result's setup. */
2138     if (is_ok)
2139     {
2140         /* Log success. */
2141         m_context.getTestContext().getLog()
2142             << tcu::TestLog::Message << "Limits are in range of specification." << tcu::TestLog::EndMessage;
2143 
2144         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2145     }
2146     else
2147     {
2148         if (test_error)
2149         {
2150             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2151         }
2152         else
2153         {
2154             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2155         }
2156     }
2157 
2158     return STOP;
2159 }
2160 
test_max_transform_feedback_interleaved_components(void)2161 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_interleaved_components(void)
2162 {
2163     /* Functions handler */
2164     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2165 
2166     /* Check that MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64. */
2167     glw::GLint max_transform_feedback_interleaved_components = 0;
2168 
2169     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
2170 
2171     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2172 
2173     if (max_transform_feedback_interleaved_components < s_min_value_of_max_transform_feedback_interleaved_components)
2174     {
2175         m_context.getTestContext().getLog()
2176             << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is equal to "
2177             << max_transform_feedback_interleaved_components << " which is less than expected "
2178             << s_min_value_of_max_transform_feedback_interleaved_components << "." << tcu::TestLog::EndMessage;
2179         return false;
2180     }
2181 
2182     return true;
2183 }
2184 
test_max_transform_feedback_separate_attribs(void)2185 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_attribs(void)
2186 {
2187     /* Functions handler */
2188     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2189 
2190     /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4. */
2191     glw::GLint max_transform_feedback_separate_attribs = 0;
2192 
2193     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
2194 
2195     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2196 
2197     if (max_transform_feedback_separate_attribs < s_min_value_of_max_transform_feedback_separate_attribs)
2198     {
2199         m_context.getTestContext().getLog()
2200             << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is equal to "
2201             << max_transform_feedback_separate_attribs << " which is less than expected "
2202             << s_min_value_of_max_transform_feedback_separate_attribs << "." << tcu::TestLog::EndMessage;
2203         return false;
2204     }
2205 
2206     return true;
2207 }
2208 
test_max_transform_feedback_separate_components(void)2209 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_components(void)
2210 {
2211     /* Functions handler */
2212     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2213 
2214     /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4. */
2215     glw::GLint max_transform_feedback_separate_components = 0;
2216 
2217     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
2218 
2219     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2220 
2221     if (max_transform_feedback_separate_components < s_min_value_of_max_transform_feedback_separate_components)
2222     {
2223         m_context.getTestContext().getLog()
2224             << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is equal to "
2225             << max_transform_feedback_separate_components << " which is less than expected "
2226             << s_min_value_of_max_transform_feedback_separate_components << "." << tcu::TestLog::EndMessage;
2227         return false;
2228     }
2229 
2230     return true;
2231 }
2232 
test_max_transform_feedback_buffers(void)2233 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_buffers(void)
2234 {
2235     /* Functions handler */
2236     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2237 
2238     /* Check that MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4. */
2239     glw::GLint max_transform_feedback_buffers = 0;
2240 
2241     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
2242 
2243     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2244 
2245     if (max_transform_feedback_buffers < s_min_value_of_max_transform_feedback_buffers)
2246     {
2247         m_context.getTestContext().getLog()
2248             << tcu::TestLog::Message << "MAX_TRANSFORM_FEEDBACK_BUFFERS is equal to " << max_transform_feedback_buffers
2249             << " which is less than expected " << s_min_value_of_max_transform_feedback_buffers << "."
2250             << tcu::TestLog::EndMessage;
2251         return false;
2252     }
2253 
2254     return true;
2255 }
2256 
test_max_vertex_streams(void)2257 bool gl3cts::TransformFeedback::Limits::test_max_vertex_streams(void)
2258 {
2259     /* Functions handler */
2260     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2261 
2262     /* Check that MAX_VERTEX_STREAMS is at least 1. */
2263     glw::GLint max_vertex_streams = 0;
2264 
2265     gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
2266 
2267     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2268 
2269     if (max_vertex_streams < s_min_value_of_max_vertex_streams)
2270     {
2271         m_context.getTestContext().getLog()
2272             << tcu::TestLog::Message << "MAX_VERTEX_STREAMS is equal to " << max_vertex_streams
2273             << " which is less than expected " << s_min_value_of_max_vertex_streams << "." << tcu::TestLog::EndMessage;
2274         return false;
2275     }
2276 
2277     return true;
2278 }
2279 
2280 /*-----------------------------------------------------------------------------------------------*/
2281 
CaptureVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2282 gl3cts::TransformFeedback::CaptureVertexInterleaved::CaptureVertexInterleaved(deqp::Context &context,
2283                                                                               const char *test_name,
2284                                                                               const char *test_description)
2285     : deqp::TestCase(context, test_name, test_description)
2286     , m_context(context)
2287     , m_program(0)
2288     , m_framebuffer(0)
2289     , m_renderbuffer(0)
2290     , m_buffer(0)
2291     , m_buffer_size(0)
2292     , m_vertex_array_object(0)
2293     , m_max_transform_feedback_components(0)
2294     , m_attrib_type(GL_INTERLEAVED_ATTRIBS)
2295     , m_max_vertices_drawn(8)
2296     , m_glBindBufferOffsetEXT(DE_NULL)
2297 {
2298 }
2299 
~CaptureVertexInterleaved(void)2300 gl3cts::TransformFeedback::CaptureVertexInterleaved::~CaptureVertexInterleaved(void)
2301 {
2302 }
2303 
iterate(void)2304 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureVertexInterleaved::iterate(void)
2305 {
2306     /* Functions handler */
2307     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2308 
2309     /* Initializations. */
2310     bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2311     bool is_ext_tf_1       = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2312 
2313     bool is_ok      = true;
2314     bool test_error = false;
2315 
2316     try
2317     {
2318         if (is_ext_tf_1)
2319         {
2320             /* Extension query. */
2321             m_glBindBufferOffsetEXT =
2322                 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
2323 
2324             if (DE_NULL == m_glBindBufferOffsetEXT)
2325             {
2326                 throw 0;
2327             }
2328         }
2329 
2330         if (is_at_least_gl_30 || is_ext_tf_1)
2331         {
2332             fetchLimits();
2333             buildProgram();
2334             createFramebuffer();
2335             createTransformFeedbackBuffer();
2336             createVertexArrayObject();
2337 
2338             gl.useProgram(m_program);
2339 
2340             GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2341 
2342             for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2343             {
2344                 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2345                 {
2346                     continue;
2347                 }
2348 
2349                 bindBuffer((BindBufferCase)i_bind_case);
2350 
2351                 for (glw::GLuint i_primitive_case = 0; (i_primitive_case < s_primitive_cases_count) && is_ok;
2352                      ++i_primitive_case)
2353                 {
2354                     draw(i_primitive_case);
2355 
2356                     is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2357                     is_ok = is_ok && checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2358                                                                   s_primitive_cases[i_primitive_case]);
2359                 }
2360             }
2361         }
2362     }
2363     catch (...)
2364     {
2365         is_ok      = false;
2366         test_error = true;
2367     }
2368 
2369     /* Clean objects. */
2370     clean();
2371 
2372     /* Result's setup. */
2373     if (is_ok)
2374     {
2375         /* Log success. */
2376         m_context.getTestContext().getLog()
2377             << tcu::TestLog::Message << "Capture Vertex have passed." << tcu::TestLog::EndMessage;
2378 
2379         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2380     }
2381     else
2382     {
2383         if (test_error)
2384         {
2385             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2386         }
2387         else
2388         {
2389             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2390         }
2391     }
2392 
2393     return STOP;
2394 }
2395 
fetchLimits(void)2396 void gl3cts::TransformFeedback::CaptureVertexInterleaved::fetchLimits(void)
2397 {
2398     /* Functions handler */
2399     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2400 
2401     /* Fetching limits. */
2402     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2403 
2404     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2405 
2406     if (m_max_transform_feedback_components == 0)
2407     {
2408         throw 0;
2409     }
2410 
2411     glw::GLint max_varyings_components = 0;
2412 
2413     gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
2414 
2415     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2416 
2417     if (max_varyings_components == 0)
2418     {
2419         throw 0;
2420     }
2421 
2422     if (m_max_transform_feedback_components > max_varyings_components)
2423     {
2424         m_max_transform_feedback_components = max_varyings_components;
2425     }
2426 }
2427 
buildProgram(void)2428 void gl3cts::TransformFeedback::CaptureVertexInterleaved::buildProgram(void)
2429 {
2430     /* Functions handler */
2431     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2432 
2433     /* Preparing source code. */
2434     std::string vertex_shader(s_vertex_shader_source_code_template); /* Storage for vertex shader source code. */
2435     std::string transform_feedback_variable_declarations(
2436         ""); /* String to contain all custom outputs from vertex shader. */
2437     std::string transform_feedback_variable_setters(
2438         ""); /* String containing all initializations of custom outputs from vertex shader. */
2439     std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2440     std::vector<const glw::GLchar *> transform_feedback_varyings_c(
2441         m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2442 
2443     glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2444         m_max_transform_feedback_components /* total max to be written by the shader */
2445             / 4                             /* components per vec4 */
2446         - 1 /* gl_Position */;
2447 
2448     glw::GLint all_transform_feedback_interleaved_varyings_count =
2449         user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2450 
2451     /* Most of varyings is declarated output variables. */
2452     for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
2453     {
2454         std::string varying = "result_";
2455         varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
2456 
2457         transform_feedback_varyings[i] = varying;
2458 
2459         transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
2460 
2461         transform_feedback_variable_declarations.append("out vec4 ");
2462         transform_feedback_variable_declarations.append(varying);
2463         transform_feedback_variable_declarations.append(";\n");
2464 
2465         transform_feedback_variable_setters.append("    ");
2466         transform_feedback_variable_setters.append(varying);
2467         transform_feedback_variable_setters.append(" = vec4(");
2468         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
2469         transform_feedback_variable_setters.append(".0, ");
2470         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
2471         transform_feedback_variable_setters.append(".0, ");
2472         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
2473         transform_feedback_variable_setters.append(".0, ");
2474         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
2475         transform_feedback_variable_setters.append(".0);\n");
2476     }
2477 
2478     /* Last four varying components are gl_Position components. */
2479     transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count] = "gl_Position";
2480 
2481     transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count] =
2482         transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count].c_str();
2483 
2484     /* Preprocess vertex shader source code template. */
2485     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2486         vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
2487     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
2488                                                                          transform_feedback_variable_setters);
2489     vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2490         vertex_shader, "TEMPLATE_RASTERIZATION_EPSILON",
2491         gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
2492 
2493     /* Compile, link and check. */
2494     m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
2495         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader_source_code,
2496         &transform_feedback_varyings_c[0], all_transform_feedback_interleaved_varyings_count, m_attrib_type);
2497 
2498     if (0 == m_program)
2499     {
2500         throw 0;
2501     }
2502 }
2503 
createFramebuffer(void)2504 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createFramebuffer(void)
2505 {
2506     /* Functions handler */
2507     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2508 
2509     /* Setting clear color */
2510     gl.clearColor(0.f, 0.f, 0.f, 1.f);
2511     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
2512 
2513     /* Creating framebuffer */
2514     gl.genFramebuffers(1, &m_framebuffer);
2515     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
2516 
2517     gl.genRenderbuffers(1, &m_renderbuffer);
2518     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
2519 
2520     gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
2521     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
2522 
2523     gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
2524     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
2525 
2526     gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32F, s_framebuffer_size, s_framebuffer_size);
2527     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
2528 
2529     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
2530     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
2531 
2532     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
2533     {
2534         throw 0;
2535     }
2536 
2537     gl.viewport(0, 0, s_framebuffer_size, s_framebuffer_size);
2538     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
2539 }
2540 
createTransformFeedbackBuffer(void)2541 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(void)
2542 {
2543     /* Functions handler */
2544     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2545 
2546     /* Creating xfb buffer */
2547     gl.genBuffers(1, &m_buffer);
2548     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2549 
2550     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer);
2551     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2552 
2553     m_buffer_size =
2554         static_cast<glw::GLuint>(m_max_transform_feedback_components * m_max_vertices_drawn * sizeof(glw::GLfloat));
2555 
2556     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
2557     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2558 }
2559 
createVertexArrayObject(void)2560 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createVertexArrayObject(void)
2561 {
2562     /* Functions handler */
2563     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2564 
2565     /* VAO Creations */
2566     gl.genVertexArrays(1, &m_vertex_array_object);
2567     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
2568 
2569     gl.bindVertexArray(m_vertex_array_object);
2570     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2571 }
2572 
draw(glw::GLuint primitive_case)2573 void gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(glw::GLuint primitive_case)
2574 {
2575     /* Functions handler */
2576     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2577 
2578     /* Draw */
2579     gl.clear(GL_COLOR_BUFFER_BIT);
2580     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
2581 
2582     gl.beginTransformFeedback(s_primitive_cases_xfb[primitive_case]);
2583     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedbac call failed.");
2584 
2585     gl.drawElements(s_primitive_cases[primitive_case], s_element_indices_counts[primitive_case], GL_UNSIGNED_INT,
2586                     s_element_indices[primitive_case]);
2587     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements call failed.");
2588 
2589     gl.endTransformFeedback();
2590     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
2591 }
2592 
checkFramebuffer(glw::GLenum primitive_type UNUSED)2593 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkFramebuffer(glw::GLenum primitive_type UNUSED)
2594 {
2595     /* Functions handler */
2596     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2597 
2598     /* Fetch framebuffer. */
2599     std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
2600 
2601     if (s_framebuffer_size > 0)
2602     {
2603         gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
2604         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
2605     }
2606 
2607     /* Check results.
2608      Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
2609     for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
2610     {
2611         if (fabs(*i - 0.5f) > 0.0625f /* precision */)
2612         {
2613             return false;
2614         }
2615     }
2616 
2617     return true;
2618 }
2619 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)2620 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
2621                                                                                        glw::GLenum primitive_type)
2622 {
2623     /* Functions handler */
2624     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2625 
2626     /* Check */
2627     glw::GLuint number_of_vertices = 0;
2628 
2629     switch (primitive_type)
2630     {
2631     case GL_POINTS:
2632         number_of_vertices = 4;
2633         break;
2634     case GL_LINES:
2635         number_of_vertices = 4;
2636         break;
2637     case GL_LINE_LOOP:
2638         number_of_vertices = 8;
2639         break;
2640     case GL_LINE_STRIP:
2641         number_of_vertices = 6;
2642         break;
2643     case GL_TRIANGLES:
2644         number_of_vertices = 6;
2645         break;
2646     case GL_TRIANGLE_STRIP:
2647         number_of_vertices = 6;
2648         break;
2649     case GL_TRIANGLE_FAN:
2650         number_of_vertices = 6;
2651         break;
2652     default:
2653         throw 0;
2654     }
2655 
2656     glw::GLfloat *results = (glw::GLfloat *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2657     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2658 
2659     bool is_ok = true;
2660 
2661     for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
2662     {
2663         for (glw::GLint i = 0; i < m_max_transform_feedback_components - 4; ++i)
2664         {
2665             glw::GLfloat result    = results[i + j * m_max_transform_feedback_components];
2666             glw::GLfloat reference = (glw::GLfloat)(i);
2667 
2668             if (fabs(result - reference) > 0.125 /* precision */)
2669             {
2670                 is_ok = false;
2671 
2672                 break;
2673             }
2674         }
2675 
2676         /* gl_Position */
2677         glw::GLfloat result[4] = {results[(j + 1) * m_max_transform_feedback_components - 4],
2678                                   results[(j + 1) * m_max_transform_feedback_components - 3],
2679                                   results[(j + 1) * m_max_transform_feedback_components - 2],
2680                                   results[(j + 1) * m_max_transform_feedback_components - 1]};
2681 
2682         if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2683             (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2684             (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
2685         {
2686             is_ok = false;
2687 
2688             break;
2689         }
2690     }
2691 
2692     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2693     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2694 
2695     return is_ok;
2696 }
2697 
bindBuffer(BindBufferCase bind_case)2698 void gl3cts::TransformFeedback::CaptureVertexInterleaved::bindBuffer(BindBufferCase bind_case)
2699 {
2700     /* Functions handler */
2701     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2702 
2703     switch (bind_case)
2704     {
2705     case BIND_BUFFER_BASE_CASE:
2706         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer);
2707         break;
2708     case BIND_BUFFER_RANGE_CASE:
2709         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0, m_buffer_size);
2710         break;
2711     case BIND_BUFFER_OFFSET_CASE:
2712         if (DE_NULL == m_glBindBufferOffsetEXT)
2713         {
2714             throw 0;
2715         }
2716         m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0);
2717         break;
2718     default:
2719         throw 0;
2720     }
2721 }
2722 
clean(void)2723 void gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(void)
2724 {
2725     /* Functions handler */
2726     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2727 
2728     if (m_program)
2729     {
2730         gl.deleteProgram(m_program);
2731 
2732         m_program = 0;
2733     }
2734 
2735     if (m_framebuffer)
2736     {
2737         gl.deleteFramebuffers(1, &m_framebuffer);
2738 
2739         m_framebuffer = 0;
2740     }
2741 
2742     if (m_renderbuffer)
2743     {
2744         gl.deleteRenderbuffers(1, &m_renderbuffer);
2745 
2746         m_renderbuffer = 0;
2747     }
2748 
2749     cleanBuffer();
2750 
2751     if (m_vertex_array_object)
2752     {
2753         gl.deleteVertexArrays(1, &m_vertex_array_object);
2754 
2755         m_vertex_array_object = 0;
2756     }
2757 }
2758 
cleanBuffer(void)2759 void gl3cts::TransformFeedback::CaptureVertexInterleaved::cleanBuffer(void)
2760 {
2761     /* Functions handler */
2762     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2763 
2764     if (m_buffer)
2765     {
2766         gl.deleteBuffers(1, &m_buffer);
2767 
2768         m_buffer = 0;
2769     }
2770 }
2771 
2772 const glw::GLchar *gl3cts::TransformFeedback::CaptureVertexInterleaved::s_vertex_shader_source_code_template =
2773     "#version 130\n"
2774     "\n"
2775     "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2776     "\n"
2777     "void main()\n"
2778     "{\n"
2779     "TEMPLATE_OUTPUT_SETTERS"
2780     "\n"
2781     "    vec4 position = vec4(0.0);\n"
2782     "\n"
2783     "    /* Note: The points are moved 0.0625 from the borders to\n"
2784     "             reduce non-XFB related rasterization problems. */\n"
2785     "    switch(gl_VertexID)\n"
2786     "    {\n"
2787     "        case 0:\n"
2788     "            position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2789     "1.0);\n"
2790     "            break;\n"
2791     "        case 1:\n"
2792     "            position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2793     "1.0);\n"
2794     "            break;\n"
2795     "        case 2:\n"
2796     "            position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2797     "1.0);\n"
2798     "            break;\n"
2799     "        case 3:\n"
2800     "            position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
2801     "1.0);\n"
2802     "            break;\n"
2803     "    }\n"
2804     "\n"
2805     "    gl_Position = position;\n"
2806     "}\n";
2807 
2808 const glw::GLchar *gl3cts::TransformFeedback::CaptureVertexInterleaved::s_fragment_shader_source_code =
2809     "#version 130\n"
2810     "\n"
2811     "out vec4 color;\n"
2812     "\n"
2813     "void main()\n"
2814     "{\n"
2815     "    color = vec4(0.5);\n"
2816     "}\n";
2817 
2818 const glw::GLuint
2819     gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices[][s_max_element_indices_count] = {
2820         {0, 1, 2, 3}, {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 1, 3, 2}, {2, 0, 1, 2, 1, 3}, {0, 1, 2, 3}, {2, 0, 1, 3}};
2821 
2822 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_count =
2823     sizeof(s_element_indices) / sizeof(s_element_indices[0]);
2824 
2825 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases[] = {
2826     GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN};
2827 
2828 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_xfb[] = {
2829     GL_POINTS, GL_LINES, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES};
2830 
2831 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices_counts[] = {4, 4, 4, 4,
2832                                                                                                      6, 4, 4};
2833 
2834 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_framebuffer_size =
2835     2; /* If you change this, update checkFramebuffer function according. */
2836 
2837 const glw::GLfloat gl3cts::TransformFeedback::CaptureVertexInterleaved::s_rasterization_epsilon = 0.0625;
2838 
2839 /*-----------------------------------------------------------------------------------------------*/
2840 
CaptureGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2841 gl3cts::TransformFeedback::CaptureGeometryInterleaved::CaptureGeometryInterleaved(deqp::Context &context,
2842                                                                                   const char *test_name,
2843                                                                                   const char *test_description)
2844     : CaptureVertexInterleaved(context, test_name, test_description)
2845 {
2846 }
2847 
~CaptureGeometryInterleaved(void)2848 gl3cts::TransformFeedback::CaptureGeometryInterleaved::~CaptureGeometryInterleaved(void)
2849 {
2850 }
2851 
iterate(void)2852 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureGeometryInterleaved::iterate(void)
2853 {
2854     /* Functions handler */
2855     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2856 
2857     /* Initializations. */
2858     bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2859     bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
2860     bool is_ext_tf_1       = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2861     bool is_arb_gs_4       = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
2862 
2863     bool is_ok      = true;
2864     bool test_error = false;
2865 
2866     /* Tests. */
2867     try
2868     {
2869         if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
2870         {
2871             fetchLimits();
2872             createFramebuffer();
2873             createTransformFeedbackBuffer();
2874             createVertexArrayObject();
2875 
2876             for (glw::GLuint i_primitive_case = 0;
2877                  (i_primitive_case < s_geometry_interleaved_primitive_cases_count) && is_ok; ++i_primitive_case)
2878             {
2879                 buildProgram(i_primitive_case);
2880 
2881                 gl.useProgram(m_program);
2882 
2883                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2884 
2885                 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2886                 {
2887                     if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2888                     {
2889                         continue;
2890                     }
2891 
2892                     bindBuffer((BindBufferCase)i_bind_case);
2893 
2894                     draw(i_primitive_case);
2895 
2896                     is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2897                     is_ok = is_ok &&
2898                             checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2899                                                          s_geometry_interleaved_primitive_cases_xfb[i_primitive_case]);
2900                 }
2901 
2902                 gl.deleteProgram(m_program);
2903 
2904                 m_program = 0;
2905 
2906                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
2907             }
2908         }
2909     }
2910     catch (...)
2911     {
2912         is_ok      = false;
2913         test_error = true;
2914     }
2915 
2916     /* Clean objects. */
2917     clean();
2918 
2919     /* Result's setup. */
2920     if (is_ok)
2921     {
2922         /* Log success. */
2923         m_context.getTestContext().getLog()
2924             << tcu::TestLog::Message << "Capture Geometry have passed." << tcu::TestLog::EndMessage;
2925 
2926         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2927     }
2928     else
2929     {
2930         if (test_error)
2931         {
2932             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2933         }
2934         else
2935         {
2936             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2937         }
2938     }
2939 
2940     return STOP;
2941 }
2942 
fetchLimits(void)2943 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::fetchLimits(void)
2944 {
2945     /* Functions handler */
2946     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2947 
2948     /* Fetching limits. */
2949     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2950 
2951     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2952 
2953     if (m_max_transform_feedback_components == 0)
2954     {
2955         throw 0;
2956     }
2957 
2958     glw::GLint max_geometry_total_components = 0;
2959 
2960     gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_geometry_total_components);
2961 
2962     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2963 
2964     if (max_geometry_total_components == 0)
2965     {
2966         throw 0;
2967     }
2968 
2969     if (m_max_transform_feedback_components * 4 > max_geometry_total_components)
2970     {
2971         m_max_transform_feedback_components = max_geometry_total_components / 4;
2972     }
2973 }
2974 
buildProgram(glw::GLuint primitive_case)2975 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::buildProgram(glw::GLuint primitive_case)
2976 {
2977     /* Functions handler */
2978     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2979 
2980     /* Preparing source code. */
2981     std::string geometry_shader(s_geometry_shader_source_code_template); /* Storage for vertex shader source code. */
2982     std::string transform_feedback_variable_declarations(
2983         ""); /* String to contain all custom outputs from vertex shader. */
2984     std::string transform_feedback_variable_setters(
2985         ""); /* String containing all initializations of custom outputs from vertex shader. */
2986     std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2987     std::vector<const glw::GLchar *> transform_feedback_varyings_c(
2988         m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2989 
2990     glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2991         m_max_transform_feedback_components /* total max to be written by the shader */
2992             / 4                             /* components per vec4 */
2993         //                                                                          / 4 /* number of vertices */
2994         - 1 /* gl_Position */;
2995 
2996     glw::GLint all_transform_feedback_interleaved_varyings_count =
2997         user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2998 
2999     /* Most of varyings is declarated output variables. */
3000     for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
3001     {
3002         /* Preparing variable name. */
3003         std::string varying = "result_";
3004         varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3005 
3006         transform_feedback_varyings[i] = varying;
3007 
3008         transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
3009 
3010         /* Preparing variable declaration. */
3011         transform_feedback_variable_declarations.append("out vec4 ");
3012         transform_feedback_variable_declarations.append(varying);
3013         transform_feedback_variable_declarations.append(";\n");
3014 
3015         /* Preparing variable setters. */
3016         transform_feedback_variable_setters.append("    ");
3017         transform_feedback_variable_setters.append(varying);
3018         transform_feedback_variable_setters.append(" = vec4(");
3019         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
3020         transform_feedback_variable_setters.append(".0, ");
3021         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
3022         transform_feedback_variable_setters.append(".0, ");
3023         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
3024         transform_feedback_variable_setters.append(".0, ");
3025         transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
3026         transform_feedback_variable_setters.append(".0);\n");
3027     }
3028 
3029     /* Last four varying components are gl_Position components. */
3030     transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
3031         "gl_Position";
3032 
3033     transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
3034         transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */]
3035             .c_str();
3036 
3037     /* Preprocess vertex shader source code template. */
3038     geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3039         geometry_shader, "TEMPLATE_PRIMITIVE_TYPE", s_geometry_interleaved_primitive_cases[primitive_case]);
3040     geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3041         geometry_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
3042     geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(geometry_shader, "TEMPLATE_OUTPUT_SETTERS",
3043                                                                            transform_feedback_variable_setters);
3044     geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3045         geometry_shader, "TEMPLATE_RASTERIZATION_EPSILON",
3046         gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
3047 
3048     /* Compile, link and check. */
3049     m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
3050         gl, m_context.getTestContext().getLog(), geometry_shader.c_str(), NULL, NULL, s_blank_vertex_shader_source_code,
3051         s_fragment_shader_source_code, &transform_feedback_varyings_c[0],
3052         all_transform_feedback_interleaved_varyings_count, m_attrib_type);
3053 
3054     if (0 == m_program)
3055     {
3056         throw 0;
3057     }
3058 }
3059 
draw(glw::GLuint primitive_case)3060 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(glw::GLuint primitive_case)
3061 {
3062     /* Functions handler */
3063     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3064 
3065     gl.clear(GL_COLOR_BUFFER_BIT);
3066     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
3067 
3068     gl.beginTransformFeedback(s_geometry_interleaved_primitive_cases_xfb[primitive_case]);
3069     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
3070 
3071     gl.drawArrays(GL_POINTS, 0, 1);
3072     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
3073 
3074     gl.endTransformFeedback();
3075     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
3076 }
3077 
3078 const glw::GLchar *gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_shader_source_code_template =
3079     "#version 150\n"
3080     "\n"
3081     "layout(points) in;\n"
3082     "layout(TEMPLATE_PRIMITIVE_TYPE, max_vertices = 4) out;\n"
3083     "\n"
3084     "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
3085     "\n"
3086     "void main()\n"
3087     "{\n"
3088     "    /* Note: The points are moved 0.0625 from the borders to\n"
3089     "             reduce non-XFB related rasterization problems. */\n"
3090     "\n"
3091     "    gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3092     "1.0);\n"
3093     "TEMPLATE_OUTPUT_SETTERS"
3094     "    EmitVertex();\n"
3095     "\n"
3096     "    gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON,  1.0 - TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3097     "1.0);\n"
3098     "TEMPLATE_OUTPUT_SETTERS"
3099     "    EmitVertex();\n"
3100     "\n"
3101     "    gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3102     "1.0);\n"
3103     "TEMPLATE_OUTPUT_SETTERS"
3104     "    EmitVertex();\n"
3105     "\n"
3106     "    gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON,  0.0,  "
3107     "1.0);\n"
3108     "TEMPLATE_OUTPUT_SETTERS"
3109     "    EmitVertex();\n"
3110     "}\n";
3111 
3112 const glw::GLchar *gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_blank_vertex_shader_source_code =
3113     "#version 130\n"
3114     "\n"
3115     "void main()\n"
3116     "{\n"
3117     "}\n";
3118 
3119 const glw::GLchar *gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases[] = {
3120     "points", "line_strip", "triangle_strip"};
3121 
3122 const glw::GLenum gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_xfb[] =
3123     {GL_POINTS, GL_LINES, GL_TRIANGLES};
3124 
3125 const glw::GLuint gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_count =
3126     sizeof(s_geometry_interleaved_primitive_cases) / sizeof(s_geometry_interleaved_primitive_cases[0]);
3127 
3128 /*-----------------------------------------------------------------------------------------------*/
3129 
CaptureVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3130 gl3cts::TransformFeedback::CaptureVertexSeparate::CaptureVertexSeparate(deqp::Context &context, const char *test_name,
3131                                                                         const char *test_description)
3132     : CaptureVertexInterleaved(context, test_name, test_description)
3133     , m_buffers(DE_NULL)
3134     , m_max_transform_feedback_separate_attribs(0)
3135 {
3136     m_attrib_type = GL_SEPARATE_ATTRIBS;
3137 }
3138 
fetchLimits(void)3139 void gl3cts::TransformFeedback::CaptureVertexSeparate::fetchLimits(void)
3140 {
3141     /* Functions handler */
3142     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3143 
3144     /* Fetching limits. */
3145     glw::GLint max_transform_feedback_separate_components;
3146 
3147     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
3148 
3149     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3150 
3151     if (max_transform_feedback_separate_components < 4)
3152     {
3153         throw 0;
3154     }
3155 
3156     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_transform_feedback_separate_attribs);
3157 
3158     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3159 
3160     if (m_max_transform_feedback_separate_attribs == 0)
3161     {
3162         throw 0;
3163     }
3164 
3165     m_max_transform_feedback_components = m_max_transform_feedback_separate_attribs * 4 /* vec4 is used */;
3166 
3167     glw::GLint max_varyings_components = 0;
3168 
3169     gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
3170 
3171     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3172 
3173     if (max_varyings_components == 0)
3174     {
3175         throw 0;
3176     }
3177 
3178     if (m_max_transform_feedback_components > max_varyings_components)
3179     {
3180         m_max_transform_feedback_components = max_varyings_components;
3181     }
3182 }
3183 
createTransformFeedbackBuffer(void)3184 void gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(void)
3185 {
3186     /* Functions handler */
3187     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3188 
3189     m_buffers = new glw::GLuint[m_max_transform_feedback_components];
3190 
3191     if (DE_NULL == m_buffers)
3192     {
3193         throw 0;
3194     }
3195 
3196     gl.genBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3197     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
3198 
3199     m_buffer_size = static_cast<glw::GLuint>(m_max_vertices_drawn * 4 /* vec4 */ * sizeof(glw::GLfloat));
3200 
3201     for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3202     {
3203         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3204         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3205 
3206         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
3207         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
3208     }
3209 }
3210 
bindBuffer(BindBufferCase bind_case)3211 void gl3cts::TransformFeedback::CaptureVertexSeparate::bindBuffer(BindBufferCase bind_case)
3212 {
3213     /* Functions handler */
3214     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3215 
3216     switch (bind_case)
3217     {
3218     case BIND_BUFFER_BASE_CASE:
3219         for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3220         {
3221             gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i]);
3222         }
3223         break;
3224     case BIND_BUFFER_RANGE_CASE:
3225         for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3226         {
3227             gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0, m_buffer_size);
3228         }
3229         break;
3230     case BIND_BUFFER_OFFSET_CASE:
3231         for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3232         {
3233             m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0);
3234         }
3235         break;
3236     default:
3237         throw 0;
3238     }
3239 }
3240 
cleanBuffer(void)3241 void gl3cts::TransformFeedback::CaptureVertexSeparate::cleanBuffer(void)
3242 {
3243     /* Functions handler */
3244     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3245 
3246     if (DE_NULL != m_buffers)
3247     {
3248         gl.deleteBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3249 
3250         delete[] m_buffers;
3251 
3252         m_buffers = DE_NULL;
3253     }
3254 }
3255 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3256 bool gl3cts::TransformFeedback::CaptureVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3257                                                                                     glw::GLenum primitive_type)
3258 {
3259     /* Functions handler */
3260     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3261 
3262     glw::GLuint number_of_vertices = 0;
3263 
3264     switch (primitive_type)
3265     {
3266     case GL_POINTS:
3267         number_of_vertices = 4;
3268         break;
3269     case GL_LINES:
3270         number_of_vertices = 4;
3271         break;
3272     case GL_LINE_LOOP:
3273         number_of_vertices = 8;
3274         break;
3275     case GL_LINE_STRIP:
3276         number_of_vertices = 6;
3277         break;
3278     case GL_TRIANGLES:
3279         number_of_vertices = 6;
3280         break;
3281     case GL_TRIANGLE_STRIP:
3282         number_of_vertices = 6;
3283         break;
3284     case GL_TRIANGLE_FAN:
3285         number_of_vertices = 6;
3286         break;
3287     default:
3288         throw 0;
3289     }
3290 
3291     bool is_ok = true;
3292 
3293     for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs - 1; ++i)
3294     {
3295         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3296         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3297 
3298         glw::GLfloat *results = (glw::GLfloat *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3299         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3300 
3301         for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3302         {
3303             for (glw::GLuint k = 0; k < 4 /* vec4 */; ++k)
3304             {
3305                 glw::GLfloat result    = results[j * 4 + k];
3306                 glw::GLfloat reference = (glw::GLfloat)(i * 4 + k);
3307 
3308                 if (fabs(result - reference) > 0.125 /* precision */)
3309                 {
3310                     is_ok = false;
3311 
3312                     break;
3313                 }
3314             }
3315         }
3316 
3317         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3318         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3319     }
3320 
3321     /* gl_Position */
3322     if (is_ok)
3323     {
3324         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[m_max_transform_feedback_separate_attribs - 1]);
3325         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3326 
3327         glw::GLfloat *results = (glw::GLfloat *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3328         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3329 
3330         for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3331         {
3332             glw::GLfloat result[4] = {results[j * 4], results[j * 4 + 1], results[j * 4 + 2], results[j * 4 + 3]};
3333 
3334             if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3335                 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3336                 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
3337             {
3338                 is_ok = false;
3339 
3340                 break;
3341             }
3342         }
3343 
3344         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3345         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3346     }
3347 
3348     return is_ok;
3349 }
3350 
3351 /*-----------------------------------------------------------------------------------------------*/
3352 
CaptureGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3353 gl3cts::TransformFeedback::CaptureGeometrySeparate::CaptureGeometrySeparate(deqp::Context &context,
3354                                                                             const char *test_name,
3355                                                                             const char *test_description)
3356     : CaptureVertexInterleaved(context, test_name, test_description)
3357     , CaptureVertexSeparate(context, test_name, test_description)
3358     , CaptureGeometryInterleaved(context, test_name, test_description)
3359     , m_buffers(DE_NULL)
3360     , m_max_transform_feedback_separate_attribs(0)
3361 {
3362 }
3363 
3364 /*-----------------------------------------------------------------------------------------------*/
3365 
CheckGetXFBVarying(deqp::Context & context,const char * test_name,const char * test_description)3366 gl3cts::TransformFeedback::CheckGetXFBVarying::CheckGetXFBVarying(deqp::Context &context, const char *test_name,
3367                                                                   const char *test_description)
3368     : deqp::TestCase(context, test_name, test_description)
3369     , m_context(context)
3370     , m_max_xfb_interleaved_components(0)
3371     , m_max_xfb_separate_attributes(0)
3372     , m_max_xfb_separate_components(0)
3373     , m_max_varying_components(0)
3374     , m_max_varying_vectors(0)
3375     , m_max_geometry_total_output_components(0)
3376 {
3377 }
3378 
~CheckGetXFBVarying(void)3379 gl3cts::TransformFeedback::CheckGetXFBVarying::~CheckGetXFBVarying(void)
3380 {
3381 }
3382 
fetchLimits(void)3383 void gl3cts::TransformFeedback::CheckGetXFBVarying::fetchLimits(void)
3384 {
3385     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3386 
3387     /* Fetching limits. */
3388     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_xfb_interleaved_components);
3389     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_xfb_separate_attributes);
3390     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &m_max_xfb_separate_components);
3391     gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &m_max_varying_components);
3392     gl.getIntegerv(GL_MAX_VARYING_VECTORS, &m_max_varying_vectors);
3393     gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_geometry_total_output_components);
3394 
3395     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3396 }
3397 
numberOfAttributes(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type)3398 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::numberOfAttributes(glw::GLuint capture_way,
3399                                                                               glw::GLuint shader_case,
3400                                                                               glw::GLuint varying_type)
3401 {
3402     /* Setup limits of the case. */
3403     const glw::GLuint max_total_components =
3404         ((s_shader_cases[shader_case].geometry_shader == DE_NULL) ? m_max_varying_components :
3405                                                                     m_max_geometry_total_output_components) -
3406         4 /* gl_Position is not captured */;
3407 
3408     const glw::GLuint attribute_components = s_varying_types[varying_type].components_count;
3409     const glw::GLuint max_xfb_components   = (s_capture_ways[capture_way] == GL_INTERLEAVED_ATTRIBS) ?
3410                                                  m_max_xfb_interleaved_components :
3411                                                  (attribute_components * m_max_xfb_separate_components);
3412 
3413     if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS)
3414     {
3415         if (attribute_components > glw::GLuint(m_max_xfb_separate_components))
3416         {
3417             return 0;
3418         }
3419     }
3420 
3421     /* Setup number of attributes. */
3422     glw::GLuint number_of_attributes = max_xfb_components / attribute_components;
3423 
3424     if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS &&
3425         number_of_attributes > glw::GLuint(m_max_xfb_separate_attributes))
3426     {
3427         number_of_attributes = m_max_xfb_separate_attributes;
3428     }
3429 
3430     /* Clamp to limits. */
3431     if (number_of_attributes * attribute_components > max_total_components)
3432     {
3433         number_of_attributes = max_total_components / attribute_components;
3434     }
3435 
3436     /* Vectors limit. */
3437     if (attribute_components <= 4)
3438     {
3439         if (number_of_attributes > glw::GLuint(m_max_varying_vectors))
3440         {
3441             number_of_attributes = m_max_varying_vectors;
3442         }
3443     }
3444     else
3445     {
3446         if (number_of_attributes > glw::GLuint(m_max_varying_vectors) / 4)
3447         {
3448             number_of_attributes = glw::GLuint(m_max_varying_vectors) / 4;
3449         }
3450     }
3451 
3452     /* Return. */
3453     return number_of_attributes;
3454 }
3455 
iterate(void)3456 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CheckGetXFBVarying::iterate(void)
3457 {
3458     /* Functions handler */
3459     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3460 
3461     /* Initializations. */
3462     bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
3463     bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
3464     bool is_ext_tf_1       = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
3465     bool is_arb_gs_4       = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
3466 
3467     bool is_ok      = true;
3468     bool test_error = false;
3469 
3470     glw::GLuint program = 0;
3471 
3472     /* Tests. */
3473     try
3474     {
3475         if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
3476         {
3477             fetchLimits();
3478 
3479             for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i)
3480             {
3481                 for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j)
3482                 {
3483                     for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k)
3484                     {
3485                         glw::GLuint n = numberOfAttributes(i, j, k);
3486 
3487                         if (n)
3488                         {
3489                             program = buildProgram(i, j, k, n);
3490 
3491                             is_ok = is_ok && (program != 0);
3492 
3493                             is_ok = is_ok && check(program, i, j, k, n);
3494 
3495                             gl.deleteProgram(program);
3496 
3497                             GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
3498 
3499                             program = 0;
3500                         }
3501                     }
3502                 }
3503             }
3504         }
3505     }
3506     catch (...)
3507     {
3508         is_ok      = false;
3509         test_error = true;
3510 
3511         if (program)
3512         {
3513             gl.deleteProgram(program);
3514 
3515             program = 0;
3516         }
3517     }
3518 
3519     /* Result's setup. */
3520     if (is_ok)
3521     {
3522         /* Log success. */
3523         m_context.getTestContext().getLog()
3524             << tcu::TestLog::Message << "Test checking Get Transform Feedback Varying have passed."
3525             << tcu::TestLog::EndMessage;
3526 
3527         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3528     }
3529     else
3530     {
3531         if (test_error)
3532         {
3533             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3534         }
3535         else
3536         {
3537             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3538         }
3539     }
3540 
3541     return STOP;
3542 }
3543 
buildProgram(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type,glw::GLuint number_of_attributes)3544 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way,
3545                                                                         glw::GLuint shader_case,
3546                                                                         glw::GLuint varying_type,
3547                                                                         glw::GLuint number_of_attributes)
3548 {
3549     /* Functions handler */
3550     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3551 
3552     /* Preparing source code. */
3553     std::string xfb_variable_declarations("");
3554     std::string xfb_variable_setters("");
3555     std::vector<std::string> xfb_varyings(number_of_attributes);
3556     std::vector<const glw::GLchar *> xfb_varyings_c(number_of_attributes);
3557 
3558     /* Most of varyings is declarated output variables. */
3559     for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3560     {
3561         /* Varying name: result_# */
3562         std::string varying = "result_";
3563         varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3564 
3565         xfb_varyings[i]   = varying;
3566         xfb_varyings_c[i] = xfb_varyings[i].c_str();
3567 
3568         /* Varying declaration: out TYPE result_#;*/
3569         xfb_variable_declarations.append("out ");
3570         xfb_variable_declarations.append(s_varying_types[varying_type].name);
3571         xfb_variable_declarations.append(" ");
3572         xfb_variable_declarations.append(varying);
3573         xfb_variable_declarations.append(";\n");
3574 
3575         /* Varying setter: result_# = TYPE(#); */
3576         xfb_variable_setters.append("    ");
3577         xfb_variable_setters.append(varying);
3578         xfb_variable_setters.append(" = ");
3579         xfb_variable_setters.append(s_varying_types[varying_type].name);
3580         xfb_variable_setters.append("(");
3581         xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i));
3582         if (s_varying_types[varying_type].float_component)
3583         {
3584             /* if varying is float varying setter is: result_# = TYPE(#.0); */
3585             xfb_variable_setters.append(".0");
3586         }
3587         xfb_variable_setters.append(");\n");
3588     }
3589 
3590     /* Preprocess vertex shader source code template. */
3591     const glw::GLchar *vertex_shader   = s_shader_cases[shader_case].vertex_shader;
3592     const glw::GLchar *geometry_shader = s_shader_cases[shader_case].geometry_shader;
3593 
3594     std::string xfb_shader;
3595 
3596     if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3597     {
3598         /* XFB tested in vertex shader. */
3599         xfb_shader = vertex_shader;
3600     }
3601     else
3602     {
3603         /* XFB tested in geometry shader. */
3604         xfb_shader = geometry_shader;
3605     }
3606 
3607     /* Preprocess shader. */
3608     xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS",
3609                                                                       xfb_variable_declarations);
3610     xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS",
3611                                                                       xfb_variable_setters);
3612 
3613     if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3614     {
3615         /* XFB tested in vertex shader. */
3616         vertex_shader = xfb_shader.c_str();
3617     }
3618     else
3619     {
3620         /* XFB tested in geometry shader. */
3621         geometry_shader = xfb_shader.c_str();
3622     }
3623 
3624     /* Compile, link and check. */
3625     glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
3626         gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader,
3627         &xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]);
3628 
3629     /* Check compilation status. */
3630     if (0 == program)
3631     {
3632         m_context.getTestContext().getLog()
3633             << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n"
3634             << vertex_shader << "Geometry shader:\n"
3635             << ((DE_NULL == geometry_shader) ? "" : geometry_shader) << "Fragment shader:\n"
3636             << s_generic_fragment_shader << tcu::TestLog::EndMessage;
3637 
3638         throw 0;
3639     }
3640 
3641     return program;
3642 }
3643 
check(glw::GLuint program,glw::GLuint capture_way,glw::GLuint shader_case UNUSED,glw::GLuint varying_type,glw::GLuint number_of_attributes)3644 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way,
3645                                                           glw::GLuint shader_case UNUSED, glw::GLuint varying_type,
3646                                                           glw::GLuint number_of_attributes)
3647 {
3648     /* Functions handler */
3649     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3650     glw::GLuint max_length   = 0;
3651 
3652     /* Inspect glGetTransformFeedbackVarying. */
3653     for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3654     {
3655         const glw::GLsizei bufSize = 18;
3656         glw::GLsizei length        = 0;
3657         glw::GLsizei size          = 0;
3658         glw::GLenum type           = GL_NONE;
3659         glw::GLchar name[18]       = {0}; /* Size of bufSize. */
3660 
3661         gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name);
3662 
3663         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed.");
3664 
3665         max_length = deMaxu32(max_length, glw::GLuint(length));
3666 
3667         /* Check name. */
3668         if (length)
3669         {
3670             std::string varying     = name;
3671             std::string varying_ref = "result_";
3672             varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3673 
3674             if (0 != varying.compare(varying_ref))
3675             {
3676                 return false;
3677             }
3678         }
3679         else
3680         {
3681             return false;
3682         }
3683 
3684         /* Check size. */
3685         const glw::GLuint size_ref = 1;
3686 
3687         if (size != size_ref)
3688         {
3689             return false;
3690         }
3691 
3692         /* Check type. */
3693         if (type != s_varying_types[varying_type].type)
3694         {
3695             return false;
3696         }
3697     }
3698 
3699     /* Inspect glGetProgramiv. */
3700     glw::GLint xfb_varyings           = 0;
3701     glw::GLint xfb_mode               = 0;
3702     glw::GLint xfb_varying_max_length = 0;
3703 
3704     gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings);
3705     gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode);
3706     gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length);
3707 
3708     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3709 
3710     if (glw::GLuint(xfb_varyings) != number_of_attributes)
3711     {
3712         return false;
3713     }
3714 
3715     if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way])
3716     {
3717         return false;
3718     }
3719 
3720     if (glw::GLuint(xfb_varying_max_length) < max_length)
3721     {
3722         return false;
3723     }
3724 
3725     return true;
3726 }
3727 
3728 const glw::GLchar *gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n"
3729                                                                                               "\n"
3730                                                                                               "out vec4 color;\n"
3731                                                                                               "\n"
3732                                                                                               "void main()\n"
3733                                                                                               "{\n"
3734                                                                                               "    color = vec4(1.0);\n"
3735                                                                                               "}\n";
3736 
3737 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase
3738     gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = {{/* Vertex Shader. */
3739                                                                         "#version 130\n"
3740                                                                         "\n"
3741                                                                         "TEMPLATE_OUTPUT_DECLARATIONS"
3742                                                                         "\n"
3743                                                                         "void main()\n"
3744                                                                         "{\n"
3745                                                                         "    gl_Position = vec4(1.0);\n"
3746                                                                         "TEMPLATE_OUTPUT_SETTERS"
3747                                                                         "}\n",
3748 
3749                                                                         /* Geometry Shader. */
3750                                                                         NULL},
3751                                                                        {/* Vertex Shader. */
3752                                                                         "#version 130\n"
3753                                                                         "\n"
3754                                                                         "void main()\n"
3755                                                                         "{\n"
3756                                                                         "}\n",
3757 
3758                                                                         /* Geometry Shader. */
3759                                                                         "#version 150\n"
3760                                                                         "\n"
3761                                                                         "layout(points) in;\n"
3762                                                                         "layout(points, max_vertices = 1) out;\n"
3763                                                                         "\n"
3764                                                                         "TEMPLATE_OUTPUT_DECLARATIONS"
3765                                                                         "\n"
3766                                                                         "void main()\n"
3767                                                                         "{\n"
3768                                                                         "    gl_Position = vec4(1.0);\n"
3769                                                                         "TEMPLATE_OUTPUT_SETTERS"
3770                                                                         "    EmitVertex();\n"
3771                                                                         "}\n"}};
3772 
3773 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count =
3774     sizeof(s_shader_cases) / sizeof(s_shader_cases[0]);
3775 
3776 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType
3777     gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = {
3778         /* type, name, #components, is component float */
3779         {GL_FLOAT, "float", 1, true},
3780         {GL_FLOAT_VEC2, "vec2", 2, true},
3781         {GL_FLOAT_VEC3, "vec3", 3, true},
3782         {GL_FLOAT_VEC4, "vec4", 4, true},
3783         {GL_INT, "int", 1, false},
3784         {GL_INT_VEC2, "ivec2", 2, false},
3785         {GL_INT_VEC3, "ivec3", 3, false},
3786         {GL_INT_VEC4, "ivec4", 4, false},
3787         {GL_UNSIGNED_INT, "uint", 1, false},
3788         {GL_UNSIGNED_INT_VEC2, "uvec2", 2, false},
3789         {GL_UNSIGNED_INT_VEC3, "uvec3", 3, false},
3790         {GL_UNSIGNED_INT_VEC4, "uvec4", 4, false},
3791         {GL_FLOAT_MAT2, "mat2", 4, true},
3792         {GL_FLOAT_MAT3, "mat3", 9, true},
3793         {GL_FLOAT_MAT4, "mat4", 16, true}};
3794 
3795 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count =
3796     sizeof(s_varying_types) / sizeof(s_varying_types[0]);
3797 
3798 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = {GL_INTERLEAVED_ATTRIBS,
3799                                                                                      GL_SEPARATE_ATTRIBS};
3800 
3801 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count =
3802     sizeof(s_capture_ways) / sizeof(s_capture_ways[0]);
3803 
3804 /*-----------------------------------------------------------------------------------------------*/
3805 
QueryVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3806 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context &context, const char *test_name,
3807                                                                           const char *test_description)
3808     : CaptureVertexInterleaved(context, test_name, test_description)
3809     , m_query_object(0)
3810 {
3811     m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3812 }
3813 
createTransformFeedbackBuffer(void)3814 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void)
3815 {
3816     /* Functions handler */
3817     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3818 
3819     /* Create buffer object. */
3820     gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer();
3821 
3822     /* Create query object. */
3823     gl.genQueries(1, &m_query_object);
3824     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3825 }
3826 
draw(glw::GLuint primitive_case)3827 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case)
3828 {
3829     /* Functions handler */
3830     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3831 
3832     gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3833     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3834 
3835     gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
3836 
3837     gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3838     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3839 }
3840 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3841 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3842                                                                                      glw::GLenum primitive_type)
3843 {
3844     /* Functions handler */
3845     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3846 
3847     glw::GLuint number_of_primitives;
3848 
3849     gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3850     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3851 
3852     /* expected result */
3853     glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3854 
3855     if (number_of_primitives_reference != number_of_primitives)
3856     {
3857         return false;
3858     }
3859 
3860     return true;
3861 }
3862 
clean(void)3863 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void)
3864 {
3865     /* Functions handler */
3866     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3867 
3868     /* Delete query object. */
3869     gl.deleteQueries(1, &m_query_object);
3870     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3871 
3872     /* Other */
3873     gl3cts::TransformFeedback::CaptureVertexInterleaved::clean();
3874 }
3875 
3876 /*-----------------------------------------------------------------------------------------------*/
3877 
QueryGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3878 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context &context,
3879                                                                               const char *test_name,
3880                                                                               const char *test_description)
3881     : CaptureVertexInterleaved(context, test_name, test_description)
3882     , CaptureGeometryInterleaved(context, test_name, test_description)
3883 {
3884     m_query_object       = 0;
3885     m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3886 }
3887 
createTransformFeedbackBuffer(void)3888 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void)
3889 {
3890     /* Functions handler */
3891     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3892 
3893     /* Create buffer object. */
3894     gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer();
3895 
3896     /* Create query object. */
3897     gl.genQueries(1, &m_query_object);
3898     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3899 }
3900 
draw(glw::GLuint primitive_case)3901 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case)
3902 {
3903     /* Functions handler */
3904     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3905 
3906     gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3907     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3908 
3909     gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
3910 
3911     gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3912     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3913 }
3914 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3915 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3916                                                                                        glw::GLenum primitive_type)
3917 {
3918     /* Functions handler */
3919     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3920 
3921     glw::GLuint number_of_primitives;
3922 
3923     gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3924     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3925 
3926     /* expected result */
3927     glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3928 
3929     if (number_of_primitives_reference != number_of_primitives)
3930     {
3931         return false;
3932     }
3933 
3934     return true;
3935 }
3936 
clean(void)3937 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void)
3938 {
3939     /* Functions handler */
3940     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3941 
3942     /* Delete query object. */
3943     gl.deleteQueries(1, &m_query_object);
3944     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3945 
3946     /* Other. */
3947     gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean();
3948 }
3949 
3950 /*-----------------------------------------------------------------------------------------------*/
3951 
QueryVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3952 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context &context, const char *test_name,
3953                                                                     const char *test_description)
3954     : CaptureVertexInterleaved(context, test_name, test_description)
3955     , CaptureVertexSeparate(context, test_name, test_description)
3956 {
3957     m_query_object       = 0;
3958     m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3959 }
3960 
createTransformFeedbackBuffer(void)3961 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void)
3962 {
3963     /* Functions handler */
3964     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3965 
3966     /* Create buffer object. */
3967     gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer();
3968 
3969     /* Create query object. */
3970     gl.genQueries(1, &m_query_object);
3971     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3972 }
3973 
draw(glw::GLuint primitive_case)3974 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case)
3975 {
3976     /* Functions handler */
3977     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3978 
3979     gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3980     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3981 
3982     gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case);
3983 
3984     gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3985     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3986 }
3987 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3988 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3989                                                                                   glw::GLenum primitive_type)
3990 {
3991     /* Functions handler */
3992     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3993 
3994     glw::GLuint number_of_primitives;
3995 
3996     gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3997     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3998 
3999     /* expected result */
4000     glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4001 
4002     if (number_of_primitives_reference != number_of_primitives)
4003     {
4004         return false;
4005     }
4006 
4007     return true;
4008 }
4009 
clean(void)4010 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void)
4011 {
4012     /* Functions handler */
4013     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4014 
4015     /* Delete query object. */
4016     gl.deleteQueries(1, &m_query_object);
4017     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4018 
4019     /* Other */
4020     gl3cts::TransformFeedback::CaptureVertexSeparate::clean();
4021 }
4022 
4023 /*-----------------------------------------------------------------------------------------------*/
4024 
QueryGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)4025 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context &context, const char *test_name,
4026                                                                         const char *test_description)
4027     : CaptureVertexInterleaved(context, test_name, test_description)
4028     , CaptureVertexSeparate(context, test_name, test_description)
4029     , CaptureGeometrySeparate(context, test_name, test_description)
4030 {
4031     m_query_object       = 0;
4032     m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
4033 }
4034 
createTransformFeedbackBuffer(void)4035 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void)
4036 {
4037     /* Functions handler */
4038     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4039 
4040     /* Create buffer object. */
4041     gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer();
4042 
4043     /* Create query object. */
4044     gl.genQueries(1, &m_query_object);
4045     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
4046 }
4047 
draw(glw::GLuint primitive_case)4048 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case)
4049 {
4050     /* Functions handler */
4051     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4052 
4053     gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
4054     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
4055 
4056     gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case);
4057 
4058     gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4059     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
4060 }
4061 
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)4062 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
4063                                                                                     glw::GLenum primitive_type)
4064 {
4065     /* Functions handler */
4066     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4067 
4068     glw::GLuint number_of_primitives;
4069 
4070     gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
4071     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
4072 
4073     /* expected result */
4074     glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4075 
4076     if (number_of_primitives_reference != number_of_primitives)
4077     {
4078         return false;
4079     }
4080 
4081     return true;
4082 }
4083 
clean(void)4084 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void)
4085 {
4086     /* Functions handler */
4087     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4088 
4089     /* Delete query object. */
4090     gl.deleteQueries(1, &m_query_object);
4091     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4092 
4093     /* Other */
4094     gl3cts::TransformFeedback::CaptureGeometrySeparate::clean();
4095 }
4096 
4097 /*-----------------------------------------------------------------------------------------------*/
4098 
DiscardVertex(deqp::Context & context,const char * test_name,const char * test_description)4099 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context &context, const char *test_name,
4100                                                         const char *test_description)
4101     : CaptureVertexInterleaved(context, test_name, test_description)
4102 {
4103 }
4104 
draw(glw::GLuint primitive_case)4105 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case)
4106 {
4107     /* Functions handler */
4108     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4109 
4110     /* Must clear before rasterizer discard */
4111     gl.clear(GL_COLOR_BUFFER_BIT);
4112     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4113 
4114     gl.enable(GL_RASTERIZER_DISCARD);
4115     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4116 
4117     gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
4118 
4119     gl.disable(GL_RASTERIZER_DISCARD);
4120     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4121 }
4122 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4123 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4124 {
4125     /* Functions handler */
4126     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4127 
4128     /* Fetch framebuffer. */
4129     std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4130 
4131     if (s_framebuffer_size > 0)
4132     {
4133         gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4134         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4135     }
4136 
4137     /* Check results.
4138      Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4139     for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4140     {
4141         if (fabs(*i) > 0.0625f /* precision */)
4142         {
4143             return false;
4144         }
4145     }
4146 
4147     return true;
4148 }
4149 
4150 /*-----------------------------------------------------------------------------------------------*/
4151 
DiscardGeometry(deqp::Context & context,const char * test_name,const char * test_description)4152 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context &context, const char *test_name,
4153                                                             const char *test_description)
4154     : CaptureVertexInterleaved(context, test_name, test_description)
4155     , CaptureGeometryInterleaved(context, test_name, test_description)
4156 {
4157 }
4158 
draw(glw::GLuint primitive_case)4159 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case)
4160 {
4161     /* Functions handler */
4162     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4163 
4164     /* Must clear before rasterizer discard */
4165     gl.clear(GL_COLOR_BUFFER_BIT);
4166     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4167 
4168     gl.enable(GL_RASTERIZER_DISCARD);
4169     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4170 
4171     gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
4172 
4173     gl.disable(GL_RASTERIZER_DISCARD);
4174     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4175 }
4176 
checkFramebuffer(glw::GLuint primitive_case UNUSED)4177 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4178 {
4179     /* Functions handler */
4180     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4181 
4182     /* Fetch framebuffer. */
4183     std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4184 
4185     if (s_framebuffer_size > 0)
4186     {
4187         gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4188         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4189     }
4190 
4191     /* Check results.
4192      Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4193     for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4194     {
4195         if (fabs(*i) > 0.0625f /* precision */)
4196         {
4197             return false;
4198         }
4199     }
4200 
4201     return true;
4202 }
4203 
4204 /*-----------------------------------------------------------------------------------------------*/
4205 
DrawXFB(deqp::Context & context,const char * test_name,const char * test_description)4206 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context &context, const char *test_name, const char *test_description)
4207     : deqp::TestCase(context, test_name, test_description)
4208     , m_context(context)
4209     , m_program_id_xfb(0)
4210     , m_program_id_draw(0)
4211     , m_fbo_id(0)
4212     , m_rbo_id(0)
4213     , m_vao_id(0)
4214 {
4215     memset(m_xfb_id, 0, sizeof(m_xfb_id));
4216     memset(m_bo_id, 0, sizeof(m_bo_id));
4217 }
4218 
~DrawXFB(void)4219 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void)
4220 {
4221 }
4222 
iterate(void)4223 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void)
4224 {
4225     /* Initializations. */
4226     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4227     bool is_arb_tf_2       = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4228 
4229     bool is_ok      = true;
4230     bool test_error = false;
4231 
4232     /* Tests. */
4233     try
4234     {
4235         if (is_at_least_gl_40 || is_arb_tf_2)
4236         {
4237             for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i)
4238             {
4239                 prepare(s_capture_modes[i]);
4240 
4241                 bindVAO(m_vao_id);
4242                 useProgram(m_program_id_xfb);
4243 
4244                 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4245                 {
4246                     bindXFB(m_xfb_id[j]);
4247                     bindBOForXFB(s_capture_modes[i], m_bo_id[j]);
4248                     useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4249                     useGeometrySet(m_program_id_xfb, false);
4250                     drawForCapture(true, true, false, false);
4251 
4252                     is_ok = is_ok && inspectXFBState(true, true);
4253                 }
4254 
4255                 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4256                 {
4257                     bindXFB(m_xfb_id[j]);
4258                     useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4259                     useGeometrySet(m_program_id_xfb, true);
4260                     drawForCapture(false, false, true, true);
4261 
4262                     is_ok = is_ok && inspectXFBState(false, false);
4263                 }
4264 
4265                 useProgram(m_program_id_draw);
4266 
4267                 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4268                 {
4269                     bindXFB(m_xfb_id[j]);
4270                     bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]);
4271                     drawToFramebuffer(m_xfb_id[j]);
4272 
4273                     is_ok =
4274                         is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4275                 }
4276 
4277                 clean();
4278             }
4279         }
4280     }
4281     catch (...)
4282     {
4283         is_ok      = false;
4284         test_error = true;
4285         clean();
4286     }
4287 
4288     /* Result's setup. */
4289     if (is_ok)
4290     {
4291         /* Log success. */
4292         m_context.getTestContext().getLog()
4293             << tcu::TestLog::Message << "Draw XFB have passed." << tcu::TestLog::EndMessage;
4294 
4295         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4296     }
4297     else
4298     {
4299         if (test_error)
4300         {
4301             /* Log error. */
4302             m_context.getTestContext().getLog()
4303                 << tcu::TestLog::Message << "Draw XFB have approached error." << tcu::TestLog::EndMessage;
4304 
4305             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4306         }
4307         else
4308         {
4309             /* Log fail. */
4310             m_context.getTestContext().getLog()
4311                 << tcu::TestLog::Message << "Draw XFB have failed." << tcu::TestLog::EndMessage;
4312 
4313             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4314         }
4315     }
4316 
4317     return STOP;
4318 }
4319 
prepare(glw::GLenum capture_mode)4320 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode)
4321 {
4322     /* Functions handler */
4323     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4324 
4325     /* Prepare programs. */
4326     m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram(
4327         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader,
4328         s_xfb_varyings, s_xfb_varyings_count, capture_mode);
4329 
4330     if (0 == m_program_id_xfb)
4331     {
4332         throw 0;
4333     }
4334 
4335     m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(),
4336                                                                            NULL, NULL, NULL, s_vertex_shader_draw,
4337                                                                            s_fragment_shader, NULL, 0, capture_mode);
4338 
4339     if (0 == m_program_id_draw)
4340     {
4341         throw 0;
4342     }
4343 
4344     /* Prepare transform feedbacks. */
4345     gl.genTransformFeedbacks(s_xfb_count, m_xfb_id);
4346     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4347 
4348     /* Prepare buffer objects. */
4349     gl.genBuffers(s_xfb_count, m_bo_id);
4350     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4351 
4352     for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4353     {
4354         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
4355         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4356 
4357         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY);
4358         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4359     }
4360 
4361     /* Prepare framebuffer. */
4362     gl.clearColor(0.f, 0.f, 0.f, 1.f);
4363     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4364 
4365     gl.genFramebuffers(1, &m_fbo_id);
4366     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
4367 
4368     gl.genRenderbuffers(1, &m_rbo_id);
4369     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
4370 
4371     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4372     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
4373 
4374     gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
4375     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
4376 
4377     gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
4378     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
4379 
4380     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
4381     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
4382 
4383     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
4384     {
4385         throw 0;
4386     }
4387 
4388     gl.viewport(0, 0, s_view_size, s_view_size);
4389     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
4390 
4391     /* Create empty Vertex Array Object */
4392     gl.genVertexArrays(1, &m_vao_id);
4393     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4394 }
4395 
bindXFB(glw::GLuint xfb_id)4396 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id)
4397 {
4398     /* Functions handler */
4399     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4400 
4401     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id);
4402     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
4403 }
4404 
bindVAO(glw::GLuint vao_id)4405 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id)
4406 {
4407     /* Functions handler */
4408     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4409 
4410     gl.bindVertexArray(vao_id);
4411     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4412 }
4413 
bindBOForXFB(glw::GLenum capture_mode,glw::GLuint bo_id)4414 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id)
4415 {
4416     /* Functions handler */
4417     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4418 
4419     switch (capture_mode)
4420     {
4421     case GL_INTERLEAVED_ATTRIBS:
4422         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
4423         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4424         break;
4425     case GL_SEPARATE_ATTRIBS:
4426         for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i)
4427         {
4428             gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count,
4429                                (i + 1) * s_capture_size / s_xfb_varyings_count);
4430             GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4431         }
4432         break;
4433     default:
4434         throw 0;
4435     }
4436 }
4437 
bindBOForDraw(glw::GLuint program_id,glw::GLenum capture_mode,glw::GLuint bo_id)4438 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode,
4439                                                        glw::GLuint bo_id)
4440 {
4441     /* Functions handler */
4442     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4443 
4444     gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
4445 
4446     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4447 
4448     glw::GLuint position_location = gl.getAttribLocation(program_id, "position");
4449     glw::GLuint color_location    = gl.getAttribLocation(program_id, "color");
4450 
4451     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4452 
4453     glw::GLvoid *color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4454                                     (glw::GLvoid *)(4 /* components */ * sizeof(glw::GLfloat)) :
4455                                     (glw::GLvoid *)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat));
4456 
4457     glw::GLuint stride =
4458         static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4459                                      (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) :
4460                                      (4 /* components */ * sizeof(glw::GLfloat)));
4461 
4462     gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL);
4463     gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset);
4464 
4465     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4466 
4467     gl.enableVertexAttribArray(position_location);
4468     gl.enableVertexAttribArray(color_location);
4469 
4470     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4471 }
4472 
useProgram(glw::GLuint program_id)4473 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id)
4474 {
4475     /* Functions handler */
4476     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4477 
4478     gl.useProgram(program_id);
4479     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4480 }
4481 
useColour(glw::GLuint program_id,glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4482 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g,
4483                                                    glw::GLfloat b, glw::GLfloat a)
4484 {
4485     /* Functions handler */
4486     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4487 
4488     glw::GLint location = gl.getUniformLocation(program_id, "color");
4489     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4490 
4491     gl.uniform4f(location, r, g, b, a);
4492     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4493 }
4494 
useGeometrySet(glw::GLuint program_id,bool invert_sign)4495 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign)
4496 {
4497     /* Functions handler */
4498     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4499 
4500     glw::GLint location = gl.getUniformLocation(program_id, "invert_sign");
4501     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4502 
4503     gl.uniform1f(location, invert_sign ? -1.f : 1.f);
4504     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4505 }
4506 
clean()4507 void gl3cts::TransformFeedback::DrawXFB::clean()
4508 {
4509     /* Functions handler */
4510     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4511 
4512     gl.useProgram(0);
4513 
4514     if (m_program_id_xfb)
4515     {
4516         gl.deleteProgram(m_program_id_xfb);
4517 
4518         m_program_id_xfb = 0;
4519     }
4520 
4521     if (m_program_id_draw)
4522     {
4523         gl.deleteProgram(m_program_id_draw);
4524 
4525         m_program_id_draw = 1;
4526     }
4527 
4528     for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4529     {
4530         if (m_xfb_id[i])
4531         {
4532             gl.deleteTransformFeedbacks(1, &m_xfb_id[i]);
4533 
4534             m_xfb_id[i] = 0;
4535         }
4536     }
4537 
4538     for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4539     {
4540         if (m_bo_id[i])
4541         {
4542             gl.deleteBuffers(1, &m_bo_id[i]);
4543 
4544             m_bo_id[i] = 0;
4545         }
4546     }
4547 
4548     if (m_vao_id)
4549     {
4550         gl.deleteVertexArrays(1, &m_vao_id);
4551 
4552         m_vao_id = 0;
4553     }
4554 
4555     if (m_fbo_id)
4556     {
4557         gl.deleteFramebuffers(1, &m_fbo_id);
4558 
4559         m_fbo_id = 0;
4560     }
4561 
4562     if (m_rbo_id)
4563     {
4564         gl.deleteRenderbuffers(1, &m_rbo_id);
4565 
4566         m_rbo_id = 0;
4567     }
4568 }
4569 
drawForCapture(bool begin_xfb,bool pause_xfb,bool resume_xfb,bool end_xfb)4570 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb)
4571 {
4572     /* Functions handler */
4573     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4574 
4575     gl.enable(GL_RASTERIZER_DISCARD);
4576     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4577 
4578     if (begin_xfb)
4579     {
4580         gl.beginTransformFeedback(GL_POINTS);
4581         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4582     }
4583 
4584     if (resume_xfb)
4585     {
4586         gl.resumeTransformFeedback();
4587         GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed.");
4588     }
4589 
4590     gl.drawArrays(GL_POINTS, 0, 3);
4591 
4592     if (pause_xfb)
4593     {
4594         gl.pauseTransformFeedback();
4595         GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
4596     }
4597 
4598     if (end_xfb)
4599     {
4600         gl.endTransformFeedback();
4601         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4602     }
4603 
4604     gl.disable(GL_RASTERIZER_DISCARD);
4605     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4606 }
4607 
drawToFramebuffer(glw::GLuint xfb_id)4608 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id)
4609 {
4610     /* Functions handler */
4611     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4612 
4613     gl.clearColor(0.f, 0.f, 0.f, 0.f);
4614     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4615 
4616     gl.clear(GL_COLOR_BUFFER_BIT);
4617     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4618 
4619     gl.drawTransformFeedback(GL_TRIANGLES, xfb_id);
4620     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4621 }
4622 
checkFramebuffer(glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4623 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b,
4624                                                           glw::GLfloat a)
4625 {
4626     /* Functions handler */
4627     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4628 
4629     /* Number of pixels. */
4630     const glw::GLuint number_of_pixels = s_view_size * s_view_size;
4631 
4632     /* Fetch framebuffer. */
4633     std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */);
4634 
4635     if (s_view_size > 0)
4636     {
4637         gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
4638         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4639     }
4640 
4641     /* Convert color to integer. */
4642     glw::GLubyte ir = (glw::GLubyte)(255.f * r);
4643     glw::GLubyte ig = (glw::GLubyte)(255.f * g);
4644     glw::GLubyte ib = (glw::GLubyte)(255.f * b);
4645     glw::GLubyte ia = (glw::GLubyte)(255.f * a);
4646 
4647     /* Check results. */
4648     for (glw::GLuint i = 0; i < number_of_pixels; ++i)
4649     {
4650         if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) ||
4651             (pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia))
4652         {
4653             return false;
4654         }
4655     }
4656 
4657     return true;
4658 }
4659 
inspectXFBState(bool shall_be_paused,bool shall_be_active)4660 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active)
4661 {
4662     /* Functions handler */
4663     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4664 
4665     glw::GLint is_paused = 0;
4666     glw::GLint is_active = 0;
4667 
4668     gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
4669     gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
4670 
4671     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4672 
4673     if ((is_paused == -1) || (is_active == -1))
4674     {
4675         throw 0;
4676     }
4677 
4678     if (shall_be_paused ^ (is_paused == GL_TRUE))
4679     {
4680         return false;
4681     }
4682 
4683     if (shall_be_active ^ (is_active == GL_TRUE))
4684     {
4685         return false;
4686     }
4687 
4688     return true;
4689 }
4690 
4691 const glw::GLchar *gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb =
4692     "#version 130\n"
4693     "\n"
4694     "uniform vec4 color;\n"
4695     "uniform float invert_sign;\n"
4696     "out     vec4 colour;\n"
4697     "\n"
4698     "void main()\n"
4699     "{\n"
4700     "    switch(gl_VertexID)\n"
4701     "    {\n"
4702     "        case 0:\n"
4703     "            gl_Position = vec4(-1.0,               -1.0,              0.0,  1.0);\n"
4704     "        break;\n"
4705     "        case 1:\n"
4706     "            gl_Position = vec4(-1.0 * invert_sign,  1.0,              0.0,  1.0);\n"
4707     "        break;\n"
4708     "        case 2:\n"
4709     "            gl_Position = vec4( 1.0,                1.0 * invert_sign, 0.0,  1.0);\n"
4710     "        break;\n"
4711     "    }\n"
4712     "\n"
4713     "    colour = color;\n"
4714     "}\n";
4715 
4716 const glw::GLchar *gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n"
4717                                                                               "\n"
4718                                                                               "in  vec4 color;\n"
4719                                                                               "in  vec4 position;\n"
4720                                                                               "out vec4 colour;\n"
4721                                                                               "\n"
4722                                                                               "void main()\n"
4723                                                                               "{\n"
4724                                                                               "    gl_Position = position;\n"
4725                                                                               "    colour      = color;\n"
4726                                                                               "}\n";
4727 
4728 const glw::GLchar *gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n"
4729                                                                            "\n"
4730                                                                            "in  vec4 colour;\n"
4731                                                                            "out vec4 pixel;\n"
4732                                                                            "\n"
4733                                                                            "void main()\n"
4734                                                                            "{\n"
4735                                                                            "    pixel = colour;\n"
4736                                                                            "}\n";
4737 
4738 const glw::GLchar *gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = {"gl_Position", "colour"};
4739 
4740 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = {GL_INTERLEAVED_ATTRIBS, GL_SEPARATE_ATTRIBS};
4741 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count =
4742     sizeof(s_capture_modes) / sizeof(s_capture_modes[0]);
4743 
4744 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = {{1.f, 0.f, 0.f, 1.f},
4745                                                                                     {0.f, 1.f, 0.f, 1.f},
4746                                                                                     {0.f, 0.f, 1.f, 1.f}};
4747 
4748 /*-----------------------------------------------------------------------------------------------*/
4749 
DrawXFBFeedback(deqp::Context & context,const char * test_name,const char * test_description)4750 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context &context, const char *test_name,
4751                                                             const char *test_description)
4752     : deqp::TestCase(context, test_name, test_description)
4753     , m_context(context)
4754     , m_program_id(0)
4755     , m_xfb_id(0)
4756     , m_source_bo_index(0)
4757 {
4758     memset(m_bo_id, 1, sizeof(m_bo_id));
4759     memset(m_bo_id, 1, sizeof(m_vao_id));
4760 }
4761 
~DrawXFBFeedback(void)4762 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void)
4763 {
4764 }
4765 
iterate(void)4766 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void)
4767 {
4768     /* Initializations. */
4769     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4770     bool is_arb_tf_2       = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4771 
4772     bool is_ok      = true;
4773     bool test_error = false;
4774 
4775     /* Tests. */
4776     try
4777     {
4778         if (is_at_least_gl_40 || is_arb_tf_2)
4779         {
4780             prepareAndBind();
4781             draw(true);
4782             swapBuffers();
4783             draw(false);
4784             swapBuffers();
4785             draw(false);
4786 
4787             is_ok = is_ok && check();
4788         }
4789     }
4790     catch (...)
4791     {
4792         is_ok      = false;
4793         test_error = true;
4794     }
4795 
4796     /* Clean GL objects. */
4797     clean();
4798 
4799     /* Result's setup. */
4800     if (is_ok)
4801     {
4802         /* Log success. */
4803         m_context.getTestContext().getLog()
4804             << tcu::TestLog::Message << "Draw XFB Feedback have passed." << tcu::TestLog::EndMessage;
4805 
4806         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4807     }
4808     else
4809     {
4810         if (test_error)
4811         {
4812             /* Log error. */
4813             m_context.getTestContext().getLog()
4814                 << tcu::TestLog::Message << "Draw XFB Feedback have approached error." << tcu::TestLog::EndMessage;
4815 
4816             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4817         }
4818         else
4819         {
4820             /* Log fail. */
4821             m_context.getTestContext().getLog()
4822                 << tcu::TestLog::Message << "Draw XFB Feedback have failed." << tcu::TestLog::EndMessage;
4823 
4824             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4825         }
4826     }
4827 
4828     return STOP;
4829 }
4830 
prepareAndBind()4831 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind()
4832 {
4833     /* Functions handler */
4834     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4835 
4836     /* Prepare programs. */
4837     m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL,
4838                                                                       NULL, NULL, s_vertex_shader, s_fragment_shader,
4839                                                                       &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
4840 
4841     if (0 == m_program_id)
4842     {
4843         throw 0;
4844     }
4845 
4846     gl.useProgram(m_program_id);
4847     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4848 
4849     /* Prepare transform feedbacks. */
4850     gl.genTransformFeedbacks(1, &m_xfb_id);
4851     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4852 
4853     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
4854     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
4855 
4856     /* Prepare buffer objects. */
4857     gl.genBuffers(s_bo_count, m_bo_id);
4858     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4859 
4860     gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]);
4861     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4862 
4863     gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY);
4864     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4865 
4866     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]);
4867     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4868 
4869     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
4870     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4871 
4872     /* Setup vertex arrays. */
4873     gl.genVertexArrays(s_bo_count, m_vao_id);
4874     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4875 
4876     glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position");
4877     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4878 
4879     for (glw::GLuint i = 0; i < 2; ++i)
4880     {
4881         gl.bindVertexArray(m_vao_id[i]);
4882         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4883 
4884         gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]);
4885         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4886 
4887         gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4888         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4889 
4890         gl.enableVertexAttribArray(position_location);
4891         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4892     }
4893 
4894     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4895     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4896 
4897     gl.bindVertexArray(m_vao_id[0]);
4898     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4899 }
4900 
swapBuffers()4901 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers()
4902 {
4903     /* Functions handler */
4904     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4905 
4906     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]);
4907     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4908 
4909     m_source_bo_index = (m_source_bo_index + 1) % 2;
4910 
4911     gl.bindVertexArray(m_vao_id[(m_source_bo_index)]);
4912     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4913 }
4914 
draw(bool is_first_draw)4915 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw)
4916 {
4917     /* Functions handler */
4918     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4919 
4920     gl.enable(GL_RASTERIZER_DISCARD);
4921     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4922 
4923     gl.beginTransformFeedback(GL_POINTS);
4924     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4925 
4926     if (is_first_draw)
4927     {
4928         gl.drawArrays(GL_POINTS, 0, 1);
4929         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
4930     }
4931     else
4932     {
4933         gl.drawTransformFeedback(GL_POINTS, m_xfb_id);
4934         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4935     }
4936 
4937     gl.endTransformFeedback();
4938     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4939 
4940     gl.disable(GL_RASTERIZER_DISCARD);
4941     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4942 }
4943 
check()4944 bool gl3cts::TransformFeedback::DrawXFBFeedback::check()
4945 {
4946     /* Functions handler */
4947     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4948 
4949     glw::GLfloat *results =
4950         (glw::GLfloat *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
4951     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
4952 
4953     bool is_ok = false;
4954 
4955     if (results)
4956     {
4957         if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f))
4958         {
4959             is_ok = true;
4960         }
4961 
4962         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4963         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
4964     }
4965 
4966     return is_ok;
4967 }
4968 
clean()4969 void gl3cts::TransformFeedback::DrawXFBFeedback::clean()
4970 {
4971     /* Functions handler */
4972     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4973 
4974     gl.useProgram(0);
4975 
4976     if (m_program_id)
4977     {
4978         gl.deleteProgram(m_program_id);
4979 
4980         m_program_id = 0;
4981     }
4982 
4983     if (m_xfb_id)
4984     {
4985         gl.deleteTransformFeedbacks(1, &m_xfb_id);
4986 
4987         m_xfb_id = 0;
4988     }
4989 
4990     for (glw::GLuint i = 0; i < s_bo_count; ++i)
4991     {
4992         if (m_bo_id[i])
4993         {
4994             gl.deleteBuffers(1, &m_bo_id[i]);
4995 
4996             m_bo_id[i] = 0;
4997         }
4998     }
4999 
5000     for (glw::GLuint i = 0; i < s_bo_count; ++i)
5001     {
5002         if (m_vao_id[i])
5003         {
5004             gl.deleteVertexArrays(1, &m_vao_id[i]);
5005 
5006             m_vao_id[i] = 0;
5007         }
5008     }
5009 }
5010 
5011 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n"
5012                                                                                  "\n"
5013                                                                                  "in  vec4 position;\n"
5014                                                                                  "\n"
5015                                                                                  "void main()\n"
5016                                                                                  "{\n"
5017                                                                                  "    gl_Position = position * 2.0;\n"
5018                                                                                  "}\n";
5019 
5020 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n"
5021                                                                                    "\n"
5022                                                                                    "out vec4 pixel;\n"
5023                                                                                    "\n"
5024                                                                                    "void main()\n"
5025                                                                                    "{\n"
5026                                                                                    "    pixel = vec4(1.0);\n"
5027                                                                                    "}\n";
5028 
5029 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position";
5030 
5031 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position";
5032 
5033 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = {1.f, 2.f, 3.f, 4.f};
5034 
5035 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count =
5036     sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */;
5037 
5038 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data);
5039 
5040 /*-----------------------------------------------------------------------------------------------*/
5041 
CaptureSpecialInterleaved(deqp::Context & context,const char * test_name,const char * test_description)5042 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context &context,
5043                                                                                 const char *test_name,
5044                                                                                 const char *test_description)
5045     : deqp::TestCase(context, test_name, test_description)
5046     , m_context(context)
5047     , m_program_id(0)
5048     , m_vao_id(0)
5049     , m_xfb_id(0)
5050 {
5051     memset(m_bo_id, 0, sizeof(m_bo_id));
5052 }
5053 
~CaptureSpecialInterleaved(void)5054 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void)
5055 {
5056 }
5057 
iterate(void)5058 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void)
5059 {
5060     /* Initializations. */
5061     bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5062     bool is_arb_tf_3       = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5063 
5064     bool is_ok      = true;
5065     bool test_error = false;
5066 
5067     /* Tests. */
5068     try
5069     {
5070         if (is_at_least_gl_40 || is_arb_tf_3)
5071         {
5072             prepareAndBind();
5073             draw();
5074 
5075             is_ok = is_ok && check();
5076         }
5077     }
5078     catch (...)
5079     {
5080         is_ok      = false;
5081         test_error = true;
5082     }
5083 
5084     /* Clean GL objects. */
5085     clean();
5086 
5087     /* Result's setup. */
5088     if (is_ok)
5089     {
5090         /* Log success. */
5091         m_context.getTestContext().getLog()
5092             << tcu::TestLog::Message << "Capture Special Interleaved have passed." << tcu::TestLog::EndMessage;
5093 
5094         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5095     }
5096     else
5097     {
5098         if (test_error)
5099         {
5100             /* Log error. */
5101             m_context.getTestContext().getLog()
5102                 << tcu::TestLog::Message << "Capture Special Interleaved have approached error."
5103                 << tcu::TestLog::EndMessage;
5104 
5105             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5106         }
5107         else
5108         {
5109             /* Log fail. */
5110             m_context.getTestContext().getLog()
5111                 << tcu::TestLog::Message << "Capture Special Interleaved have failed." << tcu::TestLog::EndMessage;
5112 
5113             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5114         }
5115     }
5116 
5117     return STOP;
5118 }
5119 
prepareAndBind()5120 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind()
5121 {
5122     /* Functions handler */
5123     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5124 
5125     /* Prepare programs. */
5126     m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(
5127         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings,
5128         s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5129 
5130     if (0 == m_program_id)
5131     {
5132         throw 0;
5133     }
5134 
5135     gl.useProgram(m_program_id);
5136     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5137 
5138     /* Prepare transform feedbacks. */
5139     gl.genTransformFeedbacks(1, &m_xfb_id);
5140     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5141 
5142     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5143     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5144 
5145     /* Create empty Vertex Array Object */
5146     gl.genVertexArrays(1, &m_vao_id);
5147     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5148 
5149     gl.bindVertexArray(m_vao_id);
5150     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5151 
5152     /* Prepare buffer objects. */
5153     gl.genBuffers(s_bo_ids_count, m_bo_id);
5154     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5155 
5156     for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5157     {
5158         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5159         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5160 
5161         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5162         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5163 
5164         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5165         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5166     }
5167 }
5168 
draw()5169 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw()
5170 {
5171     /* Functions handler */
5172     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5173 
5174     gl.enable(GL_RASTERIZER_DISCARD);
5175     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5176 
5177     gl.beginTransformFeedback(GL_POINTS);
5178     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5179 
5180     gl.drawArrays(GL_POINTS, 0, 1);
5181     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5182 
5183     gl.endTransformFeedback();
5184     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5185 
5186     gl.disable(GL_RASTERIZER_DISCARD);
5187     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5188 }
5189 
check()5190 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check()
5191 {
5192     /* Functions handler */
5193     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5194 
5195     bool is_ok = true;
5196 
5197     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]);
5198     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5199 
5200     glw::GLfloat *results =
5201         (glw::GLfloat *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5202     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5203 
5204     if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) ||
5205         /* gl_SkipComponents4 here */
5206         (results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0))
5207     {
5208         is_ok = false;
5209     }
5210 
5211     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5212     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5213 
5214     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]);
5215     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5216 
5217     results = (glw::GLfloat *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5218     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5219 
5220     if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) ||
5221         /* gl_SkipComponents4 here */
5222         (results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0))
5223     {
5224         is_ok = false;
5225     }
5226 
5227     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5228     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5229 
5230     return is_ok;
5231 }
5232 
clean()5233 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean()
5234 {
5235     /* Functions handler */
5236     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5237 
5238     gl.useProgram(0);
5239 
5240     if (m_program_id)
5241     {
5242         gl.deleteProgram(m_program_id);
5243 
5244         m_program_id = 0;
5245     }
5246 
5247     if (m_xfb_id)
5248     {
5249         gl.deleteTransformFeedbacks(1, &m_xfb_id);
5250 
5251         m_xfb_id = 0;
5252     }
5253 
5254     for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5255     {
5256         if (m_bo_id[i])
5257         {
5258             gl.deleteBuffers(1, &m_bo_id[i]);
5259 
5260             m_bo_id[i] = 0;
5261         }
5262     }
5263 
5264     if (m_vao_id)
5265     {
5266         gl.deleteVertexArrays(1, &m_vao_id);
5267 
5268         m_vao_id = 0;
5269     }
5270 }
5271 
5272 const glw::GLchar *gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader =
5273     "#version 130\n"
5274     "\n"
5275     "out vec4 variable_1;\n"
5276     "out vec4 variable_2;\n"
5277     "out vec4 variable_3;\n"
5278     "out vec4 variable_4;\n"
5279     "\n"
5280     "void main()\n"
5281     "{\n"
5282     "    variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n"
5283     "    variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n"
5284     "    variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n"
5285     "    variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n"
5286     "\n"
5287     "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5288     "}\n";
5289 
5290 const glw::GLchar *gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n"
5291                                                                                              "\n"
5292                                                                                              "out vec4 pixel;\n"
5293                                                                                              "\n"
5294                                                                                              "void main()\n"
5295                                                                                              "{\n"
5296                                                                                              "    pixel = vec4(1.0);\n"
5297                                                                                              "}\n";
5298 
5299 const glw::GLchar *gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] = {
5300     "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer",
5301     "variable_3", "gl_SkipComponents4", "variable_4"};
5302 
5303 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count =
5304     sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5305 
5306 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size =
5307     3 /*number of variables / empty places */ * 4 /* vec4 */
5308     * sizeof(glw::GLfloat);
5309 
5310 /*-----------------------------------------------------------------------------------------------*/
5311 
DrawXFBStream(deqp::Context & context,const char * test_name,const char * test_description)5312 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context &context, const char *test_name,
5313                                                         const char *test_description)
5314     : deqp::TestCase(context, test_name, test_description)
5315     , m_context(context)
5316     , m_program_id_generate(0)
5317     , m_program_id_draw(0)
5318     , m_vao_id(0)
5319     , m_xfb_id(0)
5320     , m_fbo_id(0)
5321     , m_rbo_id(0)
5322 {
5323     memset(m_bo_id, 0, sizeof(m_bo_id));
5324     memset(m_qo_id, 0, sizeof(m_qo_id));
5325 }
5326 
~DrawXFBStream(void)5327 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void)
5328 {
5329 }
5330 
iterate(void)5331 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void)
5332 {
5333     /* Functions handler */
5334     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5335 
5336     /* Initializations. */
5337     bool is_at_least_gl_40  = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5338     bool is_arb_tf_3        = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5339     bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
5340 
5341     glw::GLint max_vertex_streams = 0;
5342 
5343     bool is_ok      = true;
5344     bool test_error = false;
5345 
5346     /* Tests. */
5347     try
5348     {
5349         if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5))
5350         {
5351             gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
5352             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5353 
5354             if (max_vertex_streams >= 2)
5355             {
5356                 prepareObjects();
5357 
5358                 useProgram(m_program_id_generate);
5359 
5360                 drawForXFB();
5361 
5362                 is_ok = is_ok && inspectQueries();
5363 
5364                 useProgram(m_program_id_draw);
5365 
5366                 setupVertexArray(m_bo_id[0]);
5367 
5368                 drawForFramebuffer(0);
5369 
5370                 setupVertexArray(m_bo_id[1]);
5371 
5372                 drawForFramebuffer(1);
5373 
5374                 is_ok = is_ok && check();
5375             }
5376         }
5377     }
5378     catch (...)
5379     {
5380         is_ok      = false;
5381         test_error = true;
5382     }
5383 
5384     /* Clean GL objects. */
5385     clean();
5386 
5387     /* Result's setup. */
5388     if (is_ok)
5389     {
5390         /* Log success. */
5391         m_context.getTestContext().getLog()
5392             << tcu::TestLog::Message << "Draw XFB Stream have passed." << tcu::TestLog::EndMessage;
5393 
5394         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5395     }
5396     else
5397     {
5398         if (test_error)
5399         {
5400             /* Log error. */
5401             m_context.getTestContext().getLog()
5402                 << tcu::TestLog::Message << "Draw XFB Stream have approached error." << tcu::TestLog::EndMessage;
5403 
5404             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5405         }
5406         else
5407         {
5408             /* Log fail. */
5409             m_context.getTestContext().getLog()
5410                 << tcu::TestLog::Message << "Draw XFB Stream have failed." << tcu::TestLog::EndMessage;
5411 
5412             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5413         }
5414     }
5415 
5416     return STOP;
5417 }
5418 
prepareObjects()5419 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects()
5420 {
5421     /* Functions handler */
5422     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5423 
5424     /* Prepare programs. */
5425     m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5426         gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank,
5427         s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5428 
5429     if (0 == m_program_id_generate)
5430     {
5431         throw 0;
5432     }
5433 
5434     m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5435         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0,
5436         GL_INTERLEAVED_ATTRIBS);
5437 
5438     if (0 == m_program_id_draw)
5439     {
5440         throw 0;
5441     }
5442 
5443     /* Prepare transform feedbacks. */
5444     gl.genTransformFeedbacks(1, &m_xfb_id);
5445     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5446 
5447     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5448     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5449 
5450     /* Create empty Vertex Array Object */
5451     gl.genVertexArrays(1, &m_vao_id);
5452     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5453 
5454     gl.bindVertexArray(m_vao_id);
5455     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5456 
5457     /* Prepare buffer objects. */
5458     gl.genBuffers(s_bo_ids_count, m_bo_id);
5459     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5460 
5461     for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5462     {
5463         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5464         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5465 
5466         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5467         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5468 
5469         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5470         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5471     }
5472 
5473     /* Generate queries */
5474     gl.genQueries(s_qo_ids_count, m_qo_id);
5475     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
5476 
5477     /* Prepare framebuffer. */
5478     gl.clearColor(0.f, 0.f, 0.f, 1.f);
5479     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5480 
5481     gl.genFramebuffers(1, &m_fbo_id);
5482     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5483 
5484     gl.genRenderbuffers(1, &m_rbo_id);
5485     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5486 
5487     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5488     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5489 
5490     gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5491     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5492 
5493     gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5494     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5495 
5496     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5497     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5498 
5499     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5500     {
5501         throw 0;
5502     }
5503 
5504     gl.viewport(0, 0, s_view_size, s_view_size);
5505     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5506 }
5507 
setupVertexArray(glw::GLuint bo_id)5508 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id)
5509 {
5510     /* Functions handler */
5511     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5512 
5513     gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
5514     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5515 
5516     glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5517     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5518 
5519     gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5520     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5521 
5522     gl.enableVertexAttribArray(position_location);
5523     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5524 }
5525 
useProgram(glw::GLuint program_id)5526 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id)
5527 {
5528     /* Functions handler */
5529     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5530 
5531     gl.useProgram(program_id);
5532     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5533 }
5534 
drawForXFB()5535 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB()
5536 {
5537     /* Functions handler */
5538     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5539 
5540     gl.enable(GL_RASTERIZER_DISCARD);
5541     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5542 
5543     gl.beginTransformFeedback(GL_POINTS);
5544     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5545 
5546     gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]);
5547     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5548 
5549     gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]);
5550     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5551 
5552     gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]);
5553     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5554 
5555     gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]);
5556     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5557 
5558     gl.drawArrays(GL_POINTS, 0, 1);
5559     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5560 
5561     gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0);
5562     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5563 
5564     gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1);
5565     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5566 
5567     gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
5568     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5569 
5570     gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1);
5571     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5572 
5573     gl.endTransformFeedback();
5574     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5575 
5576     gl.disable(GL_RASTERIZER_DISCARD);
5577     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5578 }
5579 
drawForFramebuffer(glw::GLuint stream)5580 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream)
5581 {
5582     /* Functions handler */
5583     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5584 
5585     gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream);
5586     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed.");
5587 }
5588 
inspectQueries()5589 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries()
5590 {
5591     /* Functions handler */
5592     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5593 
5594     glw::GLint generated_primitives_to_stream_0 = 0;
5595     glw::GLint generated_primitives_to_stream_1 = 0;
5596 
5597     gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0);
5598     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5599 
5600     gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1);
5601     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5602 
5603     glw::GLint primitives_written_to_xfb_to_stream_0 = 0;
5604     glw::GLint primitives_written_to_xfb_to_stream_1 = 0;
5605 
5606     gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0);
5607     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5608 
5609     gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1);
5610     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5611 
5612     if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) &&
5613         (primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3))
5614     {
5615         return true;
5616     }
5617 
5618     return false;
5619 }
5620 
check()5621 bool gl3cts::TransformFeedback::DrawXFBStream::check()
5622 {
5623     /* Functions handler */
5624     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5625 
5626     /* Number of pixels. */
5627     const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5628 
5629     /* Fetch framebuffer. */
5630     std::vector<glw::GLfloat> pixels(number_of_pixels);
5631 
5632     gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
5633     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
5634 
5635     /* Check results. */
5636     for (glw::GLuint i = 0; i < number_of_pixels; ++i)
5637     {
5638         if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
5639         {
5640             return false;
5641         }
5642     }
5643 
5644     return true;
5645 }
5646 
clean()5647 void gl3cts::TransformFeedback::DrawXFBStream::clean()
5648 {
5649     /* Functions handler */
5650     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5651 
5652     gl.useProgram(0);
5653 
5654     if (m_program_id_generate)
5655     {
5656         gl.deleteProgram(m_program_id_generate);
5657 
5658         m_program_id_generate = 0;
5659     }
5660 
5661     if (m_program_id_draw)
5662     {
5663         glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5664 
5665         gl.disableVertexAttribArray(position_location);
5666 
5667         gl.deleteProgram(m_program_id_draw);
5668 
5669         m_program_id_draw = 0;
5670     }
5671 
5672     if (m_xfb_id)
5673     {
5674         gl.deleteTransformFeedbacks(1, &m_xfb_id);
5675 
5676         m_xfb_id = 0;
5677     }
5678 
5679     for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5680     {
5681         if (m_bo_id[i])
5682         {
5683             gl.deleteBuffers(1, &m_bo_id[i]);
5684 
5685             m_bo_id[i] = 0;
5686         }
5687     }
5688 
5689     if (m_vao_id)
5690     {
5691         gl.deleteVertexArrays(1, &m_vao_id);
5692 
5693         m_vao_id = 0;
5694     }
5695 
5696     if (m_fbo_id)
5697     {
5698         gl.deleteFramebuffers(1, &m_fbo_id);
5699 
5700         m_fbo_id = 0;
5701     }
5702 
5703     if (m_rbo_id)
5704     {
5705         gl.deleteRenderbuffers(1, &m_rbo_id);
5706 
5707         m_rbo_id = 0;
5708     }
5709 }
5710 
5711 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n"
5712                                                                                      "\n"
5713                                                                                      "void main()\n"
5714                                                                                      "{\n"
5715                                                                                      "}\n";
5716 
5717 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n"
5718                                                                                     "\n"
5719                                                                                     "in vec4 position;\n"
5720                                                                                     "\n"
5721                                                                                     "void main()\n"
5722                                                                                     "{\n"
5723                                                                                     "    gl_Position = position;\n"
5724                                                                                     "}\n";
5725 
5726 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader =
5727     "#version 400\n"
5728     "\n"
5729     "layout(points) in;\n"
5730     "layout(points, max_vertices = 6) out;\n"
5731     "\n"
5732     "layout(stream = 1) out vec4 position;\n"
5733     "\n"
5734     "void main()\n"
5735     "{\n"
5736     "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5737     "    EmitStreamVertex(0);\n"
5738     "    gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5739     "    EmitStreamVertex(0);\n"
5740     "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5741     "    EmitStreamVertex(0);\n"
5742     "\n"
5743     "    position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5744     "    EmitStreamVertex(1);\n"
5745     "    position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
5746     "    EmitStreamVertex(1);\n"
5747     "    position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
5748     "    EmitStreamVertex(1);\n"
5749     "}\n";
5750 
5751 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n"
5752                                                                                  "\n"
5753                                                                                  "out vec4 pixel;\n"
5754                                                                                  "\n"
5755                                                                                  "void main()\n"
5756                                                                                  "{\n"
5757                                                                                  "    pixel = vec4(1.0);\n"
5758                                                                                  "}\n";
5759 
5760 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = {"gl_Position", "gl_NextBuffer",
5761                                                                                  "position"};
5762 
5763 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count =
5764     sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5765 
5766 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size =
5767     3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat);
5768 
5769 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2;
5770 
5771 /*-----------------------------------------------------------------------------------------------*/
5772 
DrawXFBInstanced(deqp::Context & context,const char * test_name,const char * test_description)5773 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context &context, const char *test_name,
5774                                                               const char *test_description)
5775     : deqp::TestCase(context, test_name, test_description)
5776     , m_context(context)
5777     , m_program_id_generate(0)
5778     , m_program_id_draw(0)
5779     , m_vao_id(0)
5780     , m_xfb_id(0)
5781     , m_bo_id_xfb(0)
5782     , m_bo_id_uniform(0)
5783     , m_fbo_id(0)
5784     , m_rbo_id(0)
5785     , m_glGetUniformBlockIndex(DE_NULL)
5786     , m_glUniformBlockBinding(DE_NULL)
5787 {
5788 }
5789 
~DrawXFBInstanced(void)5790 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void)
5791 {
5792 }
5793 
iterate(void)5794 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void)
5795 {
5796     /* Initializations. */
5797     bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
5798     bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
5799     bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
5800     bool is_arb_ubo          = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
5801 
5802     bool is_ok      = true;
5803     bool test_error = false;
5804 
5805     if (is_arb_ubo)
5806     {
5807         m_glGetUniformBlockIndex =
5808             (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
5809 
5810         m_glUniformBlockBinding =
5811             (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
5812 
5813         if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
5814         {
5815             throw 0;
5816         }
5817     }
5818 
5819     try
5820     {
5821         if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced))
5822         {
5823             prepareObjects();
5824             drawForXFB();
5825             drawInstanced();
5826 
5827             is_ok = is_ok && check();
5828         }
5829     }
5830     catch (...)
5831     {
5832         is_ok      = false;
5833         test_error = true;
5834     }
5835 
5836     /* Clean GL objects */
5837     clean();
5838 
5839     /* Result's setup. */
5840     if (is_ok)
5841     {
5842         /* Log success. */
5843         m_context.getTestContext().getLog()
5844             << tcu::TestLog::Message << "Draw XFB Instanced have passed." << tcu::TestLog::EndMessage;
5845 
5846         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5847     }
5848     else
5849     {
5850         if (test_error)
5851         {
5852             /* Log error. */
5853             m_context.getTestContext().getLog()
5854                 << tcu::TestLog::Message << "Draw XFB Instanced have approached error." << tcu::TestLog::EndMessage;
5855 
5856             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5857         }
5858         else
5859         {
5860             /* Log fail. */
5861             m_context.getTestContext().getLog()
5862                 << tcu::TestLog::Message << "Draw XFB Instanced have failed." << tcu::TestLog::EndMessage;
5863 
5864             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5865         }
5866     }
5867 
5868     return STOP;
5869 }
5870 
prepareObjects()5871 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects()
5872 {
5873     /* Functions handler */
5874     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5875 
5876     /* Prepare programs. */
5877     m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5878         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader,
5879         &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
5880 
5881     if (0 == m_program_id_generate)
5882     {
5883         throw 0;
5884     }
5885 
5886     m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5887         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0,
5888         GL_INTERLEAVED_ATTRIBS);
5889 
5890     if (0 == m_program_id_draw)
5891     {
5892         throw 0;
5893     }
5894 
5895     /* Prepare transform feedbacks. */
5896     gl.genTransformFeedbacks(1, &m_xfb_id);
5897     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5898 
5899     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5900     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5901 
5902     /* Create empty Vertex Array Object */
5903     gl.genVertexArrays(1, &m_vao_id);
5904     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5905 
5906     gl.bindVertexArray(m_vao_id);
5907     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5908 
5909     /* Prepare xfb buffer object. */
5910     gl.genBuffers(1, &m_bo_id_xfb);
5911     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5912 
5913     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb);
5914     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5915 
5916     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5917     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5918 
5919     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb);
5920     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5921 
5922     /* Prepare uniform buffer object. */
5923     gl.genBuffers(1, &m_bo_id_uniform);
5924     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5925 
5926     gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
5927     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5928 
5929     gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
5930     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5931 
5932     gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
5933     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5934 
5935     glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
5936     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
5937 
5938     if (GL_INVALID_INDEX == uniform_index)
5939     {
5940         throw 0;
5941     }
5942 
5943     m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
5944     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
5945 
5946     /* Prepare framebuffer. */
5947     gl.clearColor(0.f, 0.f, 0.f, 1.f);
5948     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5949 
5950     gl.genFramebuffers(1, &m_fbo_id);
5951     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5952 
5953     gl.genRenderbuffers(1, &m_rbo_id);
5954     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5955 
5956     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5957     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5958 
5959     gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5960     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5961 
5962     gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5963     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5964 
5965     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5966     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5967 
5968     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5969     {
5970         throw 0;
5971     }
5972 
5973     gl.viewport(0, 0, s_view_size, s_view_size);
5974     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5975 }
5976 
drawForXFB()5977 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB()
5978 {
5979     /* Functions handler */
5980     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5981 
5982     gl.useProgram(m_program_id_generate);
5983     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5984 
5985     gl.enable(GL_RASTERIZER_DISCARD);
5986     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5987 
5988     gl.beginTransformFeedback(GL_POINTS);
5989     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5990 
5991     gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
5992     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5993 
5994     gl.endTransformFeedback();
5995     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5996 
5997     gl.disable(GL_RASTERIZER_DISCARD);
5998     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5999 }
6000 
drawInstanced()6001 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced()
6002 {
6003     /* Functions handler */
6004     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6005 
6006     gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb);
6007     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6008 
6009     glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6010     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6011 
6012     gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6013     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6014 
6015     gl.enableVertexAttribArray(position_location);
6016     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6017 
6018     gl.clear(GL_COLOR_BUFFER_BIT);
6019     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
6020 
6021     gl.useProgram(m_program_id_draw);
6022     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6023 
6024     gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4);
6025     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6026 }
6027 
check()6028 bool gl3cts::TransformFeedback::DrawXFBInstanced::check()
6029 {
6030     /* Functions handler */
6031     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6032 
6033     /* Number of pixels. */
6034     const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6035 
6036     /* Fetch framebuffer. */
6037     std::vector<glw::GLfloat> pixels(number_of_pixels);
6038 
6039     gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6040     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6041 
6042     /* Check results. */
6043     for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6044     {
6045         if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6046         {
6047             return false;
6048         }
6049     }
6050 
6051     return true;
6052 }
6053 
clean()6054 void gl3cts::TransformFeedback::DrawXFBInstanced::clean()
6055 {
6056     /* Functions handler */
6057     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6058 
6059     gl.useProgram(0);
6060 
6061     if (m_program_id_generate)
6062     {
6063         gl.deleteProgram(m_program_id_generate);
6064 
6065         m_program_id_generate = 0;
6066     }
6067 
6068     if (m_program_id_draw)
6069     {
6070         glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6071 
6072         gl.disableVertexAttribArray(position_location);
6073 
6074         gl.deleteProgram(m_program_id_draw);
6075 
6076         m_program_id_draw = 0;
6077     }
6078 
6079     if (m_xfb_id)
6080     {
6081         gl.deleteTransformFeedbacks(1, &m_xfb_id);
6082 
6083         m_xfb_id = 0;
6084     }
6085 
6086     if (m_bo_id_xfb)
6087     {
6088         gl.deleteBuffers(1, &m_bo_id_xfb);
6089 
6090         m_bo_id_xfb = 0;
6091     }
6092 
6093     if (m_bo_id_uniform)
6094     {
6095         gl.deleteBuffers(1, &m_bo_id_uniform);
6096 
6097         m_bo_id_uniform = 0;
6098     }
6099 
6100     if (m_vao_id)
6101     {
6102         gl.deleteVertexArrays(1, &m_vao_id);
6103 
6104         m_vao_id = 0;
6105     }
6106 
6107     if (m_fbo_id)
6108     {
6109         gl.deleteFramebuffers(1, &m_fbo_id);
6110 
6111         m_fbo_id = 0;
6112     }
6113 
6114     if (m_rbo_id)
6115     {
6116         gl.deleteRenderbuffers(1, &m_rbo_id);
6117 
6118         m_rbo_id = 0;
6119     }
6120 }
6121 
6122 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate =
6123     "#version 140\n"
6124     "\n"
6125     "void main()\n"
6126     "{\n"
6127     "    switch(gl_VertexID % 4)\n"
6128     "    {\n"
6129     "    case 0:\n"
6130     "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6131     "       break;\n"
6132     "    case 1:\n"
6133     "       gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6134     "       break;\n"
6135     "    case 2:\n"
6136     "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
6137     "       break;\n"
6138     "    case 3:\n"
6139     "       gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6140     "       break;\n"
6141     "    }\n"
6142     "}\n";
6143 
6144 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw =
6145     "#version 140\n"
6146     "\n"
6147     "uniform MatrixBlock\n"
6148     "{\n"
6149     "    mat4 transformation_0;\n"
6150     "    mat4 transformation_1;\n"
6151     "    mat4 transformation_2;\n"
6152     "    mat4 transformation_3;\n"
6153     "};\n"
6154     "\n"
6155     "in vec4 position;\n"
6156     "\n"
6157     "void main()\n"
6158     "{\n"
6159     "    switch(gl_InstanceID % 4)\n"
6160     "    {\n"
6161     "    case 0:\n"
6162     "       gl_Position = position * transformation_0;\n"
6163     "       break;\n"
6164     "    case 1:\n"
6165     "       gl_Position = position * transformation_1;\n"
6166     "       break;\n"
6167     "    case 2:\n"
6168     "       gl_Position = position * transformation_2;\n"
6169     "       break;\n"
6170     "    case 3:\n"
6171     "       gl_Position = position * transformation_3;\n"
6172     "       break;\n"
6173     "    }\n"
6174     "}\n";
6175 
6176 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n"
6177                                                                                     "\n"
6178                                                                                     "out vec4 pixel;\n"
6179                                                                                     "\n"
6180                                                                                     "void main()\n"
6181                                                                                     "{\n"
6182                                                                                     "    pixel = vec4(1.0);\n"
6183                                                                                     "}\n";
6184 
6185 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position";
6186 
6187 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock";
6188 
6189 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size =
6190     4 /* vertex count */ * 4 /* vec4 components */
6191     * sizeof(glw::GLfloat) /* data type size */;
6192 
6193 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = {
6194     0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6195 
6196     0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6197 
6198     0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6199 
6200     0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
6201 
6202 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6203 
6204 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4;
6205 
6206 /*-----------------------------------------------------------------------------------------------*/
6207 
DrawXFBStreamInstanced(deqp::Context & context,const char * test_name,const char * test_description)6208 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context &context, const char *test_name,
6209                                                                           const char *test_description)
6210     : deqp::TestCase(context, test_name, test_description)
6211     , m_context(context)
6212     , m_program_id_generate(0)
6213     , m_program_id_draw(0)
6214     , m_vao_id(0)
6215     , m_xfb_id(0)
6216     , m_bo_id_xfb_position(0)
6217     , m_bo_id_xfb_color(0)
6218     , m_bo_id_uniform(0)
6219     , m_fbo_id(0)
6220     , m_rbo_id(0)
6221     , m_glGetUniformBlockIndex(DE_NULL)
6222     , m_glUniformBlockBinding(DE_NULL)
6223 {
6224 }
6225 
~DrawXFBStreamInstanced(void)6226 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void)
6227 {
6228 }
6229 
iterate(void)6230 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void)
6231 {
6232     /* Initializations. */
6233     bool is_at_least_gl_31   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
6234     bool is_at_least_gl_40   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
6235     bool is_at_least_gl_42   = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
6236     bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
6237     bool is_arb_ubo          = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
6238     bool is_arb_gpu_shader5  = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
6239 
6240     bool is_ok      = true;
6241     bool test_error = false;
6242 
6243     if (is_arb_ubo)
6244     {
6245         m_glGetUniformBlockIndex =
6246             (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
6247 
6248         m_glUniformBlockBinding =
6249             (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
6250 
6251         if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
6252         {
6253             throw 0;
6254         }
6255     }
6256 
6257     /* Test. */
6258     try
6259     {
6260         if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) ||
6261             (is_at_least_gl_40 && is_arb_tf_instanced))
6262         {
6263             prepareObjects();
6264             drawForXFB();
6265             drawStreamInstanced();
6266 
6267             is_ok = is_ok && check();
6268         }
6269     }
6270     catch (...)
6271     {
6272         is_ok      = false;
6273         test_error = true;
6274     }
6275 
6276     /* Clean GL objects */
6277     clean();
6278 
6279     /* Result's setup. */
6280     if (is_ok)
6281     {
6282         /* Log success. */
6283         m_context.getTestContext().getLog()
6284             << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed." << tcu::TestLog::EndMessage;
6285 
6286         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6287     }
6288     else
6289     {
6290         if (test_error)
6291         {
6292             /* Log error. */
6293             m_context.getTestContext().getLog()
6294                 << tcu::TestLog::Message << "Draw XFB Stream Instanced have approached error."
6295                 << tcu::TestLog::EndMessage;
6296 
6297             m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
6298         }
6299         else
6300         {
6301             /* Log fail. */
6302             m_context.getTestContext().getLog()
6303                 << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed." << tcu::TestLog::EndMessage;
6304 
6305             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6306         }
6307     }
6308 
6309     return STOP;
6310 }
6311 
prepareObjects()6312 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects()
6313 {
6314     /* Functions handler */
6315     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6316 
6317     /* Prepare programs. */
6318     m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
6319         gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank,
6320         s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
6321 
6322     if (0 == m_program_id_generate)
6323     {
6324         throw 0;
6325     }
6326 
6327     m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
6328         gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL,
6329         0, GL_INTERLEAVED_ATTRIBS);
6330 
6331     if (0 == m_program_id_draw)
6332     {
6333         throw 0;
6334     }
6335 
6336     /* Prepare transform feedbacks. */
6337     gl.genTransformFeedbacks(1, &m_xfb_id);
6338     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
6339 
6340     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
6341     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
6342 
6343     /* Create empty Vertex Array Object */
6344     gl.genVertexArrays(1, &m_vao_id);
6345     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
6346 
6347     gl.bindVertexArray(m_vao_id);
6348     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
6349 
6350     /* Prepare xfb buffer objects. */
6351     gl.genBuffers(1, &m_bo_id_xfb_position);
6352     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6353 
6354     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position);
6355     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6356 
6357     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6358     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6359 
6360     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position);
6361     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6362 
6363     gl.genBuffers(1, &m_bo_id_xfb_color);
6364     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6365 
6366     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color);
6367     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6368 
6369     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6370     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6371 
6372     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color);
6373     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6374 
6375     /* Prepare uniform buffer object. */
6376     gl.genBuffers(1, &m_bo_id_uniform);
6377     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6378 
6379     gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
6380     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6381 
6382     gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
6383     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6384 
6385     gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
6386     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6387 
6388     glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
6389     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
6390 
6391     if (GL_INVALID_INDEX == uniform_index)
6392     {
6393         throw 0;
6394     }
6395 
6396     m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
6397     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
6398 
6399     /* Prepare framebuffer. */
6400     gl.clearColor(0.f, 0.f, 0.f, 1.f);
6401     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
6402 
6403     gl.genFramebuffers(1, &m_fbo_id);
6404     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
6405 
6406     gl.genRenderbuffers(1, &m_rbo_id);
6407     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
6408 
6409     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
6410     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
6411 
6412     gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
6413     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
6414 
6415     gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
6416     GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
6417 
6418     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
6419     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
6420 
6421     if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
6422     {
6423         throw 0;
6424     }
6425 
6426     gl.viewport(0, 0, s_view_size, s_view_size);
6427     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
6428 }
6429 
drawForXFB()6430 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB()
6431 {
6432     /* Functions handler */
6433     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6434 
6435     gl.useProgram(m_program_id_generate);
6436     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6437 
6438     gl.enable(GL_RASTERIZER_DISCARD);
6439     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
6440 
6441     gl.beginTransformFeedback(GL_POINTS);
6442     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
6443 
6444     gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
6445     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6446 
6447     gl.endTransformFeedback();
6448     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
6449 
6450     gl.disable(GL_RASTERIZER_DISCARD);
6451     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
6452 }
6453 
drawStreamInstanced()6454 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced()
6455 {
6456     /* Functions handler */
6457     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6458 
6459     gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position);
6460     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6461 
6462     glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6463     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6464 
6465     gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6466     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6467 
6468     gl.enableVertexAttribArray(position_location);
6469     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6470 
6471     gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color);
6472     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6473 
6474     glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6475     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6476 
6477     gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6478     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6479 
6480     gl.enableVertexAttribArray(color_location);
6481     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6482 
6483     gl.useProgram(m_program_id_draw);
6484     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6485 
6486     gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4);
6487     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6488 }
6489 
check()6490 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check()
6491 {
6492     /* Functions handler */
6493     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6494 
6495     /* Number of pixels. */
6496     const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6497 
6498     /* Fetch framebuffer. */
6499     std::vector<glw::GLfloat> pixels(number_of_pixels);
6500 
6501     gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6502     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6503 
6504     /* Check results. */
6505     for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6506     {
6507         if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6508         {
6509             return false;
6510         }
6511     }
6512 
6513     return true;
6514 }
6515 
clean()6516 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean()
6517 {
6518     /* Functions handler */
6519     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6520 
6521     gl.useProgram(0);
6522 
6523     if (m_program_id_generate)
6524     {
6525         gl.deleteProgram(m_program_id_generate);
6526 
6527         m_program_id_generate = 0;
6528     }
6529 
6530     if (m_program_id_draw)
6531     {
6532         glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6533 
6534         gl.disableVertexAttribArray(position_location);
6535 
6536         glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6537 
6538         gl.disableVertexAttribArray(color_location);
6539 
6540         gl.deleteProgram(m_program_id_draw);
6541 
6542         m_program_id_draw = 0;
6543     }
6544 
6545     if (m_xfb_id)
6546     {
6547         gl.deleteTransformFeedbacks(1, &m_xfb_id);
6548 
6549         m_xfb_id = 0;
6550     }
6551 
6552     if (m_bo_id_xfb_position)
6553     {
6554         gl.deleteBuffers(1, &m_bo_id_xfb_position);
6555 
6556         m_bo_id_xfb_position = 0;
6557     }
6558 
6559     if (m_bo_id_xfb_color)
6560     {
6561         gl.deleteBuffers(1, &m_bo_id_xfb_color);
6562 
6563         m_bo_id_xfb_position = 0;
6564     }
6565 
6566     if (m_bo_id_uniform)
6567     {
6568         gl.deleteBuffers(1, &m_bo_id_uniform);
6569 
6570         m_bo_id_uniform = 0;
6571     }
6572 
6573     if (m_vao_id)
6574     {
6575         gl.deleteVertexArrays(1, &m_vao_id);
6576 
6577         m_vao_id = 0;
6578     }
6579 
6580     if (m_fbo_id)
6581     {
6582         gl.deleteFramebuffers(1, &m_fbo_id);
6583 
6584         m_fbo_id = 0;
6585     }
6586 
6587     if (m_rbo_id)
6588     {
6589         gl.deleteRenderbuffers(1, &m_rbo_id);
6590 
6591         m_rbo_id = 0;
6592     }
6593 }
6594 
6595 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n"
6596                                                                                               "\n"
6597                                                                                               "void main()\n"
6598                                                                                               "{\n"
6599                                                                                               "}\n";
6600 
6601 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate =
6602     "#version 400\n"
6603     "\n"
6604     "layout(points) in;\n"
6605     "layout(points, max_vertices = 8) out;\n"
6606     "\n"
6607     "layout(stream = 1) out vec4 color;\n"
6608     "\n"
6609     "void main()\n"
6610     "{\n"
6611     "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6612     "    EmitStreamVertex(0);\n"
6613     "    gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6614     "    EmitStreamVertex(0);\n"
6615     "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
6616     "    EmitStreamVertex(0);\n"
6617     "    gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
6618     "    EmitStreamVertex(0);\n"
6619     "\n"
6620     "    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6621     "    EmitStreamVertex(1);\n"
6622     "    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6623     "    EmitStreamVertex(1);\n"
6624     "    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6625     "    EmitStreamVertex(1);\n"
6626     "    color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6627     "    EmitStreamVertex(1);\n"
6628     "}\n";
6629 
6630 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw =
6631     "#version 140\n"
6632     "\n"
6633     "uniform MatrixBlock\n"
6634     "{\n"
6635     "    mat4 transformation_0;\n"
6636     "    mat4 transformation_1;\n"
6637     "    mat4 transformation_2;\n"
6638     "    mat4 transformation_3;\n"
6639     "};\n"
6640     "\n"
6641     "in  vec4 position;\n"
6642     "in  vec4 color;\n"
6643     "out vec4 colour;\n"
6644     "\n"
6645     "void main()\n"
6646     "{\n"
6647     "    switch(gl_InstanceID % 4)\n"
6648     "    {\n"
6649     "    case 0:\n"
6650     "       gl_Position = position * transformation_0;\n"
6651     "       break;\n"
6652     "    case 1:\n"
6653     "       gl_Position = position * transformation_1;\n"
6654     "       break;\n"
6655     "    case 2:\n"
6656     "       gl_Position = position * transformation_2;\n"
6657     "       break;\n"
6658     "    case 3:\n"
6659     "       gl_Position = position * transformation_3;\n"
6660     "       break;\n"
6661     "    }\n"
6662     "    colour = color;\n"
6663     "}\n";
6664 
6665 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank =
6666     "#version 130\n"
6667     "\n"
6668     "out vec4 pixel;\n"
6669     "\n"
6670     "void main()\n"
6671     "{\n"
6672     "    pixel = vec4(1.0);\n"
6673     "}\n";
6674 
6675 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n"
6676                                                                                                "\n"
6677                                                                                                "in vec4 colour;\n"
6678                                                                                                "out vec4 pixel;\n"
6679                                                                                                "\n"
6680                                                                                                "void main()\n"
6681                                                                                                "{\n"
6682                                                                                                "    pixel = colour;\n"
6683                                                                                                "}\n";
6684 
6685 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = {"gl_Position",
6686                                                                                           "gl_NextBuffer", "color"};
6687 
6688 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count =
6689     sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
6690 
6691 const glw::GLchar *gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock";
6692 
6693 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size =
6694     4 /* vertex count */ * 4 /* vec4 components */
6695     * sizeof(glw::GLfloat) /* data type size */;
6696 
6697 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = {
6698     0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6699 
6700     0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f,  0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6701 
6702     0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6703 
6704     0.5f, 0.0f, 0.0f, 0.5f,  0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
6705 
6706 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6707 
6708 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4;
6709 
6710 /*-----------------------------------------------------------------------------------------------*/
6711 
buildProgram(glw::Functions const & gl,tcu::TestLog & log,glw::GLchar const * const geometry_shader_source,glw::GLchar const * const tessellation_control_shader_source,glw::GLchar const * const tessellation_evaluation_shader_source,glw::GLchar const * const vertex_shader_source,glw::GLchar const * const fragment_shader_source,glw::GLchar const * const * const transform_feedback_varyings,glw::GLsizei const transform_feedback_varyings_count,glw::GLenum const transform_feedback_varyings_mode,bool const do_not_detach,glw::GLint * linking_status)6712 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram(
6713     glw::Functions const &gl, tcu::TestLog &log, glw::GLchar const *const geometry_shader_source,
6714     glw::GLchar const *const tessellation_control_shader_source,
6715     glw::GLchar const *const tessellation_evaluation_shader_source, glw::GLchar const *const vertex_shader_source,
6716     glw::GLchar const *const fragment_shader_source, glw::GLchar const *const *const transform_feedback_varyings,
6717     glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode,
6718     bool const do_not_detach, glw::GLint *linking_status)
6719 {
6720     glw::GLuint program = 0;
6721 
6722     struct Shader
6723     {
6724         glw::GLchar const *const source;
6725         glw::GLenum const type;
6726         glw::GLuint id;
6727     } shader[] = {{geometry_shader_source, GL_GEOMETRY_SHADER, 0},
6728                   {tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0},
6729                   {tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0},
6730                   {vertex_shader_source, GL_VERTEX_SHADER, 0},
6731                   {fragment_shader_source, GL_FRAGMENT_SHADER, 0}};
6732 
6733     glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
6734 
6735     try
6736     {
6737         /* Create program. */
6738         program = gl.createProgram();
6739         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
6740 
6741         /* Shader compilation. */
6742 
6743         for (glw::GLuint i = 0; i < shader_count; ++i)
6744         {
6745             if (DE_NULL != shader[i].source)
6746             {
6747                 shader[i].id = gl.createShader(shader[i].type);
6748 
6749                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
6750 
6751                 gl.attachShader(program, shader[i].id);
6752 
6753                 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
6754 
6755                 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
6756 
6757                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
6758 
6759                 gl.compileShader(shader[i].id);
6760 
6761                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
6762 
6763                 glw::GLint status = GL_FALSE;
6764 
6765                 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
6766                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6767 
6768                 if (GL_FALSE == status)
6769                 {
6770                     glw::GLint log_size = 0;
6771                     gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
6772                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6773 
6774                     glw::GLchar *log_text = new glw::GLchar[log_size];
6775 
6776                     gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
6777 
6778                     log << tcu::TestLog::Message << "Shader compilation has failed.\n"
6779                         << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
6780                         << "Shader compilation error log:\n"
6781                         << log_text << "\n"
6782                         << "Shader source code:\n"
6783                         << shader[i].source << "\n"
6784                         << tcu::TestLog::EndMessage;
6785 
6786                     delete[] log_text;
6787 
6788                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
6789 
6790                     throw 0;
6791                 }
6792             }
6793         }
6794 
6795         /* Link. */
6796         if (transform_feedback_varyings_count)
6797         {
6798             gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings,
6799                                          transform_feedback_varyings_mode);
6800             GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6801         }
6802 
6803         gl.linkProgram(program);
6804 
6805         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6806 
6807         glw::GLint status = GL_FALSE;
6808 
6809         gl.getProgramiv(program, GL_LINK_STATUS, &status);
6810 
6811         if (DE_NULL != linking_status)
6812         {
6813             *linking_status = status;
6814         }
6815 
6816         if (GL_TRUE == status)
6817         {
6818             if (!do_not_detach)
6819             {
6820                 for (glw::GLuint i = 0; i < shader_count; ++i)
6821                 {
6822                     if (shader[i].id)
6823                     {
6824                         gl.detachShader(program, shader[i].id);
6825 
6826                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
6827                     }
6828                 }
6829             }
6830         }
6831         else
6832         {
6833             glw::GLint log_size = 0;
6834 
6835             gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
6836 
6837             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
6838 
6839             glw::GLchar *log_text = new glw::GLchar[log_size];
6840 
6841             gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
6842 
6843             log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
6844                 << log_text << "\n"
6845                 << tcu::TestLog::EndMessage;
6846 
6847             delete[] log_text;
6848 
6849             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
6850 
6851             throw 0;
6852         }
6853     }
6854     catch (...)
6855     {
6856         if (program)
6857         {
6858             gl.deleteProgram(program);
6859 
6860             program = 0;
6861         }
6862     }
6863 
6864     for (glw::GLuint i = 0; i < shader_count; ++i)
6865     {
6866         if (0 != shader[i].id)
6867         {
6868             gl.deleteShader(shader[i].id);
6869 
6870             shader[i].id = 0;
6871         }
6872     }
6873 
6874     return program;
6875 }
6876 
6877 /** @brief Substitute key with value within source code.
6878  *
6879  *  @param [in] source      Source code to be prerocessed.
6880  *  @param [in] key         Key to be substituted.
6881  *  @param [in] value       Value to be inserted.
6882  *
6883  *  @return Resulting string.
6884  */
preprocessCode(std::string source,std::string key,std::string value)6885 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value)
6886 {
6887     std::string destination = source;
6888 
6889     while (true)
6890     {
6891         /* Find token in source code. */
6892         size_t position = destination.find(key, 0);
6893 
6894         /* No more occurences of this key. */
6895         if (position == std::string::npos)
6896         {
6897             break;
6898         }
6899 
6900         /* Replace token with sub_code. */
6901         destination.replace(position, key.size(), value);
6902     }
6903 
6904     return destination;
6905 }
6906 
6907 /** @brief Convert an integer to a string.
6908  *
6909  *  @param [in] i       Integer to be converted.
6910  *
6911  *  @return String representing integer.
6912  */
itoa(glw::GLint i)6913 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i)
6914 {
6915     std::stringstream stream;
6916 
6917     stream << i;
6918 
6919     return stream.str();
6920 }
6921 
6922 /** @brief Convert an float to a string.
6923  *
6924  *  @param [in] f       Float to be converted.
6925  *
6926  *  @return String representing integer.
6927  */
ftoa(glw::GLfloat f)6928 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f)
6929 {
6930     std::stringstream stream;
6931 
6932     stream << f;
6933 
6934     return stream.str();
6935 }
6936