2011-12-05 19:31:19 +00:00
using System ;
2012-08-12 20:00:19 +00:00
using ANX.Framework ;
2011-12-05 19:31:19 +00:00
using ANX.Framework.Graphics ;
2012-08-12 20:00:19 +00:00
using ANX.Framework.NonXNA ;
using SharpDX.DXGI ;
using Dx11 = SharpDX . Direct3D11 ;
2011-12-05 19:31:19 +00:00
2012-08-09 09:45:04 +00:00
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
2011-12-05 19:31:19 +00:00
2012-08-12 20:00:19 +00:00
namespace ANX.RenderSystem.Windows.Metro
2011-12-05 19:31:19 +00:00
{
2012-08-12 20:00:19 +00:00
public class GraphicsDeviceWindowsMetro : INativeGraphicsDevice
2011-12-05 19:31:19 +00:00
{
#region Constants
private const float ColorMultiplier = 1f / 255f ;
#endregion
2012-08-13 17:31:28 +00:00
2012-08-12 20:00:19 +00:00
#region Private
internal Effect_Metro currentEffect ;
private VertexBuffer currentVertexBuffer ;
private Dx11 . Viewport currentViewport ;
private uint lastClearColor ;
private SharpDX . Color4 clearColor ;
private bool vSyncEnabled ;
internal NativeDxDevice NativeDevice
{
get ;
private set ;
}
#endregion
#region Public
public bool VSync
{
get
{
return this . vSyncEnabled ;
}
set
{
this . vSyncEnabled = value ;
}
}
#endregion
#region Constructor
public GraphicsDeviceWindowsMetro ( PresentationParameters presentationParameters )
{
this . vSyncEnabled = true ;
2012-08-13 11:23:26 +00:00
NativeDevice = new NativeDxDevice ( presentationParameters ) ;
2012-08-12 20:00:19 +00:00
ResizeRenderWindow ( presentationParameters ) ;
2012-08-14 13:07:24 +00:00
currentViewport = new Dx11 . Viewport ( 0 , 0 ,
presentationParameters . BackBufferWidth ,
presentationParameters . BackBufferHeight ) ;
2012-08-12 20:00:19 +00:00
}
#endregion
2011-12-05 19:31:19 +00:00
#region Clear
public void Clear ( ref Color color )
{
uint newClearColor = color . PackedValue ;
if ( lastClearColor ! = newClearColor )
{
lastClearColor = newClearColor ;
clearColor . Red = color . R * ColorMultiplier ;
clearColor . Green = color . G * ColorMultiplier ;
clearColor . Blue = color . B * ColorMultiplier ;
clearColor . Alpha = color . A * ColorMultiplier ;
}
2012-08-12 20:00:19 +00:00
NativeDevice . Clear ( clearColor ) ;
2011-12-05 19:31:19 +00:00
}
2012-08-12 20:00:19 +00:00
public void Clear ( ClearOptions options , Vector4 color , float depth , int stencil )
{
if ( ( options & ClearOptions . Target ) = = ClearOptions . Target )
{
// Clear a RenderTarget (or BackBuffer)
this . clearColor . Red = color . X ;
this . clearColor . Green = color . Y ;
this . clearColor . Blue = color . Z ;
this . clearColor . Alpha = color . W ;
this . lastClearColor = 0 ;
NativeDevice . Clear ( clearColor ) ;
}
if ( ( options | ClearOptions . Stencil | ClearOptions . DepthBuffer ) = = options )
{
// Clear the stencil buffer
NativeDevice . ClearDepthAndStencil ( Dx11 . DepthStencilClearFlags . Depth | Dx11 . DepthStencilClearFlags . Stencil , depth , ( byte ) stencil ) ;
}
else if ( ( options | ClearOptions . Stencil ) = = options )
{
NativeDevice . ClearDepthAndStencil ( Dx11 . DepthStencilClearFlags . Stencil , depth , ( byte ) stencil ) ;
}
else
{
NativeDevice . ClearDepthAndStencil ( Dx11 . DepthStencilClearFlags . Depth , depth , ( byte ) stencil ) ;
}
}
2011-12-05 19:31:19 +00:00
#endregion
2012-08-12 20:00:19 +00:00
#region Present
public void Present ( )
{
NativeDevice . Present ( this . vSyncEnabled ? 1 : 0 ) ;
}
#endregion // Present
2012-08-19 14:38:58 +00:00
#region DrawIndexedPrimitives
public void DrawIndexedPrimitives ( PrimitiveType primitiveType , int baseVertex ,
2012-08-16 20:57:02 +00:00
int minVertexIndex , int numVertices , int startIndex , int primitiveCount )
2012-08-12 20:00:19 +00:00
{
2012-08-19 14:38:58 +00:00
var technique = currentEffect . ManagedEffect . CurrentTechnique ;
var nativeTechnique = technique . NativeTechnique as EffectTechnique_Metro ;
EffectPass_Metro nativePass = nativeTechnique . GetPass ( 0 ) ;
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
SetInputLayout ( currentVertexBuffer . VertexDeclaration , nativePass ) ;
2012-08-16 20:57:02 +00:00
2012-08-19 14:38:58 +00:00
var d3dContext = NativeDevice . NativeContext ;
d3dContext . InputAssembler . PrimitiveTopology = FormatConverter . Translate ( primitiveType ) ;
2012-08-16 20:57:02 +00:00
d3dContext . VertexShader . Set ( nativePass . VertexShader ) ;
d3dContext . PixelShader . Set ( nativePass . PixelShader ) ;
//d3dContext.PixelShader.SetSampler(0, sampler);
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
NativeDevice . SetDefaultTargets ( ) ;
2012-08-12 20:00:19 +00:00
//for (int i = 0; i < technique.Description.PassCount; ++i)
//{
// pass.Apply();
2012-08-19 14:38:58 +00:00
int indexCount = CalculateVertexCount ( primitiveType , primitiveCount ) ;
d3dContext . DrawIndexed ( indexCount , startIndex , baseVertex ) ;
2012-08-12 20:00:19 +00:00
//}
2012-08-19 14:38:58 +00:00
}
#endregion
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
#region DrawPrimitives
public void DrawPrimitives ( PrimitiveType primitiveType , int vertexOffset , int primitiveCount )
{
var technique = currentEffect . ManagedEffect . CurrentTechnique ;
var nativeTechnique = technique . NativeTechnique as EffectTechnique_Metro ;
EffectPass_Metro nativePass = nativeTechnique . GetPass ( 0 ) ;
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
SetInputLayout ( currentVertexBuffer . VertexDeclaration , nativePass ) ;
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
var d3dContext = NativeDevice . NativeContext ;
d3dContext . InputAssembler . PrimitiveTopology = FormatConverter . Translate ( primitiveType ) ;
d3dContext . VertexShader . Set ( nativePass . VertexShader ) ;
d3dContext . PixelShader . Set ( nativePass . PixelShader ) ;
2012-08-12 20:00:19 +00:00
2012-08-19 14:38:58 +00:00
NativeDevice . SetDefaultTargets ( ) ;
2012-08-12 20:00:19 +00:00
//for (int i = 0; i < technique.Description.PassCount; ++i)
//{
// pass.Apply();
2012-08-19 14:38:58 +00:00
d3dContext . Draw ( primitiveCount , vertexOffset ) ;
2012-08-12 20:00:19 +00:00
//}
}
2012-08-19 14:38:58 +00:00
#endregion
2012-08-12 20:00:19 +00:00
#region DrawInstancedPrimitives
2012-08-14 13:07:24 +00:00
public void DrawInstancedPrimitives ( PrimitiveType primitiveType ,
int baseVertex , int minVertexIndex , int numVertices , int startIndex ,
int primitiveCount , int instanceCount )
2012-08-12 20:00:19 +00:00
{
2012-08-14 13:07:24 +00:00
NativeDevice . NativeContext . DrawIndexedInstanced ( numVertices ,
instanceCount , startIndex , baseVertex , 0 ) ;
2012-08-12 20:00:19 +00:00
}
#endregion // DrawInstancedPrimitives
#region DrawUserIndexedPrimitives < T >
2012-08-16 20:57:02 +00:00
public void DrawUserIndexedPrimitives < T > ( PrimitiveType primitiveType , T [ ] vertexData ,
int vertexOffset , int numVertices , Array indexData , int indexOffset , int primitiveCount ,
VertexDeclaration vertexDeclaration , IndexElementSize indexFormat )
where T : struct , IVertexType
2012-08-12 20:00:19 +00:00
{
int vertexCount = vertexData . Length ;
int indexCount = indexData . Length ;
VertexBuffer_Metro vb11 = new VertexBuffer_Metro ( NativeDevice . NativeDevice , vertexDeclaration , vertexCount , BufferUsage . None ) ;
vb11 . SetData < T > ( null , vertexData ) ;
Dx11 . VertexBufferBinding nativeVertexBufferBindings = new Dx11 . VertexBufferBinding ( vb11 . NativeBuffer , vertexDeclaration . VertexStride , 0 ) ;
NativeDevice . NativeContext . InputAssembler . SetVertexBuffers ( 0 , nativeVertexBufferBindings ) ;
IndexBuffer_Metro idxMetro = new IndexBuffer_Metro ( NativeDevice . NativeDevice , indexFormat , indexCount , BufferUsage . None ) ;
if ( indexData . GetType ( ) = = typeof ( Int16 [ ] ) )
{
idxMetro . SetData < short > ( null , ( short [ ] ) indexData ) ;
}
else
{
idxMetro . SetData < int > ( null , ( int [ ] ) indexData ) ;
}
DrawIndexedPrimitives ( primitiveType , 0 , vertexOffset , numVertices , indexOffset , primitiveCount ) ;
}
#endregion // DrawUserIndexedPrimitives<T>
2011-12-05 19:31:19 +00:00
2012-08-12 20:00:19 +00:00
#region DrawUserPrimitives < T >
2012-08-16 20:57:02 +00:00
public void DrawUserPrimitives < T > ( PrimitiveType primitiveType , T [ ] vertexData , int vertexOffset ,
int primitiveCount , VertexDeclaration vertexDeclaration ) where T : struct , IVertexType
2012-08-12 20:00:19 +00:00
{
int vertexCount = vertexData . Length ;
2012-08-16 20:57:02 +00:00
VertexBuffer_Metro vbMetro = new VertexBuffer_Metro ( NativeDevice . NativeDevice ,
vertexDeclaration , vertexCount , BufferUsage . None ) ;
2012-08-12 20:00:19 +00:00
vbMetro . SetData < T > ( null , vertexData ) ;
2012-08-16 20:57:02 +00:00
Dx11 . VertexBufferBinding nativeVertexBufferBindings = new Dx11 . VertexBufferBinding (
vbMetro . NativeBuffer , vertexDeclaration . VertexStride , 0 ) ;
2012-08-12 20:00:19 +00:00
NativeDevice . NativeContext . InputAssembler . SetVertexBuffers ( 0 , nativeVertexBufferBindings ) ;
DrawPrimitives ( primitiveType , vertexOffset , primitiveCount ) ;
}
2011-12-05 19:31:19 +00:00
2012-08-12 20:00:19 +00:00
#endregion // DrawUserPrimitives<T>
2012-08-16 20:57:02 +00:00
2012-08-14 08:44:12 +00:00
#region CalculateVertexCount
2012-08-12 20:00:19 +00:00
private int CalculateVertexCount ( PrimitiveType type , int primitiveCount )
{
if ( type = = PrimitiveType . TriangleList )
return primitiveCount * 3 ;
else if ( type = = PrimitiveType . LineList )
return primitiveCount * 2 ;
else if ( type = = PrimitiveType . LineStrip )
return primitiveCount + 1 ;
else if ( type = = PrimitiveType . TriangleStrip )
return primitiveCount + 2 ;
else
2012-08-19 14:38:58 +00:00
throw new NotImplementedException ( "couldn't calculate vertex count for PrimitiveType '" + type + "'" ) ;
2012-08-12 20:00:19 +00:00
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region SetIndexBuffer
2012-08-12 20:00:19 +00:00
public void SetIndexBuffer ( IndexBuffer indexBuffer )
{
if ( indexBuffer = = null )
throw new ArgumentNullException ( "indexBuffer" ) ;
IndexBuffer_Metro nativeIndexBuffer = indexBuffer . NativeIndexBuffer as IndexBuffer_Metro ;
if ( nativeIndexBuffer ! = null )
{
2012-08-19 14:38:58 +00:00
NativeDevice . NativeContext . InputAssembler . SetIndexBuffer ( nativeIndexBuffer . NativeBuffer ,
FormatConverter . Translate ( indexBuffer . IndexElementSize ) , 0 ) ;
2012-08-12 20:00:19 +00:00
}
else
{
throw new Exception ( "couldn't fetch native DirectX10 IndexBuffer" ) ;
}
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region SetVertexBuffers
2012-08-12 20:00:19 +00:00
public void SetVertexBuffers ( VertexBufferBinding [ ] vertexBuffers )
{
if ( vertexBuffers = = null )
throw new ArgumentNullException ( "vertexBuffers" ) ;
this . currentVertexBuffer = vertexBuffers [ 0 ] . VertexBuffer ; //TODO: hmmmmm, not nice :-)
2012-08-19 14:38:58 +00:00
var nativeVertexBufferBindings = new Dx11 . VertexBufferBinding [ vertexBuffers . Length ] ;
2012-08-12 20:00:19 +00:00
for ( int i = 0 ; i < vertexBuffers . Length ; i + + )
{
2012-08-19 14:38:58 +00:00
VertexBufferBinding anxVertexBufferBinding = vertexBuffers [ i ] ;
VertexBuffer_Metro nativeVertexBuffer =
anxVertexBufferBinding . VertexBuffer . NativeVertexBuffer as VertexBuffer_Metro ;
2012-08-12 20:00:19 +00:00
if ( nativeVertexBuffer ! = null )
{
2012-08-19 14:38:58 +00:00
nativeVertexBufferBindings [ i ] = new Dx11 . VertexBufferBinding ( nativeVertexBuffer . NativeBuffer ,
anxVertexBufferBinding . VertexBuffer . VertexDeclaration . VertexStride ,
anxVertexBufferBinding . VertexOffset ) ;
2012-08-12 20:00:19 +00:00
}
else
{
throw new Exception ( "couldn't fetch native DirectX10 VertexBuffer" ) ;
}
}
NativeDevice . NativeContext . InputAssembler . SetVertexBuffers ( 0 , nativeVertexBufferBindings ) ;
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region SetViewport
2012-08-12 20:00:19 +00:00
public void SetViewport ( Viewport viewport )
{
2012-08-14 08:44:12 +00:00
this . currentViewport = new Dx11 . Viewport ( viewport . X , viewport . Y ,
viewport . Width , viewport . Height , viewport . MinDepth , viewport . MaxDepth ) ;
2012-08-12 20:00:19 +00:00
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-19 14:38:58 +00:00
#region SetInputLayout
private void SetInputLayout ( VertexDeclaration vertexDeclaration , EffectPass_Metro nativePass )
{
VertexElement [ ] vertexElements = vertexDeclaration . GetVertexElements ( ) ;
int elementCount = vertexElements . Length ;
var inputElements = new Dx11 . InputElement [ elementCount ] ;
for ( int i = 0 ; i < elementCount ; i + + )
{
inputElements [ i ] = CreateInputElementFromVertexElement ( vertexElements [ i ] ) ;
}
NativeDevice . NativeContext . InputAssembler . InputLayout =
nativePass . BuildLayout ( NativeDevice . NativeDevice , inputElements ) ;
}
#endregion
#region CreateInputElementFromVertexElement
private Dx11 . InputElement CreateInputElementFromVertexElement ( VertexElement vertexElement )
2012-08-12 20:00:19 +00:00
{
string elementName = FormatConverter . Translate ( vertexElement . VertexElementUsage ) ;
Format elementFormat ;
switch ( vertexElement . VertexElementFormat )
{
case VertexElementFormat . Vector2 :
elementFormat = Format . R32G32_Float ;
break ;
case VertexElementFormat . Vector3 :
elementFormat = Format . R32G32B32_Float ;
break ;
case VertexElementFormat . Vector4 :
elementFormat = Format . R32G32B32A32_Float ;
break ;
case VertexElementFormat . Color :
elementFormat = Format . R8G8B8A8_UNorm ;
break ;
default :
throw new Exception ( "can't map '" + vertexElement . VertexElementFormat . ToString ( ) + "' to DXGI.Format in DirectX10 RenderSystem CreateInputElementFromVertexElement" ) ;
}
return new Dx11 . InputElement ( elementName , vertexElement . UsageIndex , elementFormat , vertexElement . Offset , 0 ) ;
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region SetRenderTargets ( TODO )
2012-08-12 20:00:19 +00:00
public void SetRenderTargets ( params RenderTargetBinding [ ] renderTargets )
{
/ * if ( renderTargets = = null )
{
// reset the RenderTarget to backbuffer
if ( renderTargetView ! = null )
{
renderTargetView . Dispose ( ) ;
renderTargetView = null ;
}
//TODO: device.OutputMerger.SetRenderTargets(1, new RenderTargetView[] { this.renderView }, this.depthStencilView);
deviceContext . OutputMerger . SetTargets ( this . depthStencilView , this . renderView ) ;
}
else
{
if ( renderTargets . Length = = 1 )
{
RenderTarget2D renderTarget = renderTargets [ 0 ] . RenderTarget as RenderTarget2D ;
RenderTarget2D_Metro nativeRenderTarget = renderTarget . NativeRenderTarget as RenderTarget2D_Metro ;
if ( renderTarget ! = null )
{
if ( renderTargetView ! = null )
{
renderTargetView . Dispose ( ) ;
renderTargetView = null ;
}
this . renderTargetView = new RenderTargetView ( deviceContext . Device , ( ( Texture2D_Metro ) nativeRenderTarget ) . NativeShaderResourceView . Resource ) ;
DepthStencilView depthStencilView = null ;
deviceContext . OutputMerger . SetTargets ( new RenderTargetView [ ] { this . renderTargetView } ) ;
//deviceContext.OutputMerger.SetTargets(new RenderTargetView[] { this.renderTargetView }, depthStencilView);
//TODO: set depthStencilView
}
}
else
{
throw new NotImplementedException ( "handling of multiple RenderTargets are not yet implemented" ) ;
}
} * /
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region GetBackBufferData ( TODO )
2012-08-12 20:00:19 +00:00
public void GetBackBufferData < T > ( Rectangle ? rect , T [ ] data , int startIndex , int elementCount ) where T : struct
{
throw new NotImplementedException ( ) ;
}
public void GetBackBufferData < T > ( T [ ] data ) where T : struct
{
throw new NotImplementedException ( ) ;
}
public void GetBackBufferData < T > ( T [ ] data , int startIndex , int elementCount ) where T : struct
{
throw new NotImplementedException ( ) ;
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region ResizeBuffers
2012-08-12 20:00:19 +00:00
public void ResizeBuffers ( PresentationParameters presentationParameters )
{
NativeDevice . Resize ( presentationParameters ) ;
ResizeRenderWindow ( presentationParameters ) ;
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
2012-08-14 08:44:12 +00:00
#region ResizeRenderWindow ( TODO )
2012-08-12 20:00:19 +00:00
private void ResizeRenderWindow ( PresentationParameters presentationParameters )
{
2012-08-13 17:31:28 +00:00
// TODO
//WindowsGameWindow gameWindow = (WindowsGameHost.Instance.Window as WindowsGameWindow);
//if (gameWindow.Form != null)
//{
//gameWindow.Form.Bounds
//}
2012-08-12 20:00:19 +00:00
}
2012-08-14 08:44:12 +00:00
#endregion
2012-08-12 20:00:19 +00:00
#region Dispose
public void Dispose ( )
{
if ( NativeDevice ! = null )
{
NativeDevice . Dispose ( ) ;
NativeDevice = null ;
}
}
#endregion
}
2011-12-05 19:31:19 +00:00
}