public FrameBufferSurface(Size size) { mDisplay = Display.Impl as SDX_Display; mDevice = mDisplay.D3D_Device; mSize = size; try { mTexture = new Texture(mDevice.Device, mSize.Width, mSize.Height, 0, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default); } catch { Size newSize = SDX_Surface.NextPowerOfTwo(mSize); mTexture = new Texture(mDevice.Device, newSize.Width, newSize.Height, 0, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default); } mRenderTarget = mTexture.GetSurfaceLevel(0); mAgateSurface = new SDX_Surface(new AgateLib.Utility.Ref <Texture>(mTexture), new Rectangle(Point.Empty, Size)); //SetHasDepthStencil( }
public FrameBufferWindow(Size size, SwapChain swap, AgateLib.DisplayLib.DisplayWindow attachedWindow, Direct3D.Surface backBuffer, Direct3D.Surface backDepthStencil) { mDisplay = (SDX_Display)AgateLib.DisplayLib.Display.Impl; mAttachedWindow = attachedWindow; mSize = size; mSwap = swap; mBackBuffer = backBuffer; mBackDepthStencil = backDepthStencil; if (mBackDepthStencil != null) { SetHasDepthStencil(mBackDepthStencil.Description.Format); } }
private void CreateBackBuffer(bool fullScreen) { if (mFrameBuffer != null) { mFrameBuffer.Dispose(); } // Created swap chain will be owned by the FrameBufferWindow object, and // disposal will be handled by that object. SwapChain swap = mDisplay.CreateSwapChain(this, mChooseWidth, mChooseHeight, mChooseBitDepth, fullScreen); Direct3D.Surface backBuffer = swap.GetBackBuffer(0); Direct3D.Surface backDepthStencil = Direct3D.Surface.CreateDepthStencil( mDisplay.D3D_Device.Device, mChooseWidth, mChooseHeight, mDisplay.DepthStencilFormat, MultisampleType.None, 0, true); mFrameBuffer = new FrameBufferWindow(Size, swap, mOwner, backBuffer, backDepthStencil); mRenderTarget.Resize += new EventHandler(mRenderTarget_Resize); }
/// <summary> /// Hook for IDirect3DDevice9.EndScene /// </summary> /// <param name="devicePtr">Pointer to the IDirect3DDevice9 instance. Note: object member functions always pass "this" as the first parameter.</param> /// <returns>The HRESULT of the original EndScene</returns> /// <remarks>Remember that this is called many times a second by the Direct3D application - be mindful of memory and performance!</remarks> int EndSceneHook(IntPtr devicePtr) { using (SlimDX.Direct3D9.Device device = SlimDX.Direct3D9.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 lock (_lockRenderTarget) { if (Request != null) { _lastRequestTime = DateTime.Now; DateTime start = DateTime.Now; try { // 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 = SlimDX.Direct3D9.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 (SlimDX.Direct3D9.Surface backBuffer = device.GetBackBuffer(0, 0)) { // Create a super fast copy of the back buffer on our Surface device.GetRenderTargetData(backBuffer, _renderTarget); // 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) if (this.ShowOverlay) { #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; } }
/// <summary> /// Reset the _renderTarget so that we are sure it will have the correct presentation parameters (required to support working across changes to windowed/fullscreen or resolution changes) /// </summary> /// <param name="devicePtr"></param> /// <param name="presentParameters"></param> /// <returns></returns> int ResetHook(IntPtr devicePtr, ref D3DPRESENT_PARAMETERS presentParameters) { using (SlimDX.Direct3D9.Device device = SlimDX.Direct3D9.Device.FromPointer(devicePtr)) { PresentParameters pp = new PresentParameters() { AutoDepthStencilFormat = (Format)presentParameters.AutoDepthStencilFormat, BackBufferCount = presentParameters.BackBufferCount, BackBufferFormat = (Format)presentParameters.BackBufferFormat, BackBufferHeight = presentParameters.BackBufferHeight, BackBufferWidth = presentParameters.BackBufferWidth, DeviceWindowHandle = presentParameters.DeviceWindowHandle, EnableAutoDepthStencil = presentParameters.EnableAutoDepthStencil, FullScreenRefreshRateInHertz = presentParameters.FullScreen_RefreshRateInHz, Multisample = (MultisampleType)presentParameters.MultiSampleType, MultisampleQuality = presentParameters.MultiSampleQuality, PresentationInterval = (PresentInterval)presentParameters.PresentationInterval, PresentFlags = (PresentFlags)presentParameters.Flags, SwapEffect = (SwapEffect)presentParameters.SwapEffect, Windowed = presentParameters.Windowed }; lock (_lockRenderTarget) { if (_renderTarget != null) { _renderTarget.Dispose(); _renderTarget = null; } } // EasyHook has already repatched the original Reset so calling it here will not cause an endless recursion to this function return device.Reset(pp).Code; } }
/// <summary> /// Just ensures that the surface we created is cleaned up. /// </summary> public override void Cleanup() { try { lock (_lockRenderTarget) { if (_renderTarget != null) { _renderTarget.Dispose(); _renderTarget = null; } Request = null; } } catch { } }
///<summary> /// Call this to associate a D3D surface with this pixel buffer ///</summary> public void Bind( D3D.Device device, D3D.Surface surface, bool update ) { this.device = device; this.surface = surface; D3D.SurfaceDescription desc = surface.Description; Width = desc.Width; Height = desc.Height; Depth = 1; Format = D3DHelper.ConvertEnum( desc.Format ); // Default RowPitch = Width; SlicePitch = Height * Width; sizeInBytes = PixelUtil.GetMemorySize( Width, Height, Depth, Format ); if ( ( (int)usage & (int)TextureUsage.RenderTarget ) != 0 ) CreateRenderTextures( update ); }
public D3DHardwarePixelBuffer( BufferUsage usage ) : base( 0, 0, 0, Axiom.Media.PixelFormat.Unknown, usage, false, false ) { device = null; surface = null; volume = null; tempSurface = null; tempVolume = null; doMipmapGen = false; HWMipmaps = false; mipTex = null; sliceTRT = new List<RenderTexture>(); }
/// <summary> /// Renders the sample. /// </summary> private void Render(bool isScreenshot) { if (deviceLost) { if (Context.Device.TestCooperativeLevel() == SlimDX.Direct3D9.ResultCode.DeviceNotReset) { Context.Device.Reset(Context.PresentParameters); deviceLost = false; userInterfaceRenderer = new UserInterfaceRenderer9(Context.Device, WindowWidth, WindowHeight); OnResourceLoad(); } else { Thread.Sleep(100); return; } } frameAccumulator += FrameDelta; ++frameCount; if (frameAccumulator >= 1.0f) { framesPerSecond.Value = frameCount / frameAccumulator; frameAccumulator = 0.0f; frameCount = 0; } SlimDX.Direct3D9.Surface renderTarget = null; try { if (isScreenshot) { renderTarget = Context.Device.GetRenderTarget(0); if (!Context.Direct3D.CheckDepthStencilMatch(0, DeviceType.Hardware, SlimDX.Direct3D9.Format.X8R8G8B8, SlimDX.Direct3D9.Format.A8R8G8B8, SlimDX.Direct3D9.Format.D24X8)) { throw new InvalidOperationException("DepthStencil mismatch"); } screenshotSurface = SlimDX.Direct3D9.Surface.CreateRenderTarget(Context.Device, WindowWidth, WindowHeight, SlimDX.Direct3D9.Format.A8R8G8B8, Context.MultisampleType, Context.MultisampleQuality, false); Context.Device.SetRenderTarget(0, screenshotSurface); } OnRenderBegin(isScreenshot); OnRender(); if (userInterfaceRenderer != null && isScreenshot == false) { userInterfaceRenderer.Render(userInterface); } OnRenderEnd(isScreenshot); if (isScreenshot) { string myPicturesPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures); string fileName = string.Format("ss{0}.png", System.DateTime.Now.ToFileTime()); string filePath = System.IO.Path.Combine(myPicturesPath, fileName); SlimDX.Direct3D9.Surface.ToFile(screenshotSurface, filePath, ImageFileFormat.Png); screenshotSurface.Dispose(); screenshotSurface = null; Context.Device.SetRenderTarget(0, renderTarget); } } catch (SlimDX.Direct3D9.Direct3D9Exception e) { if (screenshotSurface != null) { screenshotSurface.Dispose(); } if (e.ResultCode == SlimDX.Direct3D9.ResultCode.DeviceLost) { OnResourceUnload(); userInterfaceRenderer.Dispose(); deviceLost = true; } else { throw; } } finally { if (renderTarget != null) { renderTarget.Dispose(); } } }
public override object this[ string attribute ] { get { if ( attribute == "DDBACKBUFFER" ) { var surfaces = new D3D.Surface[ Config.MaxMultipleRenderTargets ]; // Transfer surfaces for ( var x = 0; x < Config.MaxMultipleRenderTargets; x++ ) { if ( this._targets[ x ] != null ) surfaces[ x ] = this._targets[ x ].Surface; } return surfaces; } return null; } }