CrystalSpace

Public API Reference

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.0 by doxygen 1.7.6.1