Skip to content

Commit

Permalink
修复 WGC下HDR
Browse files Browse the repository at this point in the history
  • Loading branch information
MakesYT committed Jan 3, 2025
1 parent 918c73e commit dade343
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 57 deletions.
50 changes: 6 additions & 44 deletions Core.Window/ScreenCapture/CaptureTool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Windows.Graphics;
using PluginCore;
using PluginCore;
using Silk.NET.Direct3D11;
using Silk.NET.DXGI;

Expand All @@ -12,8 +11,8 @@ public static unsafe byte[] GetBytesSpan(MappedSubresource mappedSubresource, Ou
var sizeX = outputDesc.DesktopCoordinates.Size.X;
int startX = Math.Clamp(screenCaptureInfo.X, 0, outputDesc.DesktopCoordinates.Size.X - 1);
int startY = Math.Clamp(screenCaptureInfo.Y, 0, outputDesc.DesktopCoordinates.Size.Y - 1);
int endX = Math.Clamp(screenCaptureInfo.Width, 0, outputDesc.DesktopCoordinates.Size.X);
int endY = Math.Clamp(screenCaptureInfo.Height, 0, outputDesc.DesktopCoordinates.Size.Y);
int endX = Math.Clamp(screenCaptureInfo.X+screenCaptureInfo.Width, 0, outputDesc.DesktopCoordinates.Size.X);
int endY = Math.Clamp(screenCaptureInfo.Y+screenCaptureInfo.Height, 0, outputDesc.DesktopCoordinates.Size.Y);
screenCaptureInfo.Height = endY - startY;
screenCaptureInfo.Width = endX - startX;
screenCaptureInfo.X = startX;
Expand Down Expand Up @@ -64,6 +63,7 @@ public static unsafe byte[] GetBytesSpan(MappedSubresource mappedSubresource, Ou
(int)mappedSubresource.DepthPitch / 2).ToArray();
// ReadOnlyMemory<Half> readOnlyMemory = new ReadOnlyMemory<Half>(span);
Parallel.For(startY, endY, y =>
//for (int y = startY; y < endY; y++)
{

int yOffset = y * sizeX;
Expand Down Expand Up @@ -92,49 +92,11 @@ public static unsafe byte[] GetBytesSpan(MappedSubresource mappedSubresource, Ou
result[targetIndex+ 2] = (byte)Math.Clamp(bt2020R * 255,0,255);
result[targetIndex + 3] = 255; // Alpha 固定为 255
}
});
}
);

}

return result;
}
public static unsafe byte[] GetBytesSpan(MappedSubresource mappedSubresource,SizeInt32 size,ref ScreenCaptureInfo screenCaptureInfo)
{
var sizeX = size.Width;
int startX = Math.Clamp(screenCaptureInfo.X, 0, size.Width - 1);
int startY = Math.Clamp(screenCaptureInfo.Y, 0, size.Height - 1);
int endX = Math.Clamp(screenCaptureInfo.X+screenCaptureInfo.Width, 0,size.Width);
int endY = Math.Clamp(screenCaptureInfo.Y+screenCaptureInfo.Height, 0,size.Height);
screenCaptureInfo.Height = endY - startY;
screenCaptureInfo.Width = endX - startX;
screenCaptureInfo.X = startX;
screenCaptureInfo.Y = startY;
// 结果数组:区域宽 * 区域高 * 4(RGBA)
int regionWidth = endX - startX;
int regionHeight = endY - startY;
byte[] result = new byte[regionWidth * regionHeight * 4];
{
var span = new ReadOnlySpan<uint>(mappedSubresource.PData,
(int)mappedSubresource.DepthPitch / 4);

for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; x++)
{
int sourceIndex = (y * sizeX + x) * 4;
int targetIndex = ((y - startY) * regionWidth + (x - startX)) * 4;

// 读取原始像素并复制到结果
uint value = span[sourceIndex / 4];
result[targetIndex+ 2] = (byte)(value & 0xFF); // R
result[targetIndex + 1] = (byte)((value >> 8) & 0xFF); // G
result[targetIndex ] = (byte)((value >> 16) & 0xFF); // B
result[targetIndex + 3] = (byte)((value >> 24) & 0xFF); // A
}
}

span = null;
}
return result;
}
}
80 changes: 69 additions & 11 deletions Core.Window/ScreenCapture/ScreenCaptureByWGC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,68 @@ public ScreenCaptureResult CaptureScreenBitmap(ScreenCaptureResult captureAllScr
return captureAllScreenInfo;
}

public IntPtr FindHMonitor(ScreenInfo screenInfo)
{
IntPtr h=IntPtr.Zero;
User32.EnumDisplayMonitors(default, null, (arg1, arg2, arg3, arg4) =>
{
if (screenInfo.X==arg3.left&&screenInfo.Y==arg3.top&&screenInfo.Width==arg3.right-arg3.left&&screenInfo.Height==arg3.bottom-arg3.top)
{
h = arg1;
return false;
}
return true;
}, IntPtr.Zero);
return h;
}
public static (ComPtr<IDXGIAdapter1>,OutputDesc1) GetAdapterForMonitor(ComPtr<IDXGIFactory1> factory,IntPtr hMonitor)
{
ComPtr<IDXGIAdapter1> adapter = null;
while (factory.EnumAdapters1(0, ref adapter) == 0)
{
ComPtr<IDXGIOutput> output = null;
while (adapter.EnumOutputs(0, ref output ) == 0)
{
OutputDesc desc = new OutputDesc();
output.GetDesc(ref desc);
if (desc.Monitor == hMonitor)
{
ComPtr<IDXGIOutput6> output6 = null;
if (output.QueryInterface<IDXGIOutput6>(out output6) != 0)
throw new Exception("Failed to get IDXGIOutput6");
var outputDesc = new OutputDesc1();
if (output6.GetDesc1(ref outputDesc) != 0) throw new Exception("Failed to get Desc1");
return (adapter,outputDesc);
}
else
{
output.Release();
}
}

adapter.Release();
}

throw new InvalidOperationException("No adapter found for the given monitor.");
}

public unsafe ScreenCaptureResult CaptureScreenBytes(ScreenCaptureInfo screenCaptureInfo)
{
if (screenCaptureInfo.ScreenInfo.hMonitor==null || screenCaptureInfo.ScreenInfo.hMonitor ==IntPtr.Zero)
{
screenCaptureInfo.ScreenInfo.hMonitor = FindHMonitor(screenCaptureInfo.ScreenInfo);
if (screenCaptureInfo.ScreenInfo.hMonitor==IntPtr.Zero)
{
throw new Exception("目标显示器不存在");
}
}
var factory2 = ActivationFactory.Get(typeof(GraphicsCaptureItem).FullName);
var interop = factory2.AsInterface<IGraphicsCaptureItemInterop>();
var itemPointer = interop.CreateForMonitor(screenCaptureInfo.ScreenInfo.hMonitor, GraphicsCaptureItemGuid);
var item = MarshalInterface<GraphicsCaptureItem>.FromAbi(itemPointer);
var dxgi = new DXGI(new DefaultNativeContext("dxgi"));

IDXGIAdapter1* adapter1 = null;
ComPtr<IDXGIAdapter1> adapter1 = null;
ID3D11DeviceContext* context = null;
ID3D11DeviceContext* immediateContext = null;
ID3D11Device* d3dDevice = null;
Expand All @@ -174,15 +227,17 @@ public unsafe ScreenCaptureResult CaptureScreenBytes(ScreenCaptureInfo screenCap
try
{
using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>();
if (factory.EnumAdapters1(0, ref adapter1) != 0) throw new Exception("Failed to create DXGI adapter");
var adapterForMonitor = GetAdapterForMonitor(factory,screenCaptureInfo.ScreenInfo.hMonitor);
adapter1 = adapterForMonitor.Item1;

var featureLevel = D3DFeatureLevel.Level110;
D3DFeatureLevel[] featureLevels =
[
D3DFeatureLevel.Level110
];
fixed (D3DFeatureLevel* pFeatureLevels = &featureLevels[0])
{
if (d3D11.CreateDevice((IDXGIAdapter*)adapter1, D3DDriverType.Unknown, IntPtr.Zero,
if (d3D11.CreateDevice((IDXGIAdapter*)adapter1.Handle, D3DDriverType.Unknown, IntPtr.Zero,
(uint)CreateDeviceFlag.None, pFeatureLevels, (uint)featureLevels.Length, D3D11.SdkVersion,
ref d3dDevice,
&featureLevel, ref context) != 0)
Expand Down Expand Up @@ -215,9 +270,11 @@ IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(ID3D11Device* d3dDevice)

framePool = Direct3D11CaptureFramePool.Create(
direct3DDeviceFromSharpDxDevice,
DirectXPixelFormat.R8G8B8A8UIntNormalized,
adapterForMonitor.Item2.ColorSpace.ToString().EndsWith("2020")
? DirectXPixelFormat.R16G16B16A16Float
: DirectXPixelFormat.R8G8B8A8UIntNormalized,
2,
item.Size);
item.Size);

session = framePool.CreateCaptureSession(item);

Expand All @@ -235,7 +292,9 @@ IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(ID3D11Device* d3dDevice)
{
CPUAccessFlags = (uint)CpuAccessFlag.Read,
BindFlags = (uint)BindFlag.None,
Format = Format.FormatR8G8B8A8Unorm,
Format = adapterForMonitor.Item2.ColorSpace.ToString().EndsWith("2020")
? Format.FormatR16G16B16A16Float
: Format.FormatR8G8B8A8Unorm,
Width = (uint)item.Size.Width,
Height = (uint)item.Size.Height,
MiscFlags = (uint)ResourceMiscFlag.None,
Expand All @@ -252,7 +311,7 @@ IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(ID3D11Device* d3dDevice)
immediateContext->CopyResource(stagingResource, bitmap);
if (immediateContext->Map(stagingResource, 0, Map.Read, 0, &mappedSubresource) != 0)
throw new Exception("Failed to map staging texture");
var bytesSpan = CaptureTool.GetBytesSpan(mappedSubresource, item.Size,ref screenCaptureInfo);
var bytesSpan = CaptureTool.GetBytesSpan(mappedSubresource,adapterForMonitor.Item2,ref screenCaptureInfo);

return new ScreenCaptureResult()
{
Expand All @@ -263,11 +322,10 @@ IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(ID3D11Device* d3dDevice)
finally
{

if (adapter1 != null)
{
adapter1->Release();

adapter1.Release();
adapter1 = null;
}


if (context != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ public object Deserialize(ReadOnlySpan<byte> value)
var strings = se.Split("=");
dic.Add(strings[0],strings[1]);
}

var screenCaptureInfo = new ScreenCaptureInfo
{
ScreenInfo = new ScreenInfo
{
hdcMonitor = new IntPtr(int.Parse(dic["ScreenInfo.hdcMonitor"])),
hMonitor = new IntPtr(int.Parse(dic["ScreenInfo.hMonitor"])),
Height = int.Parse(dic["ScreenInfo.Height"]),
Width = int.Parse(dic["ScreenInfo.Width"]),
X = int.Parse(dic["ScreenInfo.X"]),
Expand Down

0 comments on commit dade343

Please sign in to comment.