/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * 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 SGLR shader program.
 *//*--------------------------------------------------------------------*/

#include "sglrShaderProgram.hpp"

namespace sglr
{
namespace pdec
{

ShaderProgramDeclaration::ShaderProgramDeclaration (void)
	: m_geometryDecl		(rr::GEOMETRYSHADERINPUTTYPE_LAST, rr::GEOMETRYSHADEROUTPUTTYPE_LAST, 0, 0)
	, m_vertexShaderSet		(false)
	, m_fragmentShaderSet	(false)
	, m_geometryShaderSet	(false)
{
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexAttribute& v)
{
	m_vertexAttributes.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToFragmentVarying& v)
{
	m_vertexToFragmentVaryings.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToGeometryVarying& v)
{
	m_vertexToGeometryVaryings.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryToFragmentVarying& v)
{
	m_geometryToFragmentVaryings.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentOutput& v)
{
	m_fragmentOutputs.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const Uniform& v)
{
	m_uniforms.push_back(v);
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexSource& c)
{
	DE_ASSERT(!m_vertexShaderSet);
	m_vertexSource = c.source;
	m_vertexShaderSet = true;
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentSource& c)
{
	DE_ASSERT(!m_fragmentShaderSet);
	m_fragmentSource = c.source;
	m_fragmentShaderSet = true;
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometrySource& c)
{
	DE_ASSERT(!m_geometryShaderSet);
	m_geometrySource = c.source;
	m_geometryShaderSet = true;
	return *this;
}

ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryShaderDeclaration& c)
{
	m_geometryDecl = c;
	return *this;
}

bool ShaderProgramDeclaration::valid (void) const
{
	if (!m_vertexShaderSet || !m_fragmentShaderSet)
		return false;

	if (m_fragmentOutputs.empty())
		return false;

	if (hasGeometryShader())
	{
		if (m_geometryDecl.inputType == rr::GEOMETRYSHADERINPUTTYPE_LAST ||
			m_geometryDecl.outputType == rr::GEOMETRYSHADEROUTPUTTYPE_LAST)
			return false;
	}
	else
	{
		if (m_geometryDecl.inputType != rr::GEOMETRYSHADERINPUTTYPE_LAST ||
			m_geometryDecl.outputType != rr::GEOMETRYSHADEROUTPUTTYPE_LAST ||
			m_geometryDecl.numOutputVertices != 0 ||
			m_geometryDecl.numInvocations != 0)
			return false;
	}

	return true;
}

} //pdec

ShaderProgram::ShaderProgram (const pdec::ShaderProgramDeclaration& decl)
	: rr::VertexShader		(decl.getVertexInputCount(), decl.getVertexOutputCount())
	, rr::GeometryShader	(decl.getGeometryInputCount(),
							 decl.getGeometryOutputCount(),
							 decl.m_geometryDecl.inputType,
							 decl.m_geometryDecl.outputType,
							 decl.m_geometryDecl.numOutputVertices,
							 decl.m_geometryDecl.numInvocations)
	, rr::FragmentShader	(decl.getFragmentInputCount(), decl.getFragmentOutputCount())
	, m_attributeNames		(decl.getVertexInputCount())
	, m_uniforms			(decl.m_uniforms.size())
	, m_vertSrc				(decl.m_vertexSource)
	, m_fragSrc				(decl.m_fragmentSource)
	, m_geomSrc				(decl.hasGeometryShader() ? (decl.m_geometrySource) : (""))
	, m_hasGeometryShader	(decl.hasGeometryShader())
{
	DE_ASSERT(decl.valid());

	// Set up shader IO

	for (size_t ndx = 0; ndx < decl.m_vertexAttributes.size(); ++ndx)
	{
		this->rr::VertexShader::m_inputs[ndx].type	= decl.m_vertexAttributes[ndx].type;
		m_attributeNames[ndx]						= decl.m_vertexAttributes[ndx].name;
	}

	if (m_hasGeometryShader)
	{
		for (size_t ndx = 0; ndx < decl.m_vertexToGeometryVaryings.size(); ++ndx)
		{
			this->rr::VertexShader::m_outputs[ndx].type			= decl.m_vertexToGeometryVaryings[ndx].type;
			this->rr::VertexShader::m_outputs[ndx].flatshade	= decl.m_vertexToGeometryVaryings[ndx].flatshade;

			this->rr::GeometryShader::m_inputs[ndx]				= this->rr::VertexShader::m_outputs[ndx];
		}
		for (size_t ndx = 0; ndx < decl.m_geometryToFragmentVaryings.size(); ++ndx)
		{
			this->rr::GeometryShader::m_outputs[ndx].type		= decl.m_geometryToFragmentVaryings[ndx].type;
			this->rr::GeometryShader::m_outputs[ndx].flatshade	= decl.m_geometryToFragmentVaryings[ndx].flatshade;

			this->rr::FragmentShader::m_inputs[ndx]				= this->rr::GeometryShader::m_outputs[ndx];
		}
	}
	else
	{
		for (size_t ndx = 0; ndx < decl.m_vertexToFragmentVaryings.size(); ++ndx)
		{
			this->rr::VertexShader::m_outputs[ndx].type			= decl.m_vertexToFragmentVaryings[ndx].type;
			this->rr::VertexShader::m_outputs[ndx].flatshade	= decl.m_vertexToFragmentVaryings[ndx].flatshade;

			this->rr::FragmentShader::m_inputs[ndx]				= this->rr::VertexShader::m_outputs[ndx];
		}
	}

	for (size_t ndx = 0; ndx < decl.m_fragmentOutputs.size(); ++ndx)
		this->rr::FragmentShader::m_outputs[ndx].type = decl.m_fragmentOutputs[ndx].type;

	// Set up uniforms

	for (size_t ndx = 0; ndx < decl.m_uniforms.size(); ++ndx)
	{
		this->m_uniforms[ndx].name = decl.m_uniforms[ndx].name;
		this->m_uniforms[ndx].type = decl.m_uniforms[ndx].type;
	}
}

ShaderProgram::~ShaderProgram (void)
{
}

const UniformSlot& ShaderProgram::getUniformByName (const char* name) const
{
	DE_ASSERT(name);

	for (size_t ndx = 0; ndx < m_uniforms.size(); ++ndx)
		if (m_uniforms[ndx].name == std::string(name))
			return m_uniforms[ndx];

	DE_FATAL("Invalid uniform name, uniform not found.");
	return m_uniforms[0];
}

void ShaderProgram::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
{
	DE_UNREF(output);
	DE_UNREF(verticesIn && packets && numPackets && invocationID);

	// Should never be called.
	DE_ASSERT(DE_FALSE);
}

} // sglr
