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"
28cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos#include "tcuStringTemplate.hpp"
291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuSurface.hpp"
301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuTextureUtil.hpp"
311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "tcuVectorUtil.hpp"
321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluCallLogWrapper.hpp"
331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluContextInfo.hpp"
341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluRenderContext.hpp"
351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluStrUtil.hpp"
361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluShaderProgram.hpp"
371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluObjectWrapper.hpp"
381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "gluPixelTransfer.hpp"
391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glsStateQueryUtil.hpp"
401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glwFunctions.hpp"
411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "glwEnums.hpp"
421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deRandom.hpp"
431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deUniquePtr.hpp"
441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include "deStringUtil.hpp"
451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <vector>
471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <sstream>
481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry#include <algorithm>
491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace deqp
511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace gles31
531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace Functional
551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace
571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrynamespace StateQueryUtil = ::deqp::gls::StateQueryUtil;
601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct BoundingBox
621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4 min;
641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4 max;
651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	/*--------------------------------------------------------------------*//*!
671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 * Get component by index of a 8-component vector constructed by
681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 * concatenating 4-component min and max vectors.
691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	 *//*--------------------------------------------------------------------*/
701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	float&			getComponentAccess	(int ndx);
711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float&	getComponentAccess	(int ndx) const;
721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryfloat& BoundingBox::getComponentAccess (int ndx)
751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(ndx >= 0 && ndx < 8);
771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (ndx < 4)
781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return min[ndx];
791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return max[ndx-4];
811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryconst float& BoundingBox::getComponentAccess (int ndx) const
841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return const_cast<BoundingBox*>(this)->getComponentAccess(ndx);
861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct ProjectedBBox
891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec3	min;
911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec3	max;
921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic ProjectedBBox projectBoundingBox (const BoundingBox& bbox)
951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float		wMin	= de::max(0.0f, bbox.min.w()); // clamp to w=0 as extension requires
971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float		wMax	= de::max(0.0f, bbox.max.w());
981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	ProjectedBBox	retVal;
991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	retVal.min = tcu::min(bbox.min.swizzle(0, 1, 2) / wMin,
1011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						  bbox.min.swizzle(0, 1, 2) / wMax);
1021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	retVal.max = tcu::max(bbox.max.swizzle(0, 1, 2) / wMin,
1031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						  bbox.max.swizzle(0, 1, 2) / wMax);
1041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return retVal;
1051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystatic tcu::IVec4 getViewportBoundingBoxArea (const ProjectedBBox& bbox, const tcu::IVec2& viewportSize, float size = 0.0f)
1081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4	vertexBox;
1101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4	pixelBox;
1111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1127a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.x() = (bbox.min.x() * 0.5f + 0.5f) * (float)viewportSize.x();
1137a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.y() = (bbox.min.y() * 0.5f + 0.5f) * (float)viewportSize.y();
1147a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.z() = (bbox.max.x() * 0.5f + 0.5f) * (float)viewportSize.x();
1157a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.w() = (bbox.max.y() * 0.5f + 0.5f) * (float)viewportSize.y();
1161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.x() = deFloorFloatToInt32(vertexBox.x() - size/2.0f);
1181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.y() = deFloorFloatToInt32(vertexBox.y() - size/2.0f);
1191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.z() = deCeilFloatToInt32(vertexBox.z() + size/2.0f);
1201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	pixelBox.w() = deCeilFloatToInt32(vertexBox.w() + size/2.0f);
1211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return pixelBox;
1221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
124cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulosstatic std::string specializeShader(Context& context, const char* code)
125cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos{
126cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const glu::GLSLVersion				glslVersion			= glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
127cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	std::map<std::string, std::string>	specializationMap;
128cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
129cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	specializationMap["GLSL_VERSION_DECL"] = glu::getGLSLVersionDeclaration(glslVersion);
130cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
131cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
132cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	{
133cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GEOMETRY_SHADER_REQUIRE"] = "";
134cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GEOMETRY_POINT_SIZE"] = "#extension GL_EXT_geometry_point_size : require";
135cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GPU_SHADER5_REQUIRE"] = "";
136cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["TESSELLATION_SHADER_REQUIRE"] = "";
137cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["TESSELLATION_POINT_SIZE_REQUIRE"] = "#extension GL_EXT_tessellation_point_size : require";
138cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["PRIMITIVE_BOUNDING_BOX_REQUIRE"] = "";
139cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["PRIM_GL_BOUNDING_BOX"] = "gl_BoundingBox";
140cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	}
141cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	else
142cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	{
143cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GEOMETRY_SHADER_REQUIRE"] = "#extension GL_EXT_geometry_shader : require";
144cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GEOMETRY_POINT_SIZE"] = "#extension GL_EXT_geometry_point_size : require";
145cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["GPU_SHADER5_REQUIRE"] = "#extension GL_EXT_gpu_shader5 : require";
146cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["TESSELLATION_SHADER_REQUIRE"] = "#extension GL_EXT_tessellation_shader : require";
147cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["TESSELLATION_POINT_SIZE_REQUIRE"] = "#extension GL_EXT_tessellation_point_size : require";
148cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["PRIMITIVE_BOUNDING_BOX_REQUIRE"] = "#extension GL_EXT_primitive_bounding_box : require";
149cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		specializationMap["PRIM_GL_BOUNDING_BOX"] = "gl_BoundingBoxEXT";
150cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	}
151cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
152cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	return tcu::StringTemplate(code).specialize(specializationMap);
153cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos}
1541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass InitialValueCase : public TestCase
1561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
1581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					InitialValueCase	(Context& context, const char* name, const char* desc);
1591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			init				(void);
1611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult	iterate				(void);
1621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
1631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryInitialValueCase::InitialValueCase (Context& context, const char* name, const char* desc)
1651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase(context, name, desc)
1661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid InitialValueCase::init (void)
1701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
171cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
172cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
173cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
1741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
1751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
1761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryInitialValueCase::IterateResult InitialValueCase::iterate (void)
1781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
1791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat[8]>	state;
1801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::CallLogWrapper											gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
1811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableLogging(true);
1831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
1851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
1861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Querying GL_PRIMITIVE_BOUNDING_BOX_EXT, expecting (-1, -1, -1, 1) (1, 1, 1, 1)"
1871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
1881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
1901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
1911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!state.verifyValidity(m_testCtx))
1931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return STOP;
1941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
1961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
1971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Got " << tcu::formatArray(&state[0], &state[8])
1981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
1991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((state[0] != -1.0f) || (state[1] != -1.0f) || (state[2] != -1.0f) || (state[3] != 1.0f) ||
2011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		(state[4] !=  1.0f) || (state[5] !=  1.0f) || (state[6] !=  1.0f) || (state[7] != 1.0f))
2021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
2041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
2051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Error, unexpected value"
2061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
2071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid initial value");
2091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
2101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
2111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
2141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass QueryCase : public TestCase
2171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
2191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum QueryMethod
2201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_FLOAT = 0,
2221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_BOOLEAN,
2231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_INT,
2241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_INT64,
2251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		QUERY_LAST
2271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
2281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						QueryCase	(Context& context, const char* name, const char* desc, QueryMethod method);
2301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
2321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				init		(void);
2331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult		iterate		(void);
2341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				verifyState	(glu::CallLogWrapper& gl, const BoundingBox& bbox) const;
2361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const QueryMethod	m_method;
2381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
2391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryQueryCase::QueryCase (Context& context, const char* name, const char* desc, QueryMethod method)
2411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase	(context, name, desc)
2421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_method	(method)
2431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(method < QUERY_LAST);
2451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid QueryCase::init (void)
2481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
249cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
250cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
251cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
2521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
2531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
2541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryQueryCase::IterateResult QueryCase::iterate (void)
2561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
2571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const BoundingBox fixedCases[] =
2581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f), tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f) },
2601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4(-0.0f, -0.0f, -0.0f, -0.0f), tcu::Vec4( 0.0f,  0.0f,  0.0f, -0.0f) },
2611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 0.0f,  0.0f,  0.0f,  0.0f), tcu::Vec4( 1.0f,  1.0f,  1.0f, -1.0f) },
2621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 2.0f,  2.0f,  2.0f,  2.0f), tcu::Vec4( 1.5f,  1.5f,  1.5f,  1.0f) },
2631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f), tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f) },
2641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{ tcu::Vec4( 1.0f,  1.0f,  1.0f,  0.3f), tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.2f) },
2651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
2661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int					numRandomCases	= 9;
2681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::CallLogWrapper			gl				(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random					rnd				(0xDE3210);
2701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<BoundingBox>	cases;
2711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	cases.insert(cases.begin(), DE_ARRAY_BEGIN(fixedCases), DE_ARRAY_END(fixedCases));
2731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < numRandomCases; ++ndx)
2741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
2751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BoundingBox	boundingBox;
2761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// parameter evaluation order is not guaranteed, cannot just do "max = (rand(), rand(), ...)
2781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int coordNdx = 0; coordNdx < 8; ++coordNdx)
2791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			boundingBox.getComponentAccess(coordNdx) = rnd.getFloat(-4.0f, 4.0f);
2801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cases.push_back(boundingBox);
2821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
2831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableLogging(true);
2851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int caseNdx = 0; caseNdx < (int)cases.size(); ++caseNdx)
2881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(caseNdx+1));
29030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		const BoundingBox&			boundingBox	= cases[caseNdx];
2911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
292485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.glPrimitiveBoundingBox(boundingBox.min.x(), boundingBox.min.y(), boundingBox.min.z(), boundingBox.min.w(),
293485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								  boundingBox.max.x(), boundingBox.max.y(), boundingBox.max.z(), boundingBox.max.w());
2941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!verifyState(gl, boundingBox))
2961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected query result");
2971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
2981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
3001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
3011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool QueryCase::verifyState (glu::CallLogWrapper& gl, const BoundingBox& bbox) const
3031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
3041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	switch (m_method)
3051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
3061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_FLOAT:
3071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
3081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat[8]>	state;
3091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool														error = false;
3101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
3121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
3131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
3151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
3181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
3191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetFloatv returned " << tcu::formatArray(&state[0], &state[8])
3201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
3231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != bbox.getComponentAccess(ndx))
3241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
3251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
3271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
3281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				m_testCtx.getLog()
3291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
3301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "Error, unexpected value\n"
3311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "Expected ["
3321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< bbox.min.x() << ", " << bbox.min.y() << ", " << bbox.min.z() << ", " << bbox.min.w() << ", "
3331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< bbox.max.x() << ", " << bbox.max.y() << ", " << bbox.max.z() << ", " << bbox.max.w() << "]"
3341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
3371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
3381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
3391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_INT:
3411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
3421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[8]>	state;
3431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool														error = false;
3441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetIntegerv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
3461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
3471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
3491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
3521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
3531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetIntegerv returned " << tcu::formatArray(&state[0], &state[8])
3541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
3551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
3571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint>(bbox.getComponentAccess(ndx)) &&
3581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint>(bbox.getComponentAccess(ndx)))
3591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
3601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
3621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
3631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
3641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
3661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
3671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
3691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
3701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint roundDown	= StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint>(bbox.getComponentAccess(ndx));
3711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint roundUp	= StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint>(bbox.getComponentAccess(ndx));
3721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
3741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
3751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (roundDown == roundUp)
3771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << roundDown;
3781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					else
3791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << "{" << roundDown << ", " << roundUp << "}";
3801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
3811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
3831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
3841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
3861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
3871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
3881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_INT64:
3901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
3911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64[8]>	state;
3921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool																error = false;
3931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetInteger64v(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
3951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
3961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
3981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
3991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
4011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
4021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetInteger64v returned " << tcu::formatArray(&state[0], &state[8])
4031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
4041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
4061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(bbox.getComponentAccess(ndx)) &&
4071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					state[ndx] != StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(bbox.getComponentAccess(ndx)))
4081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
4091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
4111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
4121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
4131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
4151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
4161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
4181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
4191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint64 roundDown	= StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(bbox.getComponentAccess(ndx));
4201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const glw::GLint64 roundUp		= StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(bbox.getComponentAccess(ndx));
4211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
4231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
4241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (roundDown == roundUp)
4261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << roundDown;
4271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					else
4281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << "{" << roundDown << ", " << roundUp << "}";
4291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
4301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
4321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
4331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
4341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
4351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
4371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case QUERY_BOOLEAN:
4391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean[8]>	state;
4411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bool															error = false;
4421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.glGetBooleanv(GL_PRIMITIVE_BOUNDING_BOX_EXT, state);
4441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			GLU_EXPECT_NO_ERROR(gl.glGetError(), "query");
4451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (!state.verifyValidity(m_testCtx))
4471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
4481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
4501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::Message
4511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< "glGetBooleanv returned ["
4521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::getBooleanStr(state[0]) << ", " << glu::getBooleanStr(state[1]) << ", " << glu::getBooleanStr(state[2]) << ", " << glu::getBooleanStr(state[3]) << ", "
4531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< glu::getBooleanStr(state[4]) << ", " << glu::getBooleanStr(state[5]) << ", " << glu::getBooleanStr(state[6]) << ", " << glu::getBooleanStr(state[7]) << "]\n"
4541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< tcu::TestLog::EndMessage;
4551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int ndx = 0; ndx < 8; ++ndx)
4571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (state[ndx] != ((bbox.getComponentAccess(ndx) != 0.0f) ? (GL_TRUE) : (GL_FALSE)))
4581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					error = true;
4591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (error)
4611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
4621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				tcu::MessageBuilder builder(&m_testCtx.getLog());
4631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "Error, unexpected value\n"
4651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< "Expected [";
4661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int ndx = 0; ndx < 8; ++ndx)
4681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
4691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (ndx != 0)
4701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						builder << ", ";
4711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					builder << ((bbox.getComponentAccess(ndx) != 0.0f) ? ("GL_TRUE") : ("GL_FALSE"));
4731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
4741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				builder	<< "]"
4761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						<< tcu::TestLog::EndMessage;
4771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return false;
4781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
4791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
4811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		default:
4831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(false);
4841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
4851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
4861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
4871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass BBoxRenderCase : public TestCase
4891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
4901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
4911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
4921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
4931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_RENDERTARGET_DEFAULT	= 1u << 0, //!< render to default renderbuffer
4941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_RENDERTARGET_FBO		= 1u << 1, //!< render to framebuffer object
4951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_EQUAL			= 1u << 2, //!< set tight primitive bounding box
4971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_LARGER		= 1u << 3, //!< set padded primitive bounding box
4981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_BBOXSIZE_SMALLER		= 1u << 4, //!< set too small primitive bounding box
4991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_TESSELLATION			= 1u << 5, //!< use tessellation shader
5011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_GEOMETRY				= 1u << 6, //!< use geometry shader
5021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_SET_BBOX_STATE			= 1u << 7, //!< set primitive bounding box using global state
5041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_SET_BBOX_OUTPUT		= 1u << 8, //!< set primitive bounding box using tessellation output
5051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAG_PER_PRIMITIVE_BBOX		= 1u << 9, //!< set primitive bounding per primitive
5061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FLAGBIT_USER_BIT			= 10u //!< bits N and and up are reserved for subclasses
5081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									BBoxRenderCase					(Context& context, const char* name, const char* description, int numIterations, deUint32 flags);
5111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~BBoxRenderCase					(void);
5121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprotected:
5141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum RenderTarget
5151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDERTARGET_DEFAULT,
5171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDERTARGET_FBO,
5181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxSize
5201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_EQUAL,
5221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_LARGER,
5231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOXSIZE_SMALLER,
5241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
5271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDER_TARGET_MIN_SIZE	= 256,
5291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FBO_SIZE				= 512,
5301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		MIN_VIEWPORT_SIZE		= 256,
5311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		MAX_VIEWPORT_SIZE		= 512,
5321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_STATIC_ASSERT(MIN_VIEWPORT_SIZE <= RENDER_TARGET_MIN_SIZE);
5341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
5361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_POS_VEC_NDX		= 0,
5381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_COL_VEC_NDX		= 1,
5391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VA_NUM_ATTRIB_VECS	= 2,
5401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum AABBRoundDirection
5431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ROUND_INWARDS = 0,
5451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ROUND_OUTWARDS
5461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct IterationConfig
5491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2	viewportPos;
5511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2	viewportSize;
5521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	patternPos;		//!< in NDC
5531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	patternSize;	//!< in NDC
5541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BoundingBox	bbox;
5551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					init							(void);
5581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					deinit							(void);
5591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
5601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genVertexSource					(void) const = 0;
5621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genFragmentSource				(void) const = 0;
5631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genTessellationControlSource	(void) const = 0;
5641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genTessellationEvaluationSource	(void) const = 0;
5651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual std::string				genGeometrySource				(void) const = 0;
5661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual IterationConfig			generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const = 0;
5681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					getAttributeData				(std::vector<tcu::Vec4>& data) const = 0;
5691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					renderTestPattern				(const IterationConfig& config) = 0;
5701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	virtual void					verifyRenderResult				(const IterationConfig& config) = 0;
5711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig					generateRandomConfig			(int seed, const tcu::IVec2& renderTargetSize) const;
5731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4						getViewportPatternArea			(const tcu::Vec2& patternPos, const tcu::Vec2& patternSize, const tcu::IVec2& viewportSize, AABBRoundDirection roundDir) const;
5741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							setupRender						(const IterationConfig& config);
5761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum ShaderFunction
5781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
5791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_MIRROR_X,
5801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_MIRROR_Y,
5811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SHADER_FUNC_INSIDE_BBOX,
5821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
5831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char*						genShaderFunction				(ShaderFunction func) const;
5851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_renderTarget;
5871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxSize					m_bboxSize;
5881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_hasTessellationStage;
5891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_hasGeometryStage;
5901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_useGlobalState;
5911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_calcPerPrimitiveBBox;
5921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_numIterations;
5931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
5951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
5961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_fbo;
5971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
5981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
5991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<IterationConfig>	m_iterationConfigs;
6001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_iteration;
6011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
6021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::BBoxRenderCase (Context& context, const char* name, const char* description, int numIterations, deUint32 flags)
6041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase					(context, name, description)
6051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_renderTarget			((flags & FLAG_RENDERTARGET_DEFAULT) ? (RENDERTARGET_DEFAULT) : (RENDERTARGET_FBO))
6061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_bboxSize				((flags & FLAG_BBOXSIZE_EQUAL) ? (BBOXSIZE_EQUAL) : (flags & FLAG_BBOXSIZE_SMALLER) ? (BBOXSIZE_SMALLER) : (BBOXSIZE_LARGER))
6071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_hasTessellationStage	((flags & FLAG_TESSELLATION) != 0)
6081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_hasGeometryStage		((flags & FLAG_GEOMETRY) != 0)
6091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_useGlobalState			((flags & FLAG_SET_BBOX_STATE) != 0)
6101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_calcPerPrimitiveBBox	((flags & FLAG_PER_PRIMITIVE_BBOX) != 0)
6111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numIterations			(numIterations)
6121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_iteration				(0)
6131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
6141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// validate flags
6151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT((((m_renderTarget == RENDERTARGET_DEFAULT)	?	(FLAG_RENDERTARGET_DEFAULT)	: (0)) |
6161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_renderTarget == RENDERTARGET_FBO)		?	(FLAG_RENDERTARGET_FBO)		: (0)) |
6171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_EQUAL)				?	(FLAG_BBOXSIZE_EQUAL)		: (0)) |
6181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_LARGER)				?	(FLAG_BBOXSIZE_LARGER)		: (0)) |
6191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_bboxSize == BBOXSIZE_SMALLER)			?	(FLAG_BBOXSIZE_SMALLER)		: (0)) |
6201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_hasTessellationStage)					?	(FLAG_TESSELLATION)			: (0)) |
6211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_hasGeometryStage)						?	(FLAG_GEOMETRY)				: (0)) |
6221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_useGlobalState)							?	(FLAG_SET_BBOX_STATE)		: (0)) |
6231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((!m_useGlobalState)							?	(FLAG_SET_BBOX_OUTPUT)		: (0)) |
6241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			   ((m_calcPerPrimitiveBBox)					?	(FLAG_PER_PRIMITIVE_BBOX)	: (0))) == (flags & ((1u << FLAGBIT_USER_BIT) - 1)));
6251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_useGlobalState || m_hasTessellationStage); // using non-global state requires tessellation
6271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
6291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
6301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(!m_useGlobalState); // per-primitive test requires per-primitive (non-global) state
6311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_bboxSize == BBOXSIZE_EQUAL); // smaller is hard to verify, larger not interesting
6321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
6331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
6341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::~BBoxRenderCase (void)
6361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
6371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
6381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
6391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::init (void)
6411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
6421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
6431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		renderTargetSize	= (m_renderTarget == RENDERTARGET_DEFAULT) ?
6441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													(tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())) :
6451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													(tcu::IVec2(FBO_SIZE, FBO_SIZE));
646cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool				supportsES32		= glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
6471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// requirements
649cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
6501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
651cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && m_hasTessellationStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
6521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
653cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
6541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
6551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_renderTarget == RENDERTARGET_DEFAULT && (renderTargetSize.x() < RENDER_TARGET_MIN_SIZE || renderTargetSize.y() < RENDER_TARGET_MIN_SIZE))
6561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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");
6571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// log case specifics
6591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
6601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
6611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting primitive bounding box "
6621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_calcPerPrimitiveBBox)         ? ("to exactly cover each generated primitive")
6631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_EQUAL)   ? ("to exactly cover rendered grid")
6641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_LARGER)  ? ("to cover the grid and include some padding")
6651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (m_bboxSize == BBOXSIZE_SMALLER) ? ("to cover only a subset of the grid")
6661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			  : (DE_NULL))
6671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
6681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering with vertex"
6691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_hasTessellationStage) ? ("-tessellation{ctrl,eval}") : (""))
6701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_hasGeometryStage) ? ("-geometry") : (""))
6711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "-fragment program.\n"
6721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
6731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_useGlobalState) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
6741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
6751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying rendering results are valid within the bounding box."
6761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
6771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
6791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
6811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::ProgramSources sources;
682cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		sources << glu::VertexSource(specializeShader(m_context, genVertexSource().c_str()));
683cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		sources << glu::FragmentSource(specializeShader(m_context, genFragmentSource().c_str()));
6841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage)
686cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			sources << glu::TessellationControlSource(specializeShader(m_context, genTessellationControlSource().c_str()))
687cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos					<< glu::TessellationEvaluationSource(specializeShader(m_context, genTessellationEvaluationSource().c_str()));
6881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
689cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			sources << glu::GeometrySource(specializeShader(m_context, genGeometrySource().c_str()));
6901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), sources));
6921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "build program");
6931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
6951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::ScopedLogSection section(m_testCtx.getLog(), "ShaderProgram", "Shader program");
6961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
6971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
6981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
6991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
7001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
7011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_renderTarget == RENDERTARGET_FBO)
7041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::Texture colorAttachment(m_context.getRenderContext());
7061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindTexture(GL_TEXTURE_2D, *colorAttachment);
7081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, FBO_SIZE, FBO_SIZE);
7091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "gen tex");
7101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_fbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
7121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);
7131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *colorAttachment, 0);
7141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "attach");
7151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// unbind to prevent texture name deletion from removing it from current fbo attachments
7171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
7181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<tcu::Vec4> data;
7221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		getAttributeData(data);
7241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
7261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
7271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, (int)(data.size() * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
7281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "create vbo");
7291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Iterations
7321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int iterationNdx = 0; iterationNdx < m_numIterations; ++iterationNdx)
7331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_iterationConfigs.push_back(generateConfig(iterationNdx, renderTargetSize));
7341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::deinit (void)
7371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
7391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
7401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_fbo.clear();
7411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::IterateResult BBoxRenderCase::iterate (void)
7441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::ScopedLogSection	section		(m_testCtx.getLog(),
7461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											 std::string() + "Iteration" + de::toString((int)m_iteration),
7471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											 std::string() + "Iteration " + de::toString((int)m_iteration+1) + "/" + de::toString((int)m_iterationConfigs.size()));
7481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const IterationConfig&		config		= m_iterationConfigs[m_iteration];
7491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// default
7511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_iteration == 0)
7521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	renderTestPattern(config);
7551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	verifyRenderResult(config);
7561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (++m_iteration < (int)m_iterationConfigs.size())
7581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return CONTINUE;
7591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
7611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
7621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBBoxRenderCase::IterationConfig BBoxRenderCase::generateRandomConfig (int seed, const tcu::IVec2& renderTargetSize) const
7641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
7651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random		rnd		(seed);
7661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig	config;
7671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// viewport config
7691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportSize.x()	= rnd.getInt(MIN_VIEWPORT_SIZE, de::min<int>(renderTargetSize.x(), MAX_VIEWPORT_SIZE));
7701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportSize.y()	= rnd.getInt(MIN_VIEWPORT_SIZE, de::min<int>(renderTargetSize.y(), MAX_VIEWPORT_SIZE));
7711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportPos.x()	= rnd.getInt(0, renderTargetSize.x() - config.viewportSize.x());
7721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.viewportPos.y()	= rnd.getInt(0, renderTargetSize.y() - config.viewportSize.y());
7731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// pattern location inside viewport
7751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternSize.x()	= rnd.getFloat(0.4f, 1.4f);
7761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternSize.y()	= rnd.getFloat(0.4f, 1.4f);
7771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternPos.x()	= rnd.getFloat(-1.0f, 1.0f - config.patternSize.x());
7781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.patternPos.y()	= rnd.getFloat(-1.0f, 1.0f - config.patternSize.y());
7791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// accurate bounding box
7811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.bbox.min			= tcu::Vec4(config.patternPos.x(), config.patternPos.y(), 0.0f, 1.0f);
7821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	config.bbox.max			= tcu::Vec4(config.patternPos.x() + config.patternSize.x(), config.patternPos.y() + config.patternSize.y(), 0.0f, 1.0f);
7831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOXSIZE_LARGER)
7851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// increase bbox size
7871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.x() -= rnd.getFloat() * 0.5f;
7881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.y() -= rnd.getFloat() * 0.5f;
7891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.z() -= rnd.getFloat() * 0.5f;
7901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
7911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.x() += rnd.getFloat() * 0.5f;
7921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.y() += rnd.getFloat() * 0.5f;
7931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.z() += rnd.getFloat() * 0.5f;
7941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
7951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (m_bboxSize == BBOXSIZE_SMALLER)
7961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
7971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// reduce bbox size
7981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.x() += rnd.getFloat() * 0.4f * config.patternSize.x();
7991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.min.y() += rnd.getFloat() * 0.4f * config.patternSize.y();
8001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.x() -= rnd.getFloat() * 0.4f * config.patternSize.x();
8021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		config.bbox.max.y() -= rnd.getFloat() * 0.4f * config.patternSize.y();
8031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
8041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return config;
8061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
8071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec4 BBoxRenderCase::getViewportPatternArea (const tcu::Vec2& patternPos, const tcu::Vec2& patternSize, const tcu::IVec2& viewportSize, AABBRoundDirection roundDir) const
8091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
8101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const float	halfPixel	= 0.5f;
8111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Vec4	vertexBox;
8121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec4	pixelBox;
8131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8147a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.x() = (patternPos.x() * 0.5f + 0.5f) * (float)viewportSize.x();
8157a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.y() = (patternPos.y() * 0.5f + 0.5f) * (float)viewportSize.y();
8167a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.z() = ((patternPos.x() + patternSize.x()) * 0.5f + 0.5f) * (float)viewportSize.x();
8177a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	vertexBox.w() = ((patternPos.y() + patternSize.y()) * 0.5f + 0.5f) * (float)viewportSize.y();
8181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (roundDir == ROUND_INWARDS)
8201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
8211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.x() = (int)deFloatCeil(vertexBox.x()+halfPixel);
8221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.y() = (int)deFloatCeil(vertexBox.y()+halfPixel);
8231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.z() = (int)deFloatFloor(vertexBox.z()-halfPixel);
8241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.w() = (int)deFloatFloor(vertexBox.w()-halfPixel);
8251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
8261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
8271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
8281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.x() = (int)deFloatFloor(vertexBox.x()-halfPixel);
8291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.y() = (int)deFloatFloor(vertexBox.y()-halfPixel);
8301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.z() = (int)deFloatCeil(vertexBox.z()+halfPixel);
8311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pixelBox.w() = (int)deFloatCeil(vertexBox.w()+halfPixel);
8321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
8331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return pixelBox;
8351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
8361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BBoxRenderCase::setupRender (const IterationConfig& config)
8381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
8391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
8401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation			= gl.getAttribLocation(m_program->getProgram(), "a_position");
8411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		colLocation			= gl.getAttribLocation(m_program->getProgram(), "a_color");
8421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posScaleLocation	= gl.getUniformLocation(m_program->getProgram(), "u_posScale");
8431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posLocation != -1);
8451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(colLocation != -1);
8461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posScaleLocation != -1);
8471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
8491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
8501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting viewport to ("
8511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "x: " << config.viewportPos.x() << ", "
8521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "y: " << config.viewportPos.y() << ", "
8531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "w: " << config.viewportSize.x() << ", "
8541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "h: " << config.viewportSize.y() << ")\n"
8551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Vertex coordinates are in range:\n"
8561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tx: [" << config.patternPos.x() << ", " << (config.patternPos.x() + config.patternSize.x()) << "]\n"
8571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\ty: [" << config.patternPos.y() << ", " << (config.patternPos.y() + config.patternSize.y()) << "]\n"
8581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
8591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
8611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
8621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
8631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Setting primitive bounding box to:\n"
8641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t" << config.bbox.min << "\n"
8651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t" << config.bbox.max << "\n"
8661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
8671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_useGlobalState)
869485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.primitiveBoundingBox(config.bbox.min.x(), config.bbox.min.y(), config.bbox.min.z(), config.bbox.min.w(),
870485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								config.bbox.max.x(), config.bbox.max.y(), config.bbox.max.z(), config.bbox.max.w());
8711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
8721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// state is overriden by the tessellation output, set bbox to invisible area to imitiate dirty state left by application
873485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe		gl.primitiveBoundingBox(-2.0f, -2.0f, 0.0f, 1.0f,
874485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe								-1.7f, -1.7f, 0.0f, 1.0f);
8751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
8771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);
8781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(config.viewportPos.x(), config.viewportPos.y(), config.viewportSize.x(), config.viewportSize.y());
8801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
8811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
8821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
8841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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);
8851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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);
8861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
8871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(colLocation);
8881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
8891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform4f(posScaleLocation, config.patternPos.x(), config.patternPos.y(), config.patternSize.x(), config.patternSize.y());
8901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
8921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint bboxMinPos = gl.getUniformLocation(m_program->getProgram(), "u_primitiveBBoxMin");
8931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint bboxMaxPos = gl.getUniformLocation(m_program->getProgram(), "u_primitiveBBoxMax");
8941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4f(bboxMinPos, config.bbox.min.x(), config.bbox.min.y(), config.bbox.min.z(), config.bbox.min.w());
8961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4f(bboxMaxPos, config.bbox.max.x(), config.bbox.max.y(), config.bbox.max.z(), config.bbox.max.w());
8971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
8981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
8991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform2i(gl.getUniformLocation(m_program->getProgram(), "u_viewportPos"), config.viewportPos.x(), config.viewportPos.y());
9001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.uniform2i(gl.getUniformLocation(m_program->getProgram(), "u_viewportSize"), config.viewportSize.x(), config.viewportSize.y());
9011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup");
9031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryconst char* BBoxRenderCase::genShaderFunction (ShaderFunction func) const
9061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	switch (func)
9081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
9091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_MIRROR_X:
9101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"vec4 mirrorX(in highp vec4 p)\n"
9111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
9121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternOffset = u_posScale.xy;\n"
9131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternScale = u_posScale.zw;\n"
9141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternCenter = patternOffset + patternScale * 0.5;\n"
9151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return vec4(2.0 * patternCenter.x - p.x, p.y, p.z, p.w);\n"
9161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
9171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_MIRROR_Y:
9191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"vec4 mirrorY(in highp vec4 p)\n"
9201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
9211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternOffset = u_posScale.xy;\n"
9221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternScale = u_posScale.zw;\n"
9231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	highp vec2 patternCenter = patternOffset + patternScale * 0.5;\n"
9241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return vec4(p.x, 2.0 * patternCenter.y - p.y, p.z, p.w);\n"
9251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
9261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		case SHADER_FUNC_INSIDE_BBOX:
9281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return	"uniform highp ivec2 u_viewportPos;\n"
9291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"uniform highp ivec2 u_viewportSize;\n"
9301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp float v_bbox_expansionSize;\n"
9311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp vec3 v_bbox_clipMin;\n"
9321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"flat in highp vec3 v_bbox_clipMax;\n"
9331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"\n"
9341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"bool fragmentInsideTheBBox(in highp float depth)\n"
9351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"{\n"
9361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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"
9371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     floor((v_bbox_clipMin.y * 0.5 + 0.5) * float(u_viewportSize.y) - v_bbox_expansionSize/2.0),\n"
9381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     ceil((v_bbox_clipMax.x * 0.5 + 0.5) * float(u_viewportSize.x) + v_bbox_expansionSize/2.0),\n"
9391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	                     ceil((v_bbox_clipMax.y * 0.5 + 0.5) * float(u_viewportSize.y) + v_bbox_expansionSize/2.0));\n"
9401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	if (gl_FragCoord.x < float(u_viewportPos.x) + wc.x || gl_FragCoord.x > float(u_viewportPos.x) + wc.z ||\n"
9411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    gl_FragCoord.y < float(u_viewportPos.y) + wc.y || gl_FragCoord.y > float(u_viewportPos.y) + wc.w)\n"
9421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    return false;\n"
94326e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry					"	const highp float dEpsilon = 0.001;\n"
94426e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry					"	if (depth*2.0-1.0 < v_bbox_clipMin.z - dEpsilon || depth*2.0-1.0 > v_bbox_clipMax.z + dEpsilon)\n"
9451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	    return false;\n"
9461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	return true;\n"
9471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"}\n";
9481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		default:
9491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(false);
9501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return "";
9511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
9521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass GridRenderCase : public BBoxRenderCase
9551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
9571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					GridRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
9581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					~GridRenderCase					(void);
9591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
9611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			init							(void);
9621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genVertexSource					(void) const;
9641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genFragmentSource				(void) const;
9651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genTessellationControlSource	(void) const;
9661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genTessellationEvaluationSource	(void) const;
9671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string		genGeometrySource				(void) const;
9681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig	generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
9701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			getAttributeData				(std::vector<tcu::Vec4>& data) const;
9711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			renderTestPattern				(const IterationConfig& config);
9721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void			verifyRenderResult				(const IterationConfig& config);
9731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int		m_gridSize;
9751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
9761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::GridRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
9781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase	(context, name, description, 12, flags)
9791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_gridSize		(24)
9801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::~GridRenderCase (void)
9841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::init (void)
9881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
9891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
9901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
9911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering yellow-green grid to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
9921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Grid cells are in random order, varying grid size and location for each iteration.\n"
9931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated blue channel."
9941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
9951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
9971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
9981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
9991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genVertexSource (void) const
10001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
10011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
10021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1003cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
10041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
10051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
10061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
10071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
10081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
10091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
10101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
10121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
10131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
10141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
10151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
10161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
10171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
10181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
10191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
10221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
10231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
10241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
10251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
10261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
10271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
10291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
10311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
10321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = 0.0;\n"
10331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
10341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
10351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
10361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
10371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
10381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
10391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf<<	"}\n";
10421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
10441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
10451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genFragmentSource (void) const
10471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
10481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
10491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
10501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1051cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
10521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
10531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
10541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
10551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
10561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
10571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
10581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
10591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float blueChannel;\n"
10601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
10611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		blueChannel = 0.0;\n"
10621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
10631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		blueChannel = 1.0;\n"
10641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(baseColor.r, baseColor.g, blueChannel, baseColor.a);\n"
10651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
10661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
10681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
10691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genTessellationControlSource (void) const
10711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
10721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
10731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1074cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1075cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
1076cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${PRIMITIVE_BOUNDING_BOX_REQUIRE}\n"
10771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
10781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
10791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
10801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
10811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
10821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n";
10831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
10851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
10871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
10881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
10891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp float vp_bbox_expansionSize;\n"
10911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMin;\n"
10921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
10931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
10941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
10951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
10961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
10971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
10981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
10991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
11001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
11021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
11031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
11041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
11051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
11061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
11081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
11091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
11101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
11111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
11121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
11131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = u_tessellationLevel;\n"
11151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n"
11161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = u_tessellationLevel;\n"
11171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = u_tessellationLevel;\n";
11181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
11201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
11211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
11221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = min(min(transformVec(gl_in[0].gl_Position),\n"
11231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                             transformVec(gl_in[1].gl_Position)),\n"
11241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[2].gl_Position));\n"
11251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = max(max(transformVec(gl_in[0].gl_Position),\n"
11261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                             transformVec(gl_in[1].gl_Position)),\n"
11271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[2].gl_Position));\n";
11281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
11291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
11301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
11311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
11321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
11331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
11341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
11351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
11371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
1138cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[0] = bboxMin;\n"
1139cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[1] = bboxMax;\n";
11401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_expansionSize = 0.0;\n"
11421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
11431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
11441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
11451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
11461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
11471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
11491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
11501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genTessellationEvaluationSource (void) const
11521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
11531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
11541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1155cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1156cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
1157cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${GPU_SHADER5_REQUIRE}\n"
11581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
11591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
11611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
11621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
11631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp float vp_bbox_expansionSize;\n"
11641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
11651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
11661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
11671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
11681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
11691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"precise gl_Position;\n"
11711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
11731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
11741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
11751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
11761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(gl_TessCoord.x * gl_in[0].gl_Position.zwyx +\n"
11771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      gl_TessCoord.y * gl_in[1].gl_Position.zwyx +\n"
11781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      gl_TessCoord.z * gl_in[2].gl_Position.zwyx);\n"
11791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_color = tess_ctrl_color[0];\n"
11801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = vp_bbox_expansionSize;\n"
11811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
11821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
11831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
11841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
11861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
11871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
11881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string GridRenderCase::genGeometrySource (void) const
11891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
11901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
11911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
11921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1193cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1194cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${GEOMETRY_SHADER_REQUIRE}\n"
11951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
11961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=9, triangle_strip) out;\n"
11971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
11981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[3];\n"
11991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
12001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
12011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
12021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp float v_geo_bbox_expansionSize[3];\n"
12031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[3];\n"
12041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[3];\n"
12051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
12061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
12071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
12081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
12091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
12101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void setVisualizationVaryings()\n"
12111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
12121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_expansionSize = v_geo_bbox_expansionSize[0];\n"
12131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
12141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
12151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n"
12161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
12171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
12181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
12191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
12201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p1 = mirrorX(gl_in[1].gl_Position);\n"
12211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p2 = mirrorX(gl_in[2].gl_Position);\n"
12221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 pCentroid = vec4((p0.xyz + p1.xyz + p2.xyz) / 3.0, 1.0);\n"
12231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 triangleColor = " << colorInputName << "[0];\n"
12241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
12251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p0; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p1; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
12291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
12301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p1; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p2; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
12341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
12351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p2; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = p0; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = pCentroid; geo_color = triangleColor; setVisualizationVaryings(); EmitVertex();\n"
12381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
12391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
12401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
12421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryGridRenderCase::IterationConfig GridRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
12451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return generateRandomConfig(0xDEDEDEu * (deUint32)iteration, renderTargetSize);
12471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
12501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green				(0.0f, 1.0f, 0.0f, 1.0f);
12521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		yellow				(1.0f, 1.0f, 0.0f, 1.0f);
12531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder			(m_gridSize * m_gridSize);
12541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd					(0xDE56789);
12551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with cells in random order
12571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
12581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
12591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
12601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(m_gridSize * m_gridSize * 6 * 2);
12621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
12631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
12641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
12651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= cellNdx % m_gridSize;
12661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= cellNdx / m_gridSize;
12671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec4&	cellColor	= ((cellX+cellY)%2 == 0) ? (green) : (yellow);
12681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12697a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12717a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12737a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 2) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12757a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 3) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12777a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 4) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12797a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
12801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		data[(ndx * 6 + 5) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = cellColor;
12811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
12821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
12831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::renderTestPattern (const IterationConfig& config)
12851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
12861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
12891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
12911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
12921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
12931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 2.8f; // will be rounded up
12941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
12961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
12981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
12991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
13001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
13011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
13021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
13031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering grid." << tcu::TestLog::EndMessage;
13051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_TRIANGLES), 0, m_gridSize * m_gridSize * 6);
13071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
13081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
13091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid GridRenderCase::verifyRenderResult (const IterationConfig& config)
13111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
13121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
13131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const ProjectedBBox		projectedBBox			= projectBoundingBox(config.bbox);
13141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportBBoxArea		= getViewportBoundingBoxArea(projectedBBox, config.viewportSize);
13151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportGridOuterArea	= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_OUTWARDS);
13161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4		viewportGridInnerArea	= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
13171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewportSurface			(config.viewportSize.x(), config.viewportSize.y());
13181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			errorMask				(config.viewportSize.x(), config.viewportSize.y());
13191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					anyError				= false;
13201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
13221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
13231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
13241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
13251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
13261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
13271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
13281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
13291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
13301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
13311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box.\n"
13321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
13331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
13341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
13351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
13361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result."
13371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
13381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
13401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
13411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
13421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0,0,0,255));
13441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = de::max(viewportBBoxArea.y(), 0); y < de::min(viewportBBoxArea.w(), config.viewportSize.y()); ++y)
13461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = de::max(viewportBBoxArea.x(), 0); x < de::min(viewportBBoxArea.z(), config.viewportSize.x()); ++x)
13471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA	pixel		= viewportSurface.getPixel(x, y);
13491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		outsideGrid	= x < viewportGridOuterArea.x() ||
13501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y < viewportGridOuterArea.y() ||
13511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  x > viewportGridOuterArea.z() ||
13521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y > viewportGridOuterArea.w();
13531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		insideGrid	= x > viewportGridInnerArea.x() &&
13541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y > viewportGridInnerArea.y() &&
13551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  x < viewportGridInnerArea.z() &&
13561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									  y < viewportGridInnerArea.w();
13571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool			error		= false;
13591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (outsideGrid)
13611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// expect black
13631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixel.getRed() != 0 || pixel.getGreen() != 0 || pixel.getBlue() != 0)
13641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				error = true;
13651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (insideGrid)
13681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// expect green, yellow or a combination of these
13701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixel.getGreen() != 255 || pixel.getBlue() != 0)
13711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				error = true;
13721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
13741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
13751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// boundary, allow anything
13761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
13791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
1380c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
13811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
13821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
13831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
13841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
13861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
13871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
13881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
13891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
13901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
13911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
13921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
13931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
13941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
13951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
13961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
13971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
13981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
139930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
140030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
140130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
140230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
140330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
140430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
140530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
140630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
140730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
14081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass LineRenderCase : public BBoxRenderCase
14111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
14131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
14141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		LINEFLAG_WIDE = 1u << FLAGBIT_USER_BIT,	//!< use wide lines
14161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
14171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					LineRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
14191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					~LineRenderCase					(void);
14201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
14221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
14231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GREEN_COMPONENT_NDX = 1,
14251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BLUE_COMPONENT_NDX = 2,
14261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCAN_ROW_COMPONENT_NDX = GREEN_COMPONENT_NDX, // \note: scans are orthogonal to the line
14281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCAN_COL_COMPONENT_NDX = BLUE_COMPONENT_NDX,
14291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
14301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum QueryDirection
14321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DIRECTION_HORIZONTAL = 0,
14341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DIRECTION_VERTICAL,
14351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
14361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1437f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	enum ScanResult
1438f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
1439f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		SCANRESULT_NUM_LINES_OK_BIT		= (1 << 0),
1440f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		SCANRESULT_LINE_WIDTH_OK_BIT	= (1 << 1),
144188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		SCANRESULT_LINE_WIDTH_WARN_BIT	= (1 << 2),
144288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		SCANRESULT_LINE_WIDTH_ERR_BIT	= (1 << 3),
14432c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_OK_BIT		= (1 << 4),
14442c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_ERR_BIT	= (1 << 5),
14452c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_WARN_BIT	= (1 << 6),
1446f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	};
1447f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
14481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				init							(void);
14491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genVertexSource					(void) const;
14511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genFragmentSource				(void) const;
14521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genTessellationControlSource	(void) const;
14531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genTessellationEvaluationSource	(void) const;
14541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string			genGeometrySource				(void) const;
14551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig		generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
14571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				getAttributeData				(std::vector<tcu::Vec4>& data) const;
14581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				renderTestPattern				(const IterationConfig& config);
14591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				verifyRenderResult				(const IterationConfig& config);
14601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2			getNumberOfLinesRange			(int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const;
14622c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				scanRow							(const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
14632c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				scanColumn						(const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& floodCounter) const;
14641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				checkAreaNumLines				(const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
14652c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				checkLineContinuity				(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const;
14661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2			getNumMinimaMaxima				(const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
146788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	deUint8				checkLineWidths					(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
14681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void				printLineWidthError				(const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& floodCounter) const;
14691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			m_patternSide;
14711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			m_isWideLineCase;
14721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			m_wideLineLineWidth;
14731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
14741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::LineRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
14761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase		(context, name, description, 12, flags)
14771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_patternSide			(12)
14781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_isWideLineCase		((flags & LINEFLAG_WIDE) != 0)
14791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_wideLineLineWidth	(5)
14801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::~LineRenderCase (void)
14841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
14861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::init (void)
14881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
14891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
14901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
14911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering line pattern to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
14921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Vertical lines are green, horizontal lines blue. Using additive blending.\n"
14931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Line segments are in random order, varying pattern size and location for each iteration.\n"
14941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated red channel."
14951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
14961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
14971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWideLineCase)
14981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
14991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glw::GLfloat lineWidthRange[2] = {0.0f, 0.0f};
15001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
15011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (lineWidthRange[1] < (float)m_wideLineLineWidth)
15031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires line width " + de::toString(m_wideLineLineWidth));
15041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
15071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
15081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genVertexSource (void) const
15101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
15111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
15121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1513cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
15141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
15151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
15161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
15171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
15181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_lineWidth;\n"
15191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
15201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
15211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
15231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
15241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
15251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
15261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
15271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
15281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
15291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
15301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
15321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
15331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
15341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
15351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
15361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
15371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
15381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
15401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
15411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = u_lineWidth;\n"
15421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
15431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
15441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
15451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
15461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
15471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
15481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
15501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
15521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
15531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genFragmentSource (void) const
15551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
15561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
15571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
15581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1559cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
15601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
15611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
15621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
15631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
15641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
15651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
15661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
15671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float redChannel;\n"
15681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
15691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 0.0;\n"
15701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
15711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 1.0;\n"
15721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(redChannel, baseColor.g, baseColor.b, baseColor.a);\n"
15731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
15741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
15761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
15771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genTessellationControlSource (void) const
15791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
15801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
15811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1582cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1583cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
1584cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${PRIMITIVE_BOUNDING_BOX_REQUIRE}\n"
15851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=2) out;"
15861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
15871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
15881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
15891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
15901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
15911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_lineWidth;\n";
15921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
15941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
15951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
15961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
15971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
15981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
15991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp float vp_bbox_expansionSize;\n"
16001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMin;\n"
16011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
16021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
16041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
16051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
16061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
16071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
16081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
16091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
16111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
16121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
16131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
16141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
16151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
16171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
16181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
16191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
16201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
16211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
16221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 0.8; // will be rounded up to 1\n"
16241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n";
16251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
16271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
16281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
16291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = min(transformVec(gl_in[0].gl_Position),\n"
16301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[1].gl_Position));\n"
16311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = max(transformVec(gl_in[0].gl_Position),\n"
16321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	                         transformVec(gl_in[1].gl_Position));\n";
16331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
16341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
16351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
16361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
16371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
16381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
16391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
16401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
16421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
1643cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[0] = bboxMin;\n"
1644cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[1] = bboxMax;\n";
16451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_expansionSize = u_lineWidth;\n"
16471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
16481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
16491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
16501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
16511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
16521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
16541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
16551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genTessellationEvaluationSource (void) const
16571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
16581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
16591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1660cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1661cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
16621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(isolines) in;"
16631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
16651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
16661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
16671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp float vp_bbox_expansionSize;\n"
16691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
16701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
16711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
16721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
16731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
16741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
16751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
16761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
16771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
16781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(mix(gl_in[0].gl_Position.zwyx, gl_in[1].gl_Position.zwyx, gl_TessCoord.x));\n"
16791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_color = tess_ctrl_color[0];\n"
16801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = vp_bbox_expansionSize;\n"
16811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
16821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
16831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
16841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
16861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
16871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
16881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string LineRenderCase::genGeometrySource (void) const
16891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
16901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
16911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
16921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
1693cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
1694cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${GEOMETRY_SHADER_REQUIRE}\n"
16951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(lines) in;\n"
16961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=5, line_strip) out;\n"
16971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
16981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[2];\n"
16991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
17001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
17011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
17021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
17031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp float v_geo_bbox_expansionSize[2];\n"
17041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[2];\n"
17051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[2];\n"
17061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
17071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
17081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
17091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
17101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
17111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void setVisualizationVaryings()\n"
17121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
17131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_expansionSize = v_geo_bbox_expansionSize[0];\n"
17141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
17151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
17161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n"
17171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
17181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
17191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
17201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
17211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p1 = mirrorX(gl_in[1].gl_Position);\n"
17221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 lineColor = " << colorInputName << "[0];\n"
17231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
17241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// output two separate primitives, just in case\n"
17251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.00); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
17261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.33); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
17271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
17281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
17291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.33); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
17301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 0.67); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
17311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mix(p0, p1, 1.00); geo_color = lineColor; setVisualizationVaryings(); EmitVertex();\n"
17321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	EndPrimitive();\n"
17331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
17341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
17361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryLineRenderCase::IterationConfig LineRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
17391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int numMaxAttempts = 128;
17411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Avoid too narrow viewports, lines could merge together. Require viewport is at least 2.5x the size of the line bodies.
17431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int attemptNdx = 0; attemptNdx < numMaxAttempts; ++attemptNdx)
17441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
17451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const IterationConfig& config = generateRandomConfig((0xDEDEDEu * (deUint32)iteration) ^ (0xABAB13 * attemptNdx), renderTargetSize);
17461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17477a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		if ((float)config.viewportSize.x() * (config.patternSize.x() * 0.5f) > 2.5f * (float)m_patternSide * (float)m_wideLineLineWidth &&
17487a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			(float)config.viewportSize.y() * (config.patternSize.y() * 0.5f) > 2.5f * (float)m_patternSide * (float)m_wideLineLineWidth)
17491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return config;
17511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
17531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(false);
17551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return IterationConfig();
17561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
17591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
17611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		blue		(0.0f, 0.0f, 1.0f, 1.0f);
17621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder	(m_patternSide * m_patternSide * 2);
17631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd			(0xDE12345);
17641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate crosshatch pattern with segments in random order
17661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
17671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
17681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
17691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(cellOrder.size() * 4);
17711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
17721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
17731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int segmentID		= cellOrder[ndx];
17741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int direction		= segmentID & 0x01;
17751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int majorCoord	= (segmentID >> 1) / m_patternSide;
17761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int minorCoord	= (segmentID >> 1) % m_patternSide;
17771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (direction)
17791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17807a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
17811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
17827a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
17831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
17841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
17861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
17877a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
17881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 0) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
17897a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
17901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[(ndx * 2 + 1) * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
17911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
17921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
17931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
17941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::renderTestPattern (const IterationConfig& config)
17961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
17971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
17981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
17991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
18001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
18021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
18031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
18041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 2.8f; // will be rounded up
18051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
18071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
18091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
18111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 2);
18121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
18131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
18141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWideLineCase)
18161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.lineWidth((float)m_wideLineLineWidth);
18171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18187a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	gl.uniform1f(gl.getUniformLocation(m_program->getProgram(), "u_lineWidth"), (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f));
18191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering pattern." << tcu::TestLog::EndMessage;
18211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_BLEND);
18231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendFunc(GL_ONE, GL_ONE);
18241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendEquation(GL_FUNC_ADD);
18251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_LINES), 0, m_patternSide * m_patternSide * 2 * 2);
18271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
18281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
18291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::verifyRenderResult (const IterationConfig& config)
18311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
183288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const glw::Functions&	gl							= m_context.getRenderContext().getFunctions();
183388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const bool				isMsaa						= m_context.getRenderTarget().getNumSamples() > 1;
183488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const ProjectedBBox		projectedBBox				= projectBoundingBox(config.bbox);
183588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const float				lineWidth					= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
183688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec4		viewportBBoxArea			= getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
183788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec4		viewportPatternArea			= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
183888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec2		expectedHorizontalLines		= getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
183988591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec2		expectedVerticalLines		= getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
184088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec4		verificationArea			= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
184188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos																	 de::max(viewportBBoxArea.y(), 0),
184288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos																	 de::min(viewportBBoxArea.z(), config.viewportSize.x()),
184388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos																	 de::min(viewportBBoxArea.w(), config.viewportSize.y()));
184488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
184588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	tcu::Surface			viewportSurface				(config.viewportSize.x(), config.viewportSize.y());
184688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	int						messageLimitCounter			= 8;
18471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18482c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	enum ScanResultCodes
18492c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
18502c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_NUM_LINES_ERR	= 0,
18512c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_MSAA	= 1,
18522c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_WARN	= 2,
18532c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_WIDTH_ERR	= 3,
18542c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_ERR	= 4,
18552c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_CONT_WARN	= 5,
18562c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		SCANRESULT_LINE_LAST
18572c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	};
18582c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
18592c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int						rowScanResult[SCANRESULT_LINE_LAST]		= {0, 0, 0, 0, 0, 0};
18602c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int						columnScanResult[SCANRESULT_LINE_LAST]	= {0, 0, 0, 0, 0, 0};
18612c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					anyError								= false;
18622c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					msaaRelaxationRequired					= false;
18632c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool					hwIssueRelaxationRequired				= false;
18642c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
18651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
18661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
18671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
18681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
18691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
18701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
18711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
18721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
18731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
18741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
18751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box:\n"
18761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
18771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
18781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
18791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
18801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result:"
18811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
18821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
18841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
18851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tCalculating number of horizontal and vertical lines within the bounding box, expecting:\n"
18861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\t[" << expectedHorizontalLines.x() << ", " << expectedHorizontalLines.y() << "] horizontal lines.\n"
18871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\t[" << expectedVerticalLines.x() << ", " << expectedVerticalLines.y() << "] vertical lines.\n"
18881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
18891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
18911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
18921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
18931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
18941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// scan rows
18951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = de::max(verificationArea.y(), viewportPatternArea.y()); y < de::min(verificationArea.w(), viewportPatternArea.w()); ++y)
1896f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
189725ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry		const deUint8 result = scanRow(viewportSurface.getAccess(),
189825ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   y,
189925ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   verificationArea.x(),
190025ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   verificationArea.z(),
19012c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin									   de::max(verificationArea.x(), viewportPatternArea.x()),
19022c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin									   de::min(verificationArea.z(), viewportPatternArea.z()),
190325ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   expectedVerticalLines,
190425ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry									   messageLimitCounter);
1905f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
1906f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
19072c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			rowScanResult[SCANRESULT_NUM_LINES_ERR]++;
19082c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
19092c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
19102c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
19112c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_CONT_WARN]++;
19122c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else
19132c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_CONT_ERR]++;
19142c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
1915f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
1916f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
1917f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			if (m_isWideLineCase && isMsaa)
1918f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			{
1919f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry				// multisampled wide lines might not be supported
19202c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
1921f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			}
192288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
192388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					 (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
192488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			{
19252c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
192688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			}
1927f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			else
19282c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				rowScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
1929f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
1930f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	}
19311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
19321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// scan columns
19331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = de::max(verificationArea.x(), viewportPatternArea.x()); x < de::min(verificationArea.z(), viewportPatternArea.z()); ++x)
1934f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	{
193525ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry		const deUint8 result = scanColumn(viewportSurface.getAccess(),
193625ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  x,
193725ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  verificationArea.y(),
193825ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  verificationArea.w(),
19392c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin										  de::min(verificationArea.y(), viewportPatternArea.y()),
19402c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin										  de::min(verificationArea.w(), viewportPatternArea.w()),
194125ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  expectedHorizontalLines,
194225ed53b938fad9545a74fbebc3b7eaf7136852faJarkko Pöyry										  messageLimitCounter);
1943f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
1944f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if ((result & SCANRESULT_NUM_LINES_OK_BIT) == 0)
19452c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			columnScanResult[SCANRESULT_NUM_LINES_ERR]++;
19462c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if ((result & SCANRESULT_LINE_CONT_OK_BIT) == 0)
19472c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
19482c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((result & SCANRESULT_LINE_CONT_WARN_BIT) != 0)
19492c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_CONT_WARN]++;
19502c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else
19512c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_CONT_ERR]++;
19522c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
1953f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else if ((result & SCANRESULT_LINE_WIDTH_OK_BIT) == 0)
1954f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
1955f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			if (m_isWideLineCase && isMsaa)
1956f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			{
1957f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry				// multisampled wide lines might not be supported
19582c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_MSAA]++;
1959f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			}
19602c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
19612c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin					 (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
196288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			{
19632c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_WARN]++;
196488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			}
1965f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			else
19662c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				columnScanResult[SCANRESULT_LINE_WIDTH_ERR]++;
1967f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
1968f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry	}
19691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
19702c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (columnScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_ERR] != 0)
19712c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		anyError = true;
19722c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if(columnScanResult[SCANRESULT_LINE_CONT_ERR] != 0 || rowScanResult[SCANRESULT_LINE_CONT_ERR] != 0)
19732c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		anyError = true;
19742c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_MSAA] != 0)
19752c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		msaaRelaxationRequired = true;
19762c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0 || rowScanResult[SCANRESULT_LINE_WIDTH_WARN] != 0)
19772c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		hwIssueRelaxationRequired = true;
19782c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (columnScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
19792c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
19802c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// found missing lines in a columnw and row line continuity check reported a warning (not an error) -> line width precision issue
19812c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (rowScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && rowScanResult[SCANRESULT_LINE_CONT_WARN])
19822c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			hwIssueRelaxationRequired = true;
19832c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
19842c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			anyError = true;
19852c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
19862c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else if (rowScanResult[SCANRESULT_NUM_LINES_ERR] != 0)
19872c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
19882c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// found missing lines in a row and column line continuity check reported a warning (not an error) -> line width precision issue
19892c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (columnScanResult[SCANRESULT_LINE_CONT_ERR] == 0 && columnScanResult[SCANRESULT_LINE_CONT_WARN])
19902c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			hwIssueRelaxationRequired = true;
19912c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
19922c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			anyError = true;
19932c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
19942c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
199588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	if (anyError || msaaRelaxationRequired || hwIssueRelaxationRequired)
19961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
19971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (messageLimitCounter < 0)
19981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
19991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
20011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
20021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
20031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
20041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
20051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
20061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
20071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2008f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		if (anyError)
2009f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
201088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		else if (hwIssueRelaxationRequired)
201188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		{
201288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			// Line width hw issue
201388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Line width verification failed");
201488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		}
2015f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		else
2016f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		{
2017f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			// MSAA wide lines are optional
2018f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry			m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Multisampled wide line verification failed");
2019f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry		}
20201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
20211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
202230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
202330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
202430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
202530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
202630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
202730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
202830fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
202930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
203030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
20311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 LineRenderCase::getNumberOfLinesRange (int queryAreaBegin, int queryAreaEnd, float patternStart, float patternSize, int viewportArea, QueryDirection queryDir) const
20341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// pattern is not symmetric due to mirroring
20361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int	patternStartNdx	= (queryDir == DIRECTION_HORIZONTAL) ? ((m_hasGeometryStage) ? (1) : (0)) : ((m_hasTessellationStage) ? (1) : (0));
20371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int	patternEndNdx	= patternStartNdx + m_patternSide;
20381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int			numLinesMin		= 0;
20401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int			numLinesMax		= 0;
20411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int lineNdx = patternStartNdx; lineNdx < patternEndNdx; ++lineNdx)
20431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
20447a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		const float linePos		= (patternStart + (float(lineNdx) / float(m_patternSide)) * patternSize) * 0.5f + 0.5f;
20457a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		const float lineWidth	= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
20461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20477a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		if (linePos * (float)viewportArea > (float)queryAreaBegin + 1.0f &&
20487a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			linePos * (float)viewportArea < (float)queryAreaEnd   - 1.0f)
20491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
20501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// line center is within the area
20511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMin;
20521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMax;
20531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
20547a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		else if (linePos * (float)viewportArea > (float)queryAreaBegin - lineWidth*0.5f - 1.0f &&
20557a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		         linePos * (float)viewportArea < (float)queryAreaEnd   + lineWidth*0.5f + 1.0f)
20561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
20571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// line could leak into area
20581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++numLinesMax;
20591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
20601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
20611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(numLinesMin, numLinesMax);
20631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20652c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, int rowViewportBegin, int rowViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
20661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20672c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const bool		numLinesOk			= checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
20682c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineWidthRes		= checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
20692c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineContinuityRes	= checkLineContinuity(access, tcu::IVec2(rowViewportBegin, row), tcu::IVec2(rowViewportEnd, row), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
20702c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8			result				= 0;
207188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
207288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	if (numLinesOk)
207388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
207488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
20752c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (lineContinuityRes == 0)
20762c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
20772c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else
20782c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= lineContinuityRes;
20792c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
208088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	if (lineWidthRes == 0)
208188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
208288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	else
208388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= lineWidthRes;
2084f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
208588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	return result;
20861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
20871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
20882c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, int columnViewportBegin, int columnViewportEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
20891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
20902c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const bool		numLinesOk			= checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
20912c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineWidthRes		= checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
20922c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const deUint8	lineContinuityRes	= checkLineContinuity(access, tcu::IVec2(column, columnViewportBegin), tcu::IVec2(column, columnViewportEnd), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
20932c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8			result				= 0;
209488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
209588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	if (numLinesOk)
209688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
209788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
20982c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	if (lineContinuityRes == 0)
20992c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= (deUint8)SCANRESULT_LINE_CONT_OK_BIT;
21002c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	else
21012c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		result |= lineContinuityRes;
21022c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
210388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	if (lineWidthRes == 0)
210488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
210588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	else
210688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos		result |= lineWidthRes;
2107f0ca13a370eeeff83ecf3c4d76a13d51dabf4297Jarkko Pöyry
210888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	return result;
21091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
21101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const
21121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
21131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Num maxima == num lines
21141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::ConstPixelBufferAccess	subAccess		= tcu::getSubregion(access, area.x(), area.y(), 0, area.z(), area.w(), 1);
21151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2					numMinimaMaxima	= getNumMinimaMaxima(subAccess, componentNdx);
21161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int							numMaxima		= numMinimaMaxima.y();
21171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// In valid range
21191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (numMaxima >= numLines.x() && numMaxima <= numLines.y())
21201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
21211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--messageLimitCounter < 0)
21231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return false;
21241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (area.z() == 1)
21261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
21271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
21281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "On column " << area.x() << ", y: [" << area.y() << "," << (area.y()+area.w()) << "):\n"
21291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tExpected [" << numLines.x() << ", " << numLines.y() << "] lines but the number of lines in the area is " << numMaxima
21301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
21311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
21321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
21331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
21341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "On row " << area.y() << ", x: [" << area.x() << "," << (area.x()+area.z()) << "):\n"
21351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tExpected [" << numLines.x() << ", " << numLines.y() << "] lines but the number of lines in the area is " << numMaxima
21361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
21371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
21391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
21401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 LineRenderCase::getNumMinimaMaxima (const tcu::ConstPixelBufferAccess& access, int componentNdx) const
21421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
21431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(access.getWidth() == 1 || access.getHeight() == 1);
21441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int previousValue	= -1;
21461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int previousSign	= 0;
21471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int numMinima		= 0;
21481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int numMaxima		= 0;
21491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < access.getHeight(); ++y)
21511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < access.getWidth(); ++x)
21521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
21531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int componentValue = access.getPixelInt(x, y)[componentNdx];
21541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (previousValue != -1)
21561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
21571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int sign = (componentValue > previousValue) ? (+1) : (componentValue < previousValue) ? (-1) : (0);
21581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// local minima/maxima in sign changes (zero signless)
21601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (sign != 0 && sign == -previousSign)
21611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
21621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				previousSign = sign;
21631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (sign > 0)
21651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMinima;
21661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
21671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMaxima;
21681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
21691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (sign != 0 && previousSign == 0)
21701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
21711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				previousSign = sign;
21721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// local extreme at the start boundary
21741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (sign > 0)
21751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMinima;
21761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
21771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					++numMaxima;
21781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
21791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
21801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		previousValue = componentValue;
21821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
21831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// local extreme at the end boundary
21851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (previousSign > 0)
21861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMaxima;
21871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (previousSign < 0)
21881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMinima;
21891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
21901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
21911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMaxima;
21921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		++numMinima;
21931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
21941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(numMinima, numMaxima);
21961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
21971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
21982c9e3ec924255e414dc5e183b91348a1507d4d53Alexander GalazindeUint8 LineRenderCase::checkLineContinuity (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
21992c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin{
22002c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	bool				line					= false;
22012c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	const tcu::IVec2	advance					= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
22022c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int					missedPixels			= 0;
22032c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	int					totalPixels				= 0;
22042c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	deUint8				errorMask				= 0;
22052c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
22062c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	for (tcu::IVec2 cursor = begin; cursor != end; cursor += advance)
22072c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
22082c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		const bool hit = (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0);
22092c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
22102c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		if (hit)
22112c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			line = true;
22122c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else if (line && !hit)
22132c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		{
22142c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			// non-continuous line detected
22152c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 advanceNeighbor	= tcu::IVec2(1, 1) - advance;
22162c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 cursorNeighborPos	= cursor + advanceNeighbor;
22172c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			const tcu::IVec2 cursorNeighborNeg	= cursor - advanceNeighbor;
22182c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			// hw precision issues may lead to a line being non-straight -> check neighboring pixels
22192c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			if ((access.getPixelInt(cursorNeighborPos.x(), cursorNeighborPos.y())[componentNdx] == 0) && (access.getPixelInt(cursorNeighborNeg.x(), cursorNeighborNeg.y())[componentNdx] == 0))
22202c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin				++missedPixels;
22212c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		}
22222c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		++totalPixels;
22232c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
22242c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
2225c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin	if (missedPixels > 0)
22262c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	{
2227c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin		if (--messageLimitCounter >= 0)
2228c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin		{
2229c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin			m_testCtx.getLog()
2230c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin				<< tcu::TestLog::Message
2231c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin				<< "Found non-continuous " << ((advance.x() == 1)  ? ("horizontal") : ("vertical")) << " line near " << begin << ". "
2232c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin				<< "Missed pixels: " << missedPixels
2233c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin				<< tcu::TestLog::EndMessage;
2234c29f0d0ec4b848568e5f602cd67f89a0d25fd50cAlexander Galazin		}
22352c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		// allow 10% missing pixels for warning
2236d8b452a7533c195b1328918bb696a819542ff044Pyry Haulos		if (missedPixels <= deRoundFloatToInt32((float)totalPixels * 0.1f))
22372c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			errorMask = SCANRESULT_LINE_CONT_WARN_BIT;
22382c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin		else
22392c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin			errorMask =  SCANRESULT_LINE_CONT_ERR_BIT;
22402c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	}
22412c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
22422c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin	return errorMask;
22432c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin}
22442c9e3ec924255e414dc5e183b91348a1507d4d53Alexander Galazin
224588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry HaulosdeUint8 LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
22461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
224788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const bool			multisample				= m_context.getRenderTarget().getNumSamples() > 1;
224888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const int			lineRenderWidth			= (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
224988591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec2	lineWidthRange			= (multisample)
225088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos													? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1))	// multisampled "smooth" lines may spread to neighboring pixel
225188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos													: (tcu::IVec2(lineRenderWidth, lineRenderWidth));
225288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec2	relaxedLineWidthRange	= (tcu::IVec2(lineRenderWidth-1, lineRenderWidth+1));
22531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
225488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	int					lineWidth				= 0;
225588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	bool				bboxLimitedLine			= false;
225688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	deUint8				errorMask				= 0;
22571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
225888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	const tcu::IVec2	advance					= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
22591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fragments before begin?
22611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (access.getPixelInt(begin.x(), begin.y())[componentNdx] != 0)
22621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
22631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bboxLimitedLine = true;
22641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (tcu::IVec2 cursor = begin - advance;; cursor -= advance)
22661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
22671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (cursor.x() < 0 || cursor.y() < 0)
22681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
22701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0)
22721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
22731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				++lineWidth;
22741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
22751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
22761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
22771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
22781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
22791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (tcu::IVec2 cursor = begin; cursor != end; cursor += advance)
22811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
22821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool hit = (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0);
22831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (hit)
22851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			++lineWidth;
22861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (lineWidth)
22871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
22881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// Line is allowed to be be thinner if it borders the bbox boundary (since part of the line might have been discarded).
22891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool incorrectLineWidth = (lineWidth < lineWidthRange.x() && !bboxLimitedLine) || (lineWidth > lineWidthRange.y());
22901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
22911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (incorrectLineWidth)
22921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
229388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos				const bool incorrectRelaxedLineWidth = (lineWidth < relaxedLineWidthRange.x() && !bboxLimitedLine) || (lineWidth > relaxedLineWidthRange.y());
229488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
229588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos				if (incorrectRelaxedLineWidth)
229688591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
229788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos				else
229888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
229988591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
23001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
23011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
23021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			lineWidth = 0;
23041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxLimitedLine = false;
23051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
23061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
23071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fragments after end?
23091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (lineWidth)
23101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (tcu::IVec2 cursor = end;; cursor += advance)
23121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
23131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (cursor.x() >= access.getWidth() || cursor.y() >= access.getHeight())
23141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
23151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (lineWidth > lineWidthRange.y())
23161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
231788591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					if (lineWidth > relaxedLineWidthRange.y())
231888591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
231988591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					else
232088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
232188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
23221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
23231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
23241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				break;
23261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
23271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (access.getPixelInt(cursor.x(), cursor.y())[componentNdx] != 0)
23281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
23291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				++lineWidth;
23301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
23311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else if (lineWidth)
23321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
23331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// only check that line width is not larger than expected. Line width may be smaller
23341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// since the scanning 'cursor' is now outside the bounding box.
23351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const bool incorrectLineWidth = (lineWidth > lineWidthRange.y());
23361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (incorrectLineWidth)
23381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
233988591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					const bool incorrectRelaxedLineWidth = (lineWidth > relaxedLineWidthRange.y());
234088591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
234188591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					if (incorrectRelaxedLineWidth)
234288591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
234388591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos					else
234488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
234588591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos
23461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
23471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
23481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				lineWidth = 0;
23501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
23511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
23521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
23531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
235488591709a4f087d1ff8df373b9dfcf4b1913e91aPyry Haulos	return errorMask;
23551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid LineRenderCase::printLineWidthError (const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& messageLimitCounter) const
23581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--messageLimitCounter < 0)
23601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return;
23611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
23631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
23641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Found incorrect line width near " << pos << ": (" << ((isHorizontal) ? ("horizontal") : ("vertical")) << " line)\n"
23651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\tExpected line width in range [" << lineWidthRange.x() << ", " << lineWidthRange.y() << "] but found " << detectedLineWidth
23661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
23671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
23681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass PointRenderCase : public BBoxRenderCase
23701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
23711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
23721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
23731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINTFLAG_WIDE = 1u << FLAGBIT_USER_BIT,	//!< use wide points
23751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct GeneratedPoint
23771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec2	center;
23791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int			size;
23801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool		even;
23811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							PointRenderCase					(Context& context, const char* name, const char* description, deUint32 flags);
23841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							~PointRenderCase				(void);
23851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
23871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum ResultPointType
23881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
23891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINT_FULL = 0,
23901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		POINT_PARTIAL
23911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
23921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					init							(void);
23941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					deinit							(void);
23951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
23961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genVertexSource					(void) const;
23971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genFragmentSource				(void) const;
23981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genTessellationControlSource	(void) const;
23991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genTessellationEvaluationSource	(void) const;
24001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string				genGeometrySource				(void) const;
24011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig			generateConfig					(int iteration, const tcu::IVec2& renderTargetSize) const;
24031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					generateAttributeData			(void);
24041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					getAttributeData				(std::vector<tcu::Vec4>& data) const;
24051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					renderTestPattern				(const IterationConfig& config);
24061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					verifyRenderResult				(const IterationConfig& config);
24071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void					genReferencePointData			(const IterationConfig& config, std::vector<GeneratedPoint>& data) const;
24091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyNarrowPointPattern		(const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter);
24101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyWidePointPattern			(const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter);
24111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					verifyWidePoint					(const tcu::Surface& viewport, const GeneratedPoint& refPoint, const ProjectedBBox& bbox, ResultPointType pointType, int& logFloodCounter);
24121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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);
24131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::IVec2				scanPointWidthAt				(const tcu::IVec2& pointPos, const tcu::Surface& viewport, int expectedPointSize, int componentNdx) const;
24141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				m_numStripes;
24161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				m_isWidePointCase;
24171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>	m_attribData;
24181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
24191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::PointRenderCase (Context& context, const char* name, const char* description, deUint32 flags)
24211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: BBoxRenderCase	(context, name, description, 12, flags)
24221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numStripes		(4)
24231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_isWidePointCase	((flags & POINTFLAG_WIDE) != 0)
24241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::~PointRenderCase (void)
24281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::init (void)
24321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
24341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
24351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// extensions
24361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_point_size"))
24371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires GL_EXT_geometry_point_size extension");
24381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage && !m_hasGeometryStage && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_point_size"))
24391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_point_size extension");
24401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// point size range
24421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
24431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			glw::GLfloat pointSizeRange[2] = {0.0f, 0.0f};
24441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
24451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pointSizeRange[1] < 5.0f)
24471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				throw tcu::NotSupportedError("Test requires point size 5.0");
24481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
24491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
24501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
24521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
24531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering point pattern to " << ((m_renderTarget == RENDERTARGET_DEFAULT) ? ("default frame buffer") : ("fbo")) << ".\n"
24541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Half of the points are green, half blue. Using additive blending.\n"
24551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Points are in random order, varying pattern size and location for each iteration.\n"
24561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Marking all discardable fragments (fragments outside the bounding box) with a fully saturated red channel."
24571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
24581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	generateAttributeData();
24601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::init();
24621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::deinit (void)
24651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// clear data
24671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_attribData = std::vector<tcu::Vec4>();
24681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// deinit parent
24701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	BBoxRenderCase::deinit();
24711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
24721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genVertexSource (void) const
24741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
24751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
24761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2477cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
24781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
24791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_color;\n"
24801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_color;\n"
24811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
24821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n";
24831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
24841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
24851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
24861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
24871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n"
24881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n"
24891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp float v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize;\n"
24901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
24911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
24921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"\n";
24931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
24941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
24951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"void main()\n"
24961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
24971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternOffset = u_posScale.xy;\n"
24981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
24991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = "
25001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< ((m_isWidePointCase && !m_hasTessellationStage && !m_hasGeometryStage) ? ("(a_color.g > 0.0) ? (5.0) : (3.0)") : ("1.0"))
25011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					<< ";\n"
25021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"	gl_Position = vec4(a_position.xy * patternScale + patternOffset, a_position.z, a_position.w);\n"
25031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_PointSize = pointSize;\n"
25041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vtx_color = a_color;\n";
25051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_hasTessellationStage)
25071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DE_ASSERT(m_useGlobalState);
25091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
25101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_expansionSize = pointSize;\n"
25111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin =\n"
25121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMin.w,\n"
25131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMin.x, u_primitiveBBoxMin.y, u_primitiveBBoxMin.z) / u_primitiveBBoxMax.w);\n"
25141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax =\n"
25151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	    min(vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMin.w,\n"
25161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	        vec3(u_primitiveBBoxMax.x, u_primitiveBBoxMax.y, u_primitiveBBoxMax.z) / u_primitiveBBoxMax.w);\n";
25171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
25201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
25211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
25221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genFragmentSource (void) const
25241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
25251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasGeometryStage) ? ("geo_color") : (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
25261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
25271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2528cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
25291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorInputName << ";\n"
25301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(location = 0) out mediump vec4 o_color;\n"
25311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_INSIDE_BBOX)
25321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
25331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
25341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
25351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump vec4 baseColor = " << colorInputName << ";\n"
25361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	mediump float redChannel;\n"
25371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	if (fragmentInsideTheBBox(gl_FragCoord.z))\n"
25381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 0.0;\n"
25391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	else\n"
25401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		redChannel = 1.0;\n"
25411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = vec4(redChannel, baseColor.g, baseColor.b, baseColor.a);\n"
25421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
25431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
25451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
25461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genTessellationControlSource (void) const
25481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
25491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			tessellationWidePoints = (m_isWidePointCase) && (!m_hasGeometryStage);
25501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
25511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2552cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
2553cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
2554cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${PRIMITIVE_BOUNDING_BOX_REQUIRE}\n"
2555cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		<<	((tessellationWidePoints) ? ("${TESSELLATION_POINT_SIZE_REQUIRE}\n") : (""))
25561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(vertices=1) out;"
25571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
25581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_color[];\n"
25591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_color[];\n"
25601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_tessellationLevel;\n"
25611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n";
25621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
25641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp vec4 u_primitiveBBoxMin;\n"
25661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp vec4 u_primitiveBBoxMax;\n";
25671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"patch out highp vec3 vp_bbox_clipMin;\n"
25701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch out highp vec3 vp_bbox_clipMax;\n";
25711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
25731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
25741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
25751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
25761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf << genShaderFunction(SHADER_FUNC_MIRROR_X);
25771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << genShaderFunction(SHADER_FUNC_MIRROR_Y);
25781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"vec4 transformVec(in highp vec4 p)\n"
25801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"{\n"
25811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	return " << ((m_hasGeometryStage) ? ("mirrorX(mirrorY(p))") : ("mirrorY(p)")) << ";\n"
25821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"}\n";
25831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
25841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
25861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
25871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
25881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// convert to nonsensical coordinates, just in case\n"
25891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position.wzxy;\n"
25901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_color[gl_InvocationID] = vtx_color[gl_InvocationID];\n"
25911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
25921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = u_tessellationLevel;\n"
25931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = u_tessellationLevel;\n"
25941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = u_tessellationLevel;\n"
25951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[3] = u_tessellationLevel;\n"
25961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 0.8; // will be rounded up to 1\n"
25971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[1] = 0.8; // will be rounded up to 1\n";
25981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
25991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_calcPerPrimitiveBBox)
26001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
26011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n";
26021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
26041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf <<	"	const vec2 minExpansion = vec2(0.07 + 0.05, 0.07 + 0.02); // eval and geometry shader\n"
26051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	const vec2 maxExpansion = vec2(0.07 + 0.05, 0.07 + 0.03); // eval and geometry shader\n";
26061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
26071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			buf <<	"	const vec2 minExpansion = vec2(0.07, 0.07); // eval shader\n"
26081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					"	const vec2 maxExpansion = vec2(0.07, 0.07); // eval shader\n";
26091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp vec2 patternScale = u_posScale.zw;\n"
26111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = transformVec(gl_in[0].gl_Position) - vec4(minExpansion * patternScale, 0.0, 0.0);\n"
26121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = transformVec(gl_in[0].gl_Position) + vec4(maxExpansion * patternScale, 0.0, 0.0);\n";
26131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
26141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
26151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
26161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
26171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMin = u_primitiveBBoxMin;\n"
26181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp vec4 bboxMax = u_primitiveBBoxMax;\n";
26191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
26201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
26211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
2622cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[0] = bboxMin;\n"
2623cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[1] = bboxMax;\n";
26241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vp_bbox_clipMin = min(vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMin.w,\n"
26261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMin.x, bboxMin.y, bboxMin.z) / bboxMax.w);\n"
26271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	vp_bbox_clipMax = max(vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMin.w,\n"
26281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                      vec3(bboxMax.x, bboxMax.y, bboxMax.z) / bboxMax.w);\n"
26291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
26301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
26321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
26331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genTessellationEvaluationSource (void) const
26351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
26361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			tessellationWidePoints = (m_isWidePointCase) && (!m_hasGeometryStage);
26371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
26381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2639cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
2640cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
2641cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		<<	((tessellationWidePoints) ? ("${TESSELLATION_POINT_SIZE_REQUIRE}\n") : (""))
26421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(quads, point_mode) in;"
26431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_color[];\n"
26451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_color;\n"
26461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
26471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMin;\n"
26491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"patch in highp vec3 vp_bbox_clipMax;\n"
26501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((!m_hasGeometryStage) ? ("flat out highp float v_bbox_expansionSize;\n") : (""))
26511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin;\n"
26521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax;\n"
26531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_Y)
26551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"void main()\n"
26561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
26571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// non-trivial tessellation evaluation shader, convert from nonsensical coords, flip vertically\n"
26581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
26591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 offset = vec4((gl_TessCoord.xy * 2.0 - vec2(1.0)) * 0.07 * patternScale, 0.0, 0.0);\n"
26601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = " << ((tessellationWidePoints) ? ("(tess_ctrl_color[0].g > 0.0) ? (5.0) : (3.0)") : ("1.0")) << ";\n"
26611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_Position = mirrorY(gl_in[0].gl_Position.zwyx + offset);\n";
26621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (tessellationWidePoints)
26641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_PointSize = pointSize;\n";
26651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	tess_color = tess_ctrl_color[0];\n"
26671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	((!m_hasGeometryStage) ? ("v_bbox_expansionSize = pointSize;\n") : (""))
26681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMin = vp_bbox_clipMin;\n"
26691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_" << (m_hasGeometryStage ? "geo_" : "") << "bbox_clipMax = vp_bbox_clipMax;\n"
26701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
26711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
26731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
26741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
26751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string PointRenderCase::genGeometrySource (void) const
26761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
26771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorInputName = (m_hasTessellationStage) ? ("tess_color") : ("vtx_color");
26781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
26791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
2680cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
2681cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${GEOMETRY_SHADER_REQUIRE}\n"
2682cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		<<	((m_isWidePointCase) ? ("${GEOMETRY_POINT_SIZE}\n") : (""))
26831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"layout(points) in;\n"
26841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(max_vertices=3, points) out;\n"
26851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 " << colorInputName << "[1];\n"
26871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 geo_color;\n"
26881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_posScale;\n"
26891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMin[1];\n"
26911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat in highp vec3 v_geo_bbox_clipMax[1];\n"
26921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMin;\n"
26931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp vec3 v_bbox_clipMax;\n"
26941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"flat out highp float v_bbox_expansionSize;\n"
26951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
26961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	genShaderFunction(SHADER_FUNC_MIRROR_X)
26971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\n"
26981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
26991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
27001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// Non-trivial geometry shader: 1-to-3 amplification, mirror horizontally\n"
27011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 p0 = mirrorX(gl_in[0].gl_Position);\n"
27021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 pointColor = " << colorInputName << "[0];\n"
27031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec2 patternScale = u_posScale.zw;\n"
27041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp float pointSize = "
27051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< (m_isWidePointCase ? ("(pointColor.g > 0.0) ? (5.0) : (3.0)") : ("1.0"))
27061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< ";\n"
27071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
27081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	highp vec4 offsets[3] =\n"
2709cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"		vec4[3](\n"
2710cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4( 0.05 * patternScale.x, 0.03 * patternScale.y, 0.0, 0.0),\n"
2711cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4(-0.01 * patternScale.x,-0.02 * patternScale.y, 0.0, 0.0),\n"
2712cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"			vec4(-0.05 * patternScale.x, 0.02 * patternScale.y, 0.0, 0.0)\n"
2713cdde9ab50faadb94feeb12eeaf26195af1d0bc67Jarkko Pöyry			"		);\n"
27141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	for (int ndx = 0; ndx < 3; ++ndx)\n"
27151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	{\n"
27161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		gl_Position = p0 + offsets[ndx];\n";
27171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
27191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"		gl_PointSize = pointSize;\n";
27201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"		v_bbox_clipMin = v_geo_bbox_clipMin[0];\n"
27221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		v_bbox_clipMax = v_geo_bbox_clipMax[0];\n"
27231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		v_bbox_expansionSize = pointSize;\n"
27241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		geo_color = pointColor;\n"
27251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"		EmitVertex();\n"
27261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	}\n"
27271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
27281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
27301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPointRenderCase::IterationConfig PointRenderCase::generateConfig (int iteration, const tcu::IVec2& renderTargetSize) const
27331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterationConfig config = generateRandomConfig(0xDEDEDEu * (deUint32)iteration, renderTargetSize);
27351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// equal or larger -> expand according to shader expansion
27371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOXSIZE_EQUAL || m_bboxSize == BBOXSIZE_LARGER)
27381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
27391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec2 patternScale = config.patternSize;
27401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasTessellationStage)
27421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.min -= tcu::Vec4(0.07f * patternScale.x(), 0.07f * patternScale.y(), 0.0f, 0.0f);
27441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.max += tcu::Vec4(0.07f * patternScale.x(), 0.07f * patternScale.y(), 0.0f, 0.0f);
27451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_hasGeometryStage)
27471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.min -= tcu::Vec4(0.05f * patternScale.x(), 0.02f * patternScale.y(), 0.0f, 0.0f);
27491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			config.bbox.max += tcu::Vec4(0.05f * patternScale.x(), 0.03f * patternScale.y(), 0.0f, 0.0f);
27501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
27521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return config;
27541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::generateAttributeData (void)
27571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
27591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		blue		(0.0f, 0.0f, 1.0f, 1.0f);
27601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder	(m_numStripes * m_numStripes * 2);
27611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd			(0xDE22446);
27621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
27641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
27651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
27661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_attribData.resize(cellOrder.size() * 2);
27681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
27691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
27701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int pointID		= cellOrder[ndx];
27711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int direction		= pointID & 0x01;
27721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int majorCoord	= (pointID >> 1) / m_numStripes;
27731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int minorCoord	= (pointID >> 1) % m_numStripes;
27741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (direction)
27761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27777a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
27781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = green;
27791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
27811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
27827a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
27831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_attribData[ndx * VA_NUM_ATTRIB_VECS + VA_COL_VEC_NDX] = blue;
27841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
27851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
27861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::getAttributeData (std::vector<tcu::Vec4>& data) const
27891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data = m_attribData;
27911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
27921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::renderTestPattern (const IterationConfig& config)
27941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
27951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
27961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	setupRender(config);
27981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
27991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
28001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLint	tessLevelPos	= gl.getUniformLocation(m_program->getProgram(), "u_tessellationLevel");
28021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const glw::GLfloat	tessLevel		= 0.8f; // will be rounded up
28031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(tessLevelPos != -1);
28051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog() << tcu::TestLog::Message << "u_tessellationLevel = " << tessLevel << tcu::TestLog::EndMessage;
28071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(tessLevelPos, tessLevel);
28091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 1);
28101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "patch param");
28111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
28121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering pattern." << tcu::TestLog::EndMessage;
28141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_BLEND);
28161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendFunc(GL_ONE, GL_ONE);
28171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blendEquation(GL_FUNC_ADD);
28181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays((m_hasTessellationStage) ? (GL_PATCHES) : (GL_POINTS), 0, m_numStripes * m_numStripes * 2);
28201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
28211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
28221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::verifyRenderResult (const IterationConfig& config)
28241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
28251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&		gl						= m_context.getRenderContext().getFunctions();
28261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const ProjectedBBox			projectedBBox			= projectBoundingBox(config.bbox);
28271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4			viewportBBoxArea		= getViewportBoundingBoxArea(projectedBBox, config.viewportSize);
28281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface				viewportSurface			(config.viewportSize.x(), config.viewportSize.y());
28301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int							logFloodCounter			= 8;
28311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool						anyError;
28321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<GeneratedPoint>	refPoints;
28331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_calcPerPrimitiveBBox)
28351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
28361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
28371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Projected bounding box: (clip space)\n"
28381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << projectedBBox.min.x() << "," << projectedBBox.max.x() << "]\n"
28391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << projectedBBox.min.y() << "," << projectedBBox.max.y() << "]\n"
28401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tz: [" << projectedBBox.min.z() << "," << projectedBBox.max.z() << "]\n"
28411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "In viewport coordinates:\n"
28421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\tx: [" << viewportBBoxArea.x() << ", " << viewportBBoxArea.z() << "]\n"
28431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\ty: [" << viewportBBoxArea.y() << ", " << viewportBBoxArea.w() << "]\n"
28441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render results within the bounding box:\n"
28451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
28461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
28471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
28481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
28491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Verifying render result:"
28501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
28511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_fbo)
28531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
28541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), config.viewportPos.x(), config.viewportPos.y(), viewportSurface.getAccess());
28551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genReferencePointData(config, refPoints);
28571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_isWidePointCase)
28591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		anyError = verifyWidePointPattern(viewportSurface, refPoints, projectedBBox, logFloodCounter);
28601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
28611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		anyError = verifyNarrowPointPattern(viewportSurface, refPoints, projectedBBox, logFloodCounter);
28621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
28641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (logFloodCounter < 0)
28661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-logFloodCounter) << " error descriptions." << tcu::TestLog::EndMessage;
28671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
28691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
28701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
28711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
28721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
28731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
28741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
28751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
28771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
28781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
287930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	{
288030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry		m_testCtx.getLog()
288130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Message
288230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< "Result image ok."
288330fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
288430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
288530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewportSurface.getAccess())
288630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
288730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry	}
28881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
28891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
28901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystruct PointSorter
28911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
28921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool operator() (const PointRenderCase::GeneratedPoint& a, const PointRenderCase::GeneratedPoint& b) const
28931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
28941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (a.center.y() < b.center.y())
28951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
28961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (a.center.y() > b.center.y())
28971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return false;
28981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
28991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return (a.center.x() < b.center.x());
29001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
29021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PointRenderCase::genReferencePointData (const IterationConfig& config, std::vector<GeneratedPoint>& data) const
29041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
29051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<GeneratedPoint> currentPoints;
29061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// vertex shader
29081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	currentPoints.resize(m_attribData.size() / 2);
29091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].center	= m_attribData[ndx*2].swizzle(0, 1);
29121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].even		= (m_attribData[ndx*2 + 1].y() == 1.0f); // is green
29137d6ad9e003b52cfc23626b216b7580babf423c8fPyry Haulos		currentPoints[ndx].size		= ((m_isWidePointCase) ? ((currentPoints[ndx].even) ? 5 : 3) : 1);
29141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// tessellation
29171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasTessellationStage)
29181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<GeneratedPoint> tessellatedPoints;
29201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tessellatedPoints.resize(currentPoints.size() * 4);
29221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
29241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec2 position = tcu::Vec2(currentPoints[ndx].center.x(), 1.0f - currentPoints[ndx].center.y()); // mirror Y
29251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].center	= position + tcu::Vec2(-0.07f, -0.07f);
29271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].size		= currentPoints[ndx].size;
29281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 0].even		= currentPoints[ndx].even;
29291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].center	= position + tcu::Vec2( 0.07f, -0.07f);
29311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].size		= currentPoints[ndx].size;
29321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 1].even		= currentPoints[ndx].even;
29331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].center	= position + tcu::Vec2( 0.07f,  0.07f);
29351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].size		= currentPoints[ndx].size;
29361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 2].even		= currentPoints[ndx].even;
29371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].center	= position + tcu::Vec2(-0.07f,  0.07f);
29391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].size		= currentPoints[ndx].size;
29401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tessellatedPoints[4 * ndx + 3].even		= currentPoints[ndx].even;
29411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
29421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints.swap(tessellatedPoints);
29441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// geometry
29471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_hasGeometryStage)
29481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<GeneratedPoint> geometryShadedPoints;
29501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		geometryShadedPoints.resize(currentPoints.size() * 3);
29521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
29541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec2 position = tcu::Vec2(1.0f - currentPoints[ndx].center.x(), currentPoints[ndx].center.y()); // mirror X
29551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].center	= position + tcu::Vec2( 0.05f,  0.03f);
29571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].size		= currentPoints[ndx].size;
29581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 0].even		= currentPoints[ndx].even;
29591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].center	= position + tcu::Vec2(-0.01f, -0.02f);
29611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].size		= currentPoints[ndx].size;
29621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 1].even		= currentPoints[ndx].even;
29631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].center	= position + tcu::Vec2(-0.05f,  0.02f);
29651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].size		= currentPoints[ndx].size;
29661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			geometryShadedPoints[3 * ndx + 2].even		= currentPoints[ndx].even;
29671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
29681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints.swap(geometryShadedPoints);
29701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
29711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// sort from left to right, top to bottom
29731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::sort(currentPoints.begin(), currentPoints.end(), PointSorter());
29741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// map to pattern space
29761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)currentPoints.size(); ++ndx)
29771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		currentPoints[ndx].center = currentPoints[ndx].center * config.patternSize + config.patternPos;
29781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	currentPoints.swap(data);
29801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
29811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyNarrowPointPattern (const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter)
29831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
29841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool anyError = false;
29851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// check that there is something near each sample
29871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int pointNdx = 0; pointNdx < (int)refPoints.size(); ++pointNdx)
29881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
29891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float				epsilon		= 1.0e-6f;
29901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const GeneratedPoint&	refPoint	= refPoints[pointNdx];
29911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
29921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// skip points not in the the bbox, treat boundary as "in"
29931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (refPoint.center.x() < bbox.min.x() - epsilon ||
29941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() < bbox.min.y() - epsilon ||
29951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.x() > bbox.max.x() + epsilon ||
29961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() > bbox.max.y() + epsilon)
29971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			continue;
29981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
29991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// transform to viewport coords
30017a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			const tcu::IVec2 pixelCenter(deRoundFloatToInt32((refPoint.center.x() * 0.5f + 0.5f) * (float)viewport.getWidth()),
30027a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry										 deRoundFloatToInt32((refPoint.center.y() * 0.5f + 0.5f) * (float)viewport.getHeight()));
30031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// find rasterized point in the result
30051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (pixelCenter.x() < 1 || pixelCenter.y() < 1 || pixelCenter.x() >= viewport.getWidth()-1 || pixelCenter.y() >= viewport.getHeight()-1)
30061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
30071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// viewport boundary, assume point is fine
30081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
30091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
30101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
30111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	componentNdx	= (refPoint.even) ? (1) : (2); // analyze either green or blue channel
30121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bool		foundResult		= false;
30131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				// check neighborhood
30151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int dy = -1; dy < 2 && !foundResult; ++dy)
30161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				for (int dx = -1; dx < 2 && !foundResult; ++dx)
30171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
30181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const tcu::IVec2	testPos	(pixelCenter.x() + dx, pixelCenter.y() + dy);
30191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					const tcu::RGBA		color	= viewport.getPixel(testPos.x(), testPos.y());
30201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (color.toIVec()[componentNdx] > 0)
30221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						foundResult = true;
30231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
30241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if (!foundResult)
30261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
30271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					anyError = true;
30281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					if (--logFloodCounter >= 0)
30301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					{
30311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						m_testCtx.getLog()
30321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< tcu::TestLog::Message
30331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< "Missing point near " << pixelCenter << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
30341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							<< tcu::TestLog::EndMessage;
30351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					}
30361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
30371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
30381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return anyError;
30421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
30431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyWidePointPattern (const tcu::Surface& viewport, const std::vector<GeneratedPoint>& refPoints, const ProjectedBBox& bbox, int& logFloodCounter)
30451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
30461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool anyError = false;
30471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// check that there is something near each sample
30491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int pointNdx = 0; pointNdx < (int)refPoints.size(); ++pointNdx)
30501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const GeneratedPoint& refPoint = refPoints[pointNdx];
30521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (refPoint.center.x() >= bbox.min.x() &&
30541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() >= bbox.min.y() &&
30551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.x() <= bbox.max.x() &&
30561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			refPoint.center.y() <= bbox.max.y())
30571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// point fully in the bounding box
30591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError |= !verifyWidePoint(viewport, refPoint, bbox, POINT_FULL, logFloodCounter);
30601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30617a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry		else if (refPoint.center.x() >= bbox.min.x() + (float)refPoint.size / 2.0f &&
30627a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.y() >= bbox.min.y() - (float)refPoint.size / 2.0f &&
30637a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.x() <= bbox.max.x() + (float)refPoint.size / 2.0f &&
30647a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry				 refPoint.center.y() <= bbox.max.y() - (float)refPoint.size / 2.0f)
30651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
30661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// point leaks into bounding box
30671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError |= !verifyWidePoint(viewport, refPoint, bbox, POINT_PARTIAL, logFloodCounter);
30681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
30691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return anyError;
30721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
30731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool PointRenderCase::verifyWidePoint (const tcu::Surface& viewport, const GeneratedPoint& refPoint, const ProjectedBBox& bbox, ResultPointType pointType, int& logFloodCounter)
30751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
30761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			componentNdx		= (refPoint.even) ? (1) : (2);
30771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			halfPointSizeCeil	= (refPoint.size + 1) / 2;
30781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int			halfPointSizeFloor	= (refPoint.size + 1) / 2;
30797d6ad9e003b52cfc23626b216b7580babf423c8fPyry Haulos	const tcu::IVec4	viewportBBoxArea	= getViewportBoundingBoxArea(bbox, tcu::IVec2(viewport.getWidth(), viewport.getHeight()), (float)refPoint.size);
30801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec4	verificationArea	= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
30811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::max(viewportBBoxArea.y(), 0),
30821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::min(viewportBBoxArea.z(), viewport.getWidth()),
30831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														 de::min(viewportBBoxArea.w(), viewport.getHeight()));
30847a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	pointPos			= tcu::IVec2(deRoundFloatToInt32((refPoint.center.x()*0.5f + 0.5f) * (float)viewport.getWidth()),
30857a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry														 deRoundFloatToInt32((refPoint.center.y()*0.5f + 0.5f) * (float)viewport.getHeight()));
30861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// find any fragment within the point that is inside the bbox, start search at the center
30881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (pointPos.x() >= verificationArea.x() &&
30901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() >= verificationArea.y() &&
30911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.x() < verificationArea.z() &&
30921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() < verificationArea.w())
30931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
30941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(pointPos.x(), pointPos.y()).toIVec()[componentNdx])
30951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return verifyWidePointAt(pointPos, viewport, refPoint, verificationArea, pointType, componentNdx, logFloodCounter);
30961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
30971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
30981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int dy = -halfPointSizeCeil; dy <= halfPointSizeCeil; ++dy)
30991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int dx = -halfPointSizeCeil; dx <= halfPointSizeCeil; ++dx)
31001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2 testPos = pointPos + tcu::IVec2(dx, dy);
31021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (dx == 0 && dy == 0)
31041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			continue;
31051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (testPos.x() >= verificationArea.x() &&
31071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.y() >= verificationArea.y() &&
31081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.x() < verificationArea.z() &&
31091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			testPos.y() < verificationArea.w())
31101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (viewport.getPixel(testPos.x(), testPos.y()).toIVec()[componentNdx])
31121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return verifyWidePointAt(testPos, viewport, refPoint, verificationArea, pointType, componentNdx, logFloodCounter);
31131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// could not find point, this is only ok near boundaries
31171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (pointPos.x() + halfPointSizeFloor <  verificationArea.x() - 1 ||
31181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() + halfPointSizeFloor <  verificationArea.y() - 1 ||
31191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.x() - halfPointSizeFloor >= verificationArea.z() - 1 ||
31201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		pointPos.y() - halfPointSizeFloor >= verificationArea.w() - 1)
31211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
31221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--logFloodCounter >= 0)
31241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
31261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
31271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Missing wide point near " << pointPos << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
31281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
31291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
31321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
31331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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)
31351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
31361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				expectedPointSize		= refPoint.size;
31371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					viewportClippedTop		= false;
31381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					viewportClippedBottom	= false;
31391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					primitiveClippedTop		= false;
31401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					primitiveClippedBottom	= false;
31411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widthsUpwards;
31421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widthsDownwards;
31431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::IVec2>	widths;
31441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// search upwards
31461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = pointPos.y();; --y)
31471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (y < bbox.y() || y < 0)
31491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y < bbox.y())
31511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				primitiveClippedTop = true;
31521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y < 0)
31531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				viewportClippedTop = true;
31541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (pointPos.y() - y > expectedPointSize)
31571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no need to go further than point height
31591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (viewport.getPixel(pointPos.x(), y).toIVec()[componentNdx] == 0)
31621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
31661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			widthsUpwards.push_back(scanPointWidthAt(tcu::IVec2(pointPos.x(), y), viewport, expectedPointSize, componentNdx));
31681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// top is clipped
31721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((viewportClippedTop || (pointType == POINT_PARTIAL && primitiveClippedTop)) && !widthsUpwards.empty())
31731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2&	range			= widthsUpwards.back();
31751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			squareFits		= (range.y() - range.x() + 1) >= expectedPointSize;
31761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			widthClipped	= (pointType == POINT_PARTIAL) && (range.x() <= bbox.x() || range.y() >= bbox.z());
31771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (squareFits || widthClipped)
31791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
31801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
31811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
31821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// and downwards
31831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = pointPos.y()+1;; ++y)
31841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
31851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (y >= bbox.w() || y >= viewport.getHeight())
31861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y >= bbox.w())
31881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				primitiveClippedBottom = true;
31891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (y >= viewport.getHeight())
31901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				viewportClippedBottom = true;
31911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (y - pointPos.y() > expectedPointSize)
31941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
31951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no need to go further than point height
31961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
31971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
31981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else if (viewport.getPixel(pointPos.x(), y).toIVec()[componentNdx] == 0)
31991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
32001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
32021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
32031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
32041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			widthsDownwards.push_back(scanPointWidthAt(tcu::IVec2(pointPos.x(), y), viewport, expectedPointSize, componentNdx));
32051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
32061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// bottom is clipped
32091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if ((viewportClippedBottom || (pointType == POINT_PARTIAL && primitiveClippedBottom)) && !(widthsDownwards.empty() && widthsUpwards.empty()))
32101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec2&	range			= (widthsDownwards.empty()) ? (widthsUpwards.front()) : (widthsDownwards.back());
32121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			squareFits		= (range.y() - range.x() + 1) >= expectedPointSize;
32131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			bboxClipped		= (pointType == POINT_PARTIAL) && (range.x() <= bbox.x() || range.y() >= bbox.z()-1);
32141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			viewportClipped	= range.x() <= 0 || range.y() >= viewport.getWidth()-1;
32151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (squareFits || bboxClipped || viewportClipped)
32171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			return true;
32181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// would square point would fit into the rasterized area
32211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)widthsUpwards.size(); ++ndx)
32231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		widths.push_back(widthsUpwards[(int)widthsUpwards.size() - ndx - 1]);
32241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)widthsDownwards.size(); ++ndx)
32251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		widths.push_back(widthsDownwards[ndx]);
32261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(!widths.empty());
32271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < (int)widths.size() - expectedPointSize + 1; ++y)
32291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec2 unionRange = widths[y];
32311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int dy = 1; dy < expectedPointSize; ++dy)
32331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
32341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			unionRange.x() = de::max(unionRange.x(), widths[y+dy].x());
32351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			unionRange.y() = de::min(unionRange.y(), widths[y+dy].y());
32361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
32371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// would a N x N block fit here?
32391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
32401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool squareFits		= (unionRange.y() - unionRange.x() + 1) >= expectedPointSize;
32411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool bboxClipped		= (pointType == POINT_PARTIAL) && (unionRange.x() <= bbox.x() || unionRange.y() >= bbox.z()-1);
32421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const bool viewportClipped	= unionRange.x() <= 0 || unionRange.y() >= viewport.getWidth()-1;
32431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (squareFits || bboxClipped || viewportClipped)
32451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				return true;
32461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
32471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (--logFloodCounter >= 0)
32501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
32521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
32531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Missing " << expectedPointSize << "x" << expectedPointSize << " point near " << pointPos << ", vertex coordinates=" << refPoint.center.swizzle(0, 1) << "."
32541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
32551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return false;
32571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
32581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrytcu::IVec2 PointRenderCase::scanPointWidthAt (const tcu::IVec2& pointPos, const tcu::Surface& viewport, int expectedPointSize, int componentNdx) const
32601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
32611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int minX = pointPos.x();
32621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int maxX = pointPos.x();
32631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// search horizontally for a point edges
32651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = pointPos.x()-1; x >= 0; --x)
32661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(x, pointPos.y()).toIVec()[componentNdx] == 0)
32681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// no need to go further than point width
32711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pointPos.x() - x > expectedPointSize)
32721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		minX = x;
32751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = pointPos.x()+1; x < viewport.getWidth(); ++x)
32771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (viewport.getPixel(x, pointPos.y()).toIVec()[componentNdx] == 0)
32791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// no need to go further than point width
32821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (x - pointPos.x() > expectedPointSize)
32831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			break;
32841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		maxX = x;
32861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
32871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return tcu::IVec2(minX, maxX);
32891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
32901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass BlitFboCase : public TestCase
32921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
32931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
32941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum RenderTarget
32951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
32961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_DEFAULT = 0,
32971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_FBO,
32981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
32991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TARGET_LAST
33001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
33011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							BlitFboCase						(Context& context, const char* name, const char* description, RenderTarget src, RenderTarget dst);
33031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							~BlitFboCase					(void);
33041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
33061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
33071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FBO_SIZE = 256,
33091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
33101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct BlitArgs
33121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec4	src;
33141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::IVec4	dst;
33151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMin;
33161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMax;
33171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool		linear;
33181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
33191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init					(void);
33211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit					(void);
33221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate					(void);
33231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							fillSourceWithPattern	(void);
33251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage				(const BlitArgs& args);
33261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_src;
33281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const RenderTarget				m_dst;
33291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<BlitArgs>			m_iterations;
33311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_iteration;
33321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_srcFbo;
33331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Framebuffer>	m_dstFbo;
33341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Renderbuffer>	m_srcRbo;
33351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Renderbuffer>	m_dstRbo;
33361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
33371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
33381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
33391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::BlitFboCase (Context& context, const char* name, const char* description, RenderTarget src, RenderTarget dst)
33411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
33421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_src			(src)
33431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_dst			(dst)
33441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_iteration	(0)
33451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(src < TARGET_LAST);
33471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(dst < TARGET_LAST);
33481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
33491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::~BlitFboCase (void)
33511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
33531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
33541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::init (void)
33561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
33571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numIterations			= 12;
33581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				defaultFBMultisampled	= (m_context.getRenderTarget().getNumSamples() > 1);
33591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
33601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd						(0xABC123);
33611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
33631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
33641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Using BlitFramebuffer to blit area from "
33651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_src == TARGET_DEFAULT) ? ("default fb") : ("fbo"))
33661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< " to "
33671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_dst == TARGET_DEFAULT) ? ("default fb") : ("fbo"))
33681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
33691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Varying blit arguments and primitive bounding box between iterations.\n"
33701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting bounding box to have no effect on blitting.\n"
33711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Source framebuffer is filled with green-yellow grid.\n"
33721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
33731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3374cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
3375cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
3376cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
33771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
33781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_dst == TARGET_DEFAULT && defaultFBMultisampled)
33791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires non-multisampled default framebuffer");
33801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
33821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_src == TARGET_FBO)
33841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_srcRbo = de::MovePtr<glu::Renderbuffer>(new glu::Renderbuffer(m_context.getRenderContext()));
33861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindRenderbuffer(GL_RENDERBUFFER, **m_srcRbo);
33871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, FBO_SIZE, FBO_SIZE);
33881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "src rbo");
33891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_srcFbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
33911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_FRAMEBUFFER, **m_srcFbo);
33921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, **m_srcRbo);
33931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "src fbo");
33941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
33951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
33961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_dst == TARGET_FBO)
33971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
33981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_dstRbo = de::MovePtr<glu::Renderbuffer>(new glu::Renderbuffer(m_context.getRenderContext()));
33991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindRenderbuffer(GL_RENDERBUFFER, **m_dstRbo);
34001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, FBO_SIZE, FBO_SIZE);
34011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "dst rbo");
34021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_dstFbo = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
34041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindFramebuffer(GL_FRAMEBUFFER, **m_dstFbo);
34051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, **m_dstRbo);
34061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "dst fbo");
34071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
34081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
3410cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		const char* const vertexSource =	"${GLSL_VERSION_DECL}\n"
34111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"in highp vec4 a_position;\n"
34121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"out highp vec4 v_position;\n"
34131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"void main()\n"
34141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"{\n"
34151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	gl_Position = a_position;\n"
34161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	v_position = a_position;\n"
34171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"}\n";
3418cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		const char* const fragmentSource =	"${GLSL_VERSION_DECL}\n"
34191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"in mediump vec4 v_position;\n"
34201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"layout(location=0) out mediump vec4 dEQP_FragColor;\n"
34211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"void main()\n"
34221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"{\n"
34231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	const mediump vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
34241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"	const mediump vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
34251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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"
34261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry													"}\n";
34271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3428cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(specializeShader(m_context, vertexSource)) << glu::FragmentSource(specializeShader(m_context, fragmentSource))));
34291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
34311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
34321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
34331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
34341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
34351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
34361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
34381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const tcu::Vec4 s_quadCoords[] =
34391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
34401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
34411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
34421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
34431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
34441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
34451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
34471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
34491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_quadCoords), s_quadCoords, GL_STATIC_DRAW);
34501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "set buf");
34511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
34521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// gen iterations
34541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
34561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
34571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
34581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
34601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
34611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "srcSize = " << srcSize << "\n"
34621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "dstSize = " << dstSize << "\n"
34631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage;
34641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int ndx = 0; ndx < numIterations; ++ndx)
34661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
34671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BlitArgs args;
34681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (m_src == TARGET_DEFAULT && defaultFBMultisampled)
34701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
34711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const tcu::IVec2	unionSize	= tcu::IVec2(de::min(srcSize.x(), dstSize.x()), de::min(srcSize.y(), dstSize.y()));
34721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcWidth	= rnd.getInt(1, unionSize.x());
34731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcHeight	= rnd.getInt(1, unionSize.y());
34741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcX		= rnd.getInt(0, unionSize.x() - srcWidth);
34751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int			srcY		= rnd.getInt(0, unionSize.y() - srcHeight);
34761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.x() = srcX;
34781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.y() = srcY;
34791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.z() = srcX + srcWidth;
34801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.w() = srcY + srcHeight;
34811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst = args.src;
34831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
34841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			else
34851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
34861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcWidth	= rnd.getInt(1, srcSize.x());
34871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcHeight	= rnd.getInt(1, srcSize.y());
34881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcX		= rnd.getInt(0, srcSize.x() - srcWidth);
34891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	srcY		= rnd.getInt(0, srcSize.y() - srcHeight);
34901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstWidth	= rnd.getInt(1, dstSize.x());
34911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstHeight	= rnd.getInt(1, dstSize.y());
34921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstX		= rnd.getInt(-(dstWidth / 2), dstSize.x() - (dstWidth+1) / 2);		// allow dst go out of bounds
34931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				const int	dstY		= rnd.getInt(-(dstHeight / 2), dstSize.y() - (dstHeight+1)  / 2);
34941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
34951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.x() = srcX;
34961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.y() = srcY;
34971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.z() = srcX + srcWidth;
34981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.src.w() = srcY + srcHeight;
34991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.x() = dstX;
35001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.y() = dstY;
35011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.z() = dstX + dstWidth;
35021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				args.dst.w() = dstY + dstHeight;
35031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
35041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.x() = rnd.getFloat(-1.1f, 1.1f);
35061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.y() = rnd.getFloat(-1.1f, 1.1f);
35071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.z() = rnd.getFloat(-1.1f, 1.1f);
35081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMin.w() = rnd.getFloat( 0.9f, 1.1f);
35091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.x() = rnd.getFloat(-1.1f, 1.1f);
35111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.y() = rnd.getFloat(-1.1f, 1.1f);
35121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.z() = rnd.getFloat(-1.1f, 1.1f);
35131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.bboxMax.w() = rnd.getFloat( 0.9f, 1.1f);
35141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.x() / args.bboxMin.w() > args.bboxMax.x() / args.bboxMax.w())
35161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.x(), args.bboxMax.x());
35171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.y() / args.bboxMin.w() > args.bboxMax.y() / args.bboxMax.w())
35181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.y(), args.bboxMax.y());
35191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (args.bboxMin.z() / args.bboxMin.w() > args.bboxMax.z() / args.bboxMax.w())
35201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				std::swap(args.bboxMin.z(), args.bboxMax.z());
35211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			args.linear = rnd.getBool();
35231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_iterations.push_back(args);
35251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
35261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
35271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
35281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::deinit (void)
35301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
35311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_srcFbo.clear();
35321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_srcRbo.clear();
35331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_dstFbo.clear();
35341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_dstRbo.clear();
35351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
35361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
35371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
35381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryBlitFboCase::IterateResult BlitFboCase::iterate (void)
35401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
35411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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()));
35421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BlitArgs&				blitCfg		= m_iterations[m_iteration];
35431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
35441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_iteration == 0)
35461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
35471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// fill source with test pattern. Default fb must be filled for each iteration because contents might not survive the swap
35491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_src == TARGET_DEFAULT || m_iteration == 0)
35501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		fillSourceWithPattern();
35511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
35531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
35541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box:\n"
35551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "\tmin:" << blitCfg.bboxMin << "\n"
35561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "\tmax:" << blitCfg.bboxMax << "\n"
35571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Blit:\n"
35581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tsrc: " << blitCfg.src << "\n"
35591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tdst: " << blitCfg.dst << "\n"
35601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<<	"\tfilter: " << ((blitCfg.linear) ? ("linear") : ("nearest"))
35611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
35621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3563485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe	gl.primitiveBoundingBox(blitCfg.bboxMin.x(), blitCfg.bboxMin.y(), blitCfg.bboxMin.z(), blitCfg.bboxMin.w(),
3564485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe							blitCfg.bboxMax.x(), blitCfg.bboxMax.y(), blitCfg.bboxMax.z(), blitCfg.bboxMax.w());
35651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, (m_dst == TARGET_FBO) ? (**m_dstFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
35681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
35691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, (m_src == TARGET_FBO) ? (**m_srcFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.blitFramebuffer(blitCfg.src.x(), blitCfg.src.y(), blitCfg.src.z(), blitCfg.src.w(),
35721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   blitCfg.dst.x(), blitCfg.dst.y(), blitCfg.dst.z(), blitCfg.dst.w(),
35731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   GL_COLOR_BUFFER_BIT,
35741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					   ((blitCfg.linear) ? (GL_LINEAR) : (GL_NEAREST)));
35751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "blit");
35761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImage(blitCfg))
35781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected blit result");
35791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return (++m_iteration == (int)m_iterations.size()) ? (STOP) : (CONTINUE);
35811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
35821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool BlitFboCase::verifyImage (const BlitArgs& args)
35841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
35851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				colorThreshold	= 4; //!< this test case is not about how color is preserved, allow almost anything
35861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
35871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
35881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewport		(dstSize.x(), dstSize.y());
35891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			errorMask		(dstSize.x(), dstSize.y());
35901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool					anyError		= false;
35911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
35931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
35941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying blit result"
35951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
35961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
35971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, (m_dst == TARGET_FBO) ? (**m_dstFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
35981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, viewport.getAccess());
35991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0, 0, 0, 255));
36011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < dstSize.y(); ++y)
36031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < dstSize.x(); ++x)
36041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA color	= viewport.getPixel(x, y);
36061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		inside	= (x >= args.dst.x() && x < args.dst.z() && y >= args.dst.y() && y < args.dst.w());
36071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		error	= (inside) ? (color.getGreen() < 255 - colorThreshold || color.getBlue() > colorThreshold)
36081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry										   : (color.getRed() > colorThreshold || color.getGreen() > colorThreshold || color.getBlue() > colorThreshold);
36091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
36111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
36121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
3613c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
36141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
36151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
36161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
36181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
36201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
36211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
36221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
36231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
36241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
36251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
36261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
36271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return false;
36281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
36291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
36301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
36321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
36331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result image ok."
363430fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
363530fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
363630fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
363730fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
36381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		return true;
36391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
36401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
36411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid BlitFboCase::fillSourceWithPattern (void)
36431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
36441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
36451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
36461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				posLocation	= gl.getAttribLocation(m_program->getProgram(), "a_position");
36471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, (m_src == TARGET_FBO) ? (**m_srcFbo) : (m_context.getRenderContext().getDefaultFramebuffer()));
36491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, srcSize.x(), srcSize.y());
36501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
36511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
36531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
36541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
36561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 4 * (int)sizeof(float), NULL);
36571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
36581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
36591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
36601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass DepthDrawCase : public TestCase
36621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
36631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
36641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum DepthType
36651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_BUILTIN = 0,
36671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_USER_DEFINED,
36681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DEPTH_LAST
36701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxState
36721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_GLOBAL = 0,
36741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_PER_PRIMITIVE,
36751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		STATE_LAST
36771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum BBoxSize
36791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
36801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_EQUAL = 0,
36811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_LARGER,
36821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_LAST
36841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
36851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									DepthDrawCase					(Context& context, const char* name, const char* description, DepthType depthType, BBoxState state, BBoxSize bboxSize);
36871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~DepthDrawCase					(void);
36881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
36901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
36911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
36921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
36931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
36941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
36951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
36961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(void) const;
36971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
36981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							generateAttributeData			(std::vector<tcu::Vec4>& data) const;
36991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage						(const tcu::Surface& viewport) const;
37001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
37021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		RENDER_AREA_SIZE = 256,
37041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
37051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct LayerInfo
37071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		float		zOffset;
37091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		float		zScale;
37101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	color1;
37111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	color2;
37121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
37131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_numLayers;
37151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int						m_gridSize;
37161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const DepthType					m_depthType;
37181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxState					m_state;
37191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const BBoxSize					m_bboxSize;
37201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
37221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
37231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<LayerInfo>			m_layers;
37241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
37251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::DepthDrawCase (Context& context, const char* name, const char* description, DepthType depthType, BBoxState state, BBoxSize bboxSize)
37271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
37281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numLayers	(14)
37291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_gridSize	(24)
37301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_depthType	(depthType)
37311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_state		(state)
37321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_bboxSize	(bboxSize)
37331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(depthType < DEPTH_LAST);
37351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(state < STATE_LAST);
37361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(bboxSize < BBOX_LAST);
37371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
37381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::~DepthDrawCase (void)
37401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
37411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
37421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
37431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::init (void)
37451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
3746cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
3747cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool				supportsES32	= glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
37481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// requirements
37501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3751cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
37521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
3753cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (m_state == STATE_PER_PRIMITIVE && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
37541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
37551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_context.getRenderTarget().getDepthBits() == 0)
37561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires depth buffer");
37571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_context.getRenderTarget().getWidth() < RENDER_AREA_SIZE || m_context.getRenderTarget().getHeight() < RENDER_AREA_SIZE)
37581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_AREA_SIZE) + "x" + de::toString<int>(RENDER_AREA_SIZE) + " viewport");
37591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// log
37611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
37621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
37631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering multiple triangle grids with with different z coordinates.\n"
37641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Topmost grid is green-yellow, other grids are blue-red.\n"
37651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting only the green-yellow grid to be visible.\n"
37661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting primitive bounding box "
37671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_bboxSize == BBOX_EQUAL) ? ("to exactly cover") : ("to cover"))
37681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_state == STATE_GLOBAL) ? (" each grid") : (" each triangle"))
37691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_bboxSize == BBOX_EQUAL) ? (".") : (" and include some padding."))
37701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
37711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
37721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_state == STATE_GLOBAL) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
37731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "\n"
37741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_depthType == DEPTH_USER_DEFINED) ? ("Fragment depth is set in the fragment shader") : (""))
37751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
37761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
37781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
37801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		glu::ProgramSources sources;
3781cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		sources << glu::VertexSource(specializeShader(m_context, genVertexSource().c_str()));
3782cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		sources << glu::FragmentSource(specializeShader(m_context, genFragmentSource().c_str()));
37831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_state == STATE_PER_PRIMITIVE)
3785cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			sources << glu::TessellationControlSource(specializeShader(m_context, genTessellationControlSource().c_str()))
3786cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos					<< glu::TessellationEvaluationSource(specializeShader(m_context, genTessellationEvaluationSource().c_str()));
37871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), sources));
37891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "build program");
37901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
37921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::ScopedLogSection section(m_testCtx.getLog(), "ShaderProgram", "Shader program");
37931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog() << *m_program;
37941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
37951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
37961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_program->isOk())
37971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("failed to build program");
37981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
37991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
38011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		std::vector<tcu::Vec4> data;
38021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		generateAttributeData(data);
38041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
38061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
38071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bufferData(GL_ARRAY_BUFFER, (int)(sizeof(tcu::Vec4) * data.size()), &data[0], GL_STATIC_DRAW);
38081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		GLU_EXPECT_NO_ERROR(gl.getError(), "buf upload");
38091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
38101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// gen layers
38121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
38131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		de::Random rnd(0x12345);
38141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_layers.resize(m_numLayers);
38161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
38171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
38187a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_layers[layerNdx].zOffset	= ((float)layerNdx / (float)m_numLayers) * 2.0f - 1.0f;
38197a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry			m_layers[layerNdx].zScale	= (2.0f / (float)m_numLayers);
38201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
38211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
38221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
38231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		rnd.shuffle(m_layers.begin(), m_layers.end());
38241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
38251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
38261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::deinit (void)
38281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
38291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
38301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
38311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
38321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryDepthDrawCase::IterateResult DepthDrawCase::iterate (void)
38341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
38351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool				hasTessellation		= (m_state == STATE_PER_PRIMITIVE);
38361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
38371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation			= gl.getAttribLocation(m_program->getProgram(), "a_position");
38381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		colLocation			= gl.getAttribLocation(m_program->getProgram(), "a_colorMix");
38391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		depthBiasLocation	= gl.getUniformLocation(m_program->getProgram(), "u_depthBias");
38401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		depthScaleLocation	= gl.getUniformLocation(m_program->getProgram(), "u_depthScale");
38411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		color1Location		= gl.getUniformLocation(m_program->getProgram(), "u_color1");
38421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		color2Location		= gl.getUniformLocation(m_program->getProgram(), "u_color2");
38431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			viewport			(RENDER_AREA_SIZE, RENDER_AREA_SIZE);
38451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd					(0x213237);
38461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(posLocation != -1);
38481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(colLocation != -1);
38491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(depthBiasLocation != -1);
38501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(depthScaleLocation != -1);
38511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(color1Location != -1);
38521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	TCU_CHECK(color2Location != -1);
38531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, RENDER_AREA_SIZE, RENDER_AREA_SIZE);
38551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
38561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearDepthf(1.0f);
38571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.depthFunc(GL_LESS);
38581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enable(GL_DEPTH_TEST);
38591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
38601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup viewport");
38611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
38631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, (int)(8 * sizeof(float)), (const float*)DE_NULL);
38641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(colLocation, 4, GL_FLOAT, GL_FALSE, (int)(8 * sizeof(float)), (const float*)DE_NULL + 4);
38651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
38661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(colLocation);
38671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
38681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "setup va");
38691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (hasTessellation)
38711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
38721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int layerNdx = 0; layerNdx < m_numLayers; ++layerNdx)
38741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
38751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(depthBiasLocation, m_layers[layerNdx].zOffset);
38761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform1f(depthScaleLocation, m_layers[layerNdx].zScale);
38771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4fv(color1Location, 1, m_layers[layerNdx].color1.getPtr());
38781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.uniform4fv(color2Location, 1, m_layers[layerNdx].color2.getPtr());
38791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_state == STATE_GLOBAL)
38811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
38821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float negPadding = (m_bboxSize == BBOX_EQUAL) ? (0.0f) : (rnd.getFloat() * 0.3f);
38831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posPadding = (m_bboxSize == BBOX_EQUAL) ? (0.0f) : (rnd.getFloat() * 0.3f);
38841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3885485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe			gl.primitiveBoundingBox(-1.0f, -1.0f, m_layers[layerNdx].zOffset - negPadding, 1.0f,
3886485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe									1.0f,  1.0f, (m_layers[layerNdx].zOffset + m_layers[layerNdx].zScale + posPadding), 1.0f);
38871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
38881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.drawArrays((hasTessellation) ? (GL_PATCHES) : (GL_TRIANGLES), 0, m_gridSize * m_gridSize * 6);
38901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
38911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, viewport.getAccess());
38931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "render and read");
38941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
38951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (verifyImage(viewport))
38961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
38971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
38981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
38991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
39011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
39021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genVertexSource (void) const
39041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			hasTessellation	= (m_state == STATE_PER_PRIMITIVE);
39061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3908cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
39091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_position;\n"
39101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 a_colorMix;\n"
39111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 vtx_colorMix;\n";
39121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!hasTessellation && m_depthType == DEPTH_USER_DEFINED)
39141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "out highp float v_fragDepth;\n";
39151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!hasTessellation)
39171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"uniform highp float u_depthBias;\n"
39181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"uniform highp float u_depthScale;\n";
39191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"\n"
39211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n";
39231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (hasTessellation)
39251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_Position = a_position;\n";
39261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (m_depthType == DEPTH_USER_DEFINED)
39271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float dummyZ = a_position.z;\n"
39281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float writtenZ = a_position.w;\n"
39291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(a_position.xy, dummyZ, 1.0);\n"
39301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_fragDepth = writtenZ * u_depthScale + u_depthBias;\n";
39311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
39321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float writtenZ = a_position.w;\n"
39331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(a_position.xy, writtenZ * u_depthScale + u_depthBias, 1.0);\n";
39341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	vtx_colorMix = a_colorMix;\n"
39361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
39371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
39391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
39401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genFragmentSource (void) const
39421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool			hasTessellation	= (m_state == STATE_PER_PRIMITIVE);
39441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const char* const	colorMixName	= (hasTessellation) ? ("tess_eval_colorMix") : ("vtx_colorMix");
39451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3947cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
39481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in mediump vec4 " << colorMixName << ";\n";
39491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "in mediump float v_fragDepth;\n";
39521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"layout(location = 0) out mediump vec4 o_color;\n"
39541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_color1;\n"
39551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp vec4 u_color2;\n"
39561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
39591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	o_color = mix(u_color1, u_color2, " << colorMixName << ");\n";
39601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
39621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "	gl_FragDepth = v_fragDepth * 0.5 + 0.5;\n";
39631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
39651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
39671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
39681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
39691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genTessellationControlSource (void) const
39701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
39711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
39721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
3973cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
3974cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
3975cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${PRIMITIVE_BOUNDING_BOX_REQUIRE}\n"
39761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
39771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthBias;\n"
39791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthScale;\n"
39801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 vtx_colorMix[];\n"
39821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_ctrl_colorMix[];\n"
39831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
39851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
39861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
39871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	tess_ctrl_colorMix[gl_InvocationID] = vtx_colorMix[0];\n"
39881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
39901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
39911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
39921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
39931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
39941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	// real Z stored in w component\n"
39951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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"
39961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                                   vec3(gl_in[1].gl_Position.xy, gl_in[1].gl_Position.w * u_depthScale + u_depthBias)),\n"
39971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                               vec3(gl_in[2].gl_Position.xy, gl_in[2].gl_Position.w * u_depthScale + u_depthBias)), 1.0);\n"
39981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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"
39991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                                   vec3(gl_in[1].gl_Position.xy, gl_in[1].gl_Position.w * u_depthScale + u_depthBias)),\n"
40001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	                               vec3(gl_in[2].gl_Position.xy, gl_in[2].gl_Position.w * u_depthScale + u_depthBias)), 1.0);\n";
40011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_bboxSize == BBOX_EQUAL)
4003cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		buf <<	"	${PRIM_GL_BOUNDING_BOX}[0] = minBound;\n"
4004cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[1] = maxBound;\n";
40051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
40061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float nedPadding = mod(gl_in[0].gl_Position.z, 0.3);\n"
40071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float posPadding = mod(gl_in[1].gl_Position.z, 0.3);\n"
4008cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[0] = minBound - vec4(0.0, 0.0, nedPadding, 0.0);\n"
4009cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos				"	${PRIM_GL_BOUNDING_BOX}[1] = maxBound + vec4(0.0, 0.0, posPadding, 0.0);\n";
40101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"}\n";
40121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
40141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string DepthDrawCase::genTessellationEvaluationSource (void) const
40171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream	buf;
40191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4020cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
4021cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
4022cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${GPU_SHADER5_REQUIRE}\n"
40231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(triangles) in;\n"
40241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
40251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 tess_ctrl_colorMix[];\n"
40261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 tess_eval_colorMix;\n";
40271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
40291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf << "out highp float v_fragDepth;\n";
40301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"uniform highp float u_depthBias;\n"
40321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"uniform highp float u_depthScale;\n"
40331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
40341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"precise gl_Position;\n"
40351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"\n"
40361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
40371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
40381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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";
40391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_depthType == DEPTH_USER_DEFINED)
40411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float dummyZ = tessellatedPos.z;\n"
40421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	highp float writtenZ = tessellatedPos.w;\n"
40431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(tessellatedPos.xy, dummyZ, 1.0);\n"
40441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	v_fragDepth = writtenZ * u_depthScale + u_depthBias;\n";
40451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
40461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"	highp float writtenZ = tessellatedPos.w;\n"
40471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"	gl_Position = vec4(tessellatedPos.xy, writtenZ * u_depthScale + u_depthBias, 1.0);\n";
40481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"	tess_eval_colorMix = tess_ctrl_colorMix[0];\n"
40501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
40511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
40531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid DepthDrawCase::generateAttributeData (std::vector<tcu::Vec4>& data) const
40561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		color1				(0.0f, 0.0f, 0.0f, 0.0f); // mix weights
40581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4		color2				(1.0f, 1.0f, 1.0f, 1.0f);
40591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>	cellOrder			(m_gridSize * m_gridSize);
40601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random			rnd					(0xAB54321);
40611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with cells in random order
40631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
40641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
40651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
40661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	data.resize(m_gridSize * m_gridSize * 6 * 2);
40681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
40691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
40701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
40711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= cellNdx % m_gridSize;
40721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= cellNdx / m_gridSize;
40731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::Vec4&	cellColor	= ((cellX+cellY)%2 == 0) ? (color1) : (color2);
40741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40757a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40767a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40777a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40787a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40797a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40807a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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;
40811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// Fill Z with random values (fake Z)
40831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vtxNdx = 0; vtxNdx < 6; ++vtxNdx)
40841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[ndx * 6 * 2 + 2*vtxNdx].z() = rnd.getFloat(0.0f, 1.0);
40851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// Fill W with other random values (written Z)
40871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vtxNdx = 0; vtxNdx < 6; ++vtxNdx)
40881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			data[ndx * 6 * 2 + 2*vtxNdx].w() = rnd.getFloat(0.0f, 1.0);
40891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
40901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
40911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool DepthDrawCase::verifyImage (const tcu::Surface& viewport) const
40931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
40941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(viewport.getWidth(), viewport.getHeight());
40951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
40961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::clear(errorMask.getAccess(), tcu::IVec4(0,0,0,255));
40981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
40991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < viewport.getHeight(); ++y)
41001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < viewport.getWidth(); ++x)
41011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::RGBA	pixel		= viewport.getPixel(x, y);
41031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		bool			error		= false;
41041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// expect green, yellow or a combination of these
41061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pixel.getGreen() != 255 || pixel.getBlue() != 0)
41071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			error = true;
41081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (error)
41101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4111c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
41121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
41131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
41141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
41151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
41171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
41181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
41191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
41201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
41211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
41221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
41231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
41241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
41251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
41261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
41271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
41281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result image ok."
412930fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndMessage
413030fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
413130fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::Image("Viewport", "Viewport contents", viewport.getAccess())
413230fde0c3faee7af43a958bd572d8b6c584333a15Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
41331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
41351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass ClearCase : public TestCase
41381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
41401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum
41411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		SCISSOR_CLEAR_BIT		= 1 << 0,
41431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DRAW_TRIANGLE_BIT		= 1 << 1,
41441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		PER_PRIMITIVE_BBOX_BIT	= 1 << 2,
41451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		FULLSCREEN_SCISSOR_BIT	= 1 << 3,
41461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
41471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									ClearCase						(Context& context, const char* name, const char* description, deUint32 flags);
41491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~ClearCase						(void);
41501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
41521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	struct DrawObject
41531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
41541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int firstNdx;
41551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		int numVertices;
41561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
41571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
41591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
41601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
41611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							createVbo						(void);
41631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							createProgram					(void);
41641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							renderTo						(tcu::Surface& dst, bool useBBox);
41651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImagesEqual				(const tcu::PixelBufferAccess& withoutBBox, const tcu::PixelBufferAccess& withBBox);
41661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImageResultValid			(const tcu::PixelBufferAccess& result);
41671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
41691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
41701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(bool setBBox) const;
41711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
41721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_scissoredClear;
41741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_fullscreenScissor;
41751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_drawTriangles;
41761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const bool						m_useGlobalState;
41771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
41791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_perPrimitiveProgram;
41801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_basicProgram;
41811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<DrawObject>			m_drawObjects;
41821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>			m_objectVertices;
41831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
41841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::ClearCase (Context& context, const char* name, const char* description, deUint32 flags)
41861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase				(context, name, description)
41871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_scissoredClear		((flags & SCISSOR_CLEAR_BIT) != 0)
41881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_fullscreenScissor	((flags & FULLSCREEN_SCISSOR_BIT) != 0)
41891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_drawTriangles		((flags & DRAW_TRIANGLE_BIT) != 0)
41901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_useGlobalState		((flags & PER_PRIMITIVE_BBOX_BIT) == 0)
41911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_useGlobalState || m_drawTriangles); // per-triangle bbox requires triangles
41931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(!m_fullscreenScissor || m_scissoredClear); // fullscreenScissor requires scissoredClear
41941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
41951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
41961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::~ClearCase (void)
41971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
41981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
41991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::init (void)
42021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
4203cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
4204cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
4205cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
42061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
4207cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (m_drawTriangles && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
42081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
42091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
42111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
42121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Doing multiple"
42131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_scissoredClear) ? (" scissored") : (""))
42141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< " color buffer clears"
42151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_drawTriangles) ? (" and drawing some geometry between them") : (""))
42161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
42171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_scissoredClear && m_fullscreenScissor) ? ("Setting scissor area to cover entire viewport.\n") : (""))
42181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering with and without setting the bounding box.\n"
42191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Expecting bounding box to have no effect on clears (i.e. results are constant).\n"
42201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Set bounding box using "
42211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_useGlobalState) ? ("PRIMITIVE_BOUNDING_BOX_EXT state") : ("gl_BoundingBoxEXT output"))
42221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ".\n"
42231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Clear color is green with yellowish shades.\n"
42241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< ((m_drawTriangles) ? ("Primitive color is yellow with greenish shades.\n") : (""))
42251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
42261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_drawTriangles)
42281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		createVbo();
42301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		createProgram();
42311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::deinit (void)
42351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
42371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_perPrimitiveProgram.clear();
42381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_basicProgram.clear();
42391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_drawObjects = std::vector<DrawObject>();
42401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_objectVertices = std::vector<tcu::Vec4>();
42411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryClearCase::IterateResult ClearCase::iterate (void)
42441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2	renderTargetSize	(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
42461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		resultWithoutBBox	(renderTargetSize.x(), renderTargetSize.y());
42471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		resultWithBBox		(renderTargetSize.x(), renderTargetSize.y());
42481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// render with and without bbox set
42501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int passNdx = 0; passNdx < 2; ++passNdx)
42511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool		useBBox			= (passNdx == 1);
42531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Surface&	destination		= (useBBox) ? (resultWithBBox) : (resultWithoutBBox);
42541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		renderTo(destination, useBBox);
42561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// Verify images are equal and that the image does not contain (trivially detectable) garbage
42591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImagesEqual(resultWithoutBBox.getAccess(), resultWithBBox.getAccess()))
42611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// verifyImagesEqual will print out the image and error mask
42631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
42641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else if (!verifyImageResultValid(resultWithBBox.getAccess()))
42661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// verifyImageResultValid will print out the image and error mask
42681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
42691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
42711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
42731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
42741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image comparison passed."
42751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
42761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
42771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Result", "Result", resultWithBBox.getAccess())
42781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
42791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
42811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
42821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
42841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
42851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::createVbo (void)
42871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
42881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numObjects	= 16;
42891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
42901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd			(deStringHash(getName()));
42911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
42931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
42941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int objectNdx = 0; objectNdx < numObjects; ++objectNdx)
42951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
42961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	numTriangles	= rnd.getInt(1, 4);
42971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	minX			= rnd.getFloat(-1.2f, 0.8f);
42981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	minY			= rnd.getFloat(-1.2f, 0.8f);
42991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	maxX			= minX + rnd.getFloat(0.2f, 1.0f);
43001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const float	maxY			= minY + rnd.getFloat(0.2f, 1.0f);
43011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		DrawObject	drawObject;
43031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		drawObject.firstNdx = (int)m_objectVertices.size();
43041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		drawObject.numVertices = numTriangles * 3;
43051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_drawObjects.push_back(drawObject);
43071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int triangleNdx = 0; triangleNdx < numTriangles; ++triangleNdx)
43091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
43101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
43111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posX = rnd.getFloat(minX, maxX);
43121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posY = rnd.getFloat(minY, maxY);
43131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posZ = rnd.getFloat(-0.7f, 0.7f);
43141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const float posW = rnd.getFloat(0.9f, 1.1f);
43151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_objectVertices.push_back(tcu::Vec4(posX, posY, posZ, posW));
43171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
43181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
43191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
43211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bufferData(GL_ARRAY_BUFFER, (int)(m_objectVertices.size() * sizeof(tcu::Vec4)), &m_objectVertices[0], GL_STATIC_DRAW);
43221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "buffer upload");
43231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
43241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::createProgram (void)
43261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
43271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_basicProgram = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
43281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																			glu::ProgramSources()
4329cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																				<< glu::VertexSource(specializeShader(m_context, genVertexSource().c_str()))
4330cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																				<< glu::FragmentSource(specializeShader(m_context, genFragmentSource().c_str()))
4331cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																				<< glu::TessellationControlSource(specializeShader(m_context, genTessellationControlSource(false).c_str()))
4332cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																				<< glu::TessellationEvaluationSource(specializeShader(m_context, genTessellationEvaluationSource().c_str()))));
43331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
43351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Section("Program", "Shader program")
43361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< *m_basicProgram
43371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndSection;
43381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_basicProgram->isOk())
43401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::TestError("shader build failed");
43411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_useGlobalState)
43431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_perPrimitiveProgram = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
43451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																					   glu::ProgramSources()
4346cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																							<< glu::VertexSource(specializeShader(m_context, genVertexSource().c_str()))
4347cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																							<< glu::FragmentSource(specializeShader(m_context, genFragmentSource().c_str()))
4348cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																							<< glu::TessellationControlSource(specializeShader(m_context, genTessellationControlSource(true).c_str()))
4349cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																							<< glu::TessellationEvaluationSource(specializeShader(m_context, genTessellationEvaluationSource().c_str()))));
43501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
43521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Section("PerPrimitiveProgram", "Shader program that sets the bounding box")
43531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< *m_perPrimitiveProgram
43541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndSection;
43551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (!m_perPrimitiveProgram->isOk())
43571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			throw tcu::TestError("shader build failed");
43581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
43591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
43601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ClearCase::renderTo (tcu::Surface& dst, bool useBBox)
43621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
43631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				numOps				= 45;
43641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4			yellow				(1.0f, 1.0f, 0.0f, 1.0f);
43651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::Vec4			green				(0.0f, 1.0f, 0.0f, 1.0f);
43661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		renderTargetSize	(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
43671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
43681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd					(deStringHash(getName()));
43691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::VertexArray		vao					(m_context.getRenderContext());
43701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// always do the initial clear
43721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.disable(GL_SCISSOR_TEST);
43731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.viewport(0, 0, renderTargetSize.x(), renderTargetSize.y());
43741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(yellow.x(), yellow.y(), yellow.z(), yellow.w());
43751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
43761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.finish();
43771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// prepare draw
43791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_scissoredClear)
43801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.enable(GL_SCISSOR_TEST);
43811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (m_drawTriangles)
43831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const deUint32	programHandle		= (m_useGlobalState || !useBBox) ? (m_basicProgram->getProgram()) : (m_perPrimitiveProgram->getProgram());
43851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int		positionAttribLoc	= gl.getAttribLocation(programHandle, "a_position");
43861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TCU_CHECK(positionAttribLoc != -1);
43881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.useProgram(programHandle);
43901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.bindVertexArray(*vao);
43911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.enableVertexAttribArray(positionAttribLoc);
43921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.vertexAttribPointer(positionAttribLoc, 4, GL_FLOAT, GL_FALSE, (int)sizeof(tcu::Vec4), DE_NULL);
43931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		gl.patchParameteri(GL_PATCH_VERTICES, 3);
43941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
43951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
43961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// do random scissor/clearldraw operations
43971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int opNdx = 0; opNdx < numOps; ++opNdx)
43981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
43991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	drawObjNdx				= (m_drawTriangles) ? (rnd.getInt(0, (int)m_drawObjects.size() - 1)) : (0);
44001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	objectVertexStartNdx	= (m_drawTriangles) ? (m_drawObjects[drawObjNdx].firstNdx) : (0);
44011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int	objectVertexLength		= (m_drawTriangles) ? (m_drawObjects[drawObjNdx].numVertices) : (0);
44021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMin;
44031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::Vec4	bboxMax;
44041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_drawTriangles)
44061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
44081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax = tcu::Vec4(-1.0f, -1.0f, -1.0f, -1.0f);
44091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// calc bbox
44111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int vertexNdx = objectVertexStartNdx; vertexNdx < objectVertexStartNdx + objectVertexLength; ++vertexNdx)
44121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int componentNdx = 0; componentNdx < 4; ++componentNdx)
44131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
44141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bboxMin[componentNdx] = de::min(bboxMin[componentNdx], m_objectVertices[vertexNdx][componentNdx]);
44151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				bboxMax[componentNdx] = de::max(bboxMax[componentNdx], m_objectVertices[vertexNdx][componentNdx]);
44161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
44171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
44191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			// no geometry, just random something
44211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.x() = rnd.getFloat(-1.2f, 1.0f);
44221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.y() = rnd.getFloat(-1.2f, 1.0f);
44231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.z() = rnd.getFloat(-1.2f, 1.0f);
44241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMin.w() = 1.0f;
44251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.x() = bboxMin.x() + rnd.getFloat(0.2f, 1.0f);
44261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.y() = bboxMin.y() + rnd.getFloat(0.2f, 1.0f);
44271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.z() = bboxMin.z() + rnd.getFloat(0.2f, 1.0f);
44281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			bboxMax.w() = 1.0f;
44291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_scissoredClear)
44321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorX = (m_fullscreenScissor) ? (0)					: rnd.getInt(0, renderTargetSize.x()-1);
44341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorY = (m_fullscreenScissor) ? (0)					: rnd.getInt(0, renderTargetSize.y()-1);
44351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorW = (m_fullscreenScissor) ? (renderTargetSize.x())	: rnd.getInt(0, renderTargetSize.x()-scissorX);
44361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const int scissorH = (m_fullscreenScissor) ? (renderTargetSize.y())	: rnd.getInt(0, renderTargetSize.y()-scissorY);
44371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.scissor(scissorX, scissorY, scissorW, scissorH);
44391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const tcu::Vec4 color = tcu::mix(green, yellow, rnd.getFloat() * 0.4f); // greenish
44431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.clearColor(color.x(), color.y(), color.z(), color.w());
44441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.clear(GL_COLOR_BUFFER_BIT);
44451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (useBBox)
44481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
44491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DE_ASSERT(m_useGlobalState || m_drawTriangles); // !m_useGlobalState -> m_drawTriangles
44501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			if (m_useGlobalState)
4451485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe				gl.primitiveBoundingBox(bboxMin.x(), bboxMin.y(), bboxMin.z(), bboxMin.w(),
4452485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe										bboxMax.x(), bboxMax.y(), bboxMax.z(), bboxMax.w());
44531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (m_drawTriangles)
44561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.drawArrays(GL_PATCHES, objectVertexStartNdx, objectVertexLength);
44571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "post draw");
44601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
44611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
44621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ClearCase::verifyImagesEqual (const tcu::PixelBufferAccess& withoutBBox, const tcu::PixelBufferAccess& withBBox)
44641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
44651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(withoutBBox.getWidth() == withBBox.getWidth());
446626e8fabf4c969e2dc11d638225e7bc81c27c46f7Jarkko Pöyry	DE_ASSERT(withoutBBox.getHeight() == withBBox.getHeight());
44671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(withoutBBox.getWidth(), withoutBBox.getHeight());
44691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
44701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4471c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
44721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < withoutBBox.getHeight(); ++y)
44741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < withoutBBox.getWidth(); ++x)
44751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (withoutBBox.getPixelInt(x, y) != withBBox.getPixelInt(x, y))
44771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4478c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
44791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
44801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
44811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
44841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
44851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
44861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
44871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image comparison failed."
44881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
44891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image comparison")
44901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("WithoutBBox", "Result with bounding box not set", withoutBBox)
44911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("WithBBox", "Result with bounding box set", withBBox)
44921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
44931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
44941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
44951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
44971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
44981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
44991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ClearCase::verifyImageResultValid (const tcu::PixelBufferAccess& result)
45001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface	errorMask	(result.getWidth(), result.getHeight());
45021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool			anyError	= false;
45031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4504c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
45051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < result.getHeight(); ++y)
45071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < result.getWidth(); ++x)
45081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
45091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec4 pixel = result.getPixelInt(x, y);
45101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// allow green, yellow and any shade between
45121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (pixel[1] != 255 || pixel[2] != 0)
45131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4514c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
45151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
45161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
45171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
45181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
45201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
45211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
45221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
45231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
45241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
45251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
45261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ResultImage", "Result image", result)
45271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
45281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
45291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
45301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
45321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4534cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulosstatic const char* const s_yellowishPosOnlyVertexSource =	"${GLSL_VERSION_DECL}\n"
45351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"in highp vec4 a_position;\n"
45361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"out highp vec4 v_vertex_color;\n"
45371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"void main()\n"
45381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"{\n"
45391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	gl_Position = a_position;\n"
45401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	// yellowish shade\n"
45411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	highp float redComponent = 0.5 + float(gl_VertexID % 5) / 8.0;\n"
45421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"	v_vertex_color = vec4(redComponent, 1.0, 0.0, 1.0);\n"
45431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry															"}\n";
45441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4545cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulosstatic const char* const s_basicColorFragmentSource =	"${GLSL_VERSION_DECL}\n"
45461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"in mediump vec4 v_color;\n"
45471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"layout(location = 0) out mediump vec4 o_color;\n"
45481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"void main()\n"
45491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"{\n"
45501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	o_color = v_color;\n"
45511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"}\n";
45521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4554cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulosstatic const char* const s_basicColorTessEvalSource =	"${GLSL_VERSION_DECL}\n"
4555cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos														"${TESSELLATION_SHADER_REQUIRE}\n"
4556cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos														"${GPU_SHADER5_REQUIRE}\n"
45571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"layout(triangles) in;\n"
45581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"in highp vec4 v_tess_eval_color[];\n"
45591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"out highp vec4 v_color;\n"
45601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"precise gl_Position;\n"
45611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"void main()\n"
45621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"{\n"
45631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position\n"
45641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	            + gl_TessCoord.y * gl_in[1].gl_Position\n"
45651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	            + gl_TessCoord.z * gl_in[2].gl_Position;\n"
45661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	v_color = gl_TessCoord.x * v_tess_eval_color[0]\n"
45671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	        + gl_TessCoord.y * v_tess_eval_color[1]\n"
45681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"	        + gl_TessCoord.z * v_tess_eval_color[2];\n"
45691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry														"}\n";
45701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genVertexSource (void) const
45721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return	s_yellowishPosOnlyVertexSource;
45741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genFragmentSource (void) const
45771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorFragmentSource;
45791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
45801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genTessellationControlSource (bool setBBox) const
45821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
45831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::ostringstream buf;
45841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4585cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	buf <<	"${GLSL_VERSION_DECL}\n"
4586cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n";
45871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (setBBox)
4589cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		buf << "${PRIMITIVE_BOUNDING_BOX_REQUIRE}\n";
45901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
45911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf <<	"layout(vertices=3) out;\n"
45921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 v_vertex_color[];\n"
45931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 v_tess_eval_color[];\n"
45941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
45951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
45961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
45971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_tess_eval_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
45981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
45991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
46001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
46011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n";
46021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (setBBox)
46041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
46051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		buf <<	"\n"
4606cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		"	${PRIM_GL_BOUNDING_BOX}[0] = min(min(gl_in[0].gl_Position,\n"
46071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                               gl_in[1].gl_Position),\n"
46081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                           gl_in[2].gl_Position);\n"
4609cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos		"	${PRIM_GL_BOUNDING_BOX}[1] = max(max(gl_in[0].gl_Position,\n"
46101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                               gl_in[1].gl_Position),\n"
46111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		"	                           gl_in[2].gl_Position);\n";
46121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
46131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	buf << "}\n";
46151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return buf.str();
46161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ClearCase::genTessellationEvaluationSource (void) const
46191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorTessEvalSource;
46211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryclass ViewportCallOrderCase : public TestCase
46241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrypublic:
46261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum CallOrder
46271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
46281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		VIEWPORT_FIRST = 0,
46291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		BBOX_FIRST,
46301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		ORDER_LAST
46321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
46331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									ViewportCallOrderCase			(Context& context, const char* name, const char* description, CallOrder callOrder);
46351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry									~ViewportCallOrderCase			(void);
46361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryprivate:
46381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							init							(void);
46391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							deinit							(void);
46401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	IterateResult					iterate							(void);
46411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							genVbo							(void);
46431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	void							genProgram						(void);
46441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool							verifyImage						(const tcu::PixelBufferAccess& result);
46451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genVertexSource					(void) const;
46471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genFragmentSource				(void) const;
46481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationControlSource	(void) const;
46491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::string						genTessellationEvaluationSource	(void) const;
46501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const CallOrder					m_callOrder;
46521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::Buffer>		m_vbo;
46541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::MovePtr<glu::ShaderProgram>	m_program;
46551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	int								m_numVertices;
46561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry};
46571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::ViewportCallOrderCase (Context& context, const char* name, const char* description, CallOrder callOrder)
46591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCase		(context, name, description)
46601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_callOrder	(callOrder)
46611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	, m_numVertices	(-1)
46621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	DE_ASSERT(m_callOrder < ORDER_LAST);
46641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::~ViewportCallOrderCase (void)
46671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
46681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	deinit();
46691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::init (void)
46721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
4673cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
4674cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos
4675cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_primitive_bounding_box"))
46761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::NotSupportedError("Test requires GL_EXT_primitive_bounding_box extension");
46771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4678cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
4679c22e16e65c11afffe24ad5c07f255a9f38b11231Mika Isojärvi		throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
4680c22e16e65c11afffe24ad5c07f255a9f38b11231Mika Isojärvi
46811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
46821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
46831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Testing call order of state setting functions have no effect on the rendering.\n"
46841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Setting viewport and bounding box in the following order:\n"
46851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_callOrder == VIEWPORT_FIRST)
46861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				? ("\tFirst viewport with glViewport function.\n")
46871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				: ("\tFirst bounding box with glPrimitiveBoundingBoxEXT function.\n"))
46881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< ((m_callOrder == VIEWPORT_FIRST)
46891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				? ("\tThen bounding box with glPrimitiveBoundingBoxEXT function.\n")
46901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				: ("\tThen viewport with glViewport function.\n"))
46911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying rendering result."
46921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
46931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// resources
46951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genVbo();
46961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	genProgram();
46971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
46981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
46991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::deinit (void)
47001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo.clear();
47021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program.clear();
47031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
47041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryViewportCallOrderCase::IterateResult ViewportCallOrderCase::iterate (void)
47061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
47081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const tcu::IVec2		viewportSize	= tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
47091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::GLint		posLocation		= gl.getAttribLocation(m_program->getProgram(), "a_position");
47101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface			resultSurface	(viewportSize.x(), viewportSize.y());
47111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
47131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.clear(GL_COLOR_BUFFER_BIT);
47141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// set state
47161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int orderNdx = 0; orderNdx < 2; ++orderNdx)
47171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
47181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if ((orderNdx == 0 && m_callOrder == VIEWPORT_FIRST) ||
47191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			(orderNdx == 1 && m_callOrder == BBOX_FIRST))
47201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
47211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
47221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::Message
47231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "Setting viewport to cover the left half of the render target.\n"
47241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t(0, 0, " << (viewportSize.x()/2) << ", " << viewportSize.y() << ")"
47251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::EndMessage;
47261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			gl.viewport(0, 0, viewportSize.x()/2, viewportSize.y());
47281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
47291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
47301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
47311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			m_testCtx.getLog()
47321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::Message
47331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "Setting bounding box to cover the right half of the clip space.\n"
47341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< "\t(0.0, -1.0, -1.0, 1.0) .. (1.0, 1.0, 1.0f, 1.0)"
47351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				<< tcu::TestLog::EndMessage;
47361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4737485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe			gl.primitiveBoundingBox(0.0f, -1.0f, -1.0f, 1.0f,
4738485a2d1c89e689e6b8523fc3b9c146c63e92bfd7Daniel Andrade Groppe									1.0f,  1.0f,  1.0f, 1.0f);
47391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
47401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
47411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
47431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
47441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Rendering mesh covering the right half of the clip space."
47451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
47461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
47481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float[4]), (const float*)DE_NULL);
47491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.enableVertexAttribArray(posLocation);
47501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.useProgram(m_program->getProgram());
47511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.patchParameteri(GL_PATCH_VERTICES, 3);
47521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.drawArrays(GL_PATCHES, 0, m_numVertices);
47531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "post-draw");
47541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
47561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Message
47571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< "Verifying image"
47581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndMessage;
47591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
47601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!verifyImage(resultSurface.getAccess()))
47621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
47631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	else
47641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
47651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
47661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
47671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Result ok."
47681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
47691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
47701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("Result", "Result", resultSurface.getAccess())
47711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
47721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
47741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
47751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return STOP;
47761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
47771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::genVbo (void)
47791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
47801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const int				gridSize	= 6;
47811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
47821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<tcu::Vec4>	data		(gridSize * gridSize * 2 * 3);
47831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	std::vector<int>		cellOrder	(gridSize * gridSize * 2);
47841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	de::Random				rnd			(0x55443322);
47851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid with triangles in random order
47871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
47881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		cellOrder[ndx] = ndx;
47891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	rnd.shuffle(cellOrder.begin(), cellOrder.end());
47901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// generate grid filling the right half of the clip space: (x: 0.0, y: -1.0) .. (x: 1.0, y: 1.0)
47921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int ndx = 0; ndx < (int)cellOrder.size(); ++ndx)
47931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
47941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellNdx		= cellOrder[ndx];
47951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			cellSide	= ((cellNdx % 2) == 0);
47961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellX		= (cellNdx / 2) % gridSize;
47971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const int			cellY		= (cellNdx / 2) / gridSize;
47981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
47991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if (cellSide)
48001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
48017a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48027a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48037a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
48051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		else
48061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
48077a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48087a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48097a161d243743d8d12e12669d7464c360de1b5e97Jarkko 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);
48101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
48111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
48121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_vbo = de::MovePtr<glu::Buffer>(new glu::Buffer(m_context.getRenderContext()));
48141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bindBuffer(GL_ARRAY_BUFFER, **m_vbo);
48151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	gl.bufferData(GL_ARRAY_BUFFER, (int)(data.size() * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
48161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "create vbo");
48171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_numVertices = (int)data.size();
48191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid ViewportCallOrderCase::genProgram (void)
48221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(),
48241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry																	   glu::ProgramSources()
4825cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																			<< glu::VertexSource(specializeShader(m_context, genVertexSource().c_str()))
4826cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																			<< glu::FragmentSource(specializeShader(m_context, genFragmentSource().c_str()))
4827cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																			<< glu::TessellationControlSource(specializeShader(m_context, genTessellationControlSource().c_str()))
4828cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos																			<< glu::TessellationEvaluationSource(specializeShader(m_context, genTessellationEvaluationSource().c_str()))));
48291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	m_testCtx.getLog()
48311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::Section("Program", "Shader program")
48321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< *m_program
48331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		<< tcu::TestLog::EndSection;
48341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (!m_program->isOk())
48361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		throw tcu::TestError("shader build failed");
48371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrybool ViewportCallOrderCase::verifyImage (const tcu::PixelBufferAccess& result)
48401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48417a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	insideBorder	(deCeilFloatToInt32(0.25f * (float)result.getWidth()) + 1, deFloorFloatToInt32(0.5f * (float)result.getWidth()) - 1);
48427a161d243743d8d12e12669d7464c360de1b5e97Jarkko Pöyry	const tcu::IVec2	outsideBorder	(deFloorFloatToInt32(0.25f * (float)result.getWidth()) - 1, deCeilFloatToInt32(0.5f * (float)result.getWidth()) + 1);
48431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	tcu::Surface		errorMask		(result.getWidth(), result.getHeight());
48441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	bool				anyError		= false;
48451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
4846c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
48471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int y = 0; y < result.getHeight(); ++y)
48491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int x = 0; x < result.getWidth(); ++x)
48501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const tcu::IVec4	pixel			= result.getPixelInt(x, y);
48521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			insideMeshArea	= x >= insideBorder.x() && x <= insideBorder.x();
48531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const bool			outsideMeshArea = x <= outsideBorder.x() && x >= outsideBorder.x();
48541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// inside mesh, allow green, yellow and any shade between
48561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// outside mesh, allow background (black) only
48571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// in the border area, allow anything
48581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		if ((insideMeshArea && (pixel[1] != 255 || pixel[2] != 0)) ||
48591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			(outsideMeshArea && (pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0)))
48601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
4861c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski			errorMask.setPixel(x, y, tcu::RGBA::red());
48621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			anyError = true;
48631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
48641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
48651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	if (anyError)
48671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
48681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		m_testCtx.getLog()
48691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Message
48701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< "Image verification failed."
48711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndMessage
48721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::ImageSet("Images", "Image verification")
48731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ResultImage", "Result image", result)
48741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
48751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			<< tcu::TestLog::EndImageSet;
48761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
48771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return !anyError;
48791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genVertexSource (void) const
48821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return	s_yellowishPosOnlyVertexSource;
48841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genFragmentSource (void) const
48871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
48881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorFragmentSource;
48891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
48901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
48911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genTessellationControlSource (void) const
48921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
4893cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos	return	"${GLSL_VERSION_DECL}\n"
4894cb24d85a6dae33dd3a658b831cd5f0c34918126aPyry Haulos			"${TESSELLATION_SHADER_REQUIRE}\n"
48951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"layout(vertices=3) out;\n"
48961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"in highp vec4 v_vertex_color[];\n"
48971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"out highp vec4 v_tess_eval_color[];\n"
48981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"void main()\n"
48991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"{\n"
49001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
49011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	v_tess_eval_color[gl_InvocationID] = v_vertex_color[gl_InvocationID];\n"
49021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[0] = 2.8;\n"
49031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[1] = 2.8;\n"
49041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelOuter[2] = 2.8;\n"
49051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"	gl_TessLevelInner[0] = 2.8;\n"
49061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"}\n";
49071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
49081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
49091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyrystd::string ViewportCallOrderCase::genTessellationEvaluationSource (void) const
49101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
49111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	return s_basicColorTessEvalSource;
49121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
49131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
49141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // anonymous
49151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
49161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPrimitiveBoundingBoxTests::PrimitiveBoundingBoxTests (Context& context)
49171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	: TestCaseGroup(context, "primitive_bounding_box", "Tests for EXT_primitive_bounding_box")
49181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
49191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
49201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
49211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko PöyryPrimitiveBoundingBoxTests::~PrimitiveBoundingBoxTests (void)
49221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
49231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
49241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
49251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyryvoid PrimitiveBoundingBoxTests::init (void)
49261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry{
49271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
49281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
49301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
49311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	methodFlags;
49321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} stateSetMethods[] =
49331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"global_state",
49361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using PRIMITIVE_BOUNDING_BOX_EXT state",
49371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_STATE,
49381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"tessellation_set_per_draw",
49411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using gl_BoundingBoxEXT, use same value for all primitives",
49421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_OUTPUT,
49431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"tessellation_set_per_primitive",
49461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Set bounding box using gl_BoundingBoxEXT, use per-primitive bounding box",
49471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_SET_BBOX_OUTPUT | BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
49501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
49511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
49531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
49541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	stageFlags;
49551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} pipelineConfigs[] =
49561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_fragment",
49591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-fragment program",
49601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0u
49611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_tessellation_fragment",
49641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-tessellation{ctrl,eval}-fragment program",
49651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_TESSELLATION
49661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_geometry_fragment",
49691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-tessellation{ctrl,eval}-geometry-fragment program",
49701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_GEOMETRY
49711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"vertex_tessellation_geometry_fragment",
49741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render with vertex-geometry-fragment program",
49751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_TESSELLATION | BBoxRenderCase::FLAG_GEOMETRY
49761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
49781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	static const struct
49791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	name;
49811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*	description;
49821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	flags;
49831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	invalidFlags;
49841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32	requiredFlags;
49851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} usageConfigs[] =
49861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
49871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_equal",
49891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set tight bounding box",
49901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
49911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
49931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
49941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
49951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_larger",
49961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set padded bounding box",
49971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_LARGER,
49981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
49991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer_bbox_smaller",
50031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set too small bounding box",
50041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_SMALLER,
50051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
50061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_equal",
50101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set tight bounding box",
50111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
50121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
50131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_larger",
50171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set padded bounding box",
50181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_LARGER,
50191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
50201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo_bbox_smaller",
50241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set too small bounding box",
50251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_SMALLER,
50261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX,
50271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"default_framebuffer",
50311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to default framebuffer, set tight bounding box",
50321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_DEFAULT | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
50331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0,
50341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX
50351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"fbo",
50381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Render to texture, set tight bounding box",
50391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_RENDERTARGET_FBO | BBoxRenderCase::FLAG_BBOXSIZE_EQUAL,
50401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0,
50411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			BBoxRenderCase::FLAG_PER_PRIMITIVE_BBOX
50421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
50441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	enum PrimitiveRenderType
50451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_TRIANGLE,
50471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_LINE,
50481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		TYPE_POINT,
50491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
50501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	const struct
50511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*			name;
50531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		const char*			description;
50541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		PrimitiveRenderType	type;
50551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		deUint32			flags;
50561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	} primitiveTypes[] =
50571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"triangles",
50601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Triangle render tests",
50611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_TRIANGLE,
50621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"lines",
50661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Line render tests",
50671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_LINE,
50681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"points",
50721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Point render tests",
50731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_POINT,
50741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			0
50751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"wide_lines",
50781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Wide line render tests",
50791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_LINE,
50801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			LineRenderCase::LINEFLAG_WIDE
50811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
50831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"wide_points",
50841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			"Wide point render tests",
50851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			TYPE_POINT,
50861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			PointRenderCase::POINTFLAG_WIDE
50871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		},
50881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	};
50891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .state_query
50911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
50921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const stateQueryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "State queries");
50931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(stateQueryGroup);
50941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
50951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new InitialValueCase	(m_context,	"initial_value",	"Initial value case"));
50961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getfloat",			"getFloatv",			QueryCase::QUERY_FLOAT));
50971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getboolean",		"getBooleanv",			QueryCase::QUERY_BOOLEAN));
50981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getinteger",		"getIntegerv",			QueryCase::QUERY_INT));
50991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		stateQueryGroup->addChild(new QueryCase			(m_context,	"getinteger64",		"getInteger64v",		QueryCase::QUERY_INT64));
51001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
51011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .triangles
51031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .(wide_)lines
51041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .(wide_)points
51051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
51061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
51071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, primitiveTypes[primitiveTypeNdx].description);
51081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(primitiveGroup);
51091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int stateSetMethodNdx = 0; stateSetMethodNdx < DE_LENGTH_OF_ARRAY(stateSetMethods); ++stateSetMethodNdx)
51111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, stateSetMethods[stateSetMethodNdx].name, stateSetMethods[stateSetMethodNdx].description);
51131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			primitiveGroup->addChild(methodGroup);
51141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int pipelineConfigNdx = 0; pipelineConfigNdx < DE_LENGTH_OF_ARRAY(pipelineConfigs); ++pipelineConfigNdx)
51161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				if ((stateSetMethods[stateSetMethodNdx].methodFlags & BBoxRenderCase::FLAG_SET_BBOX_OUTPUT) != 0 &&
51181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					(pipelineConfigs[pipelineConfigNdx].stageFlags  & BBoxRenderCase::FLAG_TESSELLATION)    == 0)
51191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
51201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					// invalid config combination
51211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
51221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				else
51231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				{
51241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					tcu::TestCaseGroup* const pipelineGroup = new tcu::TestCaseGroup(m_testCtx, pipelineConfigs[pipelineConfigNdx].name, pipelineConfigs[pipelineConfigNdx].description);
51251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					methodGroup->addChild(pipelineGroup);
51261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageConfigs); ++usageNdx)
51281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					{
51291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						const deUint32 flags = primitiveTypes[primitiveTypeNdx].flags         |
51301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   stateSetMethods[stateSetMethodNdx].methodFlags |
51311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   pipelineConfigs[pipelineConfigNdx].stageFlags  |
51321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry											   usageConfigs[usageNdx].flags;
51331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						if (usageConfigs[usageNdx].invalidFlags && (flags & usageConfigs[usageNdx].invalidFlags) != 0)
51351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							continue;
51361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						if (usageConfigs[usageNdx].requiredFlags && (flags & usageConfigs[usageNdx].requiredFlags) == 0)
51371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							continue;
51381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						switch (primitiveTypes[primitiveTypeNdx].type)
51401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						{
51411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_TRIANGLE:
51421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new GridRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
51431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
51441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_LINE:
51451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new LineRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
51461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
51471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							case TYPE_POINT:
51481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								pipelineGroup->addChild(new PointRenderCase(m_context, usageConfigs[usageNdx].name, usageConfigs[usageNdx].description, flags));
51491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								break;
51501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry							default:
51511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry								DE_ASSERT(false);
51521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry						}
51531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry					}
51541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				}
51551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			}
51561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
51571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
51581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
51591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .depth
51601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
51611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const struct
51621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					name;
51641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					description;
51651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::DepthType	depthMethod;
51661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		} depthMethods[] =
51671f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51681f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51691f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"builtin_depth",
51701f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Fragment depth not modified in fragment shader",
51711f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::DEPTH_BUILTIN
51721f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51731f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51741f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"user_defined_depth",
51751f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Fragment depth is defined in the fragment shader",
51761f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::DEPTH_USER_DEFINED
51771f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51781f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
51791f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		static const struct
51801f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51811f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					name;
51821f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			const char*					description;
51831f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::BBoxState	bboxState;
51841f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			DepthDrawCase::BBoxSize		bboxSize;
51851f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		} depthCases[] =
51861f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
51871f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51881f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"global_state_bbox_equal",
51891f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test tight bounding box with global bbox state",
51901f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_GLOBAL,
51911f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_EQUAL,
51921f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51931f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
51941f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"global_state_bbox_larger",
51951f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test padded bounding box with global bbox state",
51961f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_GLOBAL,
51971f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_LARGER,
51981f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
51991f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
52001f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"per_primitive_bbox_equal",
52011f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test tight bounding box with tessellation output bbox",
52021f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_PER_PRIMITIVE,
52031f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_EQUAL,
52041f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
52051f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			{
52061f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"per_primitive_bbox_larger",
52071f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				"Test padded bounding box with tessellation output bbox",
52081f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::STATE_PER_PRIMITIVE,
52091f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				DepthDrawCase::BBOX_LARGER,
52101f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			},
52111f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		};
52121f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52131f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const depthGroup = new tcu::TestCaseGroup(m_testCtx, "depth", "Test bounding box depth component");
52141f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(depthGroup);
52151f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52161f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// .builtin_depth
52171f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		// .user_defined_depth
52181f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		for (int depthNdx = 0; depthNdx < DE_LENGTH_OF_ARRAY(depthMethods); ++depthNdx)
52191f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		{
52201f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, depthMethods[depthNdx].name, depthMethods[depthNdx].description);
52211f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			depthGroup->addChild(group);
52221f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52231f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(depthCases); ++caseNdx)
52241f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry				group->addChild(new DepthDrawCase(m_context, depthCases[caseNdx].name, depthCases[caseNdx].description, depthMethods[depthNdx].depthMethod, depthCases[caseNdx].bboxState, depthCases[caseNdx].bboxSize));
52251f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		}
52261f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52271f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52281f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .blit_fbo
52291f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
52301f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const blitFboGroup = new tcu::TestCaseGroup(m_testCtx, "blit_fbo", "Test bounding box does not affect blitting");
52311f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(blitFboGroup);
52321f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52331f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_default_to_fbo", "Blit from default fb to fbo", BlitFboCase::TARGET_DEFAULT, BlitFboCase::TARGET_FBO));
52341f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_fbo_to_default", "Blit from fbo to default fb", BlitFboCase::TARGET_FBO,     BlitFboCase::TARGET_DEFAULT));
52351f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		blitFboGroup->addChild(new BlitFboCase(m_context, "blit_fbo_to_fbo",     "Blit from fbo to fbo",        BlitFboCase::TARGET_FBO,     BlitFboCase::TARGET_FBO));
52361f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52371f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52381f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .clear
52391f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
52401f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Test bounding box does not clears");
52411f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(clearGroup);
52421f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52431f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "full_clear",                                             "Do full clears",                                               0));
52441f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "full_clear_with_triangles",                              "Do full clears and render some geometry",                      ClearCase::DRAW_TRIANGLE_BIT));
52451f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52461f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		clearGroup->addChild(new ClearCase(m_context, "scissored_clear",                                        "Do scissored clears",                                          ClearCase::SCISSOR_CLEAR_BIT));
52471f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52481f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52491f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52501f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52511f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko 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));
52521f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52531f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52541f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	// .call_order (Khronos bug #13262)
52551f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	{
52561f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		tcu::TestCaseGroup* const callOrderGroup = new tcu::TestCaseGroup(m_testCtx, "call_order", "Test viewport and bounding box calls have no effect");
52571f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		addChild(callOrderGroup);
52581f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52591f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		callOrderGroup->addChild(new ViewportCallOrderCase(m_context, "viewport_first_bbox_second", "Set up viewport first and bbox after", ViewportCallOrderCase::VIEWPORT_FIRST));
52601f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry		callOrderGroup->addChild(new ViewportCallOrderCase(m_context, "bbox_first_viewport_second", "Set up bbox first and viewport after", ViewportCallOrderCase::BBOX_FIRST));
52611f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry	}
52621f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry}
52631f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry
52641f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // Functional
52651f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // gles31
52661f99d6991ce9a27d32ec0543d95646fe4e7bf001Jarkko Pöyry} // deqp
5267