/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { this.Frame(); SwapChain swapChain = (SharpDX.DXGI.SwapChain)swapChainPtr; { try { #region Draw overlay using (Texture2D texture = Texture2D.FromSwapChain <SharpDX.Direct3D10.Texture2D>(swapChain, 0)) { foreach (var text in Texts) { using (Font font = new Font(texture.Device, text.FontDescription)) { DrawText(font, text.Position, text.Text, text.Color); } } } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.Message); } // As always we need to call the original method, note that EasyHook has already repatched the original method // so calling it here will not cause an endless recursion to this function swapChain.Present(syncInterval, flags); return(SharpDX.Result.Ok.Code); } }
/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { this.Frame(); SwapChain swapChain = (SharpDX.DXGI.SwapChain)swapChainPtr; try { #region Draw overlay (after screenshot so we don't capture overlay as well) // Initialise Overlay Engine if (_swapChainPointer != swapChain.NativePointer || OverlayEngine == null) { if (OverlayEngine != null) { OverlayEngine.Dispose(); } OverlayEngine = new DX11.DXOverlayEngine(); OverlayEngine.Overlays.Add(new DirectXHook.Hook.Common.Overlay { Elements = { new Common.ImageElement(new Bitmap(1920, 1080)) { Location = new System.Drawing.Point(0, 0) }, //new Common.TextElement(new System.Drawing.Font("Times New Roman", 22)) { Text = "Test", Location = new System.Drawing.Point(200, 200), Color = System.Drawing.Color.Yellow, AntiAliased = false}, new Common.FramesPerSecond(new System.Drawing.Font("Arial", 16)) { Location = new System.Drawing.Point(5, 5), Color = System.Drawing.Color.Red, AntiAliased = true }, } }); OverlayEngine.Initialise(swapChain); _swapChainPointer = swapChain.NativePointer; } // Draw Overlay(s) else if (OverlayEngine != null) { foreach (var overlay in OverlayEngine.Overlays) { overlay.Frame(); } OverlayEngine.Draw(); } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.ToString()); //return unchecked((int)0x8000FFFF); //E_UNEXPECTED } // As always we need to call the original method, note that EasyHook will automatically skip the hook and call the original method // i.e. calling it here will not cause a stack overflow into this function return(DXGISwapChain_PresentHook.Original(swapChainPtr, syncInterval, flags)); }
private int Detour_Present(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { SwapChain swapChain = (SwapChain)swapChainPtr; DrawFramesPerSecond(swapChain); return(_d3DPresentHook.Original(swapChainPtr, syncInterval, flags)); }
private void CreateSwapChain(IntPtr window, bool vsync) { using (SharpDX.DXGI.Factory4 factory = new Factory4()) { //SharpDX.DXGI.Adapter adapter = factory.GetAdapterByLuid(_dev.AdapterLuid); //System.Console.WriteLine($" Adapter: {adapter.Description.Description}"); System.Console.WriteLine($" Adapter: {factory.Adapters[0].Description.Description}"); if (!vsync) { using (SharpDX.DXGI.Factory5 factory5 = factory.QueryInterface <Factory5>()) { if (factory5 != null) { SharpDX.Mathematics.Interop.RawBool tearing = false; GCHandle pinnedInt = GCHandle.Alloc(tearing, GCHandleType.Pinned); IntPtr pointer = pinnedInt.AddrOfPinnedObject(); factory5.CheckFeatureSupport(SharpDX.DXGI.Feature.PresentAllowTearing, pointer, System.Runtime.InteropServices.Marshal.SizeOf(tearing)); if (tearing != false) { _swapChainFlags = SharpDX.DXGI.SwapChainFlags.AllowTearing; _presentFlags = SharpDX.DXGI.PresentFlags.AllowTearing; } pinnedInt.Free(); } } _syncInterval = 0; } else { _syncInterval = 1; } SharpDX.DXGI.SwapChainDescription1 desc = new SharpDX.DXGI.SwapChainDescription1(); desc.Width = 0; desc.Height = 0; desc.Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; desc.Stereo = false; desc.SampleDescription = new SampleDescription { Count = 1, Quality = 0 }; desc.Usage = SharpDX.DXGI.Usage.RenderTargetOutput; desc.BufferCount = FrameCount; desc.Scaling = SharpDX.DXGI.Scaling.Stretch; desc.SwapEffect = SharpDX.DXGI.SwapEffect.FlipDiscard; desc.AlphaMode = SharpDX.DXGI.AlphaMode.Unspecified; desc.Flags = _swapChainFlags; using (SharpDX.DXGI.SwapChain1 swapChain = new SharpDX.DXGI.SwapChain1(factory, _queue, window, ref desc)) { factory.MakeWindowAssociation(window, WindowAssociationFlags.IgnoreAltEnter); _swapChain = swapChain.QueryInterface <SharpDX.DXGI.SwapChain3>(); } } }
int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { SwapChain swapChain = (SharpDX.DXGI.SwapChain)swapChainPtr; //SharpDX.Direct3D11.Device device = swapChain.GetDevice<SharpDX.Direct3D11.Device>(); if (!closed) { if (dx11gui == null) { dx11gui = new DX11GUI(swapChain); } dx11gui.RenderCrosshair(); connection.getFPS = fpsTool.getFPS(); fpsTool.limitFPS(); } swapChain.Present(syncInterval, flags); return(SharpDX.Result.Ok.Code); }
/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { this.Frame(); SwapChain swapChain = (SharpDX.DXGI.SwapChain)swapChainPtr; try { #region Screenshot Request if (this.Request != null) { this.DebugMessage("PresentHook: Request Start"); DateTime startTime = DateTime.Now; using (Texture2D currentRT = Texture2D.FromSwapChain <Texture2D>(swapChain, 0)) { #region Determine region to capture Rectangle captureRegion = new Rectangle(0, 0, currentRT.Description.Width, currentRT.Description.Height); if (this.Request.RegionToCapture.Width > 0) { captureRegion = new Rectangle(this.Request.RegionToCapture.Left, this.Request.RegionToCapture.Top, this.Request.RegionToCapture.Right, this.Request.RegionToCapture.Bottom); } else if (this.Request.Resize.HasValue) { captureRegion = new Rectangle(0, 0, this.Request.Resize.Value.Width, this.Request.Resize.Value.Height); } #endregion // Create / Recreate resources as necessary EnsureResources(currentRT.Device, currentRT.Description, captureRegion, Request); Texture2D sourceTexture = null; // If texture is multisampled, then we can use ResolveSubresource to copy it into a non-multisampled texture if (currentRT.Description.SampleDescription.Count > 1 || Request.Resize.HasValue) { if (Request.Resize.HasValue) { this.DebugMessage("PresentHook: resizing texture"); } else { this.DebugMessage("PresentHook: resolving multi-sampled texture"); } // Resolve into _resolvedRT if (_resolvedRTKeyedMutex != null) { _resolvedRTKeyedMutex.Acquire(0, int.MaxValue); } currentRT.Device.ImmediateContext.ResolveSubresource(currentRT, 0, _resolvedRT, 0, _resolvedRT.Description.Format); if (_resolvedRTKeyedMutex != null) { _resolvedRTKeyedMutex.Release(1); } if (Request.Resize.HasValue) { lock (_lock) { if (_resolvedRTKeyedMutex_Dev2 != null) { _resolvedRTKeyedMutex_Dev2.Acquire(1, int.MaxValue); } _saQuad.ShaderResource = _resolvedSharedSRV; _saQuad.RenderTargetView = _resizedRTV; _saQuad.RenderTarget = _resizedRT; _saQuad.Render(); if (_resolvedRTKeyedMutex_Dev2 != null) { _resolvedRTKeyedMutex_Dev2.Release(0); } } // set sourceTexture to the resized RT sourceTexture = _resizedRT; } else { // Make sourceTexture be the resolved texture sourceTexture = _resolvedRTShared; } } else { // Copy the resource into the shared texture if (_resolvedRTKeyedMutex != null) { _resolvedRTKeyedMutex.Acquire(0, int.MaxValue); } currentRT.Device.ImmediateContext.CopySubresourceRegion(currentRT, 0, null, _resolvedRT, 0); if (_resolvedRTKeyedMutex != null) { _resolvedRTKeyedMutex.Release(1); } sourceTexture = _resolvedRTShared; } // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline _requestCopy = this.Request.Clone(); // this.Request gets set to null, so copy the Request for use in the thread // Prevent the request from being processed a second time this.Request = null; bool acquireLock = sourceTexture == _resolvedRTShared; ThreadPool.QueueUserWorkItem(new WaitCallback((o) => { // Acquire lock on second device if (acquireLock && _resolvedRTKeyedMutex_Dev2 != null) { _resolvedRTKeyedMutex_Dev2.Acquire(1, int.MaxValue); } lock (_lock) { // Copy the subresource region, we are dealing with a flat 2D texture with no MipMapping, so 0 is the subresource index sourceTexture.Device.ImmediateContext.CopySubresourceRegion(sourceTexture, 0, new ResourceRegion() { Top = captureRegion.Top, Bottom = captureRegion.Bottom, Left = captureRegion.Left, Right = captureRegion.Right, Front = 0, Back = 1 // Must be 1 or only black will be copied }, _finalRT, 0, 0, 0, 0); // Release lock upon shared surface on second device if (acquireLock && _resolvedRTKeyedMutex_Dev2 != null) { _resolvedRTKeyedMutex_Dev2.Release(0); } _finalRT.Device.ImmediateContext.End(_query); _queryIssued = true; while (!_finalRT.Device.ImmediateContext.GetData(_query).ReadBoolean()) { // Spin (usually no spin takes place) } DateTime startCopyToSystemMemory = DateTime.Now; try { DataBox db = default(DataBox); //Arvy added to support features required by average color capture if (_requestCopy.Format == ImageFormat.PixelData || _requestCopy.Format == ImageFormat.AverageColor) { db = _finalRT.Device.ImmediateContext.MapSubresource(_finalRT, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.DoNotWait); _finalRTMapped = true; } _queryIssued = false; try { using (MemoryStream ms = new MemoryStream()) { switch (_requestCopy.Format) { case ImageFormat.Bitmap: Texture2D.ToStream(_finalRT.Device.ImmediateContext, _finalRT, ImageFileFormat.Bmp, ms); break; case ImageFormat.Jpeg: Texture2D.ToStream(_finalRT.Device.ImmediateContext, _finalRT, ImageFileFormat.Jpg, ms); break; case ImageFormat.Png: Texture2D.ToStream(_finalRT.Device.ImmediateContext, _finalRT, ImageFileFormat.Png, ms); break; case ImageFormat.PixelData: //Arvy added to support features required by average color capture case ImageFormat.AverageColor: if (db.DataPointer != IntPtr.Zero) { ProcessCapture(_finalRT.Description.Width, _finalRT.Description.Height, db.RowPitch, System.Drawing.Imaging.PixelFormat.Format32bppArgb, db.DataPointer, _requestCopy); } return; } ms.Position = 0; ProcessCapture(ms, _requestCopy); } } finally { this.DebugMessage("PresentHook: Copy to System Memory time: " + (DateTime.Now - startCopyToSystemMemory).ToString()); } if (_finalRTMapped) { lock (_lock) { _finalRT.Device.ImmediateContext.UnmapSubresource(_finalRT, 0); _finalRTMapped = false; } } } catch (SharpDX.SharpDXException exc) { // Catch DXGI_ERROR_WAS_STILL_DRAWING and ignore - the data isn't available yet } } })); // Note: it would be possible to capture multiple frames and process them in a background thread } this.DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime).ToString()); this.DebugMessage("PresentHook: Request End"); } #endregion #region Draw overlay (after screenshot so we don't capture overlay as well) if (this.Config.ShowOverlay) { // Initialise Overlay Engine if (_swapChainPointer != swapChain.NativePointer || _overlayEngine == null) { if (_overlayEngine != null) { _overlayEngine.Dispose(); } _overlayEngine = new DX11.DXOverlayEngine(); _overlayEngine.Overlays.Add(new Capture.Hook.Common.Overlay { Elements = { //new Capture.Hook.Common.TextElement(new System.Drawing.Font("Times New Roman", 22)) { Text = "Test", Location = new System.Drawing.Point(200, 200), Color = System.Drawing.Color.Yellow, AntiAliased = false}, new Capture.Hook.Common.FramesPerSecond(new System.Drawing.Font("Arial", 16)) { Location = new System.Drawing.Point(5, 5), Color = System.Drawing.Color.Red, AntiAliased = true }, //new Capture.Hook.Common.ImageElement(@"C:\Temp\test.bmp") { Location = new System.Drawing.Point(20, 20) } } }); _overlayEngine.Initialise(swapChain); _swapChainPointer = swapChain.NativePointer; } // Draw Overlay(s) else if (_overlayEngine != null) { foreach (var overlay in _overlayEngine.Overlays) { overlay.Frame(); } _overlayEngine.Draw(); } } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.ToString()); //return unchecked((int)0x8000FFFF); //E_UNEXPECTED } // As always we need to call the original method, note that EasyHook will automatically skip the hook and call the original method // i.e. calling it here will not cause a stack overflow into this function return(DXGISwapChain_PresentHook.Original(swapChainPtr, syncInterval, flags)); }
/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { this.Frame(); SwapChain3 swapChain = (SharpDX.DXGI.SwapChain3)swapChainPtr; //if (!init) //{ // InitText(swapChain); //} try { #region Screenshot Request //if (this.Request != null) //{ // this.DebugMessage("PresentHook: Request Start"); // DateTime startTime = DateTime.Now; // using (Texture2D texture = Texture2D.FromSwapChain<Texture2D>(swapChain, 0)) // { // #region Determine region to capture // System.Drawing.Rectangle regionToCapture = new System.Drawing.Rectangle(0, 0, texture.Description.Width, texture.Description.Height); // if (this.Request.RegionToCapture.Width > 0) // { // regionToCapture = this.Request.RegionToCapture; // } // #endregion // var theTexture = texture; // // If texture is multisampled, then we can use ResolveSubresource to copy it into a non-multisampled texture // Texture2D textureResolved = null; // if (texture.Description.SampleDescription.Count > 1) // { // this.DebugMessage("PresentHook: resolving multi-sampled texture"); // // texture is multi-sampled, lets resolve it down to single sample // textureResolved = new Texture2D(texture.Device, new Texture2DDescription() // { // CpuAccessFlags = CpuAccessFlags.None, // Format = texture.Description.Format, // Height = texture.Description.Height, // Usage = ResourceUsage.Default, // Width = texture.Description.Width, // ArraySize = 1, // SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), // Ensure single sample // BindFlags = BindFlags.None, // MipLevels = 1, // OptionFlags = texture.Description.OptionFlags // }); // // Resolve into textureResolved // texture.Device.ImmediateContext.ResolveSubresource(texture, 0, textureResolved, 0, texture.Description.Format); // // Make "theTexture" be the resolved texture // theTexture = textureResolved; // } // // Create destination texture // Texture2D textureDest = new Texture2D(texture.Device, new Texture2DDescription() // { // CpuAccessFlags = CpuAccessFlags.None,// CpuAccessFlags.Write | CpuAccessFlags.Read, // Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, // Supports BMP/PNG // Height = regionToCapture.Height, // Usage = ResourceUsage.Default,// ResourceUsage.Staging, // Width = regionToCapture.Width, // ArraySize = 1,//texture.Description.ArraySize, // SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),// texture.Description.SampleDescription, // BindFlags = BindFlags.None, // MipLevels = 1,//texture.Description.MipLevels, // OptionFlags = texture.Description.OptionFlags // }); // // Copy the subresource region, we are dealing with a flat 2D texture with no MipMapping, so 0 is the subresource index // theTexture.Device.ImmediateContext.CopySubresourceRegion(theTexture, 0, new ResourceRegion() // { // Top = regionToCapture.Top, // Bottom = regionToCapture.Bottom, // Left = regionToCapture.Left, // Right = regionToCapture.Right, // Front = 0, // Back = 1 // Must be 1 or only black will be copied // }, textureDest, 0, 0, 0, 0); // // Note: it would be possible to capture multiple frames and process them in a background thread // // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline // Guid requestId = this.Request.RequestId; // this.Request gets set to null, so copy the RequestId for use in the thread // ThreadPool.QueueUserWorkItem(delegate // { // //FileStream fs = new FileStream(@"c:\temp\temp.bmp", FileMode.Create); // //Texture2D.ToStream(testSubResourceCopy, ImageFileFormat.Bmp, fs); // DateTime startCopyToSystemMemory = DateTime.Now; // using (MemoryStream ms = new MemoryStream()) // { // Texture2D.ToStream(textureDest.Device.ImmediateContext, textureDest, ImageFileFormat.Bmp, ms); // ms.Position = 0; // this.DebugMessage("PresentHook: Copy to System Memory time: " + (DateTime.Now - startCopyToSystemMemory).ToString()); // DateTime startSendResponse = DateTime.Now; // ProcessCapture(ms, requestId); // this.DebugMessage("PresentHook: Send response time: " + (DateTime.Now - startSendResponse).ToString()); // } // // Free the textureDest as we no longer need it. // textureDest.Dispose(); // textureDest = null; // this.DebugMessage("PresentHook: Full Capture time: " + (DateTime.Now - startTime).ToString()); // }); // // Prevent the request from being processed a second time // this.Request = null; // // Make sure we free up the resolved texture if it was created // if (textureResolved != null) // { // textureResolved.Dispose(); // textureResolved = null; // } // } // this.DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime).ToString()); // this.DebugMessage("PresentHook: Request End"); //} #endregion #region Draw overlay (after screenshot so we don't capture overlay as well) if (this.Config.ShowOverlay) { // Initialise Overlay Engine if (_swapChainPointer != swapChain.NativePointer || _overlayEngine == null) { if (_overlayEngine != null) { _overlayEngine.Dispose(); } _overlayEngine = new DX11.DXOverlayEngine(); _overlayEngine.Overlays.Add(new Common.Overlay { Elements = { //new Common.TextElement(new System.Drawing.Font("Times New Roman", 22)) { Text = "Test", Location = new System.Drawing.Point(200, 200), Color = System.Drawing.Color.Yellow, AntiAliased = false}, new Common.FramesPerSecond(new System.Drawing.Font("Arial", 12)) { Location = new System.Drawing.Point(5, 5), Color = System.Drawing.Color.Red, AntiAliased = true }, //new Common.ProcessLoad(new System.Drawing.Font("Arial", 12)){ Location = new System.Drawing.Point(5,20), Color = System.Drawing.Color.Red, AntiAliased = true }, ProcessLoad } }); _overlayEngine.Initialise(swapChain); _swapChainPointer = swapChain.NativePointer; } // Draw Overlay(s) else if (_overlayEngine != null) { foreach (var overlay in _overlayEngine.Overlays) { overlay.Frame(); } _overlayEngine.Draw(); } //direct2DRenderTarget[frameIndex].BeginDraw(); //int time = Environment.TickCount % 10000; //int t = time / 2000; //float f = (time - (t * 2000)) / 2000.0F; //textBrush.Color = Color4.Lerp(colors[t], colors[t + 1], f); //direct2DRenderTarget[frameIndex].DrawText("Hello Text", textFormat, new SharpDX.Mathematics.Interop.RawRectangleF((float)Math.Sin(Environment.TickCount / 1000.0F) * 200 + 400, 10, 2000, 500), textBrush); //direct2DRenderTarget[frameIndex].EndDraw(); } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.ToString()); //return unchecked((int)0x8000FFFF); //E_UNEXPECTED } // As always we need to call the original method, note that EasyHook has already repatched the original method // so calling it here will not cause an endless recursion to this function swapChain.Present(syncInterval, flags); return(SharpDX.Result.Ok.Code); }
/// <summary> /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing) /// </summary> /// <param name="swapChainPtr"></param> /// <param name="syncInterval"></param> /// <param name="flags"></param> /// <returns>The HRESULT of the original method</returns> int PresentHook(IntPtr swapChainPtr, int syncInterval, SharpDX.DXGI.PresentFlags flags) { this.Frame(); SwapChain swapChain = (SharpDX.DXGI.SwapChain)swapChainPtr; { try { #region Screenshot Request //if (this.Request != null) //{ // try // { // this.DebugMessage("PresentHook: Request Start"); // DateTime startTime = DateTime.Now; // using (Texture2D texture = Texture2D.FromSwapChain<SharpDX.Direct3D10.Texture2D>(swapChain, 0)) // { // #region Determine region to capture // System.Drawing.Rectangle regionToCapture = new System.Drawing.Rectangle(0, 0, texture.Description.Width, texture.Description.Height); // if (this.Request.RegionToCapture.Width > 0) // { // regionToCapture = this.Request.RegionToCapture; // } // #endregion // var theTexture = texture; // // If texture is multisampled, then we can use ResolveSubresource to copy it into a non-multisampled texture // Texture2D textureResolved = null; // if (texture.Description.SampleDescription.Count > 1) // { // this.DebugMessage("PresentHook: resolving multi-sampled texture"); // // texture is multi-sampled, lets resolve it down to single sample // textureResolved = new Texture2D(texture.Device, new Texture2DDescription() // { // CpuAccessFlags = CpuAccessFlags.None, // Format = texture.Description.Format, // Height = texture.Description.Height, // Usage = ResourceUsage.Default, // Width = texture.Description.Width, // ArraySize = 1, // SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), // Ensure single sample // BindFlags = BindFlags.None, // MipLevels = 1, // OptionFlags = texture.Description.OptionFlags // }); // // Resolve into textureResolved // texture.Device.ResolveSubresource(texture, 0, textureResolved, 0, texture.Description.Format); // // Make "theTexture" be the resolved texture // theTexture = textureResolved; // } // // Create destination texture // Texture2D textureDest = new Texture2D(texture.Device, new Texture2DDescription() // { // CpuAccessFlags = CpuAccessFlags.None,// CpuAccessFlags.Write | CpuAccessFlags.Read, // Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, // Supports BMP/PNG // Height = regionToCapture.Height, // Usage = ResourceUsage.Default,// ResourceUsage.Staging, // Width = regionToCapture.Width, // ArraySize = 1,//texture.Description.ArraySize, // SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),// texture.Description.SampleDescription, // BindFlags = BindFlags.None, // MipLevels = 1,//texture.Description.MipLevels, // OptionFlags = texture.Description.OptionFlags // }); // // Copy the subresource region, we are dealing with a flat 2D texture with no MipMapping, so 0 is the subresource index // theTexture.Device.CopySubresourceRegion(theTexture, 0, new ResourceRegion() // { // Top = regionToCapture.Top, // Bottom = regionToCapture.Bottom, // Left = regionToCapture.Left, // Right = regionToCapture.Right, // Front = 0, // Back = 1 // Must be 1 or only black will be copied // }, textureDest, 0, 0, 0, 0); // // Note: it would be possible to capture multiple frames and process them in a background thread // // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline // Guid requestId = this.Request.RequestId; // this.Request gets set to null, so copy the RequestId for use in the thread // ThreadPool.QueueUserWorkItem(delegate // { // //FileStream fs = new FileStream(@"c:\temp\temp.bmp", FileMode.Create); // //Texture2D.ToStream(testSubResourceCopy, ImageFileFormat.Bmp, fs); // DateTime startCopyToSystemMemory = DateTime.Now; // using (MemoryStream ms = new MemoryStream()) // { // Texture2D.ToStream(textureDest, ImageFileFormat.Bmp, ms); // ms.Position = 0; // this.DebugMessage("PresentHook: Copy to System Memory time: " + (DateTime.Now - startCopyToSystemMemory).ToString()); // DateTime startSendResponse = DateTime.Now; // ProcessCapture(ms, requestId); // this.DebugMessage("PresentHook: Send response time: " + (DateTime.Now - startSendResponse).ToString()); // } // // Free the textureDest as we no longer need it. // textureDest.Dispose(); // textureDest = null; // this.DebugMessage("PresentHook: Full Capture time: " + (DateTime.Now - startTime).ToString()); // }); // // Make sure we free up the resolved texture if it was created // if (textureResolved != null) // { // textureResolved.Dispose(); // textureResolved = null; // } // } // this.DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime).ToString()); // this.DebugMessage("PresentHook: Request End"); // } // finally // { // // Prevent the request from being processed a second time // this.Request = null; // } //} #endregion #region Example: Draw overlay (after screenshot so we don't capture overlay as well) if (this.Config.ShowOverlay) { using (Texture2D texture = Texture2D.FromSwapChain <SharpDX.Direct3D10.Texture2D>(swapChain, 0)) { if (FPS.GetFPS() >= 1) { FontDescription fd = new SharpDX.Direct3D10.FontDescription() { Height = 16, FaceName = "Arial", Italic = false, Width = 0, MipLevels = 1, CharacterSet = SharpDX.Direct3D10.FontCharacterSet.Default, OutputPrecision = SharpDX.Direct3D10.FontPrecision.Default, Quality = SharpDX.Direct3D10.FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Bold }; // TODO: do not create font every frame! using (Font font = new Font(texture.Device, fd)) { DrawText(font, new Vector2(5, 5), String.Format("{0:N0} fps", FPS.GetFPS()), new Color4(Color.Red.ToColor3())); if (this.TextDisplay != null && this.TextDisplay.Display) { DrawText(font, new Vector2(5, 25), this.TextDisplay.Text, new Color4(Color.Red.ToColor3(), (Math.Abs(1.0f - TextDisplay.Remaining)))); } } } } } #endregion } catch (Exception e) { // If there is an error we do not want to crash the hooked application, so swallow the exception this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.Message); } // As always we need to call the original method, note that EasyHook has already repatched the original method // so calling it here will not cause an endless recursion to this function swapChain.Present(syncInterval, flags); return(SharpDX.Result.Ok.Code); } }