Quantcast
Channel: Windows Presentation Foundation (WPF) forum
Viewing all articles
Browse latest Browse all 18858

WPF: How to capture screen with DirectX and convert to D3DImage

$
0
0

What I am trying to capture screen with DirectX and display with WPF's Image (then maybe do some 2D control to 3D stuff). I already implemented capture with Win32 API which doesn't look pretty. As for DWM, there's no way to go 3D with it.

Well, so much for the background. Basically I am referencing to this post, using managed DirectX to capture screen.

I created a DirectX device:

PresentParameters presentParameters = new PresentParameters
{
  Windowed = true, 
  SwapEffect = SwapEffect.Discard
};

WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
_device = new Device(0, DeviceType.Hardware, windowInteropHelper.Handle, CreateFlags.SoftwareVertexProcessing, presentParameters);

Then I created a surface and get the front buffer data:

_surface = _device.CreateOffscreenPlainSurface(Screen.PrimaryScreen.Bounds.Width,   
    Screen.PrimaryScreen.Bounds.Height, Format.A8R8G8B8, Pool.Scracth);
_device.GetFrontBufferData(0, _surface);

But when I tried to assign it to a D3DImage:

_image = new D3DImage();
_image.IsFrontBufferAvailableChanged += ImageOnIsFrontBufferAvailableChanged;

_image.Lock();

_image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, (IntPtr) _surface.UnmanagedComPointer); //ArgumentException Here

_image.Unlock();

I got an exception at SetBackBuffer

ArgumentException: Back buffer's usage does not meet the requirements for the resource type.

So I did some digging, found a MSDN document specifies the required back buffer settings:

The following list shows the required back buffer settings for the IDirect3DSurface9 type.

  • D3DFMT_A8R8G8B8 or D3DFMT_X8R8G8B8

  • D3DUSAGE_RENDERTARGET

  • D3DPOOL_DEFAULT

So my surface's format is A8R8G8B8, but it cannot be Pool.Default. Otherwise I will get anInvalidCallException at _device.GetFrontBufferData(0, _surface);

Well, after some more digging, I set it to Pool.SystemMemory. And make a copy to a surface in Pool.Default:

_defaultSurface = _device.CreateOffscreenPlainSurface(Screen.PrimaryScreen.Bounds.Width,
            Screen.PrimaryScreen.Bounds.Height, Format.A8R8G8B8, Pool.Default);
_device.UpdateSurface(_surface, _defaultSurface );

But I am still getting that ArgumentException when SetBackBuffer. 

I couldn't figure it out since then.

Any ideas? Thanks.


Viewing all articles
Browse latest Browse all 18858

Trending Articles