diff --git a/ScreenCast.Win/Models/DirectXOutput.cs b/ScreenCast.Win/Models/DirectXOutput.cs
new file mode 100644
index 00000000..bb91f321
--- /dev/null
+++ b/ScreenCast.Win/Models/DirectXOutput.cs
@@ -0,0 +1,35 @@
+using SharpDX.Direct3D11;
+using SharpDX.DXGI;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Remotely.ScreenCast.Win.Models
+{
+ public class DirectXOutput : IDisposable
+ {
+ public DirectXOutput(Adapter1 adapter,
+ SharpDX.Direct3D11.Device device,
+ OutputDuplication outputDuplication,
+ Texture2D texture2D)
+ {
+ Adapter = adapter;
+ Device = device;
+ OutputDuplication = outputDuplication;
+ Texture2D = texture2D;
+ }
+
+ public Adapter1 Adapter { get; }
+ public SharpDX.Direct3D11.Device Device { get; }
+ public OutputDuplication OutputDuplication { get; }
+ public Texture2D Texture2D { get; }
+
+ public void Dispose()
+ {
+ Adapter?.Dispose();
+ Device?.Dispose();
+ OutputDuplication?.Dispose();
+ Texture2D?.Dispose();
+ }
+ }
+}
diff --git a/ScreenCast.Win/ScreenCast.Win.csproj b/ScreenCast.Win/ScreenCast.Win.csproj
index 47ffb26b..2ffecd49 100644
--- a/ScreenCast.Win/ScreenCast.Win.csproj
+++ b/ScreenCast.Win/ScreenCast.Win.csproj
@@ -36,10 +36,6 @@
-
-
-
-
diff --git a/ScreenCast.Win/Services/ScreenCapturerWin.cs b/ScreenCast.Win/Services/ScreenCapturerWin.cs
index 19bcd326..ac9153bf 100644
--- a/ScreenCast.Win/Services/ScreenCapturerWin.cs
+++ b/ScreenCast.Win/Services/ScreenCapturerWin.cs
@@ -23,6 +23,7 @@
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
+using Remotely.ScreenCast.Win.Models;
using Remotely.Shared.Win32;
using SharpDX;
using SharpDX.Direct3D;
@@ -43,26 +44,7 @@ namespace Remotely.ScreenCast.Win.Services
public class ScreenCapturerWin : IScreenCapturer
{
private readonly Dictionary bitBltScreens = new Dictionary();
- private readonly Dictionary directxScreens = new Dictionary();
- private Adapter1 adapter;
- private SharpDX.Direct3D11.Device device;
- private Factory1 factory;
- private FeatureLevel[] featureLevels = new FeatureLevel[]
- {
- FeatureLevel.Level_9_1,
- FeatureLevel.Level_9_2,
- FeatureLevel.Level_9_3,
- FeatureLevel.Level_10_0,
- FeatureLevel.Level_10_1,
- FeatureLevel.Level_11_0,
- FeatureLevel.Level_11_1,
- FeatureLevel.Level_12_0,
- FeatureLevel.Level_12_1
- };
- private int height;
- private Texture2D screenTexture;
- private Texture2DDescription textureDesc;
- private int width;
+ private readonly Dictionary directxScreens = new Dictionary();
public ScreenCapturerWin()
{
Init();
@@ -80,7 +62,7 @@ namespace Remotely.ScreenCast.Win.Services
public void Dispose()
{
- DisposeDirectX();
+ ClearDirectXOutputs();
CurrentFrame?.Dispose();
PreviousFrame?.Dispose();
@@ -162,16 +144,13 @@ namespace Remotely.ScreenCast.Win.Services
ScreenChanged?.Invoke(this, CurrentScreenBounds);
}
- private void DisposeDirectX()
+ private void ClearDirectXOutputs()
{
- foreach (var output in directxScreens.Values)
+ foreach (var screen in directxScreens.Values)
{
- output.Dispose();
+ screen.Dispose();
}
directxScreens.Clear();
- device?.Dispose();
- adapter?.Dispose();
- factory?.Dispose();
}
private void GetBitBltFrame()
{
@@ -202,7 +181,10 @@ namespace Remotely.ScreenCast.Win.Services
SharpDX.DXGI.Resource screenResource;
OutputDuplicateFrameInformation duplicateFrameInformation;
- var duplicatedOutput = directxScreens[SelectedScreen];
+ var duplicatedOutput = directxScreens[SelectedScreen].OutputDuplication;
+ var device = directxScreens[SelectedScreen].Device;
+ var texture2D = directxScreens[SelectedScreen].Texture2D;
+
// Try to get duplicated frame within given time is ms
var result = duplicatedOutput.TryAcquireNextFrame(100, out duplicateFrameInformation, out screenResource);
@@ -233,22 +215,22 @@ namespace Remotely.ScreenCast.Win.Services
// copy resource into memory that can be accessed by the CPU
using (var screenTexture2D = screenResource.QueryInterface())
{
- device.ImmediateContext.CopyResource(screenTexture2D, screenTexture);
+ device.ImmediateContext.CopyResource(screenTexture2D, texture2D);
}
// Get the desktop capture texture
- var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
+ var mapSource = device.ImmediateContext.MapSubresource(texture2D, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
- var boundsRect = new Rectangle(0, 0, width, height);
+ var boundsRect = new Rectangle(0, 0, texture2D.Description.Width, texture2D.Description.Height);
// Copy pixels from screen capture Texture to GDI bitmap
var mapDest = CurrentFrame.LockBits(boundsRect, ImageLockMode.WriteOnly, CurrentFrame.PixelFormat);
var sourcePtr = mapSource.DataPointer;
var destPtr = mapDest.Scan0;
- for (int y = 0; y < height; y++)
+ for (int y = 0; y < texture2D.Description.Height; y++)
{
// Copy a single line
- SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, width * 4);
+ SharpDX.Utilities.CopyMemory(destPtr, sourcePtr, texture2D.Description.Width * 4);
// Advance pointers
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
@@ -257,7 +239,7 @@ namespace Remotely.ScreenCast.Win.Services
// Release source and dest locks
CurrentFrame.UnlockBits(mapDest);
- device.ImmediateContext.UnmapSubresource(screenTexture, 0);
+ device.ImmediateContext.UnmapSubresource(texture2D, 0);
screenResource.Dispose();
duplicatedOutput.ReleaseFrame();
@@ -283,54 +265,54 @@ namespace Remotely.ScreenCast.Win.Services
}
private void InitDirectX()
{
- DisposeDirectX();
+ ClearDirectXOutputs();
- factory = new Factory1();
-
- //Get first adapter
- adapter = factory.Adapters1.FirstOrDefault(x => x.Outputs.Length > 0);
- //Get device from adapter
- device = new SharpDX.Direct3D11.Device(adapter);
-
- for (var i = 0; i < adapter.GetOutputCount(); i++)
+ using (var factory = new Factory1())
{
- using (var output = adapter.GetOutput(i))
- using (var output1 = output.QueryInterface())
+ foreach (var adapter in factory.Adapters1.Where(x => (x.Outputs?.Length ?? 0) > 0))
{
- // Width/Height of desktop to capture
- var bounds = output1.Description.DesktopBounds;
- var newWidth = bounds.Right - bounds.Left;
- var newHeight = bounds.Bottom - bounds.Top;
- CurrentScreenBounds = new Rectangle(bounds.Left, bounds.Top, newWidth, newHeight);
- if (newWidth != width || newHeight != height)
+ try
{
- ScreenChanged?.Invoke(this, CurrentScreenBounds);
+ var device = new SharpDX.Direct3D11.Device(adapter);
+ var output = adapter.Outputs.FirstOrDefault();
+ var output1 = output.QueryInterface();
+
+ var bounds = output1.Description.DesktopBounds;
+ var width = bounds.Right - bounds.Left;
+ var height = bounds.Bottom - bounds.Top;
+
+ // Create Staging texture CPU-accessible
+ var textureDesc = new Texture2DDescription
+ {
+ CpuAccessFlags = CpuAccessFlags.Read,
+ BindFlags = BindFlags.None,
+ Format = Format.B8G8R8A8_UNorm,
+ Width = width,
+ Height = height,
+ OptionFlags = ResourceOptionFlags.None,
+ MipLevels = 1,
+ ArraySize = 1,
+ SampleDescription = { Count = 1, Quality = 0 },
+ Usage = ResourceUsage.Staging
+ };
+
+ var texture2D = new Texture2D(device, textureDesc);
+
+ directxScreens.Add(
+ output1.Description.DeviceName,
+ new DirectXOutput(adapter,
+ device,
+ output1.DuplicateOutput(device),
+ texture2D));
}
- width = newWidth;
- height = newHeight;
-
- CurrentFrame = new Bitmap(width, height, PixelFormat.Format32bppArgb);
- PreviousFrame = new Bitmap(width, height, PixelFormat.Format32bppArgb);
-
- // Create Staging texture CPU-accessible
- textureDesc = new Texture2DDescription
+ catch (Exception ex)
{
- CpuAccessFlags = CpuAccessFlags.Read,
- BindFlags = BindFlags.None,
- Format = Format.B8G8R8A8_UNorm,
- Width = width,
- Height = height,
- OptionFlags = ResourceOptionFlags.None,
- MipLevels = 1,
- ArraySize = 1,
- SampleDescription = { Count = 1, Quality = 0 },
- Usage = ResourceUsage.Staging
- };
- screenTexture = new Texture2D(device, textureDesc);
- directxScreens.Add(output1.Description.DeviceName, output1.DuplicateOutput(device));
+ Logger.Write(ex);
+ }
}
}
+
NeedsInit = false;
}
}