• 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 /**
25  */ /*!
26  * \file  gl4cDirectStateAccessXFBTests.cpp
27  * \brief Conformance tests for the Direct State Access feature functionality (Transform Feedbeck access 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 Samplers
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, "samplers_creation", "Sampler 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 	/* Samplers objects */
92 	static const glw::GLuint samplers_count = 2;
93 
94 	glw::GLuint samplers_dsa[samplers_count] = {};
95 
96 	try
97 	{
98 		/* Check direct state creation. */
99 		gl.createSamplers(samplers_count, samplers_dsa);
100 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateSamplers have failed");
101 
102 		for (glw::GLuint i = 0; i < samplers_count; ++i)
103 		{
104 			if (!gl.isSampler(samplers_dsa[i]))
105 			{
106 				is_ok = false;
107 
108 				/* Log. */
109 				m_context.getTestContext().getLog() << tcu::TestLog::Message
110 													<< "CreateSamplers has not created defualt objects."
111 													<< tcu::TestLog::EndMessage;
112 			}
113 		}
114 	}
115 	catch (...)
116 	{
117 		is_ok	= false;
118 		is_error = true;
119 	}
120 
121 	/* Cleanup. */
122 	for (glw::GLuint i = 0; i < samplers_count; ++i)
123 	{
124 		if (samplers_dsa[i])
125 		{
126 			gl.deleteSamplers(1, &samplers_dsa[i]);
127 
128 			samplers_dsa[i] = 0;
129 		}
130 	}
131 
132 	/* Result's setup. */
133 	if (is_ok)
134 	{
135 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
136 	}
137 	else
138 	{
139 		if (is_error)
140 		{
141 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
142 		}
143 		else
144 		{
145 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
146 		}
147 	}
148 
149 	return STOP;
150 }
151 
152 /******************************** Defaults Test Implementation   ********************************/
153 
154 /** @brief Defaults Test constructor.
155  *
156  *  @param [in] context     OpenGL context.
157  */
DefaultsTest(deqp::Context & context)158 DefaultsTest::DefaultsTest(deqp::Context& context)
159 	: deqp::TestCase(context, "samplers_defaults", "Samplers Defaults Test"), m_sampler_dsa(0)
160 {
161 	/* Intentionally left blank. */
162 }
163 
164 /** @brief Iterate Defaults Test cases.
165  *
166  *  @return Iteration result.
167  */
iterate()168 tcu::TestNode::IterateResult DefaultsTest::iterate()
169 {
170 	/* Get context setup. */
171 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
172 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
173 
174 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
175 	{
176 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
177 
178 		return STOP;
179 	}
180 
181 	/* Running tests. */
182 	bool is_ok	= true;
183 	bool is_error = false;
184 
185 	try
186 	{
187 		prepare();
188 
189 		glw::GLfloat expected_vector[4] = { 0.0, 0.0, 0.0, 0.0 };
190 
191 		is_ok &= testSamplerFloatVectorParameter(GL_TEXTURE_BORDER_COLOR, expected_vector);
192 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
193 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_COMPARE_MODE, GL_NONE);
194 		is_ok &= testSamplerFloatParameter(GL_TEXTURE_LOD_BIAS, 0.0);
195 		is_ok &= testSamplerFloatParameter(GL_TEXTURE_MAX_LOD, 1000);
196 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
197 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
198 		is_ok &= testSamplerFloatParameter(GL_TEXTURE_MIN_LOD, -1000);
199 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
200 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
201 		is_ok &= testSamplerIntegerParameter(GL_TEXTURE_WRAP_R, GL_REPEAT);
202 	}
203 	catch (...)
204 	{
205 		is_ok	= false;
206 		is_error = true;
207 	}
208 
209 	/* Clean up. */
210 	clean();
211 
212 	/* Result's setup. */
213 	if (is_ok)
214 	{
215 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
216 	}
217 	else
218 	{
219 		if (is_error)
220 		{
221 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
222 		}
223 		else
224 		{
225 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
226 		}
227 	}
228 
229 	return STOP;
230 }
231 
232 /** @brief Create Sampler Objects.
233  *
234  *  @note The function may throw if unexpected error has occured.
235  *
236  *  @return True if test succeeded, false otherwise.
237  */
prepare()238 void DefaultsTest::prepare()
239 {
240 	/* Shortcut for GL functionality */
241 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
242 
243 	/* Sampler object creation */
244 	gl.createSamplers(1, &m_sampler_dsa);
245 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
246 }
247 
248 /** @brief Test Sampler Integer Parameter.
249  *
250  *  @note The function may throw if unexpected error has occured.
251  *
252  *  @return True if test succeeded, false otherwise.
253  */
testSamplerIntegerParameter(glw::GLenum pname,glw::GLint expected_value)254 bool DefaultsTest::testSamplerIntegerParameter(glw::GLenum pname, glw::GLint expected_value)
255 {
256 	/* Shortcut for GL functionality */
257 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
258 
259 	/* Get data. */
260 	glw::GLint value = -1;
261 
262 	gl.getSamplerParameteriv(m_sampler_dsa, pname, &value);
263 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameteriv have failed");
264 
265 	if (-1 == value)
266 	{
267 		m_context.getTestContext().getLog()
268 			<< tcu::TestLog::Message << "glGetSamplerParameteriv with parameter " << glu::getTextureParameterName(pname)
269 			<< " has not returned anything and error has not been generated." << tcu::TestLog::EndMessage;
270 
271 		return false;
272 	}
273 	else
274 	{
275 		if (expected_value != value)
276 		{
277 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameteriv with parameter "
278 												<< glu::getTextureParameterName(pname) << " has returned " << value
279 												<< ", however " << expected_value << " was expected."
280 												<< tcu::TestLog::EndMessage;
281 
282 			return false;
283 		}
284 	}
285 
286 	return true;
287 }
288 
289 /** @brief Test Sampler Float Parameter.
290  *
291  *  @note The function may throw if unexpected error has occured.
292  *
293  *  @return True if test succeeded, false otherwise.
294  */
testSamplerFloatParameter(glw::GLenum pname,glw::GLfloat expected_value)295 bool DefaultsTest::testSamplerFloatParameter(glw::GLenum pname, glw::GLfloat expected_value)
296 {
297 	/* Shortcut for GL functionality */
298 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
299 
300 	/* Get data. */
301 	glw::GLfloat value = -1.0;
302 
303 	gl.getSamplerParameterfv(m_sampler_dsa, pname, &value);
304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameteriv have failed");
305 
306 	if (de::abs(expected_value - value) > 0.015625f /* Precision */)
307 	{
308 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameterfv with parameter "
309 											<< glu::getTextureParameterName(pname) << " has returned " << value
310 											<< ", however " << expected_value << " was expected."
311 											<< tcu::TestLog::EndMessage;
312 
313 		return false;
314 	}
315 
316 	return true;
317 }
318 
319 /** @brief Test Sampler Float Parameter.
320  *
321  *  @note The function may throw if unexpected error has occured.
322  *
323  *  @return True if test succeeded, false otherwise.
324  */
testSamplerFloatVectorParameter(glw::GLenum pname,glw::GLfloat expected_value[4])325 bool DefaultsTest::testSamplerFloatVectorParameter(glw::GLenum pname, glw::GLfloat expected_value[4])
326 {
327 	/* Shortcut for GL functionality */
328 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
329 
330 	/* Get data. */
331 	glw::GLfloat value[4] = { -1.0, -1.0, -1.0, -1.0 };
332 
333 	gl.getSamplerParameterfv(m_sampler_dsa, pname, value);
334 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSamplerParameterfv have failed");
335 
336 	if ((de::abs(expected_value[0] - value[0]) > 0.015625f /* Precision */) ||
337 		(de::abs(expected_value[1] - value[1]) > 0.015625f /* Precision */) ||
338 		(de::abs(expected_value[2] - value[2]) > 0.015625f /* Precision */) ||
339 		(de::abs(expected_value[3] - value[3]) > 0.015625f /* Precision */))
340 	{
341 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetSamplerParameterfv with parameter "
342 											<< glu::getTextureParameterName(pname) << " has returned [" << value[0]
343 											<< ", " << value[1] << ", " << value[2] << ", " << value[3] << "], however "
344 											<< expected_value << " was expected." << tcu::TestLog::EndMessage;
345 
346 		return false;
347 	}
348 
349 	return true;
350 }
351 
352 /** @brief Release GL objects.
353  */
clean()354 void DefaultsTest::clean()
355 {
356 	/* Shortcut for GL functionality */
357 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
358 
359 	if (m_sampler_dsa)
360 	{
361 		gl.deleteSamplers(1, &m_sampler_dsa);
362 
363 		m_sampler_dsa = 0;
364 	}
365 }
366 
367 /******************************** Errors Test Implementation   ********************************/
368 
369 /** @brief Errors Test constructor.
370  *
371  *  @param [in] context     OpenGL context.
372  */
ErrorsTest(deqp::Context & context)373 ErrorsTest::ErrorsTest(deqp::Context& context) : deqp::TestCase(context, "samplers_errors", "Samplers Errors Test")
374 {
375 	/* Intentionally left blank. */
376 }
377 
378 /** @brief Iterate Errors Test cases.
379  *
380  *  @return Iteration result.
381  */
iterate()382 tcu::TestNode::IterateResult ErrorsTest::iterate()
383 {
384 	/* Shortcut for GL functionality */
385 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
386 
387 	/* Get context setup. */
388 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
389 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
390 
391 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
392 	{
393 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
394 
395 		return STOP;
396 	}
397 
398 	/* Running tests. */
399 	bool is_ok	= true;
400 	bool is_error = false;
401 
402 	glw::GLuint sampler_dsa = 0;
403 
404 	try
405 	{
406 		/* Check direct state creation. */
407 		gl.createSamplers(-1, &sampler_dsa);
408 
409 		glw::GLenum error = GL_NO_ERROR;
410 
411 		if (GL_INVALID_VALUE != (error = gl.getError()))
412 		{
413 			is_ok = false;
414 
415 			/* Log. */
416 			m_context.getTestContext().getLog()
417 				<< tcu::TestLog::Message << "CreateSamplers has not generated INVALID_VALUE error when callded with "
418 											"negative number of samplers to be created."
419 				<< "Instead, " << glu::getErrorStr(error) << " error value was generated." << tcu::TestLog::EndMessage;
420 		}
421 	}
422 	catch (...)
423 	{
424 		is_ok	= false;
425 		is_error = true;
426 	}
427 
428 	/* Cleanup. */
429 	if (sampler_dsa)
430 	{
431 		gl.deleteSamplers(1, &sampler_dsa);
432 
433 		sampler_dsa = 0;
434 	}
435 
436 	/* Result's setup. */
437 	if (is_ok)
438 	{
439 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
440 	}
441 	else
442 	{
443 		if (is_error)
444 		{
445 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
446 		}
447 		else
448 		{
449 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
450 		}
451 	}
452 
453 	return STOP;
454 }
455 
456 /******************************** Functional Test Implementation   ********************************/
457 
458 /** @brief Functional Test constructor.
459  *
460  *  @param [in] context     OpenGL context.
461  */
FunctionalTest(deqp::Context & context)462 FunctionalTest::FunctionalTest(deqp::Context& context)
463 	: deqp::TestCase(context, "samplers_functional", "Samplers Functional Test")
464 	, m_fbo(0)
465 	, m_rbo(0)
466 	, m_vao(0)
467 	, m_to(0)
468 	, m_so(0)
469 	, m_po(0)
470 {
471 	/* Intentionally left blank. */
472 }
473 
474 /** @brief Iterate Functional Test cases.
475  *
476  *  @return Iteration result.
477  */
iterate()478 tcu::TestNode::IterateResult FunctionalTest::iterate()
479 {
480 	/* Get context setup. */
481 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
482 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
483 
484 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
485 	{
486 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
487 
488 		return STOP;
489 	}
490 
491 	/* Running tests. */
492 	bool is_ok	= true;
493 	bool is_error = false;
494 
495 	try
496 	{
497 		prepareFramebuffer();
498 		prepareVertexArrayObject();
499 		prepareProgram();
500 		prepareTexture();
501 		prepareSampler();
502 		draw();
503 
504 		is_ok &= checkFramebufferContent();
505 	}
506 	catch (...)
507 	{
508 		is_ok	= false;
509 		is_error = true;
510 	}
511 
512 	/* Clean-up. */
513 	clean();
514 
515 	/* Result's setup. */
516 	if (is_ok)
517 	{
518 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
519 	}
520 	else
521 	{
522 		if (is_error)
523 		{
524 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
525 		}
526 		else
527 		{
528 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
529 		}
530 	}
531 
532 	return STOP;
533 }
534 
535 /** @brief Function prepares framebuffer with RGBA8 color attachment.
536  *         Viewport is set up. Content of the framebuffer is cleared.
537  *
538  *  @note The function may throw if unexpected error has occured.
539  */
prepareFramebuffer()540 void FunctionalTest::prepareFramebuffer()
541 {
542 	/* Shortcut for GL functionality. */
543 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
544 
545 	/* Prepare framebuffer. */
546 	gl.genFramebuffers(1, &m_fbo);
547 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
548 
549 	gl.genRenderbuffers(1, &m_rbo);
550 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
551 
552 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
553 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
554 
555 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
556 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
557 
558 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */);
559 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
560 
561 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
562 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
563 
564 	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
565 	{
566 		throw 0;
567 	}
568 
569 	gl.viewport(0, 0, 1, 1);
570 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
571 
572 	/* Clear framebuffer's content. */
573 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
574 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
575 
576 	gl.clear(GL_COLOR_BUFFER_BIT);
577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
578 }
579 
580 /** @brief Function generate and bind empty vertex array object.
581  *
582  *  @note The function may throw if unexpected error has occured.
583  */
prepareVertexArrayObject()584 void FunctionalTest::prepareVertexArrayObject()
585 {
586 	/* Shortcut for GL functionality */
587 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
588 
589 	gl.genVertexArrays(1, &m_vao);
590 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
591 
592 	gl.bindVertexArray(m_vao);
593 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
594 }
595 
596 /** @brief Function builds test's GLSL program.
597  *         If succeded, the program will be set to be used.
598  *
599  *  @note The function may throw if unexpected error has occured.
600  */
prepareProgram()601 void FunctionalTest::prepareProgram()
602 {
603 	/* Shortcut for GL functionality */
604 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
605 
606 	struct Shader
607 	{
608 		glw::GLchar const* const source;
609 		glw::GLenum const		 type;
610 		glw::GLuint				 id;
611 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
612 
613 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
614 
615 	try
616 	{
617 		/* Create program. */
618 		m_po = gl.createProgram();
619 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
620 
621 		/* Shader compilation. */
622 
623 		for (glw::GLuint i = 0; i < shader_count; ++i)
624 		{
625 			if (DE_NULL != shader[i].source)
626 			{
627 				shader[i].id = gl.createShader(shader[i].type);
628 
629 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
630 
631 				gl.attachShader(m_po, shader[i].id);
632 
633 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
634 
635 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
636 
637 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
638 
639 				gl.compileShader(shader[i].id);
640 
641 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
642 
643 				glw::GLint status = GL_FALSE;
644 
645 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
646 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
647 
648 				if (GL_FALSE == status)
649 				{
650 					glw::GLint log_size = 0;
651 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
652 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
653 
654 					glw::GLchar* log_text = new glw::GLchar[log_size];
655 
656 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
657 
658 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
659 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
660 														<< "\n"
661 														<< "Shader compilation error log:\n"
662 														<< log_text << "\n"
663 														<< "Shader source code:\n"
664 														<< shader[i].source << "\n"
665 														<< tcu::TestLog::EndMessage;
666 
667 					delete[] log_text;
668 
669 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
670 
671 					throw 0;
672 				}
673 			}
674 		}
675 
676 		/* Link. */
677 		gl.linkProgram(m_po);
678 
679 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
680 
681 		glw::GLint status = GL_FALSE;
682 
683 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
684 
685 		if (GL_TRUE == status)
686 		{
687 			for (glw::GLuint i = 0; i < shader_count; ++i)
688 			{
689 				if (shader[i].id)
690 				{
691 					gl.detachShader(m_po, shader[i].id);
692 
693 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
694 				}
695 			}
696 		}
697 		else
698 		{
699 			glw::GLint log_size = 0;
700 
701 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
702 
703 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
704 
705 			glw::GLchar* log_text = new glw::GLchar[log_size];
706 
707 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
708 
709 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
710 												<< log_text << "\n"
711 												<< tcu::TestLog::EndMessage;
712 
713 			delete[] log_text;
714 
715 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
716 
717 			throw 0;
718 		}
719 	}
720 	catch (...)
721 	{
722 		if (m_po)
723 		{
724 			gl.deleteProgram(m_po);
725 
726 			m_po = 0;
727 		}
728 	}
729 
730 	for (glw::GLuint i = 0; i < shader_count; ++i)
731 	{
732 		if (0 != shader[i].id)
733 		{
734 			gl.deleteShader(shader[i].id);
735 
736 			shader[i].id = 0;
737 		}
738 	}
739 
740 	if (m_po)
741 	{
742 		gl.useProgram(m_po);
743 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
744 	}
745 
746 	if (0 == m_po)
747 	{
748 		throw 0;
749 	}
750 }
751 
752 /** @brief Function prepares texture object with test's data.
753  *
754  *  @note The function may throw if unexpected error has occured.
755  */
prepareTexture()756 void FunctionalTest::prepareTexture()
757 {
758 	/* Shortcut for GL functionality */
759 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
760 
761 	gl.activeTexture(GL_TEXTURE0);
762 	GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture call failed.");
763 
764 	/* Texture creation and binding. */
765 	gl.genTextures(1, &m_to);
766 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures call failed.");
767 
768 	gl.bindTexture(GL_TEXTURE_2D, m_to);
769 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture call failed.");
770 
771 	/* Uploading texture. */
772 
773 	gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, s_texture_data);
774 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D call failed.");
775 
776 	/* Setup fragment shader's sampler. */
777 	glw::GLint location = 0;
778 
779 	gl.getUniformLocation(m_po, s_uniform_sampler);
780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
781 
782 	gl.uniform1i(location, 0);
783 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i call failed.");
784 }
785 
786 /** @brief Function prepares sampler with test setup and binds it to unit 0.
787  *
788  *  @note The function may throw if unexpected error has occured.
789  */
prepareSampler()790 void FunctionalTest::prepareSampler()
791 {
792 	/* Shortcut for GL functionality. */
793 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
794 
795 	/* Sampler creation and setup. */
796 	gl.createSamplers(1, &m_so);
797 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
798 
799 	gl.bindSampler(0, m_so);
800 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindSampler have failed");
801 
802 	gl.samplerParameteri(m_so, GL_TEXTURE_WRAP_S, GL_REPEAT);
803 	gl.samplerParameteri(m_so, GL_TEXTURE_WRAP_T, GL_REPEAT);
804 	gl.samplerParameteri(m_so, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
805 	gl.samplerParameteri(m_so, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
806 	GLU_EXPECT_NO_ERROR(gl.getError(), "glSamplerParameteri have failed");
807 }
808 
809 /** @brief Function draws a quad.
810  *
811  *  @note The function may throw if unexpected error has occured.
812  */
draw()813 void FunctionalTest::draw()
814 {
815 	/* Shortcut for GL functionality. */
816 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
817 
818 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed");
820 }
821 
822 /** @brief Check content of the framebuffer and compare it with expected data.
823  *
824  *  @note The function may throw if unexpected error has occured.
825  *
826  *  @return True if succeeded, false otherwise.
827  */
checkFramebufferContent()828 bool FunctionalTest::checkFramebufferContent()
829 {
830 	/* Shortcut for GL functionality. */
831 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
832 
833 	/* Fetch framebuffer data. */
834 	glw::GLubyte pixel[4] = { 0 };
835 
836 	gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
838 
839 	/* Comparison with expected values. */
840 	if ((s_texture_data[0] != pixel[0]) || (s_texture_data[1] != pixel[1]) || (s_texture_data[2] != pixel[2]) ||
841 		(s_texture_data[3] != pixel[3]))
842 	{
843 		m_context.getTestContext().getLog()
844 			<< tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", "
845 			<< (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3]
846 			<< ") is different than expected (" << (unsigned int)s_texture_data[0] << ", "
847 			<< (unsigned int)s_texture_data[1] << ", " << (unsigned int)s_texture_data[2] << ", "
848 			<< (unsigned int)s_texture_data[3] << ")." << tcu::TestLog::EndMessage;
849 
850 		return false;
851 	}
852 
853 	return true;
854 }
855 
856 /** @brief Release all GL objects.
857  */
clean()858 void FunctionalTest::clean()
859 {
860 	/* Shortcut for GL functionality. */
861 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
862 
863 	/* Release framebuffer. */
864 	if (m_fbo)
865 	{
866 		gl.deleteFramebuffers(1, &m_fbo);
867 
868 		m_fbo = 0;
869 	}
870 
871 	/* Release renderbuffer. */
872 	if (m_rbo)
873 	{
874 		gl.deleteRenderbuffers(1, &m_rbo);
875 
876 		m_rbo = 0;
877 	}
878 
879 	/* Release vertex array object. */
880 	if (m_vao)
881 	{
882 		gl.deleteVertexArrays(1, &m_vao);
883 
884 		m_vao = 0;
885 	}
886 
887 	/* Release texture. */
888 	if (m_to)
889 	{
890 		gl.deleteTextures(1, &m_to);
891 
892 		m_to = 0;
893 	}
894 
895 	/* Release sampler. */
896 	if (m_so)
897 	{
898 		gl.deleteSamplers(1, &m_so);
899 
900 		m_so = 0;
901 	}
902 
903 	/* Release GLSL program. */
904 	if (m_po)
905 	{
906 		gl.useProgram(0);
907 
908 		gl.deleteProgram(m_po);
909 
910 		m_po = 0;
911 	}
912 }
913 
914 /* Vertex shader source code. */
915 const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 330\n"
916 													  "\n"
917 													  "void main()\n"
918 													  "{\n"
919 													  "    switch(gl_VertexID)\n"
920 													  "    {\n"
921 													  "        case 0:\n"
922 													  "            gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
923 													  "            break;\n"
924 													  "        case 1:\n"
925 													  "            gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
926 													  "            break;\n"
927 													  "        case 2:\n"
928 													  "            gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
929 													  "            break;\n"
930 													  "        case 3:\n"
931 													  "            gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
932 													  "            break;\n"
933 													  "    }\n"
934 													  "}\n";
935 
936 /* Fragment shader source program. */
937 const glw::GLchar FunctionalTest::s_fragment_shader[] =
938 	"#version 330\n"
939 	"\n"
940 	"uniform sampler2D texture_sampler;\n"
941 	"\n"
942 	"out vec4 color;\n"
943 	"\n"
944 	"void main()\n"
945 	"{\n"
946 	"    color = texture(texture_sampler, vec2(0.33333, 0.33333));\n"
947 	"}\n";
948 
949 /* Name of texture sampler uniform. */
950 const glw::GLchar FunctionalTest::s_uniform_sampler[] = "texture_sampler";
951 
952 /* Test's texture data. */
953 const glw::GLubyte FunctionalTest::s_texture_data[] = {
954 	0xFF, 0x00, 0x00, 0xFF, /* RED  */
955 	0x00, 0xFF, 0x00, 0xFF, /* GREEN  */
956 	0x00, 0x00, 0xFF, 0xFF, /* BLUE */
957 	0xFF, 0xFF, 0x00, 0xFF  /* YELLOW */
958 };
959 
960 } /* Samplers namespace. */
961 } /* DirectStateAccess namespace. */
962 } /* gl4cts namespace. */
963