1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief SGLR shader program.
22 *//*--------------------------------------------------------------------*/
23
24#include "sglrShaderProgram.hpp"
25
26namespace sglr
27{
28namespace pdec
29{
30
31ShaderProgramDeclaration::ShaderProgramDeclaration (void)
32	: m_geometryDecl		(rr::GEOMETRYSHADERINPUTTYPE_LAST, rr::GEOMETRYSHADEROUTPUTTYPE_LAST, 0, 0)
33	, m_vertexShaderSet		(false)
34	, m_fragmentShaderSet	(false)
35	, m_geometryShaderSet	(false)
36{
37}
38
39ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexAttribute& v)
40{
41	m_vertexAttributes.push_back(v);
42	return *this;
43}
44
45ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToFragmentVarying& v)
46{
47	m_vertexToFragmentVaryings.push_back(v);
48	return *this;
49}
50
51ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToGeometryVarying& v)
52{
53	m_vertexToGeometryVaryings.push_back(v);
54	return *this;
55}
56
57ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryToFragmentVarying& v)
58{
59	m_geometryToFragmentVaryings.push_back(v);
60	return *this;
61}
62
63ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentOutput& v)
64{
65	m_fragmentOutputs.push_back(v);
66	return *this;
67}
68
69ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const Uniform& v)
70{
71	m_uniforms.push_back(v);
72	return *this;
73}
74
75ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexSource& c)
76{
77	DE_ASSERT(!m_vertexShaderSet);
78	m_vertexSource = c.source;
79	m_vertexShaderSet = true;
80	return *this;
81}
82
83ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentSource& c)
84{
85	DE_ASSERT(!m_fragmentShaderSet);
86	m_fragmentSource = c.source;
87	m_fragmentShaderSet = true;
88	return *this;
89}
90
91ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometrySource& c)
92{
93	DE_ASSERT(!m_geometryShaderSet);
94	m_geometrySource = c.source;
95	m_geometryShaderSet = true;
96	return *this;
97}
98
99ShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryShaderDeclaration& c)
100{
101	m_geometryDecl = c;
102	return *this;
103}
104
105bool ShaderProgramDeclaration::valid (void) const
106{
107	if (!m_vertexShaderSet || !m_fragmentShaderSet)
108		return false;
109
110	if (m_fragmentOutputs.empty())
111		return false;
112
113	if (hasGeometryShader())
114	{
115		if (m_geometryDecl.inputType == rr::GEOMETRYSHADERINPUTTYPE_LAST ||
116			m_geometryDecl.outputType == rr::GEOMETRYSHADEROUTPUTTYPE_LAST)
117			return false;
118	}
119	else
120	{
121		if (m_geometryDecl.inputType != rr::GEOMETRYSHADERINPUTTYPE_LAST ||
122			m_geometryDecl.outputType != rr::GEOMETRYSHADEROUTPUTTYPE_LAST ||
123			m_geometryDecl.numOutputVertices != 0 ||
124			m_geometryDecl.numInvocations != 0)
125			return false;
126	}
127
128	return true;
129}
130
131} //pdec
132
133ShaderProgram::ShaderProgram (const pdec::ShaderProgramDeclaration& decl)
134	: rr::VertexShader		(decl.getVertexInputCount(), decl.getVertexOutputCount())
135	, rr::GeometryShader	(decl.getGeometryInputCount(),
136							 decl.getGeometryOutputCount(),
137							 decl.m_geometryDecl.inputType,
138							 decl.m_geometryDecl.outputType,
139							 decl.m_geometryDecl.numOutputVertices,
140							 decl.m_geometryDecl.numInvocations)
141	, rr::FragmentShader	(decl.getFragmentInputCount(), decl.getFragmentOutputCount())
142	, m_attributeNames		(decl.getVertexInputCount())
143	, m_uniforms			(decl.m_uniforms.size())
144	, m_vertSrc				(decl.m_vertexSource)
145	, m_fragSrc				(decl.m_fragmentSource)
146	, m_geomSrc				(decl.hasGeometryShader() ? (decl.m_geometrySource) : (""))
147	, m_hasGeometryShader	(decl.hasGeometryShader())
148{
149	DE_ASSERT(decl.valid());
150
151	// Set up shader IO
152
153	for (size_t ndx = 0; ndx < decl.m_vertexAttributes.size(); ++ndx)
154	{
155		this->rr::VertexShader::m_inputs[ndx].type	= decl.m_vertexAttributes[ndx].type;
156		m_attributeNames[ndx]						= decl.m_vertexAttributes[ndx].name;
157	}
158
159	if (m_hasGeometryShader)
160	{
161		for (size_t ndx = 0; ndx < decl.m_vertexToGeometryVaryings.size(); ++ndx)
162		{
163			this->rr::VertexShader::m_outputs[ndx].type			= decl.m_vertexToGeometryVaryings[ndx].type;
164			this->rr::VertexShader::m_outputs[ndx].flatshade	= decl.m_vertexToGeometryVaryings[ndx].flatshade;
165
166			this->rr::GeometryShader::m_inputs[ndx]				= this->rr::VertexShader::m_outputs[ndx];
167		}
168		for (size_t ndx = 0; ndx < decl.m_geometryToFragmentVaryings.size(); ++ndx)
169		{
170			this->rr::GeometryShader::m_outputs[ndx].type		= decl.m_geometryToFragmentVaryings[ndx].type;
171			this->rr::GeometryShader::m_outputs[ndx].flatshade	= decl.m_geometryToFragmentVaryings[ndx].flatshade;
172
173			this->rr::FragmentShader::m_inputs[ndx]				= this->rr::GeometryShader::m_outputs[ndx];
174		}
175	}
176	else
177	{
178		for (size_t ndx = 0; ndx < decl.m_vertexToFragmentVaryings.size(); ++ndx)
179		{
180			this->rr::VertexShader::m_outputs[ndx].type			= decl.m_vertexToFragmentVaryings[ndx].type;
181			this->rr::VertexShader::m_outputs[ndx].flatshade	= decl.m_vertexToFragmentVaryings[ndx].flatshade;
182
183			this->rr::FragmentShader::m_inputs[ndx]				= this->rr::VertexShader::m_outputs[ndx];
184		}
185	}
186
187	for (size_t ndx = 0; ndx < decl.m_fragmentOutputs.size(); ++ndx)
188		this->rr::FragmentShader::m_outputs[ndx].type = decl.m_fragmentOutputs[ndx].type;
189
190	// Set up uniforms
191
192	for (size_t ndx = 0; ndx < decl.m_uniforms.size(); ++ndx)
193	{
194		this->m_uniforms[ndx].name = decl.m_uniforms[ndx].name;
195		this->m_uniforms[ndx].type = decl.m_uniforms[ndx].type;
196	}
197}
198
199ShaderProgram::~ShaderProgram (void)
200{
201}
202
203const UniformSlot& ShaderProgram::getUniformByName (const char* name) const
204{
205	DE_ASSERT(name);
206
207	for (size_t ndx = 0; ndx < m_uniforms.size(); ++ndx)
208		if (m_uniforms[ndx].name == std::string(name))
209			return m_uniforms[ndx];
210
211	DE_ASSERT(!"Invalid uniform name, uniform not found.");
212	return m_uniforms[0];
213}
214
215void ShaderProgram::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
216{
217	DE_UNREF(output);
218	DE_UNREF(verticesIn && packets && numPackets && invocationID);
219
220	// Should never be called.
221	DE_ASSERT(DE_FALSE);
222}
223
224} // sglr
225