Jump to content

  • Log In with Google      Sign In   
  • Create Account


Fullscreen capture to surface


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 dsiebes   Members   -  Reputation: 100

Like
0Likes
Like

Posted 12 March 2012 - 04:01 PM

Greetings,

I'm new to DirectX and l am trying to modify an existing project (http://spazzarama.co...sing-api-hooks/) so that it will properly take screenshots from fullscreen directx9 applications from a third party application written in c#, hence the SlimDX. This app also hooks with easy hook.

The comments on the author's post above indicate that to get fullscreen working for dx9, one must set DeviceType.NullReference when initializing the device:

using (device = new Device(d3d, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 }))
				{
					id3dDeviceFunctionAddresses.AddRange(GetVTblAddresses(device.ComPointer, D3D9_DEVICE_METHOD_COUNT));
				}


This, however, is not working for me in various DX9 games running fullscreen. It does seem to work fine for games running Windowed mode.

Here is the exception:
SlimDX.Direct3D9.Direct3D9Exception: D3DERR_INVALIDCALL: Invalid call (-2005530516)

Similar to this thread:
http://www.gamedev.n...devices-solved/

I've tried the solution offered in that thread, but I am having the same result. Here is the screenshot producing function, can anybody point me in the right direction to overcome this exception?

Thank you,
Dan

int EndSceneHook(IntPtr devicePtr)
		{
			Configuration.AddResultWatch(ResultCode.DeviceLost, ResultWatchFlags.AlwaysIgnore);
			using (Device device = Device.FromPointer(devicePtr))
			{
				// If you need to capture at a particular frame rate, add logic here decide whether or not to skip the frame
				try
				{
					#region Screenshot Request
					// Is there a screenshot request? If so lets grab the backbuffer
					//this.DebugMessage("Locking");
					lock (_lockRenderTarget)
					{
					  
						if (Request != null)
						{
							this.DebugMessage("Locked");
							_lastRequestTime = DateTime.Now;
							DateTime start = DateTime.Now;
							try
							{
								// First ensure we have a Surface to the render target data into
								if (_renderTarget == null)
								{
									this.DebugMessage("Render Target is Null");
									// Create offscreen surface to use as copy of render target data
									using (SwapChain sc = device.GetSwapChain(0))
									{
										this.DebugMessage("Create a New Target to Render on");
										_renderTarget = Surface.CreateOffscreenPlain(device, sc.PresentParameters.BackBufferWidth, sc.PresentParameters.BackBufferHeight, sc.PresentParameters.BackBufferFormat, Pool.SystemMemory);
									}
								}
								#region Prepare lines for overlay
								if (this.Request.RegionToCapture.Width == 0)
								{
									_lineVectors = new SlimDX.Vector2[] {
										new SlimDX.Vector2(0, 0),
										new SlimDX.Vector2(_renderTarget.Description.Width - 1, _renderTarget.Description.Height - 1),
										new SlimDX.Vector2(0, _renderTarget.Description.Height - 1),
										new SlimDX.Vector2(_renderTarget.Description.Width - 1, 0),
										new SlimDX.Vector2(0, 0),
										new SlimDX.Vector2(0, _renderTarget.Description.Height - 1),
										new SlimDX.Vector2(_renderTarget.Description.Width - 1, _renderTarget.Description.Height - 1),
										new SlimDX.Vector2(_renderTarget.Description.Width - 1, 0),
									};
								}
								else
								{
									_lineVectors = new SlimDX.Vector2[] {
										new SlimDX.Vector2(this.Request.RegionToCapture.X, this.Request.RegionToCapture.Y),
										new SlimDX.Vector2(this.Request.RegionToCapture.Right, this.Request.RegionToCapture.Bottom),
										new SlimDX.Vector2(this.Request.RegionToCapture.X, this.Request.RegionToCapture.Bottom),
										new SlimDX.Vector2(this.Request.RegionToCapture.Right, this.Request.RegionToCapture.Y),
										new SlimDX.Vector2(this.Request.RegionToCapture.X, this.Request.RegionToCapture.Y),
										new SlimDX.Vector2(this.Request.RegionToCapture.X, this.Request.RegionToCapture.Bottom),
										new SlimDX.Vector2(this.Request.RegionToCapture.Right, this.Request.RegionToCapture.Bottom),
										new SlimDX.Vector2(this.Request.RegionToCapture.Right, this.Request.RegionToCapture.Y),
									};
								}
								#endregion
								using (Surface backBuffer = device.GetBackBuffer(0, 0))
								{
									// Create a super fast copy of the back buffer on our Surface
									device.GetRenderTargetData(backBuffer, _renderTarget);
								  
									this.DebugMessage("We have the frame in memory");
									// We have the back buffer data and can now work on copying it to a bitmap
									ProcessRequest();
								}
							}
							finally
							{
								// We have completed the request - mark it as null so we do not continue to try to capture the same request
								// Note: If you are after high frame rates, consider implementing buffers here to capture more frequently
								//		 and send back to the host application as needed. The IPC overhead significantly slows down
								//		 the whole process if sending frame by frame.
								Request = null;
							}
							DateTime end = DateTime.Now;
							this.DebugMessage("EndSceneHook: Capture time: " + (end - start).ToString());
							_lastScreenshotTime = (end - start);
						}
					}
					#endregion
					#region Example: Draw Overlay (after screenshot so we don't capture overlay as well)
					#region Draw fading lines based on last screencapture request
					if (_lastRequestTime != null && _lineVectors != null)
					{
						TimeSpan timeSinceRequest = DateTime.Now - _lastRequestTime.Value;
						if (timeSinceRequest.TotalMilliseconds < 1000.0)
						{
							using (Line line = new Line(device))
							{
								_lineAlpha = (float)((1000.0 - timeSinceRequest.TotalMilliseconds) / 1000.0); // This is our fade out
								line.Antialias = true;
								line.Width = 1.0f;
								line.Begin();
								line.Draw(_lineVectors, new SlimDX.Color4(_lineAlpha, 0.5f, 0.5f, 1.0f));
								line.End();
							}
						}
						else
						{
							_lineVectors = null;
						}
					}
					#endregion
					#region Draw frame rate
					using (SlimDX.Direct3D9.Font font = new SlimDX.Direct3D9.Font(device, new System.Drawing.Font("Times New Roman", 16.0f)))
					{
						if (_lastFrame != null)
						{
							font.DrawString(null, String.Format("{0:N1} fps", (1000.0 / (DateTime.Now - _lastFrame.Value).TotalMilliseconds)), 100, 100, System.Drawing.Color.Red);
						}
						_lastFrame = DateTime.Now;
					}
					#endregion
					#endregion
				}
				catch(Exception e)
				{
					// If there is an error we do not want to crash the hooked application, so swallow the exception
					this.DebugMessage("EndSceneHook: Exeception: " + e.GetType().FullName + ": " + e.Message);
				}
				// EasyHook has already repatched the original EndScene - so calling EndScene against the SlimDX device will call the original
				// EndScene and bypass this hook. EasyHook will automatically reinstall the hook after this hook function exits.
				return device.EndScene().Code;
			}
		}


Sponsor:



Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS