dwm加锁并返回mat

This commit is contained in:
辉鸭蛋
2025-03-15 02:23:17 +08:00
parent 6e80999817
commit 0257d548f2
3 changed files with 66 additions and 19 deletions

View File

@@ -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<Texture2D>(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<Texture2D>(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()

View File

@@ -238,6 +238,7 @@ public class GraphicsCapture : IGameCapture
_captureSession = null!;
_captureFramePool = null!;
_captureItem = null!;
_stagingTexture?.Dispose();
_d3dDevice?.Dispose();
_hWnd = IntPtr.Zero;

View File

@@ -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();
}
}
}