• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* Includes. */
25 #include "gl4cContextFlushControlTests.hpp"
26 #include "deClock.h"
27 #include "gluContextInfo.hpp"
28 #include "gluDefs.hpp"
29 #include "gluPlatform.hpp"
30 #include "gluRenderContext.hpp"
31 #include "gluStrUtil.hpp"
32 #include "tcuTestLog.hpp"
33 
34 #ifndef GL_CONTEXT_RELEASE_BEHAVIOR
35 #define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
36 #endif
37 
38 #ifndef GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH
39 #define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
40 #endif
41 
42 #define CONTEXT_FLUSH_CONTROL_FUNCTIONAL_TEST_DRAW_COUNT 1024
43 
44 /******************************** Test Group Implementation       ********************************/
45 
46 /** @brief Context Flush Control tests group constructor.
47  *
48  *  @param [in] context     OpenGL context.
49  */
Tests(deqp::Context & context)50 gl4cts::ContextFlushControl::Tests::Tests(deqp::Context& context)
51 	: TestCaseGroup(context, "context_flush_control", "Context Flush Control Test Suite")
52 {
53 	/* Intentionally left blank */
54 }
55 
56 /** @brief Context Flush Control tests initializer. */
init()57 void gl4cts::ContextFlushControl::Tests::init()
58 {
59 	addChild(new gl4cts::ContextFlushControl::CoverageTest(m_context));
60 	addChild(new gl4cts::ContextFlushControl::FunctionalTest(m_context));
61 }
62 
63 /******************************** Coverage Tests Implementation   ********************************/
64 
65 /** @brief API coverage tests constructor.
66  *
67  *  @param [in] context     OpenGL context.
68  */
CoverageTest(deqp::Context & context)69 gl4cts::ContextFlushControl::CoverageTest::CoverageTest(deqp::Context& context)
70 	: deqp::TestCase(context, "coverage", "Context Flush Control API Coverage Test")
71 {
72 	/* Intentionally left blank. */
73 }
74 
75 /** @brief Iterate API coverage tests.
76  *
77  *  @return Iteration result.
78  */
iterate()79 tcu::TestNode::IterateResult gl4cts::ContextFlushControl::CoverageTest::iterate()
80 {
81 	/* OpenGL support query. */
82 	bool is_at_least_gl_44 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)));
83 	bool is_khr_context_flush_control = m_context.getContextInfo().isExtensionSupported("GL_KHR_context_flush_control");
84 
85 	/* Running tests. */
86 	bool is_ok = true;
87 
88 	/* This test should only be executed if we're running a GL4.4 context or related extension is available */
89 	if (is_at_least_gl_44 || is_khr_context_flush_control)
90 	{
91 		/* Test deafult context which shall use implicit flush when swapped. */
92 		is_ok = is_ok && testQuery(m_context.getRenderContext(), GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH);
93 
94 		/* Create context which shall swap without flush. */
95 		glu::RenderContext* no_flush_context = createNoFlushContext();
96 
97 		/* Proceed only if such context has been created. */
98 		if (DE_NULL != no_flush_context)
99 		{
100 			/* Test no-flush context. */
101 			no_flush_context->makeCurrent();
102 
103 			is_ok = is_ok && testQuery(*no_flush_context, GL_NONE);
104 
105 			/* Release no-flush context. */
106 			m_context.getRenderContext().makeCurrent();
107 
108 			delete no_flush_context;
109 		}
110 	}
111 
112 	/* Result's setup. */
113 	if (is_ok)
114 	{
115 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
116 	}
117 	else
118 	{
119 		m_context.getTestContext().getLog() << tcu::TestLog::Message
120 											<< "The Context Flush Control Coverage test have failed."
121 											<< tcu::TestLog::EndMessage;
122 
123 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
124 	}
125 
126 	return STOP;
127 }
128 
129 /** @brief Test getter coverage for the given GL context.
130  *
131  *  This function tests following GL query functions:
132  *      glGetIntegerv,
133  *      glGetFloatv,
134  *      glGetBooleanv,
135  *      glGetDoublev,
136  *      glGetInteger64v.
137  *  Expected value is clamped to <0, 1> range flor glGetBooleanv.
138  *  For reference see KHR_context_flush_control extension.
139  *
140  *  @param [in] context         Render context to be used with the test.
141  *  @param [in] expected_value  Expected value to be returned by glGet*v function.
142  *
143  *  @return True if all tested functions returned expected value, false otherwise.
144  */
testQuery(glu::RenderContext & context,glw::GLenum expected_value)145 bool gl4cts::ContextFlushControl::CoverageTest::testQuery(glu::RenderContext& context, glw::GLenum expected_value)
146 {
147 	/* Shortcut for GL functionality. */
148 	const glw::Functions& gl = context.getFunctions();
149 
150 	/* Variables for query. */
151 	glw::GLint	 value_i   = -1;
152 	glw::GLint64   value_i64 = -1;
153 	glw::GLfloat   value_f   = -1;
154 	glw::GLdouble  value_d   = -1;
155 	glw::GLboolean value_b   = -1;
156 
157 	glw::GLboolean expected_bool_value = (glw::GLboolean)de::min((glw::GLint)expected_value, (glw::GLint)1);
158 
159 	/* Test. */
160 	try
161 	{
162 		/* Fetch data. */
163 		gl.getIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &value_i);
164 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
165 
166 		gl.getInteger64v(GL_CONTEXT_RELEASE_BEHAVIOR, &value_i64);
167 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v call failed.");
168 
169 		gl.getFloatv(GL_CONTEXT_RELEASE_BEHAVIOR, &value_f);
170 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv call failed.");
171 
172 		gl.getDoublev(GL_CONTEXT_RELEASE_BEHAVIOR, &value_d);
173 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev call failed.");
174 
175 		gl.getBooleanv(GL_CONTEXT_RELEASE_BEHAVIOR, &value_b);
176 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv call failed.");
177 
178 		/* Check result. */
179 		if ((expected_value == value_i) && (expected_value == value_i64) && (expected_value == value_f) &&
180 			(expected_value == value_d) && (expected_bool_value == value_b))
181 		{
182 			return true;
183 		}
184 	}
185 	catch (...)
186 	{
187 		return false;
188 	}
189 
190 	return false;
191 }
192 
193 /** @brief Create render context with CONTEXT_RELEASE_BEHAVIOR set as NONE.
194  *
195  *  @return Render context pointer if creation succeeded, DE_NULL otherwise.
196  */
createNoFlushContext()197 glu::RenderContext* gl4cts::ContextFlushControl::CoverageTest::createNoFlushContext()
198 {
199 	/* Get current platform.*/
200 	glu::Platform& platform = dynamic_cast<glu::Platform&>(m_context.getTestContext().getPlatform());
201 
202 	/* Context to be returned (NULL if failed). */
203 	glu::RenderContext* context = DE_NULL;
204 
205 	/* Get context related attributes needed to create no-flush context. */
206 	const int* attributes = platform.getContextFlushControlContextAttributes();
207 
208 	/* Proceed only if it is possible to make no-flush context. */
209 	if (DE_NULL != attributes)
210 	{
211 		glu::ContextType renderContextType = m_context.getRenderContext().getType();
212 
213 		/* Create no-flush context. */
214 		context = platform.createRenderContext(renderContextType, m_context.getTestContext().getCommandLine(),
215 											   0 /* shared_context */, attributes);
216 	}
217 
218 	return context;
219 }
220 
221 /******************************** Functional Test Implementation   ********************************/
222 
223 /** @brief Functional test constructor.
224  *
225  *  @param [in] context     OpenGL context.
226  */
FunctionalTest(deqp::Context & context)227 gl4cts::ContextFlushControl::FunctionalTest::FunctionalTest(deqp::Context& context)
228 	: deqp::TestCase(context, "functional", "Context Flush Control Functional Test")
229 {
230 	/* Intentionally left blank. */
231 }
232 
233 /** @brief Iterate Functional test cases.
234  *
235  *  @return Iteration result.
236  */
iterate()237 tcu::TestNode::IterateResult gl4cts::ContextFlushControl::FunctionalTest::iterate()
238 {
239 	/* Shortcut for GL functionality. */
240 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
241 
242 	/* Get current platform.*/
243 	glu::Platform& platform = dynamic_cast<glu::Platform&>(m_context.getTestContext().getPlatform());
244 
245 	/* OpenGL support query. */
246 	bool is_at_least_gl_44 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)));
247 	bool is_khr_context_flush_control = m_context.getContextInfo().isExtensionSupported("GL_KHR_context_flush_control");
248 
249 	/* Running tests. */
250 	bool is_ok	= true;
251 	bool is_error = false;
252 
253 	/* This test should only be executed if we're running a GL4.4 context or related extension is available */
254 	try
255 	{
256 		if ((is_at_least_gl_44 || is_khr_context_flush_control) &&
257 			(DE_NULL != platform.getContextFlushControlContextAttributes()))
258 		{
259 			glw::GLfloat test_time_no_flush = testTime(false);
260 			glw::GLfloat test_time_flush	= testTime(true);
261 
262 			is_ok = (test_time_no_flush < test_time_flush);
263 		}
264 		else
265 		{
266 			is_error = true;
267 		}
268 	}
269 	catch (...)
270 	{
271 		is_ok	= false;
272 		is_error = true;
273 	}
274 
275 	/* Result's setup. */
276 	if (is_ok)
277 	{
278 		if (is_error)
279 		{
280 			m_context.getTestContext().getLog() << tcu::TestLog::Message
281 												<< "The context does not support No-Flush behavior."
282 												<< tcu::TestLog::EndMessage;
283 
284 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported.");
285 		}
286 		else
287 		{
288 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
289 		}
290 	}
291 	else
292 	{
293 		if (is_error)
294 		{
295 			m_context.getTestContext().getLog()
296 				<< tcu::TestLog::Message << "Internal error has occured during Context Flush Control Functional test."
297 				<< tcu::TestLog::EndMessage;
298 
299 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Test error.");
300 		}
301 		else
302 		{
303 			m_context.getTestContext().getLog()
304 				<< tcu::TestLog::Message << "The running time of no-flush context switches has been slower than flush "
305 											"behavior context switching case. "
306 				<< "This is not expected from quality implementation." << tcu::TestLog::EndMessage;
307 
308 			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Quality warning.");
309 		}
310 	}
311 
312 	return STOP;
313 }
314 
315 /** @brief This function measures time of loop consisting of draw and switch context,
316  *         which shall or shall not flush on switch.
317  *
318  *  The test is based on KHR_context_flush_control extension overview, that the main reason
319  *  for no-flush context is to increase the performance of the implementation.
320  *
321  *  @param [in] shall_flush_on_release      Flag indicating that contexts shall flush when switched.
322  *
323  *  @return Run-time of the test loop.
324  */
testTime(bool shall_flush_on_release)325 glw::GLfloat gl4cts::ContextFlushControl::FunctionalTest::testTime(bool shall_flush_on_release)
326 {
327 	/* Create two contexts to be switched during test. */
328 	DrawSetup draw_context_setup[2] = { DrawSetup(m_context, shall_flush_on_release),
329 										DrawSetup(m_context, shall_flush_on_release) };
330 
331 	/* Check starting time. */
332 	deUint64 start_time = deGetMicroseconds();
333 
334 	/* Loop over draw-switch context. */
335 	for (glw::GLuint i = 0; i < 1024; ++i)
336 	{
337 		draw_context_setup[i % 2].makeCurrent();
338 		draw_context_setup[i % 2].draw();
339 	}
340 
341 	/* Check end time. */
342 	deUint64 end_time = deGetMicroseconds();
343 
344 	/* Return resulting run-time. */
345 	return (glw::GLfloat)(end_time - start_time);
346 }
347 
348 /** @brief Make context current.
349  */
makeCurrent()350 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::makeCurrent()
351 {
352 	/* Switch context to this. */
353 	m_context->makeCurrent();
354 }
355 
356 /** @brief Use program and draw full screen quad.
357  */
draw()358 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::draw()
359 {
360 	/* Shortcut for GL functionality. */
361 	const glw::Functions& gl = m_context->getFunctions();
362 
363 	/* Use GLSL program. */
364 	gl.useProgram(m_po);
365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
366 
367 	/* Clear. */
368 	gl.clear(GL_COLOR_BUFFER_BIT);
369 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
370 
371 	/* Draw. */
372 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4 /* quad */);
373 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
374 }
375 
376 /** @brief Draw Setup object constructor.
377  *
378  *  The constructor will throw on error.
379  *
380  *  @param [in] test_context                Test context for platform, logging and switching to default context on destruction.
381  *  @param [in] shall_flush_on_release      Flag indicating that contexts shall flush when switched.
382  */
DrawSetup(deqp::Context & test_context,bool shall_flush_on_release)383 gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::DrawSetup(deqp::Context& test_context,
384 																  bool			 shall_flush_on_release)
385 	: m_test_context(test_context), m_fbo(0), m_rbo(0), m_vao(0), m_po(0)
386 {
387 	createContext(shall_flush_on_release);
388 
389 	if (DE_NULL == m_context)
390 	{
391 		throw 0;
392 	}
393 
394 	createGeometry();
395 
396 	if (0 == m_vao)
397 	{
398 		throw 0;
399 	}
400 
401 	createView();
402 
403 	if ((0 == m_fbo) || (0 == m_rbo))
404 	{
405 		throw 0;
406 	}
407 
408 	createProgram();
409 
410 	if (0 == m_po)
411 	{
412 		throw 0;
413 	}
414 }
415 
416 /** @brief Draw Setup object destructor.
417  */
~DrawSetup()418 gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::~DrawSetup()
419 {
420 	if (m_context)
421 	{
422 		/* Make sure context is current. */
423 		makeCurrent();
424 
425 		/* Shortcut for GL functionality. */
426 		const glw::Functions& gl = m_context->getFunctions();
427 
428 		/* Cleanup. */
429 		if (m_vao)
430 		{
431 			gl.deleteVertexArrays(1, &m_vao);
432 
433 			m_vao = 0;
434 		}
435 
436 		if (m_fbo)
437 		{
438 			gl.deleteFramebuffers(1, &m_fbo);
439 
440 			m_fbo = 0;
441 		}
442 
443 		if (m_rbo)
444 		{
445 			gl.deleteRenderbuffers(1, &m_rbo);
446 
447 			m_rbo = 0;
448 		}
449 
450 		if (m_po)
451 		{
452 			gl.deleteProgram(m_po);
453 
454 			m_po = 0;
455 		}
456 
457 		/* Make default context current. */
458 		m_test_context.getRenderContext().makeCurrent();
459 
460 		/* Cleanup context. */
461 		delete m_context;
462 	}
463 }
464 
465 /** @brief Create render context with CONTEXT_RELEASE_BEHAVIOR set to NONE or CONTEXT_RELEASE_BEHAVIOR_FLUSH.
466  *
467  *  @return Render context pointer if creation succeeded, DE_NULL otherwise.
468  */
createContext(bool shall_flush_on_release)469 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::createContext(bool shall_flush_on_release)
470 {
471 	/* Get current platform.*/
472 	glu::Platform& platform = dynamic_cast<glu::Platform&>(m_test_context.getTestContext().getPlatform());
473 
474 	/* Get context related attributes needed to create no-flush context. */
475 	const int* attributes = DE_NULL;
476 
477 	if (!shall_flush_on_release)
478 	{
479 		attributes = platform.getContextFlushControlContextAttributes();
480 	}
481 
482 	/* Proceed only if it is possible to make no-flush context. */
483 	glu::ContextType renderContextType = m_test_context.getRenderContext().getType();
484 
485 	/* Create no-flush context. */
486 	m_context = platform.createRenderContext(renderContextType, m_test_context.getTestContext().getCommandLine(),
487 											 0 /* shared_context */, attributes);
488 }
489 
490 /** @brief Create RGBA8 framebuffer with attached renderbuffer.
491  */
createView()492 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::createView()
493 {
494 	/* Shortcut for GL functionality. */
495 	const glw::Functions& gl = m_context->getFunctions();
496 
497 	/* Prepare framebuffer. */
498 	gl.clearColor(0.f, 0.f, 0.f, 1.f);
499 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
500 
501 	gl.genFramebuffers(1, &m_fbo);
502 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
503 
504 	gl.genRenderbuffers(1, &m_rbo);
505 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
506 
507 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
508 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
509 
510 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
511 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
512 
513 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
514 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
515 
516 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
517 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
518 
519 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
520 	{
521 		throw 0;
522 	}
523 
524 	gl.viewport(0, 0, s_view_size, s_view_size);
525 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
526 }
527 
528 /** @brief Create and bind empty vertex array object.
529  */
createGeometry()530 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::createGeometry()
531 {
532 	/* Shortcut for GL functionality. */
533 	const glw::Functions& gl = m_context->getFunctions();
534 
535 	/* Create and bind vertex array. */
536 	gl.genVertexArrays(1, &m_vao);
537 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
538 
539 	gl.bindVertexArray(m_vao);
540 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
541 }
542 
543 /** @brief Compile and link shader program.
544  */
createProgram()545 void gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::createProgram()
546 {
547 	/* Shortcut for GL functionality. */
548 	const glw::Functions& gl = m_context->getFunctions();
549 
550 	struct Shader
551 	{
552 		glw::GLchar const* const source;
553 		glw::GLenum const		 type;
554 		glw::GLuint				 id;
555 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
556 
557 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
558 
559 	try
560 	{
561 		/* Create program. */
562 		m_po = gl.createProgram();
563 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
564 
565 		/* Shader compilation. */
566 
567 		for (glw::GLuint i = 0; i < shader_count; ++i)
568 		{
569 			if (DE_NULL != shader[i].source)
570 			{
571 				shader[i].id = gl.createShader(shader[i].type);
572 
573 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
574 
575 				gl.attachShader(m_po, shader[i].id);
576 
577 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
578 
579 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
580 
581 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
582 
583 				gl.compileShader(shader[i].id);
584 
585 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
586 
587 				glw::GLint status = GL_FALSE;
588 
589 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
590 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
591 
592 				if (GL_FALSE == status)
593 				{
594 					throw 0;
595 				}
596 			}
597 		}
598 
599 		/* Link. */
600 		gl.linkProgram(m_po);
601 
602 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
603 
604 		glw::GLint status = GL_FALSE;
605 
606 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
607 
608 		if (GL_TRUE == status)
609 		{
610 			for (glw::GLuint i = 0; i < shader_count; ++i)
611 			{
612 				if (shader[i].id)
613 				{
614 					gl.detachShader(m_po, shader[i].id);
615 
616 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
617 				}
618 			}
619 		}
620 		else
621 		{
622 			throw 0;
623 		}
624 	}
625 	catch (...)
626 	{
627 		if (m_po)
628 		{
629 			gl.deleteProgram(m_po);
630 
631 			m_po = 0;
632 		}
633 	}
634 
635 	for (glw::GLuint i = 0; i < shader_count; ++i)
636 	{
637 		if (0 != shader[i].id)
638 		{
639 			gl.deleteShader(shader[i].id);
640 
641 			shader[i].id = 0;
642 		}
643 	}
644 }
645 
646 const glw::GLuint gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::s_view_size = 256;
647 
648 const glw::GLchar gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::s_vertex_shader[] =
649 	"#version 130\n"
650 	"\n"
651 	"void main()\n"
652 	"{\n"
653 	"    switch(gl_VertexID % 4)\n"
654 	"    {\n"
655 	"    case 0:\n"
656 	"       gl_Position = vec4(-1.0, -1.0,  0.0,  1.0);\n"
657 	"       break;\n"
658 	"    case 1:\n"
659 	"       gl_Position = vec4( 1.0, -1.0,  0.0,  1.0);\n"
660 	"       break;\n"
661 	"    case 2:\n"
662 	"       gl_Position = vec4(-1.0,  1.0,  0.0,  1.0);\n"
663 	"       break;\n"
664 	"    case 3:\n"
665 	"       gl_Position = vec4( 1.0,  1.0,  0.0,  1.0);\n"
666 	"       break;\n"
667 	"    }\n"
668 	"}\n";
669 
670 const glw::GLchar gl4cts::ContextFlushControl::FunctionalTest::DrawSetup::s_fragment_shader[] =
671 	"#version 130\n"
672 	"\n"
673 	"out vec4 pixel;\n"
674 	"\n"
675 	"void main()\n"
676 	"{\n"
677 	"    pixel = vec4(1.0);\n"
678 	"}\n";
679