//-----------------------------------------------------------------------
void CompositorChain::setCompositorEnabled(size_t position, bool state)
{
	CompositorInstance* inst = getCompositor(position);
	if (!state && inst->getEnabled())
	{
		// If we're disabling a 'middle' compositor in a chain, we have to be
		// careful about textures which might have been shared by non-adjacent
		// instances which have now become adjacent. 
		CompositorInstance* nextInstance = getNextInstance(inst, true);
		if (nextInstance)
		{
			CompositionTechnique::TargetPassIterator tpit = nextInstance->getTechnique()->getTargetPassIterator();
			while(tpit.hasMoreElements())
			{
				CompositionTargetPass* tp = tpit.getNext();
				if (tp->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
				{
					if (nextInstance->getTechnique()->getTextureDefinition(tp->getOutputName())->pooled)
					{
						// recreate
						nextInstance->freeResources(false, true);
						nextInstance->createResources(false);
					}
				}

			}
		}

	}
    inst->setEnabled(state);
}
//-----------------------------------------------------------------------
void CompositorInstance::_compileTargetOperations(CompiledState &compiledState)
{
    /// Collect targets of previous state
	if(mPreviousInstance)
	    mPreviousInstance->_compileTargetOperations(compiledState);
    /// Texture targets
    CompositionTechnique::TargetPassIterator it = mTechnique->getTargetPassIterator();
    while(it.hasMoreElements())
    {
        CompositionTargetPass *target = it.getNext();
        
        TargetOperation ts(getTargetForTex(target->getOutputName()));
        /// Set "only initial" flag, visibilityMask and lodBias according to CompositionTargetPass.
        ts.onlyInitial = target->getOnlyInitial();
        ts.visibilityMask = target->getVisibilityMask();
        ts.lodBias = target->getLodBias();
        /// Check for input mode previous
        if(target->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
        {
            /// Collect target state for previous compositor
            /// The TargetOperation for the final target is collected seperately as it is merged
            /// with later operations
            mPreviousInstance->_compileOutputOperation(ts);
        }
        /// Collect passes of our own target
        collectPasses(ts, target);
        compiledState.push_back(ts);
    }
}
//---------------------------------------------------------------------
bool CompositorManager::isInputPreviousTarget(CompositorInstance* inst, const Ogre::String& localName)
{
    CompositionTechnique::TargetPassIterator tpit = inst->getTechnique()->getTargetPassIterator();
    while(tpit.hasMoreElements())
    {
        CompositionTargetPass* tp = tpit.getNext();
        if (tp->getInputMode() == CompositionTargetPass::IM_PREVIOUS &&
            tp->getOutputName() == localName)
        {
            return true;
        }

    }

    return false;

}
//---------------------------------------------------------------------
bool CompositorManager::isInputPreviousTarget(CompositorInstance* inst, TexturePtr tex)
{
    CompositionTechnique::TargetPassIterator tpit = inst->getTechnique()->getTargetPassIterator();
    while(tpit.hasMoreElements())
    {
        CompositionTargetPass* tp = tpit.getNext();
        if (tp->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
        {
            // Don't have to worry about an MRT, because no MRT can be input previous
            TexturePtr t = inst->getTextureInstance(tp->getOutputName(), 0);
            if (!t.isNull() && t.get() == tex.get())
                return true;
        }

    }

    return false;

}
//-----------------------------------------------------------------------
void CompositorInstance::_compileOutputOperation(TargetOperation &finalState)
{
    /// Final target
    CompositionTargetPass *tpass = mTechnique->getOutputTargetPass();
    
    /// Logical-and together the visibilityMask, and multiply the lodBias
    finalState.visibilityMask &= tpass->getVisibilityMask();
    finalState.lodBias *= tpass->getLodBias();
    
    if(tpass->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
    {
        /// Collect target state for previous compositor
        /// The TargetOperation for the final target is collected seperately as it is merged
        /// with later operations
        mPreviousInstance->_compileOutputOperation(finalState);
    }
    /// Collect passes
    collectPasses(finalState, tpass);
}
//---------------------------------------------------------------------
void CompositorInstance::deriveTextureRenderTargetOptions(
	const String& texname, bool *hwGammaWrite, uint *fsaa)
{
	// search for passes on this texture def that either include a render_scene
	// or use input previous
	bool renderingScene = false;

	CompositionTechnique::TargetPassIterator it = mTechnique->getTargetPassIterator();
	while (it.hasMoreElements())
	{
		CompositionTargetPass* tp = it.getNext();
		if (tp->getOutputName() == texname)
		{
			if (tp->getInputMode() == CompositionTargetPass::IM_PREVIOUS)
			{
				// this may be rendering the scene implicitly
				// Can't check mPreviousInstance against mChain->_getOriginalSceneCompositor()
				// at this time, so check the position
				CompositorChain::InstanceIterator instit = mChain->getCompositors();
				renderingScene = true;
				while(instit.hasMoreElements())
				{
					CompositorInstance* inst = instit.getNext();
					if (inst == this)
						break;
					else if (inst->getEnabled())
					{
						// nope, we have another compositor before us, this will
						// be doing the AA
						renderingScene = false;
					}
				}
				if (renderingScene)
					break;
			}
			else
			{
				// look for a render_scene pass
				CompositionTargetPass::PassIterator pit = tp->getPassIterator();
				while(pit.hasMoreElements())
				{
					CompositionPass* pass = pit.getNext();
					if (pass->getType() == CompositionPass::PT_RENDERSCENE)
					{
						renderingScene = true;
						break;
					}
				}
			}

		}
	}

	if (renderingScene)
	{
		// Ok, inherit settings from target
		RenderTarget* target = mChain->getViewport()->getTarget();
		*hwGammaWrite = target->isHardwareGammaEnabled();
		*fsaa = target->getFSAA();
	}
	else
	{
		*hwGammaWrite = false;
		*fsaa = 0;
	}

}