csplugincommon/rendermanager/dependenttarget.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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__