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 gl4cDirectStateAccessProgramPipelinesTests.cpp
27 * \brief Conformance tests for the Direct State Access feature functionality (Program Pipelines part).
28 */ /*-----------------------------------------------------------------------------------------------------------*/
29
30 /* Includes. */
31 #include "gl4cDirectStateAccessTests.hpp"
32
33 #include "deSharedPtr.hpp"
34
35 #include "gluContextInfo.hpp"
36 #include "gluDefs.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluStrUtil.hpp"
39
40 #include "tcuFuzzyImageCompare.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRenderTarget.hpp"
43 #include "tcuSurface.hpp"
44 #include "tcuTestLog.hpp"
45
46 #include "glw.h"
47 #include "glwFunctions.hpp"
48
49 namespace gl4cts
50 {
51 namespace DirectStateAccess
52 {
53 namespace ProgramPipelines
54 {
55 /******************************** Creation Test Implementation ********************************/
56
57 /** @brief Creation Test constructor.
58 *
59 * @param [in] context OpenGL context.
60 */
CreationTest(deqp::Context & context)61 CreationTest::CreationTest(deqp::Context &context)
62 : deqp::TestCase(context, "program_pipelines_creation", "Program Pipeline Objects Creation Test")
63 {
64 /* Intentionally left blank. */
65 }
66
67 /** @brief Iterate Creation Test cases.
68 *
69 * @return Iteration result.
70 */
iterate()71 tcu::TestNode::IterateResult CreationTest::iterate()
72 {
73 /* Shortcut for GL functionality */
74 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
75
76 /* Get context setup. */
77 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
78 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
79
80 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
81 {
82 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
83
84 return STOP;
85 }
86
87 /* Running tests. */
88 bool is_ok = true;
89 bool is_error = false;
90
91 /* Program pipeline objects */
92 static const glw::GLuint program_pipelines_count = 2;
93
94 glw::GLuint program_pipelines_legacy[program_pipelines_count] = {};
95 glw::GLuint program_pipelines_dsa[program_pipelines_count] = {};
96
97 try
98 {
99 /* Check legacy state creation. */
100 gl.genProgramPipelines(program_pipelines_count, program_pipelines_legacy);
101 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines have failed");
102
103 for (glw::GLuint i = 0; i < program_pipelines_count; ++i)
104 {
105 if (gl.isProgramPipeline(program_pipelines_legacy[i]))
106 {
107 is_ok = false;
108
109 /* Log. */
110 m_context.getTestContext().getLog()
111 << tcu::TestLog::Message
112 << "GenProgramPipelines has created default objects, but it should create only a names."
113 << tcu::TestLog::EndMessage;
114 }
115 }
116
117 /* Check direct state creation. */
118 gl.createProgramPipelines(program_pipelines_count, program_pipelines_dsa);
119 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines have failed");
120
121 for (glw::GLuint i = 0; i < program_pipelines_count; ++i)
122 {
123 if (!gl.isProgramPipeline(program_pipelines_dsa[i]))
124 {
125 is_ok = false;
126
127 /* Log. */
128 m_context.getTestContext().getLog()
129 << tcu::TestLog::Message << "CreateProgramPipelines has not created default objects."
130 << tcu::TestLog::EndMessage;
131 }
132 }
133 }
134 catch (...)
135 {
136 is_ok = false;
137 is_error = true;
138 }
139
140 /* Cleanup. */
141 for (glw::GLuint i = 0; i < program_pipelines_count; ++i)
142 {
143 if (program_pipelines_legacy[i])
144 {
145 gl.deleteProgramPipelines(1, &program_pipelines_legacy[i]);
146
147 program_pipelines_legacy[i] = 0;
148 }
149
150 if (program_pipelines_dsa[i])
151 {
152 gl.deleteProgramPipelines(1, &program_pipelines_dsa[i]);
153
154 program_pipelines_dsa[i] = 0;
155 }
156 }
157
158 /* Result's setup. */
159 if (is_ok)
160 {
161 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
162 }
163 else
164 {
165 if (is_error)
166 {
167 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
168 }
169 else
170 {
171 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
172 }
173 }
174
175 return STOP;
176 }
177
178 /******************************** Defaults Test Implementation ********************************/
179
180 /** @brief Defaults Test constructor.
181 *
182 * @param [in] context OpenGL context.
183 */
DefaultsTest(deqp::Context & context)184 DefaultsTest::DefaultsTest(deqp::Context &context)
185 : deqp::TestCase(context, "program_pipelines_defaults", "Program Pipelines Defaults Test")
186 , m_program_pipeline_dsa(0)
187 {
188 /* Intentionally left blank. */
189 }
190
191 /** @brief Iterate Defaults Test cases.
192 *
193 * @return Iteration result.
194 */
iterate()195 tcu::TestNode::IterateResult DefaultsTest::iterate()
196 {
197 /* Get context setup. */
198 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
199 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
200
201 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
202 {
203 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
204
205 return STOP;
206 }
207
208 /* Running tests. */
209 bool is_ok = true;
210 bool is_error = false;
211
212 try
213 {
214 prepare();
215
216 is_ok &= testProgramPipelineParameter(GL_ACTIVE_PROGRAM, 0);
217 is_ok &= testProgramPipelineParameter(GL_VERTEX_SHADER, 0);
218 is_ok &= testProgramPipelineParameter(GL_GEOMETRY_SHADER, 0);
219 is_ok &= testProgramPipelineParameter(GL_FRAGMENT_SHADER, 0);
220 is_ok &= testProgramPipelineParameter(GL_COMPUTE_SHADER, 0);
221 is_ok &= testProgramPipelineParameter(GL_TESS_CONTROL_SHADER, 0);
222 is_ok &= testProgramPipelineParameter(GL_TESS_EVALUATION_SHADER, 0);
223 is_ok &= testProgramPipelineParameter(GL_VALIDATE_STATUS, 0);
224 is_ok &= testProgramPipelineParameter(GL_INFO_LOG_LENGTH, 0);
225
226 is_ok &= testProgramPipelineInfoLog(DE_NULL);
227 }
228 catch (...)
229 {
230 is_ok = false;
231 is_error = true;
232 }
233
234 /* Clean up. */
235 clean();
236
237 /* Result's setup. */
238 if (is_ok)
239 {
240 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
241 }
242 else
243 {
244 if (is_error)
245 {
246 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
247 }
248 else
249 {
250 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
251 }
252 }
253
254 return STOP;
255 }
256
257 /** @brief Create Program Pipeline Objects.
258 *
259 * @note The function may throw if unexpected error has occured.
260 *
261 * @return True if test succeeded, false otherwise.
262 */
prepare()263 void DefaultsTest::prepare()
264 {
265 /* Shortcut for GL functionality */
266 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
267
268 /* Program Pipeline object creation */
269 gl.createProgramPipelines(1, &m_program_pipeline_dsa);
270 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines have failed");
271 }
272
273 /** @brief Test if Program Pipeline Parameter has value as expected.
274 *
275 * @note The function may throw if unexpected error has occured.
276 *
277 * @param [in] pname Parameter name enumeration. Must be one of
278 * GL_ACTIVE_PROGRAM, GL_VERTEX_SHADER, GL_TESS_CONTROL_SHADER,
279 * GL_TESS_EVALUATION_SHADER, GL_GEOMETRY_SHADER,
280 * GL_FRAGMENT_SHADER, GL_INFO_LOG_LENGTH.
281 * @param [in] expected_value Reference value to be compared.
282 *
283 * @return True if test succeeded, false otherwise.
284 */
testProgramPipelineParameter(glw::GLenum pname,glw::GLint expected_value)285 bool DefaultsTest::testProgramPipelineParameter(glw::GLenum pname, glw::GLint expected_value)
286 {
287 /* Shortcut for GL functionality */
288 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
289
290 /* Get data. */
291 glw::GLint value = -1;
292
293 gl.getProgramPipelineiv(m_program_pipeline_dsa, pname, &value);
294 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv have failed");
295
296 if (-1 == value)
297 {
298 m_context.getTestContext().getLog()
299 << tcu::TestLog::Message << "glGetProgramPipelineiv with parameter " << pname
300 << " has not returned anything and error has not been generated." << tcu::TestLog::EndMessage;
301
302 return false;
303 }
304 else
305 {
306 if (expected_value != value)
307 {
308 m_context.getTestContext().getLog()
309 << tcu::TestLog::Message << "glGetProgramPipelineiv with parameter " << pname << " has returned "
310 << value << ", however " << expected_value << " was expected." << tcu::TestLog::EndMessage;
311
312 return false;
313 }
314 }
315
316 return true;
317 }
318
319 /** @brief Test if Program Pipeline Parameter has value as expected.
320 *
321 * @note The function may throw if unexpected error has occured.
322 *
323 * @param [in] expected_value Reference value to be compared.
324 *
325 * @return True if test succeeded, false otherwise.
326 */
testProgramPipelineInfoLog(glw::GLchar * expected_value)327 bool DefaultsTest::testProgramPipelineInfoLog(glw::GLchar *expected_value)
328 {
329 /* Shortcut for GL functionality */
330 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
331
332 /* Comparison limit. */
333 static const glw::GLsizei max_log_size = 4096;
334
335 /* Storage for data. */
336 glw::GLchar log[max_log_size] = {0};
337
338 /* Storage fetched length. */
339 glw::GLsizei log_size = 0;
340
341 /* Fetch. */
342 gl.getProgramPipelineInfoLog(m_program_pipeline_dsa, max_log_size, &log_size, log);
343 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineInfoLog have failed");
344
345 /* Comparison. */
346 if (DE_NULL == expected_value)
347 {
348 if (0 != log_size)
349 {
350 m_context.getTestContext().getLog()
351 << tcu::TestLog::Message
352 << "glGetProgramPipelineInfoLog returned unexpectedly non-empty string: " << log << "."
353 << tcu::TestLog::EndMessage;
354
355 return false;
356 }
357
358 return true;
359 }
360
361 if (0 != strcmp(log, expected_value))
362 {
363 m_context.getTestContext().getLog()
364 << tcu::TestLog::Message << "glGetProgramPipelineInfoLog returned string: " << log
365 << ", but is not the same as expected: " << expected_value << "." << tcu::TestLog::EndMessage;
366
367 return false;
368 }
369
370 return true;
371 }
372
373 /** @brief Release GL objects.
374 */
clean()375 void DefaultsTest::clean()
376 {
377 /* Shortcut for GL functionality */
378 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
379
380 if (m_program_pipeline_dsa)
381 {
382 gl.deleteProgramPipelines(1, &m_program_pipeline_dsa);
383
384 m_program_pipeline_dsa = 0;
385 }
386 }
387
388 /******************************** Errors Test Implementation ********************************/
389
390 /** @brief Errors Test constructor.
391 *
392 * @param [in] context OpenGL context.
393 */
ErrorsTest(deqp::Context & context)394 ErrorsTest::ErrorsTest(deqp::Context &context)
395 : deqp::TestCase(context, "program_pipelines_errors", "Program Pipeline Objects Errors Test")
396 {
397 /* Intentionally left blank. */
398 }
399
400 /** @brief Iterate Errors Test cases.
401 *
402 * @return Iteration result.
403 */
iterate()404 tcu::TestNode::IterateResult ErrorsTest::iterate()
405 {
406 /* Shortcut for GL functionality */
407 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
408
409 /* Get context setup. */
410 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
411 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
412
413 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
414 {
415 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
416
417 return STOP;
418 }
419
420 /* Running tests. */
421 bool is_ok = true;
422 bool is_error = false;
423
424 glw::GLuint program_pipeline_dsa = 0;
425
426 try
427 {
428 /* Check direct state creation. */
429 gl.createProgramPipelines(-1, &program_pipeline_dsa);
430
431 glw::GLenum error = GL_NO_ERROR;
432
433 if (GL_INVALID_VALUE != (error = gl.getError()))
434 {
435 is_ok = false;
436
437 /* Log. */
438 m_context.getTestContext().getLog()
439 << tcu::TestLog::Message
440 << "CreateProgramPipelines has not generated INVALID_VALUE error when callded "
441 "with negative number of objects to be created."
442 << "Instead, " << glu::getErrorStr(error) << " error value was generated." << tcu::TestLog::EndMessage;
443 }
444 }
445 catch (...)
446 {
447 is_ok = false;
448 is_error = true;
449 }
450
451 /* Cleanup. */
452 if (program_pipeline_dsa)
453 {
454 gl.deleteProgramPipelines(1, &program_pipeline_dsa);
455
456 program_pipeline_dsa = 0;
457 }
458
459 /* Result's setup. */
460 if (is_ok)
461 {
462 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
463 }
464 else
465 {
466 if (is_error)
467 {
468 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
469 }
470 else
471 {
472 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
473 }
474 }
475
476 return STOP;
477 }
478
479 /******************************** Functional Test Implementation ********************************/
480
481 /** @brief Functional Test constructor.
482 *
483 * @param [in] context OpenGL context.
484 */
FunctionalTest(deqp::Context & context)485 FunctionalTest::FunctionalTest(deqp::Context &context)
486 : deqp::TestCase(context, "program_pipelines_functional", "Program Pipeline Objects Functional Test")
487 , m_fbo(0)
488 , m_rbo(0)
489 , m_vao(0)
490 , m_spo_v(0)
491 , m_spo_f(0)
492 , m_ppo(0)
493 {
494 /* Intentionally left blank. */
495 }
496
497 /** @brief Iterate Functional Test cases.
498 *
499 * @return Iteration result.
500 */
iterate()501 tcu::TestNode::IterateResult FunctionalTest::iterate()
502 {
503 /* Get context setup. */
504 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
505 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
506
507 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
508 {
509 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
510
511 return STOP;
512 }
513
514 /* Running tests. */
515 bool is_ok = true;
516 bool is_error = false;
517
518 try
519 {
520 prepareFramebuffer();
521 prepareVertexArrayObject();
522 prepareShaderPrograms();
523 preparePipeline();
524 draw();
525
526 is_ok &= checkFramebufferContent();
527 }
528 catch (...)
529 {
530 is_ok = false;
531 is_error = true;
532 }
533
534 /* Clean-up. */
535 clean();
536
537 /* Result's setup. */
538 if (is_ok)
539 {
540 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
541 }
542 else
543 {
544 if (is_error)
545 {
546 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
547 }
548 else
549 {
550 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
551 }
552 }
553
554 return STOP;
555 }
556
557 /** @brief Function prepares framebuffer with RGBA8 color attachment.
558 * Viewport is set up. Content of the framebuffer is cleared.
559 *
560 * @note The function may throw if unexpected error has occured.
561 */
prepareFramebuffer()562 void FunctionalTest::prepareFramebuffer()
563 {
564 /* Shortcut for GL functionality. */
565 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
566
567 /* Prepare framebuffer. */
568 gl.genFramebuffers(1, &m_fbo);
569 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
570
571 gl.genRenderbuffers(1, &m_rbo);
572 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
573
574 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
575 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
576
577 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
578 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
579
580 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */);
581 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
582
583 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
584 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
585
586 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
587 {
588 throw 0;
589 }
590
591 gl.viewport(0, 0, 1, 1);
592 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
593
594 /* Clear framebuffer's content. */
595 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
596 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
597
598 gl.clear(GL_COLOR_BUFFER_BIT);
599 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
600 }
601
602 /** @brief Function generate and bind empty vertex array object.
603 *
604 * @note The function may throw if unexpected error has occured.
605 */
prepareVertexArrayObject()606 void FunctionalTest::prepareVertexArrayObject()
607 {
608 /* Shortcut for GL functionality */
609 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
610
611 gl.genVertexArrays(1, &m_vao);
612 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
613
614 gl.bindVertexArray(m_vao);
615 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
616 }
617
618 /** @brief Function builds test's GLSL shader program.
619 * If succeded, the program will be set to be used.
620 *
621 * @note The function may throw if unexpected error has occured.
622 */
prepareShaderPrograms()623 void FunctionalTest::prepareShaderPrograms()
624 {
625 /* Shortcut for GL functionality. */
626 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
627
628 /* Log size limit. */
629 static const glw::GLsizei max_log_size = 4096;
630
631 /* Quick check. */
632 if (m_spo_v || m_spo_f)
633 {
634 throw 0;
635 }
636
637 /* Create Vertex Shader Program. */
638 m_spo_v = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, &s_vertex_shader);
639 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv call failed.");
640
641 glw::GLint status = GL_TRUE;
642
643 gl.validateProgram(m_spo_v);
644 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgram call failed.");
645
646 gl.getProgramiv(m_spo_v, GL_VALIDATE_STATUS, &status);
647 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
648
649 if (GL_FALSE == status)
650 {
651 /* Storage for data. */
652 glw::GLchar log[max_log_size] = {0};
653
654 /* Storage fetched length. */
655 glw::GLsizei log_size = 0;
656
657 gl.getProgramInfoLog(m_spo_v, max_log_size, &log_size, log);
658 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
659
660 m_context.getTestContext().getLog()
661 << tcu::TestLog::Message << "Vertex shader program building failed with log: " << log
662 << tcu::TestLog::EndMessage;
663
664 throw 0;
665 }
666
667 m_spo_f = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, &s_fragment_shader);
668 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv call failed.");
669
670 status = GL_TRUE;
671
672 gl.validateProgram(m_spo_f);
673 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgram call failed.");
674
675 gl.getProgramiv(m_spo_f, GL_VALIDATE_STATUS, &status);
676 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
677
678 if (GL_FALSE == status)
679 {
680 /* Storage for data. */
681 glw::GLchar log[max_log_size] = {0};
682
683 /* Storage fetched length. */
684 glw::GLsizei log_size = 0;
685
686 gl.getProgramInfoLog(m_spo_f, max_log_size, &log_size, log);
687 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
688
689 m_context.getTestContext().getLog()
690 << tcu::TestLog::Message << "Fragment shader program building failed with log: " << log
691 << tcu::TestLog::EndMessage;
692
693 throw 0;
694 }
695 }
696
697 /** @brief Function prepares program pipeline object.
698 *
699 * @note The function may throw if unexpected error has occured.
700 */
preparePipeline()701 void FunctionalTest::preparePipeline()
702 {
703 /* Shortcut for GL functionality. */
704 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
705
706 /* Quick check. */
707 if (m_ppo)
708 {
709 throw 0;
710 }
711
712 /* Create, use and set up program pipeline. */
713 gl.createProgramPipelines(1, &m_ppo);
714 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines call failed.");
715
716 gl.bindProgramPipeline(m_ppo);
717 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline call failed.");
718
719 gl.useProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_spo_v);
720 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages call failed.");
721
722 gl.useProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_spo_f);
723 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages call failed.");
724 }
725
726 /** @brief Function draws a quad.
727 *
728 * @note The function may throw if unexpected error has occured.
729 */
draw()730 void FunctionalTest::draw()
731 {
732 /* Shortcut for GL functionality. */
733 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
734
735 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
736 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
737 }
738
739 /** @brief Check content of the framebuffer and compare it with expected data.
740 *
741 * @note The function may throw if unexpected error has occured.
742 *
743 * @return True if succeeded, false otherwise.
744 */
checkFramebufferContent()745 bool FunctionalTest::checkFramebufferContent()
746 {
747 /* Shortcut for GL functionality. */
748 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
749
750 /* Fetch framebuffer data. */
751 glw::GLubyte pixel[4] = {0};
752
753 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
754 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
755
756 /* Comparison with expected values. */
757 if ((255 != pixel[0]) || (0 != pixel[1]) || (0 != pixel[2]) || (255 != pixel[3]))
758 {
759 m_context.getTestContext().getLog()
760 << tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", "
761 << (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3]
762 << ") is different than expected (255, 0, 0, 255)." << tcu::TestLog::EndMessage;
763
764 return false;
765 }
766
767 return true;
768 }
769
770 /** @brief Release all GL objects.
771 */
clean()772 void FunctionalTest::clean()
773 {
774 /* Shortcut for GL functionality. */
775 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
776
777 /* Release framebuffer. */
778 if (m_fbo)
779 {
780 gl.deleteFramebuffers(1, &m_fbo);
781
782 m_fbo = 0;
783 }
784
785 /* Release renderbuffer. */
786 if (m_rbo)
787 {
788 gl.deleteRenderbuffers(1, &m_rbo);
789
790 m_rbo = 0;
791 }
792
793 /* Release vertex array object. */
794 if (m_vao)
795 {
796 gl.deleteVertexArrays(1, &m_vao);
797
798 m_vao = 0;
799 }
800
801 /* Release shader programs. */
802 if (m_spo_v)
803 {
804 gl.deleteProgram(m_spo_v);
805
806 m_spo_v = 0;
807 }
808
809 if (m_spo_f)
810 {
811 gl.deleteProgram(m_spo_f);
812
813 m_spo_f = 0;
814 }
815
816 /* Release program pipelines. */
817 if (m_ppo)
818 {
819 gl.bindProgramPipeline(0);
820
821 gl.deleteProgramPipelines(1, &m_ppo);
822
823 m_ppo = 0;
824 }
825 }
826
827 /* Vertex shader source code. */
828 const glw::GLchar *FunctionalTest::s_vertex_shader = "#version 450\n"
829 "\n"
830 "out gl_PerVertex\n"
831 "{\n"
832 " vec4 gl_Position;\n"
833 " float gl_PointSize;\n"
834 " float gl_ClipDistance[];\n"
835 "};\n"
836 "\n"
837 "void main()\n"
838 "{\n"
839 " switch(gl_VertexID)\n"
840 " {\n"
841 " case 0:\n"
842 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
843 " break;\n"
844 " case 1:\n"
845 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
846 " break;\n"
847 " case 2:\n"
848 " gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
849 " break;\n"
850 " case 3:\n"
851 " gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
852 " break;\n"
853 " }\n"
854 "}\n";
855
856 /* Fragment shader source program. */
857 const glw::GLchar *FunctionalTest::s_fragment_shader = "#version 450\n"
858 "\n"
859 "out vec4 color;\n"
860 "\n"
861 "void main()\n"
862 "{\n"
863 " color = vec4(1.0, 0.0, 0.0, 1.0);\n"
864 "}\n";
865
866 } // namespace ProgramPipelines
867 } // namespace DirectStateAccess
868 } // namespace gl4cts
869