/***********************************************************************
    created:    Tue Feb 17 2009
    author:     Paul D Turner, Henri I Hyyryläinen
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/Ogre/Renderer.h"
#include "CEGUI/RendererModules/Ogre/GeometryBuffer.h"
#include "CEGUI/RendererModules/Ogre/Texture.h"
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
#include "CEGUI/RendererModules/Ogre/RenderTarget2.h"
#else
#include "CEGUI/RendererModules/Ogre/TextureTarget.h"
#include "CEGUI/RendererModules/Ogre/WindowTarget.h"
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
#include "CEGUI/GUIContext.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/System.h"
#include "CEGUI/RendererModules/Ogre/ResourceProvider.h"
#include "CEGUI/RendererModules/Ogre/ImageCodec.h"
#include "CEGUI/RenderMaterial.h"
#include "CEGUI/Logger.h"
#include "CEGUI/BitmapImage.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/Window.h"

#include <OgreRoot.h>
#include <OgreRenderSystem.h>
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
#include <OgreWindow.h>
#include <OgreTextureGpuManager.h>
#else
#include <OgreRenderWindow.h>
#include <OgreTextureManager.h>
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
#include <OgreHighLevelGpuProgramManager.h>
#include <OgreHighLevelGpuProgram.h>
#include <OgreGpuProgramManager.h>
#include <OgreGpuProgramParams.h>
#include <OgreFrameListener.h>
#include <OgreViewport.h>
#include <OgreCamera.h>
#include <OgreHardwareVertexBuffer.h>

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
#include "CEGUI/WindowManager.h"

#include <Compositor/OgreCompositorManager2.h>
#include <Compositor/OgreCompositorCommon.h>
#include <Compositor/OgreCompositorWorkspaceDef.h>
#include <Compositor/OgreCompositorWorkspace.h>
#include <Compositor/OgreCompositorNodeDef.h>
#include <Compositor/Pass/PassClear/OgreCompositorPassClear.h>
#include <Compositor/Pass/PassScene/OgreCompositorPassScene.h>
#include <Compositor/OgreCompositorWorkspaceListener.h>
#endif // CEGUI_USE_OGRE_COMPOSITOR2

#ifdef CEGUI_USE_OGRE_HLMS
#include <OgreHlmsManager.h>
#include <OgreHlmsDatablock.h>
#include <OgrePsoCacheHelper.h>
#endif

#ifndef CEGUI_USE_OGRE_HLMS
#if OGRE_VERSION >= 0x10800
#   include "OgreRTShaderConfig.h"
#endif
#endif

#if OGRE_VERSION >= 0x020100
#include <CommandBuffer/OgreCbDrawCall.h>
#endif

#include "CEGUI/RendererModules/Ogre/ShaderWrapper.h"

#include "Shaders.inl"

#include "glm/gtc/type_ptr.hpp"

#include <unordered_map>
#include <sstream>

#define VERTEXBUFFER_POOL_SIZE_STARTCLEAR           60

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
// The new method will be used
// Internal Ogre::CompositorWorkspaceListener. This is how the renderer gets notified
// of workspaces that need rendering
class OgreGUIRenderQueueListener : public Ogre::CompositorWorkspaceListener
{
public:
    OgreGUIRenderQueueListener(OgreRenderer* owner, OgreRenderer_impl* owner_impl);
    virtual ~OgreGUIRenderQueueListener(){}    
    virtual void passPreExecute(Ogre::CompositorPass *pass);

private:
    OgreRenderer* d_owner;
    OgreRenderer_impl* d_owner_impl;
};

#else // Use the old method
// Internal Ogre::FrameListener based class.  This is how we noew hook into the
// rendering process (as opposed to render queues previously)
static class OgreGUIFrameListener : public Ogre::FrameListener
{
public:
    OgreGUIFrameListener();

    void setCEGUIRenderEnabled(bool enabled);
    bool isCEGUIRenderEnabled() const;

    bool frameRenderingQueued(const Ogre::FrameEvent& evt);

private:
    bool d_enabled;

} S_frameListener;

#endif // CEGUI_USE_OGRE_COMPOSITOR2
//----------------------------------------------------------------------------//
//! container type used to hold TextureTargets we create.
typedef std::vector<TextureTarget*> TextureTargetList;
//! container type used to hold GeometryBuffers we create.
typedef std::vector<OgreGeometryBuffer*> GeometryBufferList;
//! container type used to hold Textures we create.
typedef std::unordered_map<String, OgreTexture*> TextureMap;

#ifdef CEGUI_USE_OGRE_HLMS
typedef Ogre::v1::HardwareVertexBufferSharedPtr UsedOgreHWBuffer;
#else
typedef Ogre::HardwareVertexBufferSharedPtr UsedOgreHWBuffer;
#endif //CEGUI_USE_OGRE_HLMS

//----------------------------------------------------------------------------//
// Implementation data for the OgreRenderer
struct OgreRenderer_impl
{
    OgreRenderer_impl() :
        //! TODO: Currently there is no way to do this easily using Ogre
        d_maxTextureSize(2048),
        d_ogreRoot(Ogre::Root::getSingletonPtr()),
#if !defined(CEGUI_USE_OGRE_COMPOSITOR2)
        d_previousVP(0),
#else
        d_frameListener(0),
        d_dummyScene(0),
        d_dummyCamera(0),
        d_workspace(0),
        d_RenderingMode(OgreRenderer::RenderingModes::RenderAllCeguiGUIContexts),
#endif
#ifdef CEGUI_USE_OGRE_HLMS
        //d_renderTarget(nullptr),
        d_hlmsMacroblock(nullptr),
        d_hlmsBlendblock(nullptr),
        d_hlmsSamplerblock(nullptr),
#endif
        d_activeBlendMode(BlendMode::Invalid),
        d_makeFrameControlCalls(true),
        d_useGLSL(false),
        d_useGLSLES(false),
        d_useHLSL(false),
        d_useGLSLCore(false),
        d_texturedShaderWrapper(0),
        d_colouredShaderWrapper(0)
        {}


    //! String holding the renderer identification text.
    static String d_rendererID;
    //! What the renderer considers to be the current display size.
    Sizef d_displaySize;
    //! The default RenderTarget
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    OgreRenderTextureTarget* d_defaultTarget;
#else
    OgreWindowTarget* d_defaultTarget;
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
    //! Container used to track texture targets.
    TextureTargetList d_textureTargets;
    //! Container used to track geometry buffers.
    GeometryBufferList d_geometryBuffers;
    //! Container used to track textures.
    TextureMap d_textures;
    //! What the renderer thinks the max texture size is.
    unsigned int d_maxTextureSize;
    //! OGRE root object ptr
    Ogre::Root* d_ogreRoot;
    //! Pointer to the render system for Ogre.
    Ogre::RenderSystem* d_renderSystem;
#if !defined(CEGUI_USE_OGRE_COMPOSITOR2)
    //! Pointer to the previous viewport set in render system.
    Ogre::Viewport* d_previousVP;
    //! Previous projection matrix set on render system.
    Ogre::Matrix4 d_previousProjMatrix;
#else

    //! This is used to get notifications when our scene is rendered
    //! no longer static because it requires a pointer to this
    OgreGUIRenderQueueListener* d_frameListener;

    //! Used to render at the correct time
    Ogre::SceneManager* d_dummyScene;
    //! This might not be needed, but it's here
    Ogre::Camera* d_dummyCamera;

    Ogre::CompositorWorkspace* d_workspace;

    //! Makes all scene names unique
    static int s_createdSceneNumber;

    //! Allows the initialization to remain the same by automatically
    //! initializing the Compositor if it isn't already
    static bool s_compositorResourcesInitialized;

#endif

#ifdef CEGUI_USE_OGRE_HLMS
    //! OGRE render target
    //Ogre::RenderTarget* d_renderTarget;
    //! HLMS block used to set macro parameters
    const Ogre::HlmsMacroblock* d_hlmsMacroblock;
    //! HLMS block used to set blending parameters
    const Ogre::HlmsBlendblock* d_hlmsBlendblock;
    //! HLMS block used to set sampling parameters
    const Ogre::HlmsSamplerblock* d_hlmsSamplerblock;

    //! HLMS cache used to store pso
    Ogre::SharedPtr<Ogre::PsoCacheHelper> d_hlmsCache;
#endif

    //! What we think is the current blend mode to use
    BlendMode d_activeBlendMode;
    //! Whether _beginFrame and _endFrame will be called.
    bool d_makeFrameControlCalls;
    //! Whether shaders are glsl or hlsl
    bool d_useGLSL;
    //! Whether shaders are glsles
    bool d_useGLSLES;
    //! Whether shaders are hlsl
    bool d_useHLSL;
    //! Whether we use the ARB glsl shaders or the OpenGL 3.2 Core shader profile (140 core)
    bool d_useGLSLCore;

#ifdef CEGUI_USE_OGRE_HLMS
    //! Vector containing vertex buffers that can be reused
    std::vector<Ogre::v1::HardwareVertexBufferSharedPtr> d_vbPool;
#else
    //! Vector containing vertex buffers that can be reused
    std::vector<Ogre::HardwareVertexBufferSharedPtr> d_vbPool;
#endif //CEGUI_USE_OGRE_HLMS

    OgreShaderWrapper* d_texturedShaderWrapper;
    OgreShaderWrapper* d_colouredShaderWrapper;

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    OgreRenderer::RenderingModes d_RenderingMode;
    std::vector<CEGUI::GUIContext*> d_ManualRenderingEveryFrame;
    std::vector<CEGUI::GUIContext*> d_ManualRenderingOnce;
    CEGUI::GUIContext* mGUIContextToRenderManually; //If set, only this GUIContext is rendered, used by void OgreRenderer::renderGuiContext(CEGUI::GUIContext* guiContext)
#endif
};

//----------------------------------------------------------------------------//
String OgreRenderer_impl::d_rendererID(
"CEGUI::OgreRenderer - OGRE based 3rd generation renderer module"
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
" with Ogre::Compositor2 enabled"
#endif // CEGUI_USE_OGRE_COMPOSITOR2
".");

#if defined(CEGUI_USE_OGRE_COMPOSITOR2)
int OgreRenderer_impl::s_createdSceneNumber = 0;
bool OgreRenderer_impl::s_compositorResourcesInitialized = false;
#endif

//----------------------------------------------------------------------------//
void OgreRenderer::configureCeguiWindowForRTT(CEGUI::Window* window, const std::string& ogreTextureName, float textureWidth, float textureHeight)
{
    // We create a CEGUI Texture using the renderer you use:
    CEGUI::Texture* texture;
    if(isTextureDefined(ogreTextureName + "_CEGUI"))
        texture = &getTexture(ogreTextureName + "_CEGUI");
    else
        texture = &createTexture(ogreTextureName + "_CEGUI");

    // Now we need to cast it to the CEGUI::Texture superclass which matches your Renderer. This can be CEGUI::OgreTexture or CEGUI::OpenGLTexture, depending on the renderer you use in your application
    CEGUI::OgreTexture& rendererTexture = static_cast<CEGUI::OgreTexture&>(*texture);

    // Now we can set the appropriate Ogre::Texture for our CEGUI Texture
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    Ogre::TextureGpu* ogreTexture = Ogre::Root::getSingleton().getRenderSystem()->getTextureGpuManager()->findTextureNoThrow(ogreTextureName);
    if(!ogreTexture)
        throw std::runtime_error("could not find RTT-texture (OgreRenderer::configureCeguiWindowForRTT)");
#else
    Ogre::TexturePtr ogreTexture = Ogre::TextureManager::getSingletonPtr()->getByName(ogreTextureName);
    if(ogreTexture.isNull())
        throw std::runtime_error("could not find RTT-texture (OgreRenderer::configureCeguiWindowForRTT)");
#endif

    rendererTexture.setOgreTexture(ogreTexture, false);

    // We create a BasicImage and set the Texture
    CEGUI::BitmapImage* image;
    if(CEGUI::ImageManager::getSingleton().isDefined(ogreTextureName))
        image = static_cast<CEGUI::BitmapImage*>(&CEGUI::ImageManager::getSingleton().get(ogreTextureName));
    else
        image = static_cast<CEGUI::BitmapImage*>(&CEGUI::ImageManager::getSingleton().create("BitmapImage", ogreTextureName));

    image->setTexture(&rendererTexture);

    //Flipping is necessary due to differences between renderers regarding top or bottom being the origin
    CEGUI::Rectf imageArea = CEGUI::Rectf(0.0f, 0.0f, textureWidth, textureHeight);
    image->setImageArea(imageArea);
    image->setAutoScaled(CEGUI::AutoScaledMode::Disabled);

    window->setProperty("Image", ogreTextureName);
}
//----------------------------------------------------------------------------//
OgreRenderer& OgreRenderer::bootstrapSystem(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        throw InvalidRequestException(
        "CEGUI::System object is already initialised.");

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    createOgreCompositorResources();
#endif

    OgreRenderer& renderer = create();
    OgreResourceProvider& rp = createOgreResourceProvider();
    OgreImageCodec& ic = createOgreImageCodec();
    System::create(renderer, &rp, static_cast<XMLParser*>(0), &ic);

    return renderer;
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
OgreRenderer& OgreRenderer::bootstrapSystem(Ogre::Window* target,
                                            const int abi)
#else
OgreRenderer& OgreRenderer::bootstrapSystem(Ogre::RenderTarget& target,
                                            const int abi)
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        throw InvalidRequestException(
            "CEGUI::System object is already initialised.");

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    createOgreCompositorResources();
#endif

    OgreRenderer& renderer = OgreRenderer::create(target);
    OgreResourceProvider& rp = createOgreResourceProvider();
    OgreImageCodec& ic = createOgreImageCodec();
    System::create(renderer, &rp, static_cast<XMLParser*>(0), &ic);

    return renderer;
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroySystem()
{
    System* sys;
    if (!(sys = System::getSingletonPtr()))
        throw InvalidRequestException(
            "CEGUI::System object is not created or was already destroyed.");

    OgreRenderer* renderer = static_cast<OgreRenderer*>(sys->getRenderer());
    OgreResourceProvider* rp =
        static_cast<OgreResourceProvider*>(sys->getResourceProvider());

    OgreImageCodec* ic = &static_cast<OgreImageCodec&>(sys->getImageCodec());

    System::destroy();
    destroyOgreImageCodec(*ic);
    destroyOgreResourceProvider(*rp);
    destroy(*renderer);
}

//----------------------------------------------------------------------------//
OgreRenderer& OgreRenderer::create(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *new OgreRenderer();
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
OgreRenderer& OgreRenderer::create(Ogre::Window* target,
                                   const int abi)
#else
OgreRenderer& OgreRenderer::create(Ogre::RenderTarget& target,
                                   const int abi)
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *new OgreRenderer(target);
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroy(OgreRenderer& renderer)
{
    delete &renderer;
}

//----------------------------------------------------------------------------//
OgreResourceProvider& OgreRenderer::createOgreResourceProvider()
{
    return *new OgreResourceProvider();
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
OgreRenderer& OgreRenderer::registerWindow(OgreRenderer& /*main_window*/,
    Ogre::Window* new_window)
#else
OgreRenderer& OgreRenderer::registerWindow(OgreRenderer& /*main_window*/,
    Ogre::RenderTarget &new_window)
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    // Link the second renderer to the first for them to share some resources

    return *new OgreRenderer(new_window);
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
void OgreRenderer::createOgreCompositorResources()
{
    // Create all the definitions for the workspaces and nodes

    Ogre::CompositorManager2* manager = Ogre::Root::getSingleton().
        getCompositorManager2();

    // We want this to fail if it isn't initialized
    if (!manager)
        throw RendererException(
        "Ogre CompositorManager2 is not initialized, "
        "you must call Ogre::Root::initialiseCompositor() after "
        "creating at least one window.");

    Ogre::CompositorWorkspaceDef* templatedworkspace =
        manager->addWorkspaceDefinition("CEGUI_workspace");

    // Create a node for rendering on top of everything
    Ogre::CompositorNodeDef* rendernode =
        manager->addNodeDefinition("CEGUIRenderNode");

    // Use the render target passed from the workspace for rendering on top of
    // everything
    rendernode->addTextureSourceName("renderwindow", 0,
        Ogre::TextureDefinitionBase::TEXTURE_INPUT);

    rendernode->setNumTargetPass(1);

    // Pass for it
    Ogre::CompositorTargetDef* targetpasses =
        rendernode->addTargetPass("renderwindow");
    targetpasses->setNumPasses(2);

    Ogre::CompositorPassClearDef* clearpass =
        static_cast<Ogre::CompositorPassClearDef*>(targetpasses->
            addPass(Ogre::PASS_CLEAR));

    // Only clear depth and stencil since we are rendering on top
    // of an existing image
    #ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    clearpass->setBuffersToClear(Ogre::RenderPassDescriptor::Depth | Ogre::RenderPassDescriptor::Stencil);
    #else
    clearpass->mClearBufferFlags = Ogre::FBT_DEPTH | Ogre::FBT_STENCIL;
    #endif // CEGUI_USE_OGRE_TEXTURE_GPU

    // Now the render scene pass during which the render queue listener
    // should render the GUI
    Ogre::CompositorPassSceneDef* scenepass =
        static_cast<Ogre::CompositorPassSceneDef*>(targetpasses->
            addPass(Ogre::PASS_SCENE));
#ifdef CEGUI_USE_OGRE_HLMS
    (void)scenepass;

    // Connect the main render target to the node
    templatedworkspace->connectExternal(0, "CEGUIRenderNode", 0);

#else
    // Just render the overlay group since it is the only one used
    scenepass->mFirstRQ = Ogre::RENDER_QUEUE_OVERLAY;
    scenepass->mLastRQ = Ogre::RENDER_QUEUE_OVERLAY+1;

    // Connect the main render target to the node
    templatedworkspace->connectOutput("CEGUIRenderNode", 0);
#endif //CEGUI_USE_OGRE_HLMS

    // Resources now created
    OgreRenderer_impl::s_compositorResourcesInitialized = true;

}
#endif

//----------------------------------------------------------------------------//
void OgreRenderer::destroyOgreResourceProvider(OgreResourceProvider& rp)
{
    delete &rp;
}

//----------------------------------------------------------------------------//
OgreImageCodec& OgreRenderer::createOgreImageCodec()
{
    return *new OgreImageCodec();
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyOgreImageCodec(OgreImageCodec& ic)
{
    delete &ic;
}

//----------------------------------------------------------------------------//
//! Conversion function from Ogre to glm
glm::mat4 OgreRenderer::ogreToGlmMatrix(const Ogre::Matrix4& matrix)
{
    return glm::mat4(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
                     matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
                     matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
                     matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
}

//----------------------------------------------------------------------------//
//! Conversion function from glm to Ogre
Ogre::Matrix4 OgreRenderer::glmToOgreMatrix(const glm::mat4& matrix)
{
    return Ogre::Matrix4(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
                         matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
                         matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
                         matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
}

//----------------------------------------------------------------------------//
void OgreRenderer::setRenderingEnabled(const bool enabled)
{
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    d_pimpl->d_RenderingMode = enabled ? OgreRenderer::RenderingModes::RenderAllCeguiGUIContexts : OgreRenderer::RenderingModes::Disabled;
    d_pimpl->d_workspace->setEnabled(enabled);
#else
    S_frameListener.setCEGUIRenderEnabled(enabled);
#endif // CEGUI_USE_OGRE_COMPOSITOR2
}

//----------------------------------------------------------------------------//
bool OgreRenderer::isRenderingEnabled() const
{
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    return (d_pimpl->d_RenderingMode != OgreRenderer::RenderingModes::Disabled);
#else
    return S_frameListener.isCEGUIRenderEnabled();
#endif // CEGUI_USE_OGRE_COMPOSITOR2
}

//----------------------------------------------------------------------------//
RenderTarget& OgreRenderer::getDefaultRenderTarget()
{
    return *d_pimpl->d_defaultTarget;
}

//----------------------------------------------------------------------------//
TextureTarget* OgreRenderer::createTextureTarget(bool addStencilBuffer)
{
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    TextureTarget* tt = new OgreRenderTextureTarget(*this, d_pimpl->d_renderSystem, NULL, addStencilBuffer);
#else
    TextureTarget* tt = new OgreTextureTarget(*this, *d_pimpl->d_renderSystem, addStencilBuffer);
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
    d_pimpl->d_textureTargets.push_back(tt);
    return tt;
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyTextureTarget(TextureTarget* target)
{
    TextureTargetList::iterator i = std::find(d_pimpl->d_textureTargets.begin(),
                                              d_pimpl->d_textureTargets.end(),
                                              target);

    if (d_pimpl->d_textureTargets.end() != i)
    {
        d_pimpl->d_textureTargets.erase(i);
        delete target;
    }
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyAllTextureTargets()
{
    while (!d_pimpl->d_textureTargets.empty())
        destroyTextureTarget(*d_pimpl->d_textureTargets.begin());
}

//----------------------------------------------------------------------------//
Texture& OgreRenderer::createTexture(const String& name)
{
    return createTexture(name, true);
}

Texture& OgreRenderer::createTexture(const String& name, bool notNullTexture)
{
    throwIfNameExists(name);

    OgreTexture* t = new OgreTexture(name, notNullTexture);
    d_pimpl->d_textures[name] = t;

    logTextureCreation(name);

    return *t;
}

//----------------------------------------------------------------------------//
Texture& OgreRenderer::createTexture(const String& name, const String& filename,
                                     const String& resourceGroup)
{
    throwIfNameExists(name);

    OgreTexture* t = new OgreTexture(name, filename, resourceGroup);
    d_pimpl->d_textures[name] = t;

    logTextureCreation(name);

    return *t;
}

//----------------------------------------------------------------------------//
Texture& OgreRenderer::createTexture(const String& name, const Sizef& size)
{
    throwIfNameExists(name);

    OgreTexture* t = new OgreTexture(name, size);
    d_pimpl->d_textures[name] = t;

    logTextureCreation(name);

    return *t;
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
Texture& OgreRenderer::createTexture(const String& name, Ogre::TextureGpu* tex,
                                     bool take_ownership)
#else
Texture& OgreRenderer::createTexture(const String& name, Ogre::TexturePtr& tex,
                                     bool take_ownership)
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    throwIfNameExists(name);

    OgreTexture* t = new OgreTexture(name, tex, take_ownership);
    d_pimpl->d_textures[name] = t;

    logTextureCreation(name);

    return *t;
}

//----------------------------------------------------------------------------//
void OgreRenderer::throwIfNameExists(const String& name) const
{
    if (d_pimpl->d_textures.find(name) != d_pimpl->d_textures.end())
        throw AlreadyExistsException(
            "[OgreRenderer] Texture already exists: " + name);
}

//----------------------------------------------------------------------------//
void OgreRenderer::logTextureCreation(const String& name)
{
    Logger* logger = Logger::getSingletonPtr();
    if (logger)
        logger->logEvent("[OgreRenderer] Created texture: " + name);
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyTexture(Texture& texture)
{
    destroyTexture(texture.getName());
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyTexture(const String& name)
{
    TextureMap::iterator i = d_pimpl->d_textures.find(name);

    if (d_pimpl->d_textures.end() != i)
    {
        logTextureDestruction(name);
        delete i->second;
        d_pimpl->d_textures.erase(i);
    }
}

//----------------------------------------------------------------------------//
void OgreRenderer::logTextureDestruction(const String& name)
{
    Logger* logger = Logger::getSingletonPtr();
    if (logger)
        logger->logEvent("[OgreRenderer] Destroyed texture: " + name);
}

//----------------------------------------------------------------------------//
void OgreRenderer::destroyAllTextures()
{
    while (!d_pimpl->d_textures.empty())
        destroyTexture(d_pimpl->d_textures.begin()->first);
}

//----------------------------------------------------------------------------//
Texture& OgreRenderer::getTexture(const String& name) const
{
    TextureMap::const_iterator i = d_pimpl->d_textures.find(name);

    if (i == d_pimpl->d_textures.end())
        throw UnknownObjectException("Texture does not exist: " + name);

    return *i->second;
}

//----------------------------------------------------------------------------//
bool OgreRenderer::isTextureDefined(const String& name) const
{
    return d_pimpl->d_textures.find(name) != d_pimpl->d_textures.end();
}

//----------------------------------------------------------------------------//
void OgreRenderer::beginRendering()
{
    #if !defined(CEGUI_USE_OGRE_COMPOSITOR2)
        if ( !d_pimpl->d_previousVP )
        {
            d_pimpl->d_previousVP = d_pimpl->d_renderSystem->_getViewport();
            if ( d_pimpl->d_previousVP && d_pimpl->d_previousVP->getCamera() )
                d_pimpl->d_previousProjMatrix =
                    d_pimpl->d_previousVP->getCamera()->getProjectionMatrixRS();
        }
    #endif

    if (d_pimpl->d_makeFrameControlCalls)
        d_pimpl->d_renderSystem->_beginFrame();
}

//----------------------------------------------------------------------------//
void OgreRenderer::endRendering()
{
    if (d_pimpl->d_makeFrameControlCalls)
        d_pimpl->d_renderSystem->_endFrame();

    #if !defined(CEGUI_USE_OGRE_COMPOSITOR2)
        if ( d_pimpl->d_previousVP )
        {
            d_pimpl->d_renderSystem->_setViewport(d_pimpl->d_previousVP);

            if ( d_pimpl->d_previousVP->getCamera() )
            {
                d_pimpl->d_renderSystem->_setProjectionMatrix(
                    d_pimpl->d_previousProjMatrix);
                d_pimpl->d_renderSystem->_setViewMatrix(
                    d_pimpl->d_previousVP->getCamera()->getViewMatrix());
            }
            d_pimpl->d_previousVP = 0;
            d_pimpl->d_previousProjMatrix = Ogre::Matrix4::IDENTITY;
        }
    #endif
}

//----------------------------------------------------------------------------//
const Sizef& OgreRenderer::getDisplaySize() const
{
    return d_pimpl->d_displaySize;
}
//----------------------------------------------------------------------------//
unsigned int OgreRenderer::getMaxTextureSize() const
{
    return d_pimpl->d_maxTextureSize;
}

//----------------------------------------------------------------------------//
const String& OgreRenderer::getIdentifierString() const
{
    return d_pimpl->d_rendererID;
}

//----------------------------------------------------------------------------//
OgreRenderer::OgreRenderer() :
    d_pimpl(new OgreRenderer_impl())
{
    checkOgreInitialised();

    // get auto created window
    #ifndef CEGUI_USE_OGRE_TEXTURE_GPU
    Ogre::RenderWindow* rwnd = d_pimpl->d_ogreRoot->getAutoCreatedWindow();
    #else
    Ogre::Window* rwnd = d_pimpl->d_ogreRoot->getAutoCreatedWindow();
    #endif // CEGUI_USE_OGRE_TEXTURE_GPU

    if (!rwnd)
        throw RendererException(
            "Ogre was not initialised to automatically create a window, you "
            "should therefore be explicitly specifying a Ogre::RenderTarget in "
            "the OgreRenderer::create function.");

    #ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    constructor_impl(rwnd);
    #else
    constructor_impl(*rwnd);
    #endif // CEGUI_USE_OGRE_TEXTURE_GPU
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
OgreRenderer::OgreRenderer(Ogre::Window* target) :
    d_pimpl(new OgreRenderer_impl())
#else
OgreRenderer::OgreRenderer(Ogre::RenderTarget& target) :
    d_pimpl(new OgreRenderer_impl())
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    checkOgreInitialised();

    constructor_impl(target);
}

//----------------------------------------------------------------------------//
OgreRenderer::~OgreRenderer()
{
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    // Remove the listener and then delete the scene
    #ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    d_pimpl->d_workspace->removeListener(d_pimpl->d_frameListener);
    #else
    d_pimpl->d_workspace->setListener(0);
    #endif

    d_pimpl->d_ogreRoot->destroySceneManager(d_pimpl->d_dummyScene);

    d_pimpl->d_dummyScene = 0;
    d_pimpl->d_dummyCamera = 0;

    // Remove the workspace so the contents aren't rendered anymore
    d_pimpl->d_ogreRoot->getCompositorManager2()->removeWorkspace(
        d_pimpl->d_workspace);

    d_pimpl->d_workspace = 0;

#else
    d_pimpl->d_ogreRoot->removeFrameListener(&S_frameListener);
#endif // CEGUI_USE_OGRE_COMPOSITOR2

    cleanupShaders();

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
    delete d_pimpl->d_frameListener;
#endif

    delete d_pimpl->d_defaultTarget;

    destroyAllGeometryBuffers();
    destroyAllTextureTargets();
    destroyAllTextures();
    clearVertexBufferPool();

    delete d_pimpl;
    d_pimpl = NULL;
}

//----------------------------------------------------------------------------//
void OgreRenderer::checkOgreInitialised()
{
    if (!d_pimpl->d_ogreRoot)
        throw RendererException("The Ogre::Root object has not been "
            "created. You must initialise Ogre first!");

    if (!d_pimpl->d_ogreRoot->isInitialised())
        throw RendererException("Ogre has not been initialised. You must "
            "initialise Ogre first!");
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
void OgreRenderer::constructor_impl(Ogre::Window* target)
#else
void OgreRenderer::constructor_impl(Ogre::RenderTarget& target)
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
{
    d_pimpl->d_renderSystem = d_pimpl->d_ogreRoot->getRenderSystem();

    // set size and create default target & rendering root (surface) that uses it
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    d_pimpl->d_displaySize.d_width  = static_cast<float>(target->getWidth());
    d_pimpl->d_displaySize.d_height = static_cast<float>(target->getHeight());
    d_pimpl->d_defaultTarget = new OgreRenderTextureTarget(
        *this, d_pimpl->d_renderSystem, target->getTexture(),
        false, false, false
    );
#else
    d_pimpl->d_displaySize.d_width  = static_cast<float>(target.getWidth());
    d_pimpl->d_displaySize.d_height = static_cast<float>(target.getHeight());
    d_pimpl->d_defaultTarget =
        new OgreWindowTarget(*this, *d_pimpl->d_renderSystem, target);
#endif // CEGUI_USE_OGRE_TEXTURE_GPU


    // Checking if OpenGL > 3.2 supported
    if (d_pimpl->d_renderSystem->getName().find("OpenGL 3+") != Ogre::String::npos)
    {
        d_pimpl->d_useGLSLCore = true;
    }

#ifndef CEGUI_USE_OGRE_HLMS
#if OGRE_VERSION >= 0x10800
    #ifndef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
        throw RendererException("RT Shader System not available. However CEGUI relies on shaders for rendering. ");
    #endif
#endif
#endif //CEGUI_USE_OGRE_HLMS

    // hook into the rendering process
#ifdef CEGUI_USE_OGRE_COMPOSITOR2

    // Some automatic bootstrapping
    if (!OgreRenderer_impl::s_compositorResourcesInitialized)
    {
        createOgreCompositorResources();
    }

    // Create the dummy scene and camera
    std::stringstream scene_name;
    scene_name << "CEGUI_forWindow_" <<
        OgreRenderer_impl::s_createdSceneNumber++;

    d_pimpl->d_dummyScene = d_pimpl->d_ogreRoot->createSceneManager(
        Ogre::ST_INTERIOR, 1,
        #ifndef CEGUI_USE_OGRE_TEXTURE_GPU
        Ogre::INSTANCING_CULLING_SINGLETHREAD,
        #endif
        scene_name.str());

    // Unused camera for the scene
    d_pimpl->d_dummyCamera = d_pimpl->d_dummyScene->createCamera(
        "CEGUI_dummy_camera");

    // We will get notified when the workspace is drawn
    d_pimpl->d_frameListener = new OgreGUIRenderQueueListener(this, d_pimpl);

    // Create the workspace for rendering
    Ogre::CompositorManager2* manager = d_pimpl->d_ogreRoot->
        getCompositorManager2();

    // The -1 should guarantee this to be rendered last on top of everything
    d_pimpl->d_workspace = manager->addWorkspace(d_pimpl->d_dummyScene,
        #ifdef CEGUI_USE_OGRE_TEXTURE_GPU
        target->getTexture(),
        #else
        &target,
        #endif
        d_pimpl->d_dummyCamera, "CEGUI_workspace", true, -1
    );

    #ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    d_pimpl->d_workspace->addListener(d_pimpl->d_frameListener);
    #else
    d_pimpl->d_workspace->setListener(d_pimpl->d_frameListener);
    #endif

#else
    d_pimpl->d_ogreRoot->addFrameListener(&S_frameListener);
#endif // CEGUI_USE_OGRE_COMPOSITOR2

    initialiseShaders();
}

//----------------------------------------------------------------------------//
void OgreRenderer::initialiseShaders()
{
#ifdef CEGUI_USE_OGRE_HLMS
    Ogre::HlmsManager* hlmsManager = d_pimpl->d_ogreRoot->getHlmsManager();

    // Macro block
    Ogre::HlmsMacroblock macroblock;
    macroblock.mDepthCheck = false;
    macroblock.mDepthWrite = false;
    macroblock.mDepthBiasConstant = 0;
    macroblock.mDepthBiasSlopeScale = 0;
    macroblock.mCullMode = Ogre::CULL_NONE;
    macroblock.mPolygonMode = Ogre::PM_SOLID;
    macroblock.mScissorTestEnabled = true;
    d_pimpl->d_hlmsMacroblock = hlmsManager->getMacroblock(macroblock);

    // Sampler block
    Ogre::HlmsSamplerblock samplerblock;
    samplerblock.mMinFilter = Ogre::FO_LINEAR;
    samplerblock.mMagFilter = Ogre::FO_LINEAR;
    samplerblock.mMipFilter = Ogre::FO_POINT;
    samplerblock.mU = Ogre::TAM_CLAMP;
    samplerblock.mV = Ogre::TAM_CLAMP;
    samplerblock.mW = Ogre::TAM_CLAMP;
    samplerblock.mCompareFunction = Ogre::NUM_COMPARE_FUNCTIONS;
    d_pimpl->d_hlmsSamplerblock = hlmsManager->getSamplerblock(samplerblock);

    // PSO
    d_pimpl->d_hlmsCache = Ogre::SharedPtr<Ogre::PsoCacheHelper>(
        new Ogre::PsoCacheHelper(d_pimpl->d_renderSystem));

#endif

    Ogre::HighLevelGpuProgramPtr texture_vs;
    Ogre::HighLevelGpuProgramPtr texture_ps;

    Ogre::HighLevelGpuProgramPtr colour_vs;
    Ogre::HighLevelGpuProgramPtr colour_ps;

    d_pimpl->d_useGLSL = Ogre::HighLevelGpuProgramManager::getSingleton().
        isLanguageSupported("glsl");
    d_pimpl->d_useGLSLES = Ogre::HighLevelGpuProgramManager::getSingleton().
        isLanguageSupported("glsles");
    d_pimpl->d_useHLSL = Ogre::HighLevelGpuProgramManager::getSingleton().
        isLanguageSupported("hlsl");

    Ogre::String shaderLanguage;

    if (d_pimpl->d_useGLSL)
    {
        shaderLanguage = "glsl";
    }
    else if (d_pimpl->d_useGLSLES)
    {
        shaderLanguage = "glsles";
    }
    else if (d_pimpl->d_useHLSL)
    {
        shaderLanguage = "hlsl";
    }
    else {
        throw RendererException("Underlying Ogre render system does not support available "
            "shader languages which should be one of glsl, glsles or hlsl "
            "which are required for supporting custom shaders in this CEGUI version");
    }

    // Create vertex shaders
    texture_vs = Ogre::HighLevelGpuProgramManager::getSingleton().
        createProgram("__cegui_internal_texture_vs__",
               Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
               shaderLanguage, Ogre::GPT_VERTEX_PROGRAM);

    colour_vs = Ogre::HighLevelGpuProgramManager::getSingleton().
        createProgram("__cegui_internal_colour_vs__",
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
        shaderLanguage, Ogre::GPT_VERTEX_PROGRAM);

    // Create pixel shaders
    texture_ps = Ogre::HighLevelGpuProgramManager::getSingleton().
        createProgram("__cegui_internal_texture_ps__",
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
        shaderLanguage, Ogre::GPT_FRAGMENT_PROGRAM);

    colour_ps = Ogre::HighLevelGpuProgramManager::getSingleton().
        createProgram("__cegui_internal_colour_ps__",
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
        shaderLanguage, Ogre::GPT_FRAGMENT_PROGRAM);

    // We always enter through the main function
    texture_vs->setParameter("entry_point", "main");
    texture_ps->setParameter("entry_point", "main");
    colour_vs->setParameter("entry_point", "main");
    colour_ps->setParameter("entry_point", "main");

    // If we use GLSL
    if (d_pimpl->d_useGLSL)
    {
        // We check if we want to use a GLSL core shader, which is required for the Ogre OpenGL 3+ Renderer
        if (d_pimpl->d_useGLSLCore)
        {
            texture_vs->setParameter("target", "glsl");
            texture_vs->setSource(VertexShaderTextured_GLSL);

            colour_vs->setParameter("target", "glsl");
            colour_vs->setSource(VertexShaderColoured_GLSL);

            texture_ps->setParameter("target", "glsl");
            texture_ps->setSource(PixelShaderTextured_GLSL);

            colour_ps->setParameter("target", "glsl");
            colour_ps->setSource(PixelShaderColoured_GLSL);
        }
        else // else we use regular GLSL shader, as in the normal Ogre OpenGL Renderer
        {
            texture_vs->setParameter("target", "arbvp1");
            texture_vs->setSource(VertexShaderTextured_GLSL_Compat);

            colour_vs->setParameter("target", "arbvp1");
            colour_vs->setSource(VertexShaderColoured_GLSL_Compat);

            texture_ps->setParameter("target", "arbfp1");
            texture_ps->setSource(PixelShaderTextured_GLSL_Compat);

            colour_ps->setParameter("target", "arbfp1");
            colour_ps->setSource(PixelShaderColoured_GLSL_Compat);
        }
    }
    else if (d_pimpl->d_useGLSLES)
    {
        texture_vs->setParameter("target", "glsles");
        texture_vs->setSource(VertexShaderTextured_GLSLES1);

        colour_vs->setParameter("target", "glsles");
        colour_vs->setSource(VertexShaderColoured_GLSLES1);

        texture_ps->setParameter("target", "glsles");
        texture_ps->setSource(PixelShaderTextured_GLSLES1);

        colour_ps->setParameter("target", "glsles");
        colour_ps->setSource(PixelShaderColoured_GLSLES1);
    }
    else // else we use a hlsl shader with an available syntax code
    {
        if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("vs_5_0"))
        {
            texture_vs->setParameter("target", "vs_5_0");
            texture_vs->setSource(VertexShaderTextured_HLSL);

            colour_vs->setParameter("target", "vs_5_0");
            colour_vs->setSource(VertexShaderColoured_HLSL);
        }
        else if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0"))
        {
            texture_vs->setParameter("target", "vs_4_0");
            texture_vs->setSource(VertexShaderTextured_HLSL);

            colour_vs->setParameter("target", "vs_4_0");
            colour_vs->setSource(VertexShaderColoured_HLSL);
        }
        else if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("vs_2_0"))
        {
            texture_vs->setParameter("target", "vs_2_0");
            texture_vs->setSource(VertexShaderTextured_HLSL);

            colour_vs->setParameter("target", "vs_2_0");
            colour_vs->setSource(VertexShaderColoured_HLSL);
        }
        else// If no shader was compatible
        {
            throw RendererException(
                "OgreRenderer::initialiseShaders: No supported syntax - "
                "unable to compile for vs_5_0, vs_4_0 or vs_2_0");
        }

        if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_5_0"))
        {
            texture_ps->setParameter("target", "ps_5_0");
            texture_ps->setSource(PixelShaderTextured_PS5_HLSL);

            colour_ps->setParameter("target", "ps_5_0");
            colour_ps->setSource(PixelShaderColoured_PS5_HLSL);
        }
        else if (Ogre::GpuProgramManager::getSingletonPtr()->isSyntaxSupported("ps_4_0"))
        {
            texture_ps->setParameter("target", "ps_4_0");
            texture_ps->setSource(PixelShaderTextured_PS5_HLSL);

            colour_ps->setParameter("target", "ps_4_0");
            colour_ps->setSource(PixelShaderColoured_PS5_HLSL);
        }
        else if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0"))
        {
            texture_ps->setParameter("target", "ps_2_0");
            texture_ps->setSource(PixelShaderTextured_HLSL);

            colour_ps->setParameter("target", "ps_2_0");
            colour_ps->setSource(PixelShaderColoured_HLSL);
        }
        else
        {
            throw RendererException(
                "OgreRenderer::initialiseShaders: No supported syntax - "
                "unable to compile for ps_5_0, ps_4_0 or ps_2_0");
        }

    }

    // Load all the shaders after setting the source code
    texture_vs->load();
    texture_ps->load();
    colour_vs->load();
    colour_ps->load();

    d_pimpl->d_texturedShaderWrapper = new OgreShaderWrapper(*this,
        *d_pimpl->d_renderSystem, texture_vs, texture_ps);

    d_pimpl->d_colouredShaderWrapper = new OgreShaderWrapper(*this,
        *d_pimpl->d_renderSystem, colour_vs, colour_ps);
}

void OgreRenderer::cleanupShaders()
{
    delete d_pimpl->d_texturedShaderWrapper;
    delete d_pimpl->d_colouredShaderWrapper;

#ifdef CEGUI_USE_OGRE_HLMS

    Ogre::HlmsManager* hlmsManager = d_pimpl->d_ogreRoot->getHlmsManager();

    d_pimpl->d_hlmsCache.setNull();

    if (d_pimpl->d_hlmsBlendblock != nullptr)
        hlmsManager->destroyBlendblock(d_pimpl->d_hlmsBlendblock);
    if (d_pimpl->d_hlmsMacroblock != nullptr)
        hlmsManager->destroyMacroblock(d_pimpl->d_hlmsMacroblock);
    if (d_pimpl->d_hlmsSamplerblock != nullptr)
        hlmsManager->destroySamplerblock(d_pimpl->d_hlmsSamplerblock);



#endif //CEGUI_USE_OGRE_HLMS
}

//----------------------------------------------------------------------------//
void OgreRenderer::setDisplaySize(const Sizef& sz)
{
    if (sz != d_pimpl->d_displaySize)
    {
        d_pimpl->d_displaySize = sz;

        // FIXME: This is probably not the right thing to do in all cases.
        Rectf area(d_pimpl->d_defaultTarget->getArea());
        area.setSize(sz);
        d_pimpl->d_defaultTarget->setArea(area);
    }

}

//----------------------------------------------------------------------------//
void OgreRenderer::setupRenderingBlendMode(const BlendMode mode,
                                           bool force)
{
#ifdef CEGUI_USE_OGRE_HLMS
    // Enable force if no blend block has been created
    if (!d_pimpl->d_hlmsBlendblock)
        force = true;

#endif //CEGUI_USE_OGRE_HLMS

    // do nothing if mode appears current (and is not forced)
    if ((d_pimpl->d_activeBlendMode == mode) && !force)
        return;

    d_pimpl->d_activeBlendMode = mode;

#ifdef CEGUI_USE_OGRE_HLMS

    Ogre::HlmsManager* hlmsManager = d_pimpl->d_ogreRoot->getHlmsManager();

    // Blend block
    Ogre::HlmsBlendblock blendblock;
    blendblock.mAlphaToCoverageEnabled = false;
    if (d_pimpl->d_activeBlendMode == BlendMode::RttPremultiplied)
    {
        blendblock.mSourceBlendFactor = Ogre::SBF_SOURCE_ALPHA;
        blendblock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
    }
    else
    {
        blendblock.mSeparateBlend = true;
        blendblock.mSourceBlendFactor = Ogre::SBF_SOURCE_ALPHA;
        blendblock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
        blendblock.mSourceBlendFactorAlpha = Ogre::SBF_ONE_MINUS_DEST_ALPHA;
        blendblock.mDestBlendFactorAlpha = Ogre::SBF_ONE;
    }
    d_pimpl->d_hlmsBlendblock = hlmsManager->getBlendblock(blendblock);


#else
    using namespace Ogre;

    if (d_pimpl->d_activeBlendMode == BlendMode::RttPremultiplied)
        d_pimpl->d_renderSystem->_setSceneBlending(SBF_ONE,
            SBF_ONE_MINUS_SOURCE_ALPHA);
    else
        d_pimpl->d_renderSystem->
            _setSeparateSceneBlending(SBF_SOURCE_ALPHA,
                SBF_ONE_MINUS_SOURCE_ALPHA,
                SBF_ONE_MINUS_DEST_ALPHA,
                SBF_ONE);

#endif //CEGUI_USE_OGRE_HLMS
}

#ifdef CEGUI_USE_OGRE_HLMS
void OgreRenderer::bindPSO(const Ogre::v1::RenderOperation render_operation)
{
    // Blendmode must be set before
    assert(d_pimpl->d_hlmsBlendblock);

    d_pimpl->d_hlmsCache->setBlendblock(const_cast<Ogre::HlmsBlendblock*>(
            d_pimpl->d_hlmsBlendblock));
    d_pimpl->d_hlmsCache->setMacroblock(const_cast<Ogre::HlmsMacroblock*>(
            d_pimpl->d_hlmsMacroblock));

	#if OGRE_VERSION >= 0x020100
    //! Needed for DX11 in order for InputLayout to be specified right when we get the PSO.
    Ogre::VertexElement2VecVec elements = render_operation.vertexData->vertexDeclaration->convertToV2();
    d_pimpl->d_hlmsCache->setVertexFormat( elements, render_operation.operationType, false );
	#endif

    // This should have all the rendering settings
    Ogre::HlmsPso* pso = d_pimpl->d_hlmsCache->getPso();

    // Bind it
    d_pimpl->d_renderSystem->_setPipelineStateObject(pso);

	#if OGRE_VERSION >= 0x020100
    const Ogre::v1::CbRenderOp cmd( render_operation );
    d_pimpl->d_renderSystem->_setRenderOperation( &cmd );
	#endif
}

void OgreRenderer::setGPUPrograms(const Ogre::HighLevelGpuProgramPtr &vs,
    const Ogre::HighLevelGpuProgramPtr &ps)
{
    Ogre::GpuProgramPtr vsConverted = vs;
    Ogre::GpuProgramPtr psConverted = ps;

    d_pimpl->d_hlmsCache->setVertexShader(vsConverted);
    d_pimpl->d_hlmsCache->setPixelShader(psConverted);
}

#endif //CEGUI_USE_OGRE_HLMS

//----------------------------------------------------------------------------//
void OgreRenderer::setFrameControlExecutionEnabled(const bool enabled)
{
    d_pimpl->d_makeFrameControlCalls = enabled;

    // default rendering requires _beginFrame and _endFrame calls be made,
    // so if we're disabling those we must also disable default rendering.
    if (!d_pimpl->d_makeFrameControlCalls)
        setRenderingEnabled(false);
}

//----------------------------------------------------------------------------//
bool OgreRenderer::isFrameControlExecutionEnabled() const
{
    return d_pimpl->d_makeFrameControlCalls;
}

//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_colourBlendMode =
{
    Ogre::LBT_COLOUR,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_alphaBlendMode =
{
    Ogre::LBT_ALPHA,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
#ifndef CEGUI_USE_OGRE_HLMS
static const Ogre::TextureUnitState::UVWAddressingMode S_textureAddressMode =
    {
        Ogre::TextureUnitState::TAM_CLAMP,
        Ogre::TextureUnitState::TAM_CLAMP,
        Ogre::TextureUnitState::TAM_CLAMP
    };
#endif //CEGUI_USE_OGRE_HLMS

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
void OgreRenderer::initialiseRenderStateSettings(OgreRenderTextureTarget* target) {
    setViewProjectionMatrix(target->d_matrix);

    if (target->d_texture->getOgreTexture()->requiresTextureFlipping())
    {
        d_viewProjectionMatrix[0][1] = -d_viewProjectionMatrix[0][1];
        d_viewProjectionMatrix[1][1] = -d_viewProjectionMatrix[1][1];
        d_viewProjectionMatrix[2][1] = -d_viewProjectionMatrix[2][1];
        d_viewProjectionMatrix[3][1] = -d_viewProjectionMatrix[3][1];
    }

    d_pimpl->d_hlmsCache->setRenderTarget( target->d_renderPassDescriptor );

    d_activeRenderTarget = target;
}
void OgreRenderer::startWithClippingRegion(const Rectf& clippingRegion) {
    OgreRenderTextureTarget* target = dynamic_cast<OgreRenderTextureTarget*>(d_activeRenderTarget);
    Ogre::TextureGpu* targetTexture = target->d_texture->getOgreTexture();

    int actualWidth = targetTexture->getWidth();
    int actualHeight = targetTexture->getHeight();

    Ogre::Vector4 scissors(
        clippingRegion.left() / actualWidth,
        clippingRegion.top() / actualHeight,
        (clippingRegion.right() - clippingRegion.left()) / actualWidth,
        (clippingRegion.bottom() - clippingRegion.top()) / actualHeight
    );

    target->manageClear();

    d_pimpl->d_renderSystem->beginRenderPassDescriptor(
        target->d_renderPassDescriptor,
        targetTexture,
        0,
        &target->d_viewportSize,
        &scissors,
        1,
        false,
        false
    );
}
void OgreRenderer::startWithoutClippingRegion() {
    OgreRenderTextureTarget* target = dynamic_cast<OgreRenderTextureTarget*>(d_activeRenderTarget);
    Ogre::TextureGpu* targetTexture = target->d_texture->getOgreTexture();

    Ogre::Vector4 scissors(0, 0, 1, 1);
    d_pimpl->d_renderSystem->beginRenderPassDescriptor(
        target->d_renderPassDescriptor,
        targetTexture,
        0,
        &target->d_viewportSize,
        &scissors,
        1,
        false,
        false
    );
}
#else
#ifdef CEGUI_USE_OGRE_HLMS
void OgreRenderer::initialiseRenderStateSettings(Ogre::RenderTarget* target)
#else
void OgreRenderer::initialiseRenderStateSettings()
#endif
{
    using namespace Ogre;

#ifdef CEGUI_USE_OGRE_HLMS
    // The geometry buffer is responsible for binding all our hlms blocks
    // when it is ready to render

    // But we need to prepare the PSO cache to generate PSOs for this render target

    // This is in the Ogre example usage but doesn't seem to be needed.
    // d_pimpl->d_hlmsCache->clearState();
    d_pimpl->d_hlmsCache->setRenderTarget(target);
#else
    // initialise render settings
    d_pimpl->d_renderSystem->setLightingEnabled(false);
    d_pimpl->d_renderSystem->_setDepthBufferParams(false, false);
    d_pimpl->d_renderSystem->_setDepthBias(0, 0);
    d_pimpl->d_renderSystem->_setCullingMode(CULL_NONE);
    d_pimpl->d_renderSystem->_setFog(FOG_NONE);
    d_pimpl->d_renderSystem->_setColourBufferWriteEnabled(true, true, true, true);
    d_pimpl->d_renderSystem->setShadingType(SO_GOURAUD);
    d_pimpl->d_renderSystem->_setPolygonMode(PM_SOLID);
    d_pimpl->d_renderSystem->setScissorTest(false);

    // set alpha blending to known state
    setupRenderingBlendMode(BlendMode::Normal, true);
#endif //CEGUI_USE_OGRE_HLMS
}
#endif // CEGUI_USE_OGRE_TEXTURE_GPU

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
void OgreRenderer::setDefaultRootRenderTarget(Ogre::Window* target)
{
    d_pimpl->d_defaultTarget->setOgreTexture(target->getTexture());
}
#else
void OgreRenderer::setDefaultRootRenderTarget(Ogre::RenderTarget& target)
{
    d_pimpl->d_defaultTarget->setOgreRenderTarget(target);
}
#endif // CEGUI_USE_OGRE_TEXTURE_GPU

#ifdef CEGUI_USE_OGRE_COMPOSITOR2
#ifndef CEGUI_USE_OGRE_TEXTURE_GPU
void OgreRenderer::updateWorkspaceRenderTarget(Ogre::RenderTarget& target)
{
    // There seems to be no way to change the target, so we need to recreate it
    Ogre::CompositorManager2* manager = d_pimpl->d_ogreRoot->
        getCompositorManager2();

    d_pimpl->d_ogreRoot->getCompositorManager2()->removeWorkspace(
        d_pimpl->d_workspace);

    // The -1 should guarantee this to be rendered last on top of everything
    d_pimpl->d_workspace = manager->addWorkspace(d_pimpl->d_dummyScene,
        &target, d_pimpl->d_dummyCamera, "CEGUI_workspace", true, -1);
}
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
#endif // CEGUI_USE_OGRE_COMPOSITOR2

//----------------------------------------------------------------------------//
void OgreRenderer::setViewProjectionMatrix(const glm::mat4& viewProjMatrix)
{
    d_pimpl->d_renderSystem->_setProjectionMatrix( OgreRenderer::glmToOgreMatrix(viewProjMatrix) );

    d_viewProjectionMatrix = viewProjMatrix;

#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    // for Ogre >= 2.2 moved to initialiseRenderStateSettings()
#else
    if (d_pimpl->d_renderSystem->_getViewport()->getTarget()->requiresTextureFlipping())
    {
        d_viewProjectionMatrix[0][1] = -d_viewProjectionMatrix[0][1];
        d_viewProjectionMatrix[1][1] = -d_viewProjectionMatrix[1][1];
        d_viewProjectionMatrix[2][1] = -d_viewProjectionMatrix[2][1];
        d_viewProjectionMatrix[3][1] = -d_viewProjectionMatrix[3][1];
    }
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
}

//----------------------------------------------------------------------------//
void OgreRenderer::bindBlendMode(BlendMode blend)
{
    setupRenderingBlendMode(blend, false);
}

//----------------------------------------------------------------------------//
RefCounted<RenderMaterial> OgreRenderer::createRenderMaterial(
    const DefaultShaderType shaderType) const
{
    if (shaderType == DefaultShaderType::Textured)
    {
        RefCounted<RenderMaterial> render_material(new
            RenderMaterial(d_pimpl->d_texturedShaderWrapper));

        return render_material;
    }
    else if (shaderType == DefaultShaderType::Solid)
    {
        RefCounted<RenderMaterial> render_material(new
            RenderMaterial(d_pimpl->d_colouredShaderWrapper));

        return render_material;
    }
    else
    {
        throw RendererException("A default shader of this type does not exist.");

        return RefCounted<RenderMaterial>();
    }
}

//----------------------------------------------------------------------------//
GeometryBuffer& OgreRenderer::createGeometryBufferColoured(
    CEGUI::RefCounted<RenderMaterial> renderMaterial)
{
    OgreGeometryBuffer* geom_buffer = new OgreGeometryBuffer(*this,
        *d_pimpl->d_renderSystem, renderMaterial);

    geom_buffer->addVertexAttribute(VertexAttributeType::Position0);
    geom_buffer->addVertexAttribute(VertexAttributeType::Colour0);
    geom_buffer->finaliseVertexAttributes(
        OgreGeometryBuffer::MT_COLOURED);

    addGeometryBuffer(*geom_buffer);
    return *geom_buffer;
}

//----------------------------------------------------------------------------//
GeometryBuffer& OgreRenderer::createGeometryBufferTextured(
    CEGUI::RefCounted<RenderMaterial> renderMaterial)
{
    OgreGeometryBuffer* geom_buffer = new OgreGeometryBuffer(*this,
        *d_pimpl->d_renderSystem, renderMaterial);

    geom_buffer->addVertexAttribute(VertexAttributeType::Position0);
    geom_buffer->addVertexAttribute(VertexAttributeType::Colour0);
    geom_buffer->addVertexAttribute(VertexAttributeType::TexCoord0);
    geom_buffer->finaliseVertexAttributes(
        OgreGeometryBuffer::MT_TEXTURED);

    addGeometryBuffer(*geom_buffer);
    return *geom_buffer;
}

//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
Ogre::SceneManager& OgreRenderer::getDummyScene() const{
    return *d_pimpl->d_dummyScene;
}
#endif

//----------------------------------------------------------------------------//
UsedOgreHWBuffer OgreRenderer::getVertexBuffer(size_t
    min_size)
{
    UsedOgreHWBuffer result(0);

    if (d_pimpl->d_vbPool.empty())
        return result;

    size_t best_found = -1;
    size_t best_over = -1;

    // The vector is searched in reverse to find exact matches from the end
    // which will allow popping the last element which is faster then removing
    // the first one

    for (size_t i = d_pimpl->d_vbPool.size(); --i > 0;)
    {
        // It seems that there can be nullptrs in the pool
        UsedOgreHWBuffer current = d_pimpl->d_vbPool[i];

        if (!current.get()){

            d_pimpl->d_vbPool.erase(d_pimpl->d_vbPool.begin()+i);
            continue;
        }

        size_t current_over = current->getNumVertices()-min_size;

        // Perfect match stops searching instantly
        if (current_over == 0)
        {

            best_found = i;
            best_over = 0;
            break;
        }

        if (current_over <= best_over)
        {

            best_over = current_over;
            best_found = i;
        }
    }

    // If the smallest buffer is too large then none is found
    // This will also be true if all buffers are too small
    if (best_over > min_size*1.5f || best_found >= d_pimpl->d_vbPool.size())
    {
        // Clear if there are too many buffers
        int over_size = d_pimpl->d_vbPool.size()-
            VERTEXBUFFER_POOL_SIZE_STARTCLEAR;

        if (over_size > 2)
            cleanLargestVertexBufferPool(over_size);

    } else {

        result = d_pimpl->d_vbPool[best_found];

        d_pimpl->d_vbPool.erase(d_pimpl->d_vbPool.begin()+best_found);

        // We want to avoid using too much memory
        // even if matches are always found
        int over_size = d_pimpl->d_vbPool.size()-
            (VERTEXBUFFER_POOL_SIZE_STARTCLEAR*5);

        if (over_size > 5)
            cleanLargestVertexBufferPool(over_size/2);
    }

    return result;
}

void OgreRenderer::returnVertexBuffer(UsedOgreHWBuffer
    buffer)
{
    //If d_pimpl is null this has been called via the destructor so
    //no need to cache 
    if (d_pimpl)
        d_pimpl->d_vbPool.push_back(buffer);
    else
        buffer.reset();
}

void OgreRenderer::clearVertexBufferPool()
{
    d_pimpl->d_vbPool.clear();
}

bool hardwareBufferSizeLess(const UsedOgreHWBuffer &first,
    const UsedOgreHWBuffer &second)
{
    return first->getNumVertices() < second->getNumVertices();
}

void OgreRenderer::cleanLargestVertexBufferPool(size_t count)
{
    // The easiest way might be to sort the vector and delete the last count
    // elements
    std::sort(d_pimpl->d_vbPool.begin(), d_pimpl->d_vbPool.end(),
        &hardwareBufferSizeLess);

    // Adjust the count if there aren't enough elements to delete to avoid
    // asserting
    if (count >= d_pimpl->d_vbPool.size())
    {

        d_pimpl->d_vbPool.clear();
    }

    for (size_t i = 0; i < count; i++)
    {

        d_pimpl->d_vbPool.pop_back();
    }
}

//----------------------------------------------------------------------------//
void OgreRenderer::initialiseTextureStates()
{
#ifndef CEGUI_USE_OGRE_HLMS
    d_pimpl->d_renderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE);
    d_pimpl->d_renderSystem->_setTextureCoordSet(0, 0);
    d_pimpl->d_renderSystem->_setTextureAddressingMode(0, S_textureAddressMode);
    d_pimpl->d_renderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY);
    d_pimpl->d_renderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE);
    d_pimpl->d_renderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false);
    d_pimpl->d_renderSystem->_setTextureBlendMode(0, S_colourBlendMode);
    d_pimpl->d_renderSystem->_setTextureBlendMode(0, S_alphaBlendMode);

#else
    d_pimpl->d_renderSystem->_setHlmsSamplerblock(0, d_pimpl->d_hlmsSamplerblock);
#endif //CEGUI_USE_OGRE_HLMS

#ifndef CEGUI_USE_OGRE_TEXTURE_GPU
    // This might be a good setting in Ogre 2.1, too
    d_pimpl->d_renderSystem->_disableTextureUnitsFrom(1);
#endif // CEGUI_USE_OGRE_TEXTURE_GPU
}

//----------------------------------------------------------------------------//
bool OgreRenderer::usesOpenGL()
{
    return d_pimpl->d_renderSystem->getName().find("OpenGL") != Ogre::String::npos;
}

//----------------------------------------------------------------------------//
bool OgreRenderer::usesDirect3D()
{
    return d_pimpl->d_renderSystem->getName().find("Direct3D") != Ogre::String::npos;
}

//----------------------------------------------------------------------------//
bool OgreRenderer::isTexCoordSystemFlipped() const
{
    return false;
}
//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
OgreRenderer::RenderingModes OgreRenderer::getRenderingMode() const
{
    return d_pimpl->d_RenderingMode;
}
//----------------------------------------------------------------------------//
void OgreRenderer::setRenderingMode(OgreRenderer::RenderingModes renderingMode)
{
    d_pimpl->d_RenderingMode = renderingMode;
    d_pimpl->d_workspace->setEnabled(renderingMode != OgreRenderer::RenderingModes::Disabled);
}
//----------------------------------------------------------------------------//
void OgreRenderer::renderGuiContext(CEGUI::GUIContext* guiContext)
{
    //render given guiContext, probalby to render a Cegui-RTT used on an Ogre::Material or Ogre::HLMS
    if(!guiContext || d_pimpl->d_RenderingMode != RenderingModes::ConfigureManual)
        return;

    //configure the RenderQueueListener:
    d_pimpl->mGUIContextToRenderManually = guiContext;	//configure to render just that one guiContext

    //Manual Render workspace:
    d_pimpl->d_dummyScene->updateSceneGraph();
    d_pimpl->d_workspace->_beginUpdate(true);
    d_pimpl->d_workspace->_update();
    d_pimpl->d_workspace->_endUpdate(true);
#ifdef CEGUI_USE_OGRE_TEXTURE_GPU
    Ogre::vector<Ogre::TextureGpu*>::type swappedTargets;
#else
    Ogre::vector<Ogre::RenderTarget*>::type swappedTargets;
#endif
    d_pimpl->d_workspace->_swapFinalTarget(swappedTargets);
    d_pimpl->d_dummyScene->clearFrameData();

    d_pimpl->mGUIContextToRenderManually = 0;
}
//----------------------------------------------------------------------------//
void OgreRenderer::addGuiContextToRenderEveryFrame(CEGUI::GUIContext* guiContext)
{
    if(!guiContext || hasGuiContextToRenderEveryFrame(guiContext))
        return;	//nothing to do 

    d_pimpl->d_ManualRenderingEveryFrame.push_back(guiContext);
}
//----------------------------------------------------------------------------//
void OgreRenderer::removeGuiContextToRenderEveryFrame(CEGUI::GUIContext* guiContext)
{
    if(!guiContext)
        return;

    std::vector<CEGUI::GUIContext*>::iterator iter = std::find(d_pimpl->d_ManualRenderingEveryFrame.begin(), d_pimpl->d_ManualRenderingEveryFrame.end(), guiContext);
    if(iter != d_pimpl->d_ManualRenderingEveryFrame.end())
        d_pimpl->d_ManualRenderingEveryFrame.erase(iter);
}
//----------------------------------------------------------------------------//
bool OgreRenderer::hasGuiContextToRenderEveryFrame(CEGUI::GUIContext* guiContext) const
{
    return (std::find(d_pimpl->d_ManualRenderingEveryFrame.begin(), d_pimpl->d_ManualRenderingEveryFrame.end(), guiContext) != d_pimpl->d_ManualRenderingEveryFrame.end());
}
//----------------------------------------------------------------------------//
void OgreRenderer::addGuiContextToRenderQueuedOnce(CEGUI::GUIContext* guiContext)
{
    if(!guiContext)
        return;

    //allow no duplicates, as rendering twice per frame does not help anyone
    if(std::find(d_pimpl->d_ManualRenderingOnce.begin(), d_pimpl->d_ManualRenderingOnce.end(), guiContext) != d_pimpl->d_ManualRenderingOnce.end())
        return;

    d_pimpl->d_ManualRenderingOnce.push_back(guiContext);
}
#endif
//----------------------------------------------------------------------------//
#ifdef CEGUI_USE_OGRE_COMPOSITOR2
OgreGUIRenderQueueListener::OgreGUIRenderQueueListener(OgreRenderer* owner, OgreRenderer_impl* owner_impl) :
    d_owner(owner),
    d_owner_impl(owner_impl)
{
}
//----------------------------------------------------------------------------//
void OgreGUIRenderQueueListener::passPreExecute(Ogre::CompositorPass *pass)
{
    if(pass->getType() == Ogre::PASS_SCENE)
    {
        if(d_owner_impl->d_RenderingMode == OgreRenderer::RenderingModes::ConfigureManual && d_owner_impl->mGUIContextToRenderManually)
        {
            //render manually only the one GUIContext that is set
            d_owner->beginRendering();
            d_owner_impl->mGUIContextToRenderManually->draw();
            d_owner->endRendering();
            // do final destruction on dead-pool windows
            WindowManager::getSingleton().cleanDeadPool();
        }
        else if(d_owner_impl->d_RenderingMode == OgreRenderer::RenderingModes::ConfigureManual)
        {
            if(d_owner_impl->d_ManualRenderingEveryFrame.size() > 0 || d_owner_impl->d_ManualRenderingOnce.size() > 0)
            {
                //render what is configured when running automatically
                d_owner->beginRendering();
                for(std::vector<CEGUI::GUIContext*>::const_iterator iter = d_owner_impl->d_ManualRenderingEveryFrame.begin(); iter != d_owner_impl->d_ManualRenderingEveryFrame.end(); ++iter)
                    (*iter)->draw();
                for(std::vector<CEGUI::GUIContext*>::const_iterator iter = d_owner_impl->d_ManualRenderingOnce.begin(); iter != d_owner_impl->d_ManualRenderingOnce.end(); ++iter)
                    (*iter)->draw();
                d_owner->endRendering();
                // do final destruction on dead-pool windows
                WindowManager::getSingleton().cleanDeadPool();
            }
            d_owner_impl->d_ManualRenderingOnce.clear();
        }
        else if(d_owner->getRenderingMode() == OgreRenderer::RenderingModes::RenderAllCeguiGUIContexts)
        {
            // We should only render contexts that are on this render target
            System::getSingleton().renderAllGUIContextsOnTarget(d_owner);
        }
    }
}
//----------------------------------------------------------------------------//
#else
OgreGUIFrameListener::OgreGUIFrameListener() :
    d_enabled(true)
{
}
//----------------------------------------------------------------------------//
void OgreGUIFrameListener::setCEGUIRenderEnabled(bool enabled)
{
    d_enabled = enabled;
}
//----------------------------------------------------------------------------//
bool OgreGUIFrameListener::isCEGUIRenderEnabled() const
{
    return d_enabled;
}
//----------------------------------------------------------------------------//
bool OgreGUIFrameListener::frameRenderingQueued(const Ogre::FrameEvent&)
{
    if (d_enabled){
    }
    return true;
}
#endif // CEGUI_USE_OGRE_COMPOSITOR2
} // End of  CEGUI namespace section
