Skip to content

Commit 14f585e

Browse files
committed
add back DesktopDuplicator.cs
1 parent d1782c4 commit 14f585e

3 files changed

Lines changed: 152 additions & 3 deletions

File tree

Project-Aurora/Project-Aurora/Settings/Layers/Ambilight/DXScreenCapture.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88

99
namespace Aurora.Settings.Layers.Ambilight;
1010

11-
internal class DXScreenCapture : IScreenCapture
11+
internal class DxScreenCapture : IScreenCapture
1212
{
1313
private static readonly Semaphore Semaphore = new(1, 1);
1414
private Rectangle _currentBounds;
1515
private DesktopDuplicator _desktopDuplicator;
16-
private int _display;
1716

1817
public Bitmap Capture(Rectangle desktopRegion)
1918
{
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Based on https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct3D11.1/ScreenCapture/Program.cs
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Drawing;
6+
using System.Drawing.Imaging;
7+
using SharpDX;
8+
using SharpDX.Direct3D11;
9+
using SharpDX.DXGI;
10+
using Device = SharpDX.Direct3D11.Device;
11+
using MapFlags = SharpDX.Direct3D11.MapFlags;
12+
13+
namespace Aurora.Settings.Layers.Ambilight;
14+
15+
public class DesktopDuplicator : IDisposable
16+
{
17+
private static readonly IDictionary<Adapter1, OutputDuplication> Duplicators = new Dictionary<Adapter1, OutputDuplication>();
18+
19+
private readonly Device _device;
20+
private readonly OutputDuplication _deskDupl;
21+
22+
private readonly Texture2D _desktopImageTexture;
23+
24+
private readonly Rectangle _rect;
25+
26+
public DesktopDuplicator(Adapter1 adapter, Output1 output, Rectangle rect)
27+
{
28+
Global.logger.Info("Starting desktop duplicator");
29+
_rect = rect;
30+
_device = new Device(adapter);
31+
var textureDesc = new Texture2DDescription
32+
{
33+
CpuAccessFlags = CpuAccessFlags.Read,
34+
BindFlags = BindFlags.None,
35+
Format = Format.B8G8R8A8_UNorm,
36+
Width = output.Description.DesktopBounds.Right - output.Description.DesktopBounds.Left,
37+
Height = output.Description.DesktopBounds.Bottom - output.Description.DesktopBounds.Top,
38+
OptionFlags = ResourceOptionFlags.None,
39+
MipLevels = 1,
40+
ArraySize = 1,
41+
SampleDescription = { Count = 1, Quality = 0 },
42+
Usage = ResourceUsage.Staging
43+
};
44+
45+
if (!Duplicators.TryGetValue(adapter, out _deskDupl))
46+
{
47+
_deskDupl = output.DuplicateOutput(_device);
48+
Duplicators.Add(adapter, _deskDupl);
49+
}
50+
51+
_desktopImageTexture = new Texture2D(_device, textureDesc);
52+
}
53+
54+
public Bitmap Capture(int timeout)
55+
{
56+
SharpDX.DXGI.Resource desktopResource;
57+
if (_deskDupl.IsDisposed || _device.IsDisposed)
58+
return null;
59+
60+
try {
61+
_deskDupl.TryAcquireNextFrame(timeout, out _, out desktopResource);
62+
}
63+
catch (SharpDXException e) when (e.Descriptor == SharpDX.DXGI.ResultCode.WaitTimeout)
64+
{
65+
Global.logger.Debug(String.Format("Timeout of {0}ms exceeded while acquiring next frame", timeout));
66+
return null;
67+
}
68+
catch (SharpDXException e) when (e.Descriptor == SharpDX.DXGI.ResultCode.AccessLost)
69+
{
70+
// Can happen when going fullscreen / exiting fullscreen
71+
return null;
72+
}
73+
catch (SharpDXException e) when (e.Descriptor == SharpDX.DXGI.ResultCode.AccessDenied)
74+
{
75+
// Happens when locking PC
76+
return null;
77+
}
78+
catch (SharpDXException e) when (e.ResultCode.Failure)
79+
{
80+
Global.logger.Warn(e.Message);
81+
return null;
82+
}
83+
84+
using (desktopResource) {
85+
using (var tempTexture = desktopResource.QueryInterface<Texture2D>())
86+
_device.ImmediateContext.CopyResource(tempTexture, _desktopImageTexture);
87+
}
88+
89+
bool disposed = ReleaseFrame();
90+
if (disposed)
91+
return null;
92+
93+
var mapSource = _device.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read, MapFlags.None);
94+
95+
try
96+
{
97+
return ProcessFrame(mapSource.DataPointer, mapSource.RowPitch);
98+
}
99+
finally
100+
{
101+
if (!_device.IsDisposed && !_device.ImmediateContext.IsDisposed && !_desktopImageTexture.IsDisposed)
102+
{
103+
_device.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0);
104+
}
105+
}
106+
}
107+
108+
Bitmap ProcessFrame(IntPtr SourcePtr, int SourceRowPitch)
109+
{
110+
var frame = new Bitmap(_rect.Width, _rect.Height, PixelFormat.Format32bppRgb);
111+
// Copy pixels from screen capture Texture to GDI bitmap
112+
var mapDest = frame.LockBits(new Rectangle(0, 0, _rect.Width, _rect.Height), ImageLockMode.WriteOnly, frame.PixelFormat);
113+
var screenY = _rect.Top;
114+
var sizeInBytesToCopy = _rect.Width * 4;
115+
for (var y = 0; screenY < _rect.Bottom; screenY++, y++)
116+
{
117+
var mapDestStride = mapDest.Scan0 + y * mapDest.Stride;
118+
var sourceRowPitch = SourcePtr + screenY * SourceRowPitch + _rect.Left * 4;
119+
Utilities.CopyMemory(mapDestStride, sourceRowPitch, sizeInBytesToCopy);
120+
}
121+
// Release source and dest locks
122+
frame.UnlockBits(mapDest);
123+
124+
return frame;
125+
}
126+
127+
bool ReleaseFrame()
128+
{
129+
try
130+
{
131+
_deskDupl.ReleaseFrame();
132+
return _deskDupl.IsDisposed;
133+
}
134+
catch (SharpDXException e)
135+
{
136+
if (e.ResultCode.Failure)
137+
{
138+
Global.logger.Warn(e.Message);
139+
}
140+
return true;
141+
}
142+
}
143+
144+
public void Dispose()
145+
{
146+
_device?.Dispose();
147+
_deskDupl?.Dispose();
148+
_desktopImageTexture?.Dispose();
149+
}
150+
}

Project-Aurora/Project-Aurora/Settings/Layers/AmbilightLayerHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ public AmbilightLayerHandler() : base("Ambilight Layer")
300300
private void Initialize()
301301
{
302302
_screenCapture?.Dispose();
303-
_screenCapture = Properties.ExperimentalMode ? new DXScreenCapture() : new GDIScreenCapture();
303+
_screenCapture = Properties.ExperimentalMode ? new DxScreenCapture() : new GDIScreenCapture();
304304
Global.logger.Info("Started regular ambilight mode");
305305
InvokePropertyChanged(nameof(Displays));
306306
}

0 commit comments

Comments
 (0)