2007-06-15 18:30:55 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program 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 General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using System.Windows.Forms ;
using System.IO ;
using System.Reflection ;
using System.Drawing ;
2007-07-07 09:40:34 +00:00
using SlimDX.Direct3D9 ;
2007-06-15 18:30:55 +00:00
using System.ComponentModel ;
2007-06-24 18:56:43 +00:00
using CodeImp.DoomBuilder.Geometry ;
2007-06-26 09:09:54 +00:00
using SlimDX ;
2008-05-29 11:54:45 +00:00
using CodeImp.DoomBuilder.Windows ;
2008-05-13 14:24:35 +00:00
using CodeImp.DoomBuilder.Data ;
using Configuration = CodeImp . DoomBuilder . IO . Configuration ;
2008-05-29 11:54:45 +00:00
using CodeImp.DoomBuilder.Controls ;
2007-06-15 18:30:55 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
2008-01-02 21:49:43 +00:00
internal class D3DDevice
2007-06-15 18:30:55 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
// NVPerfHUD device name
public const string NVPERFHUD_ADAPTER = "NVPerfHUD" ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Settings
private int adapter ;
2008-09-13 13:24:06 +00:00
2007-06-15 18:30:55 +00:00
// Main objects
2008-09-13 13:24:06 +00:00
private static Direct3D d3d ;
2007-10-16 21:15:27 +00:00
private RenderTargetControl rendertarget ;
2007-06-26 09:09:54 +00:00
private Capabilities devicecaps ;
2007-06-24 18:56:43 +00:00
private Device device ;
2007-07-07 09:40:34 +00:00
private Viewport viewport ;
2008-10-15 11:46:43 +00:00
private Dictionary < ID3DResource , ID3DResource > resources ;
2007-10-19 17:05:21 +00:00
private ShaderManager shaders ;
2007-10-23 05:08:02 +00:00
private Surface backbuffer ;
private Surface depthbuffer ;
2008-05-13 14:24:35 +00:00
private TextFont font ;
private ResourceImage fonttexture ;
2007-06-15 18:30:55 +00:00
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2008-01-02 21:49:43 +00:00
internal Device Device { get { return device ; } }
2007-06-15 18:30:55 +00:00
public bool IsDisposed { get { return isdisposed ; } }
2008-01-02 21:49:43 +00:00
internal RenderTargetControl RenderTarget { get { return rendertarget ; } }
internal Viewport Viewport { get { return viewport ; } }
internal ShaderManager Shaders { get { return shaders ; } }
internal Surface BackBuffer { get { return backbuffer ; } }
internal Surface DepthBuffer { get { return depthbuffer ; } }
2008-05-13 14:24:35 +00:00
internal TextFont Font { get { return font ; } }
internal Texture FontTexture { get { return fonttexture . Texture ; } }
2007-10-19 17:05:21 +00:00
2007-06-15 18:30:55 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2008-01-02 21:49:43 +00:00
internal D3DDevice ( RenderTargetControl rendertarget )
2007-06-15 18:30:55 +00:00
{
// Set render target
this . rendertarget = rendertarget ;
2007-07-07 09:40:34 +00:00
2007-10-19 14:27:46 +00:00
// Create resources list
2008-10-15 11:46:43 +00:00
resources = new Dictionary < ID3DResource , ID3DResource > ( ) ;
2007-10-19 14:27:46 +00:00
2007-06-15 18:30:55 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
2008-01-02 21:49:43 +00:00
// Disposer
internal void Dispose ( )
2007-06-15 18:30:55 +00:00
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
2008-10-15 11:46:43 +00:00
foreach ( ID3DResource res in resources . Values ) res . UnloadResource ( ) ;
2007-10-26 18:04:54 +00:00
if ( shaders ! = null ) shaders . Dispose ( ) ;
2007-06-15 18:30:55 +00:00
rendertarget = null ;
2007-10-26 18:04:54 +00:00
if ( backbuffer ! = null ) backbuffer . Dispose ( ) ;
if ( depthbuffer ! = null ) depthbuffer . Dispose ( ) ;
device . Dispose ( ) ;
2008-05-13 14:24:35 +00:00
if ( font ! = null ) font . Dispose ( ) ;
if ( fonttexture ! = null ) fonttexture . Dispose ( ) ;
2007-07-07 09:40:34 +00:00
2007-06-15 18:30:55 +00:00
// Done
isdisposed = true ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Renderstates
// This completes initialization after the device has started or has been reset
2008-02-24 21:52:18 +00:00
public void SetupSettings ( )
2007-06-15 18:30:55 +00:00
{
// Setup renderstates
2008-05-26 20:06:15 +00:00
device . SetRenderState ( RenderState . AlphaRef , 0x0000007E ) ;
2007-11-10 19:24:52 +00:00
device . SetRenderState ( RenderState . AlphaFunc , Compare . GreaterEqual ) ;
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . AntialiasedLineEnable , false ) ;
device . SetRenderState ( RenderState . Ambient , Color . White . ToArgb ( ) ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . AmbientMaterialSource , ColorSource . Material ) ;
2008-04-12 16:07:10 +00:00
device . SetRenderState ( RenderState . ColorWriteEnable , ColorWriteEnable . Red | ColorWriteEnable . Green | ColorWriteEnable . Blue | ColorWriteEnable . Alpha ) ;
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . ColorVertex , false ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . DiffuseMaterialSource , ColorSource . Color1 ) ;
device . SetRenderState ( RenderState . FillMode , FillMode . Solid ) ;
2007-06-26 09:09:54 +00:00
device . SetRenderState ( RenderState . FogEnable , false ) ;
device . SetRenderState ( RenderState . Lighting , false ) ;
device . SetRenderState ( RenderState . LocalViewer , false ) ;
device . SetRenderState ( RenderState . NormalizeNormals , false ) ;
device . SetRenderState ( RenderState . SpecularEnable , false ) ;
device . SetRenderState ( RenderState . StencilEnable , false ) ;
device . SetRenderState ( RenderState . PointSpriteEnable , false ) ;
device . SetRenderState ( RenderState . DitherEnable , true ) ;
device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
device . SetRenderState ( RenderState . ZEnable , false ) ;
device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
device . SetRenderState ( RenderState . Clipping , true ) ;
2007-07-07 09:40:34 +00:00
device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
2008-05-11 00:42:34 +00:00
device . PixelShader = null ;
device . VertexShader = null ;
2007-06-15 18:30:55 +00:00
2008-05-18 11:43:28 +00:00
// Matrices
device . SetTransform ( TransformState . World , Matrix . Identity ) ;
device . SetTransform ( TransformState . View , Matrix . Identity ) ;
device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
2007-06-15 18:30:55 +00:00
// Sampler settings
2008-05-18 11:43:28 +00:00
device . SetSamplerState ( 0 , SamplerState . MagFilter , TextureFilter . Point ) ;
device . SetSamplerState ( 0 , SamplerState . MinFilter , TextureFilter . Point ) ;
device . SetSamplerState ( 0 , SamplerState . MipFilter , TextureFilter . Point ) ;
2007-10-23 05:08:02 +00:00
device . SetSamplerState ( 0 , SamplerState . MipMapLodBias , 0f ) ;
2007-10-21 04:07:36 +00:00
2007-06-15 18:30:55 +00:00
// Texture addressing
2007-07-07 09:40:34 +00:00
device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
2007-06-15 18:30:55 +00:00
// First texture stage
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorOperation , TextureOperation . Modulate ) ;
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorArg1 , TextureArgument . Texture ) ;
2007-10-22 09:00:54 +00:00
device . SetTextureStageState ( 0 , TextureStage . ColorArg2 , TextureArgument . Diffuse ) ;
2007-07-07 09:40:34 +00:00
device . SetTextureStageState ( 0 , TextureStage . ResultArg , TextureArgument . Current ) ;
2007-06-26 09:09:54 +00:00
device . SetTextureStageState ( 0 , TextureStage . TexCoordIndex , 0 ) ;
2007-06-15 18:30:55 +00:00
2008-02-24 21:52:18 +00:00
// Second texture stage
device . SetTextureStageState ( 1 , TextureStage . ColorOperation , TextureOperation . Modulate ) ;
device . SetTextureStageState ( 1 , TextureStage . ColorArg1 , TextureArgument . Current ) ;
device . SetTextureStageState ( 1 , TextureStage . ColorArg2 , TextureArgument . TFactor ) ;
device . SetTextureStageState ( 1 , TextureStage . ResultArg , TextureArgument . Current ) ;
device . SetTextureStageState ( 1 , TextureStage . TexCoordIndex , 0 ) ;
2007-06-15 18:30:55 +00:00
// No more further stages
2008-02-24 21:52:18 +00:00
device . SetTextureStageState ( 2 , TextureStage . ColorOperation , TextureOperation . Disable ) ;
2007-06-15 18:30:55 +00:00
// First alpha stage
2007-10-21 04:07:36 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaOperation , TextureOperation . Modulate ) ;
2007-10-19 14:27:46 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaArg1 , TextureArgument . Texture ) ;
2007-10-22 09:00:54 +00:00
device . SetTextureStageState ( 0 , TextureStage . AlphaArg2 , TextureArgument . Diffuse ) ;
2008-02-24 21:52:18 +00:00
// Second alpha stage
device . SetTextureStageState ( 1 , TextureStage . AlphaOperation , TextureOperation . Modulate ) ;
device . SetTextureStageState ( 1 , TextureStage . AlphaArg1 , TextureArgument . Current ) ;
device . SetTextureStageState ( 1 , TextureStage . AlphaArg2 , TextureArgument . TFactor ) ;
2007-10-21 04:07:36 +00:00
2007-06-15 18:30:55 +00:00
// No more further stages
2008-02-24 21:52:18 +00:00
device . SetTextureStageState ( 2 , TextureStage . AlphaOperation , TextureOperation . Disable ) ;
2007-06-15 18:30:55 +00:00
// Setup material
Material material = new Material ( ) ;
2008-05-11 00:42:34 +00:00
material . Ambient = new Color4 ( Color . White ) ;
material . Diffuse = new Color4 ( Color . White ) ;
material . Specular = new Color4 ( Color . White ) ;
2007-06-24 18:56:43 +00:00
device . Material = material ;
2007-06-15 18:30:55 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Initialization
2008-09-13 13:24:06 +00:00
// This starts up Direct3D
public static void Startup ( )
{
d3d = new Direct3D ( ) ;
}
// This terminates Direct3D
public static void Terminate ( )
{
if ( d3d ! = null )
{
d3d . Dispose ( ) ;
d3d = null ;
}
}
2007-06-15 18:30:55 +00:00
// This initializes the graphics
public bool Initialize ( )
{
PresentParameters displaypp ;
DeviceType devtype ;
2008-09-13 13:24:06 +00:00
2007-06-15 18:30:55 +00:00
// Use default adapter
2007-06-26 09:09:54 +00:00
this . adapter = 0 ; // Manager.Adapters.Default.Adapter;
2007-06-15 18:30:55 +00:00
// Make present parameters
displaypp = CreatePresentParameters ( adapter ) ;
// Determine device type for compatability with NVPerfHUD
2008-09-13 13:24:06 +00:00
if ( d3d . Adapters [ adapter ] . Details . Description . EndsWith ( NVPERFHUD_ADAPTER ) )
2007-06-15 18:30:55 +00:00
devtype = DeviceType . Reference ;
else
devtype = DeviceType . Hardware ;
// Get the device capabilities
2008-09-13 13:24:06 +00:00
devicecaps = d3d . GetDeviceCaps ( adapter , devtype ) ;
2007-06-15 18:30:55 +00:00
try
{
// Check if this adapter supports TnL
2007-06-26 09:09:54 +00:00
if ( ( devicecaps . DeviceCaps & DeviceCaps . HWTransformAndLight ) ! = 0 )
2007-06-15 18:30:55 +00:00
{
// Initialize with hardware TnL
2008-09-13 13:24:06 +00:00
device = new Device ( d3d , adapter , devtype , rendertarget . Handle ,
2007-06-15 18:30:55 +00:00
CreateFlags . HardwareVertexProcessing , displaypp ) ;
}
else
{
// Initialize with software TnL
2008-09-13 13:24:06 +00:00
device = new Device ( d3d , adapter , devtype , rendertarget . Handle ,
2007-06-15 18:30:55 +00:00
CreateFlags . SoftwareVertexProcessing , displaypp ) ;
}
}
catch ( Exception )
{
// Failed
MessageBox . Show ( General . MainWindow , "Unable to initialize the Direct3D video device. Another application may have taken exclusive mode on this video device." , Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return false ;
}
// Add event to cancel resize event
2007-06-26 09:09:54 +00:00
//device.DeviceResizing += new CancelEventHandler(CancelResize);
2007-10-31 20:34:09 +00:00
2008-02-24 21:52:18 +00:00
// Keep a reference to the original buffers
backbuffer = device . GetBackBuffer ( 0 , 0 ) ;
2008-05-11 00:42:34 +00:00
depthbuffer = device . DepthStencilSurface ;
2008-02-24 21:52:18 +00:00
// Get the viewport
viewport = device . Viewport ;
2007-10-31 20:34:09 +00:00
// Create shader manager
2007-10-31 21:33:06 +00:00
shaders = new ShaderManager ( this ) ;
2007-10-19 14:27:46 +00:00
2008-05-13 14:24:35 +00:00
// Font
font = new TextFont ( ) ;
fonttexture = new ResourceImage ( "Font.png" ) ;
fonttexture . LoadImage ( ) ;
2008-05-14 21:48:36 +00:00
fonttexture . MipMapLevels = 2 ;
2008-05-13 14:24:35 +00:00
fonttexture . CreateTexture ( ) ;
2008-05-18 07:31:33 +00:00
// Initialize presentations
Presentation . Initialize ( ) ;
2007-06-15 18:30:55 +00:00
// Initialize settings
SetupSettings ( ) ;
// Done
return true ;
}
// This is to disable the automatic resize reset
private static void CancelResize ( object sender , CancelEventArgs e )
{
// Cancel resize event
e . Cancel = true ;
}
// This creates present parameters
private PresentParameters CreatePresentParameters ( int adapter )
{
PresentParameters displaypp = new PresentParameters ( ) ;
DisplayMode currentmode ;
// Get current display mode
2008-09-13 13:24:06 +00:00
currentmode = d3d . Adapters [ adapter ] . CurrentDisplayMode ;
2007-06-15 18:30:55 +00:00
// Make present parameters
displaypp . Windowed = true ;
displaypp . SwapEffect = SwapEffect . Discard ;
displaypp . BackBufferCount = 1 ;
displaypp . BackBufferFormat = currentmode . Format ;
displaypp . BackBufferWidth = rendertarget . ClientSize . Width ;
displaypp . BackBufferHeight = rendertarget . ClientSize . Height ;
displaypp . EnableAutoDepthStencil = true ;
2007-07-07 09:40:34 +00:00
displaypp . AutoDepthStencilFormat = Format . D16 ;
2007-10-19 14:27:46 +00:00
displaypp . Multisample = MultisampleType . None ;
2007-06-15 18:30:55 +00:00
displaypp . PresentationInterval = PresentInterval . Immediate ;
// Return result
return displaypp ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Resetting
2007-10-19 14:27:46 +00:00
// This registers a resource
2008-01-02 21:49:43 +00:00
internal void RegisterResource ( ID3DResource res )
2007-10-19 14:27:46 +00:00
{
// Add resource
2008-10-15 11:46:43 +00:00
resources . Add ( res , res ) ;
2007-10-19 14:27:46 +00:00
}
// This unregisters a resource
2008-01-02 21:49:43 +00:00
internal void UnregisterResource ( ID3DResource res )
2007-10-19 14:27:46 +00:00
{
// Remove resource
resources . Remove ( res ) ;
}
2007-06-15 18:30:55 +00:00
// This resets the device and returns true on success
2008-01-02 21:49:43 +00:00
internal bool Reset ( )
2007-06-15 18:30:55 +00:00
{
PresentParameters displaypp ;
2008-05-26 06:54:32 +00:00
// Test the cooperative level
Result coopresult = device . TestCooperativeLevel ( ) ;
2007-06-15 18:30:55 +00:00
2008-05-26 06:54:32 +00:00
// Can we reset?
//if(coopresult.Name != "D3DERR_DEVICENOTRESET")
2007-06-15 18:30:55 +00:00
{
2008-05-26 06:54:32 +00:00
// Unload all Direct3D resources
2008-10-15 11:46:43 +00:00
foreach ( ID3DResource res in resources . Values ) res . UnloadResource ( ) ;
2007-06-15 18:30:55 +00:00
2008-05-26 06:54:32 +00:00
// Lose backbuffers
if ( backbuffer ! = null ) backbuffer . Dispose ( ) ;
if ( depthbuffer ! = null ) depthbuffer . Dispose ( ) ;
backbuffer = null ;
depthbuffer = null ;
2008-02-24 21:52:18 +00:00
2008-05-26 06:54:32 +00:00
// Make present parameters
displaypp = CreatePresentParameters ( adapter ) ;
2008-04-17 05:36:48 +00:00
2008-05-26 06:54:32 +00:00
try
{
// Reset the device
device . Reset ( displaypp ) ;
}
catch ( Exception )
{
// Failed to re-initialize
return false ;
}
2007-06-15 18:30:55 +00:00
2008-05-26 06:54:32 +00:00
// Keep a reference to the original buffers
backbuffer = device . GetBackBuffer ( 0 , 0 ) ;
depthbuffer = device . DepthStencilSurface ;
// Get the viewport
viewport = device . Viewport ;
// Initialize settings
SetupSettings ( ) ;
// Reload all Direct3D resources
2008-10-15 11:46:43 +00:00
foreach ( ID3DResource res in resources . Values ) res . ReloadResource ( ) ;
2008-05-26 06:54:32 +00:00
// Success
return true ;
}
/ *
else
{
// Failed
return false ;
}
* /
2007-06-15 18:30:55 +00:00
}
#endregion
2007-06-24 18:56:43 +00:00
#region = = = = = = = = = = = = = = = = = = Rendering
// This begins a drawing session
2008-05-11 00:42:34 +00:00
public bool StartRendering ( bool clear , Color4 backcolor , Surface target , Surface depthbuffer )
2007-06-24 18:56:43 +00:00
{
// When minimized, do not render anything
if ( General . MainWindow . WindowState ! = FormWindowState . Minimized )
{
// Test the cooperative level
2008-05-11 00:42:34 +00:00
Result coopresult = device . TestCooperativeLevel ( ) ;
2007-06-26 09:09:54 +00:00
2007-06-24 18:56:43 +00:00
// Check if device must be reset
2008-05-11 00:42:34 +00:00
if ( ! coopresult . IsSuccess )
2007-06-24 18:56:43 +00:00
{
2008-05-23 06:00:37 +00:00
// Should we reset?
if ( coopresult . Name = = "D3DERR_DEVICENOTRESET" )
{
// Device is lost and must be reset now
Reset ( ) ;
}
// Impossible to render at this point
return false ;
2007-06-24 18:56:43 +00:00
}
2007-10-31 20:34:09 +00:00
// Set rendertarget
2008-05-11 00:42:34 +00:00
device . DepthStencilSurface = depthbuffer ;
2007-10-31 20:34:09 +00:00
device . SetRenderTarget ( 0 , target ) ;
2007-06-24 18:56:43 +00:00
// Clear the screen
2007-10-31 20:34:09 +00:00
if ( clear )
{
if ( depthbuffer ! = null )
device . Clear ( ClearFlags . Target | ClearFlags . ZBuffer , backcolor , 1f , 0 ) ;
else
device . Clear ( ClearFlags . Target , backcolor , 1f , 0 ) ;
}
2007-06-24 18:56:43 +00:00
// Ready to render
device . BeginScene ( ) ;
return true ;
}
else
{
// Minimized, you cannot see anything
return false ;
}
}
// This ends a drawing session
2007-10-31 20:34:09 +00:00
public void FinishRendering ( )
2007-06-24 18:56:43 +00:00
{
try
{
// Done
device . EndScene ( ) ;
}
// Errors are not a problem here
catch ( Exception ) { }
}
2007-10-31 20:34:09 +00:00
// This presents what has been drawn
public void Present ( )
{
try
{
device . Present ( ) ;
}
// Errors are not a problem here
catch ( Exception ) { }
}
2007-06-24 18:56:43 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Tools
// Make a color from ARGB
public static int ARGB ( float a , float r , float g , float b )
{
return Color . FromArgb ( ( int ) ( a * 255f ) , ( int ) ( r * 255f ) , ( int ) ( g * 255f ) , ( int ) ( b * 255f ) ) . ToArgb ( ) ;
}
// Make a color from RGB
public static int RGB ( int r , int g , int b )
{
return Color . FromArgb ( 255 , r , g , b ) . ToArgb ( ) ;
}
// This makes a Vector3 from Vector3D
public static Vector3 V3 ( Vector3D v3d )
{
return new Vector3 ( v3d . x , v3d . y , v3d . z ) ;
}
// This makes a Vector3D from Vector3
public static Vector3D V3D ( Vector3 v3 )
{
return new Vector3D ( v3 . X , v3 . Y , v3 . Z ) ;
}
#endregion
2007-06-15 18:30:55 +00:00
}
}