When capturing the desktop using Vortice with the code below it works just fine. Although, when I try to use any other value than 0 for the X or Y location of the rectangle it only returns frame as a black bitmap. The code I used for reference is located here: https://github.com/diogotr7/DesktopDuplicationSamples/blob/master/VorticeCore/Program.cs, but it suffers from the same problem. I have tried altering most values in the var frame and var mapDest with not much luck.
public void Start()
{
_isCapturing = true;
DXGI.CreateDXGIFactory1<IDXGIFactory1>(out var factory);
if (factory == null)
{
return;
}
var adapter = factory.GetAdapter(0);
var output = adapter.GetOutput(0);
var output1 = output.QueryInterface<IDXGIOutput1>();
//D3D12.D3D12CreateDevice(adapter, FeatureLevel.Level_12_0, out ID3D12Device? device);
D3D11.D3D11CreateDevice(adapter, DriverType.Unknown, DeviceCreationFlags.None, _featureLevels, out var device);
if (device == null)
throw new Exception("Unable to Locate Device.");
// Width/Height of desktop to capture
Rectangle rectangle = new Rectangle(0, 0,
output.Description.DesktopCoordinates.Right,
output.Description.DesktopCoordinates.Bottom);
// Create Staging texture CPU-accessible
var texture2dDescription = new Texture2DDescription
{
ArraySize = 1,
BindFlags = BindFlags.None,
CPUAccessFlags = CpuAccessFlags.Read | CpuAccessFlags.Write,
Format = Format.B8G8R8A8_UNorm,
Height = rectangle.Bottom,
MipLevels = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = ResourceUsage.Staging,
Width = rectangle.Right
};
Task.Factory.StartNew(() =>
{
// Duplicate the output
using var duplicatedOutput = output1.DuplicateOutput(device);
while (_isCapturing)
{
try
{
var currentFrame = device.CreateTexture2D(texture2dDescription);
Thread.Sleep(50);
rectangle.X = 0;
duplicatedOutput.AcquireNextFrame(100, out var frameInfo, out var desktopResource);
if (desktopResource == null)
continue;
var tempTexture = desktopResource.QueryInterface<ID3D11Texture2D>();
device.ImmediateContext.CopyResource(currentFrame, tempTexture);
var dataBox = device.ImmediateContext.Map(currentFrame, 0);
var frame = new Bitmap(rectangle.Right, rectangle.Bottom, PixelFormat.Format32bppRgb);
var mapDest = frame.LockBits(rectangle, ImageLockMode.WriteOnly, frame.PixelFormat);
for (int y = rectangle.Y, sizeInBytesToCopy = rectangle.Width * 4; y < rectangle.Height; y++)
{
MemoryHelpers.CopyMemory(mapDest.Scan0 + y * rectangle.Right * 4,
dataBox.DataPointer + y * dataBox.RowPitch, sizeInBytesToCopy);
}
frame.UnlockBits(mapDest);
ScreenRefreshed?.Invoke(this, frame);
desktopResource.Dispose();
frame.Dispose();
tempTexture.Dispose();
currentFrame.Dispose();
}
catch (Exception e)
{
if (e.HResult != Vortice.DXGI.ResultCode.WaitTimeout.Code)
{
Trace.TraceError(e.Message);
Trace.TraceError(e.StackTrace);
}
}
duplicatedOutput.ReleaseFrame();
}
});
}