00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00190 return;
00191
00192
00193 NewTargetFn newTarget (*this, renderTree);
00194 typedef TraverseUsedSVs<RenderTree, NewTargetFn> MeshTraverseType;
00195 MeshTraverseType svTraverser
00196 (newTarget, shaderManager->GetSVNameStringset ()->GetSize (),
00197 iShader::svuTextures);
00198
00199
00200 Implementation::OnceOperationBlockRef<typename RenderTree::ContextNode*>
00201 opBlock (contextsTested);
00202
00203 Implementation::NoOperationBlock<typename RenderTree::MeshNode*> meshNoBlock;
00204
00205
00206 Implementation::MeshContextTraverser<
00207 typename RenderTree::ContextNode,
00208 MeshTraverseType,
00209 Implementation::NoOperationBlock<typename RenderTree::MeshNode*>
00210 > contextTraverse (svTraverser, meshNoBlock);
00211
00212
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
00247
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
00299 csBitArray names;
00300
00301 HandledTargetsSet handledTargets;
00302
00303
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
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
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
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 }
00408 }
00409
00410 #endif // __CS_CSPLUGINCOMMON_RENDERMANAGER_DEPENDENTTARGET_H__