es31fPrimitiveBoundingBoxTests.cpp revision d8b452a7533c195b1328918bb696a819542ff044
11f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry/*-------------------------------------------------------------------------
21f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * drawElements Quality Program OpenGL ES 3.1 Module
31f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * -------------------------------------------------
41f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *
51f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * Copyright 2015 The Android Open Source Project
61f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *
71f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * Licensed under the Apache License, Version 2.0 (the "License");
81f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * you may not use this file except in compliance with the License.
91f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * You may obtain a copy of the License at
101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *
111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *      http://www.apache.org/licenses/LICENSE-2.0
121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *
131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * Unless required by applicable law or agreed to in writing, software
141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * distributed under the License is distributed on an "AS IS" BASIS,
151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * See the License for the specific language governing permissions and
171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * limitations under the License.
181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *
191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *//*!
201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * \file
211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry * \brief Primitive bounding box tests.
221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry *//*--------------------------------------------------------------------*/
231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "es31fPrimitiveBoundingBoxTests.hpp"
251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuTestLog.hpp"
271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuRenderTarget.hpp"
281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuSurface.hpp"
291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuTextureUtil.hpp"
301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuVectorUtil.hpp"
311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluCallLogWrapper.hpp"
321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluContextInfo.hpp"
331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluRenderContext.hpp"
341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluStrUtil.hpp"
351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluShaderProgram.hpp"
361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluObjectWrapper.hpp"
371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluPixelTransfer.hpp"
381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glsStateQueryUtil.hpp"
391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glwFunctions.hpp"
401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glwEnums.hpp"
411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deRandom.hpp"
421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deUniquePtr.hpp"
431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deStringUtil.hpp"
441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <vector>
461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <sstream>
471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <algorithm>
481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace deqp
501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace gles31
521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace Functional
541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace
561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace StateQueryUtil = ::deqp::gls::StateQueryUtil;
591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct BoundingBox
611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4 min;
631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4 max;
641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	/*--------------------------------------------------------------------*//*!
661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 * Get component by index of a 8-component vector constructed by
671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 * concatenating 4-component min and max vectors.
681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 *//*--------------------------------------------------------------------*/
691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	float&			getComponentAccess	(int ndx);
701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float&	getComponentAccess	(int ndx) const;
711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryfloat& BoundingBox::getComponentAccess (int ndx)
741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(ndx >= 0 && ndx < 8);
761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (ndx < 4)
771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return min[ndx];
781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return max[ndx-4];
801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryconst float& BoundingBox::getComponentAccess (int ndx) const
831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return const_cast<BoundingBox*>(this)->getComponentAccess(ndx);
851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct ProjectedBBox
881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec3	min;
901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec3	max;
911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic ProjectedBBox projectBoundingBox (const BoundingBox& bbox)
941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float		wMin	= de::max(0.0f, bbox.min.w()); // clamp to w=0 as extension requires
961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float		wMax	= de::max(0.0f, bbox.max.w());
971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	ProjectedBBox	retVal;
981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	retVal.min = tcu::min(bbox.min.swizzle(0, 1, 2) / wMin,
1001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						  bbox.min.swizzle(0, 1, 2) / wMax);
1011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	retVal.max = tcu::max(bbox.max.swizzle(0, 1, 2) / wMin,
1021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						  bbox.max.swizzle(0, 1, 2) / wMax);
1031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return retVal;
1041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic tcu::IVec4 getViewportBoundingBoxArea (const ProjectedBBox& bbox, const tcu::IVec2& viewportSize, float size = 0.0f)
1071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4	vertexBox;
1091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4	pixelBox;
1101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1117a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.x() = (bbox.min.x() * 0.5f + 0.5f) * (float)viewportSize.x();
1127a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.y() = (bbox.min.y() * 0.5f + 0.5f) * (float)viewportSize.y();
1137a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.z() = (bbox.max.x() * 0.5f + 0.5f) * (float)viewportSize.x();
1147a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.w() = (bbox.max.y() * 0.5f + 0.5f) * (float)viewportSize.y();
1151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.x() = deFloorFloatToInt32(vertexBox.x() - size/2.0f);
1171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.y() = deFloorFloatToInt32(vertexBox.y() - size/2.0f);
1181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.z() = deCeilFloatToInt32(vertexBox.z() + size/2.0f);
1191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.w() = deCeilFloatToInt32(vertexBox.w() + size/2.0f);
1201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return pixelBox;
1211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass InitialValueCase : public TestCase
1251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
1271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					InitialValueCase	(Context& context, const char* name, const char* desc);
1281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			init				(void);
1301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult	iterate				(void);
1311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
1321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryInitialValueCase::InitialValueCase (Context& context, const char* name, const char* desc)
1341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase(context, name, desc)
1351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid InitialValueCase::init (void)
1391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
1411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
1421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryInitialValueCase::IterateResult InitialValueCase::iterate (void)
1451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat[8]>	state;
1471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::CallLogWrapper											gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
1481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableLogging(true);
1501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
1521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
1531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Querying GL_PRIMITIVE_BOUNDING_BOX_EXT, expecting (-1, -1, -1, 1) (1, 1, 1, 1)"
1541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
1551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
1571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
1581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!state.verifyValidity(m_testCtx))
1601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return STOP;
1611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
1631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
1641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Got " << tcu::formatArray(&state[0], &state[8])
1651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
1661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((state[0] != -1.0f) || (state[1] != -1.0f) || (state[2] != -1.0f) || (state[3] != 1.0f) ||
1681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		(state[4] !=  1.0f) || (state[5] !=  1.0f) || (state[6] !=  1.0f) || (state[7] != 1.0f))
1691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
1701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
1711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
1721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Error, unexpected value"
1731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
1741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid initial value");
1761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
1771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
1781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
1811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass QueryCase : public TestCase
1841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
1861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum QueryMethod
1871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
1881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_FLOAT = 0,
1891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_BOOLEAN,
1901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_INT,
1911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_INT64,
1921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_LAST
1941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
1951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						QueryCase	(Context& context, const char* name, const char* desc, QueryMethod method);
1971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
1991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				init		(void);
2001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult		iterate		(void);
2011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				verifyState	(glu::CallLogWrapper& gl, const BoundingBox& bbox) const;
2031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const QueryMethod	m_method;
2051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
2061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryQueryCase::QueryCase (Context& context, const char* name, const char* desc, QueryMethod method)
2081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase	(context, name, desc)
2091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_method	(method)
2101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(method < QUERY_LAST);
2121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid QueryCase::init (void)
2151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
2171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
2181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryQueryCase::IterateResult QueryCase::iterate (void)
2211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const BoundingBox fixedCases[] =
2231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f), tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f) },
2251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4(-0.0f, -0.0f, -0.0f, -0.0f), tcu::Vec4( 0.0f,  0.0f,  0.0f, -0.0f) },
2261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f), tcu::Vec4( 1.0f,  1.0f,  1.0f, -1.0f) },
2271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 2.0f,  2.0f,  2.0f,  2.0f), tcu::Vec4( 1.5f,  1.5f,  1.5f,  1.0f) },
2281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f), tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f) },
2291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 1.0f,  1.0f,  1.0f,  0.3f), tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.2f) },
2301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
2311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int					numRandomCases	= 9;
2331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::CallLogWrapper			gl				(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random					rnd				(0xDE3210);
2351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<BoundingBox>	cases;
2361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	cases.insert(cases.begin(), DE_ARRAY_BEGIN(fixedCases), DE_ARRAY_END(fixedCases));
2381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < numRandomCases; ++ndx)
2391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BoundingBox	boundingBox;
2411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// parameter evaluation order is not guaranteed, cannot just do "max = (rand(), rand(), ...)
2431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int coordNdx = 0; coordNdx < 8; ++coordNdx)
2441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			boundingBox.getComponentAccess(coordNdx) = rnd.getFloat(-4.0f, 4.0f);
2451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cases.push_back(boundingBox);
2471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
2481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableLogging(true);
2501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int caseNdx = 0; caseNdx < (int)cases.size(); ++caseNdx)
2531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(caseNdx+1));
25530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		const BoundingBox&			boundingBox	= cases[caseNdx];
2561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
257485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.glPrimitiveBoundingBox(boundingBox.min.x(), boundingBox.min.y(), boundingBox.min.z(), boundingBox.min.w(),
258485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								  boundingBox.max.x(), boundingBox.max.y(), boundingBox.max.z(), boundingBox.max.w());
2591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!verifyState(gl, boundingBox))
2611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected query result");
2621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
2631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
2651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool QueryCase::verifyState (glu::CallLogWrapper& gl, const BoundingBox& bbox) const
2681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	switch (m_method)
2701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_FLOAT:
2721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
2731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat[8]>	state;
2741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool														error = false;
2751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
2771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
2781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
2801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
2811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
2831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
2841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetFloatv returned " << tcu::formatArray(&state[0], &state[8])
2851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
2861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
2881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != bbox.getComponentAccess(ndx))
2891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
2901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
2921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
2931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				m_testCtx.getLog()
2941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
2951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "Error, unexpected value\n"
2961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "Expected ["
2971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< bbox.min.x() << ", " << bbox.min.y() << ", " << bbox.min.z() << ", " << bbox.min.w() << ", "
2981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< bbox.max.x() << ", " << bbox.max.y() << ", " << bbox.max.z() << ", " << bbox.max.w() << "]"
2991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
3021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
3031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
3041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_INT:
3061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
3071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[8]>	state;
3081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool														error = false;
3091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetIntegerv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
3111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
3121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
3141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
3171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
3181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetIntegerv returned " << tcu::formatArray(&state[0], &state[8])
3191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
3221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint>(bbox.getComponentAccess(ndx)) &&
3231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint>(bbox.getComponentAccess(ndx)))
3241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
3251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
3271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
3281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
3291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
3311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
3321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
3341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
3351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint roundDown	= StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint>(bbox.getComponentAccess(ndx));
3361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint roundUp	= StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint>(bbox.getComponentAccess(ndx));
3371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
3391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
3401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (roundDown == roundUp)
3421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << roundDown;
3431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					else
3441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << "{" << roundDown << ", " << roundUp << "}";
3451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
3461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
3481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
3491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
3511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
3521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
3531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_INT64:
3551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
3561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64[8]>	state;
3571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool																error = false;
3581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetInteger64v(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
3601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
3611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
3631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
3661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
3671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetInteger64v returned " << tcu::formatArray(&state[0], &state[8])
3681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
3711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(bbox.getComponentAccess(ndx)) &&
3721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(bbox.getComponentAccess(ndx)))
3731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
3741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
3761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
3771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
3781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
3801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
3811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
3831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
3841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint64 roundDown	= StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(bbox.getComponentAccess(ndx));
3851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint64 roundUp		= StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(bbox.getComponentAccess(ndx));
3861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
3881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
3891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (roundDown == roundUp)
3911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << roundDown;
3921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					else
3931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << "{" << roundDown << ", " << roundUp << "}";
3941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
3951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
3971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
3981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
4001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
4021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_BOOLEAN:
4041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean[8]>	state;
4061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool															error = false;
4071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetBooleanv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
4091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
4101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
4121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
4131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
4151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
4161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetBooleanv returned ["
4171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::getBooleanStr(state[0]) << ", " << glu::getBooleanStr(state[1]) << ", " << glu::getBooleanStr(state[2]) << ", " << glu::getBooleanStr(state[3]) << ", "
4181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::getBooleanStr(state[4]) << ", " << glu::getBooleanStr(state[5]) << ", " << glu::getBooleanStr(state[6]) << ", " << glu::getBooleanStr(state[7]) << "]\n"
4191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
4201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
4221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != ((bbox.getComponentAccess(ndx) != 0.0f) ? (GL_TRUE) : (GL_FALSE)))
4231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
4241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
4261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
4271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
4281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
4301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
4311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
4331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
4341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
4351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
4361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					builder << ((bbox.getComponentAccess(ndx) != 0.0f) ? ("GL_TRUE") : ("GL_FALSE"));
4381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
4391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
4411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
4421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
4431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
4441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
4461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		default:
4481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(false);
4491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
4511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
4521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass BBoxRenderCase : public TestCase
4541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
4551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
4561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
4571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
4581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_RENDERTARGET_DEFAULT	= 1u << 0, //!< render to default renderbuffer
4591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_RENDERTARGET_FBO		= 1u << 1, //!< render to framebuffer object
4601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_EQUAL			= 1u << 2, //!< set tight primitive bounding box
4621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_LARGER		= 1u << 3, //!< set padded primitive bounding box
4631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_SMALLER		= 1u << 4, //!< set too small primitive bounding box
4641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_TESSELLATION			= 1u << 5, //!< use tessellation shader
4661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_GEOMETRY				= 1u << 6, //!< use geometry shader
4671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_SET_BBOX_STATE			= 1u << 7, //!< set primitive bounding box using global state
4691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_SET_BBOX_OUTPUT		= 1u << 8, //!< set primitive bounding box using tessellation output
4701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_PER_PRIMITIVE_BBOX		= 1u << 9, //!< set primitive bounding per primitive
4711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAGBIT_USER_BIT			= 10u //!< bits N and and up are reserved for subclasses
4731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
4741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									BBoxRenderCase					(Context& context, const char* name, const char* description, int numIterations, deUint32 flags);
4761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~BBoxRenderCase					(void);
4771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprotected:
4791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum RenderTarget
4801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
4811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDERTARGET_DEFAULT,
4821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDERTARGET_FBO,
4831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
4841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxSize
4851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
4861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_EQUAL,
4871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_LARGER,
4881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_SMALLER,
4891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
4901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
4921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
4931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDER_TARGET_MIN_SIZE	= 256,
4941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FBO_SIZE				= 512,
4951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		MIN_VIEWPORT_SIZE		= 256,
4961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		MAX_VIEWPORT_SIZE		= 512,
4971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
4981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_STATIC_ASSERT(MIN_VIEWPORT_SIZE <= RENDER_TARGET_MIN_SIZE);
4991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
5011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_POS_VEC_NDX		= 0,
5031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_COL_VEC_NDX		= 1,
5041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_NUM_ATTRIB_VECS	= 2,
5051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum AABBRoundDirection
5081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ROUND_INWARDS = 0,
5101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ROUND_OUTWARDS
5111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct IterationConfig
5141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2	viewportPos;
5161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2	viewportSize;
5171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	patternPos;		//!< in NDC
5181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	patternSize;	//!< in NDC
5191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BoundingBox	bbox;
5201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					init							(void);
5231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					deinit							(void);
5241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
5251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genVertexSource					(void) const = 0;
5271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genFragmentSource				(void) const = 0;
5281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genTessellationControlSource	(void) const = 0;
5291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genTessellationEvaluationSource	(void) const = 0;
5301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genGeometrySource				(void) const = 0;
5311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual IterationConfig			generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const = 0;
5331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					getAttributeData				(std::vector<tcu::Vec4>& data) const = 0;
5341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					renderTestPattern				(const IterationConfig& config) = 0;
5351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					verifyRenderResult				(const IterationConfig& config) = 0;
5361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig					generateRandomConfig			(int seed, const tcu::IVec2& renderTargetSize) const;
5381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4						getViewportPatternArea			(const tcu::Vec2& patternPos, const tcu::Vec2& patternSize, const tcu::IVec2& viewportSize, AABBRoundDirection roundDir) const;
5391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							setupRender						(const IterationConfig& config);
5411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum ShaderFunction
5431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_MIRROR_X,
5451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_MIRROR_Y,
5461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_INSIDE_BBOX,
5471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char*						genShaderFunction				(ShaderFunction func) const;
5501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_renderTarget;
5521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxSize					m_bboxSize;
5531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_hasTessellationStage;
5541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_hasGeometryStage;
5551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_useGlobalState;
5561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_calcPerPrimitiveBBox;
5571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_numIterations;
5581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
5601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
5611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_fbo;
5621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
5641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<IterationConfig>	m_iterationConfigs;
5651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_iteration;
5661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
5671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::BBoxRenderCase (Context& context, const char* name, const char* description, int numIterations, deUint32 flags)
5691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase					(context, name, description)
5701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_renderTarget			((flags & FLAG_RENDERTARGET_DEFAULT) ? (RENDERTARGET_DEFAULT) : (RENDERTARGET_FBO))
5711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_bboxSize				((flags & FLAG_BBOXSIZE_EQUAL) ? (BBOXSIZE_EQUAL) : (flags & FLAG_BBOXSIZE_SMALLER) ? (BBOXSIZE_SMALLER) : (BBOXSIZE_LARGER))
5721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_hasTessellationStage	((flags & FLAG_TESSELLATION) != 0)
5731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_hasGeometryStage		((flags & FLAG_GEOMETRY) != 0)
5741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_useGlobalState			((flags & FLAG_SET_BBOX_STATE) != 0)
5751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_calcPerPrimitiveBBox	((flags & FLAG_PER_PRIMITIVE_BBOX) != 0)
5761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numIterations			(numIterations)
5771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_iteration				(0)
5781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
5791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// validate flags
5801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT((((m_renderTarget == RENDERTARGET_DEFAULT)	?	(FLAG_RENDERTARGET_DEFAULT)	: (0)) |
5811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_renderTarget == RENDERTARGET_FBO)		?	(FLAG_RENDERTARGET_FBO)		: (0)) |
5821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_EQUAL)				?	(FLAG_BBOXSIZE_EQUAL)		: (0)) |
5831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_LARGER)				?	(FLAG_BBOXSIZE_LARGER)		: (0)) |
5841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_SMALLER)			?	(FLAG_BBOXSIZE_SMALLER)		: (0)) |
5851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_hasTessellationStage)					?	(FLAG_TESSELLATION)			: (0)) |
5861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_hasGeometryStage)						?	(FLAG_GEOMETRY)				: (0)) |
5871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_useGlobalState)							?	(FLAG_SET_BBOX_STATE)		: (0)) |
5881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((!m_useGlobalState)							?	(FLAG_SET_BBOX_OUTPUT)		: (0)) |
5891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_calcPerPrimitiveBBox)					?	(FLAG_PER_PRIMITIVE_BBOX)	: (0))) == (flags & ((1u << FLAGBIT_USER_BIT) - 1)));
5901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_useGlobalState || m_hasTessellationStage); // using non-global state requires tessellation
5921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
5941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(!m_useGlobalState); // per-primitive test requires per-primitive (non-global) state
5961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_bboxSize == BBOXSIZE_EQUAL); // smaller is hard to verify, larger not interesting
5971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
5981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
5991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::~BBoxRenderCase (void)
6011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
6021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
6031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
6041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::init (void)
6061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
6071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
6081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		renderTargetSize	= (m_renderTarget == RENDERTARGET_DEFAULT) ?
6091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													(tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) :
6101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													(tcu::IVec2(FBO_SIZE, FBO_SIZE));
6111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// requirements
6131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
6141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
6151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
6161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
6171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
6181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
6191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_renderTarget == RENDERTARGET_DEFAULT && (renderTargetSize.x() < RENDER_TARGET_MIN_SIZE || renderTargetSize.y() < RENDER_TARGET_MIN_SIZE))
6201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError(std::string() + "Test requires " + de::toString<int>(RENDER_TARGET_MIN_SIZE) + "x" + de::toString<int>(RENDER_TARGET_MIN_SIZE) + " default framebuffer");
6211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// log case specifics
6231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
6241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
6251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting primitive bounding box "
6261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_calcPerPrimitiveBBox)         ? ("to exactly cover each generated primitive")
6271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_EQUAL)   ? ("to exactly cover rendered grid")
6281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_LARGER)  ? ("to cover the grid and include some padding")
6291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_SMALLER) ? ("to cover only a subset of the grid")
6301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (DE_NULL))
6311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
6321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering with vertex"
6331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_hasTessellationStage) ? ("-tessellation{ctrl,eval}") : (""))
6341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_hasGeometryStage) ? ("-geometry") : (""))
6351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "-fragment program.\n"
6361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
6371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_useGlobalState) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
6381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
6391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying rendering results are valid within the bounding box."
6401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
6411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
6431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
6451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::ProgramSources sources;
6461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		sources << glu::VertexSource(genVertexSource());
6471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		sources << glu::FragmentSource(genFragmentSource());
6481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage)
6501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			sources << glu::TessellationControlSource(genTessellationControlSource())
6511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::TessellationEvaluationSource(genTessellationEvaluationSource());
6521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
6531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			sources << glu::GeometrySource(genGeometrySource());
6541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), sources));
6561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "build program");
6571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
6591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::ScopedLogSection section(m_testCtx.getLog(), "ShaderProgram", "Shader program");
6601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
6611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
6621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
6641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
6651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
6661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_renderTarget == RENDERTARGET_FBO)
6681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
6691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::Texture colorAttachment(m_context.getRenderContext());
6701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindTexture(GL_TEXTURE_2D, *colorAttachment);
6721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, FBO_SIZE, FBO_SIZE);
6731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen tex");
6741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_fbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
6761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);
6771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *colorAttachment, 0);
6781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "attach");
6791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// unbind to prevent texture name deletion from removing it from current fbo attachments
6811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
6821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
6831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
6851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<tcu::Vec4> data;
6861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		getAttributeData(data);
6881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
6901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
6911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, (int)(data.size() * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
6921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "create vbo");
6931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
6941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Iterations
6961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int iterationNdx = 0; iterationNdx < m_numIterations; ++iterationNdx)
6971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_iterationConfigs.push_back(generateConfig(iterationNdx, renderTargetSize));
6981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
6991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::deinit (void)
7011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
7031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
7041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_fbo.clear();
7051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::IterateResult BBoxRenderCase::iterate (void)
7081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::ScopedLogSection	section		(m_testCtx.getLog(),
7101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											 std::string() + "Iteration" + de::toString((int)m_iteration),
7111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											 std::string() + "Iteration " + de::toString((int)m_iteration+1) + "/" + de::toString((int)m_iterationConfigs.size()));
7121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const IterationConfig&		config		= m_iterationConfigs[m_iteration];
7131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// default
7151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_iteration == 0)
7161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	renderTestPattern(config);
7191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	verifyRenderResult(config);
7201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (++m_iteration < (int)m_iterationConfigs.size())
7221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return CONTINUE;
7231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
7251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::IterationConfig BBoxRenderCase::generateRandomConfig (int seed, const tcu::IVec2& renderTargetSize) const
7281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random		rnd		(seed);
7301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig	config;
7311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// viewport config
7331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportSize.x()	= rnd.getInt(MIN_VIEWPORT_SIZE, de::min<int>(renderTargetSize.x(), MAX_VIEWPORT_SIZE));
7341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportSize.y()	= rnd.getInt(MIN_VIEWPORT_SIZE, de::min<int>(renderTargetSize.y(), MAX_VIEWPORT_SIZE));
7351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportPos.x()	= rnd.getInt(0, renderTargetSize.x() - config.viewportSize.x());
7361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportPos.y()	= rnd.getInt(0, renderTargetSize.y() - config.viewportSize.y());
7371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// pattern location inside viewport
7391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternSize.x()	= rnd.getFloat(0.4f, 1.4f);
7401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternSize.y()	= rnd.getFloat(0.4f, 1.4f);
7411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternPos.x()	= rnd.getFloat(-1.0f, 1.0f - config.patternSize.x());
7421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternPos.y()	= rnd.getFloat(-1.0f, 1.0f - config.patternSize.y());
7431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// accurate bounding box
7451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.bbox.min			= tcu::Vec4(config.patternPos.x(), config.patternPos.y(), 0.0f, 1.0f);
7461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.bbox.max			= tcu::Vec4(config.patternPos.x() + config.patternSize.x(), config.patternPos.y() + config.patternSize.y(), 0.0f, 1.0f);
7471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOXSIZE_LARGER)
7491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// increase bbox size
7511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.x() -= rnd.getFloat() * 0.5f;
7521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.y() -= rnd.getFloat() * 0.5f;
7531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.z() -= rnd.getFloat() * 0.5f;
7541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.x() += rnd.getFloat() * 0.5f;
7561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.y() += rnd.getFloat() * 0.5f;
7571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.z() += rnd.getFloat() * 0.5f;
7581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (m_bboxSize == BBOXSIZE_SMALLER)
7601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// reduce bbox size
7621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.x() += rnd.getFloat() * 0.4f * config.patternSize.x();
7631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.y() += rnd.getFloat() * 0.4f * config.patternSize.y();
7641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.x() -= rnd.getFloat() * 0.4f * config.patternSize.x();
7661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.y() -= rnd.getFloat() * 0.4f * config.patternSize.y();
7671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return config;
7701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec4 BBoxRenderCase::getViewportPatternArea (const tcu::Vec2& patternPos, const tcu::Vec2& patternSize, const tcu::IVec2& viewportSize, AABBRoundDirection roundDir) const
7731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float	halfPixel	= 0.5f;
7751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4	vertexBox;
7761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4	pixelBox;
7771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7787a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.x() = (patternPos.x() * 0.5f + 0.5f) * (float)viewportSize.x();
7797a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.y() = (patternPos.y() * 0.5f + 0.5f) * (float)viewportSize.y();
7807a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.z() = ((patternPos.x() + patternSize.x()) * 0.5f + 0.5f) * (float)viewportSize.x();
7817a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.w() = ((patternPos.y() + patternSize.y()) * 0.5f + 0.5f) * (float)viewportSize.y();
7821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (roundDir == ROUND_INWARDS)
7841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.x() = (int)deFloatCeil(vertexBox.x()+halfPixel);
7861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.y() = (int)deFloatCeil(vertexBox.y()+halfPixel);
7871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.z() = (int)deFloatFloor(vertexBox.z()-halfPixel);
7881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.w() = (int)deFloatFloor(vertexBox.w()-halfPixel);
7891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
7911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.x() = (int)deFloatFloor(vertexBox.x()-halfPixel);
7931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.y() = (int)deFloatFloor(vertexBox.y()-halfPixel);
7941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.z() = (int)deFloatCeil(vertexBox.z()+halfPixel);
7951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.w() = (int)deFloatCeil(vertexBox.w()+halfPixel);
7961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return pixelBox;
7991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
8001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::setupRender (const IterationConfig& config)
8021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
8031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
8041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation			= gl.getAttribLocation(m_program->getProgram(), "a_position");
8051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		colLocation			= gl.getAttribLocation(m_program->getProgram(), "a_color");
8061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posScaleLocation	= gl.getUniformLocation(m_program->getProgram(), "u_posScale");
8071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posLocation != -1);
8091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(colLocation != -1);
8101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posScaleLocation != -1);
8111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
8131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
8141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting viewport to ("
8151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "x: " << config.viewportPos.x() << ", "
8161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "y: " << config.viewportPos.y() << ", "
8171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "w: " << config.viewportSize.x() << ", "
8181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "h: " << config.viewportSize.y() << ")\n"
8191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Vertex coordinates are in range:\n"
8201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tx: [" << config.patternPos.x() << ", " << (config.patternPos.x() + config.patternSize.x()) << "]\n"
8211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\ty: [" << config.patternPos.y() << ", " << (config.patternPos.y() + config.patternSize.y()) << "]\n"
8221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
8231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
8251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
8261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
8271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Setting primitive bounding box to:\n"
8281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t" << config.bbox.min << "\n"
8291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t" << config.bbox.max << "\n"
8301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
8311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_useGlobalState)
833485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.primitiveBoundingBox(config.bbox.min.x(), config.bbox.min.y(), config.bbox.min.z(), config.bbox.min.w(),
834485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								config.bbox.max.x(), config.bbox.max.y(), config.bbox.max.z(), config.bbox.max.w());
8351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
8361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// state is overriden by the tessellation output, set bbox to invisible area to imitiate dirty state left by application
837485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.primitiveBoundingBox(-2.0f, -2.0f, 0.0f, 1.0f,
838485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								-1.7f, -1.7f, 0.0f, 1.0f);
8391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
8411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);
8421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(config.viewportPos.x(), config.viewportPos.y(), config.viewportSize.x(), config.viewportSize.y());
8441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
8451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
8461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
8481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, (int)(VA_NUM_ATTRIB_VECS * sizeof(float[4])), (const float*)DE_NULL + 4 * VA_POS_VEC_NDX);
8491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(colLocation, 4, GL_FLOAT, GL_FALSE, (int)(VA_NUM_ATTRIB_VECS * sizeof(float[4])), (const float*)DE_NULL + 4 * VA_COL_VEC_NDX);
8501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
8511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(colLocation);
8521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
8531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform4f(posScaleLocation, config.patternPos.x(), config.patternPos.y(), config.patternSize.x(), config.patternSize.y());
8541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
8561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint bboxMinPos = gl.getUniformLocation(m_program->getProgram(), "u_primitiveBBoxMin");
8571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint bboxMaxPos = gl.getUniformLocation(m_program->getProgram(), "u_primitiveBBoxMax");
8581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4f(bboxMinPos, config.bbox.min.x(), config.bbox.min.y(), config.bbox.min.z(), config.bbox.min.w());
8601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4f(bboxMaxPos, config.bbox.max.x(), config.bbox.max.y(), config.bbox.max.z(), config.bbox.max.w());
8611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
8621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform2i(gl.getUniformLocation(m_program->getProgram(), "u_viewportPos"), config.viewportPos.x(), config.viewportPos.y());
8641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform2i(gl.getUniformLocation(m_program->getProgram(), "u_viewportSize"), config.viewportSize.x(), config.viewportSize.y());
8651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup");
8671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
8681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryconst char* BBoxRenderCase::genShaderFunction (ShaderFunction func) const
8701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
8711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	switch (func)
8721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
8731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_MIRROR_X:
8741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"vec4 mirrorX(in highp vec4 p)\n"
8751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
8761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternOffset = u_posScale.xy;\n"
8771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternScale = u_posScale.zw;\n"
8781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternCenter = patternOffset + patternScale * 0.5;\n"
8791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return vec4(2.0 * patternCenter.x - p.x, p.y, p.z, p.w);\n"
8801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
8811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_MIRROR_Y:
8831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"vec4 mirrorY(in highp vec4 p)\n"
8841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
8851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternOffset = u_posScale.xy;\n"
8861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternScale = u_posScale.zw;\n"
8871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternCenter = patternOffset + patternScale * 0.5;\n"
8881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return vec4(p.x, 2.0 * patternCenter.y - p.y, p.z, p.w);\n"
8891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
8901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_INSIDE_BBOX:
8921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"uniform highp ivec2 u_viewportPos;\n"
8931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"uniform highp ivec2 u_viewportSize;\n"
8941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp float v_bbox_expansionSize;\n"
8951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp vec3 v_bbox_clipMin;\n"
8961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp vec3 v_bbox_clipMax;\n"
8971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"\n"
8981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"bool fragmentInsideTheBBox(in highp float depth)\n"
8991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
9001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec4 wc = vec4(floor((v_bbox_clipMin.x * 0.5 + 0.5) * float(u_viewportSize.x) - v_bbox_expansionSize/2.0),\n"
9011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     floor((v_bbox_clipMin.y * 0.5 + 0.5) * float(u_viewportSize.y) - v_bbox_expansionSize/2.0),\n"
9021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     ceil((v_bbox_clipMax.x * 0.5 + 0.5) * float(u_viewportSize.x) + v_bbox_expansionSize/2.0),\n"
9031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     ceil((v_bbox_clipMax.y * 0.5 + 0.5) * float(u_viewportSize.y) + v_bbox_expansionSize/2.0));\n"
9041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	if (gl_FragCoord.x < float(u_viewportPos.x) + wc.x || gl_FragCoord.x > float(u_viewportPos.x) + wc.z ||\n"
9051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    gl_FragCoord.y < float(u_viewportPos.y) + wc.y || gl_FragCoord.y > float(u_viewportPos.y) + wc.w)\n"
9061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    return false;\n"
90726e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry					"	const highp float dEpsilon = 0.001;\n"
90826e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry					"	if (depth*2.0-1.0 < v_bbox_clipMin.z - dEpsilon || depth*2.0-1.0 > v_bbox_clipMax.z + dEpsilon)\n"
9091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    return false;\n"
9101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return true;\n"
9111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
9121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		default:
9131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(false);
9141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return "";
9151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
9161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass GridRenderCase : public BBoxRenderCase
9191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
9211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					GridRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
9221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					~GridRenderCase					(void);
9231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
9251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			init							(void);
9261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genVertexSource					(void) const;
9281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genFragmentSource				(void) const;
9291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genTessellationControlSource	(void) const;
9301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genTessellationEvaluationSource	(void) const;
9311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genGeometrySource				(void) const;
9321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig	generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
9341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			getAttributeData				(std::vector<tcu::Vec4>& data) const;
9351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			renderTestPattern				(const IterationConfig& config);
9361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			verifyRenderResult				(const IterationConfig& config);
9371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int		m_gridSize;
9391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
9401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::GridRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
9421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase	(context, name, description, 12, flags)
9431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_gridSize		(24)
9441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::~GridRenderCase (void)
9481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::init (void)
9521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
9541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
9551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering yellow-green grid to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
9561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Grid cells are in random order, varying grid size and location for each iteration.\n"
9571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated blue channel."
9581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
9591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
9611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genVertexSource (void) const
9641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
9661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
9681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
9691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
9701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
9711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
9721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
9731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
9741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
9751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
9761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
9771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
9781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
9791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
9801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
9811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
9821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
9831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
9841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
9861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
9871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
9881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
9891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
9901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
9911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
9931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
9941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
9951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
9961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = 0.0;\n"
9971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
9981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
9991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
10001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
10011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
10021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
10031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf<<	"}\n";
10061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
10081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
10091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genFragmentSource (void) const
10111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
10121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
10131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
10141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
10161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
10171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
10181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
10191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
10201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
10211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
10221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
10231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float blueChannel;\n"
10241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
10251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		blueChannel = 0.0;\n"
10261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
10271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		blueChannel = 1.0;\n"
10281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(baseColor.r, baseColor.g, blueChannel, baseColor.a);\n"
10291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
10301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
10321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
10331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genTessellationControlSource (void) const
10351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
10361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
10371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
10391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
10401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_primitive_bounding_box : require\n"
10411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
10421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
10431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
10441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
10451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
10461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n";
10471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
10491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
10511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
10521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp float vp_bbox_expansionSize;\n"
10551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMin;\n"
10561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
10571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
10591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
10611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
10621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
10631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
10641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
10661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
10671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
10681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
10691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
10721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
10731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
10741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
10751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
10761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
10771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
10781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = u_tessellationLevel;\n"
10791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n"
10801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = u_tessellationLevel;\n"
10811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = u_tessellationLevel;\n";
10821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
10841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
10861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = min(min(transformVec(gl_in[0].gl_Position),\n"
10871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                             transformVec(gl_in[1].gl_Position)),\n"
10881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[2].gl_Position));\n"
10891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = max(max(transformVec(gl_in[0].gl_Position),\n"
10901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                             transformVec(gl_in[1].gl_Position)),\n"
10911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[2].gl_Position));\n";
10921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
10941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
10961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
10971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
10981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
11011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
11021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[0] = bboxMin;\n"
11031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[1] = bboxMax;\n";
11041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_expansionSize = 0.0;\n"
11061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
11071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
11081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
11091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
11101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
11111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
11131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
11141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genTessellationEvaluationSource (void) const
11161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
11171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
11181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
11201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
11211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_gpu_shader5 : require\n"
11221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
11231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
11251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
11261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
11271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp float vp_bbox_expansionSize;\n"
11281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
11291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
11301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
11311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
11321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
11331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"precise gl_Position;\n"
11351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
11371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
11381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
11391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
11401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(gl_TessCoord.x * gl_in[0].gl_Position.zwyx +\n"
11411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      gl_TessCoord.y * gl_in[1].gl_Position.zwyx +\n"
11421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      gl_TessCoord.z * gl_in[2].gl_Position.zwyx);\n"
11431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_color = tess_ctrl_color[0];\n"
11441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = vp_bbox_expansionSize;\n"
11451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
11461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
11471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
11481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
11501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
11511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genGeometrySource (void) const
11531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
11541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
11551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
11561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
11581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_geometry_shader : require\n"
11591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
11601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=9, triangle_strip) out;\n"
11611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[3];\n"
11631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
11641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
11651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp float v_geo_bbox_expansionSize[3];\n"
11671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[3];\n"
11681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[3];\n"
11691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
11701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
11711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
11721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
11731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
11741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void setVisualizationVaryings()\n"
11751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
11761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_expansionSize = v_geo_bbox_expansionSize[0];\n"
11771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
11781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
11791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n"
11801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
11811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
11821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
11831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
11841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p1 = mirrorX(gl_in[1].gl_Position);\n"
11851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p2 = mirrorX(gl_in[2].gl_Position);\n"
11861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 pCentroid = vec4((p0.xyz + p1.xyz + p2.xyz) / 3.0, 1.0);\n"
11871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 triangleColor = " << colorInputName << "[0];\n"
11881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p0; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p1; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
11931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p1; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p2; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
11971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
11981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p2; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p0; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
12031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
12041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
12061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::IterationConfig GridRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
12091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return generateRandomConfig(0xDEDEDEu * (deUint32)iteration, renderTargetSize);
12111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
12141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green				(0.0f, 1.0f, 0.0f, 1.0f);
12161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		yellow				(1.0f, 1.0f, 0.0f, 1.0f);
12171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder			(m_gridSize * m_gridSize);
12181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd					(0xDE56789);
12191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with cells in random order
12211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
12221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
12231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
12241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(m_gridSize * m_gridSize * 6 * 2);
12261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
12271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
12281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
12291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= cellNdx % m_gridSize;
12301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= cellNdx / m_gridSize;
12311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec4&	cellColor	= ((cellX+cellY)%2 == 0) ? (green) : (yellow);
12321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12337a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 0) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+0) / float(m_gridSize), float(cellY+0) / float(m_gridSize), 0.0f, 1.0f);
12341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12357a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 1) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+1) / float(m_gridSize), float(cellY+1) / float(m_gridSize), 0.0f, 1.0f);
12361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12377a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 2) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+0) / float(m_gridSize), float(cellY+1) / float(m_gridSize), 0.0f, 1.0f);
12381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 2) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12397a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 3) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+0) / float(m_gridSize), float(cellY+0) / float(m_gridSize), 0.0f, 1.0f);
12401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 3) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12417a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 4) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+1) / float(m_gridSize), float(cellY+0) / float(m_gridSize), 0.0f, 1.0f);
12421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 4) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12437a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[(ndx * 6 + 5) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(cellX+1) / float(m_gridSize), float(cellY+1) / float(m_gridSize), 0.0f, 1.0f);
12441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 5) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
12461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::renderTestPattern (const IterationConfig& config)
12491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
12531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
12551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
12561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
12571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 2.8f; // will be rounded up
12581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
12601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
12621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
12641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
12651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
12661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
12671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering grid." << tcu::TestLog::EndMessage;
12691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_TRIANGLES), 0, m_gridSize * m_gridSize * 6);
12711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
12721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::verifyRenderResult (const IterationConfig& config)
12751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
12771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const ProjectedBBox		projectedBBox			= projectBoundingBox(config.bbox);
12781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportBBoxArea		= getViewportBoundingBoxArea(projectedBBox, config.viewportSize);
12791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportGridOuterArea	= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_OUTWARDS);
12801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportGridInnerArea	= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
12811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewportSurface			(config.viewportSize.x(), config.viewportSize.y());
12821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			errorMask				(config.viewportSize.x(), config.viewportSize.y());
12831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					anyError				= false;
12841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
12861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
12871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
12881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
12891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
12901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
12911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
12921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
12931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
12941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
12951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box.\n"
12961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
12971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
12981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
12991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
13001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result."
13011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
13021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
13041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
13051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
13061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0,0,0,255));
13081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = de::max(viewportBBoxArea.y(), 0); y < de::min(viewportBBoxArea.w(), config.viewportSize.y()); ++y)
13101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = de::max(viewportBBoxArea.x(), 0); x < de::min(viewportBBoxArea.z(), config.viewportSize.x()); ++x)
13111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA	pixel		= viewportSurface.getPixel(x, y);
13131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		outsideGrid	= x < viewportGridOuterArea.x() ||
13141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y < viewportGridOuterArea.y() ||
13151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  x > viewportGridOuterArea.z() ||
13161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y > viewportGridOuterArea.w();
13171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		insideGrid	= x > viewportGridInnerArea.x() &&
13181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y > viewportGridInnerArea.y() &&
13191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  x < viewportGridInnerArea.z() &&
13201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y < viewportGridInnerArea.w();
13211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool			error		= false;
13231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (outsideGrid)
13251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// expect black
13271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixel.getRed() != 0 || pixel.getGreen() != 0 || pixel.getBlue() != 0)
13281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				error = true;
13291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (insideGrid)
13321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// expect green, yellow or a combination of these
13341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixel.getGreen() != 255 || pixel.getBlue() != 0)
13351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				error = true;
13361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
13381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// boundary, allow anything
13401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
13431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
1344c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
13451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
13461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
13481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
13501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
13521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
13531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
13541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
13551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
13561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
13571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
13581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
13591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
13611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
13621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
136330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
136430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
136530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
136630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
136730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
136830fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
136930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
137030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
137130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
13721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
13731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass LineRenderCase : public BBoxRenderCase
13751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
13761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
13771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
13781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		LINEFLAG_WIDE = 1u << FLAGBIT_USER_BIT,	//!< use wide lines
13801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
13811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					LineRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
13831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					~LineRenderCase					(void);
13841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
13861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
13871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GREEN_COMPONENT_NDX = 1,
13891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BLUE_COMPONENT_NDX = 2,
13901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCAN_ROW_COMPONENT_NDX = GREEN_COMPONENT_NDX, // \note: scans are orthogonal to the line
13921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCAN_COL_COMPONENT_NDX = BLUE_COMPONENT_NDX,
13931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
13941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum QueryDirection
13961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DIRECTION_HORIZONTAL = 0,
13981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DIRECTION_VERTICAL,
13991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
14001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1401f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	enum ScanResult
1402f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
1403f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		SCANRESULT_NUM_LINES_OK_BIT		= (1 << 0),
1404f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		SCANRESULT_LINE_WIDTH_OK_BIT	= (1 << 1),
1405ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		SCANRESULT_LINE_WIDTH_WARN_BIT	= (1 << 2),
1406ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		SCANRESULT_LINE_WIDTH_ERR_BIT	= (1 << 3),
14072c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_OK_BIT		= (1 << 4),
14082c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_ERR_BIT	= (1 << 5),
14092c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_WARN_BIT	= (1 << 6),
1410f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	};
1411f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
14121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				init							(void);
14131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genVertexSource					(void) const;
14151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genFragmentSource				(void) const;
14161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genTessellationControlSource	(void) const;
14171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genTessellationEvaluationSource	(void) const;
14181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genGeometrySource				(void) const;
14191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig		generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
14211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				getAttributeData				(std::vector<tcu::Vec4>& data) const;
14221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				renderTestPattern				(const IterationConfig& config);
14231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				verifyRenderResult				(const IterationConfig& config);
14241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2			getNumberOfLinesRange			(int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const;
14262c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				scanRow							(const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
14272c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				scanColumn						(const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
14281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				checkAreaNumLines				(const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
14292c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				checkLineContinuity				(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const;
14301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2			getNumMinimaMaxima				(const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
1431ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	deUint8				checkLineWidths					(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
14321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				printLineWidthError				(const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& floodCounter) const;
14331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			m_patternSide;
14351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			m_isWideLineCase;
14361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			m_wideLineLineWidth;
14371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
14381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::LineRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
14401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase		(context, name, description, 12, flags)
14411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_patternSide			(12)
14421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_isWideLineCase		((flags & LINEFLAG_WIDE) != 0)
14431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_wideLineLineWidth	(5)
14441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::~LineRenderCase (void)
14481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::init (void)
14521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
14541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
14551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering line pattern to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
14561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Vertical lines are green, horizontal lines blue. Using additive blending.\n"
14571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Line segments are in random order, varying pattern size and location for each iteration.\n"
14581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated red channel."
14591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
14601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWideLineCase)
14621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glw::GLfloat lineWidthRange[2] = {0.0f, 0.0f};
14641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
14651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (lineWidthRange[1] < (float)m_wideLineLineWidth)
14671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires line width " + de::toString(m_wideLineLineWidth));
14681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
14691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
14711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genVertexSource (void) const
14741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
14761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
14781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
14791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
14801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
14811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
14821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_lineWidth;\n"
14831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
14841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
14851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
14871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
14881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
14891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
14901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
14911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
14921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
14931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
14941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
14951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
14961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
14971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
14981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
14991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
15001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
15011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
15021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
15041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
15051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = u_lineWidth;\n"
15061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
15071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
15081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
15091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
15101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
15111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
15121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
15141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
15161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
15171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genFragmentSource (void) const
15191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
15201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
15211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
15221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
15241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
15251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
15261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
15271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
15281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
15291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
15301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
15311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float redChannel;\n"
15321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
15331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 0.0;\n"
15341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
15351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 1.0;\n"
15361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(redChannel, baseColor.g, baseColor.b, baseColor.a);\n"
15371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
15381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
15401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
15411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genTessellationControlSource (void) const
15431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
15441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
15451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
15471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
15481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_primitive_bounding_box : require\n"
15491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=2) out;"
15501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
15511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
15521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
15531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
15541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
15551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_lineWidth;\n";
15561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
15581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
15601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
15611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp float vp_bbox_expansionSize;\n"
15641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMin;\n"
15651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
15661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
15681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
15701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
15711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
15721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
15731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
15751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
15761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
15771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
15781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
15811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
15821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
15831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
15841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
15851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
15861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
15871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 0.8; // will be rounded up to 1\n"
15881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n";
15891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
15911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
15931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = min(transformVec(gl_in[0].gl_Position),\n"
15941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[1].gl_Position));\n"
15951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = max(transformVec(gl_in[0].gl_Position),\n"
15961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[1].gl_Position));\n";
15971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
15991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
16001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
16011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
16021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
16031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
16041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
16061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
16071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[0] = bboxMin;\n"
16081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[1] = bboxMax;\n";
16091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_expansionSize = u_lineWidth;\n"
16111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
16121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
16131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
16141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
16151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
16161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
16181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
16191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genTessellationEvaluationSource (void) const
16211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
16221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
16231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
16251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
16261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(isolines) in;"
16271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
16291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
16301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
16311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp float vp_bbox_expansionSize;\n"
16331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
16341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
16351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
16361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
16371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
16381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
16391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
16401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
16411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
16421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(mix(gl_in[0].gl_Position.zwyx, gl_in[1].gl_Position.zwyx, gl_TessCoord.x));\n"
16431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_color = tess_ctrl_color[0];\n"
16441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = vp_bbox_expansionSize;\n"
16451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
16461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
16471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
16481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
16501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
16511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genGeometrySource (void) const
16531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
16541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
16551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
16561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
16581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_geometry_shader : require\n"
16591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(lines) in;\n"
16601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=5, line_strip) out;\n"
16611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[2];\n"
16631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
16641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
16651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp float v_geo_bbox_expansionSize[2];\n"
16681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[2];\n"
16691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[2];\n"
16701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
16711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
16721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
16731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
16741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
16751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void setVisualizationVaryings()\n"
16761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
16771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_expansionSize = v_geo_bbox_expansionSize[0];\n"
16781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
16791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
16801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n"
16811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
16821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
16831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
16841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
16851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p1 = mirrorX(gl_in[1].gl_Position);\n"
16861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 lineColor = " << colorInputName << "[0];\n"
16871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// output two separate primitives, just in case\n"
16891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.00); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
16901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.33); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
16911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
16921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.33); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
16941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.67); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
16951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 1.00); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
16961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
16971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
16981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
17001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::IterationConfig LineRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
17031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int numMaxAttempts = 128;
17051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Avoid too narrow viewports, lines could merge together. Require viewport is at least 2.5x the size of the line bodies.
17071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int attemptNdx = 0; attemptNdx < numMaxAttempts; ++attemptNdx)
17081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
17091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const IterationConfig& config = generateRandomConfig((0xDEDEDEu * (deUint32)iteration) ^ (0xABAB13 * attemptNdx), renderTargetSize);
17101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17117a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		if ((float)config.viewportSize.x() * (config.patternSize.x() * 0.5f) > 2.5f * (float)m_patternSide * (float)m_wideLineLineWidth &&
17127a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			(float)config.viewportSize.y() * (config.patternSize.y() * 0.5f) > 2.5f * (float)m_patternSide * (float)m_wideLineLineWidth)
17131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return config;
17151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
17171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(false);
17191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return IterationConfig();
17201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
17231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
17251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		blue		(0.0f, 0.0f, 1.0f, 1.0f);
17261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder	(m_patternSide * m_patternSide * 2);
17271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd			(0xDE12345);
17281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate crosshatch pattern with segments in random order
17301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
17311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
17321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
17331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(cellOrder.size() * 4);
17351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
17361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
17371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int segmentID		= cellOrder[ndx];
17381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int direction		= segmentID & 0x01;
17391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int majorCoord	= (segmentID >> 1) / m_patternSide;
17401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int minorCoord	= (segmentID >> 1) % m_patternSide;
17411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (direction)
17431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17447a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(minorCoord) / float(m_patternSide), float(majorCoord) / float(m_patternSide), 0.0f, 1.0f);
17451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
17467a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(minorCoord) / float(m_patternSide), float(majorCoord + 1) / float(m_patternSide), 0.0f, 1.0f);
17471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
17481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
17501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17517a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(majorCoord) / float(m_patternSide), float(minorCoord) / float(m_patternSide), 0.0f, 1.0f);
17521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
17537a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(majorCoord + 1) / float(m_patternSide), float(minorCoord) / float(m_patternSide), 0.0f, 1.0f);
17541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
17551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
17571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::renderTestPattern (const IterationConfig& config)
17601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
17621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
17641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
17661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
17671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
17681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 2.8f; // will be rounded up
17691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
17711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
17731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
17751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 2);
17761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
17771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
17781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWideLineCase)
17801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.lineWidth((float)m_wideLineLineWidth);
17811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17827a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	gl.uniform1f(gl.getUniformLocation(m_program->getProgram(), "u_lineWidth"), (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f));
17831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering pattern." << tcu::TestLog::EndMessage;
17851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_BLEND);
17871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendFunc(GL_ONE, GL_ONE);
17881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendEquation(GL_FUNC_ADD);
17891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_LINES), 0, m_patternSide * m_patternSide * 2 * 2);
17911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
17921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::verifyRenderResult (const IterationConfig& config)
17951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1796ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const glw::Functions&	gl							= m_context.getRenderContext().getFunctions();
1797ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const bool				isMsaa						= m_context.getRenderTarget().getNumSamples() > 1;
1798ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const ProjectedBBox		projectedBBox				= projectBoundingBox(config.bbox);
1799ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const float				lineWidth					= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
1800ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec4		viewportBBoxArea			= getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
1801ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec4		viewportPatternArea			= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
1802ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec2		expectedHorizontalLines		= getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
1803ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec2		expectedVerticalLines		= getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
1804ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec4		verificationArea			= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
1805ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos																	 de::max(viewportBBoxArea.y(), 0),
1806ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos																	 de::min(viewportBBoxArea.z(), config.viewportSize.x()),
1807ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos																	 de::min(viewportBBoxArea.w(), config.viewportSize.y()));
1808ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
1809ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	tcu::Surface			viewportSurface				(config.viewportSize.x(), config.viewportSize.y());
1810ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	int						messageLimitCounter			= 8;
18111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18122c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	enum ScanResultCodes
18132c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
18142c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_NUM_LINES_ERR	= 0,
18152c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_MSAA	= 1,
18162c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_WARN	= 2,
18172c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_ERR	= 3,
18182c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_ERR	= 4,
18192c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_WARN	= 5,
18202c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_LAST
18212c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	};
18222c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
18232c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int						rowScanResult[SCANRESULT_LINE_LAST]		= {0, 0, 0, 0, 0, 0};
18242c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int						columnScanResult[SCANRESULT_LINE_LAST]	= {0, 0, 0, 0, 0, 0};
18252c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					anyError								= false;
18262c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					msaaRelaxationRequired					= false;
18272c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					hwIssueRelaxationRequired				= false;
18282c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
18291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
18301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
18311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
18321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
18331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
18341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
18351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
18361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
18371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
18381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
18391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box:\n"
18401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
18411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
18421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
18431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
18441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result:"
18451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
18461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
18481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
18491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tCalculating number of horizontal and vertical lines within the bounding box, expecting:\n"
18501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\t[" << expectedHorizontalLines.x() << ", " << expectedHorizontalLines.y() << "] horizontal lines.\n"
18511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\t[" << expectedVerticalLines.x() << ", " << expectedVerticalLines.y() << "] vertical lines.\n"
18521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
18531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
18551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
18561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
18571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// scan rows
18591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = de::max(verificationArea.y(), viewportPatternArea.y()); y < de::min(verificationArea.w(), viewportPatternArea.w()); ++y)
1860f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
186125ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry		const deUint8 result = scanRow(viewportSurface.getAccess(),
186225ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   y,
186325ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   verificationArea.x(),
186425ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   verificationArea.z(),
18652c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin									   de::max(verificationArea.x(), viewportPatternArea.x()),
18662c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin									   de::min(verificationArea.z(), viewportPatternArea.z()),
186725ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   expectedVerticalLines,
186825ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   messageLimitCounter);
1869f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
1870f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
18712c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			rowScanResult[SCANRESULT_NUM_LINES_ERR]++;
18722c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
18732c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
18742c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
18752c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_CONT_WARN]++;
18762c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else
18772c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_CONT_ERR]++;
18782c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
1879f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
1880f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
1881f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			if (m_isWideLineCase && isMsaa)
1882f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			{
1883f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry				// multisampled wide lines might not be supported
18842c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
1885f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			}
1886ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
1887ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					 (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
1888ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			{
18892c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
1890ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			}
1891f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			else
18922c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
1893f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
1894f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	}
18951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// scan columns
18971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = de::max(verificationArea.x(), viewportPatternArea.x()); x < de::min(verificationArea.z(), viewportPatternArea.z()); ++x)
1898f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
189925ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry		const deUint8 result = scanColumn(viewportSurface.getAccess(),
190025ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  x,
190125ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  verificationArea.y(),
190225ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  verificationArea.w(),
19032c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin										  de::min(verificationArea.y(), viewportPatternArea.y()),
19042c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin										  de::min(verificationArea.w(), viewportPatternArea.w()),
190525ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  expectedHorizontalLines,
190625ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  messageLimitCounter);
1907f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
1908f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
19092c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			columnScanResult[SCANRESULT_NUM_LINES_ERR]++;
19102c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
19112c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
19122c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
19132c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_CONT_WARN]++;
19142c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else
19152c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_CONT_ERR]++;
19162c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
1917f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
1918f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
1919f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			if (m_isWideLineCase && isMsaa)
1920f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			{
1921f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry				// multisampled wide lines might not be supported
19222c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
1923f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			}
19242c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
19252c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin					 (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
1926ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			{
19272c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
1928ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			}
1929f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			else
19302c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
1931f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
1932f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	}
19331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
19342c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (columnScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0)
19352c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		anyError = true;
19362c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if(columnScanResult[SCANRESULT_LINE_CONT_ERR] != 0 || rowScanResult[SCANRESULT_LINE_CONT_ERR] != 0)
19372c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		anyError = true;
19382c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0)
19392c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		msaaRelaxationRequired = true;
19402c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0)
19412c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		hwIssueRelaxationRequired = true;
19422c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
19432c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
19442c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// found missing lines in a columnw and row line continuity check reported a warning (not an error) -> line width precision issue
19452c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (rowScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && rowScanResult[SCANRESULT_LINE_CONT_WARN])
19462c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			hwIssueRelaxationRequired = true;
19472c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
19482c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			anyError = true;
19492c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
19502c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (rowScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
19512c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
19522c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// found missing lines in a row and column line continuity check reported a warning (not an error) -> line width precision issue
19532c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (columnScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && columnScanResult[SCANRESULT_LINE_CONT_WARN])
19542c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			hwIssueRelaxationRequired = true;
19552c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
19562c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			anyError = true;
19572c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
19582c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
1959ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	if (anyError || msaaRelaxationRequired || hwIssueRelaxationRequired)
19601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
19611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (messageLimitCounter < 0)
19621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
19631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
19641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
19651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
19661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
19671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
19681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
19691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
19701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
19711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1972f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if (anyError)
1973f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
1974ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		else if (hwIssueRelaxationRequired)
1975ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		{
1976ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			// Line width hw issue
1977ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Line width verification failed");
1978ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		}
1979f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else
1980f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
1981f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			// MSAA wide lines are optional
1982f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Multisampled wide line verification failed");
1983f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
19841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
19851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
198630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
198730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
198830fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
198930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
199030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
199130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
199230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
199330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
199430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
19951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
19961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
19971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 LineRenderCase::getNumberOfLinesRange (int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const
19981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
19991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// pattern is not symmetric due to mirroring
20001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int	patternStartNdx	= (queryDir == DIRECTION_HORIZONTAL) ? ((m_hasGeometryStage) ? (1) : (0)) : ((m_hasTessellationStage) ? (1) : (0));
20011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int	patternEndNdx	= patternStartNdx + m_patternSide;
20021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int			numLinesMin		= 0;
20041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int			numLinesMax		= 0;
20051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int lineNdx = patternStartNdx; lineNdx < patternEndNdx; ++lineNdx)
20071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
20087a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		const float linePos		= (patternStart + (float(lineNdx) / float(m_patternSide)) * patternSize) * 0.5f + 0.5f;
20097a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		const float lineWidth	= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
20101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20117a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		if (linePos * (float)viewportArea > (float)queryAreaBegin + 1.0f &&
20127a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			linePos * (float)viewportArea < (float)queryAreaEnd   - 1.0f)
20131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
20141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// line center is within the area
20151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMin;
20161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMax;
20171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
20187a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		else if (linePos * (float)viewportArea > (float)queryAreaBegin - lineWidth*0.5f - 1.0f &&
20197a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		         linePos * (float)viewportArea < (float)queryAreaEnd   + lineWidth*0.5f + 1.0f)
20201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
20211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// line could leak into area
20221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMax;
20231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
20241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
20251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(numLinesMin, numLinesMax);
20271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20292c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
20301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20312c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const bool		numLinesOk			= checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
20322c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineWidthRes		= checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
20332c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineContinuityRes	= checkLineContinuity(access, tcu::IVec2(rowViewportBegin, row), tcu::IVec2(rowViewportEnd, row), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
20342c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8			result				= 0;
2035ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
2036ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	if (numLinesOk)
2037ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
2038ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
20392c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (lineContinuityRes == 0)
20402c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
20412c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else
20422c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= lineContinuityRes;
20432c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
2044ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	if (lineWidthRes == 0)
2045ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
2046ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	else
2047ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= lineWidthRes;
2048f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
2049ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	return result;
20501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20522c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
20531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20542c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const bool		numLinesOk			= checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
20552c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineWidthRes		= checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
20562c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineContinuityRes	= checkLineContinuity(access, tcu::IVec2(column, columnViewportBegin), tcu::IVec2(column, columnViewportEnd), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
20572c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8			result				= 0;
2058ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
2059ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	if (numLinesOk)
2060ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
2061ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
20622c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (lineContinuityRes == 0)
20632c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
20642c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else
20652c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= lineContinuityRes;
20662c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
2067ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	if (lineWidthRes == 0)
2068ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
2069ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	else
2070ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos		result |= lineWidthRes;
2071f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
2072ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	return result;
20731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const
20761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Num maxima == num lines
20781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::ConstPixelBufferAccess	subAccess		= tcu::getSubregion(access, area.x(), area.y(), 0, area.z(), area.w(), 1);
20791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2					numMinimaMaxima	= getNumMinimaMaxima(subAccess, componentNdx);
20801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int							numMaxima		= numMinimaMaxima.y();
20811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// In valid range
20831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (numMaxima >= numLines.x() && numMaxima <= numLines.y())
20841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
20851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--messageLimitCounter < 0)
20871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return false;
20881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (area.z() == 1)
20901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
20911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
20921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "On column " << area.x() << ", y: [" << area.y() << "," << (area.y()+area.w()) << "):\n"
20931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tExpected [" << numLines.x() << ", " << numLines.y() << "] lines but the number of lines in the area is " << numMaxima
20941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
20951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
20961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
20971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
20981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "On row " << area.y() << ", x: [" << area.x() << "," << (area.x()+area.z()) << "):\n"
20991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tExpected [" << numLines.x() << ", " << numLines.y() << "] lines but the number of lines in the area is " << numMaxima
21001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
21011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
21031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
21041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 LineRenderCase::getNumMinimaMaxima (const tcu::ConstPixelBufferAccess& access, int componentNdx) const
21061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
21071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(access.getWidth() == 1 || access.getHeight() == 1);
21081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int previousValue	= -1;
21101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int previousSign	= 0;
21111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int numMinima		= 0;
21121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int numMaxima		= 0;
21131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < access.getHeight(); ++y)
21151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < access.getWidth(); ++x)
21161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
21171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int componentValue = access.getPixelInt(x, y)[componentNdx];
21181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (previousValue != -1)
21201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
21211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int sign = (componentValue > previousValue) ? (+1) : (componentValue < previousValue) ? (-1) : (0);
21221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// local minima/maxima in sign changes (zero signless)
21241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (sign != 0 && sign == -previousSign)
21251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
21261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				previousSign = sign;
21271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (sign > 0)
21291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMinima;
21301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
21311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMaxima;
21321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
21331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (sign != 0 && previousSign == 0)
21341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
21351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				previousSign = sign;
21361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// local extreme at the start boundary
21381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (sign > 0)
21391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMinima;
21401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
21411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMaxima;
21421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
21431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
21441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		previousValue = componentValue;
21461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
21471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// local extreme at the end boundary
21491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (previousSign > 0)
21501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMaxima;
21511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (previousSign < 0)
21521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMinima;
21531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
21541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
21551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMaxima;
21561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMinima;
21571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
21581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(numMinima, numMaxima);
21601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
21611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21622c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::checkLineContinuity (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
21632c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin{
21642c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool				line					= false;
21652c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const tcu::IVec2	advance					= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
21662c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int					missedPixels			= 0;
21672c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int					totalPixels				= 0;
21682c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				errorMask				= 0;
21692c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
21702c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	for (tcu::IVec2 cursor = begin; cursor != end; cursor += advance)
21712c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
21722c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		const bool hit = (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0);
21732c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
21742c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (hit)
21752c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			line = true;
21762c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else if (line && !hit)
21772c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
21782c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			// non-continuous line detected
21792c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 advanceNeighbor	= tcu::IVec2(1, 1) - advance;
21802c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 cursorNeighborPos	= cursor + advanceNeighbor;
21812c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 cursorNeighborNeg	= cursor - advanceNeighbor;
21822c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			// hw precision issues may lead to a line being non-straight -> check neighboring pixels
21832c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((access.getPixelInt(cursorNeighborPos.x(), cursorNeighborPos.y())[componentNdx] == 0) && (access.getPixelInt(cursorNeighborNeg.x(), cursorNeighborNeg.y())[componentNdx] == 0))
21842c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				++missedPixels;
21852c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
21862c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		++totalPixels;
21872c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
21882c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
21892c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (missedPixels > 0 && --messageLimitCounter >= 0)
21902c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
21912c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		m_testCtx.getLog()
21922c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			<< tcu::TestLog::Message
21932c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			<< "Found non-continuous " << ((advance.x() == 1)  ? ("horizontal") : ("vertical")) << " line near " << begin << ". "
21942c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			<< "Missed pixels: " << missedPixels
21952c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			<< tcu::TestLog::EndMessage;
21962c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// allow 10% missing pixels for warning
2197d8b452a7533c195b1328918bb696a819542ff044Pyry Haulos		if (missedPixels <= deRoundFloatToInt32((float)totalPixels * 0.1f))
21982c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			errorMask = SCANRESULT_LINE_CONT_WARN_BIT;
21992c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
22002c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			errorMask =  SCANRESULT_LINE_CONT_ERR_BIT;
22012c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
22022c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
22032c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	return errorMask;
22042c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin}
22052c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
2206ba45591407d0207e8ba0634ea5636fd721ed781fPyry HaulosdeUint8 LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
22071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2208ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const bool			multisample				= m_context.getRenderTarget().getNumSamples() > 1;
2209ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const int			lineRenderWidth			= (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
2210ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec2	lineWidthRange			= (multisample)
2211ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos													? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1))	// multisampled "smooth" lines may spread to neighboring pixel
2212ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos													: (tcu::IVec2(lineRenderWidth, lineRenderWidth));
2213ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec2	relaxedLineWidthRange	= (tcu::IVec2(lineRenderWidth-1, lineRenderWidth+1));
22141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2215ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	int					lineWidth				= 0;
2216ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	bool				bboxLimitedLine			= false;
2217ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	deUint8				errorMask				= 0;
22181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2219ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	const tcu::IVec2	advance					= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
22201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fragments before begin?
22221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (access.getPixelInt(begin.x(), begin.y())[componentNdx] != 0)
22231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
22241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bboxLimitedLine = true;
22251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (tcu::IVec2 cursor = begin - advance;; cursor -= advance)
22271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
22281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (cursor.x() < 0 || cursor.y() < 0)
22291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
22311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0)
22331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				++lineWidth;
22351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
22371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
22381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
22391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
22401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (tcu::IVec2 cursor = begin; cursor != end; cursor += advance)
22421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
22431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool hit = (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0);
22441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (hit)
22461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++lineWidth;
22471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (lineWidth)
22481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
22491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// Line is allowed to be be thinner if it borders the bbox boundary (since part of the line might have been discarded).
22501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool incorrectLineWidth = (lineWidth < lineWidthRange.x() && !bboxLimitedLine) || (lineWidth > lineWidthRange.y());
22511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (incorrectLineWidth)
22531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
2254ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos				const bool incorrectRelaxedLineWidth = (lineWidth < relaxedLineWidthRange.x() && !bboxLimitedLine) || (lineWidth > relaxedLineWidthRange.y());
2255ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
2256ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos				if (incorrectRelaxedLineWidth)
2257ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
2258ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos				else
2259ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
2260ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
22611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
22621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			lineWidth = 0;
22651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxLimitedLine = false;
22661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
22671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
22681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fragments after end?
22701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (lineWidth)
22711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
22721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (tcu::IVec2 cursor = end;; cursor += advance)
22731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
22741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (cursor.x() >= access.getWidth() || cursor.y() >= access.getHeight())
22751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (lineWidth > lineWidthRange.y())
22771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
2278ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					if (lineWidth > relaxedLineWidthRange.y())
2279ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
2280ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					else
2281ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
2282ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
22831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
22841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
22851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
22871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0)
22891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				++lineWidth;
22911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (lineWidth)
22931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// only check that line width is not larger than expected. Line width may be smaller
22951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// since the scanning 'cursor' is now outside the bounding box.
22961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const bool incorrectLineWidth = (lineWidth > lineWidthRange.y());
22971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (incorrectLineWidth)
22991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
2300ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					const bool incorrectRelaxedLineWidth = (lineWidth > relaxedLineWidthRange.y());
2301ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
2302ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					if (incorrectRelaxedLineWidth)
2303ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
2304ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos					else
2305ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
2306ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos
23071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
23081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
23091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				lineWidth = 0;
23111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
23121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
23131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
23141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2315ba45591407d0207e8ba0634ea5636fd721ed781fPyry Haulos	return errorMask;
23161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::printLineWidthError (const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& messageLimitCounter) const
23191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--messageLimitCounter < 0)
23211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return;
23221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
23241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
23251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Found incorrect line width near " << pos << ": (" << ((isHorizontal) ? ("horizontal") : ("vertical")) << " line)\n"
23261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tExpected line width in range [" << lineWidthRange.x() << ", " << lineWidthRange.y() << "] but found " << detectedLineWidth
23271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
23281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass PointRenderCase : public BBoxRenderCase
23311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
23331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
23341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINTFLAG_WIDE = 1u << FLAGBIT_USER_BIT,	//!< use wide points
23361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct GeneratedPoint
23381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	center;
23401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int			size;
23411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool		even;
23421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							PointRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
23451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							~PointRenderCase				(void);
23461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
23481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum ResultPointType
23491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINT_FULL = 0,
23511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINT_PARTIAL
23521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					init							(void);
23551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					deinit							(void);
23561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genVertexSource					(void) const;
23581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genFragmentSource				(void) const;
23591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genTessellationControlSource	(void) const;
23601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genTessellationEvaluationSource	(void) const;
23611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genGeometrySource				(void) const;
23621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig			generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
23641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					generateAttributeData			(void);
23651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					getAttributeData				(std::vector<tcu::Vec4>& data) const;
23661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					renderTestPattern				(const IterationConfig& config);
23671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					verifyRenderResult				(const IterationConfig& config);
23681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					genReferencePointData			(const IterationConfig& config, std::vector<GeneratedPoint>& data) const;
23701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyNarrowPointPattern		(const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter);
23711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyWidePointPattern			(const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter);
23721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyWidePoint					(const tcu::Surface& viewport, const GeneratedPoint& refPoint, const ProjectedBBox& bbox, ResultPointType pointType, int& logFloodCounter);
23731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyWidePointAt				(const tcu::IVec2& pointPos, const tcu::Surface& viewport, const GeneratedPoint& refPoint, const tcu::IVec4& bbox, ResultPointType pointType, int componentNdx, int& logFloodCounter);
23741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2				scanPointWidthAt				(const tcu::IVec2& pointPos, const tcu::Surface& viewport, int expectedPointSize, int componentNdx) const;
23751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				m_numStripes;
23771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				m_isWidePointCase;
23781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>	m_attribData;
23791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
23801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::PointRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
23821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase	(context, name, description, 12, flags)
23831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numStripes		(4)
23841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_isWidePointCase	((flags & POINTFLAG_WIDE) != 0)
23851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::~PointRenderCase (void)
23891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::init (void)
23931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
23951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// extensions
23971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_point_size"))
23981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires GL_EXT_geometry_point_size extension");
23991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage && !m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_point_size"))
24001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_point_size extension");
24011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// point size range
24031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
24041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			glw::GLfloat pointSizeRange[2] = {0.0f, 0.0f};
24051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
24061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pointSizeRange[1] < 5.0f)
24081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				throw tcu::NotSupportedError("Test requires point size 5.0");
24091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
24101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
24111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
24131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
24141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering point pattern to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
24151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Half of the points are green, half blue. Using additive blending.\n"
24161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Points are in random order, varying pattern size and location for each iteration.\n"
24171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated red channel."
24181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
24191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	generateAttributeData();
24211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
24231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::deinit (void)
24261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// clear data
24281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_attribData = std::vector<tcu::Vec4>();
24291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// deinit parent
24311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::deinit();
24321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genVertexSource (void) const
24351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
24371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
24391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
24401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
24411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
24421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
24431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
24441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
24451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
24461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
24471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
24481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
24491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
24501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
24511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
24521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
24531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
24541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
24551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
24571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
24581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
24591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
24601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = "
24611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< ((m_isWidePointCase && !m_hasTessellationStage && !m_hasGeometryStage) ? ("(a_color.g > 0.0) ? (5.0) : (3.0)") : ("1.0"))
24621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< ";\n"
24631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
24641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_PointSize = pointSize;\n"
24651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
24661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
24681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
24691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
24701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
24711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = pointSize;\n"
24721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
24731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
24741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
24751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
24761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
24771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
24781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
24791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
24811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
24821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genFragmentSource (void) const
24851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
24871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
24881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
24901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
24911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
24921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
24931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
24941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
24951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
24961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
24971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float redChannel;\n"
24981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
24991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 0.0;\n"
25001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
25011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 1.0;\n"
25021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(redChannel, baseColor.g, baseColor.b, baseColor.a);\n"
25031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
25041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
25061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
25071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genTessellationControlSource (void) const
25091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
25101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			tessellationWidePoints = (m_isWidePointCase) && (!m_hasGeometryStage);
25111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
25121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
25141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
25151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_primitive_bounding_box : require\n"
25161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((tessellationWidePoints) ? ("#extension GL_EXT_tessellation_point_size : require\n") : (""))
25171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(vertices=1) out;"
25181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
25191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
25201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
25211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
25221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n";
25231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
25251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
25271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
25281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp vec3 vp_bbox_clipMin;\n"
25311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
25321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
25341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
25361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
25371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
25381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
25391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
25411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
25421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
25431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
25441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
25471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
25481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
25491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
25501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
25511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
25521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
25531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = u_tessellationLevel;\n"
25541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n"
25551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = u_tessellationLevel;\n"
25561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[3] = u_tessellationLevel;\n"
25571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 0.8; // will be rounded up to 1\n"
25581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[1] = 0.8; // will be rounded up to 1\n";
25591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
25611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
25631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
25651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf <<	"	const vec2 minExpansion = vec2(0.07 + 0.05, 0.07 + 0.02); // eval and geometry shader\n"
25661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	const vec2 maxExpansion = vec2(0.07 + 0.05, 0.07 + 0.03); // eval and geometry shader\n";
25671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
25681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf <<	"	const vec2 minExpansion = vec2(0.07, 0.07); // eval shader\n"
25691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	const vec2 maxExpansion = vec2(0.07, 0.07); // eval shader\n";
25701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp vec2 patternScale = u_posScale.zw;\n"
25721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = transformVec(gl_in[0].gl_Position) - vec4(minExpansion * patternScale, 0.0, 0.0);\n"
25731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = transformVec(gl_in[0].gl_Position) + vec4(maxExpansion * patternScale, 0.0, 0.0);\n";
25741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
25761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
25781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
25791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
25801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
25821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
25831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[0] = bboxMin;\n"
25841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[1] = bboxMax;\n";
25851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
25871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
25881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
25891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
25901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
25911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
25931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
25941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genTessellationEvaluationSource (void) const
25961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
25971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			tessellationWidePoints = (m_isWidePointCase) && (!m_hasGeometryStage);
25981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
25991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
26011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
26021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((tessellationWidePoints) ? ("#extension GL_EXT_tessellation_point_size : require\n") : (""))
26031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(quads, point_mode) in;"
26041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
26061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
26071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
26081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
26101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
26111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((!m_hasGeometryStage) ? ("flat out highp float v_bbox_expansionSize;\n") : (""))
26121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
26131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
26141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
26161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
26171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
26181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
26191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
26201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 offset = vec4((gl_TessCoord.xy * 2.0 - vec2(1.0)) * 0.07 * patternScale, 0.0, 0.0);\n"
26211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = " << ((tessellationWidePoints) ? ("(tess_ctrl_color[0].g > 0.0) ? (5.0) : (3.0)") : ("1.0")) << ";\n"
26221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(gl_in[0].gl_Position.zwyx + offset);\n";
26231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (tessellationWidePoints)
26251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_PointSize = pointSize;\n";
26261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	tess_color = tess_ctrl_color[0];\n"
26281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((!m_hasGeometryStage) ? ("v_bbox_expansionSize = pointSize;\n") : (""))
26291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
26301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
26311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
26321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
26341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
26351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genGeometrySource (void) const
26371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
26381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
26391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
26401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
26421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_geometry_shader : require\n"
26431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((m_isWidePointCase) ? ("#extension GL_EXT_geometry_point_size : require\n") : (""))
26441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(points) in;\n"
26451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=3, points) out;\n"
26461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[1];\n"
26481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
26491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
26501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[1];\n"
26521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[1];\n"
26531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
26541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
26551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
26561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
26581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
26591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
26601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
26611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
26621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
26631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 pointColor = " << colorInputName << "[0];\n"
26641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
26651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = "
26661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< (m_isWidePointCase ? ("(pointColor.g > 0.0) ? (5.0) : (3.0)") : ("1.0"))
26671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< ";\n"
26681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 offsets[3] =\n"
2670cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"		vec4[3](\n"
2671cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4( 0.05 * patternScale.x, 0.03 * patternScale.y, 0.0, 0.0),\n"
2672cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4(-0.01 * patternScale.x,-0.02 * patternScale.y, 0.0, 0.0),\n"
2673cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4(-0.05 * patternScale.x, 0.02 * patternScale.y, 0.0, 0.0)\n"
2674cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"		);\n"
26751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	for (int ndx = 0; ndx < 3; ++ndx)\n"
26761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	{\n"
26771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		gl_Position = p0 + offsets[ndx];\n";
26781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
26801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"		gl_PointSize = pointSize;\n";
26811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"		v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
26831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
26841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		v_bbox_expansionSize = pointSize;\n"
26851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		geo_color = pointColor;\n"
26861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		EmitVertex();\n"
26871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	}\n"
26881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
26891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
26911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
26921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::IterationConfig PointRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
26941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
26951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig config = generateRandomConfig(0xDEDEDEu * (deUint32)iteration, renderTargetSize);
26961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// equal or larger -> expand according to shader expansion
26981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOXSIZE_EQUAL || m_bboxSize == BBOXSIZE_LARGER)
26991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
27001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec2 patternScale = config.patternSize;
27011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage)
27031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.min -= tcu::Vec4(0.07f * patternScale.x(), 0.07f * patternScale.y(), 0.0f, 0.0f);
27051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.max += tcu::Vec4(0.07f * patternScale.x(), 0.07f * patternScale.y(), 0.0f, 0.0f);
27061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
27081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.min -= tcu::Vec4(0.05f * patternScale.x(), 0.02f * patternScale.y(), 0.0f, 0.0f);
27101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.max += tcu::Vec4(0.05f * patternScale.x(), 0.03f * patternScale.y(), 0.0f, 0.0f);
27111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
27131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return config;
27151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::generateAttributeData (void)
27181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
27201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		blue		(0.0f, 0.0f, 1.0f, 1.0f);
27211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder	(m_numStripes * m_numStripes * 2);
27221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd			(0xDE22446);
27231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
27251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
27261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
27271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_attribData.resize(cellOrder.size() * 2);
27291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
27301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
27311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int pointID		= cellOrder[ndx];
27321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int direction		= pointID & 0x01;
27331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int majorCoord	= (pointID >> 1) / m_numStripes;
27341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int minorCoord	= (pointID >> 1) % m_numStripes;
27351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (direction)
27371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27387a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(float(minorCoord) / float(m_numStripes), float(majorCoord) / float(m_numStripes), 0.0f, 1.0f);
27391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
27401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
27421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27437a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_POS_VEC_NDX] = tcu::Vec4(((float)majorCoord + 0.5f) / float(m_numStripes), ((float)minorCoord + 0.5f) / float(m_numStripes), 0.0f, 1.0f);
27441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
27451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
27471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
27501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data = m_attribData;
27521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::renderTestPattern (const IterationConfig& config)
27551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
27571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
27591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
27611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
27621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
27631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 0.8f; // will be rounded up
27641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
27661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
27681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
27701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 1);
27711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
27721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
27731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering pattern." << tcu::TestLog::EndMessage;
27751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_BLEND);
27771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendFunc(GL_ONE, GL_ONE);
27781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendEquation(GL_FUNC_ADD);
27791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_POINTS), 0, m_numStripes * m_numStripes * 2);
27811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
27821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::verifyRenderResult (const IterationConfig& config)
27851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&		gl						= m_context.getRenderContext().getFunctions();
27871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const ProjectedBBox			projectedBBox			= projectBoundingBox(config.bbox);
27881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4			viewportBBoxArea		= getViewportBoundingBoxArea(projectedBBox, config.viewportSize);
27891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface				viewportSurface			(config.viewportSize.x(), config.viewportSize.y());
27911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int							logFloodCounter			= 8;
27921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool						anyError;
27931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<GeneratedPoint>	refPoints;
27941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
27961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
27971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
27981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
27991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
28001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
28011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
28021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
28031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
28041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
28051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box:\n"
28061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
28071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
28081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
28091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
28101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result:"
28111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
28121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
28141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
28151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
28161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genReferencePointData(config, refPoints);
28181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
28201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		anyError = verifyWidePointPattern(viewportSurface, refPoints, projectedBBox, logFloodCounter);
28211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
28221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		anyError = verifyNarrowPointPattern(viewportSurface, refPoints, projectedBBox, logFloodCounter);
28231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
28251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (logFloodCounter < 0)
28271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-logFloodCounter) << " error descriptions." << tcu::TestLog::EndMessage;
28281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
28301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
28311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
28321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
28331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
28341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
28351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
28361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
28381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
28391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
284030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
284130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
284230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
284330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
284430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
284530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
284630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
284730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
284830fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
28491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
28501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct PointSorter
28521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
28531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool operator() (const PointRenderCase::GeneratedPoint& a, const PointRenderCase::GeneratedPoint& b) const
28541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (a.center.y() < b.center.y())
28561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
28571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (a.center.y() > b.center.y())
28581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return false;
28591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
28601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return (a.center.x() < b.center.x());
28611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
28621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
28631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::genReferencePointData (const IterationConfig& config, std::vector<GeneratedPoint>& data) const
28651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
28661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<GeneratedPoint> currentPoints;
28671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// vertex shader
28691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	currentPoints.resize(m_attribData.size() / 2);
28701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
28711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].center	= m_attribData[ndx*2].swizzle(0, 1);
28731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].even		= (m_attribData[ndx*2 + 1].y() == 1.0f); // is green
28747d6ad9e003b52cfc23626b216b7580babf423c8fPyry Haulos		currentPoints[ndx].size		= ((m_isWidePointCase) ? ((currentPoints[ndx].even) ? 5 : 3) : 1);
28751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
28761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// tessellation
28781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
28791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<GeneratedPoint> tessellatedPoints;
28811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tessellatedPoints.resize(currentPoints.size() * 4);
28831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
28841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
28851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec2 position = tcu::Vec2(currentPoints[ndx].center.x(), 1.0f - currentPoints[ndx].center.y()); // mirror Y
28861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].center	= position + tcu::Vec2(-0.07f, -0.07f);
28881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].size		= currentPoints[ndx].size;
28891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].even		= currentPoints[ndx].even;
28901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].center	= position + tcu::Vec2( 0.07f, -0.07f);
28921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].size		= currentPoints[ndx].size;
28931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].even		= currentPoints[ndx].even;
28941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].center	= position + tcu::Vec2( 0.07f,  0.07f);
28961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].size		= currentPoints[ndx].size;
28971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].even		= currentPoints[ndx].even;
28981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].center	= position + tcu::Vec2(-0.07f,  0.07f);
29001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].size		= currentPoints[ndx].size;
29011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].even		= currentPoints[ndx].even;
29021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
29031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints.swap(tessellatedPoints);
29051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// geometry
29081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasGeometryStage)
29091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<GeneratedPoint> geometryShadedPoints;
29111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		geometryShadedPoints.resize(currentPoints.size() * 3);
29131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
29151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec2 position = tcu::Vec2(1.0f - currentPoints[ndx].center.x(), currentPoints[ndx].center.y()); // mirror X
29161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].center	= position + tcu::Vec2( 0.05f,  0.03f);
29181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].size		= currentPoints[ndx].size;
29191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].even		= currentPoints[ndx].even;
29201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].center	= position + tcu::Vec2(-0.01f, -0.02f);
29221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].size		= currentPoints[ndx].size;
29231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].even		= currentPoints[ndx].even;
29241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].center	= position + tcu::Vec2(-0.05f,  0.02f);
29261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].size		= currentPoints[ndx].size;
29271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].even		= currentPoints[ndx].even;
29281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
29291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints.swap(geometryShadedPoints);
29311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// sort from left to right, top to bottom
29341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::sort(currentPoints.begin(), currentPoints.end(), PointSorter());
29351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// map to pattern space
29371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].center = currentPoints[ndx].center * config.patternSize + config.patternPos;
29391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	currentPoints.swap(data);
29411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
29421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyNarrowPointPattern (const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter)
29441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
29451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool anyError = false;
29461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// check that there is something near each sample
29481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int pointNdx = 0; pointNdx < (int)refPoints.size(); ++pointNdx)
29491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float				epsilon		= 1.0e-6f;
29511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const GeneratedPoint&	refPoint	= refPoints[pointNdx];
29521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// skip points not in the the bbox, treat boundary as "in"
29541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (refPoint.center.x() < bbox.min.x() - epsilon ||
29551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() < bbox.min.y() - epsilon ||
29561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.x() > bbox.max.x() + epsilon ||
29571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() > bbox.max.y() + epsilon)
29581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			continue;
29591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
29601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
29611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// transform to viewport coords
29627a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			const tcu::IVec2 pixelCenter(deRoundFloatToInt32((refPoint.center.x() * 0.5f + 0.5f) * (float)viewport.getWidth()),
29637a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry										 deRoundFloatToInt32((refPoint.center.y() * 0.5f + 0.5f) * (float)viewport.getHeight()));
29641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// find rasterized point in the result
29661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixelCenter.x() < 1 || pixelCenter.y() < 1 || pixelCenter.x() >= viewport.getWidth()-1 || pixelCenter.y() >= viewport.getHeight()-1)
29671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
29681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// viewport boundary, assume point is fine
29691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
29701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
29711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
29721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	componentNdx	= (refPoint.even) ? (1) : (2); // analyze either green or blue channel
29731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bool		foundResult		= false;
29741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// check neighborhood
29761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int dy = -1; dy < 2 && !foundResult; ++dy)
29771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int dx = -1; dx < 2 && !foundResult; ++dx)
29781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
29791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const tcu::IVec2	testPos	(pixelCenter.x() + dx, pixelCenter.y() + dy);
29801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const tcu::RGBA		color	= viewport.getPixel(testPos.x(), testPos.y());
29811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (color.toIVec()[componentNdx] > 0)
29831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						foundResult = true;
29841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
29851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (!foundResult)
29871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
29881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					anyError = true;
29891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (--logFloodCounter >= 0)
29911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					{
29921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						m_testCtx.getLog()
29931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< tcu::TestLog::Message
29941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< "Missing point near " << pixelCenter << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
29951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< tcu::TestLog::EndMessage;
29961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					}
29971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
29981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
29991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return anyError;
30031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
30041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyWidePointPattern (const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter)
30061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
30071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool anyError = false;
30081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// check that there is something near each sample
30101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int pointNdx = 0; pointNdx < (int)refPoints.size(); ++pointNdx)
30111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const GeneratedPoint& refPoint = refPoints[pointNdx];
30131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (refPoint.center.x() >= bbox.min.x() &&
30151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() >= bbox.min.y() &&
30161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.x() <= bbox.max.x() &&
30171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() <= bbox.max.y())
30181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// point fully in the bounding box
30201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError |= !verifyWidePoint(viewport, refPoint, bbox, POINT_FULL, logFloodCounter);
30211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30227a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		else if (refPoint.center.x() >= bbox.min.x() + (float)refPoint.size / 2.0f &&
30237a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.y() >= bbox.min.y() - (float)refPoint.size / 2.0f &&
30247a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.x() <= bbox.max.x() + (float)refPoint.size / 2.0f &&
30257a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.y() <= bbox.max.y() - (float)refPoint.size / 2.0f)
30261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// point leaks into bounding box
30281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError |= !verifyWidePoint(viewport, refPoint, bbox, POINT_PARTIAL, logFloodCounter);
30291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return anyError;
30331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
30341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyWidePoint (const tcu::Surface& viewport, const GeneratedPoint& refPoint, const ProjectedBBox& bbox, ResultPointType pointType, int& logFloodCounter)
30361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
30371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			componentNdx		= (refPoint.even) ? (1) : (2);
30381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			halfPointSizeCeil	= (refPoint.size + 1) / 2;
30391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			halfPointSizeFloor	= (refPoint.size + 1) / 2;
30407d6ad9e003b52cfc23626b216b7580babf423c8fPyry Haulos	const tcu::IVec4	viewportBBoxArea	= getViewportBoundingBoxArea(bbox, tcu::IVec2(viewport.getWidth(), viewport.getHeight()), (float)refPoint.size);
30411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4	verificationArea	= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
30421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::max(viewportBBoxArea.y(), 0),
30431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::min(viewportBBoxArea.z(), viewport.getWidth()),
30441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::min(viewportBBoxArea.w(), viewport.getHeight()));
30457a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	pointPos			= tcu::IVec2(deRoundFloatToInt32((refPoint.center.x()*0.5f + 0.5f) * (float)viewport.getWidth()),
30467a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry														 deRoundFloatToInt32((refPoint.center.y()*0.5f + 0.5f) * (float)viewport.getHeight()));
30471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// find any fragment within the point that is inside the bbox, start search at the center
30491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (pointPos.x() >= verificationArea.x() &&
30511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() >= verificationArea.y() &&
30521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.x() < verificationArea.z() &&
30531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() < verificationArea.w())
30541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(pointPos.x(), pointPos.y()).toIVec()[componentNdx])
30561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return verifyWidePointAt(pointPos, viewport, refPoint, verificationArea, pointType, componentNdx, logFloodCounter);
30571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int dy = -halfPointSizeCeil; dy <= halfPointSizeCeil; ++dy)
30601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int dx = -halfPointSizeCeil; dx <= halfPointSizeCeil; ++dx)
30611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2 testPos = pointPos + tcu::IVec2(dx, dy);
30631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (dx == 0 && dy == 0)
30651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			continue;
30661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (testPos.x() >= verificationArea.x() &&
30681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.y() >= verificationArea.y() &&
30691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.x() < verificationArea.z() &&
30701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.y() < verificationArea.w())
30711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (viewport.getPixel(testPos.x(), testPos.y()).toIVec()[componentNdx])
30731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return verifyWidePointAt(testPos, viewport, refPoint, verificationArea, pointType, componentNdx, logFloodCounter);
30741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// could not find point, this is only ok near boundaries
30781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (pointPos.x() + halfPointSizeFloor <  verificationArea.x() - 1 ||
30791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() + halfPointSizeFloor <  verificationArea.y() - 1 ||
30801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.x() - halfPointSizeFloor >= verificationArea.z() - 1 ||
30811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() - halfPointSizeFloor >= verificationArea.w() - 1)
30821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
30831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--logFloodCounter >= 0)
30851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
30871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
30881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Missing wide point near " << pointPos << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
30891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
30901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
30931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
30941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyWidePointAt (const tcu::IVec2& pointPos, const tcu::Surface& viewport, const GeneratedPoint& refPoint, const tcu::IVec4& bbox, ResultPointType pointType, int componentNdx, int& logFloodCounter)
30961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
30971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				expectedPointSize		= refPoint.size;
30981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					viewportClippedTop		= false;
30991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					viewportClippedBottom	= false;
31001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					primitiveClippedTop		= false;
31011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					primitiveClippedBottom	= false;
31021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widthsUpwards;
31031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widthsDownwards;
31041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widths;
31051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// search upwards
31071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = pointPos.y();; --y)
31081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (y < bbox.y() || y < 0)
31101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y < bbox.y())
31121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				primitiveClippedTop = true;
31131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y < 0)
31141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				viewportClippedTop = true;
31151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (pointPos.y() - y > expectedPointSize)
31181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no need to go further than point height
31201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (viewport.getPixel(pointPos.x(), y).toIVec()[componentNdx] == 0)
31231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
31271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			widthsUpwards.push_back(scanPointWidthAt(tcu::IVec2(pointPos.x(), y), viewport, expectedPointSize, componentNdx));
31291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// top is clipped
31331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((viewportClippedTop || (pointType == POINT_PARTIAL && primitiveClippedTop)) && !widthsUpwards.empty())
31341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2&	range			= widthsUpwards.back();
31361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			squareFits		= (range.y() - range.x() + 1) >= expectedPointSize;
31371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			widthClipped	= (pointType == POINT_PARTIAL) && (range.x() <= bbox.x() || range.y() >= bbox.z());
31381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (squareFits || widthClipped)
31401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
31411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// and downwards
31441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = pointPos.y()+1;; ++y)
31451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (y >= bbox.w() || y >= viewport.getHeight())
31471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y >= bbox.w())
31491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				primitiveClippedBottom = true;
31501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y >= viewport.getHeight())
31511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				viewportClippedBottom = true;
31521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (y - pointPos.y() > expectedPointSize)
31551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no need to go further than point height
31571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (viewport.getPixel(pointPos.x(), y).toIVec()[componentNdx] == 0)
31601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
31641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			widthsDownwards.push_back(scanPointWidthAt(tcu::IVec2(pointPos.x(), y), viewport, expectedPointSize, componentNdx));
31661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// bottom is clipped
31701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((viewportClippedBottom || (pointType == POINT_PARTIAL && primitiveClippedBottom)) && !(widthsDownwards.empty() && widthsUpwards.empty()))
31711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2&	range			= (widthsDownwards.empty()) ? (widthsUpwards.front()) : (widthsDownwards.back());
31731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			squareFits		= (range.y() - range.x() + 1) >= expectedPointSize;
31741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			bboxClipped		= (pointType == POINT_PARTIAL) && (range.x() <= bbox.x() || range.y() >= bbox.z()-1);
31751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			viewportClipped	= range.x() <= 0 || range.y() >= viewport.getWidth()-1;
31761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (squareFits || bboxClipped || viewportClipped)
31781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
31791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// would square point would fit into the rasterized area
31821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)widthsUpwards.size(); ++ndx)
31841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		widths.push_back(widthsUpwards[(int)widthsUpwards.size() - ndx - 1]);
31851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)widthsDownwards.size(); ++ndx)
31861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		widths.push_back(widthsDownwards[ndx]);
31871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(!widths.empty());
31881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < (int)widths.size() - expectedPointSize + 1; ++y)
31901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2 unionRange = widths[y];
31921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int dy = 1; dy < expectedPointSize; ++dy)
31941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			unionRange.x() = de::max(unionRange.x(), widths[y+dy].x());
31961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			unionRange.y() = de::min(unionRange.y(), widths[y+dy].y());
31971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// would a N x N block fit here?
32001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
32011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool squareFits		= (unionRange.y() - unionRange.x() + 1) >= expectedPointSize;
32021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool bboxClipped		= (pointType == POINT_PARTIAL) && (unionRange.x() <= bbox.x() || unionRange.y() >= bbox.z()-1);
32031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool viewportClipped	= unionRange.x() <= 0 || unionRange.y() >= viewport.getWidth()-1;
32041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (squareFits || bboxClipped || viewportClipped)
32061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return true;
32071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
32081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--logFloodCounter >= 0)
32111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
32131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
32141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Missing " << expectedPointSize << "x" << expectedPointSize << " point near " << pointPos << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
32151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
32161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
32181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
32191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 PointRenderCase::scanPointWidthAt (const tcu::IVec2& pointPos, const tcu::Surface& viewport, int expectedPointSize, int componentNdx) const
32211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
32221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int minX = pointPos.x();
32231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int maxX = pointPos.x();
32241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// search horizontally for a point edges
32261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = pointPos.x()-1; x >= 0; --x)
32271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(x, pointPos.y()).toIVec()[componentNdx] == 0)
32291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// no need to go further than point width
32321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pointPos.x() - x > expectedPointSize)
32331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		minX = x;
32361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = pointPos.x()+1; x < viewport.getWidth(); ++x)
32381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(x, pointPos.y()).toIVec()[componentNdx] == 0)
32401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// no need to go further than point width
32431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (x - pointPos.x() > expectedPointSize)
32441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		maxX = x;
32471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(minX, maxX);
32501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
32511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass BlitFboCase : public TestCase
32531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
32541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
32551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum RenderTarget
32561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_DEFAULT = 0,
32581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_FBO,
32591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_LAST
32611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
32621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							BlitFboCase						(Context& context, const char* name, const char* description, RenderTarget src, RenderTarget dst);
32641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							~BlitFboCase					(void);
32651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
32671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
32681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FBO_SIZE = 256,
32701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
32711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct BlitArgs
32731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec4	src;
32751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec4	dst;
32761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMin;
32771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMax;
32781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool		linear;
32791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
32801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init					(void);
32821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit					(void);
32831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate					(void);
32841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							fillSourceWithPattern	(void);
32861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage				(const BlitArgs& args);
32871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_src;
32891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_dst;
32901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<BlitArgs>			m_iterations;
32921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_iteration;
32931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_srcFbo;
32941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_dstFbo;
32951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Renderbuffer>	m_srcRbo;
32961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Renderbuffer>	m_dstRbo;
32971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
32981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
32991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
33001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::BlitFboCase (Context& context, const char* name, const char* description, RenderTarget src, RenderTarget dst)
33021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
33031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_src			(src)
33041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_dst			(dst)
33051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_iteration	(0)
33061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(src < TARGET_LAST);
33081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(dst < TARGET_LAST);
33091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
33101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::~BlitFboCase (void)
33121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
33141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
33151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::init (void)
33171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numIterations			= 12;
33191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				defaultFBMultisampled	= (m_context.getRenderTarget().getNumSamples() > 1);
33201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
33211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd						(0xABC123);
33221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
33241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
33251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Using BlitFramebuffer to blit area from "
33261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_src == TARGET_DEFAULT) ? ("default fb") : ("fbo"))
33271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< " to "
33281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_dst == TARGET_DEFAULT) ? ("default fb") : ("fbo"))
33291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
33301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Varying blit arguments and primitive bounding box between iterations.\n"
33311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting bounding box to have no effect on blitting.\n"
33321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Source framebuffer is filled with green-yellow grid.\n"
33331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
33341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
33361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
33371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_dst == TARGET_DEFAULT && defaultFBMultisampled)
33381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires non-multisampled default framebuffer");
33391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
33411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_src == TARGET_FBO)
33431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_srcRbo = de::MovePtr<glu::Renderbuffer>(new glu::Renderbuffer(m_context.getRenderContext()));
33451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindRenderbuffer(GL_RENDERBUFFER, **m_srcRbo);
33461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, FBO_SIZE, FBO_SIZE);
33471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "src rbo");
33481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_srcFbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
33501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_FRAMEBUFFER, **m_srcFbo);
33511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, **m_srcRbo);
33521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "src fbo");
33531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
33541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_dst == TARGET_FBO)
33561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_dstRbo = de::MovePtr<glu::Renderbuffer>(new glu::Renderbuffer(m_context.getRenderContext()));
33581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindRenderbuffer(GL_RENDERBUFFER, **m_dstRbo);
33591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, FBO_SIZE, FBO_SIZE);
33601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "dst rbo");
33611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_dstFbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
33631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_FRAMEBUFFER, **m_dstFbo);
33641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, **m_dstRbo);
33651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "dst fbo");
33661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
33671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const char* const s_vertexSource =	"#version 310 es\n"
33701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"in highp vec4 a_position;\n"
33711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"out highp vec4 v_position;\n"
33721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"void main()\n"
33731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"{\n"
33741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	gl_Position = a_position;\n"
33751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	v_position = a_position;\n"
33761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"}\n";
33771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const char* const s_fragmentSource =	"#version 310 es\n"
33781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"in mediump vec4 v_position;\n"
33791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"layout(location=0) out mediump vec4 dEQP_FragColor;\n"
33801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"void main()\n"
33811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"{\n"
33821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	const mediump vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
33831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	const mediump vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
33841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	dEQP_FragColor = (step(0.1, mod(v_position.x, 0.2)) == step(0.1, mod(v_position.y, 0.2))) ? (green) : (yellow);\n"
33851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"}\n";
33861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_vertexSource) << glu::FragmentSource(s_fragmentSource)));
33881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
33901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
33911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
33921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
33931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
33941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
33951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const tcu::Vec4 s_quadCoords[] =
33981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
33991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
34001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
34011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
34021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
34031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
34041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
34061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
34081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_quadCoords), s_quadCoords, GL_STATIC_DRAW);
34091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "set buf");
34101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
34111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// gen iterations
34131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
34151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2 srcSize = (m_src == TARGET_DEFAULT) ? (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) : (tcu::IVec2(FBO_SIZE, FBO_SIZE));
34161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2 dstSize = (m_dst == TARGET_DEFAULT) ? (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) : (tcu::IVec2(FBO_SIZE, FBO_SIZE));
34171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
34191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
34201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "srcSize = " << srcSize << "\n"
34211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "dstSize = " << dstSize << "\n"
34221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
34231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < numIterations; ++ndx)
34251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
34261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BlitArgs args;
34271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (m_src == TARGET_DEFAULT && defaultFBMultisampled)
34291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
34301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const tcu::IVec2	unionSize	= tcu::IVec2(de::min(srcSize.x(), dstSize.x()), de::min(srcSize.y(), dstSize.y()));
34311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcWidth	= rnd.getInt(1, unionSize.x());
34321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcHeight	= rnd.getInt(1, unionSize.y());
34331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcX		= rnd.getInt(0, unionSize.x() - srcWidth);
34341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcY		= rnd.getInt(0, unionSize.y() - srcHeight);
34351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.x() = srcX;
34371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.y() = srcY;
34381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.z() = srcX + srcWidth;
34391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.w() = srcY + srcHeight;
34401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst = args.src;
34421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
34431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
34441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
34451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcWidth	= rnd.getInt(1, srcSize.x());
34461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcHeight	= rnd.getInt(1, srcSize.y());
34471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcX		= rnd.getInt(0, srcSize.x() - srcWidth);
34481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcY		= rnd.getInt(0, srcSize.y() - srcHeight);
34491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstWidth	= rnd.getInt(1, dstSize.x());
34501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstHeight	= rnd.getInt(1, dstSize.y());
34511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstX		= rnd.getInt(-(dstWidth / 2), dstSize.x() - (dstWidth+1) / 2);		// allow dst go out of bounds
34521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstY		= rnd.getInt(-(dstHeight / 2), dstSize.y() - (dstHeight+1)  / 2);
34531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.x() = srcX;
34551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.y() = srcY;
34561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.z() = srcX + srcWidth;
34571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.w() = srcY + srcHeight;
34581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.x() = dstX;
34591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.y() = dstY;
34601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.z() = dstX + dstWidth;
34611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.w() = dstY + dstHeight;
34621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
34631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.x() = rnd.getFloat(-1.1f, 1.1f);
34651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.y() = rnd.getFloat(-1.1f, 1.1f);
34661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.z() = rnd.getFloat(-1.1f, 1.1f);
34671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.w() = rnd.getFloat( 0.9f, 1.1f);
34681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.x() = rnd.getFloat(-1.1f, 1.1f);
34701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.y() = rnd.getFloat(-1.1f, 1.1f);
34711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.z() = rnd.getFloat(-1.1f, 1.1f);
34721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.w() = rnd.getFloat( 0.9f, 1.1f);
34731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.x() / args.bboxMin.w() > args.bboxMax.x() / args.bboxMax.w())
34751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.x(), args.bboxMax.x());
34761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.y() / args.bboxMin.w() > args.bboxMax.y() / args.bboxMax.w())
34771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.y(), args.bboxMax.y());
34781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.z() / args.bboxMin.w() > args.bboxMax.z() / args.bboxMax.w())
34791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.z(), args.bboxMax.z());
34801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.linear = rnd.getBool();
34821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_iterations.push_back(args);
34841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
34851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
34861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
34871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::deinit (void)
34891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
34901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_srcFbo.clear();
34911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_srcRbo.clear();
34921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_dstFbo.clear();
34931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_dstRbo.clear();
34941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
34951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
34961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
34971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::IterateResult BlitFboCase::iterate (void)
34991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
35001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Iteration" + de::toString(m_iteration), "Iteration " + de::toString(m_iteration+1) + " / " + de::toString((int)m_iterations.size()));
35011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BlitArgs&				blitCfg		= m_iterations[m_iteration];
35021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
35031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_iteration == 0)
35051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
35061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fill source with test pattern. Default fb must be filled for each iteration because contents might not survive the swap
35081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_src == TARGET_DEFAULT || m_iteration == 0)
35091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		fillSourceWithPattern();
35101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
35121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
35131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box:\n"
35141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "\tmin:" << blitCfg.bboxMin << "\n"
35151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "\tmax:" << blitCfg.bboxMax << "\n"
35161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Blit:\n"
35171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tsrc: " << blitCfg.src << "\n"
35181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tdst: " << blitCfg.dst << "\n"
35191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tfilter: " << ((blitCfg.linear) ? ("linear") : ("nearest"))
35201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
35211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3522485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe	gl.primitiveBoundingBox(blitCfg.bboxMin.x(), blitCfg.bboxMin.y(), blitCfg.bboxMin.z(), blitCfg.bboxMin.w(),
3523485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe							blitCfg.bboxMax.x(), blitCfg.bboxMax.y(), blitCfg.bboxMax.z(), blitCfg.bboxMax.w());
35241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, (m_dst == TARGET_FBO) ? (**m_dstFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
35271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
35281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, (m_src == TARGET_FBO) ? (**m_srcFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blitFramebuffer(blitCfg.src.x(), blitCfg.src.y(), blitCfg.src.z(), blitCfg.src.w(),
35311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   blitCfg.dst.x(), blitCfg.dst.y(), blitCfg.dst.z(), blitCfg.dst.w(),
35321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   GL_COLOR_BUFFER_BIT,
35331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   ((blitCfg.linear) ? (GL_LINEAR) : (GL_NEAREST)));
35341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "blit");
35351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImage(blitCfg))
35371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected blit result");
35381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return (++m_iteration == (int)m_iterations.size()) ? (STOP) : (CONTINUE);
35401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
35411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool BlitFboCase::verifyImage (const BlitArgs& args)
35431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
35441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				colorThreshold	= 4; //!< this test case is not about how color is preserved, allow almost anything
35451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		dstSize			= (m_dst == TARGET_DEFAULT) ? (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) : (tcu::IVec2(FBO_SIZE, FBO_SIZE));
35461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
35471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewport		(dstSize.x(), dstSize.y());
35481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			errorMask		(dstSize.x(), dstSize.y());
35491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					anyError		= false;
35501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
35521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
35531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying blit result"
35541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
35551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, (m_dst == TARGET_FBO) ? (**m_dstFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, viewport.getAccess());
35581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0, 0, 0, 255));
35601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < dstSize.y(); ++y)
35621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < dstSize.x(); ++x)
35631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
35641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA color	= viewport.getPixel(x, y);
35651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		inside	= (x >= args.dst.x() && x < args.dst.z() && y >= args.dst.y() && y < args.dst.w());
35661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		error	= (inside) ? (color.getGreen() < 255 - colorThreshold || color.getBlue() > colorThreshold)
35671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry										   : (color.getRed() > colorThreshold || color.getGreen() > colorThreshold || color.getBlue() > colorThreshold);
35681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
35701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
35711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
3572c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
35731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
35741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
35751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
35771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
35781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
35791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
35801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
35811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
35821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
35831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
35841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
35851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
35861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return false;
35871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
35881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
35891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
35901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
35911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
35921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result image ok."
359330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
359430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
359530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
359630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
35971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
35981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
35991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
36001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::fillSourceWithPattern (void)
36021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
36031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
36041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		srcSize		= (m_src == TARGET_DEFAULT) ? (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) : (tcu::IVec2(FBO_SIZE, FBO_SIZE));
36051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				posLocation	= gl.getAttribLocation(m_program->getProgram(), "a_position");
36061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, (m_src == TARGET_FBO) ? (**m_srcFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
36081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, srcSize.x(), srcSize.y());
36091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
36101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
36121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
36131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
36151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 4 * (int)sizeof(float), NULL);
36161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
36171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
36181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
36191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass DepthDrawCase : public TestCase
36211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
36221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
36231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum DepthType
36241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_BUILTIN = 0,
36261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_USER_DEFINED,
36271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_LAST
36291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxState
36311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_GLOBAL = 0,
36331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_PER_PRIMITIVE,
36341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_LAST
36361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxSize
36381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_EQUAL = 0,
36401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_LARGER,
36411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_LAST
36431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									DepthDrawCase					(Context& context, const char* name, const char* description, DepthType depthType, BBoxState state, BBoxSize bboxSize);
36461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~DepthDrawCase					(void);
36471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
36491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
36501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
36511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
36521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
36541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
36551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(void) const;
36561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
36571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							generateAttributeData			(std::vector<tcu::Vec4>& data) const;
36581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage						(const tcu::Surface& viewport) const;
36591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
36611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDER_AREA_SIZE = 256,
36631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct LayerInfo
36661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		float		zOffset;
36681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		float		zScale;
36691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	color1;
36701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	color2;
36711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_numLayers;
36741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_gridSize;
36751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const DepthType					m_depthType;
36771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxState					m_state;
36781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxSize					m_bboxSize;
36791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
36811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
36821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<LayerInfo>			m_layers;
36831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
36841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::DepthDrawCase (Context& context, const char* name, const char* description, DepthType depthType, BBoxState state, BBoxSize bboxSize)
36861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
36871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numLayers	(14)
36881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_gridSize	(24)
36891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_depthType	(depthType)
36901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_state		(state)
36911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_bboxSize	(bboxSize)
36921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
36931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(depthType < DEPTH_LAST);
36941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(state < STATE_LAST);
36951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(bboxSize < BBOX_LAST);
36961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
36971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::~DepthDrawCase (void)
36991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
37011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
37021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::init (void)
37041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
37061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// requirements
37081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
37101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
37111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_state == STATE_PER_PRIMITIVE && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
37121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
37131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_context.getRenderTarget().getDepthBits() == 0)
37141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires depth buffer");
37151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_context.getRenderTarget().getWidth() < RENDER_AREA_SIZE || m_context.getRenderTarget().getHeight() < RENDER_AREA_SIZE)
37161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_AREA_SIZE) + "x" + de::toString<int>(RENDER_AREA_SIZE) + " viewport");
37171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// log
37191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
37201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
37211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering multiple triangle grids with with different z coordinates.\n"
37221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Topmost grid is green-yellow, other grids are blue-red.\n"
37231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting only the green-yellow grid to be visible.\n"
37241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting primitive bounding box "
37251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_bboxSize == BBOX_EQUAL) ? ("to exactly cover") : ("to cover"))
37261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_state == STATE_GLOBAL) ? (" each grid") : (" each triangle"))
37271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_bboxSize == BBOX_EQUAL) ? (".") : (" and include some padding."))
37281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
37291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
37301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_state == STATE_GLOBAL) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
37311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
37321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_depthType == DEPTH_USER_DEFINED) ? ("Fragment depth is set in the fragment shader") : (""))
37331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
37341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
37361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::ProgramSources sources;
37391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		sources << glu::VertexSource(genVertexSource());
37401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		sources << glu::FragmentSource(genFragmentSource());
37411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_state == STATE_PER_PRIMITIVE)
37431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			sources << glu::TessellationControlSource(genTessellationControlSource())
37441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::TessellationEvaluationSource(genTessellationEvaluationSource());
37451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), sources));
37471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "build program");
37481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
37501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::ScopedLogSection section(m_testCtx.getLog(), "ShaderProgram", "Shader program");
37511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
37521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
37531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
37551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
37561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
37571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<tcu::Vec4> data;
37601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		generateAttributeData(data);
37621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
37641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
37651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, (int)(sizeof(tcu::Vec4) * data.size()), &data[0], GL_STATIC_DRAW);
37661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "buf upload");
37671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
37681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// gen layers
37701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		de::Random rnd(0x12345);
37721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_layers.resize(m_numLayers);
37741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
37751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
37767a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_layers[layerNdx].zOffset	= ((float)layerNdx / (float)m_numLayers) * 2.0f - 1.0f;
37777a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_layers[layerNdx].zScale	= (2.0f / (float)m_numLayers);
37781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_layers[layerNdx].color1	= (layerNdx == 0) ? (tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)) : (tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
37791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_layers[layerNdx].color2	= (layerNdx == 0) ? (tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f)) : (tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
37801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
37811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		rnd.shuffle(m_layers.begin(), m_layers.end());
37821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
37831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
37841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::deinit (void)
37861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
37881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
37891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
37901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::IterateResult DepthDrawCase::iterate (void)
37921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				hasTessellation		= (m_state == STATE_PER_PRIMITIVE);
37941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
37951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation			= gl.getAttribLocation(m_program->getProgram(), "a_position");
37961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		colLocation			= gl.getAttribLocation(m_program->getProgram(), "a_colorMix");
37971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		depthBiasLocation	= gl.getUniformLocation(m_program->getProgram(), "u_depthBias");
37981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		depthScaleLocation	= gl.getUniformLocation(m_program->getProgram(), "u_depthScale");
37991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		color1Location		= gl.getUniformLocation(m_program->getProgram(), "u_color1");
38001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		color2Location		= gl.getUniformLocation(m_program->getProgram(), "u_color2");
38011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewport			(RENDER_AREA_SIZE, RENDER_AREA_SIZE);
38031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd					(0x213237);
38041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posLocation != -1);
38061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(colLocation != -1);
38071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(depthBiasLocation != -1);
38081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(depthScaleLocation != -1);
38091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(color1Location != -1);
38101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(color2Location != -1);
38111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, RENDER_AREA_SIZE, RENDER_AREA_SIZE);
38131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
38141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearDepthf(1.0f);
38151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.depthFunc(GL_LESS);
38161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_DEPTH_TEST);
38171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
38181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup viewport");
38191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
38211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, (int)(8 * sizeof(float)), (const float*)DE_NULL);
38221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(colLocation, 4, GL_FLOAT, GL_FALSE, (int)(8 * sizeof(float)), (const float*)DE_NULL + 4);
38231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
38241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(colLocation);
38251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
38261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup va");
38271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (hasTessellation)
38291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
38301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
38321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
38331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(depthBiasLocation, m_layers[layerNdx].zOffset);
38341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(depthScaleLocation, m_layers[layerNdx].zScale);
38351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4fv(color1Location, 1, m_layers[layerNdx].color1.getPtr());
38361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4fv(color2Location, 1, m_layers[layerNdx].color2.getPtr());
38371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_state == STATE_GLOBAL)
38391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
38401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float negPadding = (m_bboxSize == BBOX_EQUAL) ? (0.0f) : (rnd.getFloat() * 0.3f);
38411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posPadding = (m_bboxSize == BBOX_EQUAL) ? (0.0f) : (rnd.getFloat() * 0.3f);
38421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3843485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe			gl.primitiveBoundingBox(-1.0f, -1.0f, m_layers[layerNdx].zOffset - negPadding, 1.0f,
3844485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe									1.0f,  1.0f, (m_layers[layerNdx].zOffset + m_layers[layerNdx].zScale + posPadding), 1.0f);
38451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
38461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.drawArrays((hasTessellation) ? (GL_PATCHES) : (GL_TRIANGLES), 0, m_gridSize * m_gridSize * 6);
38481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
38491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, viewport.getAccess());
38511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "render and read");
38521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (verifyImage(viewport))
38541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
38551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
38561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
38571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
38591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
38601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genVertexSource (void) const
38621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
38631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			hasTessellation	= (m_state == STATE_PER_PRIMITIVE);
38641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
38651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
38671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
38681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_colorMix;\n"
38691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_colorMix;\n";
38701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!hasTessellation && m_depthType == DEPTH_USER_DEFINED)
38721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "out highp float v_fragDepth;\n";
38731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!hasTessellation)
38751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp float u_depthBias;\n"
38761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp float u_depthScale;\n";
38771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
38791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
38801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n";
38811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (hasTessellation)
38831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_Position = a_position;\n";
38841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (m_depthType == DEPTH_USER_DEFINED)
38851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float dummyZ = a_position.z;\n"
38861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float writtenZ = a_position.w;\n"
38871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(a_position.xy, dummyZ, 1.0);\n"
38881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_fragDepth = writtenZ * u_depthScale + u_depthBias;\n";
38891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
38901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float writtenZ = a_position.w;\n"
38911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(a_position.xy, writtenZ * u_depthScale + u_depthBias, 1.0);\n";
38921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vtx_colorMix = a_colorMix;\n"
38941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
38951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
38971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
38981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genFragmentSource (void) const
39001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			hasTessellation	= (m_state == STATE_PER_PRIMITIVE);
39021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorMixName	= (hasTessellation) ? ("tess_eval_colorMix") : ("vtx_colorMix");
39031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
39061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorMixName << ";\n";
39071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "in mediump float v_fragDepth;\n";
39101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"layout(location = 0) out mediump vec4 o_color;\n"
39121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_color1;\n"
39131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_color2;\n"
39141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
39171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = mix(u_color1, u_color2, " << colorMixName << ");\n";
39181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_FragDepth = v_fragDepth * 0.5 + 0.5;\n";
39211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
39231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
39251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
39261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genTessellationControlSource (void) const
39281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
39321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
39331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_primitive_bounding_box : require\n"
39341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
39351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthBias;\n"
39371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthScale;\n"
39381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_colorMix[];\n"
39401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_colorMix[];\n"
39411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
39441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
39451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_colorMix[gl_InvocationID] = vtx_colorMix[0];\n"
39461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
39481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
39491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
39501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
39511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// real Z stored in w component\n"
39531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 minBound = vec4(min(min(vec3(gl_in[0].gl_Position.xy, gl_in[0].gl_Position.w * u_depthScale + u_depthBias),\n"
39541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                                   vec3(gl_in[1].gl_Position.xy, gl_in[1].gl_Position.w * u_depthScale + u_depthBias)),\n"
39551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                               vec3(gl_in[2].gl_Position.xy, gl_in[2].gl_Position.w * u_depthScale + u_depthBias)), 1.0);\n"
39561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 maxBound = vec4(max(max(vec3(gl_in[0].gl_Position.xy, gl_in[0].gl_Position.w * u_depthScale + u_depthBias),\n"
39571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                                   vec3(gl_in[1].gl_Position.xy, gl_in[1].gl_Position.w * u_depthScale + u_depthBias)),\n"
39581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                               vec3(gl_in[2].gl_Position.xy, gl_in[2].gl_Position.w * u_depthScale + u_depthBias)), 1.0);\n";
39591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOX_EQUAL)
39611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	gl_BoundingBoxEXT[0] = minBound;\n"
39621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[1] = maxBound;\n";
39631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
39641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float nedPadding = mod(gl_in[0].gl_Position.z, 0.3);\n"
39651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float posPadding = mod(gl_in[1].gl_Position.z, 0.3);\n"
39661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[0] = minBound - vec4(0.0, 0.0, nedPadding, 0.0);\n"
39671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_BoundingBoxEXT[1] = maxBound + vec4(0.0, 0.0, posPadding, 0.0);\n";
39681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
39701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
39721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
39731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genTessellationEvaluationSource (void) const
39751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
39791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
39801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_gpu_shader5 : require\n"
39811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
39821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_colorMix[];\n"
39841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_eval_colorMix;\n";
39851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "out highp float v_fragDepth;\n";
39881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"uniform highp float u_depthBias;\n"
39901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthScale;\n"
39911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"precise gl_Position;\n"
39931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
39961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 tessellatedPos = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n";
39971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float dummyZ = tessellatedPos.z;\n"
40001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float writtenZ = tessellatedPos.w;\n"
40011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(tessellatedPos.xy, dummyZ, 1.0);\n"
40021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_fragDepth = writtenZ * u_depthScale + u_depthBias;\n";
40031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
40041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float writtenZ = tessellatedPos.w;\n"
40051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(tessellatedPos.xy, writtenZ * u_depthScale + u_depthBias, 1.0);\n";
40061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	tess_eval_colorMix = tess_ctrl_colorMix[0];\n"
40081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
40091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
40111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::generateAttributeData (std::vector<tcu::Vec4>& data) const
40141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		color1				(0.0f, 0.0f, 0.0f, 0.0f); // mix weights
40161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		color2				(1.0f, 1.0f, 1.0f, 1.0f);
40171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder			(m_gridSize * m_gridSize);
40181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd					(0xAB54321);
40191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with cells in random order
40211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
40221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
40231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
40241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(m_gridSize * m_gridSize * 6 * 2);
40261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
40271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
40281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
40291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= cellNdx % m_gridSize;
40301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= cellNdx / m_gridSize;
40311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec4&	cellColor	= ((cellX+cellY)%2 == 0) ? (color1) : (color2);
40321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40337a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 +  0] = tcu::Vec4(float(cellX+0) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+0) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 +  1] = cellColor;
40347a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 +  2] = tcu::Vec4(float(cellX+1) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+1) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 +  3] = cellColor;
40357a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 +  4] = tcu::Vec4(float(cellX+0) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+1) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 +  5] = cellColor;
40367a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 +  6] = tcu::Vec4(float(cellX+0) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+0) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 +  7] = cellColor;
40377a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 +  8] = tcu::Vec4(float(cellX+1) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+0) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 +  9] = cellColor;
40387a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		data[ndx * 6 * 2 + 10] = tcu::Vec4(float(cellX+1) / float(m_gridSize) * 2.0f - 1.0f, float(cellY+1) / float(m_gridSize) * 2.0f - 1.0f, 0.0f, 0.0f);	data[ndx * 6 * 2 + 11] = cellColor;
40391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// Fill Z with random values (fake Z)
40411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vtxNdx = 0; vtxNdx < 6; ++vtxNdx)
40421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[ndx * 6 * 2 + 2*vtxNdx].z() = rnd.getFloat(0.0f, 1.0);
40431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// Fill W with other random values (written Z)
40451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vtxNdx = 0; vtxNdx < 6; ++vtxNdx)
40461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[ndx * 6 * 2 + 2*vtxNdx].w() = rnd.getFloat(0.0f, 1.0);
40471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
40481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool DepthDrawCase::verifyImage (const tcu::Surface& viewport) const
40511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(viewport.getWidth(), viewport.getHeight());
40531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
40541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0,0,0,255));
40561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < viewport.getHeight(); ++y)
40581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < viewport.getWidth(); ++x)
40591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
40601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA	pixel		= viewport.getPixel(x, y);
40611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool			error		= false;
40621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// expect green, yellow or a combination of these
40641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pixel.getGreen() != 255 || pixel.getBlue() != 0)
40651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			error = true;
40661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
40681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4069c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
40701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
40711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
40721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
40731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
40751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
40761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
40771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
40781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
40791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
40801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
40811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
40821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
40831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
40841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
40851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
40861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result image ok."
408730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
408830fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
408930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
409030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
40911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
40931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass ClearCase : public TestCase
40961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
40981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
40991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCISSOR_CLEAR_BIT		= 1 << 0,
41011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DRAW_TRIANGLE_BIT		= 1 << 1,
41021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		PER_PRIMITIVE_BBOX_BIT	= 1 << 2,
41031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FULLSCREEN_SCISSOR_BIT	= 1 << 3,
41041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
41051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									ClearCase						(Context& context, const char* name, const char* description, deUint32 flags);
41071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~ClearCase						(void);
41081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
41101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct DrawObject
41111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int firstNdx;
41131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int numVertices;
41141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
41151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
41171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
41181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
41191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							createVbo						(void);
41211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							createProgram					(void);
41221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							renderTo						(tcu::Surface& dst, bool useBBox);
41231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImagesEqual				(const tcu::PixelBufferAccess& withoutBBox, const tcu::PixelBufferAccess& withBBox);
41241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImageResultValid			(const tcu::PixelBufferAccess& result);
41251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
41271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
41281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(bool setBBox) const;
41291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
41301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_scissoredClear;
41321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_fullscreenScissor;
41331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_drawTriangles;
41341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_useGlobalState;
41351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
41371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_perPrimitiveProgram;
41381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_basicProgram;
41391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<DrawObject>			m_drawObjects;
41401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>			m_objectVertices;
41411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
41421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::ClearCase (Context& context, const char* name, const char* description, deUint32 flags)
41441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase				(context, name, description)
41451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_scissoredClear		((flags & SCISSOR_CLEAR_BIT) != 0)
41461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_fullscreenScissor	((flags & FULLSCREEN_SCISSOR_BIT) != 0)
41471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_drawTriangles		((flags & DRAW_TRIANGLE_BIT) != 0)
41481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_useGlobalState		((flags & PER_PRIMITIVE_BBOX_BIT) == 0)
41491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_useGlobalState || m_drawTriangles); // per-triangle bbox requires triangles
41511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(!m_fullscreenScissor || m_scissoredClear); // fullscreenScissor requires scissoredClear
41521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::~ClearCase (void)
41551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
41571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::init (void)
41601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
41621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
41631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_drawTriangles && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
41641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
41651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
41671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
41681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Doing multiple"
41691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_scissoredClear) ? (" scissored") : (""))
41701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< " color buffer clears"
41711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_drawTriangles) ? (" and drawing some geometry between them") : (""))
41721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
41731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_scissoredClear && m_fullscreenScissor) ? ("Setting scissor area to cover entire viewport.\n") : (""))
41741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering with and without setting the bounding box.\n"
41751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting bounding box to have no effect on clears (i.e. results are constant).\n"
41761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
41771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_useGlobalState) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
41781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
41791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Clear color is green with yellowish shades.\n"
41801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_drawTriangles) ? ("Primitive color is yellow with greenish shades.\n") : (""))
41811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
41821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_drawTriangles)
41841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		createVbo();
41861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		createProgram();
41871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
41881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::deinit (void)
41911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
41931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_perPrimitiveProgram.clear();
41941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_basicProgram.clear();
41951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_drawObjects = std::vector<DrawObject>();
41961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_objectVertices = std::vector<tcu::Vec4>();
41971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::IterateResult ClearCase::iterate (void)
42001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2	renderTargetSize	(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
42021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		resultWithoutBBox	(renderTargetSize.x(), renderTargetSize.y());
42031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		resultWithBBox		(renderTargetSize.x(), renderTargetSize.y());
42041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// render with and without bbox set
42061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int passNdx = 0; passNdx < 2; ++passNdx)
42071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		useBBox			= (passNdx == 1);
42091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Surface&	destination		= (useBBox) ? (resultWithBBox) : (resultWithoutBBox);
42101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		renderTo(destination, useBBox);
42121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Verify images are equal and that the image does not contain (trivially detectable) garbage
42151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImagesEqual(resultWithoutBBox.getAccess(), resultWithBBox.getAccess()))
42171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// verifyImagesEqual will print out the image and error mask
42191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
42201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (!verifyImageResultValid(resultWithBBox.getAccess()))
42221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// verifyImageResultValid will print out the image and error mask
42241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
42251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
42271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
42291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
42301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image comparison passed."
42311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
42321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
42331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Result", "Result", resultWithBBox.getAccess())
42341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
42351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
42371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
42401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::createVbo (void)
42431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numObjects	= 16;
42451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
42461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd			(deStringHash(getName()));
42471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
42491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int objectNdx = 0; objectNdx < numObjects; ++objectNdx)
42511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	numTriangles	= rnd.getInt(1, 4);
42531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	minX			= rnd.getFloat(-1.2f, 0.8f);
42541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	minY			= rnd.getFloat(-1.2f, 0.8f);
42551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	maxX			= minX + rnd.getFloat(0.2f, 1.0f);
42561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	maxY			= minY + rnd.getFloat(0.2f, 1.0f);
42571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DrawObject	drawObject;
42591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		drawObject.firstNdx = (int)m_objectVertices.size();
42601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		drawObject.numVertices = numTriangles * 3;
42611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_drawObjects.push_back(drawObject);
42631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int triangleNdx = 0; triangleNdx < numTriangles; ++triangleNdx)
42651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
42661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
42671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posX = rnd.getFloat(minX, maxX);
42681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posY = rnd.getFloat(minY, maxY);
42691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posZ = rnd.getFloat(-0.7f, 0.7f);
42701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posW = rnd.getFloat(0.9f, 1.1f);
42711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_objectVertices.push_back(tcu::Vec4(posX, posY, posZ, posW));
42731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
42741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
42771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bufferData(GL_ARRAY_BUFFER, (int)(m_objectVertices.size() * sizeof(tcu::Vec4)), &m_objectVertices[0], GL_STATIC_DRAW);
42781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "buffer upload");
42791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::createProgram (void)
42821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_basicProgram = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
42841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			glu::ProgramSources()
42851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																				<< glu::VertexSource(genVertexSource())
42861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																				<< glu::FragmentSource(genFragmentSource())
42871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																				<< glu::TessellationControlSource(genTessellationControlSource(false))
42881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																				<< glu::TessellationEvaluationSource(genTessellationEvaluationSource())));
42891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
42911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Section("Program", "Shader program")
42921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< *m_basicProgram
42931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndSection;
42941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_basicProgram->isOk())
42961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::TestError("shader build failed");
42971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
42991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_perPrimitiveProgram = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
43011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																					   glu::ProgramSources()
43021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																							<< glu::VertexSource(genVertexSource())
43031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																							<< glu::FragmentSource(genFragmentSource())
43041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																							<< glu::TessellationControlSource(genTessellationControlSource(true))
43051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																							<< glu::TessellationEvaluationSource(genTessellationEvaluationSource())));
43061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
43081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Section("PerPrimitiveProgram", "Shader program that sets the bounding box")
43091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< *m_perPrimitiveProgram
43101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndSection;
43111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_perPrimitiveProgram->isOk())
43131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("shader build failed");
43141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
43151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
43161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::renderTo (tcu::Surface& dst, bool useBBox)
43181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
43191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numOps				= 45;
43201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4			yellow				(1.0f, 1.0f, 0.0f, 1.0f);
43211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4			green				(0.0f, 1.0f, 0.0f, 1.0f);
43221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		renderTargetSize	(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
43231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
43241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd					(deStringHash(getName()));
43251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::VertexArray		vao					(m_context.getRenderContext());
43261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// always do the initial clear
43281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.disable(GL_SCISSOR_TEST);
43291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, renderTargetSize.x(), renderTargetSize.y());
43301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(yellow.x(), yellow.y(), yellow.z(), yellow.w());
43311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
43321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.finish();
43331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// prepare draw
43351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_scissoredClear)
43361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.enable(GL_SCISSOR_TEST);
43371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_drawTriangles)
43391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const deUint32	programHandle		= (m_useGlobalState || !useBBox) ? (m_basicProgram->getProgram()) : (m_perPrimitiveProgram->getProgram());
43411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int		positionAttribLoc	= gl.getAttribLocation(programHandle, "a_position");
43421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(positionAttribLoc != -1);
43441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.useProgram(programHandle);
43461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindVertexArray(*vao);
43471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.enableVertexAttribArray(positionAttribLoc);
43481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.vertexAttribPointer(positionAttribLoc, 4, GL_FLOAT, GL_FALSE, (int)sizeof(tcu::Vec4), DE_NULL);
43491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
43501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
43511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// do random scissor/clearldraw operations
43531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int opNdx = 0; opNdx < numOps; ++opNdx)
43541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	drawObjNdx				= (m_drawTriangles) ? (rnd.getInt(0, (int)m_drawObjects.size() - 1)) : (0);
43561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	objectVertexStartNdx	= (m_drawTriangles) ? (m_drawObjects[drawObjNdx].firstNdx) : (0);
43571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	objectVertexLength		= (m_drawTriangles) ? (m_drawObjects[drawObjNdx].numVertices) : (0);
43581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMin;
43591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMax;
43601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_drawTriangles)
43621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
43631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
43641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax = tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f);
43651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// calc bbox
43671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int vertexNdx = objectVertexStartNdx; vertexNdx < objectVertexStartNdx + objectVertexLength; ++vertexNdx)
43681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int componentNdx = 0; componentNdx < 4; ++componentNdx)
43691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
43701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bboxMin[componentNdx] = de::min(bboxMin[componentNdx], m_objectVertices[vertexNdx][componentNdx]);
43711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bboxMax[componentNdx] = de::max(bboxMax[componentNdx], m_objectVertices[vertexNdx][componentNdx]);
43721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
43731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
43741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
43751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
43761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no geometry, just random something
43771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.x() = rnd.getFloat(-1.2f, 1.0f);
43781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.y() = rnd.getFloat(-1.2f, 1.0f);
43791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.z() = rnd.getFloat(-1.2f, 1.0f);
43801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.w() = 1.0f;
43811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.x() = bboxMin.x() + rnd.getFloat(0.2f, 1.0f);
43821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.y() = bboxMin.y() + rnd.getFloat(0.2f, 1.0f);
43831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.z() = bboxMin.z() + rnd.getFloat(0.2f, 1.0f);
43841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.w() = 1.0f;
43851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
43861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_scissoredClear)
43881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
43891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorX = (m_fullscreenScissor) ? (0)					: rnd.getInt(0, renderTargetSize.x()-1);
43901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorY = (m_fullscreenScissor) ? (0)					: rnd.getInt(0, renderTargetSize.y()-1);
43911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorW = (m_fullscreenScissor) ? (renderTargetSize.x())	: rnd.getInt(0, renderTargetSize.x()-scissorX);
43921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorH = (m_fullscreenScissor) ? (renderTargetSize.y())	: rnd.getInt(0, renderTargetSize.y()-scissorY);
43931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.scissor(scissorX, scissorY, scissorW, scissorH);
43951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
43961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
43981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec4 color = tcu::mix(green, yellow, rnd.getFloat() * 0.4f); // greenish
43991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.clearColor(color.x(), color.y(), color.z(), color.w());
44001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.clear(GL_COLOR_BUFFER_BIT);
44011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (useBBox)
44041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(m_useGlobalState || m_drawTriangles); // !m_useGlobalState -> m_drawTriangles
44061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (m_useGlobalState)
4407485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe				gl.primitiveBoundingBox(bboxMin.x(), bboxMin.y(), bboxMin.z(), bboxMin.w(),
4408485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe										bboxMax.x(), bboxMax.y(), bboxMax.z(), bboxMax.w());
44091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_drawTriangles)
44121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.drawArrays(GL_PATCHES, objectVertexStartNdx, objectVertexLength);
44131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "post draw");
44161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
44171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
44181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ClearCase::verifyImagesEqual (const tcu::PixelBufferAccess& withoutBBox, const tcu::PixelBufferAccess& withBBox)
44201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
44211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(withoutBBox.getWidth() == withBBox.getWidth());
442226e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry	DE_ASSERT(withoutBBox.getHeight() == withBBox.getHeight());
44231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(withoutBBox.getWidth(), withoutBBox.getHeight());
44251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
44261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4427c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
44281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < withoutBBox.getHeight(); ++y)
44301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < withoutBBox.getWidth(); ++x)
44311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (withoutBBox.getPixelInt(x, y) != withBBox.getPixelInt(x, y))
44331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4434c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
44351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
44361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
44401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
44421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
44431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image comparison failed."
44441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
44451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image comparison")
44461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("WithoutBBox", "Result with bounding box not set", withoutBBox)
44471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("WithBBox", "Result with bounding box set", withBBox)
44481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
44491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
44501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
44531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
44541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ClearCase::verifyImageResultValid (const tcu::PixelBufferAccess& result)
44561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
44571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(result.getWidth(), result.getHeight());
44581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
44591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4460c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
44611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < result.getHeight(); ++y)
44631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < result.getWidth(); ++x)
44641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec4 pixel = result.getPixelInt(x, y);
44661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// allow green, yellow and any shade between
44681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pixel[1] != 255 || pixel[2] != 0)
44691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4470c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
44711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
44721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
44761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
44781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
44791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
44801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
44811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
44821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ResultImage", "Result image", result)
44831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
44841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
44851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
44881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
44891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic const char* const s_yellowishPosOnlyVertexSource =	"#version 310 es\n"
44911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"in highp vec4 a_position;\n"
44921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"out highp vec4 v_vertex_color;\n"
44931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"void main()\n"
44941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"{\n"
44951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	gl_Position = a_position;\n"
44961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	// yellowish shade\n"
44971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	highp float redComponent = 0.5 + float(gl_VertexID % 5) / 8.0;\n"
44981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	v_vertex_color = vec4(redComponent, 1.0, 0.0, 1.0);\n"
44991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"}\n";
45001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic const char* const s_basicColorFragmentSource =	"#version 310 es\n"
45021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"in mediump vec4 v_color;\n"
45031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"layout(location = 0) out mediump vec4 o_color;\n"
45041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"void main()\n"
45051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"{\n"
45061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	o_color = v_color;\n"
45071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"}\n";
45081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic const char* const s_basicColorTessEvalSource =	"#version 310 es\n"
45111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"#extension GL_EXT_tessellation_shader : require\n"
45121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"#extension GL_EXT_gpu_shader5 : require\n"
45131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"layout(triangles) in;\n"
45141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"in highp vec4 v_tess_eval_color[];\n"
45151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"out highp vec4 v_color;\n"
45161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"precise gl_Position;\n"
45171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"void main()\n"
45181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"{\n"
45191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position\n"
45201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	            + gl_TessCoord.y * gl_in[1].gl_Position\n"
45211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	            + gl_TessCoord.z * gl_in[2].gl_Position;\n"
45221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	v_color = gl_TessCoord.x * v_tess_eval_color[0]\n"
45231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	        + gl_TessCoord.y * v_tess_eval_color[1]\n"
45241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	        + gl_TessCoord.z * v_tess_eval_color[2];\n"
45251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"}\n";
45261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genVertexSource (void) const
45281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return	s_yellowishPosOnlyVertexSource;
45301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genFragmentSource (void) const
45331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorFragmentSource;
45351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genTessellationControlSource (bool setBBox) const
45381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream buf;
45401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"#version 310 es\n"
45421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n";
45431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (setBBox)
45451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "#extension GL_EXT_primitive_bounding_box : require\n";
45461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"layout(vertices=3) out;\n"
45481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 v_vertex_color[];\n"
45491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 v_tess_eval_color[];\n"
45501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
45511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
45521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
45531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_tess_eval_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
45541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
45551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
45561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
45571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n";
45581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (setBBox)
45601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
45611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
45621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	gl_BoundingBoxEXT[0] = min(min(gl_in[0].gl_Position,\n"
45631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                               gl_in[1].gl_Position),\n"
45641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                           gl_in[2].gl_Position);\n"
45651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	gl_BoundingBoxEXT[1] = max(max(gl_in[0].gl_Position,\n"
45661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                               gl_in[1].gl_Position),\n"
45671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                           gl_in[2].gl_Position);\n";
45681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
45691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf << "}\n";
45711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
45721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genTessellationEvaluationSource (void) const
45751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorTessEvalSource;
45771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass ViewportCallOrderCase : public TestCase
45801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
45821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum CallOrder
45831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
45841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VIEWPORT_FIRST = 0,
45851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_FIRST,
45861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ORDER_LAST
45881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
45891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									ViewportCallOrderCase			(Context& context, const char* name, const char* description, CallOrder callOrder);
45911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~ViewportCallOrderCase			(void);
45921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
45941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
45951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
45961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
45971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							genVbo							(void);
45991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							genProgram						(void);
46001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage						(const tcu::PixelBufferAccess& result);
46011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
46031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
46041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(void) const;
46051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
46061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const CallOrder					m_callOrder;
46081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
46101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
46111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_numVertices;
46121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
46131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::ViewportCallOrderCase (Context& context, const char* name, const char* description, CallOrder callOrder)
46151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
46161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_callOrder	(callOrder)
46171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numVertices	(-1)
46181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_callOrder < ORDER_LAST);
46201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::~ViewportCallOrderCase (void)
46231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
46251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::init (void)
46281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
46301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
46311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4632c22e16e65c11afffe24ad5c07f255a9f38b11231Mika Isojärvi	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
4633c22e16e65c11afffe24ad5c07f255a9f38b11231Mika Isojärvi		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
4634c22e16e65c11afffe24ad5c07f255a9f38b11231Mika Isojärvi
46351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
46361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
46371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Testing call order of state setting functions have no effect on the rendering.\n"
46381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting viewport and bounding box in the following order:\n"
46391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_callOrder == VIEWPORT_FIRST)
46401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				? ("\tFirst viewport with glViewport function.\n")
46411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				: ("\tFirst bounding box with glPrimitiveBoundingBoxEXT function.\n"))
46421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_callOrder == VIEWPORT_FIRST)
46431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				? ("\tThen bounding box with glPrimitiveBoundingBoxEXT function.\n")
46441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				: ("\tThen viewport with glViewport function.\n"))
46451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying rendering result."
46461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
46471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
46491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genVbo();
46501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genProgram();
46511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::deinit (void)
46541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
46561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
46571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::IterateResult ViewportCallOrderCase::iterate (void)
46601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
46621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		viewportSize	= tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
46631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation		= gl.getAttribLocation(m_program->getProgram(), "a_position");
46641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			resultSurface	(viewportSize.x(), viewportSize.y());
46651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
46671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
46681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// set state
46701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int orderNdx = 0; orderNdx < 2; ++orderNdx)
46711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
46721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if ((orderNdx == 0 && m_callOrder == VIEWPORT_FIRST) ||
46731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			(orderNdx == 1 && m_callOrder == BBOX_FIRST))
46741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
46751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
46761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::Message
46771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "Setting viewport to cover the left half of the render target.\n"
46781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t(0, 0, " << (viewportSize.x()/2) << ", " << viewportSize.y() << ")"
46791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::EndMessage;
46801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.viewport(0, 0, viewportSize.x()/2, viewportSize.y());
46821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
46831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
46841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
46851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
46861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::Message
46871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "Setting bounding box to cover the right half of the clip space.\n"
46881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t(0.0, -1.0, -1.0, 1.0) .. (1.0, 1.0, 1.0f, 1.0)"
46891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::EndMessage;
46901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4691485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe			gl.primitiveBoundingBox(0.0f, -1.0f, -1.0f, 1.0f,
4692485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe									1.0f,  1.0f,  1.0f, 1.0f);
46931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
46941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
46951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
46971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
46981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering mesh covering the right half of the clip space."
46991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
47001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
47021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float[4]), (const float*)DE_NULL);
47031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
47041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
47051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.patchParameteri(GL_PATCH_VERTICES, 3);
47061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays(GL_PATCHES, 0, m_numVertices);
47071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "post-draw");
47081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
47101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
47111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying image"
47121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
47131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
47141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImage(resultSurface.getAccess()))
47161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
47171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
47181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
47191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
47201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
47211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result ok."
47221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
47231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
47241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Result", "Result", resultSurface.getAccess())
47251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
47261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
47281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
47291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
47301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
47311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::genVbo (void)
47331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				gridSize	= 6;
47351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
47361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>	data		(gridSize * gridSize * 2 * 3);
47371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>		cellOrder	(gridSize * gridSize * 2);
47381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd			(0x55443322);
47391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with triangles in random order
47411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
47421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
47431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
47441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid filling the right half of the clip space: (x: 0.0, y: -1.0) .. (x: 1.0, y: 1.0)
47461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
47471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
47481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
47491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			cellSide	= ((cellNdx % 2) == 0);
47501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= (cellNdx / 2) % gridSize;
47511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= (cellNdx / 2) / gridSize;
47521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (cellSide)
47541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
47557a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 0] = tcu::Vec4(float(cellX+0) / float(gridSize), (float(cellY+0) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47567a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 1] = tcu::Vec4(float(cellX+1) / float(gridSize), (float(cellY+1) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47577a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 2] = tcu::Vec4(float(cellX+0) / float(gridSize), (float(cellY+1) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
47591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
47601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
47617a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 0] = tcu::Vec4(float(cellX+0) / float(gridSize), (float(cellY+0) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47627a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 1] = tcu::Vec4(float(cellX+1) / float(gridSize), (float(cellY+0) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47637a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			data[ndx * 3 + 2] = tcu::Vec4(float(cellX+1) / float(gridSize), (float(cellY+1) / float(gridSize)) * 2.0f - 1.0f, 0.0f, 1.0f);
47641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
47651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
47661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
47681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
47691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bufferData(GL_ARRAY_BUFFER, (int)(data.size() * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
47701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "create vbo");
47711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_numVertices = (int)data.size();
47731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
47741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::genProgram (void)
47761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
47781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																	   glu::ProgramSources()
47791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			<< glu::VertexSource(genVertexSource())
47801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			<< glu::FragmentSource(genFragmentSource())
47811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			<< glu::TessellationControlSource(genTessellationControlSource())
47821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			<< glu::TessellationEvaluationSource(genTessellationEvaluationSource())));
47831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
47851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Section("Program", "Shader program")
47861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< *m_program
47871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndSection;
47881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_program->isOk())
47901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::TestError("shader build failed");
47911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
47921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ViewportCallOrderCase::verifyImage (const tcu::PixelBufferAccess& result)
47941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47957a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	insideBorder	(deCeilFloatToInt32(0.25f * (float)result.getWidth()) + 1, deFloorFloatToInt32(0.5f * (float)result.getWidth()) - 1);
47967a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	outsideBorder	(deFloorFloatToInt32(0.25f * (float)result.getWidth()) - 1, deCeilFloatToInt32(0.5f * (float)result.getWidth()) + 1);
47971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		errorMask		(result.getWidth(), result.getHeight());
47981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				anyError		= false;
47991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4800c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
48011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < result.getHeight(); ++y)
48031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < result.getWidth(); ++x)
48041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec4	pixel			= result.getPixelInt(x, y);
48061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			insideMeshArea	= x >= insideBorder.x() && x <= insideBorder.x();
48071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			outsideMeshArea = x <= outsideBorder.x() && x >= outsideBorder.x();
48081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// inside mesh, allow green, yellow and any shade between
48101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// outside mesh, allow background (black) only
48111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// in the border area, allow anything
48121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if ((insideMeshArea && (pixel[1] != 255 || pixel[2] != 0)) ||
48131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			(outsideMeshArea && (pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0)))
48141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4815c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
48161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
48171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
48181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
48191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
48211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
48231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
48241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
48251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
48261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
48271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ResultImage", "Result image", result)
48281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
48291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
48301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
48311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
48331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genVertexSource (void) const
48361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return	s_yellowishPosOnlyVertexSource;
48381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genFragmentSource (void) const
48411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorFragmentSource;
48431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genTessellationControlSource (void) const
48461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return	"#version 310 es\n"
48481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"#extension GL_EXT_tessellation_shader : require\n"
48491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
48501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 v_vertex_color[];\n"
48511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 v_tess_eval_color[];\n"
48521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
48531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
48541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
48551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_tess_eval_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
48561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
48571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
48581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
48591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
48601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
48611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genTessellationEvaluationSource (void) const
48641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorTessEvalSource;
48661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // anonymous
48691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPrimitiveBoundingBoxTests::PrimitiveBoundingBoxTests (Context& context)
48711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCaseGroup(context, "primitive_bounding_box", "Tests for EXT_primitive_bounding_box")
48721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPrimitiveBoundingBoxTests::~PrimitiveBoundingBoxTests (void)
48761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PrimitiveBoundingBoxTests::init (void)
48801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
48821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
48841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
48851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	methodFlags;
48861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} stateSetMethods[] =
48871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
48891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"global_state",
48901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using PRIMITIVE_BOUNDING_BOX_EXT state",
48911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_STATE,
48921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
48931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
48941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"tessellation_set_per_draw",
48951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using gl_BoundingBoxEXT, use same value for all primitives",
48961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_OUTPUT,
48971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
48981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
48991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"tessellation_set_per_primitive",
49001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using gl_BoundingBoxEXT, use per-primitive bounding box",
49011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_OUTPUT | BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
49041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
49051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
49071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
49081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	stageFlags;
49091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} pipelineConfigs[] =
49101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_fragment",
49131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-fragment program",
49141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0u
49151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_tessellation_fragment",
49181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-tessellation{ctrl,eval}-fragment program",
49191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_TESSELLATION
49201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_geometry_fragment",
49231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-tessellation{ctrl,eval}-geometry-fragment program",
49241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_GEOMETRY
49251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_tessellation_geometry_fragment",
49281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-geometry-fragment program",
49291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_TESSELLATION | BBoxRenderCase::FLAG_GEOMETRY
49301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
49321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
49331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
49351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
49361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	flags;
49371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	invalidFlags;
49381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	requiredFlags;
49391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} usageConfigs[] =
49401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_equal",
49431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set tight bounding box",
49441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
49451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_larger",
49501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set padded bounding box",
49511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_LARGER,
49521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_smaller",
49571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set too small bounding box",
49581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_SMALLER,
49591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_equal",
49641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set tight bounding box",
49651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
49661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_larger",
49711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set padded bounding box",
49721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_LARGER,
49731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_smaller",
49781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set too small bounding box",
49791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_SMALLER,
49801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer",
49851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set tight bounding box",
49861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
49871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0,
49881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX
49891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo",
49921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set tight bounding box",
49931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
49941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0,
49951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX
49961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
49981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum PrimitiveRenderType
49991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_TRIANGLE,
50011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_LINE,
50021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_POINT,
50031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
50041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const struct
50051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*			name;
50071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*			description;
50081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		PrimitiveRenderType	type;
50091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32			flags;
50101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} primitiveTypes[] =
50111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"triangles",
50141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Triangle render tests",
50151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_TRIANGLE,
50161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"lines",
50201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Line render tests",
50211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_LINE,
50221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"points",
50261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Point render tests",
50271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_POINT,
50281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"wide_lines",
50321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Wide line render tests",
50331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_LINE,
50341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			LineRenderCase::LINEFLAG_WIDE
50351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"wide_points",
50381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Wide point render tests",
50391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_POINT,
50401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			PointRenderCase::POINTFLAG_WIDE
50411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
50431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .state_query
50451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const stateQueryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "State queries");
50471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(stateQueryGroup);
50481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new InitialValueCase	(m_context,	"initial_value",	"Initial value case"));
50501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getfloat",			"getFloatv",			QueryCase::QUERY_FLOAT));
50511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getboolean",		"getBooleanv",			QueryCase::QUERY_BOOLEAN));
50521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getinteger",		"getIntegerv",			QueryCase::QUERY_INT));
50531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getinteger64",		"getInteger64v",		QueryCase::QUERY_INT64));
50541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
50551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .triangles
50571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .(wide_)lines
50581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .(wide_)points
50591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
50601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, primitiveTypes[primitiveTypeNdx].description);
50621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(primitiveGroup);
50631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int stateSetMethodNdx = 0; stateSetMethodNdx < DE_LENGTH_OF_ARRAY(stateSetMethods); ++stateSetMethodNdx)
50651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, stateSetMethods[stateSetMethodNdx].name, stateSetMethods[stateSetMethodNdx].description);
50671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			primitiveGroup->addChild(methodGroup);
50681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int pipelineConfigNdx = 0; pipelineConfigNdx < DE_LENGTH_OF_ARRAY(pipelineConfigs); ++pipelineConfigNdx)
50701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
50711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if ((stateSetMethods[stateSetMethodNdx].methodFlags & BBoxRenderCase::FLAG_SET_BBOX_OUTPUT) != 0 &&
50721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					(pipelineConfigs[pipelineConfigNdx].stageFlags  & BBoxRenderCase::FLAG_TESSELLATION)    == 0)
50731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
50741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					// invalid config combination
50751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
50761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
50771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
50781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					tcu::TestCaseGroup* const pipelineGroup = new tcu::TestCaseGroup(m_testCtx, pipelineConfigs[pipelineConfigNdx].name, pipelineConfigs[pipelineConfigNdx].description);
50791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					methodGroup->addChild(pipelineGroup);
50801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageConfigs); ++usageNdx)
50821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					{
50831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						const deUint32 flags = primitiveTypes[primitiveTypeNdx].flags         |
50841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   stateSetMethods[stateSetMethodNdx].methodFlags |
50851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   pipelineConfigs[pipelineConfigNdx].stageFlags  |
50861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   usageConfigs[usageNdx].flags;
50871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						if (usageConfigs[usageNdx].invalidFlags && (flags & usageConfigs[usageNdx].invalidFlags) != 0)
50891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							continue;
50901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						if (usageConfigs[usageNdx].requiredFlags && (flags & usageConfigs[usageNdx].requiredFlags) == 0)
50911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							continue;
50921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						switch (primitiveTypes[primitiveTypeNdx].type)
50941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						{
50951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_TRIANGLE:
50961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new GridRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
50971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
50981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_LINE:
50991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new LineRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
51001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
51011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_POINT:
51021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new PointRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
51031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
51041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							default:
51051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								DE_ASSERT(false);
51061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						}
51071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					}
51081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
51091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
51101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
51111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
51121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .depth
51141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
51151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const struct
51161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					name;
51181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					description;
51191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::DepthType	depthMethod;
51201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		} depthMethods[] =
51211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"builtin_depth",
51241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Fragment depth not modified in fragment shader",
51251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::DEPTH_BUILTIN
51261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"user_defined_depth",
51291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Fragment depth is defined in the fragment shader",
51301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::DEPTH_USER_DEFINED
51311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
51331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const struct
51341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					name;
51361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					description;
51371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::BBoxState	bboxState;
51381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::BBoxSize		bboxSize;
51391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		} depthCases[] =
51401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"global_state_bbox_equal",
51431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test tight bounding box with global bbox state",
51441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_GLOBAL,
51451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_EQUAL,
51461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"global_state_bbox_larger",
51491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test padded bounding box with global bbox state",
51501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_GLOBAL,
51511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_LARGER,
51521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"per_primitive_bbox_equal",
51551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test tight bounding box with tessellation output bbox",
51561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_PER_PRIMITIVE,
51571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_EQUAL,
51581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"per_primitive_bbox_larger",
51611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test padded bounding box with tessellation output bbox",
51621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_PER_PRIMITIVE,
51631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_LARGER,
51641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
51661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const depthGroup = new tcu::TestCaseGroup(m_testCtx, "depth", "Test bounding box depth component");
51681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(depthGroup);
51691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// .builtin_depth
51711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// .user_defined_depth
51721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int depthNdx = 0; depthNdx < DE_LENGTH_OF_ARRAY(depthMethods); ++depthNdx)
51731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, depthMethods[depthNdx].name, depthMethods[depthNdx].description);
51751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			depthGroup->addChild(group);
51761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(depthCases); ++caseNdx)
51781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				group->addChild(new DepthDrawCase(m_context, depthCases[caseNdx].name, depthCases[caseNdx].description, depthMethods[depthNdx].depthMethod, depthCases[caseNdx].bboxState, depthCases[caseNdx].bboxSize));
51791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
51801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
51811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .blit_fbo
51831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
51841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const blitFboGroup = new tcu::TestCaseGroup(m_testCtx, "blit_fbo", "Test bounding box does not affect blitting");
51851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(blitFboGroup);
51861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_default_to_fbo", "Blit from default fb to fbo", BlitFboCase::TARGET_DEFAULT, BlitFboCase::TARGET_FBO));
51881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_fbo_to_default", "Blit from fbo to default fb", BlitFboCase::TARGET_FBO,     BlitFboCase::TARGET_DEFAULT));
51891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_fbo_to_fbo",     "Blit from fbo to fbo",        BlitFboCase::TARGET_FBO,     BlitFboCase::TARGET_FBO));
51901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
51911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .clear
51931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
51941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Test bounding box does not clears");
51951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(clearGroup);
51961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "full_clear",                                             "Do full clears",                                               0));
51981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "full_clear_with_triangles",                              "Do full clears and render some geometry",                      ClearCase::DRAW_TRIANGLE_BIT));
51991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "full_clear_with_triangles_per_primitive_bbox",           "Do full clears and render some geometry",                      ClearCase::DRAW_TRIANGLE_BIT | ClearCase::PER_PRIMITIVE_BBOX_BIT));
52001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_clear",                                        "Do scissored clears",                                          ClearCase::SCISSOR_CLEAR_BIT));
52011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_clear_with_triangles",                         "Do scissored clears and render some geometry",                 ClearCase::SCISSOR_CLEAR_BIT | ClearCase::DRAW_TRIANGLE_BIT));
52021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_clear_with_triangles_per_primitive_bbox",      "Do scissored clears and render some geometry",                 ClearCase::SCISSOR_CLEAR_BIT | ClearCase::DRAW_TRIANGLE_BIT | ClearCase::PER_PRIMITIVE_BBOX_BIT));
52031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_full_clear",                                   "Do full clears with enabled scissor",                          ClearCase::FULLSCREEN_SCISSOR_BIT | ClearCase::SCISSOR_CLEAR_BIT));
52041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_full_clear_with_triangles",                    "Do full clears with enabled scissor and render some geometry", ClearCase::FULLSCREEN_SCISSOR_BIT | ClearCase::SCISSOR_CLEAR_BIT | ClearCase::DRAW_TRIANGLE_BIT));
52051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_full_clear_with_triangles_per_primitive_bbox", "Do full clears with enabled scissor and render some geometry", ClearCase::FULLSCREEN_SCISSOR_BIT | ClearCase::SCISSOR_CLEAR_BIT | ClearCase::DRAW_TRIANGLE_BIT | ClearCase::PER_PRIMITIVE_BBOX_BIT));
52061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .call_order (Khronos bug #13262)
52091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
52101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const callOrderGroup = new tcu::TestCaseGroup(m_testCtx, "call_order", "Test viewport and bounding box calls have no effect");
52111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(callOrderGroup);
52121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		callOrderGroup->addChild(new ViewportCallOrderCase(m_context, "viewport_first_bbox_second", "Set up viewport first and bbox after", ViewportCallOrderCase::VIEWPORT_FIRST));
52141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		callOrderGroup->addChild(new ViewportCallOrderCase(m_context, "bbox_first_viewport_second", "Set up bbox first and viewport after", ViewportCallOrderCase::BBOX_FIRST));
52151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
52171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // Functional
52191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // gles31
52201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // deqp
5221