#include "RenderTargetPool.h" #include "RenderTarget.h" #include "Services.h" #include "Renderer.h" #include #include using namespace std; //list of render targets map RenderTargetPool::mRTPool; IDirect3DDevice9Ptr RenderTargetPool::GDevice; D3DVIEWPORT9 RenderTargetPool::Viewport; RTObject::RTObject() { RefCount = 0; } RTObject::~RTObject() { //rt automatically deleted w/ shared_ptr } /*---------------------------------------------------- * Initialize the rt pool *----------------------------------------------------*/ void RenderTargetPool::Initialize(IDirect3DDevice9Ptr &device, D3DVIEWPORT9& viewport) { GDevice = device; Viewport = viewport; } /*---------------------------------------------------- * Destroy all the render targets *----------------------------------------------------*/ void RenderTargetPool::DestroyRenderTargets() { if(mRTPool.size() == 0) return; mRTPool.clear(); } /*---------------------------------------------------- * Notify render targets of lost device *----------------------------------------------------*/ void RenderTargetPool::OnLostDevice() { static map::iterator iter; for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) { iter->second.RT->OnLostDevice(); } } /*---------------------------------------------------- * Notify render targets of reset device *----------------------------------------------------*/ void RenderTargetPool::OnResetDevice() { static map::iterator iter; for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) { iter->second.RT->OnResetDevice(); } } /*---------------------------------------------------- * Retrieve a render target. If the render target * already exists this will update its ref count and * return the already existing render target. If the * render target doesn't exist it will create a new one * and return it. * * @info - the information about the rendertarget to get * specifies: w + h, surface formats * * @return - A valid render target created with info *----------------------------------------------------*/ RenderTargetPtr RenderTargetPool::GetRenderTarget(RenderTargetInfo& info) { //update the reference count static map::iterator iter; for( iter = mRTPool.begin(); iter != mRTPool.end(); ++iter ) { if(iter->first == info) { iter->second.RefCount++; return iter->second.RT; } } //check for support for the render target RendererPtr renderer = boost::static_pointer_cast(Services::GetService(RendererService)); if(GDevice == NULL && !IsFormatSupported(renderer->GetD3D(), info.Format, renderer->GetPresentParams().BackBufferFormat)) { return RenderTargetPtr(); } RTObject rtObject; rtObject.RefCount = 1; rtObject.RT = RenderTargetPtr(new RenderTarget(GDevice, Viewport, (UINT)info.Width, (UINT)info.Height, 1, info.Format)); //insert the info[key] and object[data] pair into the map mRTPool.insert(make_pair(info, rtObject)); return rtObject.RT; } /*---------------------------------------------------- * Retrieve a render target. If the render target * already exists this will update its ref count and * return the already existing render target. If the * render target doesn't exist it will create a new one * and return it. * * @info - the information about the rendertarget to get * specifies: w + h, surface formats * @createNew - [true]will forcibly create a new render * target even if one with the same formats * and dimenstions already already exists. * * @return - A valid render target created with info *----------------------------------------------------*/ RenderTargetPtr RenderTargetPool::GetRenderTarget(RenderTargetInfo &info, bool createNew) { static map::iterator iter; if(createNew && (iter = mRTPool.find(info)) != mRTPool.end()) { info.Modifier = 0; info.Modifier += iter->second.RefCount + iter->first.Modifier; } return GetRenderTarget(info); } /*---------------------------------------------------- * Check for support for a render target * @device - a valid D3D object * @format - the surface format of the render target * @adapterFormat - backbuffer format * * @return - return true if successfull *----------------------------------------------------*/ bool RenderTargetPool::IsFormatSupported(const IDirect3D9Ptr& device, D3DFORMAT format, D3DFORMAT adapterFormat) { HRESULT hr = device->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format); return SUCCEEDED( hr ); }