/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Program interface
 *//*--------------------------------------------------------------------*/

#include "es31fProgramInterfaceDefinition.hpp"
#include "es31fProgramInterfaceDefinitionUtil.hpp"
#include "gluVarType.hpp"
#include "gluShaderProgram.hpp"
#include "deSTLUtil.hpp"
#include "deStringUtil.hpp"
#include "glwEnums.hpp"

#include <set>

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace ProgramInterfaceDefinition
{
namespace
{

static const glu::ShaderType s_shaderStageOrder[] =
{
	glu::SHADERTYPE_COMPUTE,

	glu::SHADERTYPE_VERTEX,
	glu::SHADERTYPE_TESSELLATION_CONTROL,
	glu::SHADERTYPE_TESSELLATION_EVALUATION,
	glu::SHADERTYPE_GEOMETRY,
	glu::SHADERTYPE_FRAGMENT,
	glu::SHADERTYPE_RAYGEN,
	glu::SHADERTYPE_ANY_HIT,
	glu::SHADERTYPE_CLOSEST_HIT,
	glu::SHADERTYPE_MISS,
	glu::SHADERTYPE_INTERSECTION,
	glu::SHADERTYPE_CALLABLE,
};

// s_shaderStageOrder does not contain ShaderType_LAST
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST);

static bool containsMatchingSubtype (const glu::VarType& varType, bool (*predicate)(glu::DataType))
{
	if (varType.isBasicType() && predicate(varType.getBasicType()))
		return true;

	if (varType.isArrayType())
		return containsMatchingSubtype(varType.getElementType(), predicate);

	if (varType.isStructType())
		for (int memberNdx = 0; memberNdx < varType.getStructPtr()->getNumMembers(); ++memberNdx)
			if (containsMatchingSubtype(varType.getStructPtr()->getMember(memberNdx).getType(), predicate))
				return true;

	return false;
}

static bool containsMatchingSubtype (const std::vector<glu::VariableDeclaration>& decls, bool (*predicate)(glu::DataType))
{
	for (int varNdx = 0; varNdx < (int)decls.size(); ++varNdx)
		if (containsMatchingSubtype(decls[varNdx].varType, predicate))
			return true;
	return false;
}

static bool isOpaqueType (glu::DataType type)
{
	return	glu::isDataTypeAtomicCounter(type)	||
			glu::isDataTypeImage(type)			||
			glu::isDataTypeSampler(type);
}

static int getShaderStageIndex (glu::ShaderType stage)
{
	const glu::ShaderType* const it = std::find(DE_ARRAY_BEGIN(s_shaderStageOrder), DE_ARRAY_END(s_shaderStageOrder), stage);

	if (it == DE_ARRAY_END(s_shaderStageOrder))
		return -1;
	else
	{
		const int index = (int)(it - DE_ARRAY_BEGIN(s_shaderStageOrder));
		return index;
	}
}

} // anonymous

Shader::Shader (glu::ShaderType type, glu::GLSLVersion version)
	: m_shaderType	(type)
	, m_version		(version)
{
}

Shader::~Shader (void)
{
}

static bool isIllegalVertexInput (const glu::VarType& varType)
{
	// booleans, opaque types, arrays, structs are not allowed as inputs
	if (!varType.isBasicType())
		return true;
	if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
		return true;
	return false;
}

static bool isIllegalVertexOutput (const glu::VarType& varType, bool insideAStruct = false, bool insideAnArray = false)
{
	// booleans, opaque types, arrays of arrays, arrays of structs, array in struct, struct struct are not allowed as vertex outputs

	if (varType.isBasicType())
	{
		const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());

		if (glu::isDataTypeBoolOrBVec(varType.getBasicType()))
			return true;

		if (isOpaqueType)
			return true;

		return false;
	}
	else if (varType.isArrayType())
	{
		if (insideAnArray || insideAStruct)
			return true;

		return isIllegalVertexOutput(varType.getElementType(), insideAStruct, true);
	}
	else if (varType.isStructType())
	{
		if (insideAnArray || insideAStruct)
			return true;

		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
			if (isIllegalVertexOutput(varType.getStructPtr()->getMember(ndx).getType(), true, insideAnArray))
				return true;

		return false;
	}
	else
	{
		DE_ASSERT(false);
		return true;
	}
}

static bool isIllegalFragmentInput (const glu::VarType& varType)
{
	return isIllegalVertexOutput(varType);
}

static bool isIllegalFragmentOutput (const glu::VarType& varType, bool insideAnArray = false)
{
	// booleans, opaque types, matrices, structs, arrays of arrays are not allowed as outputs

	if (varType.isBasicType())
	{
		const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType());

		if (glu::isDataTypeBoolOrBVec(varType.getBasicType()) || isOpaqueType || glu::isDataTypeMatrix(varType.getBasicType()))
			return true;
		return false;
	}
	else if (varType.isArrayType())
	{
		if (insideAnArray)
			return true;
		return isIllegalFragmentOutput(varType.getElementType(), true);
	}
	else if (varType.isStructType())
		return true;
	else
	{
		DE_ASSERT(false);
		return true;
	}
}

static bool isTypeIntegerOrContainsIntegers (const glu::VarType& varType)
{
	if (varType.isBasicType())
		return glu::isDataTypeIntOrIVec(varType.getBasicType()) || glu::isDataTypeUintOrUVec(varType.getBasicType());
	else if (varType.isArrayType())
		return isTypeIntegerOrContainsIntegers(varType.getElementType());
	else if (varType.isStructType())
	{
		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
			if (isTypeIntegerOrContainsIntegers(varType.getStructPtr()->getMember(ndx).getType()))
				return true;
		return false;
	}
	else
	{
		DE_ASSERT(false);
		return true;
	}
}

bool Shader::isValid (void) const
{
	// Default block variables
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			// atomic declaration in the default block without binding
			if (m_defaultBlock.variables[varNdx].layout.binding == -1 &&
				containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
				return false;

			// atomic declaration in a struct
			if (m_defaultBlock.variables[varNdx].varType.isStructType() &&
				containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter))
				return false;

			// Unsupported layout qualifiers

			if (m_defaultBlock.variables[varNdx].layout.matrixOrder != glu::MATRIXORDER_LAST)
				return false;

			if (containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeSampler))
			{
				const glu::Layout layoutWithLocationAndBinding(m_defaultBlock.variables[varNdx].layout.location, m_defaultBlock.variables[varNdx].layout.binding);

				if (m_defaultBlock.variables[varNdx].layout != layoutWithLocationAndBinding)
					return false;
			}
		}
	}

	// Interface blocks
	{
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			// ES31 disallows interface block array arrays
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.size() > 1)
				return false;

			// Interface block arrays must have instance name
			if (!m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty() && m_defaultBlock.interfaceBlocks[interfaceNdx].instanceName.empty())
				return false;

			// Opaque types in interface block
			if (containsMatchingSubtype(m_defaultBlock.interfaceBlocks[interfaceNdx].variables, isOpaqueType))
				return false;
		}
	}

	// Shader type specific

	if (m_shaderType == glu::SHADERTYPE_VERTEX)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalVertexInput(m_defaultBlock.variables[varNdx].varType))
				return false;
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalVertexOutput(m_defaultBlock.variables[varNdx].varType))
				return false;
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
				return false;
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN			||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
		}
	}
	else if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalFragmentInput(m_defaultBlock.variables[varNdx].varType))
				return false;
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType))
				return false;
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalFragmentOutput(m_defaultBlock.variables[varNdx].varType))
				return false;
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT		||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
		}
	}
	else if (m_shaderType == glu::SHADERTYPE_COMPUTE)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN			||
				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT		||
				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN			||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT		||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
		}
	}
	else if (m_shaderType == glu::SHADERTYPE_GEOMETRY)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
			// arrayed input
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
				return false;
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN	||
				m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
			{
				return false;
			}
			// arrayed input
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
				return false;
		}
	}
	else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN)
				return false;
			// arrayed input
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
				return false;
			// arrayed output
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && !m_defaultBlock.variables[varNdx].varType.isArrayType())
				return false;
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN)
				return false;
			// arrayed input
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
				return false;
			// arrayed output
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
				return false;
		}
	}
	else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
	{
		for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx)
		{
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT)
				return false;
			// arrayed input
			if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType())
				return false;
		}
		for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
		{
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT)
				return false;
			// arrayed input
			if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty())
				return false;
		}
	}
	else
		DE_ASSERT(false);

	return true;
}

Program::Program (void)
	: m_separable				(false)
	, m_xfbMode					(0)
	, m_geoNumOutputVertices	(0)
	, m_tessNumOutputVertices	(0)
{
}

static void collectStructPtrs (std::set<const glu::StructType*>& dst, const glu::VarType& type)
{
	if (type.isArrayType())
		collectStructPtrs(dst, type.getElementType());
	else if (type.isStructType())
	{
		dst.insert(type.getStructPtr());

		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
			collectStructPtrs(dst, type.getStructPtr()->getMember(memberNdx).getType());
	}
}

Program::~Program (void)
{
	// delete shader struct types, need to be done by the program since shaders might share struct types
	{
		std::set<const glu::StructType*> structTypes;

		for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
		{
			for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.variables.size(); ++varNdx)
				collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.variables[varNdx].varType);

			for (int interfaceNdx = 0; interfaceNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx)
				for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
					collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables[varNdx].varType);
		}

		for (std::set<const glu::StructType*>::iterator it = structTypes.begin(); it != structTypes.end(); ++it)
			delete *it;
	}

	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
		delete m_shaders[shaderNdx];
	m_shaders.clear();
}

Shader* Program::addShader (glu::ShaderType type, glu::GLSLVersion version)
{
	DE_ASSERT(type < glu::SHADERTYPE_LAST);

	Shader* shader;

	// make sure push_back() cannot throw
	m_shaders.reserve(m_shaders.size() + 1);

	shader = new Shader(type, version);
	m_shaders.push_back(shader);

	return shader;
}

void Program::setSeparable (bool separable)
{
	m_separable = separable;
}

bool Program::isSeparable (void) const
{
	return m_separable;
}

const std::vector<Shader*>& Program::getShaders (void) const
{
	return m_shaders;
}

glu::ShaderType Program::getFirstStage (void) const
{
	const int	nullValue	= DE_LENGTH_OF_ARRAY(s_shaderStageOrder);
	int			firstStage	= nullValue;

	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
	{
		const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
		if (index != -1)
			firstStage = de::min(firstStage, index);
	}

	if (firstStage == nullValue)
		return glu::SHADERTYPE_LAST;
	else
		return s_shaderStageOrder[firstStage];
}

glu::ShaderType Program::getLastStage (void) const
{
	const int	nullValue	= -1;
	int			lastStage	= nullValue;

	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
	{
		const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType());
		if (index != -1)
			lastStage = de::max(lastStage, index);
	}

	if (lastStage == nullValue)
		return glu::SHADERTYPE_LAST;
	else
		return s_shaderStageOrder[lastStage];
}

bool Program::hasStage (glu::ShaderType stage) const
{
	for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx)
	{
		if (m_shaders[shaderNdx]->getType() == stage)
			return true;
	}
	return false;
}

void Program::addTransformFeedbackVarying (const std::string& varName)
{
	m_xfbVaryings.push_back(varName);
}

const std::vector<std::string>& Program::getTransformFeedbackVaryings (void) const
{
	return m_xfbVaryings;
}

void Program::setTransformFeedbackMode (deUint32 mode)
{
	m_xfbMode = mode;
}

deUint32 Program::getTransformFeedbackMode (void) const
{
	return m_xfbMode;
}

deUint32 Program::getGeometryNumOutputVertices (void) const
{
	return m_geoNumOutputVertices;
}

void Program::setGeometryNumOutputVertices (deUint32 vertices)
{
	m_geoNumOutputVertices = vertices;
}

deUint32 Program::getTessellationNumOutputPatchVertices (void) const
{
	return m_tessNumOutputVertices;
}

void Program::setTessellationNumOutputPatchVertices (deUint32 vertices)
{
	m_tessNumOutputVertices = vertices;
}

bool Program::isValid (void) const
{
	const bool	isOpenGLES			= (m_shaders.empty()) ? (false) : (glu::glslVersionIsES(m_shaders[0]->getVersion()));
	bool		computePresent		= false;
	bool		vertexPresent		= false;
	bool		fragmentPresent		= false;
	bool		tessControlPresent	= false;
	bool		tessEvalPresent		= false;
	bool		geometryPresent		= false;

	if (m_shaders.empty())
		return false;

	for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
		if (!m_shaders[ndx]->isValid())
			return false;

	// same version
	for (int ndx = 1; ndx < (int)m_shaders.size(); ++ndx)
		if (m_shaders[0]->getVersion() != m_shaders[ndx]->getVersion())
			return false;

	for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx)
	{
		switch (m_shaders[ndx]->getType())
		{
			case glu::SHADERTYPE_COMPUTE:					computePresent = true;		break;
			case glu::SHADERTYPE_VERTEX:					vertexPresent = true;		break;
			case glu::SHADERTYPE_FRAGMENT:					fragmentPresent = true;		break;
			case glu::SHADERTYPE_TESSELLATION_CONTROL:		tessControlPresent = true;	break;
			case glu::SHADERTYPE_TESSELLATION_EVALUATION:	tessEvalPresent = true;		break;
			case glu::SHADERTYPE_GEOMETRY:					geometryPresent = true;		break;
			default:
				DE_ASSERT(false);
				break;
		}
	}
	// compute present -> no other stages present
	{
		const bool nonComputePresent = vertexPresent || fragmentPresent || tessControlPresent || tessEvalPresent || geometryPresent;
		if (computePresent && nonComputePresent)
			return false;
	}

	// must contain both vertex and fragment shaders
	if (!computePresent && !m_separable)
	{
		if (!vertexPresent || !fragmentPresent)
			return false;
	}

	// tess.Eval present <=> tess.Control present
	if (!m_separable)
	{
		if (tessEvalPresent != tessControlPresent)
			return false;
	}

	if ((m_tessNumOutputVertices != 0) != (tessControlPresent || tessEvalPresent))
		return false;

	if ((m_geoNumOutputVertices != 0) != geometryPresent)
		return false;

	for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
	{
		// user-defined
		if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
		{
			std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
			if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
				return false;
			if (!path.back().isVariableType())
				return false;

			// Khronos bug #12787 disallowed capturing whole structs in OpenGL ES.
			if (path.back().getVariableType()->isStructType() && isOpenGLES)
				return false;
		}
	}

	return true;
}

} // ProgramInterfaceDefinition
} // Functional
} // gles31
} // deqp
