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 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "OgreStableHeaders.h"
29 #include "OgreCompositor.h"
30 #include "OgreCompositorChain.h"
31 #include "OgreCompositionTechnique.h"
32 #include "OgreCompositorInstance.h"
33 #include "OgreCompositionTargetPass.h"
34 #include "OgreCompositionPass.h"
35 #include "OgreCompositorManager.h"
36 #include "OgreRenderTarget.h"
37 
38 namespace Ogre {
CompositorChain(Viewport * vp)39 CompositorChain::CompositorChain(Viewport *vp):
40     mViewport(vp),
41     mOriginalScene(0),
42     mDirty(true),
43     mAnyCompositorsEnabled(false),
44     mOldLodBias(1.0f)
45 {
46     assert(vp);
47     mOldClearEveryFrameBuffers = vp->getClearBuffers();
48     vp->addListener(this);
49 
50     createOriginalScene();
51     vp->getTarget()->addListener(this);
52 }
53 //-----------------------------------------------------------------------
~CompositorChain()54 CompositorChain::~CompositorChain()
55 {
56     destroyResources();
57 }
58 //-----------------------------------------------------------------------
destroyResources(void)59 void CompositorChain::destroyResources(void)
60 {
61     clearCompiledState();
62 
63     if (mViewport)
64     {
65         mViewport->getTarget()->removeListener(this);
66         mViewport->removeListener(this);
67         removeAllCompositors();
68         destroyOriginalScene();
69 
70         // destory base "original scene" compositor
71         CompositorManager::getSingleton().remove(getCompositorName(), ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
72 
73         mViewport = 0;
74     }
75 }
76 //-----------------------------------------------------------------------
getCompositorName() const77 const String CompositorChain::getCompositorName() const
78 {
79     return StringUtil::format("Ogre/Scene/%zu", (size_t)mViewport);
80 }
81 //-----------------------------------------------------------------------
createOriginalScene()82 void CompositorChain::createOriginalScene()
83 {
84     /// Create "default" compositor
85     /** Compositor that is used to implicitly represent the original
86         render in the chain. This is an identity compositor with only an output pass:
87     compositor Ogre/Scene
88     {
89         technique
90         {
91             target_output
92             {
93                 pass clear
94                 {
95                     /// Clear frame
96                 }
97                 pass render_scene
98                 {
99                     visibility_mask FFFFFFFF
100                     render_queues SKIES_EARLY SKIES_LATE
101                 }
102             }
103         }
104     };
105     */
106 
107     // If two viewports use the same scheme but differ in settings like visibility masks, shadows, etc we don't
108     // want compositors to share their technique.  Otherwise both compositors will have to recompile every time they
109     // render.  Thus we generate a unique compositor per viewport.
110     const String compName = getCompositorName();
111 
112     mOriginalSceneScheme = mViewport->getMaterialScheme();
113     CompositorPtr scene = CompositorManager::getSingleton().getByName(compName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
114     if (!scene)
115     {
116         scene = CompositorManager::getSingleton().create(compName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
117         CompositionTargetPass *tp = scene->createTechnique()->getOutputTargetPass();
118         tp->createPass(CompositionPass::PT_CLEAR);
119 
120         /// Render everything, including skies
121         CompositionPass *pass = tp->createPass(CompositionPass::PT_RENDERSCENE);
122         pass->setFirstRenderQueue(RENDER_QUEUE_BACKGROUND);
123         pass->setLastRenderQueue(RENDER_QUEUE_SKIES_LATE);
124 
125         /// Create base "original scene" compositor
126         scene = static_pointer_cast<Compositor>(CompositorManager::getSingleton().load(compName,
127             ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME));
128     }
129     mOriginalScene = OGRE_NEW CompositorInstance(scene->getSupportedTechnique(), this);
130 }
131 //-----------------------------------------------------------------------
destroyOriginalScene()132 void CompositorChain::destroyOriginalScene()
133 {
134     /// Destroy "original scene" compositor instance
135     if (mOriginalScene)
136     {
137         OGRE_DELETE mOriginalScene;
138         mOriginalScene = 0;
139     }
140 }
141 
142 //-----------------------------------------------------------------------
addCompositor(CompositorPtr filter,size_t addPosition,const String & scheme)143 CompositorInstance* CompositorChain::addCompositor(CompositorPtr filter, size_t addPosition, const String& scheme)
144 {
145 
146 
147     filter->touch();
148     CompositionTechnique *tech = filter->getSupportedTechnique(scheme);
149     if(!tech)
150     {
151         /// Warn user
152         LogManager::getSingleton().logMessage(
153             "CompositorChain: Compositor " + filter->getName() + " has no supported techniques.", LML_CRITICAL
154             );
155         return 0;
156     }
157     CompositorInstance *t = OGRE_NEW CompositorInstance(tech, this);
158 
159     if(addPosition == LAST)
160         addPosition = mInstances.size();
161     else
162         assert(addPosition <= mInstances.size() && "Index out of bounds.");
163     mInstances.insert(mInstances.begin()+addPosition, t);
164 
165     mDirty = true;
166     mAnyCompositorsEnabled = true;
167     return t;
168 }
169 //-----------------------------------------------------------------------
removeCompositor(size_t index)170 void CompositorChain::removeCompositor(size_t index)
171 {
172     if(index == LAST)
173         index = mInstances.size() - 1;
174 
175     assert (index < mInstances.size() && "Index out of bounds.");
176     Instances::iterator i = mInstances.begin() + index;
177     OGRE_DELETE *i;
178     mInstances.erase(i);
179 
180     mDirty = true;
181 }
182 //-----------------------------------------------------------------------
getNumCompositors()183 size_t CompositorChain::getNumCompositors()
184 {
185     return mInstances.size();
186 }
187 //-----------------------------------------------------------------------
removeAllCompositors()188 void CompositorChain::removeAllCompositors()
189 {
190     Instances::iterator i, iend;
191     iend = mInstances.end();
192     for (i = mInstances.begin(); i != iend; ++i)
193     {
194         OGRE_DELETE *i;
195     }
196     mInstances.clear();
197 
198     mDirty = true;
199 }
200 //-----------------------------------------------------------------------
_removeInstance(CompositorInstance * i)201 void CompositorChain::_removeInstance(CompositorInstance *i)
202 {
203     Instances::iterator it = std::find(mInstances.begin(), mInstances.end(), i);
204     assert(it != mInstances.end());
205     if(it != mInstances.end())
206     {
207         mInstances.erase(it);
208         OGRE_DELETE i;
209     }
210 }
211 //-----------------------------------------------------------------------
_queuedOperation(CompositorInstance::RenderSystemOperation * op)212 void CompositorChain::_queuedOperation(CompositorInstance::RenderSystemOperation* op)
213 {
214     mRenderSystemOperations.push_back(op);
215 
216 }
217 //-----------------------------------------------------------------------
getCompositor(size_t index)218 CompositorInstance *CompositorChain::getCompositor(size_t index)
219 {
220     assert (index < mInstances.size() && "Index out of bounds.");
221     return mInstances[index];
222 }
223 //-----------------------------------------------------------------------
getCompositorPosition(const String & name)224 size_t CompositorChain::getCompositorPosition(const String& name)
225 {
226     for (Instances::iterator it = mInstances.begin(); it != mInstances.end(); ++it)
227     {
228         if ((*it)->getCompositor()->getName() == name)
229         {
230             return std::distance(mInstances.begin(), it);
231         }
232     }
233     return NPOS;
234 }
getCompositor(const String & name)235 CompositorInstance *CompositorChain::getCompositor(const String& name)
236 {
237     size_t idx = getCompositorPosition(name);
238     return idx == NPOS ? NULL : mInstances[idx];
239 }
240 //-----------------------------------------------------------------------
getCompositors()241 CompositorChain::InstanceIterator CompositorChain::getCompositors()
242 {
243     return InstanceIterator(mInstances.begin(), mInstances.end());
244 }
245 //-----------------------------------------------------------------------
setCompositorEnabled(size_t position,bool state)246 void CompositorChain::setCompositorEnabled(size_t position, bool state)
247 {
248     CompositorInstance* inst = mInstances[position];
249     if (!state && inst->getEnabled())
250     {
251         // If we're disabling a 'middle' compositor in a chain, we have to be
252         // careful about textures which might have been shared by non-adjacent
253         // instances which have now become adjacent.
254         CompositorInstance* nextInstance = getNextInstance(inst, true);
255         if (nextInstance)
256         {
257             const CompositionTechnique::TargetPasses& tps =
258                 nextInstance->getTechnique()->getTargetPasses();
259             CompositionTechnique::TargetPasses::const_iterator tpit = tps.begin();
260             for(;tpit != tps.end(); ++tpit)
261             {
262                 CompositionTargetPass* tp = *tpit;
263                 if (tp->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
264                 {
265                     if (nextInstance->getTechnique()->getTextureDefinition(tp->getOutputName())->pooled)
266                     {
267                         // recreate
268                         nextInstance->freeResources(false, true);
269                         nextInstance->createResources(false);
270                     }
271                 }
272 
273             }
274         }
275 
276     }
277     inst->setEnabled(state);
278 }
279 //-----------------------------------------------------------------------
preRenderTargetUpdate(const RenderTargetEvent & evt)280 void CompositorChain::preRenderTargetUpdate(const RenderTargetEvent& evt)
281 {
282     /// Compile if state is dirty
283     if(mDirty)
284         _compile();
285 
286     // Do nothing if no compositors enabled
287     if (!mAnyCompositorsEnabled)
288     {
289         return;
290     }
291 
292 
293     /// Update dependent render targets; this is done in the preRenderTarget
294     /// and not the preViewportUpdate for a reason: at this time, the
295     /// target Rendertarget will not yet have been set as current.
296     /// ( RenderSystem::setViewport(...) ) if it would have been, the rendering
297     /// order would be screwed up and problems would arise with copying rendertextures.
298     Camera *cam = mViewport->getCamera();
299     if (cam)
300     {
301         cam->getSceneManager()->_setActiveCompositorChain(this);
302     }
303 
304     /// Iterate over compiled state
305     CompositorInstance::CompiledState::iterator i;
306     for(i=mCompiledState.begin(); i!=mCompiledState.end(); ++i)
307     {
308         /// Skip if this is a target that should only be initialised initially
309         if(i->onlyInitial && i->hasBeenRendered)
310             continue;
311         i->hasBeenRendered = true;
312         /// Setup and render
313         preTargetOperation(*i, i->target->getViewport(0), cam);
314         i->target->update();
315         postTargetOperation(*i, i->target->getViewport(0), cam);
316     }
317 }
318 //-----------------------------------------------------------------------
postRenderTargetUpdate(const RenderTargetEvent & evt)319 void CompositorChain::postRenderTargetUpdate(const RenderTargetEvent& evt)
320 {
321     Camera *cam = mViewport->getCamera();
322     if (cam)
323     {
324         cam->getSceneManager()->_setActiveCompositorChain(0);
325     }
326 }
327 //-----------------------------------------------------------------------
preViewportUpdate(const RenderTargetViewportEvent & evt)328 void CompositorChain::preViewportUpdate(const RenderTargetViewportEvent& evt)
329 {
330     // Only set up if there is at least one compositor enabled, and it's this viewport
331     if(evt.source != mViewport || !mAnyCompositorsEnabled)
332         return;
333 
334     // set original scene details from viewport
335     CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPasses()[0];
336     CompositionTargetPass* passParent = pass->getParent();
337     if (pass->getClearBuffers() != mViewport->getClearBuffers() ||
338         pass->getClearColour() != mViewport->getBackgroundColour() ||
339         pass->getClearDepth() != mViewport->getDepthClear() ||
340         passParent->getVisibilityMask() != mViewport->getVisibilityMask() ||
341         passParent->getMaterialScheme() != mViewport->getMaterialScheme() ||
342         passParent->getShadowsEnabled() != mViewport->getShadowsEnabled())
343     {
344         // recompile if viewport settings are different
345         pass->setClearBuffers(mViewport->getClearBuffers());
346         pass->setClearColour(mViewport->getBackgroundColour());
347         pass->setClearDepth(mViewport->getDepthClear());
348         passParent->setVisibilityMask(mViewport->getVisibilityMask());
349         passParent->setMaterialScheme(mViewport->getMaterialScheme());
350         passParent->setShadowsEnabled(mViewport->getShadowsEnabled());
351         _compile();
352     }
353 
354     Camera *cam = mViewport->getCamera();
355     if (cam)
356     {
357         /// Prepare for output operation
358         preTargetOperation(mOutputOperation, mViewport, cam);
359     }
360 }
361 //-----------------------------------------------------------------------
preTargetOperation(CompositorInstance::TargetOperation & op,Viewport * vp,Camera * cam)362 void CompositorChain::preTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
363 {
364     if (cam)
365     {
366         SceneManager *sm = cam->getSceneManager();
367         /// Set up render target listener
368         mOurListener.setOperation(&op, sm, sm->getDestinationRenderSystem());
369         mOurListener.notifyViewport(vp);
370         /// Register it
371         sm->addRenderQueueListener(&mOurListener);
372         /// Set whether we find visibles
373         mOldFindVisibleObjects = sm->getFindVisibleObjects();
374         sm->setFindVisibleObjects(op.findVisibleObjects);
375         /// Set LOD bias level
376         mOldLodBias = cam->getLodBias();
377         cam->setLodBias(cam->getLodBias() * op.lodBias);
378     }
379 
380     // Set the visibility mask
381     mOldVisibilityMask = vp->getVisibilityMask();
382     vp->setVisibilityMask(op.visibilityMask);
383     /// Set material scheme
384     mOldMaterialScheme = vp->getMaterialScheme();
385     vp->setMaterialScheme(op.materialScheme);
386     /// Set shadows enabled
387     mOldShadowsEnabled = vp->getShadowsEnabled();
388     vp->setShadowsEnabled(op.shadowsEnabled);
389     /// XXX TODO
390     //vp->setClearEveryFrame( true );
391     //vp->setOverlaysEnabled( false );
392     //vp->setBackgroundColour( op.clearColour );
393 }
394 //-----------------------------------------------------------------------
postTargetOperation(CompositorInstance::TargetOperation & op,Viewport * vp,Camera * cam)395 void CompositorChain::postTargetOperation(CompositorInstance::TargetOperation &op, Viewport *vp, Camera *cam)
396 {
397     if (cam)
398     {
399         SceneManager *sm = cam->getSceneManager();
400         /// Unregister our listener
401         sm->removeRenderQueueListener(&mOurListener);
402         /// Restore default scene and camera settings
403         sm->setFindVisibleObjects(mOldFindVisibleObjects);
404         cam->setLodBias(mOldLodBias);
405     }
406 
407     vp->setVisibilityMask(mOldVisibilityMask);
408     vp->setMaterialScheme(mOldMaterialScheme);
409     vp->setShadowsEnabled(mOldShadowsEnabled);
410 }
411 //-----------------------------------------------------------------------
postViewportUpdate(const RenderTargetViewportEvent & evt)412 void CompositorChain::postViewportUpdate(const RenderTargetViewportEvent& evt)
413 {
414     // Only tidy up if there is at least one compositor enabled, and it's this viewport
415     if(evt.source != mViewport || !mAnyCompositorsEnabled)
416         return;
417 
418     Camera *cam = mViewport->getCamera();
419     postTargetOperation(mOutputOperation, mViewport, cam);
420 }
421 //-----------------------------------------------------------------------
viewportCameraChanged(Viewport * viewport)422 void CompositorChain::viewportCameraChanged(Viewport* viewport)
423 {
424     Camera* camera = viewport->getCamera();
425     size_t count = mInstances.size();
426     for (size_t i = 0; i < count; ++i)
427     {
428         mInstances[i]->notifyCameraChanged(camera);
429     }
430 }
431 //-----------------------------------------------------------------------
viewportDimensionsChanged(Viewport * viewport)432 void CompositorChain::viewportDimensionsChanged(Viewport* viewport)
433 {
434     size_t count = mInstances.size();
435     for (size_t i = 0; i < count; ++i)
436     {
437         mInstances[i]->notifyResized();
438     }
439 }
440 //-----------------------------------------------------------------------
viewportDestroyed(Viewport * viewport)441 void CompositorChain::viewportDestroyed(Viewport* viewport)
442 {
443     // this chain is now orphaned. tell compositor manager to delete it.
444     CompositorManager::getSingleton().removeCompositorChain(viewport);
445 }
446 //-----------------------------------------------------------------------
clearCompiledState()447 void CompositorChain::clearCompiledState()
448 {
449     for (RenderSystemOperations::iterator i = mRenderSystemOperations.begin();
450         i != mRenderSystemOperations.end(); ++i)
451     {
452         OGRE_DELETE *i;
453     }
454     mRenderSystemOperations.clear();
455 
456     /// Clear compiled state
457     mCompiledState.clear();
458     mOutputOperation = CompositorInstance::TargetOperation(0);
459 
460 }
461 //-----------------------------------------------------------------------
_compile()462 void CompositorChain::_compile()
463 {
464     // remove original scene if it has the wrong material scheme
465     if( mOriginalSceneScheme != mViewport->getMaterialScheme() )
466     {
467         destroyOriginalScene();
468         createOriginalScene();
469     }
470 
471     clearCompiledState();
472 
473     bool compositorsEnabled = false;
474 
475     // force default scheme so materials for compositor quads will determined correctly
476     MaterialManager& matMgr = MaterialManager::getSingleton();
477     String prevMaterialScheme = matMgr.getActiveScheme();
478     matMgr.setActiveScheme(Root::getSingleton().getRenderSystem()->_getDefaultViewportMaterialScheme());
479 
480     /// Set previous CompositorInstance for each compositor in the list
481     CompositorInstance *lastComposition = mOriginalScene;
482     mOriginalScene->mPreviousInstance = 0;
483     CompositionPass* pass = mOriginalScene->getTechnique()->getOutputTargetPass()->getPasses()[0];
484     pass->setClearBuffers(mViewport->getClearBuffers());
485     pass->setClearColour(mViewport->getBackgroundColour());
486     pass->setClearDepth(mViewport->getDepthClear());
487     for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
488     {
489         if((*i)->getEnabled())
490         {
491             compositorsEnabled = true;
492             (*i)->mPreviousInstance = lastComposition;
493             lastComposition = (*i);
494         }
495     }
496 
497 
498     /// Compile misc targets
499     lastComposition->_compileTargetOperations(mCompiledState);
500 
501     /// Final target viewport (0)
502     mOutputOperation.renderSystemOperations.clear();
503     lastComposition->_compileOutputOperation(mOutputOperation);
504 
505     // Deal with viewport settings
506     if (compositorsEnabled != mAnyCompositorsEnabled)
507     {
508         mAnyCompositorsEnabled = compositorsEnabled;
509         if (mAnyCompositorsEnabled)
510         {
511             // Save old viewport clearing options
512             mOldClearEveryFrameBuffers = mViewport->getClearBuffers();
513             // Don't clear anything every frame since we have our own clear ops
514             mViewport->setClearEveryFrame(false);
515         }
516         else
517         {
518             // Reset clearing options
519             mViewport->setClearEveryFrame(mOldClearEveryFrameBuffers > 0,
520                 mOldClearEveryFrameBuffers);
521         }
522     }
523 
524     // restore material scheme
525     matMgr.setActiveScheme(prevMaterialScheme);
526 
527 
528     mDirty = false;
529 }
530 //-----------------------------------------------------------------------
_markDirty()531 void CompositorChain::_markDirty()
532 {
533     mDirty = true;
534 }
535 //-----------------------------------------------------------------------
getViewport()536 Viewport *CompositorChain::getViewport()
537 {
538     return mViewport;
539 }
540 //---------------------------------------------------------------------
_notifyViewport(Viewport * vp)541 void CompositorChain::_notifyViewport(Viewport* vp)
542 {
543     if (vp != mViewport)
544     {
545         if (mViewport != NULL)
546             mViewport->removeListener(this);
547 
548         if (vp != NULL)
549             vp->addListener(this);
550 
551         if (!vp || !mViewport || vp->getTarget() != mViewport->getTarget())
552         {
553             if(mViewport)
554                 mViewport->getTarget()->removeListener(this);
555 
556             if(vp)
557                 vp->getTarget()->addListener(this);
558         }
559         mOurListener.notifyViewport(vp);
560         mViewport = vp;
561     }
562 }
563 //-----------------------------------------------------------------------
renderQueueStarted(uint8 id,const String & invocation,bool & skipThisQueue)564 void CompositorChain::RQListener::renderQueueStarted(uint8 id,
565     const String& invocation, bool& skipThisQueue)
566 {
567     // Skip when not matching viewport
568     // shadows update is nested within main viewport update
569     if (mSceneManager->getCurrentViewport() != mViewport)
570         return;
571 
572     flushUpTo(id);
573     /// If no one wants to render this queue, skip it
574     /// Don't skip the OVERLAY queue because that's handled separately
575     if(!mOperation->renderQueues.test(id) && id!=RENDER_QUEUE_OVERLAY)
576     {
577         skipThisQueue = true;
578     }
579 }
580 //-----------------------------------------------------------------------
renderQueueEnded(uint8 id,const String & invocation,bool & repeatThisQueue)581 void CompositorChain::RQListener::renderQueueEnded(uint8 id,
582     const String& invocation, bool& repeatThisQueue)
583 {
584 }
585 //-----------------------------------------------------------------------
setOperation(CompositorInstance::TargetOperation * op,SceneManager * sm,RenderSystem * rs)586 void CompositorChain::RQListener::setOperation(CompositorInstance::TargetOperation *op,SceneManager *sm,RenderSystem *rs)
587 {
588     mOperation = op;
589     mSceneManager = sm;
590     mRenderSystem = rs;
591     currentOp = op->renderSystemOperations.begin();
592     lastOp = op->renderSystemOperations.end();
593 }
594 //-----------------------------------------------------------------------
flushUpTo(uint8 id)595 void CompositorChain::RQListener::flushUpTo(uint8 id)
596 {
597     /// Process all RenderSystemOperations up to and including render queue id.
598     /// Including, because the operations for RenderQueueGroup x should be executed
599     /// at the beginning of the RenderQueueGroup render for x.
600     while(currentOp != lastOp && currentOp->first <= id)
601     {
602         currentOp->second->execute(mSceneManager, mRenderSystem);
603         ++currentOp;
604     }
605 }
606 //-----------------------------------------------------------------------
getPreviousInstance(CompositorInstance * curr,bool activeOnly)607 CompositorInstance* CompositorChain::getPreviousInstance(CompositorInstance* curr, bool activeOnly)
608 {
609     bool found = false;
610     for(Instances::reverse_iterator i=mInstances.rbegin(); i!=mInstances.rend(); ++i)
611     {
612         if (found)
613         {
614             if ((*i)->getEnabled() || !activeOnly)
615                 return *i;
616         }
617         else if(*i == curr)
618         {
619             found = true;
620         }
621     }
622 
623     return 0;
624 }
625 //---------------------------------------------------------------------
getNextInstance(CompositorInstance * curr,bool activeOnly)626 CompositorInstance* CompositorChain::getNextInstance(CompositorInstance* curr, bool activeOnly)
627 {
628     bool found = false;
629     for(Instances::iterator i=mInstances.begin(); i!=mInstances.end(); ++i)
630     {
631         if (found)
632         {
633             if ((*i)->getEnabled() || !activeOnly)
634                 return *i;
635         }
636         else if(*i == curr)
637         {
638             found = true;
639         }
640     }
641 
642     return 0;
643 }
644 //---------------------------------------------------------------------
645 }
646 
647