Ejemplo n.º 1
0
    public DwmCapture(IntPtr hWnd)
    {
        _captureHwnd = hWnd;

        #region Initialise the Direct3D device

        int adapterOrdinal = 0;

        _d3dEx       = new Direct3DEx();
        _adapterLuid = _d3dEx.GetAdapterLuid(adapterOrdinal);

        var presentParams = new PresentParameters
        {
            PresentFlags     = PresentFlags.LockableBackBuffer,
            Windowed         = true,
            BackBufferFormat = Format.A8R8G8B8,
            SwapEffect       = SwapEffect.Flip
        };

        _deviceEx = new DeviceEx(_d3dEx, adapterOrdinal, DeviceType.Hardware, _captureHwnd, SlimDX.Direct3D9.CreateFlags.Multithreaded | SlimDX.Direct3D9.CreateFlags.SoftwareVertexProcessing, presentParams);

        #endregion

        #region Setup the shared surface (using DWM)

        uint   format        = 0;
        IntPtr pSharedHandle = IntPtr.Zero;
        int    hr            = NativeMethods.GetSharedSurface(_captureHwnd, _adapterLuid, 0, 0, ref format, out pSharedHandle, 0);
        NativeMethods.UpdateWindowShared(_captureHwnd, 0, 0, 0, IntPtr.Zero, IntPtr.Zero);

        RECT winRect;
        NativeMethods.GetWindowRect(_captureHwnd, out winRect);

        Size size = new Size(winRect.Right - winRect.Left, winRect.Bottom - winRect.Top);

        /* Hack because SlimDX does not let you specify a shared handle for creating shared resources we
         * have to create an IDirect3DDevice9 reference to the device instead */
        IDirect3DDevice9 devEx = (IDirect3DDevice9)Marshal.GetObjectForIUnknown(_deviceEx.ComPointer);
        IntPtr           pTexture;
        devEx.CreateTexture((int)size.Width, (int)size.Height, 1, 1, format, 0, out pTexture, ref pSharedHandle);
        Texture texture = Texture.FromPointer(pTexture);

        _sharedSurface = texture.GetSurfaceLevel(0);

        _renderTarget = Surface.CreateRenderTarget(_deviceEx, (int)size.Width, (int)size.Height, Format.X8R8G8B8,
                                                   MultisampleType.None, 0, false);

        _deviceEx.SetRenderTarget(0, _renderTarget);

        Surface.FromSurface(_renderTarget, _sharedSurface, Filter.None, 0);

        _systemMemorySurface = Surface.CreateOffscreenPlain(_deviceEx, (int)size.Width, (int)size.Height,
                                                            Format.X8R8G8B8, Pool.SystemMemory);

        #endregion
    }
Ejemplo n.º 2
0
        /// <summary>
        /// The InitializeDevice method is called by the Video Mixing Renderer 9 (VMR-9)
        /// when it needs the allocator-presenter to allocate surfaces.
        /// </summary>
        /// <param name="userId">
        /// Application-defined identifier. This value is the same value that the application
        /// passed to the IVMRSurfaceAllocatorNotify9.AdviseSurfaceAllocator method in the
        /// dwUserID parameter.
        /// </param>
        /// <param name="lpAllocInfo">
        /// Pointer to a VMR9AllocationInfo structure that contains a description of the surfaces to create.
        /// </param>
        /// <param name="lpNumBuffers">
        /// On input, specifies the number of surfaces to create. When the method returns,
        /// this parameter contains the number of buffers that were actually allocated.
        /// </param>
        /// <returns>Returns an HRESULT code</returns>
        public int InitializeDevice(IntPtr userId, ref VMR9AllocationInfo lpAllocInfo, ref int lpNumBuffers)
        {
            if (m_allocatorNotify == null)
            {
                return(E_FAIL);
            }

            try
            {
                int hr;

                lock (m_staticLock)
                {
                    /* These two pointers are passed to the the helper
                     * to create our D3D surfaces */
                    var pDevice  = GetComPointer(m_device);
                    var pMonitor = GetAdapterMonitor(0);

                    /* Setup our D3D Device with our renderer */
                    hr = m_allocatorNotify.SetD3DDevice(pDevice, pMonitor);
                    DsError.ThrowExceptionForHR(hr);

                    /* This is only used if the AllocateSurfaceHelper is used */
                    lpAllocInfo.dwFlags |= VMR9SurfaceAllocationFlags.TextureSurface;

                    /* Make sure our old surfaces are free'd */
                    FreeSurfaces();

                    /* This is an IntPtr array of pointers to D3D surfaces */
                    DxSurfaces = new IntPtr[lpNumBuffers];

                    /* This is where the magic happens, surfaces are allocated */
                    hr = m_allocatorNotify.AllocateSurfaceHelper(ref lpAllocInfo, ref lpNumBuffers, DxSurfaces);

                    if (hr < 0)
                    {
                        FreeSurfaces();


                        if (lpAllocInfo.Format > 0)
                        {
                            hr = m_device.CreateTexture(lpAllocInfo.dwWidth,
                                                        lpAllocInfo.dwHeight,
                                                        1,
                                                        1,
                                                        D3DFORMAT.D3DFMT_X8R8G8B8,
                                                        0,
                                                        out m_privateTexture,
                                                        IntPtr.Zero);

                            DsError.ThrowExceptionForHR(hr);

                            hr = m_privateTexture.GetSurfaceLevel(0, out m_privateSurface);
                            DsError.ThrowExceptionForHR(hr);
                        }

                        lpAllocInfo.dwFlags &= ~VMR9SurfaceAllocationFlags.TextureSurface;
                        lpAllocInfo.dwFlags |= VMR9SurfaceAllocationFlags.OffscreenSurface;

                        DxSurfaces = new IntPtr[lpNumBuffers];

                        hr = m_allocatorNotify.AllocateSurfaceHelper(ref lpAllocInfo,
                                                                     ref lpNumBuffers,
                                                                     DxSurfaces);
                        if (hr < 0)
                        {
                            FreeSurfaces();
                            return(hr);
                        }
                    }
                }

                /* Nofity to our listeners we have new surfaces */
                InvokeNewSurfaceEvent(m_privateSurface != null ? GetComPointer(m_privateSurface) : DxSurfaces[0]);

                return(hr);
            }
            catch
            {
                return(E_FAIL);
            }
        }