/** * \file render_target_manager.cpp * \brief CRenderTargetManager * \date 2014-07-30 21:30GMT * \author Jan Boon (Kaetemi) * CRenderTargetManager */ /* * Copyright (C) 2014 by authors * * This file is part of NL3D. * NL3D is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * NL3D is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with NL3D. If not, see * <http://www.gnu.org/licenses/>. */ #include <nel/misc/types_nl.h> #include <nel/3d/render_target_manager.h> // STL includes #include <sstream> // NeL includes // #include <nel/misc/debug.h> #include <nel/3d/u_camera.h> #include <nel/3d/u_driver.h> #include <nel/3d/material.h> #include <nel/3d/texture_bloom.h> #include <nel/3d/texture_user.h> #include <nel/3d/driver_user.h> #include <nel/3d/u_texture.h> // Project includes using namespace std; // using namespace NLMISC; namespace NL3D { struct CRenderTargetDescInt { public: uint Width; uint Height; NL3D::CTextureUser *TextureUser; NLMISC::CSmartPtr<NL3D::ITexture> TextureInterface; bool InUse; bool Used; }; CRenderTargetManager::CRenderTargetManager() : m_Driver(NULL) { } CRenderTargetManager::~CRenderTargetManager() { // Call twice to reset counters and cleanup cleanup(); cleanup(); } NL3D::CTextureUser *CRenderTargetManager::getRenderTarget(uint width, uint height) { // Find or create a render target, short loop so no real optimization for (std::vector<CRenderTargetDescInt *>::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it) { CRenderTargetDescInt *desc = *it; if (!desc->InUse && desc->Width == width && desc->Height == height) { desc->InUse = true; desc->Used = true; return desc->TextureUser; } } nldebug("3D: Create new render target (%u x %u)", width, height); NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver(); CRenderTargetDescInt *desc = new CRenderTargetDescInt(); desc->TextureInterface = new CTextureBloom(); // LOL desc->TextureInterface->setRenderTarget(true); desc->TextureInterface->setReleasable(false); desc->TextureInterface->resize(width, height); desc->TextureInterface->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff); desc->TextureInterface->setWrapS(ITexture::Clamp); desc->TextureInterface->setWrapT(ITexture::Clamp); drvInternal->setupTexture(*desc->TextureInterface); desc->TextureUser = new CTextureUser(desc->TextureInterface); nlassert(!drvInternal->isTextureRectangle(desc->TextureInterface)); // Not allowed, we only support NPOT for render targets now. desc->Width = width; desc->Height = height; desc->Used = true; desc->InUse = true; m_RenderTargets.push_back(desc); return desc->TextureUser; } void CRenderTargetManager::recycleRenderTarget(NL3D::CTextureUser *renderTarget) { for (std::vector<CRenderTargetDescInt *>::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it) { CRenderTargetDescInt *desc = *it; if (desc->TextureUser == renderTarget) { desc->InUse = false; return; } } nlerror("3D: Render target not found"); } void CRenderTargetManager::cleanup() { for (sint i = 0; i < (sint)m_RenderTargets.size(); ++i) { CRenderTargetDescInt *desc = m_RenderTargets[i]; nlassert(!desc->InUse); // Assert for debugging, to not allow textures being carried over between frames. Optional assert if (!desc->InUse) { if (!desc->Used) { // No longer in use nldebug("3D: Release render target (%u x %u)", desc->Width, desc->Height); delete desc->TextureUser; desc->TextureUser = NULL; desc->TextureInterface = NULL; // CSmartPtr m_RenderTargets.erase(m_RenderTargets.begin() + i); --i; } else { // Flag for next round desc->Used = false; } } } } } /* namespace NL3D */ /* end of file */