1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Random Shader Generator
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 Shader Class.
22 *//*--------------------------------------------------------------------*/
23
24#include "rsgShader.hpp"
25
26using std::vector;
27
28namespace rsg
29{
30
31namespace
32{
33
34template <typename T>
35void deleteVectorElements (std::vector<T*>& vec)
36{
37	for (typename std::vector<T*>::iterator i = vec.begin(); i != vec.end(); i++)
38		delete *i;
39	vec.clear();
40}
41
42} // anonymous
43
44Function::Function (void)
45{
46}
47
48Function::Function (const char* name)
49	: m_name(name)
50{
51}
52
53Function::~Function (void)
54{
55	deleteVectorElements(m_parameters);
56}
57
58ShaderInput::ShaderInput (const Variable* variable, ConstValueRangeAccess valueRange)
59	: m_variable	(variable)
60	, m_min			(variable->getType().getScalarSize())
61	, m_max			(variable->getType().getScalarSize())
62{
63	ValueAccess(variable->getType(), &m_min[0]) = valueRange.getMin().value();
64	ValueAccess(variable->getType(), &m_max[0]) = valueRange.getMax().value();
65}
66
67Shader::Shader (Type type)
68	: m_type			(type)
69	, m_mainFunction	("main")
70{
71}
72
73Shader::~Shader (void)
74{
75	deleteVectorElements(m_functions);
76	deleteVectorElements(m_globalStatements);
77	deleteVectorElements(m_inputs);
78	deleteVectorElements(m_uniforms);
79}
80
81void Shader::getOutputs (vector<const Variable*>& outputs) const
82{
83	outputs.clear();
84	const vector<Variable*>& globalVars = m_globalScope.getDeclaredVariables();
85	for (vector<Variable*>::const_iterator i = globalVars.begin(); i != globalVars.end(); i++)
86	{
87		const Variable* var = *i;
88		if (var->getStorage() == Variable::STORAGE_SHADER_OUT)
89			outputs.push_back(var);
90	}
91}
92
93void Shader::tokenize (GeneratorState& state, TokenStream& str) const
94{
95	// Add default precision for float in fragment shaders \todo [pyry] Proper precision handling
96	if (state.getShader().getType() == Shader::TYPE_FRAGMENT)
97		str << Token::PRECISION << Token::MEDIUM_PRECISION << Token::FLOAT << Token::SEMICOLON << Token::NEWLINE;
98
99	// Tokenize global declaration statements
100	for (int ndx = (int)m_globalStatements.size()-1; ndx >= 0; ndx--)
101		m_globalStatements[ndx]->tokenize(state, str);
102
103	// Tokenize all functions
104	for (int ndx = (int)m_functions.size()-1; ndx >= 0; ndx--)
105	{
106		str << Token::NEWLINE;
107		m_functions[ndx]->tokenize(state, str);
108	}
109
110	// Tokenize main
111	str << Token::NEWLINE;
112	m_mainFunction.tokenize(state, str);
113}
114
115void Shader::execute (ExecutionContext& execCtx) const
116{
117	// Execute global statements (declarations)
118	for (vector<Statement*>::const_reverse_iterator i = m_globalStatements.rbegin(); i != m_globalStatements.rend(); i++)
119		(*i)->execute(execCtx);
120
121	// \todo [2011-03-08 pyry] Proper function calls
122	m_mainFunction.getBody().execute(execCtx);
123}
124
125void Function::tokenize (GeneratorState& state, TokenStream& str) const
126{
127	// Return type
128	m_returnType.tokenizeShortType(str);
129
130	// Function name
131	DE_ASSERT(m_name != "");
132	str << Token(m_name.c_str());
133
134	// Parameters
135	str << Token::LEFT_PAREN;
136
137	for (vector<Variable*>::const_iterator i = m_parameters.begin(); i != m_parameters.end(); i++)
138	{
139		if (i != m_parameters.begin())
140			str << Token::COMMA;
141		(*i)->tokenizeDeclaration(state, str);
142	}
143
144	str << Token::RIGHT_PAREN << Token::NEWLINE;
145
146	// Tokenize body
147	m_functionBlock.tokenize(state, str);
148}
149
150} // rsg
151