csplugincommon/rendermanager/dependenttarget.h
Go to the documentation of this file.00001 /* 00002 Copyright (C) 2007-2008 by Marten Svanfeldt 00003 (C) 2007 by Frank Richter 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_DEPENDENTTARGET_H__ 00021 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_DEPENDENTTARGET_H__ 00022 00027 #include "iengine/rendermanager.h" 00028 00029 #include "csplugincommon/rendermanager/operations.h" 00030 #include "csplugincommon/rendermanager/rendertree.h" 00031 #include "csplugincommon/rendermanager/shadersetup.h" 00032 #include "csplugincommon/rendermanager/svtraverse.h" 00033 #include "csutil/fifo.h" 00034 #include "csutil/set.h" 00035 00036 namespace CS 00037 { 00038 namespace RenderManager 00039 { 00040 00054 template<typename RenderTree, typename TargetHandler> 00055 class DependentTargetManager 00056 { 00057 public: 00061 struct TargetSettings 00062 { 00064 iView* view; 00066 iTextureHandle* target; 00068 int targetSubTexture; 00070 int drawFlags; 00071 }; 00072 00074 DependentTargetManager (TargetHandler& targetHandler) 00075 : targetHandler (targetHandler), rendering (false) 00076 {} 00077 00078 void RegisterRenderTarget (iTextureHandle* target, 00079 iView* view, int subtexture = 0, uint flags = 0) 00080 { 00081 typename RenderTargetInfo::ViewInfo newView; 00082 newView.view = view; 00083 newView.flags = flags & 00084 ~(iRenderManagerTargets::updateOnce | iRenderManagerTargets::assumeAlwaysUsed); 00085 TargetsHash* targets; 00086 if (flags & iRenderManagerTargets::updateOnce) 00087 { 00088 targets = &oneTimeTargets; 00089 } 00090 else if (flags & iRenderManagerTargets::assumeAlwaysUsed) 00091 { 00092 targets = &alwaysUsedTargets; 00093 } 00094 else 00095 { 00096 targets = &this->targets; 00097 } 00098 RenderTargetInfo* targetInfo = targets->GetElementPointer (target); 00099 if (targetInfo == 0) 00100 { 00101 RenderTargetInfo newInfo; 00102 newInfo.views.Put (subtexture, newView); 00103 targets->PutUnique (target, newInfo); 00104 } 00105 else 00106 { 00107 targetInfo->views.Put (subtexture, newView); 00108 } 00109 } 00110 00111 void UnregisterRenderTarget (iTextureHandle* target, 00112 int subtexture = 0) 00113 { 00114 00115 RenderTargetInfo* targetInfo = targets.GetElementPointer (target); 00116 if (targetInfo != 0) 00117 { 00118 targetInfo->views.DeleteAll (subtexture); 00119 if (targetInfo->views.IsEmpty()) targets.DeleteAll (target); 00120 return; 00121 } 00122 targetInfo = oneTimeTargets.GetElementPointer (target); 00123 if (targetInfo != 0) 00124 { 00125 targetInfo->views.DeleteAll (subtexture); 00126 if (targetInfo->views.IsEmpty()) oneTimeTargets.DeleteAll (target); 00127 } 00128 targetInfo = alwaysUsedTargets.GetElementPointer (target); 00129 if (targetInfo != 0) 00130 { 00131 targetInfo->views.DeleteAll (subtexture); 00132 if (targetInfo->views.IsEmpty()) alwaysUsedTargets.DeleteAll (target); 00133 } 00134 forciblyUsedTextures.Delete (target); 00135 } 00136 00137 void MarkAsUsed (iTextureHandle* target) 00138 { 00139 if (rendering) 00140 HandleTexture (target, CS::InvalidShaderVarStringID, 0); 00141 else 00142 forciblyUsedTextures.Push (target); 00143 } 00144 00149 void StartRendering (iShaderManager* shaderManager) 00150 { 00151 CS_ASSERT(!rendering); 00152 rendering = true; 00153 00154 size_t numSVs = shaderManager->GetSVNameStringset()->GetSize(); 00155 names.SetSize (numSVs); 00156 handledTargets.Empty(); 00157 handledTargets.SetCapacity (targets.GetSize() + oneTimeTargets.GetSize() 00158 + alwaysUsedTargets.GetSize()); 00159 00160 targetQueue.DeleteAll (); 00161 00162 typename TargetsHash::GlobalIterator alwaysUsedIt ( 00163 alwaysUsedTargets.GetIterator()); 00164 while (alwaysUsedIt.HasNext()) 00165 { 00166 csRef<iTextureHandle> target; 00167 RenderTargetInfo& targetInfo (alwaysUsedIt.Next (target)); 00168 00169 HandleTarget (target, &targetInfo, 0); 00170 } 00171 00172 for (size_t i = 0; i < forciblyUsedTextures.GetSize(); i++) 00173 { 00174 HandleTexture (forciblyUsedTextures[i], CS::InvalidShaderVarStringID, 0); 00175 } 00176 forciblyUsedTextures.DeleteAll(); 00177 } 00178 00183 template<typename LayerConfigType> 00184 void EnqueueTargets (RenderTree& renderTree, iShaderManager* shaderManager, 00185 const LayerConfigType& layerConfig, 00186 csSet<typename RenderTree::ContextNode*>& contextsTested) 00187 { 00188 if ((targets.GetSize() + oneTimeTargets.GetSize()) == 0) 00189 // Nothing to do (forced textures were already dealt with) 00190 return; 00191 00192 // Setup callbacks for SVs and mesh nodes 00193 NewTargetFn newTarget (*this, renderTree); 00194 typedef TraverseUsedSVs<RenderTree, NewTargetFn> MeshTraverseType; 00195 MeshTraverseType svTraverser 00196 (newTarget, shaderManager->GetSVNameStringset ()->GetSize (), 00197 iShader::svuTextures); 00198 00199 // Just traverse each context once 00200 Implementation::OnceOperationBlockRef<typename RenderTree::ContextNode*> 00201 opBlock (contextsTested); 00202 00203 Implementation::NoOperationBlock<typename RenderTree::MeshNode*> meshNoBlock; 00204 00205 // Helper for traversing all contexts within tree 00206 Implementation::MeshContextTraverser< 00207 typename RenderTree::ContextNode, 00208 MeshTraverseType, 00209 Implementation::NoOperationBlock<typename RenderTree::MeshNode*> 00210 > contextTraverse (svTraverser, meshNoBlock); 00211 00212 // And do the iteration 00213 ForEachContext (renderTree, contextTraverse, opBlock); 00214 } 00215 00219 bool HaveMoreTargets() const 00220 { 00221 return targetQueue.GetSize () > 0; 00222 } 00223 00227 void GetNextTarget (TargetSettings& settings) 00228 { 00229 settings = targetQueue.PopTop (); 00230 } 00231 00235 void FinishRendering () 00236 { 00237 CS_ASSERT(rendering); 00238 rendering = false; 00239 00240 oneTimeTargets.DeleteAll (); 00241 targetQueue.DeleteAll (); 00242 } 00243 private: 00244 typedef DependentTargetManager<RenderTree, TargetHandler> DependentTargetManagerType; 00245 00246 /* FIXME: better handle multiple views per target 00247 'flags' per subtexture seems odd */ 00248 struct RenderTargetInfo 00249 { 00250 struct ViewInfo 00251 { 00252 csRef<iView> view; 00253 uint flags; 00254 }; 00255 typedef csHash<ViewInfo, int> ViewsHash; 00256 ViewsHash views; 00257 }; 00258 typedef csHash<RenderTargetInfo, csRef<iTextureHandle> > TargetsHash; 00259 TargetsHash targets; 00260 TargetsHash oneTimeTargets; 00261 TargetsHash alwaysUsedTargets; 00262 00263 class HandledTargetsSet 00264 { 00265 public: 00266 void SetCapacity (size_t n) 00267 { 00268 set.SetCapacity (n); 00269 } 00270 00271 void Empty () 00272 { 00273 set.Empty(); 00274 } 00275 00276 void Insert (size_t index, iTextureHandle* texh) 00277 { 00278 set.Insert (index, texh); 00279 } 00280 00281 bool Find (iTextureHandle* texh, size_t& candidate) const 00282 { 00283 return set.FindSortedKey ( 00284 csArrayCmp<iTextureHandle*, iTextureHandle*> (texh), &candidate) 00285 != csArrayItemNotFound; 00286 } 00287 00288 private: 00289 csArray<iTextureHandle*> set; 00290 }; 00291 00292 // 00293 TargetHandler& targetHandler; 00294 00295 bool rendering; 00296 csArray<iTextureHandle*> forciblyUsedTextures; 00297 00298 // Storage for used SV names 00299 csBitArray names; 00300 // Storage for handled targets 00301 HandledTargetsSet handledTargets; 00302 00303 // Queue of contexts to setup 00304 csFIFO<TargetSettings> targetQueue; 00305 00306 void HandleTexture (iTextureHandle* textureHandle, 00307 CS::ShaderVarStringID svName, 00308 csShaderVariable* sv) 00309 { 00310 iView* localView = 0; 00311 bool handleTarget = false; 00312 00313 // Check any of the explicit targets 00314 RenderTargetInfo* targetInfo; 00315 targetInfo = targets.GetElementPointer (textureHandle); 00316 handleTarget = (targetInfo != 0); 00317 if (!targetInfo) 00318 { 00319 targetInfo = oneTimeTargets.GetElementPointer (textureHandle); 00320 handleTarget |= (targetInfo != 0); 00321 } 00322 00323 // Dispatch upwards 00324 if (!handleTarget && sv) 00325 { 00326 handleTarget = targetHandler.HandleTargetSetup (svName, sv, 00327 textureHandle, localView); 00328 } 00329 00330 if (handleTarget) 00331 { 00332 HandleTarget (textureHandle, targetInfo, localView); 00333 } 00334 } 00335 00336 void HandleTarget (iTextureHandle* textureHandle, 00337 RenderTargetInfo* targetInfo, 00338 iView* localView) 00339 { 00340 size_t insertPos; 00341 if (handledTargets.Find (textureHandle, insertPos)) return; 00342 handledTargets.Insert (insertPos, textureHandle); 00343 00344 if (targetInfo) 00345 { 00346 typename RenderTargetInfo::ViewsHash::GlobalIterator viewsIt ( 00347 targetInfo->views.GetIterator()); 00348 00349 while (viewsIt.HasNext ()) 00350 { 00351 int subtexture; 00352 const typename RenderTargetInfo::ViewInfo& viewInfo ( 00353 viewsIt.Next (subtexture)); 00354 int drawFlags = 0; 00355 if (viewInfo.flags & iRenderManagerTargets::clearScreen) 00356 drawFlags |= CSDRAW_CLEARSCREEN | CSDRAW_CLEARZBUFFER; 00357 HandleView (viewInfo.view, textureHandle, subtexture, drawFlags); 00358 } 00359 } 00360 else 00361 { 00362 HandleView (localView, textureHandle, 0, 0); 00363 } 00364 } 00365 00366 void HandleView (iView* targetView, 00367 iTextureHandle* texh, int subtexture, int drawFlags) 00368 { 00369 if (!targetView) return; 00370 00371 targetView->UpdateClipper (); 00372 00373 // Setup a target info struct 00374 TargetSettings settings; 00375 settings.target = texh; 00376 settings.targetSubTexture = subtexture; 00377 settings.view = targetView; 00378 settings.drawFlags = drawFlags; 00379 00380 targetQueue.Push (settings); 00381 } 00382 00383 struct NewTargetFn 00384 { 00385 NewTargetFn (DependentTargetManagerType& parent, RenderTree& renderTree) 00386 : parent (parent), renderTree (renderTree) 00387 {} 00388 00389 void operator() (CS::ShaderVarStringID name, csShaderVariable* sv) 00390 { 00391 if (sv->GetType() != csShaderVariable::TEXTURE) 00392 return; 00393 00394 iTextureHandle* textureHandle; 00395 sv->GetValue (textureHandle); 00396 00397 parent.HandleTexture (textureHandle, name, sv); 00398 } 00399 00400 DependentTargetManager& parent; 00401 RenderTree& renderTree; 00402 }; 00403 00404 friend struct TargetTraverser; 00405 }; 00406 00407 } // namespace RenderManager 00408 } // namespace CS 00409 00410 #endif // __CS_CSPLUGINCOMMON_RENDERMANAGER_DEPENDENTTARGET_H__
Generated for Crystal Space 2.1 by doxygen 1.6.1
