/*-------------------------------------------------------------------------
* 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