/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> void DoCaptureRenderTarget(Device device, string hook) { this.Frame(); try { #region Screenshot Request // If we have issued the command to copy data to our render target, check if it is complete bool qryResult; if (_queryIssued && _requestCopy != null && _query.GetData(out qryResult, false)) { // The GPU has finished copying data to _renderTargetCopy, we can now lock // the data and access it on another thread. _queryIssued = false; // Lock the render target SharpDX.Rectangle rect; SharpDX.DataRectangle lockedRect = LockRenderTarget(_renderTargetCopy, out rect); _renderTargetCopyLocked = true; // Copy the data from the render target System.Threading.Tasks.Task.Factory.StartNew(() => { lock (_lockRenderTarget) { ProcessCapture(rect.Width, rect.Height, lockedRect.Pitch, _renderTargetCopy.Description.Format.ToPixelFormat(), lockedRect.DataPointer, _requestCopy); } }); } // Single frame capture request if (this.Request != null) { DateTime start = DateTime.Now; try { using (Surface renderTarget = device.GetRenderTarget(0)) { int width, height; // If resizing of the captured image, determine correct dimensions if (Request.Resize != null && (renderTarget.Description.Width > Request.Resize.Value.Width || renderTarget.Description.Height > Request.Resize.Value.Height)) { if (renderTarget.Description.Width > Request.Resize.Value.Width) { width = Request.Resize.Value.Width; height = (int)Math.Round((renderTarget.Description.Height * ((double)Request.Resize.Value.Width / (double)renderTarget.Description.Width))); } else { height = Request.Resize.Value.Height; width = (int)Math.Round((renderTarget.Description.Width * ((double)Request.Resize.Value.Height / (double)renderTarget.Description.Height))); } } else { width = renderTarget.Description.Width; height = renderTarget.Description.Height; } // If existing _renderTargetCopy, ensure that it is the correct size and format if (_renderTargetCopy != null && (_renderTargetCopy.Description.Width != width || _renderTargetCopy.Description.Height != height || _renderTargetCopy.Description.Format != renderTarget.Description.Format)) { // Cleanup resources Cleanup(); } // Ensure that we have something to put the render target data into if (!_resourcesInitialised || _renderTargetCopy == null) { CreateResources(device, width, height, renderTarget.Description.Format); } // Resize from render target Surface to resolvedSurface (also deals with resolving multi-sampling) device.StretchRectangle(renderTarget, _resolvedTarget, TextureFilter.None); } // If the render target is locked from a previous request unlock it if (_renderTargetCopyLocked) { // Wait for the the ProcessCapture thread to finish with it lock (_lockRenderTarget) { if (_renderTargetCopyLocked) { _renderTargetCopy.UnlockRectangle(); _renderTargetCopyLocked = false; } } } // Copy data from resolved target to our render target copy device.GetRenderTargetData(_resolvedTarget, _renderTargetCopy); _requestCopy = Request.Clone(); _query.Issue(Issue.End); _queryIssued = true; } 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(hook + ": Capture time: " + (end - start).ToString()); } #endregion if (this.Config.ShowOverlay) { #region Draw Overlay // Check if overlay needs to be initialised if (_overlayEngine == null || _overlayEngine.Device.NativePointer != device.NativePointer) { // Cleanup if necessary if (_overlayEngine != null) RemoveAndDispose(ref _overlayEngine); _overlayEngine = ToDispose(new DX9.DXOverlayEngine()); // Create Overlay _overlayEngine.Overlays.Add(new Capture.Hook.Common.Overlay { Elements = { // Add frame rate new Capture.Hook.Common.FramesPerSecond(new System.Drawing.Font("Arial", 14, FontStyle.Bold)) { Location = new System.Drawing.Point(5,5), Color = System.Drawing.Color.Red, AntiAliased = true }/*, new Capture.Hook.Common.TextElement(new System.Drawing.Font("Arial", 16, FontStyle.Bold)) { Location = new Point(20, 50), Color = Color.Yellow, Text = "Test" }*/ // Example of adding an image to overlay (can implement semi transparency with Tint, e.g. Ting = Color.FromArgb(127, 255, 255, 255)) //new Capture.Hook.Common.ImageElement(@"C:\Temp\test.bmp") { Location = new System.Drawing.Point(20, 20) } } }); _overlayEngine.Initialise(device); } // Draw Overlay(s) else if (_overlayEngine != null) { foreach (var overlay in _overlayEngine.Overlays) overlay.Frame(); _overlayEngine.Draw(); } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
private void HandleCaptureRequest(Device device) { try { for (int i = 0; i < BUFFERS; i++) { bool tmp; if (this.issuedQueries[i] && this.queries[i].GetData(out tmp, false)) { this.issuedQueries[i] = false; try { var lockedRect = this.surfaces[i].LockRectangle(LockFlags.ReadOnly); this.surfaceDataPointer = lockedRect.DataPointer; this.currentSurface = i; this.surfaceLocked[i] = true; } catch (Exception ex) { DebugMessage(ex.ToString()); } } } if (previousRequestId != null || lastRequestId != null) { this.previousRequestId = null; int nextCapture = (curCapture == BUFFERS - 1) ? 0 : (curCapture + 1); var sourceTexture = copySurfaces[curCapture]; try { using (var backbuffer = device.GetBackBuffer(0, 0)) { device.StretchRectangle(backbuffer, sourceTexture, TextureFilter.None); } if (copyWait < BUFFERS - 1) { copyWait++; } else { var prevSourceTexture = copySurfaces[nextCapture]; var targetTexture = surfaces[nextCapture]; if (this.surfaceLocked[nextCapture]) { lock (this.surfaceLocks[nextCapture]) { this.surfaces[nextCapture].UnlockRectangle(); this.surfaceLocked[nextCapture] = false; } } try { device.GetRenderTargetData(prevSourceTexture, targetTexture); } catch (Exception ex) { DebugMessage(ex.ToString()); } this.queries[nextCapture].Issue(Issue.End); this.issuedQueries[nextCapture] = true; } } catch (Exception ex) { this.DebugMessage(ex.ToString()); } curCapture = nextCapture; } } catch (Exception e) { this.DebugMessage(e.ToString()); } }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> private void DoCaptureRenderTarget(Device device, string hook) { Frame(); try { #region Screenshot Request // If we have issued the command to copy data to our render target, check if it is complete bool qryResult; if (_queryIssued && _requestCopy != null && _query.GetData(out qryResult, false)) { // The GPU has finished copying data to _renderTargetCopy, we can now lock // the data and access it on another thread. _queryIssued = false; // Lock the render target Rectangle rect; var lockedRect = LockRenderTarget(_renderTargetCopy, out rect); _renderTargetCopyLocked = true; // Copy the data from the render target Task.Factory.StartNew(() => { lock (_lockRenderTarget) { ProcessCapture(rect.Width, rect.Height, lockedRect.Pitch, _renderTargetCopy.Description.Format.ToPixelFormat(), lockedRect.DataPointer, _requestCopy); } }); } // Single frame capture request if (Request != null) { var start = DateTime.Now; try { using (var renderTarget = device.GetRenderTarget(0)) { int width, height; // If resizing of the captured image, determine correct dimensions if (Request.Resize != null && (renderTarget.Description.Width > Request.Resize.Value.Width || renderTarget.Description.Height > Request.Resize.Value.Height)) { if (renderTarget.Description.Width > Request.Resize.Value.Width) { width = Request.Resize.Value.Width; height = (int) Math.Round((renderTarget.Description.Height* (Request.Resize.Value.Width/ (double) renderTarget.Description.Width))); } else { height = Request.Resize.Value.Height; width = (int) Math.Round((renderTarget.Description.Width* (Request.Resize.Value.Height/ (double) renderTarget.Description.Height))); } } else { width = renderTarget.Description.Width; height = renderTarget.Description.Height; } // If existing _renderTargetCopy, ensure that it is the correct size and format if (_renderTargetCopy != null && (_renderTargetCopy.Description.Width != width || _renderTargetCopy.Description.Height != height || _renderTargetCopy.Description.Format != renderTarget.Description.Format)) { // Cleanup resources Cleanup(); } // Ensure that we have something to put the render target data into if (!_resourcesInitialised || _renderTargetCopy == null) { CreateResources(device, width, height, renderTarget.Description.Format); } // Resize from render target Surface to resolvedSurface (also deals with resolving multi-sampling) device.StretchRectangle(renderTarget, _resolvedTarget, TextureFilter.None); } // If the render target is locked from a previous request unlock it if (_renderTargetCopyLocked) { // Wait for the the ProcessCapture thread to finish with it lock (_lockRenderTarget) { if (_renderTargetCopyLocked) { _renderTargetCopy.UnlockRectangle(); _renderTargetCopyLocked = false; } } } // Copy data from resolved target to our render target copy device.GetRenderTargetData(_resolvedTarget, _renderTargetCopy); _requestCopy = Request.Clone(); _query.Issue(Issue.End); _queryIssued = true; } 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; } var end = DateTime.Now; DebugMessage(hook + ": Capture time: " + (end - start)); } #endregion if (Config.ShowOverlay) { #region Draw Overlay // Check if overlay needs to be initialised if (_overlayEngine == null || _overlayEngine.Device.NativePointer != device.NativePointer || IsOverlayUpdatePending) { // Cleanup if necessary if (_overlayEngine != null) _overlayEngine.Dispose(); _overlayEngine = ToDispose(new DXOverlayEngine()); // Create Overlay _overlayEngine.Overlays.Add(new Overlay { Elements = OverlayElements }); _overlayEngine.Initialise(device); IsOverlayUpdatePending = false; } // Draw Overlay(s) else if (_overlayEngine != null) { foreach (var overlay in _overlayEngine.Overlays) overlay.Frame(); _overlayEngine.Draw(); } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> void DoCaptureRenderTarget(Device device, string hook) { this.Frame(); try { #region Screenshot Request // Single frame capture request if (this.Request != null) { DateTime start = DateTime.Now; try { using (Surface renderTargetTemp = device.GetRenderTarget(0)) { int width, height; // TODO: If resizing the captured image is required it can be adjusted here //if (renderTargetTemp.Description.Width > 1280) //{ // width = 1280; // height = (int)Math.Round((renderTargetTemp.Description.Height * (1280.0 / renderTargetTemp.Description.Width))); //} //else { width = renderTargetTemp.Description.Width; height = renderTargetTemp.Description.Height; } // First ensure we have a Surface to the render target data into if (_renderTarget == null) { // Create offscreen surface to use as copy of render target data using (SwapChain sc = device.GetSwapChain(0)) { _renderTarget = Surface.CreateOffscreenPlain(device, width, height, sc.PresentParameters.BackBufferFormat, Pool.SystemMemory); } } // Create our resolved surface (resizing if necessary and to resolve any multi-sampling) using (Surface resolvedSurface = Surface.CreateRenderTarget(device, width, height, renderTargetTemp.Description.Format, MultisampleType.None, 0, false)) { // Resize from Render Surface to resolvedSurface device.StretchRectangle(renderTargetTemp, resolvedSurface, TextureFilter.None); // Get Render Data device.GetRenderTargetData(resolvedSurface, _renderTarget); } } if (Request != null) 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(hook + ": Capture time: " + (end - start).ToString()); } #endregion if (this.Config.ShowOverlay) { #region Draw frame rate // TODO: font needs to be created and then reused, not created each frame! using (SharpDX.Direct3D9.Font font = new SharpDX.Direct3D9.Font(device, new FontDescription() { Height = 16, FaceName = "Arial", Italic = false, Width = 0, MipLevels = 1, CharacterSet = FontCharacterSet.Default, OutputPrecision = FontPrecision.Default, Quality = FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Bold })) { if (this.FPS.GetFPS() >= 1) { font.DrawText(null, String.Format("{0:N0} fps", this.FPS.GetFPS()), 5, 5, SharpDX.Color.Red); } if (this.TextDisplay != null && this.TextDisplay.Display) { font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); } } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
private void HandleCaptureRequest(Device device) { try { bool tmp; if (this.queryIssued && this.query.GetData(out tmp, false)) { this.queryIssued = false; var lockedRect = this.surface.LockRectangle(LockFlags.ReadOnly); this.surfaceDataPointer = lockedRect.DataPointer; this.surfaceLocked = true; this.copyEvent.Set(); } using (var backbuffer = device.GetBackBuffer(0, 0)) { device.StretchRectangle(backbuffer, this.renderTarget, TextureFilter.None); } if (this.surfaceLocked) { lock (this.renderTargetLock) { if (this.surfaceLocked) { this.surface.UnlockRectangle(); this.surfaceLocked = false; } } } try { var cooplevel = device.TestCooperativeLevel(); if (cooplevel.Code == ResultCode.Success.Code) { device.GetRenderTargetData(this.renderTarget, this.surface); this.query.Issue(Issue.End); this.queryIssued = true; } else { this.DebugMessage(string.Format("DirectX Error: TestCooperativeLevel = {0}", cooplevel.Code)); } } catch (Exception ex) { this.DebugMessage(ex.ToString()); } } catch (Exception e) { this.DebugMessage(e.ToString()); } }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> void DoCaptureRenderTarget(Device device, string hook) { this.Frame(); try { #region Screenshot Request // If we have issued the command to copy data to our render target, check if it is complete bool qryResult; if (_queryIssued && _requestCopy != null && _query.GetData(out qryResult, false)) { // The GPU has finished copying data to _renderTargetCopy, we can now lock // the data and access it on another thread. _queryIssued = false; // Lock the render target SharpDX.Rectangle rect; SharpDX.DataRectangle lockedRect = LockRenderTarget(_renderTargetCopy, out rect); _renderTargetCopyLocked = true; // Copy the data from the render target System.Threading.Tasks.Task.Factory.StartNew(() => { lock (_lockRenderTarget) { ProcessCapture(rect.Width, rect.Height, lockedRect.Pitch, _renderTargetCopy.Description.Format.ToPixelFormat(), lockedRect.DataPointer, _requestCopy); } }); } // Single frame capture request if (this.Request != null) { DateTime start = DateTime.Now; try { using (Surface renderTarget = device.GetRenderTarget(0)) { int width, height; // If resizing of the captured image, determine correct dimensions if (Request.Resize != null && (renderTarget.Description.Width > Request.Resize.Value.Width || renderTarget.Description.Height > Request.Resize.Value.Height)) { if (renderTarget.Description.Width > Request.Resize.Value.Width) { width = Request.Resize.Value.Width; height = (int)Math.Round((renderTarget.Description.Height * ((double)Request.Resize.Value.Width / (double)renderTarget.Description.Width))); } else { height = Request.Resize.Value.Height; width = (int)Math.Round((renderTarget.Description.Width * ((double)Request.Resize.Value.Height / (double)renderTarget.Description.Height))); } } else { width = renderTarget.Description.Width; height = renderTarget.Description.Height; } // If existing _renderTargetCopy, ensure that it is the correct size and format if (_renderTargetCopy != null && (_renderTargetCopy.Description.Width != width || _renderTargetCopy.Description.Height != height || _renderTargetCopy.Description.Format != renderTarget.Description.Format)) { // Cleanup resources Cleanup(); } // Ensure that we have something to put the render target data into if (!_resourcesInitialised || _renderTargetCopy == null) { CreateResources(device, width, height, renderTarget.Description.Format); } // Resize from render target Surface to resolvedSurface (also deals with resolving multi-sampling) device.StretchRectangle(renderTarget, _resolvedTarget, TextureFilter.None); } // If the render target is locked from a previous request unlock it if (_renderTargetCopyLocked) { // Wait for the the ProcessCapture thread to finish with it lock (_lockRenderTarget) { if (_renderTargetCopyLocked) { _renderTargetCopy.UnlockRectangle(); _renderTargetCopyLocked = false; } } } // Copy data from resolved target to our render target copy device.GetRenderTargetData(_resolvedTarget, _renderTargetCopy); _requestCopy = Request.Clone(); _query.Issue(Issue.End); _queryIssued = true; } 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(hook + ": Capture time: " + (end - start).ToString()); } #endregion if (this.Config.ShowOverlay) { #region Draw frame rate if (_font == null || _font.Device.NativePointer != device.NativePointer) CreateFont(device); if (this.FPS.GetFPS() >= 1) { _font.DrawText(null, String.Format("{0:N0} fps", this.FPS.GetFPS()), 5, 5, SharpDX.Color.Red); } if (this.TextDisplay != null && this.TextDisplay.Display) { _font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
private void HandleCaptureRequest(Device device) { if (Request == null) { return; } try { bool tmp; if (queryIssued && query.GetData(out tmp, false)) { queryIssued = false; var lockedRect = surface.LockRectangle(LockFlags.ReadOnly); surfaceDataPointer = lockedRect.DataPointer; surfaceLocked = true; new Thread(HandleCaptureRequestThread).Start(); } using (var backbuffer = device.GetBackBuffer(0, 0)) { device.StretchRectangle(backbuffer, renderTarget, TextureFilter.None); } if (surfaceLocked) { lock (renderTargetLock) { if (!this.surfaceLocked) { return; } this.surface.UnlockRectangle(); this.surfaceLocked = false; } } try { device.GetRenderTargetData(renderTarget, surface); query.Issue(Issue.End); queryIssued = true; } catch (Exception ex) { DebugMessage(ex.ToString()); } } catch (Exception e) { DebugMessage(e.ToString()); } }
private void HandleCaptureRequest(Device device) { try { if (_killThread) { return; } for (var i = 0; i < BUFFERS; i++) { bool tmp; if (_issuedQueries[i] && _queries[i].GetData(out tmp, false)) { _issuedQueries[i] = false; var lockedRect = _surfaces[i].LockRectangle(LockFlags.ReadOnly); _surfaceDataPointer = lockedRect.DataPointer; _currentSurface = i; _surfaceLocked[i] = true; _copyReadySignal.Set(); } } if (_captureWaitHandle.WaitOne(0) || _copyWait < BUFFERS - 1) { var nextCapture = (_curCapture == BUFFERS - 1) ? 0 : (_curCapture + 1); try { using (var backbuffer = device.GetBackBuffer(0, 0)) { var sourceTexture = _copySurfaces[_curCapture]; device.StretchRectangle(backbuffer, sourceTexture, TextureFilter.None); } if (_copyWait < BUFFERS - 1) { _copyWait++; } else { var prevSourceTexture = _copySurfaces[nextCapture]; var targetTexture = _surfaces[nextCapture]; if (_surfaceLocked[nextCapture]) { lock (_surfaceLocks[nextCapture]) { _surfaces[nextCapture].UnlockRectangle(); _surfaceLocked[nextCapture] = false; } } try { device.GetRenderTargetData(prevSourceTexture, targetTexture); } catch (Exception ex) { DebugMessage(ex.ToString()); } _queries[nextCapture].Issue(Issue.End); _issuedQueries[nextCapture] = true; } } catch (Exception ex) { DebugMessage(ex.ToString()); } finally { _captureWaitHandle.Reset(); _curCapture = nextCapture; } } } catch (Exception e) { DebugMessage(e.ToString()); } }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> void DoCaptureRenderTarget(Device device, string hook) { try { #region Screenshot Request // Single frame capture request if (this.Request != null) { DateTime start = DateTime.Now; try { using (Surface renderTargetTemp = device.GetRenderTarget(0)) { int width, height; // TODO: If resizing the captured image is required it can be adjusted here //if (renderTargetTemp.Description.Width > 1280) //{ // width = 1280; // height = (int)Math.Round((renderTargetTemp.Description.Height * (1280.0 / renderTargetTemp.Description.Width))); //} //else { width = renderTargetTemp.Description.Width; height = renderTargetTemp.Description.Height; } // First ensure we have a Surface to the render target data into if (_renderTarget == null) { // Create offscreen surface to use as copy of render target data using (SwapChain sc = device.GetSwapChain(0)) { _renderTarget = Surface.CreateOffscreenPlain(device, width, height, sc.PresentParameters.BackBufferFormat, Pool.SystemMemory); } } // Create our resolved surface (resizing if necessary and to resolve any multi-sampling) using ( Surface resolvedSurface = Surface.CreateRenderTarget(device, width, height, renderTargetTemp.Description.Format, MultisampleType.None, 0, false)) { // Resize from Render Surface to resolvedSurface device.StretchRectangle(renderTargetTemp, resolvedSurface, TextureFilter.None); // Get Render Data device.GetRenderTargetData(resolvedSurface, _renderTarget); } } if (Request != null) { 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(hook + ": Capture time: " + (end - start).ToString()); } #endregion if (this.Config.ShowOverlay) { // SHIT this.Frame(); #region Draw frame rate // TODO: font needs to be created and then reused, not created each frame! using (var font = new SharpDX.Direct3D9.Font(device, new FontDescription() { Height = 26, FaceName = "Quartz MS", Italic = false, Width = 0, MipLevels = 1, CharacterSet = FontCharacterSet.Default, OutputPrecision = FontPrecision.Default, Quality = FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Normal })) { // Make a Texture from a file... using (FileStream myFileStream = new FileStream(@"baronbutton.png", System.IO.FileMode.Open)) { mytexStream = SharpDX.Direct3D9.Texture.FromStream(device, myFileStream); } Sprite spritezor = new SharpDX.Direct3D9.Sprite(device); spritezor.Begin(SharpDX.Direct3D9.SpriteFlags.None); var baronPos = new Vector3(1476, 812, 0); spritezor.Draw(mytexStream, new ColorBGRA(0xffffffff), null, null, baronPos); // Display always... if (this.Config.TestThisShit != 0) { // Draw sprite... spritezor.End(); spritezor.Dispose(); // Oritinal Text before sprites worked... //font.DrawText(null, "Timer 1", 5, 10, SharpDX.Color.Lime); } // Display on Timer... if (this.TextDisplay != null && this.TextDisplay.Display) { font.DrawText(null, this.TextDisplay.Text, 1477, 870, new SharpDX.ColorBGRA(255, 0, 0, 255)); // Alternate font for timers pulsed with alpha fading between ticks... // font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); } /* DXHookD3D9 Original statements to draw the FPS... * if (this.FPS.GetFPS() >= 1) * { * font.DrawText(null, String.Format("{0:N0} fps", this.FPS.GetFPS()), 5, 5, SharpDX.Color.Red); * } * if (this.TextDisplay != null && this.TextDisplay.Display) * { * font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); * } */ } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
public void createScreenShot(String screenShotName, double positionSeconds, String videoLocation, int offsetSeconds) { lock (renderLock) { if (device == null) { return; } int width = offscreen.Description.Width; int height = offscreen.Description.Height; Rectangle sourceSize = new Rectangle(0, 0, width, height); Rectangle destSize = calcOutputAspectRatio(sourceSize); if (screenShot.Description.Width != destSize.Width || screenShot.Description.Height != destSize.Height) { Utils.removeAndDispose(ref screenShot); screenShot = D3D.Surface.CreateRenderTarget(device, destSize.Width, destSize.Height, D3D.Format.A8R8G8B8, MultisampleType.None, 0, true); } SharpDX.Rectangle sourceSizeDX = new SharpDX.Rectangle(0, 0, sourceSize.Width, sourceSize.Height); SharpDX.Rectangle destSizeDX = new SharpDX.Rectangle(0, 0, destSize.Width, destSize.Height); device.StretchRectangle(offscreen, sourceSizeDX, screenShot, destSizeDX, D3D.TextureFilter.Linear); SharpDX.DataRectangle stream = screenShot.LockRectangle(destSizeDX, D3D.LockFlags.ReadOnly); try { JpegBitmapEncoder encoder = new JpegBitmapEncoder(); BitmapMetadata metaData = new BitmapMetadata("jpg"); UriBuilder uri = new UriBuilder(new Uri(videoLocation).AbsoluteUri); int seconds = (int)Math.Floor(Math.Max(positionSeconds + offsetSeconds, 0)); TimeSpan time = new TimeSpan(0, 0, seconds); String timeString = ""; if (time.Days > 0) { timeString += time.Days + "d"; } if (time.Hours > 0) { timeString += time.Hours + "h"; } if (time.Minutes > 0) { timeString += time.Minutes + "m"; } timeString += time.Seconds + "s"; uri.Query = "t=" + timeString; metaData.ApplicationName = "MediaViewer v1.0"; metaData.Title = uri.ToString(); metaData.DateTaken = DateTime.Now.ToString("R"); BitmapSource image = System.Windows.Media.Imaging.BitmapSource.Create( destSize.Width, destSize.Height, 96, 96, System.Windows.Media.PixelFormats.Bgra32, null, stream.DataPointer, height * stream.Pitch, stream.Pitch ); float scale = ImageUtils.resizeRectangle(destSize.Width, destSize.Height, Constants.MAX_THUMBNAIL_WIDTH, Constants.MAX_THUMBNAIL_HEIGHT); TransformedBitmap thumbnail = new TransformedBitmap(image, new System.Windows.Media.ScaleTransform(scale, scale)); encoder.Frames.Add(BitmapFrame.Create(image, thumbnail, metaData, null)); FileStream outputFile = new FileStream(screenShotName, FileMode.Create); //encoder.QualityLevel = asyncState.JpegQuality; encoder.Save(outputFile); outputFile.Close(); System.Media.SystemSounds.Exclamation.Play(); } catch (Exception e) { throw new VideoPlayerException("Error creating screenshot: " + e.Message, e); } finally { screenShot.UnlockRectangle(); } } }
/// <summary> /// Implementation of capturing from the render target of the Direct3D9 Device (or DeviceEx) /// </summary> /// <param name="device"></param> void DoCaptureRenderTarget(Device device, string hook) { try { #region Screenshot Request // Single frame capture request if (this.Request != null) { DateTime start = DateTime.Now; try { using (Surface renderTargetTemp = device.GetRenderTarget(0)) { int width, height; // TODO: If resizing the captured image is required it can be adjusted here //if (renderTargetTemp.Description.Width > 1280) //{ // width = 1280; // height = (int)Math.Round((renderTargetTemp.Description.Height * (1280.0 / renderTargetTemp.Description.Width))); //} //else { width = renderTargetTemp.Description.Width; height = renderTargetTemp.Description.Height; } // First ensure we have a Surface to the render target data into if (_renderTarget == null) { // Create offscreen surface to use as copy of render target data using (SwapChain sc = device.GetSwapChain(0)) { _renderTarget = Surface.CreateOffscreenPlain(device, width, height, sc.PresentParameters.BackBufferFormat, Pool.SystemMemory); } } // Create our resolved surface (resizing if necessary and to resolve any multi-sampling) using ( Surface resolvedSurface = Surface.CreateRenderTarget(device, width, height, renderTargetTemp.Description.Format, MultisampleType.None, 0, false)) { // Resize from Render Surface to resolvedSurface device.StretchRectangle(renderTargetTemp, resolvedSurface, TextureFilter.None); // Get Render Data device.GetRenderTargetData(resolvedSurface, _renderTarget); } } if (Request != null) 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(hook + ": Capture time: " + (end - start).ToString()); } #endregion if (this.Config.ShowOverlay) { // SHIT this.Frame(); #region Draw frame rate // TODO: font needs to be created and then reused, not created each frame! using (var font = new SharpDX.Direct3D9.Font(device, new FontDescription() { Height = 26, FaceName = "Quartz MS", Italic = false, Width = 0, MipLevels = 1, CharacterSet = FontCharacterSet.Default, OutputPrecision = FontPrecision.Default, Quality = FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Normal })) { // Make a Texture from a file... using (FileStream myFileStream = new FileStream(@"baronbutton.png", System.IO.FileMode.Open)) { mytexStream = SharpDX.Direct3D9.Texture.FromStream(device, myFileStream); } Sprite spritezor = new SharpDX.Direct3D9.Sprite(device); spritezor.Begin(SharpDX.Direct3D9.SpriteFlags.None); var baronPos = new Vector3(1476, 812, 0); spritezor.Draw(mytexStream, new ColorBGRA(0xffffffff), null, null, baronPos); // Display always... if (this.Config.TestThisShit != 0) { // Draw sprite... spritezor.End(); spritezor.Dispose(); // Oritinal Text before sprites worked... //font.DrawText(null, "Timer 1", 5, 10, SharpDX.Color.Lime); } // Display on Timer... if (this.TextDisplay != null && this.TextDisplay.Display) { font.DrawText(null, this.TextDisplay.Text, 1477, 870, new SharpDX.ColorBGRA(255, 0, 0, 255)); // Alternate font for timers pulsed with alpha fading between ticks... // font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); } /* DXHookD3D9 Original statements to draw the FPS... if (this.FPS.GetFPS() >= 1) { font.DrawText(null, String.Format("{0:N0} fps", this.FPS.GetFPS()), 5, 5, SharpDX.Color.Red); } if (this.TextDisplay != null && this.TextDisplay.Display) { font.DrawText(null, this.TextDisplay.Text, 5, 25, new SharpDX.ColorBGRA(255, 0, 0, (byte)Math.Round((Math.Abs(1.0f - TextDisplay.Remaining) * 255f)))); } */ } #endregion } } catch (Exception e) { DebugMessage(e.ToString()); } }
private void DoCaptureRenderTarget(Device device, string hook) { try { if (isCapturing && signalEnd.WaitOne(0)) { ClearD3D9Data(); isCapturing = false; stopRequested = true; } if (!isCapturing) { return; } if (!bHasTextures) { using (Surface backbuffer = device.GetRenderTarget(0)) { copyData.format = (int)backbuffer.Description.Format; copyData.width = backbuffer.Description.Width; copyData.height = backbuffer.Description.Height; } DoD3DHooks(device); } if (!bHasTextures) { return; } long timeVal = DateTime.Now.Ticks; long frameTime = 1000000 / targetFps; // lock at 30 fps if (frameTime != 0) { for (var i = 0; i < NUM_BUFFERS; i++) { if (issuedQueries[i]) { bool tmp; if (queries[i].GetData(out tmp, false)) { issuedQueries[i] = false; Surface targetTexture = textures[i]; try { var lockedRect = targetTexture.LockRectangle(LockFlags.ReadOnly); pCopyData = lockedRect.DataPointer; curCPUTexture = i; lockedTextures[i] = true; hCopyEvent.Set(); } catch (Exception ex) { DebugMessage(ex.ToString()); } } } } long timeElapsed = timeVal - lastTime; if (timeElapsed >= frameTime) { lastTime += frameTime; if (timeElapsed > frameTime * 2) { lastTime = timeVal; } var nextCapture = (curCapture == NUM_BUFFERS - 1) ? 0 : (curCapture + 1); Surface sourceTexture = copyD3D9Textures[curCapture]; using (var backbuffer = device.GetBackBuffer(0, 0)) { device.StretchRectangle(backbuffer, sourceTexture, TextureFilter.None); } if (copyWait < (NUM_BUFFERS - 1)) { copyWait++; } else { Surface prevSourceTexture = copyD3D9Textures[nextCapture]; Surface targetTexture = textures[nextCapture]; if (lockedTextures[nextCapture]) { Monitor.Enter(dataMutexes[nextCapture]); targetTexture.UnlockRectangle(); lockedTextures[nextCapture] = false; Monitor.Exit(dataMutexes[nextCapture]); } try { device.GetRenderTargetData(prevSourceTexture, targetTexture); } catch (Exception ex) { DebugMessage(ex.ToString()); } queries[nextCapture].Issue(Issue.End); issuedQueries[nextCapture] = true; } curCapture = nextCapture; } } } catch (Exception e) { DebugMessage("Error in PresentHook: " + e); } }