From 3e177e42502de0781d4d883ef15cffad149b30f2 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Mon, 25 Sep 2023 15:18:05 +0800 Subject: [PATCH] refactor --- .../BetterGenshinImpact.Win32.csproj | 20 +++ BetterGenshinImpact.Win32/NativeMethods.json | 7 ++ BetterGenshinImpact.Win32/NativeMethods.txt | 25 ++++ BetterGenshinImpact.sln | 6 + .../BetterGenshinImpact.csproj | 6 +- Vision.WindowCapture/BitBlt/BitBltCapture.cs | 45 +++---- .../GraphicsCapture/GraphicsCapture.cs | 36 ++---- .../GraphicsCapture/Helpers/CaptureHelper.cs | 89 +++++--------- .../Helpers/Direct3D11Helper.cs | 115 +++++++----------- .../Helpers/Texture2DExtensions.cs | 80 +++++------- .../GraphicsCapture/Helpers/WinRT.cs | 115 ------------------ Vision.WindowCapture/IWindowCapture.cs | 18 +-- .../Vision.WindowCapture.csproj | 9 +- Vision.WindowCapture/WindowCaptureFactory.cs | 61 ++++------ 14 files changed, 241 insertions(+), 391 deletions(-) create mode 100644 BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj create mode 100644 BetterGenshinImpact.Win32/NativeMethods.json create mode 100644 BetterGenshinImpact.Win32/NativeMethods.txt delete mode 100644 Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs diff --git a/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj b/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj new file mode 100644 index 00000000..56db0fdd --- /dev/null +++ b/BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + enable + enable + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/BetterGenshinImpact.Win32/NativeMethods.json b/BetterGenshinImpact.Win32/NativeMethods.json new file mode 100644 index 00000000..c26e5346 --- /dev/null +++ b/BetterGenshinImpact.Win32/NativeMethods.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/CsWin32/main/src/Microsoft.Windows.CsWin32/settings.schema.json", + "allowMarshaling": true, + "useSafeHandles": false, + "emitSingleFile": true, + "public": true +} \ No newline at end of file diff --git a/BetterGenshinImpact.Win32/NativeMethods.txt b/BetterGenshinImpact.Win32/NativeMethods.txt new file mode 100644 index 00000000..6d93a35b --- /dev/null +++ b/BetterGenshinImpact.Win32/NativeMethods.txt @@ -0,0 +1,25 @@ +// D3D11 +CreateDirect3D11DeviceFromDXGIDevice +CreateDirect3D11SurfaceFromDXGISurface + +// GDI32 +BitBlt +CreateCompatibleBitmap +CreateCompatibleDC +DeleteDC +SelectObject + +// User32 +GetWindowDC +GetWindowRect +ReleaseDC + +// COM & WinRT +D3D11CreateDevice +ID3D11Device3 +IDirect3DDxgiInterfaceAccess +IGraphicsCaptureItem +IGraphicsCaptureItemInterop + +// Constants +D3D11_SDK_VERSION diff --git a/BetterGenshinImpact.sln b/BetterGenshinImpact.sln index 2d9b197c..b16a7af1 100644 --- a/BetterGenshinImpact.sln +++ b/BetterGenshinImpact.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.WindowCapture", "Vis EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.Recognition", "Vision.Recognition\Vision.Recognition.csproj", "{97A12A37-613B-4BE3-B01B-BF3411503711}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterGenshinImpact.Win32", "BetterGenshinImpact.Win32\BetterGenshinImpact.Win32.csproj", "{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {97A12A37-613B-4BE3-B01B-BF3411503711}.Debug|Any CPU.Build.0 = Debug|Any CPU {97A12A37-613B-4BE3-B01B-BF3411503711}.Release|Any CPU.ActiveCfg = Release|Any CPU {97A12A37-613B-4BE3-B01B-BF3411503711}.Release|Any CPU.Build.0 = Release|Any CPU + {75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index 2553f418..fb561ce0 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -10,8 +10,10 @@ - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Vision.WindowCapture/BitBlt/BitBltCapture.cs b/Vision.WindowCapture/BitBlt/BitBltCapture.cs index ad5163fb..4dc39d6d 100644 --- a/Vision.WindowCapture/BitBlt/BitBltCapture.cs +++ b/Vision.WindowCapture/BitBlt/BitBltCapture.cs @@ -1,23 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics; using System.Drawing; -using System.Linq; -using System.Reflection.Metadata; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Vanara.Extensions; -using Vanara.PInvoke; +using Windows.Win32.Foundation; +using Windows.Win32.Graphics.Gdi; +using static Windows.Win32.PInvoke; namespace Vision.WindowCapture.BitBlt { public class BitBltCapture : IWindowCapture { - private IntPtr _hWnd; + private HWND _hWnd; + public bool IsCapturing { get; private set; } - public void Start(IntPtr hWnd) + public void Start(HWND hWnd) { _hWnd = hWnd; IsCapturing = true; @@ -32,21 +27,21 @@ namespace Vision.WindowCapture.BitBlt try { - User32.GetWindowRect(_hWnd, out var windowRect); + GetWindowRect(_hWnd, out var windowRect); var width = windowRect.Width; var height = windowRect.Height; - var hdcSrc = User32.GetWindowDC(_hWnd); - var hdcDest = Gdi32.CreateCompatibleDC(hdcSrc); - var hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height); - var hOld = Gdi32.SelectObject(hdcDest, hBitmap); - Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.RasterOperationMode.SRCCOPY); - Gdi32.SelectObject(hdcDest, hOld); - Gdi32.DeleteDC(hdcDest); - User32.ReleaseDC(_hWnd, hdcSrc); - - var bitmap = hBitmap.ToBitmap(); - Gdi32.DeleteObject(hBitmap); + var hdcSrc = GetWindowDC(_hWnd); + var hdcDest = CreateCompatibleDC(hdcSrc); + var hBitmap = CreateCompatibleBitmap(hdcSrc, width, height); + var hOld = SelectObject(hdcDest, hBitmap); + Windows.Win32.PInvoke.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, ROP_CODE.SRCCOPY); + SelectObject(hdcDest, hOld); + DeleteDC(hdcDest); + ReleaseDC(_hWnd, hdcSrc); + + var bitmap = Image.FromHbitmap(hBitmap); + DeleteObject(hBitmap); return bitmap; } catch (Exception e) @@ -58,7 +53,7 @@ namespace Vision.WindowCapture.BitBlt public void Stop() { - _hWnd = IntPtr.Zero; + _hWnd = HWND.Null; IsCapturing = false; } } diff --git a/Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs b/Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs index e281f4fe..c8b461c5 100644 --- a/Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs +++ b/Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs @@ -1,32 +1,22 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Reflection.Metadata.Ecma335; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using System.Drawing; using Vision.WindowCapture.GraphicsCapture.Helpers; -using Windows.Devices.HumanInterfaceDevice; using Windows.Graphics.Capture; using Windows.Graphics.DirectX; -using Windows.Graphics.DirectX.Direct3D11; -using SharpDX.Direct3D11; -using WinRT.Interop; +using Windows.Win32.Foundation; namespace Vision.WindowCapture.GraphicsCapture { public class GraphicsCapture : IWindowCapture { - private IntPtr _hWnd; + private HWND _hWnd; - private Direct3D11CaptureFramePool _captureFramePool; - private GraphicsCaptureItem _captureItem; - private GraphicsCaptureSession _captureSession; + private Direct3D11CaptureFramePool? _captureFramePool; + private GraphicsCaptureItem? _captureItem; + private GraphicsCaptureSession? _captureSession; public bool IsCapturing { get; private set; } - public void Start(IntPtr hWnd) + public void Start(HWND hWnd) { _hWnd = hWnd; IsCapturing = true; @@ -47,7 +37,7 @@ namespace Vision.WindowCapture.GraphicsCapture throw new InvalidOperationException("Failed to create capture item."); } - _captureItem.Closed += CaptureItemOnClosed; + _captureItem.Closed += OnCaptureItemClosed; var device = Direct3D11Helper.CreateDevice(); @@ -72,15 +62,15 @@ namespace Vision.WindowCapture.GraphicsCapture { _captureSession?.Dispose(); _captureFramePool?.Dispose(); - _captureSession = null; - _captureFramePool = null; - _captureItem = null; + _captureSession = default; + _captureFramePool = default; + _captureItem = default; - _hWnd = IntPtr.Zero; + _hWnd = HWND.Null; IsCapturing = false; } - private void CaptureItemOnClosed(GraphicsCaptureItem sender, object args) + private void OnCaptureItemClosed(GraphicsCaptureItem sender, object args) { Stop(); } diff --git a/Vision.WindowCapture/GraphicsCapture/Helpers/CaptureHelper.cs b/Vision.WindowCapture/GraphicsCapture/Helpers/CaptureHelper.cs index e0513189..eb7dca86 100644 --- a/Vision.WindowCapture/GraphicsCapture/Helpers/CaptureHelper.cs +++ b/Vision.WindowCapture/GraphicsCapture/Helpers/CaptureHelper.cs @@ -22,67 +22,40 @@ // THE SOFTWARE. // --------------------------------------------------------------------------------- -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.System.WinRT.Graphics.Capture; using Windows.Graphics.Capture; -using WinRT; +using WinRT.Interop; -namespace Vision.WindowCapture.GraphicsCapture.Helpers +namespace Vision.WindowCapture.GraphicsCapture.Helpers; + +public static class CaptureHelper { - public static class CaptureHelper + static readonly Guid GraphicsCaptureItemGuid = Guid.Parse("79C3F95B-31F7-4EC2-A464-632EF5D30760"); + + public static void SetWindow(this GraphicsCapturePicker picker, IntPtr hwnd) { - static readonly Guid GraphicsCaptureItemGuid = new Guid("79C3F95B-31F7-4EC2-A464-632EF5D30760"); - - [ComImport] - [Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComVisible(true)] - interface IInitializeWithWindow - { - void Initialize( - IntPtr hwnd); - } - - [ComImport] - [Guid("3628E81B-3CAC-4C60-B7F4-23CE0E0C3356")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComVisible(true)] - interface IGraphicsCaptureItemInterop - { - IntPtr CreateForWindow( - [In] IntPtr window, - [In] ref Guid iid); - - IntPtr CreateForMonitor( - [In] IntPtr monitor, - [In] ref Guid iid); - } - - public static void SetWindow(this GraphicsCapturePicker picker, IntPtr hwnd) - { - var interop = picker.As(); - interop.Initialize(hwnd); - } - - public static GraphicsCaptureItem CreateItemForWindow(IntPtr hwnd) - { - var factory = WinrtModule.GetActivationFactory("Windows.Graphics.Capture.GraphicsCaptureItem"); - var interop = factory.AsInterface(); - var itemPointer = interop.CreateForWindow(hwnd, GraphicsCaptureItemGuid); - return GraphicsCaptureItem.FromAbi(itemPointer); - } - - //public static GraphicsCaptureItem CreateItemForMonitor(IntPtr hmon) - //{ - // var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem)); - // var interop = (IGraphicsCaptureItemInterop)factory; - // var temp = typeof(GraphicsCaptureItem); - // var itemPointer = interop.CreateForMonitor(hmon, GraphicsCaptureItemGuid); - // var item = Marshal.GetObjectForIUnknown(itemPointer) as GraphicsCaptureItem; - // Marshal.Release(itemPointer); - - // return item; - //} + InitializeWithWindow.Initialize(picker, hwnd); } + + public static GraphicsCaptureItem CreateItemForWindow(HWND hwnd) + { + GraphicsCaptureItem + .As() + .CreateForWindow(hwnd, GraphicsCaptureItemGuid, out var obj); + return (GraphicsCaptureItem)obj; + } + + //public static GraphicsCaptureItem CreateItemForMonitor(IntPtr hmon) + //{ + // var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem)); + // var interop = (IGraphicsCaptureItemInterop)factory; + // var temp = typeof(GraphicsCaptureItem); + // var itemPointer = interop.CreateForMonitor(hmon, GraphicsCaptureItemGuid); + // var item = Marshal.GetObjectForIUnknown(itemPointer) as GraphicsCaptureItem; + // Marshal.Release(itemPointer); + + // return item; + //} } diff --git a/Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs b/Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs index 480696cd..0bd4561b 100644 --- a/Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs +++ b/Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs @@ -22,11 +22,15 @@ // THE SOFTWARE. // --------------------------------------------------------------------------------- -using System; -using System.Drawing; using System.Runtime.InteropServices; using Windows.Graphics.DirectX.Direct3D11; +using Windows.Win32; +using Windows.Win32.Graphics.Direct3D; +using Windows.Win32.Graphics.Direct3D11; +using Windows.Win32.Graphics.Dxgi; +using Windows.Win32.System.WinRT.Direct3D11; using WinRT; +using static Windows.Win32.PInvoke; namespace Vision.WindowCapture.GraphicsCapture.Helpers { @@ -35,106 +39,69 @@ namespace Vision.WindowCapture.GraphicsCapture.Helpers static Guid IInspectable = new Guid("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90"); static Guid ID3D11Resource = new Guid("dc8e63f3-d12b-4952-b47b-5e45026a862d"); static Guid IDXGIAdapter3 = new Guid("645967A4-1392-4310-A798-8053CE3E93FD"); - static Guid ID3D11Device = new Guid("db6f6ddb-ac77-4e88-8253-819df9bbf140"); + //static Guid ID3D11Device = new Guid("db6f6ddb-ac77-4e88-8253-819df9bbf140"); static Guid ID3D11Texture2D = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); - [ComImport] - [Guid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComVisible(true)] - interface IDirect3DDxgiInterfaceAccess - { - IntPtr GetInterface([In] ref Guid iid); - }; - - [DllImport( - "d3d11.dll", - EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice", - SetLastError = true, - CharSet = CharSet.Unicode, - ExactSpelling = true, - CallingConvention = CallingConvention.StdCall - )] - static extern UInt32 CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice); - - [DllImport( - "d3d11.dll", - EntryPoint = "CreateDirect3D11SurfaceFromDXGISurface", - SetLastError = true, - CharSet = CharSet.Unicode, - ExactSpelling = true, - CallingConvention = CallingConvention.StdCall - )] - static extern UInt32 CreateDirect3D11SurfaceFromDXGISurface(IntPtr dxgiSurface, out IntPtr graphicsSurface); - public static IDirect3DDevice CreateDevice() { return CreateDevice(false); } - public static IDirect3DDevice CreateDevice(bool useWARP) + public static unsafe IDirect3DDevice? CreateDevice(bool useWARP) { - var d3dDevice = new SharpDX.Direct3D11.Device( - useWARP ? SharpDX.Direct3D.DriverType.Software : SharpDX.Direct3D.DriverType.Hardware, - SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport); - var device = CreateDirect3DDeviceFromSharpDXDevice(d3dDevice); - return device; + D3D_DRIVER_TYPE driverType = useWARP ? D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_SOFTWARE : D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE; + D3D11CreateDevice( + default, + driverType, + default, + D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT, + default, + D3D11_SDK_VERSION, + out ID3D11Device? d3d11Device, + default, + out _); + + return CreateDirect3DDeviceFromD3D11Device(d3d11Device); } - public static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device d3dDevice) + public static IDirect3DDevice? CreateDirect3DDeviceFromD3D11Device(ID3D11Device d3d11Device) { - IDirect3DDevice device = null; - // Acquire the DXGI interface for the Direct3D device. - using (var dxgiDevice = d3dDevice.QueryInterface()) + // Wrap the native device using a WinRT interop object. + if (CreateDirect3D11DeviceFromDXGIDevice(d3d11Device.As(), out Windows.Win32.System.WinRT.IInspectable iInspectable).Succeeded) { - // Wrap the native device using a WinRT interop object. - uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown); - - if (hr == 0) - { - device = MarshalInterface.FromAbi(pUnknown); - Marshal.Release(pUnknown); - } + return iInspectable.As(); } - return device; + return default; } - public static IDirect3DSurface CreateDirect3DSurfaceFromSharpDXTexture(SharpDX.Direct3D11.Texture2D texture) + public static IDirect3DSurface? CreateDirect3DSurfaceFromSharpDXTexture(ID3D11Texture2D texture) { - IDirect3DSurface surface = null; - // Acquire the DXGI interface for the Direct3D surface. - using (var dxgiSurface = texture.QueryInterface()) + // Wrap the native device using a WinRT interop object. + if (CreateDirect3D11SurfaceFromDXGISurface(texture.As(), out Windows.Win32.System.WinRT.IInspectable iInspectable).Succeeded) { - // Wrap the native device using a WinRT interop object. - uint hr = CreateDirect3D11SurfaceFromDXGISurface(dxgiSurface.NativePointer, out IntPtr pUnknown); - - if (hr == 0) - { - surface = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DSurface; - Marshal.Release(pUnknown); - } + return iInspectable.As(); } - return surface; + return default; } - public static SharpDX.Direct3D11.Device CreateSharpDXDevice(IDirect3DDevice device) + public static ID3D11Device CreateD3D11Device(IDirect3DDevice device) { - var access = (IDirect3DDxgiInterfaceAccess)device; - var d3dPointer = access.GetInterface(ID3D11Device); - var d3dDevice = new SharpDX.Direct3D11.Device(d3dPointer); - return d3dDevice; + device + .As() + .GetInterface(typeof(ID3D11Device).GUID, out var d3dDevice); + return d3dDevice.As(); } - public static SharpDX.Direct3D11.Texture2D CreateSharpDXTexture2D(IDirect3DSurface surface) + public static ID3D11Texture2D CreateD3D11Texture2D(IDirect3DSurface surface) { - var access = surface.As(); - var d3dPointer = access.GetInterface(ID3D11Texture2D); - var d3dSurface = new SharpDX.Direct3D11.Texture2D(d3dPointer); - return d3dSurface; + surface + .As() + .GetInterface(typeof(ID3D11Texture2D).GUID, out var d3dSurface); + return d3dSurface.As(); } } } diff --git a/Vision.WindowCapture/GraphicsCapture/Helpers/Texture2DExtensions.cs b/Vision.WindowCapture/GraphicsCapture/Helpers/Texture2DExtensions.cs index 5cd120c7..617f6ff9 100644 --- a/Vision.WindowCapture/GraphicsCapture/Helpers/Texture2DExtensions.cs +++ b/Vision.WindowCapture/GraphicsCapture/Helpers/Texture2DExtensions.cs @@ -1,65 +1,51 @@ -using SharpDX; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using System; -using System.Collections.Generic; -using System.Drawing; +using System.Drawing; using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; using Windows.Graphics.Capture; -using Windows.Graphics.DirectX.Direct3D11; -using Windows.Graphics.Imaging; -using Windows.Storage.Streams; -using Vision.WindowCapture.GraphicsCapture.Helpers; +using Windows.Win32; +using Windows.Win32.Graphics.Direct3D11; +using Windows.Win32.Graphics.Dxgi.Common; using WinRT; namespace Vision.WindowCapture.GraphicsCapture.Helpers { public static class Texture2DExtensions { - public static Bitmap? ToBitmap(this Direct3D11CaptureFrame frame) + public static unsafe Bitmap ToBitmap(this Direct3D11CaptureFrame frame) { - var texture2dBitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface); + var texture2dBitmap = Direct3D11Helper.CreateD3D11Texture2D(frame.Surface); - var d3dDevice = texture2dBitmap.Device; + texture2dBitmap.GetDevice(out var d3dDevice); + texture2dBitmap.GetDesc(out D3D11_TEXTURE2D_DESC desc); + D3D11_TEXTURE2D_DESC newDesc = new() + { + Width = (uint)frame.ContentSize.Width, + Height = (uint)frame.ContentSize.Height, + MipLevels = 1U, + ArraySize = 1U, + Format = desc.Format, + Usage = D3D11_USAGE.D3D11_USAGE_STAGING, + SampleDesc = new DXGI_SAMPLE_DESC() { Count = 1 }, + CPUAccessFlags = D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ, + }; // Create texture copy - var staging = new Texture2D(d3dDevice, new Texture2DDescription - { - Width = frame.ContentSize.Width, - Height = frame.ContentSize.Height, - MipLevels = 1, - ArraySize = 1, - Format = texture2dBitmap.Description.Format, - Usage = ResourceUsage.Staging, - SampleDescription = new SampleDescription(1, 0), - BindFlags = BindFlags.None, - CpuAccessFlags = CpuAccessFlags.Read, - OptionFlags = ResourceOptionFlags.None - }); + d3dDevice.CreateTexture2D(newDesc, default, out ID3D11Texture2D staging); + d3dDevice.GetImmediateContext(out ID3D11DeviceContext context); - try - { - // Copy data - d3dDevice.ImmediateContext.CopyResource(texture2dBitmap, staging); + // Copy data + context.CopyResource(texture2dBitmap, staging); + D3D11_MAPPED_SUBRESOURCE subResource = default; + context.Map(staging, default, D3D11_MAP.D3D11_MAP_READ, default, &subResource); - var dataBox = d3dDevice.ImmediateContext.MapSubresource(staging, 0, 0, MapMode.Read, - SharpDX.Direct3D11.MapFlags.None, - out DataStream stream); + staging.GetDesc(out var stagingDesc); + var bitmap = new Bitmap( + (int)stagingDesc.Width, + (int)stagingDesc.Height, + (int)subResource.RowPitch, + PixelFormat.Format32bppArgb, + (nint)subResource.pData); - var bitmap = new Bitmap(staging.Description.Width, staging.Description.Height, dataBox.RowPitch, - PixelFormat.Format32bppArgb, dataBox.DataPointer); - - return bitmap; - } - finally - { - staging.Dispose(); - } + return bitmap; } //public static Stream ToBitmapStream(this Direct3D11CaptureFrame frame) diff --git a/Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs b/Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs deleted file mode 100644 index d632a06b..00000000 --- a/Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Reflection; -using System.Runtime.InteropServices; -using WinRT; - -namespace Vision.WindowCapture.GraphicsCapture.Helpers -{ - [ComImport] - [Guid( "3628E81B-3CAC-4C60-B7F4-23CE0E0C3356" )] - [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] - internal interface IGraphicsCaptureItemInterop - { - int CreateForWindow( [In] IntPtr window, [In] ref Guid iid, out IntPtr result ); - - int CreateForMonitor( [In] IntPtr monitor, [In] ref Guid iid, out IntPtr result ); - } - - [Guid( "00000035-0000-0000-C000-000000000046" )] - internal unsafe struct IActivationFactoryVftbl - { -#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value - public readonly IInspectable.Vftbl IInspectableVftbl; - private readonly void* _ActivateInstance; -#pragma warning restore - - public delegate* unmanaged[Stdcall]< IntPtr, IntPtr*, int > ActivateInstance => (delegate* unmanaged[Stdcall]< IntPtr, IntPtr*, int >)_ActivateInstance; - } - - internal class Platform - { - [DllImport( "api-ms-win-core-com-l1-1-0.dll" )] - internal static extern int CoDecrementMTAUsage( IntPtr cookie ); - - [DllImport( "api-ms-win-core-com-l1-1-0.dll" )] - internal static extern unsafe int CoIncrementMTAUsage( IntPtr* cookie ); - - [DllImport( "api-ms-win-core-winrt-l1-1-0.dll" )] - internal static extern unsafe int RoGetActivationFactory( IntPtr runtimeClassId, ref Guid iid, IntPtr* factory ); - } - - /// - /// https://github.com/zlatanov/windows-screen-recorder - /// - internal static class WinrtModule - { - private static readonly Dictionary> Cache = new Dictionary>(); - - public static ObjectReference GetActivationFactory( string runtimeClassId ) - { - lock ( Cache ) - { - if ( Cache.TryGetValue( runtimeClassId, out var factory ) ) - return factory; - - var m = MarshalString.CreateMarshaler( runtimeClassId ); - - try - { - var instancePtr = GetActivationFactory( MarshalString.GetAbi( m ) ); - - factory = ObjectReference.Attach( ref instancePtr ); - Cache.Add( runtimeClassId, factory ); - - return factory; - } - finally - { - m.Dispose(); - } - } - } - - private static unsafe IntPtr GetActivationFactory( IntPtr hstrRuntimeClassId ) - { - if ( s_cookie == IntPtr.Zero ) - { - lock ( s_lock ) - { - if ( s_cookie == IntPtr.Zero ) - { - IntPtr cookie; - Marshal.ThrowExceptionForHR( Platform.CoIncrementMTAUsage( &cookie ) ); - - s_cookie = cookie; - } - } - } - - Guid iid = typeof( IActivationFactoryVftbl ).GUID; - IntPtr instancePtr; - int hr = Platform.RoGetActivationFactory( hstrRuntimeClassId, ref iid, &instancePtr ); - - if ( hr == 0 ) - return instancePtr; - - throw new Win32Exception( hr ); - } - - public static bool ResurrectObjectReference( IObjectReference objRef ) - { - var disposedField = objRef.GetType().GetField( "disposed", BindingFlags.NonPublic | BindingFlags.Instance )!; - if ( !(bool)disposedField.GetValue( objRef )! ) - return false; - disposedField.SetValue( objRef, false ); - GC.ReRegisterForFinalize( objRef ); - return true; - } - - private static IntPtr s_cookie; - private static readonly object s_lock = new object(); - } -} diff --git a/Vision.WindowCapture/IWindowCapture.cs b/Vision.WindowCapture/IWindowCapture.cs index b58085c2..b95aa07c 100644 --- a/Vision.WindowCapture/IWindowCapture.cs +++ b/Vision.WindowCapture/IWindowCapture.cs @@ -1,15 +1,15 @@ using System.Drawing; +using Windows.Win32.Foundation; -namespace Vision.WindowCapture +namespace Vision.WindowCapture; + +public interface IWindowCapture { - public interface IWindowCapture - { - bool IsCapturing { get; } - - void Start(IntPtr hWnd); + bool IsCapturing { get; } + + void Start(HWND hWnd); - Bitmap? Capture(); + Bitmap? Capture(); - void Stop(); - } + void Stop(); } \ No newline at end of file diff --git a/Vision.WindowCapture/Vision.WindowCapture.csproj b/Vision.WindowCapture/Vision.WindowCapture.csproj index c5e426bd..2d2cfa5a 100644 --- a/Vision.WindowCapture/Vision.WindowCapture.csproj +++ b/Vision.WindowCapture/Vision.WindowCapture.csproj @@ -8,11 +8,12 @@ - - - - + + + + + diff --git a/Vision.WindowCapture/WindowCaptureFactory.cs b/Vision.WindowCapture/WindowCaptureFactory.cs index f66f5d00..04e6062b 100644 --- a/Vision.WindowCapture/WindowCaptureFactory.cs +++ b/Vision.WindowCapture/WindowCaptureFactory.cs @@ -1,44 +1,37 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Vision.WindowCapture; -namespace Vision.WindowCapture +public enum CaptureMode { - public enum CaptureMode + BitBlt, + WindowsGraphicsCapture +} + +public static class CaptureModeExtensions +{ + public static CaptureMode ToCaptureMode(this string modeName) { - BitBlt, - WindowsGraphicsCapture + return (CaptureMode) Enum.Parse(typeof(CaptureMode), modeName); + } +} + +public class WindowCaptureFactory +{ + public static string[] ModeNames() + { + return Enum.GetNames(typeof(CaptureMode)); } - public static class CaptureModeExtensions + + public static IWindowCapture Create(CaptureMode mode) { - public static CaptureMode ToCaptureMode(this string modeName) + switch (mode) { - return (CaptureMode) Enum.Parse(typeof(CaptureMode), modeName); - } - } - - public class WindowCaptureFactory - { - public static string[] ModeNames() - { - return Enum.GetNames(typeof(CaptureMode)); - } - - - public static IWindowCapture Create(CaptureMode mode) - { - switch (mode) - { - case CaptureMode.BitBlt: - return new BitBlt.BitBltCapture(); - case CaptureMode.WindowsGraphicsCapture: - return new GraphicsCapture.GraphicsCapture(); - default: - throw new ArgumentOutOfRangeException(nameof(mode), mode, null); - } + case CaptureMode.BitBlt: + return new BitBlt.BitBltCapture(); + case CaptureMode.WindowsGraphicsCapture: + return new GraphicsCapture.GraphicsCapture(); + default: + throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } } }