/**************************************************************************** Copyright (c) 2011-2013,WebJet Business Division,CYOU http://www.genesis-3d.com.cn 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 OR COPYRIGHT HOLDERS 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 "stdneb.h" #include "RenderSystem.h" #include "config/RenderDeviceConfig.h" #if RENDERDEVICE_D3D9 #include "d3d9/RenderDeviceD3D9.h" #include "d3d9/PrimitiveGroupD3D9.h" #endif #if RENDERDEVICE_OPENGLES #include "gles/RenderDeviceGLES.h" #endif #if RENDERDEVICE_NULL #include "null/RenderDeviceNull.h" #endif #include "base/PrimitiveGroup.h" #include "RenderMessageProtocol.h" namespace RenderBase { __ImplementClass(RenderSystem, 'REND', Core::RefCounted); __ImplementThreadSingleton(RenderSystem); #if RENDERDEVICE_D3D9 using namespace D3D9; #endif #if RENDERDEVICE_OPENGLES using namespace GLES; #endif #if RENDERDEVICE_NULL using namespace NullDevice; #endif void RenderSystem::Open(int width, int height) { #if RENDERDEVICE_D3D9 m_renderDevice = RenderDeviceD3D9::Create(); m_renderDevice.cast()->SetMainWindowHandle(m_mainHWND); #endif #if RENDERDEVICE_NULL m_renderDevice = RenderDeviceNull::Create(); m_renderDevice.cast()->SetMainWindowHandle(m_mainHWND); #endif #if RENDERDEVICE_OPENGLES m_renderDevice = RenderDeviceGLES::Create(); m_renderDevice.cast()->SetMainWindowHandle(m_mainHWND); #endif m_renderDevice->SetSize(width, height); m_renderDevice->InitDevice(); m_renderDevice->DetectGraphicCardCaps(); if (!m_dummyRenderTargetHandle.IsValid()) { GPtr renderTarget = RenderBase::RenderTarget::Create(); renderTarget->SetDefaultRenderTarget(true); renderTarget->SetClearColor(Math::float4(0.f,0.f,1.f,1.f)); renderTarget->SetClearFlags(RenderBase::RenderTarget::ClearAll); renderTarget->SetWidth(1); renderTarget->SetHeight(1); renderTarget->SetDummy(true); RenderBase::TextureHandle dummytexhandle; m_dummyRenderTargetHandle = CreateRenderTarget(renderTarget,dummytexhandle); } } void RenderSystem::Close() { for ( RenderResourceHandleSet::type::iterator itor = m_renderHandles.begin(); itor != m_renderHandles.end(); ++itor ) { itor->mRO->Release(); } m_renderHandles.clear(); } RenderSystem::RenderSystem() { __ConstructThreadSingleton; m_renderDisplay = RenderDisplay::Create(); } RenderSystem::~RenderSystem() { m_renderDisplay = 0; m_renderDevice = 0; __DestructThreadSingleton; } void RenderSystem::BeginFrame() { m_renderDevice->BeginFrame(); } void RenderSystem::EndFrame() { m_renderDevice->EndFrame(); } bool RenderSystem::IsBeginFrame() const { return m_renderDevice->IsBeginFrame(); } void RenderSystem::Clear() { } PrimitiveGroup* RenderSystem::GetPrimitiveGroup(const PrimitiveHandle& handle) const { if (RenderBase::RenderCommandType::DrawPrimGroup == handle.GetType()) { return static_cast(handle.mRO); } return NULL; } Texture* RenderSystem::GetTexture(const TextureHandle& handle) const { if (RenderBase::RenderCommandType::SetTexture == handle.GetType()) { return static_cast(handle.mRO); } return NULL; } PrimitiveHandle RenderSystem::CreatePrimitiveHandle(const VertexBufferData* vbd, const IndexBufferData* ibd /* = NULL */) { GPtr pg = m_renderDevice->CreatePrimitiveGroup(vbd, ibd); pg->SetRenderCommandType(RenderCommandType::DrawPrimGroup); PrimitiveHandle handle; handle.mRO = pg.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); return handle; } void RenderSystem::ChangePrimitiveHandle(RenderBase::PrimitiveHandle& handle, const RenderBase::VertexBufferData* vbd, const RenderBase::IndexBufferData* ibd /* = NULL */) { n_assert (RenderBase::RenderCommandType::DrawPrimGroup == handle.GetType()) m_renderDevice->ChangePrimitiveGroup(static_cast(handle.mRO), vbd, ibd); } void RenderSystem::UpdateVertexBuffer(PrimitiveHandle& handle, const DataStream& data) { PrimitiveGroup* pg = GetPrimitiveGroup(handle); m_renderDevice->UpdateVertexBuffer(pg->GetVertexBuffer().get(), data); } void RenderSystem::UpdateIndexBuffer(PrimitiveHandle& handle, const DataStream& data) { PrimitiveGroup* pg = GetPrimitiveGroup(handle); m_renderDevice->UpdateIndexBuffer(pg->GetIndexBuffer().get(), data); } GPUProgramHandle RenderSystem::CreateShaderProgram( const GPtr& program ) { const GPtr rcType = m_renderDevice->CreateRenderGPUProgram(program).upcast(); rcType->SetRenderCommandType(RenderCommandType::SetGPUProgram); GPUProgramHandle handle; handle.mRO = rcType.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); return handle; } RenderStateDescHandle RenderSystem::CreateRenderStateObject( const GPtr& rsObject) { n_assert(rsObject.isvalid()) const GPtr rcType = m_renderDevice->CreateRenderState(rsObject).upcast(); rcType->SetRenderCommandType(RenderCommandType::SetRenderState); RenderStateDescHandle handle; handle.mRO = rcType.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); return handle; } RenderTargetHandle RenderSystem::CreateRenderTarget( const GPtr& rt, TextureHandle& texhandle) { n_assert(rt.isvalid()) //generate render target guid GPtr deviceRT = m_renderDevice->CreateRenderTarget(rt); GPtr rcType = deviceRT.upcast(); rcType->SetRenderCommandType(RenderCommandType::SetRenderTarget); RenderTargetHandle handle; handle.mRO = rcType.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); if (!rt->IsDefaultRenderTarget()) { //generate render texture guid GPtr rcType = deviceRT->GetResolveTexture().upcast(); texhandle.mRO = rcType.get(); bool bOK = _AddRenderHandle(texhandle); n_assert(bOK); } return handle; } MultipleRenderTargetHandle RenderSystem::CreateMultipleRenderTarget(const GPtr& mrt, Util::Array< RenderBase::RenderTargetHandle >& handles) { n_assert(mrt.isvalid()) for (IndexT i = 0; i < handles.Size(); ++i) { GPtr rcType( (RenderCommandType*)handles[i].mRO ); GPtr rt = rcType.downcast(); n_assert(rt); mrt->AddRenderTarget(rt); } GPtr deviceMRT = m_renderDevice->CreateMultipleRenderTarget(mrt); GPtr rcType = deviceMRT.upcast(); rcType->SetRenderCommandType(RenderCommandType::SetMultiRenderTarget); MultipleRenderTargetHandle handle; handle.mRO = rcType.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); return handle; } TextureHandle RenderSystem::CreateTexture( const GPtr& tex) { n_assert(tex.isvalid()) GPtr rcType = m_renderDevice->CreateRenderSideTexture(tex).upcast(); rcType->SetRenderCommandType(RenderCommandType::SetTexture); TextureHandle handle; handle.mRO = rcType.get(); bool bOK = _AddRenderHandle(handle); n_assert(bOK); return handle; } void RenderSystem::UpdateTexture(TextureHandle texHandle, RenderBase::Texture::UpdateFunction texUpdateFunc, void* tag) { if (!texHandle.IsValid()) { n_warning("RenderSystem::UpdateTexture():texHandle is invalid!\n"); return; } GPtr rcType( (RenderCommandType*)texHandle.mRO ); GPtr destTex = rcType.downcast(); n_assert(destTex.isvalid()) m_renderDevice->UpdateTexture(texUpdateFunc,destTex, tag); } void RenderSystem::UpdateTexture(TextureHandle texHandle, GPtr texture) { if (!texHandle.IsValid()) { n_warning("RenderSystem::UpdateTexture():texHandle is invalid!\n"); return; } GPtr rcType( (RenderCommandType*)texHandle.mRO ); GPtr destTex = rcType.downcast(); n_assert(destTex.isvalid()) m_renderDevice->UpdateTexture( texture, destTex ); } void RenderSystem::ChangeTexture(RenderBase::TextureHandle texHandle, GPtr texture) { if (!texHandle.IsValid()) { n_warning("RenderSystem::UpdateTexture():texHandle is invalid!\n"); return; } GPtr rcType( (RenderCommandType*)texHandle.mRO ); GPtr destTex = rcType.downcast(); n_assert(destTex.isvalid()) m_renderDevice->ChangeTexture( texture, destTex ); } void RenderSystem::_DrawPrimitive(PrimitiveHandle handle,SizeT startVertice,SizeT endVertice,SizeT startIndice,SizeT endIndice) { n_assert( handle.IsValid() ); n_assert(startVertice >= 0); n_assert(endVertice >= 0); n_assert(startIndice >= 0); n_assert(endIndice >= 0); const PrimitiveGroup* primGroup = static_cast(handle.mRO); n_assert(primGroup); m_renderDevice->SetPrimitiveGroup(primGroup); m_renderDevice->Draw(startVertice, endVertice, startIndice, endIndice); } //-------------------------------------------------------------------------------- void RenderSystem::_DrawPrimitive(PrimitiveHandle handle) { const PrimitiveGroup* primGroup = RenderDevice::_Convert(handle.mRO); m_renderDevice->SetPrimitiveGroup(primGroup); m_renderDevice->Draw(primGroup->GetBaseVertex(), primGroup->GetNumVertices(), primGroup->GetBaseIndex(), primGroup->GetNumIndices()); } //-------------------------------------------------------------------------------- void RenderSystem::_DrawPrimitiveHWInstance(PrimitiveHandle handle) { } //-------------------------------------------------------------------------------- void RenderSystem::_SetRenderTarget(RenderTargetHandle handle,SizeT index,uint clearflag) { if (!handle.IsValid()) { if (0 != index) { m_renderDevice->DisableRenderTarget(index); return; } handle = m_dummyRenderTargetHandle; } GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr rt = rcType.downcast(); n_assert(rt); if (handle != m_dummyRenderTargetHandle) { rt->SetMRTIndex(index); } rt->SetClearFlags(clearflag); m_renderDevice->SetRenderTarget(rt); } //-------------------------------------------------------------------------------- void RenderSystem::_SetRenderTargetClearColor(RenderTargetHandle handle,const Math::float4& clearColor) { GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr rt = rcType.downcast(); n_assert(rt); rt->SetClearColor(clearColor); } //-------------------------------------------------------------------------------- void RenderSystem::_ReSizeRenderTarget(RenderTargetHandle handle,const int& width,const int& height) { GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr rt = rcType.downcast(); n_assert(rt); rt->SetWidth(width); rt->SetHeight(height); } //-------------------------------------------------------------------------------- void RenderSystem::CopyRenderTarget(RenderTargetHandle srcHandle, const Math::float4& srcRect, RenderTargetHandle desHandle, const Math::float4& desRect) { GPtr srcRCType( (RenderCommandType*)srcHandle.mRO ); GPtr srcRT = srcRCType.downcast(); n_assert(srcRT); GPtr desRCType( (RenderCommandType*)desHandle.mRO ); GPtr desRT = desRCType.downcast(); n_assert(desRT); desRT->CopyFrom(srcRect,srcRT,desRect); } void RenderSystem::_SetMultipleRenderTarget(MultipleRenderTargetHandle handle, bool resume) { GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr mrt = rcType.downcast(); m_renderDevice->SetMultipleRenderTarget(mrt, resume); } void RenderSystem::_ReSizeMultipleRenderTarget(MultipleRenderTargetHandle handle,const int& width,const int& height) { //TODO n_error("RenderSystem::_ReSizeMultipleRenderTarget() has not implemented!"); } void RenderSystem::_SetTexture(TextureHandle handle,SizeT index) { n_assert(handle.IsValid()); GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr tex = rcType.downcast(); n_assert(tex); n_assert( index >= 0 && index <= 12) tex->SetUnitIndex(index); m_renderDevice->SetTexture(tex); } void RenderSystem::_SetShaderProgram(GPUProgramHandle handle) { n_assert(handle.IsValid()); GPtr rcType( (RenderCommandType*)handle.mRO ); GPtr program = rcType.downcast(); n_assert(program); m_renderDevice->SetGPUProgram(program); } void RenderSystem::SetVertexShaderConstantVectorF(const int& reg, float* val, const int& vec4count) { m_renderDevice->SetVertexShaderConstantVectorF(reg,val,vec4count); } void RenderSystem::SetPixelShaderConstantVectorF(const int& reg, float* val, const int& vec4count) { m_renderDevice->SetPixelShaderConstantVectorF(reg,val,vec4count); } void RenderSystem::SetVertexShaderConstantFloat(const int& reg, float* val) { m_renderDevice->SetVertexShaderConstantFloat(reg, val); } void RenderSystem::SetPixelShaderConstantFloat(const int& reg, float* val) { m_renderDevice->SetPixelShaderConstantFloat(reg, val); } void RenderSystem::SetVertexShaderConstantMatrixF(const int& reg, float* val, const int& matrixCount) { m_renderDevice->SetVertexShaderConstantMatrixF(reg, val, matrixCount); } void RenderSystem::SetPixelShaderConstantMatrixF(const int& reg, float* val, const int& matrixCount) { m_renderDevice->SetPixelShaderConstantMatrixF(reg, val, matrixCount); } void RenderSystem::_SetRenderState( GPtr rsObject, const uint& shaderMask) { n_assert(rsObject.isvalid()) unsigned int flag = rsObject->GetUpdateFlag(); n_assert(RenderStateDesc::eInvalidRenderState != flag) if (flag & RenderStateDesc::eRenderSamplerState) { m_renderDevice->SetTextureSamplerState(rsObject->GetSamplerState(shaderMask)); } if (flag & RenderStateDesc::eRenderBlendState) { m_renderDevice->SetBlendState(rsObject->GetBlendState()); } if (flag & RenderStateDesc::eRenderDepthAndStencilState) { m_renderDevice->SetDepthAndStencilState(rsObject->GetDepthAndStencilState()); } if (flag & RenderStateDesc::eRenderRasterizerState) { m_renderDevice->SetRasterState(rsObject->GetRasterizerState()); } } void RenderSystem::_RemoveResouce(const RenderResourceHandle& handle) { if ( handle.IsValid() ) { bool bOK = _RemoveRenderHandle( handle ); n_assert(bOK); } } void RenderSystem::_SetDisplayMode(const DisplayMode& mode) { } void RenderSystem::_SetViewPort(const int& x,const int& y,const int& width,const int& height,const float& minZ,const float& maxZ) { m_renderDevice->SetViewPort(x,y,width,height,minZ,maxZ); } ////////////////////////////////////////////////////////////////////////// void RenderSystem::_FXSetClipPlane(const int& index,const Math::float4& plane) { m_renderDevice->FXSetClipPlane(index,plane); } //------------------------------------------------------------------------ bool RenderSystem::_AddRenderHandle( const RenderBase::RenderResourceHandle& handle) { n_assert(handle); RenderResourceHandleSet::InsertResult res = m_renderHandles.insert(handle); if( res.second ) { res.first->mRO->AddRef(); // make a new insert return true; } else { return false; } } //------------------------------------------------------------------------ bool RenderSystem::_RemoveRenderHandle( const RenderBase::RenderResourceHandle& handle) { n_assert(handle); RenderResourceHandleSet::type::iterator itor = m_renderHandles.find(handle); if ( itor != m_renderHandles.end() ) { RenderResourceHandle oldHandle = *itor; n_assert(oldHandle); m_renderHandles.erase(itor); oldHandle.mRO->Release(); return true; } else { return false; } } //------------------------------------------------------------------------ bool RenderSystem::_HasRenderHandle(const RenderBase::RenderResourceHandle& handle) { return m_renderHandles.find( handle ) != m_renderHandles.end(); } GPtr RenderSystem::GetRenderTarget( RenderTargetHandle hdl ) { if ( !hdl.IsValid() ) { return NULL ; } GPtr rcType( (RenderCommandType*)hdl.mRO ); GPtr rt = rcType.downcast(); n_assert(rt); return rt ; } bool RenderSystem::OutPutRenderTarget( RenderTargetHandle hdl , const Util::String& path ) { GPtr rt = GetRenderTarget( hdl ) ; if( !rt.isvalid() ) return false ; return false; #if RENDERDEVICE_D3D9 Core::Rtti* pRtti = rt->GetRtti() ; if( *pRtti != RenderTargetD3D9::RTTI ) return false ; GPtr dx9rt = rt.downcast() ; if( !dx9rt.isvalid() ) return false ; IDirect3DSurface9* sfs = dx9rt->GetD3DRT() ; HRESULT res = D3DXSaveSurfaceToFile( path.Get() , D3DXIFF_TGA , sfs , NULL , NULL ) ; return ( res == S_OK ) ; #endif } void RenderSystem::_OnDeviceLost() { RenderBase::RenderSystem::RenderResourceHandleSet::type &handles = RenderSystem::Instance()->GetRenderResourceHandles(); RenderBase::RenderSystem::RenderResourceHandleSet::type::iterator it = handles.begin(); while(it != handles.end()) { GPtr rcType( (RenderCommandType*)(*it).mRO ); rcType->OnDeviceLost(); ++it; } } void RenderSystem::_OnDeviceReset() { RenderBase::RenderSystem::RenderResourceHandleSet::type &handles = RenderSystem::Instance()->GetRenderResourceHandles(); RenderBase::RenderSystem::RenderResourceHandleSet::type::iterator it = handles.begin(); while(it != handles.end()) { GPtr rcType( (RenderCommandType*)(*it).mRO ); rcType->OnDeviceReset(); ++it; } } void RenderSystem::SetDeviceLostCallBack(deviceLostCallBackFunc func) { m_renderDevice->SetDeviceLostCallBack(func); } void RenderSystem::_OnWindowChanged() { #if RENDERDEVICE_D3D9 // part this operator //m_renderDevice.cast()->SetDeviceLost(); #endif } RenderWindow* RenderSystem::CreateRenderWindow( WindHandle hWnd ) { return m_renderDevice->CreateRenderWindow(hWnd); } void RenderSystem::DestroyRenderWindow(RenderWindow* rw) { m_renderDevice->DestroyRenderWindow(rw); } void RenderSystem::OnDeviceLost() { m_renderDevice->OnDeviceLost(); _OnDeviceLost(); } bool RenderSystem::CheckReset() { return m_renderDevice->CheckReset(); } void RenderSystem::OnDeviceReset() { m_renderDevice->OnDeviceReset(); _OnDeviceReset(); } }