From 0257d548f2aeb9625d95146706c130f524304cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sat, 15 Mar 2025 02:23:17 +0800 Subject: [PATCH] =?UTF-8?q?dwm=E5=8A=A0=E9=94=81=E5=B9=B6=E8=BF=94?= =?UTF-8?q?=E5=9B=9Emat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DwmSharedSurface/SharedSurfaceCapture.cs | 47 +++++++++++-------- .../Graphics/GraphicsCapture.cs | 1 + .../Graphics/Helpers/Texture2DExtensions.cs | 37 +++++++++++++++ 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs b/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs index a1ea064f..53f2b6c8 100644 --- a/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs +++ b/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs @@ -13,6 +13,7 @@ namespace Fischless.GameCapture.DwmSharedSurface public class SharedSurfaceCapture : IGameCapture { private nint _hWnd; + private static readonly object LockObject = new object(); private Device? _d3dDevice; public void Dispose() => Stop(); @@ -73,27 +74,38 @@ namespace Fischless.GameCapture.DwmSharedSurface return null; } - - NativeMethods.DwmGetDxSharedSurface(_hWnd, out var phSurface, out _, out _, out _, out _); - if (phSurface == nint.Zero) + lock (LockObject) { - return null; - } + NativeMethods.DwmGetDxSharedSurface(_hWnd, out var phSurface, out _, out _, out _, out _); + if (phSurface == nint.Zero) + { + return null; + } - return ToBitmap(phSurface)?.ToMat(); + + if (_d3dDevice == null) + { + Debug.WriteLine("D3Device is null."); + return null; + } + + using var surfaceTexture = _d3dDevice.OpenSharedResource(phSurface); + using var stagingTexture = CreateStagingTexture(surfaceTexture, _d3dDevice); + var mat = stagingTexture.CreateMat(_d3dDevice, surfaceTexture, _region); + if (mat == null) + { + return null; + } + var bgrMat = new Mat(); + Cv2.CvtColor(mat, bgrMat, ColorConversionCodes.BGRA2BGR); + return bgrMat; + } } + - private Bitmap? ToBitmap(nint phSurface) + private Texture2D CreateStagingTexture(Texture2D surfaceTexture, Device device) { - if (_d3dDevice == null) - { - Debug.WriteLine("D3Device is null."); - return null; - } - - using var surfaceTexture = _d3dDevice.OpenSharedResource(phSurface); - - var staging = new Texture2D(_d3dDevice, new Texture2DDescription + return new Texture2D(device, new Texture2DDescription { Width = _region == null ? surfaceTexture.Description.Width : _region.Value.Right - _region.Value.Left, Height = _region == null ? surfaceTexture.Description.Height : _region.Value.Bottom - _region.Value.Top, @@ -106,9 +118,6 @@ namespace Fischless.GameCapture.DwmSharedSurface CpuAccessFlags = CpuAccessFlags.Read, OptionFlags = ResourceOptionFlags.None }); - - - return staging.CreateBitmap(_d3dDevice, surfaceTexture, _region); } public void Stop() diff --git a/Fischless.GameCapture/Graphics/GraphicsCapture.cs b/Fischless.GameCapture/Graphics/GraphicsCapture.cs index 3aba30d6..da25b0af 100644 --- a/Fischless.GameCapture/Graphics/GraphicsCapture.cs +++ b/Fischless.GameCapture/Graphics/GraphicsCapture.cs @@ -238,6 +238,7 @@ public class GraphicsCapture : IGameCapture _captureSession = null!; _captureFramePool = null!; _captureItem = null!; + _stagingTexture?.Dispose(); _d3dDevice?.Dispose(); _hWnd = IntPtr.Zero; diff --git a/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs index 0feca9c5..f3f94a4e 100644 --- a/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs +++ b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs @@ -4,6 +4,7 @@ using SharpDX.DXGI; using System.Diagnostics; using System.Drawing.Imaging; using Windows.Graphics.Capture; +using OpenCvSharp; namespace Fischless.GameCapture.Graphics.Helpers; @@ -67,4 +68,40 @@ public static class Texture2DExtensions staging.Dispose(); } } + + public static Mat? CreateMat(this Texture2D staging, SharpDX.Direct3D11.Device d3dDevice, Texture2D surfaceTexture, ResourceRegion? region = null) + { + try + { + // Copy data + if (region != null) + { + d3dDevice.ImmediateContext.CopySubresourceRegion(surfaceTexture, 0, region, staging, 0); + } + else + { + d3dDevice.ImmediateContext.CopyResource(surfaceTexture, staging); + } + + // 映射纹理以便CPU读取 + var dataBox = d3dDevice.ImmediateContext.MapSubresource( + staging, + 0, + MapMode.Read, + SharpDX.Direct3D11.MapFlags.None); + + var mat = new Mat(staging.Description.Height, staging.Description.Width, MatType.CV_8UC4, dataBox.DataPointer); + return mat; + } + catch (Exception e) + { + Debug.WriteLine("Failed to copy texture to mat."); + Debug.WriteLine(e.StackTrace); + return null; + } + finally + { + staging.Dispose(); + } + } } \ No newline at end of file