/// <summary> /// Releases reference to all allocated D3D surfaces /// </summary> private void FreeSurfaces() { lock (m_instanceLock) { if (m_privateSurface != null) { Marshal.ReleaseComObject(m_privateSurface); m_privateSurface = null; } if (m_privateTexture != null) { Marshal.ReleaseComObject(m_privateTexture); m_privateTexture = null; } if (DxSurfaces != null) { foreach (var ptr in DxSurfaces) { if (ptr != IntPtr.Zero) { /* Release COM reference */ Marshal.Release(ptr); } } } /* Make sure we uninitialize the pointer array * so the rest of our code knows it is invalid */ DxSurfaces = null; } }
public void Dispose() { GC.SuppressFinalize(this); SafeRelease(m_pDevice); m_pDevice = null; SafeRelease(m_pSurfaceRepaint); m_pSurfaceRepaint = null; SafeRelease(m_pDeviceManager); m_pDeviceManager = null; SafeRelease(m_pD3D9); m_pD3D9 = null; }
//----------------------------------------------------------------------------- // PresentSwapChain // // Presents a swap chain that contains a video frame. // // pSwapChain: Pointer to the swap chain. // pSurface: Pointer to the swap chain's back buffer surface. // // Note: This method simply calls IDirect3DSwapChain9::Present, but a derived // class could do something fancier. //----------------------------------------------------------------------------- protected void PresentSwapChain(IDirect3DSwapChain9 pSwapChain, IDirect3DSurface9 pSurface) { if (m_hwnd == IntPtr.Zero) { throw new COMException("D3DPresentEngine::PresentSwapChain", (int)HResult.MF_E_INVALIDREQUEST); } pSwapChain.Present(null, m_rcDestRect, m_hwnd, null, 0); m_iFrames++; }
protected MFRect m_rcDestRect; // Destination rectangle. #endregion Fields #region Constructors public D3DPresentEngine() { m_iFrames = 0; m_hwnd = IntPtr.Zero; m_DeviceResetToken = 0; m_pD3D9 = null; m_pDevice = null; m_pDeviceManager = null; m_pSurfaceRepaint = null; m_rcDestRect = new MFRect(); m_DisplayMode = new D3DDISPLAYMODE(); InitializeD3D(); CreateD3DDevice(); }
protected IDirect3DSurface9 m_pSurfaceRepaint; // Surface for repaint requests. #endregion public D3DPresentEngine() { m_iFrames = 0; m_hwnd = IntPtr.Zero; m_DeviceResetToken = 0; m_pD3D9 = null; m_pDevice = null; m_pDeviceManager = null; m_pSurfaceRepaint = null; m_rcDestRect = new MFRect(); m_DisplayMode = new D3DDISPLAYMODE(); InitializeD3D(); CreateD3DDevice(); }
//----------------------------------------------------------------------------- // CreateD3DSample // // Creates an sample object (IMFSample) to hold a Direct3D swap chain. //----------------------------------------------------------------------------- protected void CreateD3DSample(IDirect3DSwapChain9 pSwapChain, out IMFSample ppVideoSample) { HResult hr; IDirect3DSurface9 pSurface = null; // Caller holds the object lock. try { // Get the back buffer surface. pSwapChain.GetBackBuffer(0, D3DBACKBUFFER_TYPE.Mono, out pSurface); // Create the sample. hr = MFExtern.MFCreateVideoSampleFromSurface(pSurface, out ppVideoSample); MFError.ThrowExceptionForHR(hr); } finally { SafeRelease(pSurface); pSurface = null; } }
//----------------------------------------------------------------------------- // PresentSample // // Presents a video frame. // // pSample: Pointer to the sample that contains the surface to present. If // this parameter is NULL, the method paints a black rectangle. // llTarget: Target presentation time. // // This method is called by the scheduler and/or the presenter. //----------------------------------------------------------------------------- public void PresentSample(IMFSample pSample, long llTarget) { HResult hr; IMFMediaBuffer pBuffer = null; IDirect3DSurface9 pSurface = null; IDirect3DSwapChain9 pSwapChain = null; object o; try { if (pSample != null) { // Get the buffer from the sample. hr = pSample.GetBufferByIndex(0, out pBuffer); MFError.ThrowExceptionForHR(hr); // Get the surface from the buffer. hr = MFExtern.MFGetService(pBuffer, MFServices.MR_BUFFER_SERVICE, typeof(IDirect3DSurface9).GUID, out o); MFError.ThrowExceptionForHR(hr); pSurface = o as IDirect3DSurface9; } else if (m_pSurfaceRepaint != null) { // Redraw from the last surface. pSurface = m_pSurfaceRepaint; } if (pSurface != null) { // Get the swap chain from the surface. pSurface.GetContainer(typeof(IDirect3DSwapChain9).GUID, out o); pSwapChain = o as IDirect3DSwapChain9; // Present the swap chain. PresentSwapChain(pSwapChain, pSurface); // Store this pointer in case we need to repaint the surface. if (m_pSurfaceRepaint != pSurface) { SafeRelease(m_pSurfaceRepaint); m_pSurfaceRepaint = pSurface; } } else { // No surface. All we can do is paint a black rectangle. PaintFrameWithGDI(); } } catch (Exception e) { hr = (HResult)Marshal.GetHRForException(e); if (hr == (HResult)D3DError.DeviceLost || hr == (HResult)D3DError.DeviceNotReset || hr == (HResult)D3DError.DeviceHung) { // We failed because the device was lost. Fill the destination rectangle. PaintFrameWithGDI(); // Ignore. We need to reset or re-create the device, but this method // is probably being called from the scheduler thread, which is not the // same thread that created the device. The Reset(Ex) method must be // called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() // on the next sample. } } finally { SafeRelease(pSwapChain); pSwapChain = null; //SafeRelease(pSurface); pSurface = null; SafeRelease(pBuffer); pBuffer = null; } }
//----------------------------------------------------------------------------- // ReleaseResources // // Released Direct3D resources used by this object. //----------------------------------------------------------------------------- public void ReleaseResources() { SafeRelease(m_pSurfaceRepaint); m_pSurfaceRepaint = null; m_iFrames = 0; }
//----------------------------------------------------------------------------- // PresentSwapChain // // Presents a swap chain that contains a video frame. // // pSwapChain: Pointer to the swap chain. // pSurface: Pointer to the swap chain's back buffer surface. // // Note: This method simply calls IDirect3DSwapChain9::Present, but a derived // class could do something fancier. //----------------------------------------------------------------------------- protected void PresentSwapChain(IDirect3DSwapChain9 pSwapChain, IDirect3DSurface9 pSurface) { if (m_hwnd == IntPtr.Zero) { throw new COMException("D3DPresentEngine::PresentSwapChain", MFError.MF_E_INVALIDREQUEST); } pSwapChain.Present(null, m_rcDestRect, m_hwnd, null, 0); m_iFrames++; }
//----------------------------------------------------------------------------- // PresentSample // // Presents a video frame. // // pSample: Pointer to the sample that contains the surface to present. If // this parameter is NULL, the method paints a black rectangle. // llTarget: Target presentation time. // // This method is called by the scheduler and/or the presenter. //----------------------------------------------------------------------------- public void PresentSample(IMFSample pSample, long llTarget) { int hr; IMFMediaBuffer pBuffer = null; IDirect3DSurface9 pSurface = null; IDirect3DSwapChain9 pSwapChain = null; object o; try { if (pSample != null) { // Get the buffer from the sample. hr = pSample.GetBufferByIndex(0, out pBuffer); MFError.ThrowExceptionForHR(hr); // Get the surface from the buffer. hr = MFExtern.MFGetService(pBuffer, MFServices.MR_BUFFER_SERVICE, typeof(IDirect3DSurface9).GUID, out o); MFError.ThrowExceptionForHR(hr); pSurface = o as IDirect3DSurface9; } else if (m_pSurfaceRepaint != null) { // Redraw from the last surface. pSurface = m_pSurfaceRepaint; } if (pSurface != null) { // Get the swap chain from the surface. pSurface.GetContainer(typeof(IDirect3DSwapChain9).GUID, out o); pSwapChain = o as IDirect3DSwapChain9; // Present the swap chain. PresentSwapChain(pSwapChain, pSurface); // Store this pointer in case we need to repaint the surface. if (m_pSurfaceRepaint != pSurface) { SafeRelease(m_pSurfaceRepaint); m_pSurfaceRepaint = pSurface; } } else { // No surface. All we can do is paint a black rectangle. PaintFrameWithGDI(); } } catch (Exception e) { hr = Marshal.GetHRForException(e); if (hr == (int)D3DError.DeviceLost || hr == (int)D3DError.DeviceNotReset || hr == (int)D3DError.DeviceHung) { // We failed because the device was lost. Fill the destination rectangle. PaintFrameWithGDI(); // Ignore. We need to reset or re-create the device, but this method // is probably being called from the scheduler thread, which is not the // same thread that created the device. The Reset(Ex) method must be // called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() // on the next sample. } } finally { SafeRelease(pSwapChain); pSwapChain = null; //SafeRelease(pSurface); pSurface = null; SafeRelease(pBuffer); pBuffer = null; } }
/// <summary> /// Releases reference to all allocated D3D surfaces /// </summary> private void FreeSurfaces() { lock (m_instanceLock) { if(m_privateSurface != null) { Marshal.ReleaseComObject(m_privateSurface); m_privateSurface = null; } if (m_privateTexture != null) { Marshal.ReleaseComObject(m_privateTexture); m_privateTexture = null; } if (DxSurfaces != null) { foreach (var ptr in DxSurfaces) { if (ptr != IntPtr.Zero) { /* Release COM reference */ Marshal.Release(ptr); } } } /* Make sure we uninitialize the pointer array * so the rest of our code knows it is invalid */ DxSurfaces = null; } }
/// <summary> /// Allows an application to fill a rectangular area of a D3DPOOL_DEFAULT surface with a specified color. /// </summary> /// <remarks> /// This method can only be applied to a render target, a render-target texture surface, or an off-screen plain surface with a pool type of D3DPOOL_DEFAULT. IDirect3DDevice9::ColorFill will work with all formats. However, when using a reference or software device, the only formats supported are D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_YUY2, D3DFMT_G8R8_G8B8, D3DFMT_UYVY, D3DFMT_R8G8_B8G8, D3DFMT_R16F, D3DFMT_G16R16F, D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F, and D3DFMT_A32B32G32R32F. When using a DirectX 7 or DirectX 8.x driver, the only YUV formats supported are D3DFMT_UYVY and D3DFMT_YUY2. /// </remarks> /// <param name="surface"> Pointer to the surface to be filled. </param> /// <param name="color"> Color used for filling. </param> public void ColorFill(IDirect3DSurface9 surface, in Color color)