Login
 
Archive
Links
Search
Blog List
There are no categories in this blog.
 
Aug 12

Written by: Jeremiah Morrill
8/12/2008 2:28 AM

XNA in WPF The new D3DImage in WPF opens up worlds for WPF.  Direct3D content rendered with WPF...it doesn't get any better!  The downside is it seems (correct me if I'm wrong) that Microsoft was only targeting unmanaged Direct3D.  Yes there is Managed DirectX, but it seems as if MDX is no longer being maintained and it's not so obvious how to get a D3D surface pointer from the API.  It really seems MDX has been left in the dust in favor for XNA, which is a very intuitive D3D wrapper.  XNA further exacerbates the issue with XNA and WPF. 

 

A couple of the issues are:

1.) XNA hides all the nasty D3D COM pointers, so you can't get the surface pointer via the XNA API.

2.) XNA creates a IDirect3DDevice9 internally.  WPF D3DImage needs a IDirect3DDevice9Ex for maximum performance on Vista.

Initially, my plan was create a 9Ex device, inject it into the XNA GraphicsDevice class via reflection, which *worked* until you tried to load a texture.  The XNA libraries are hard coded for a D3DPOOL_MANAGED pool, which is incompatible with the 9Ex device (Thanks Doc!).  Ok, so we can live without break-neck performance of 9Ex...for now.  So I just focused on getting the surface pointer and setting the render target.  Here is a quick snippet for the Microsoft.Xna.Framework.Game subclass.  You will need to add reference to the MDX assembly Microsoft.DirectX.Direct3D.  Ignore all "LoaderLock" exceptions or just turn them off in Visual Studio.  You will also need to throw an event on the Draw override to notify your D3DImage that there is a dirty rect.  You should probably also add an event for when a new surface is available also, for when the D3D device is lost.

 

private Surface m_surface;
private int WIDTH = 300;
private int HEIGHT = 300;

unsafe protected override void BeginRun()

{
    Type deviceType = typeof(GraphicsDevice);
    FieldInfo fi = deviceType.GetField("pComPtr", 
                                        BindingFlags.NonPublic | BindingFlags.Instance);
    object ptr = fi.GetValue(graphics.GraphicsDevice);
    IntPtr pComPtr = new IntPtr(Pointer.Unbox(ptr));

    Microsoft.DirectX.Direct3D.Device dev = new Microsoft.DirectX.Direct3D.Device(pComPtr);

    m_surface = dev.CreateRenderTarget(WIDTH, 
                                       HEIGHT, 
                                       Format.X8R8G8B8, 
                                       Microsoft.DirectX.Direct3D.MultiSampleType.None, 
                                       0, 
                                       System.Environment.OSVersion.Version.Major >= 6);

    dev.SetRenderTarget(0, m_surface);

    base.BeginRun();
}

unsafe public IntPtr GetSurfacePointer()
{
    /* TODO:  Figure out how to convert Surface.UnmanagedComPointer to IntPtr */
    return m_surface.GetObjectByValue(unchecked((int)0xd2b543af));
}

Tags:

6 comments so far...

Re: XNA, Meet WPF

Awesome stuff! Thanks for posting this, Jer.

I totally agree that XNA should be extended to support the 9Ex device. It would be great if there were a global setting that controlled this. Then the XNA framework could dynamically allocate resources in the default pool, rather than the managed pool, for 9Ex devices. Let's hope this is planned for the future. :-)

By Dr. WPF on   8/12/2008 9:44 AM

Re: XNA, Meet WPF

Hey Doc!

I think XNA is a fantastic framework. And it's just becoming more and more popular, supporting thinks like the 360 and Zune. It just makes sense to support WPF. I sure hope theres somebody on the inside lobbying for it.

By Jeremiah Morrill on   8/14/2008 6:03 AM

Re: XNA, Meet WPF

Even when XNA was still in preview the DirectX SDK read-me said that MDX 2.0 would be cancelled infavour of XNA so there isn't any ambiguity.

[)amien

By Damien Guard on   8/14/2008 6:24 PM

Re: XNA, Meet WPF

This is great - that d3dimage forces us to use unmanaged DirectX just seems like such a backwards step to me, so it makes me glad to see someone else working on this problem. Hopefully they'll release some mods for XNA so you won't have to resort to hacks to get it to work.

Thanks for the post =)

By Erik on   8/14/2008 7:47 PM

Re: XNA, Meet WPF

Have you thought about using SlimDX? It's a low level wrapper for DirectX which does not use MDX or XNA.

http://slimdx.mdxinfo.com/wiki/index.php?title=Main_Page

By Pekka Heikura on   8/15/2008 2:36 AM

Re: XNA, Meet WPF

Thanks for the link to SlimDX Pekka!

I have not really looked into any other managed wrappers, though there is one here that supports DX9, DX9Ex and DX10. http://www.codeplex.com/MD3D10

I do prefer the XNA model much more though ;)

By Jeremiah Morrill on   8/15/2008 7:06 AM

Your name:
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment    Cancel  
  Minimize
Text/HTML Minimize
Copyright 2007
Downloaded from DNNSkins.com