1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 -----------------------------------------------------------------------------
26 */
27 #include "OgreShaderPrecompiledHeaders.h"
28 
29 namespace Ogre {
30 namespace RTShader {
31 
32 
33 //-----------------------------------------------------------------------
RenderState()34 RenderState::RenderState()
35 {
36     mLightCountAutoUpdate    = true;
37     mLightCount[0]           = 0;
38     mLightCount[1]           = 0;
39     mLightCount[2]           = 0;
40 }
41 
42 //-----------------------------------------------------------------------
~RenderState()43 RenderState::~RenderState()
44 {
45     reset();
46 }
47 
48 //-----------------------------------------------------------------------
reset()49 void RenderState::reset()
50 {
51     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
52     {
53         ShaderGenerator::getSingleton().destroySubRenderState(*it);
54     }
55     mSubRenderStateList.clear();
56 }
57 
58 //-----------------------------------------------------------------------
setLightCount(const int lightCount[3])59 void RenderState::setLightCount(const int lightCount[3])
60 {
61     mLightCount[0] = lightCount[0];
62     mLightCount[1] = lightCount[1];
63     mLightCount[2] = lightCount[2];
64 }
65 
66 //-----------------------------------------------------------------------
getLightCount(int lightCount[3]) const67 void RenderState::getLightCount(int lightCount[3]) const
68 {
69     lightCount[0] = mLightCount[0];
70     lightCount[1] = mLightCount[1];
71     lightCount[2] = mLightCount[2];
72 }
73 
74 //-----------------------------------------------------------------------
addTemplateSubRenderState(SubRenderState * subRenderState)75 void RenderState::addTemplateSubRenderState(SubRenderState* subRenderState)
76 {
77     bool addSubRenderState = true;
78 
79     // Go over the current sub render state.
80     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
81     {
82         // Case the same instance already exists -> do not add to list.
83         if (*it == subRenderState)
84         {
85             addSubRenderState = false;
86             break;
87         }
88 
89         // Case it is different sub render state instance with the same type, use the new sub render state
90         // instead of the previous sub render state. This scenario is usually caused by material inheritance, so we use the derived material sub render state
91         // and destroy the base sub render state.
92         else if ((*it)->getType() == subRenderState->getType())
93         {
94             removeTemplateSubRenderState(*it);
95             break;
96         }
97     }
98 
99     // Add only if this sub render state instance is not on the list.
100     if (addSubRenderState)
101     {
102         mSubRenderStateList.push_back(subRenderState);
103     }
104 }
105 
106 //-----------------------------------------------------------------------
removeTemplateSubRenderState(SubRenderState * subRenderState)107 void RenderState::removeTemplateSubRenderState(SubRenderState* subRenderState)
108 {
109     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
110     {
111         if ((*it) == subRenderState)
112         {
113             ShaderGenerator::getSingleton().destroySubRenderState(*it);
114             mSubRenderStateList.erase(it);
115             break;
116         }
117     }
118 }
119 
120 //-----------------------------------------------------------------------
TargetRenderState()121 TargetRenderState::TargetRenderState()
122 {
123     mProgramSet              = NULL;
124     mSubRenderStateSortValid = false;
125 }
126 
127 //-----------------------------------------------------------------------
~TargetRenderState()128 TargetRenderState::~TargetRenderState()
129 {
130     destroyProgramSet();
131 }
132 
133 
134 //-----------------------------------------------------------------------
addSubRenderStateInstance(SubRenderState * subRenderState)135 void TargetRenderState::addSubRenderStateInstance(SubRenderState* subRenderState)
136 {
137     mSubRenderStateList.push_back(subRenderState);
138     mSubRenderStateSortValid = false;
139 }
140 
141 //-----------------------------------------------------------------------
removeSubRenderStateInstance(SubRenderState * subRenderState)142 void TargetRenderState::removeSubRenderStateInstance(SubRenderState* subRenderState)
143 {
144     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
145     {
146         if ((*it) == subRenderState)
147         {
148             ShaderGenerator::getSingleton().destroySubRenderState(*it);
149             mSubRenderStateList.erase(it);
150             break;
151         }
152     }
153 }
154 
155 //-----------------------------------------------------------------------
createCpuPrograms()156 bool TargetRenderState::createCpuPrograms()
157 {
158     sortSubRenderStates();
159 
160     ProgramSet* programSet = createProgramSet();
161     Program* vsProgram = ProgramManager::getSingleton().createCpuProgram(GPT_VERTEX_PROGRAM);
162     Program* psProgram = ProgramManager::getSingleton().createCpuProgram(GPT_FRAGMENT_PROGRAM);
163     RTShader::Function* vsMainFunc = NULL;
164     RTShader::Function* psMainFunc = NULL;
165 
166     programSet->setCpuProgram(vsProgram, GPT_VERTEX_PROGRAM);
167     programSet->setCpuProgram(psProgram, GPT_FRAGMENT_PROGRAM);
168 
169     // Create entry point functions.
170     vsMainFunc = vsProgram->createFunction("main", "Vertex Program Entry point", Function::FFT_VS_MAIN);
171     vsProgram->setEntryPointFunction(vsMainFunc);
172 
173     psMainFunc = psProgram->createFunction("main", "Pixel Program Entry point", Function::FFT_PS_MAIN);
174     psProgram->setEntryPointFunction(psMainFunc);
175 
176     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
177     {
178         SubRenderState* srcSubRenderState = *it;
179 
180         if (false == srcSubRenderState->createCpuSubPrograms(programSet))
181         {
182             LogManager::getSingleton().stream() << "RTShader::TargetRenderState : Could not generate sub render program of type: " << srcSubRenderState->getType();
183             return false;
184         }
185     }
186 
187     return true;
188 }
189 
190 //-----------------------------------------------------------------------
createProgramSet()191 ProgramSet* TargetRenderState::createProgramSet()
192 {
193     destroyProgramSet();
194 
195     mProgramSet = OGRE_NEW ProgramSet;
196 
197     return mProgramSet;
198 }
199 //-----------------------------------------------------------------------
destroyProgramSet()200 void TargetRenderState::destroyProgramSet()
201 {
202     if (mProgramSet != NULL)
203     {
204         OGRE_DELETE mProgramSet;
205         mProgramSet = NULL;
206     }
207 }
208 
209 //-----------------------------------------------------------------------
updateGpuProgramsParams(Renderable * rend,Pass * pass,const AutoParamDataSource * source,const LightList * pLightList)210 void TargetRenderState::updateGpuProgramsParams(Renderable* rend, Pass* pass, const AutoParamDataSource* source,
211                                                 const LightList* pLightList)
212 {
213     for (SubRenderStateListIterator it=mSubRenderStateList.begin(); it != mSubRenderStateList.end(); ++it)
214     {
215         SubRenderState* curSubRenderState = *it;
216 
217         curSubRenderState->updateGpuProgramsParams(rend, pass, source, pLightList);
218     }
219 }
220 
221 //-----------------------------------------------------------------------
link(const RenderState & rhs,Pass * srcPass,Pass * dstPass)222 void TargetRenderState::link(const RenderState& rhs, Pass* srcPass, Pass* dstPass)
223 {
224     SubRenderStateList customSubRenderStates;
225 
226     // Sort current render states.
227     sortSubRenderStates();
228 
229     // Insert all custom sub render states. (I.E Not FFP sub render states).
230     const SubRenderStateList& subRenderStateList = rhs.getTemplateSubRenderStateList();
231 
232     for (SubRenderStateListConstIterator itSrc=subRenderStateList.begin(); itSrc != subRenderStateList.end(); ++itSrc)
233     {
234         const SubRenderState* srcSubRenderState = *itSrc;
235         bool isCustomSubRenderState = true;
236 
237         if (srcSubRenderState->getExecutionOrder() == FFP_TRANSFORM ||
238             srcSubRenderState->getExecutionOrder() == FFP_COLOUR ||
239             srcSubRenderState->getExecutionOrder() == FFP_LIGHTING ||
240             srcSubRenderState->getExecutionOrder() == FFP_TEXTURING ||
241             srcSubRenderState->getExecutionOrder() == FFP_FOG)
242         {
243             isCustomSubRenderState = false;
244         }
245 
246 
247         // Case it is a custom sub render state.
248         if (isCustomSubRenderState)
249         {
250             bool subStateTypeExists = false;
251 
252             // Check if this type of sub render state already exists.
253             for (SubRenderStateListConstIterator itDst=mSubRenderStateList.begin(); itDst != mSubRenderStateList.end(); ++itDst)
254             {
255                 if ((*itDst)->getType() == srcSubRenderState->getType())
256                 {
257                     subStateTypeExists = true;
258                     break;
259                 }
260             }
261 
262             // Case custom sub render state not exits -> add it to custom list.
263             if (subStateTypeExists == false)
264             {
265                 SubRenderState* newSubRenderState = NULL;
266 
267                 newSubRenderState = ShaderGenerator::getSingleton().createSubRenderState(srcSubRenderState->getType());
268                 *newSubRenderState = *srcSubRenderState;
269                 customSubRenderStates.push_back(newSubRenderState);
270             }
271         }
272     }
273 
274     // Merge the local custom sub render states.
275     for (SubRenderStateListIterator itSrc=customSubRenderStates.begin(); itSrc != customSubRenderStates.end(); ++itSrc)
276     {
277         SubRenderState* customSubRenderState = *itSrc;
278 
279         if (customSubRenderState->preAddToRenderState(this, srcPass, dstPass))
280         {
281             addSubRenderStateInstance(customSubRenderState);
282         }
283         else
284         {
285             ShaderGenerator::getSingleton().destroySubRenderState(customSubRenderState);
286         }
287     }
288 }
289 
290 namespace {
291     struct CmpSubRenderStates {
operator ()Ogre::RTShader::__anondf415dbe0111::CmpSubRenderStates292         bool operator()(const SubRenderState* a, const SubRenderState* b) const
293         {
294             return a->getExecutionOrder() < b->getExecutionOrder();
295         }
296     };
297 }
298 
299 //-----------------------------------------------------------------------
sortSubRenderStates()300 void TargetRenderState::sortSubRenderStates()
301 {
302     if (mSubRenderStateSortValid == false)
303     {
304         std::sort(mSubRenderStateList.begin(), mSubRenderStateList.end(), CmpSubRenderStates());
305         mSubRenderStateSortValid = true;
306     }
307 }
308 
309 }
310 }
311