Skip to content

Commit 4392dba

Browse files
authored
Merge pull request #47 from BradyBrenot/dxgifixes
fix two DXGI issues
2 parents 775d058 + 76b9e30 commit 4392dba

7 files changed

+97
-74
lines changed

include/SCCommon.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace Screen_Capture {
4343
enum DUPL_RETURN { DUPL_RETURN_SUCCESS = 0, DUPL_RETURN_ERROR_EXPECTED = 1, DUPL_RETURN_ERROR_UNEXPECTED = 2 };
4444
const int PixelStride = 4;
4545
Monitor CreateMonitor(int index, int id, int h, int w, int ox, int oy, const std::string &n, float scale);
46+
Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scale);
4647

4748
Image Create(const ImageRect &imgrect, int pixelstride, int rowpadding, const unsigned char *data);
4849
// this function will copy data from the src into the dst. The only requirement is that src must not be larger than dst, but it can be smaller

include/ScreenCapture.h

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace Screen_Capture {
2727
struct Monitor {
2828
int Id = INT32_MAX;
2929
int Index = INT32_MAX;
30+
int Adapter = INT32_MAX;
3031
int Height = 0;
3132
int Width = 0;
3233
// Offsets are the number of pixels that a monitor can be from the origin. For example, users can shuffle their
@@ -68,6 +69,7 @@ namespace Screen_Capture {
6869
SC_LITE_EXTERN int Index(const Monitor &mointor);
6970
// unique identifier
7071
SC_LITE_EXTERN int Id(const Monitor &mointor);
72+
SC_LITE_EXTERN int Adapter(const Monitor &mointor);
7173
SC_LITE_EXTERN int OffsetX(const Monitor &mointor);
7274
SC_LITE_EXTERN int OffsetY(const Monitor &mointor);
7375
SC_LITE_EXTERN const char *Name(const Monitor &mointor);

include/windows/DXFrameProcessor.h

+20-23
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
11
#pragma once
22
#include "SCCommon.h"
3+
#include <DXGI.h>
34
#include <memory>
5+
#include <wrl.h>
46

5-
#define NOMINMAX
6-
#define WIN32_LEAN_AND_MEAN
7-
#include <windows.h>
87
#include <d3d11.h>
98
#include <dxgi1_2.h>
10-
#include <wrl.h>
119

12-
#pragma comment(lib,"dxgi.lib")
13-
#pragma comment(lib,"d3d11.lib")
10+
#pragma comment(lib, "dxgi.lib")
11+
#pragma comment(lib, "d3d11.lib")
1412

1513
namespace SL {
16-
namespace Screen_Capture {
17-
class DXFrameProcessor: public BaseFrameProcessor {
18-
Microsoft::WRL::ComPtr<ID3D11Device> Device;
19-
Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
20-
Microsoft::WRL::ComPtr<ID3D11Texture2D> StagingSurf;
21-
22-
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> OutputDuplication;
23-
DXGI_OUTPUT_DESC OutputDesc;
24-
UINT Output;
25-
std::vector<BYTE> MetaDataBuffer;
26-
Monitor SelectedMonitor;
14+
namespace Screen_Capture {
15+
class DXFrameProcessor : public BaseFrameProcessor {
16+
Microsoft::WRL::ComPtr<ID3D11Device> Device;
17+
Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
18+
Microsoft::WRL::ComPtr<ID3D11Texture2D> StagingSurf;
2719

28-
public:
29-
DUPL_RETURN Init(std::shared_ptr<Thread_Data> data, Monitor& monitor);
30-
DUPL_RETURN ProcessFrame(const Monitor& currentmonitorinfo);
20+
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> OutputDuplication;
21+
DXGI_OUTPUT_DESC OutputDesc;
22+
UINT Output;
23+
std::vector<BYTE> MetaDataBuffer;
24+
Monitor SelectedMonitor;
3125

32-
};
26+
public:
27+
DUPL_RETURN Init(std::shared_ptr<Thread_Data> data, Monitor &monitor);
28+
DUPL_RETURN ProcessFrame(const Monitor &currentmonitorinfo);
29+
};
3330

34-
}
35-
}
31+
} // namespace Screen_Capture
32+
} // namespace SL

src/SCCommon.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ namespace Screen_Capture {
138138
return ret;
139139
}
140140

141+
Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scaling)
142+
{
143+
Monitor ret = CreateMonitor(index, id, h, w, ox, oy, n, scaling);
144+
ret.Adapter = adapter;
145+
return ret;
146+
}
147+
141148
Image Create(const ImageRect &imgrect, int pixelstride, int rowpadding, const unsigned char *data)
142149
{
143150
Image ret;
@@ -149,6 +156,7 @@ namespace Screen_Capture {
149156
}
150157
int Index(const Monitor &mointor) { return mointor.Index; }
151158
int Id(const Monitor &mointor) { return mointor.Id; }
159+
int Adapter(const Monitor &mointor) { return mointor.Adapter; }
152160
int OffsetX(const Monitor &mointor) { return mointor.OffsetX; }
153161
int OffsetY(const Monitor &mointor) { return mointor.OffsetY; }
154162
const char *Name(const Monitor &mointor) { return mointor.Name; }

src/windows/DXFrameProcessor.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#include <atomic>
33
#include <iostream>
44
#include <memory>
5-
#include <mutex>
65
#include <string>
76

87
#if (_MSC_VER >= 1700) && defined(_USING_V110_SDK71_)
@@ -137,21 +136,21 @@ namespace Screen_Capture {
137136
return DUPL_RETURN_SUCCESS;
138137
}
139138

140-
DUPL_RETURN Initialize(DUPLE_RESOURCES &r, ID3D11Device *device, const UINT output)
139+
DUPL_RETURN Initialize(DUPLE_RESOURCES &r, ID3D11Device *device, const UINT adapter, const UINT output)
141140
{
141+
Microsoft::WRL::ComPtr<IDXGIFactory> pFactory;
142142

143-
// Get DXGI device
144-
Microsoft::WRL::ComPtr<IDXGIDevice> DxgiDevice;
145-
HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(DxgiDevice.GetAddressOf()));
143+
// Create a DXGIFactory object.
144+
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)pFactory.GetAddressOf());
146145
if (FAILED(hr)) {
147-
return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr);
146+
return ProcessFailure(nullptr, L"Failed to construct DXGIFactory", L"Error", hr);
148147
}
149148

150-
// Get DXGI adapter
151149
Microsoft::WRL::ComPtr<IDXGIAdapter> DxgiAdapter;
152-
hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(DxgiAdapter.GetAddressOf()));
150+
hr = pFactory->EnumAdapters(adapter, DxgiAdapter.GetAddressOf());
151+
153152
if (FAILED(hr)) {
154-
return ProcessFailure(device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
153+
return ProcessFailure(device, L"Failed to get DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors);
155154
}
156155

157156
// Get output
@@ -179,6 +178,7 @@ namespace Screen_Capture {
179178
r.Output = output;
180179
return DUPL_RETURN_SUCCESS;
181180
}
181+
182182
RECT ConvertRect(RECT Dirty, const DXGI_OUTPUT_DESC &DeskDesc)
183183
{
184184
RECT DestDirty = Dirty;
@@ -278,7 +278,7 @@ namespace Screen_Capture {
278278
return ret;
279279
}
280280
DUPLE_RESOURCES dupl;
281-
ret = Initialize(dupl, res.Device.Get(), Id(SelectedMonitor));
281+
ret = Initialize(dupl, res.Device.Get(), Adapter(SelectedMonitor), Id(SelectedMonitor));
282282
if (ret != DUPL_RETURN_SUCCESS) {
283283
return ret;
284284
}

src/windows/GetMonitors.cpp

+50-37
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,64 @@
11
#include "SCCommon.h"
22
#include "ScreenCapture.h"
3-
#define NOMINMAX
4-
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
5-
#include <Windows.h>
3+
#include <DXGI.h>
64

75
namespace SL {
86
namespace Screen_Capture {
97

8+
float scaleFromDpi(int xdpi)
9+
{
10+
switch (xdpi) {
11+
case 96:
12+
return 1.0f;
13+
break;
14+
case 120:
15+
return 1.25f;
16+
break;
17+
case 144:
18+
return 1.5f;
19+
break;
20+
case 192:
21+
return 2.0f;
22+
break;
23+
}
24+
25+
return 1.0f;
26+
}
27+
1028
std::vector<Monitor> GetMonitors()
1129
{
1230
std::vector<Monitor> ret;
13-
DISPLAY_DEVICEA dd;
14-
ZeroMemory(&dd, sizeof(dd));
15-
dd.cb = sizeof(dd);
16-
for (auto i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); i++) {
17-
// monitor must be attached to desktop and not a mirroring device
18-
19-
if (((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0 || (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0) &&
20-
(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) {
21-
DEVMODEA devMode;
22-
devMode.dmSize = sizeof(devMode);
23-
EnumDisplaySettingsA(dd.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
24-
std::string name = dd.DeviceName;
25-
auto mon = CreateDCA(dd.DeviceName, NULL, NULL, NULL);
26-
auto xdpi = GetDeviceCaps(mon, LOGPIXELSX);
27-
DeleteDC(mon);
28-
auto scale = 1.0f;
29-
switch (xdpi) {
30-
case 96:
31-
scale = 1.0f;
32-
break;
33-
case 120:
34-
scale = 1.25f;
35-
break;
36-
case 144:
37-
scale = 1.5f;
38-
break;
39-
case 192:
40-
scale = 2.0f;
41-
break;
42-
default:
43-
scale = 1.0f;
44-
break;
31+
32+
IDXGIAdapter *pAdapter = nullptr;
33+
IDXGIFactory *pFactory = nullptr;
34+
35+
// Create a DXGIFactory object.
36+
if (SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&pFactory))) {
37+
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) {
38+
IDXGIOutput *pOutput;
39+
40+
for (UINT j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j) {
41+
DXGI_OUTPUT_DESC desc;
42+
pOutput->GetDesc(&desc);
43+
pOutput->Release();
44+
std::wstring wname = desc.DeviceName;
45+
std::string name(wname.begin(), wname.end());
46+
DEVMODEW devMode;
47+
EnumDisplaySettingsW(desc.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
48+
49+
auto mon = CreateDCW(desc.DeviceName, NULL, NULL, NULL);
50+
auto xdpi = GetDeviceCaps(mon, LOGPIXELSX);
51+
DeleteDC(mon);
52+
auto scale = scaleFromDpi(xdpi);
53+
54+
bool flipSides = desc.Rotation == DXGI_MODE_ROTATION_ROTATE90 || desc.Rotation == DXGI_MODE_ROTATION_ROTATE270;
55+
ret.push_back(CreateMonitor(static_cast<int>(ret.size()), j, i, flipSides ? devMode.dmPelsWidth : devMode.dmPelsHeight,
56+
flipSides ? devMode.dmPelsHeight : devMode.dmPelsWidth, devMode.dmPosition.x, devMode.dmPosition.y,
57+
name, scale));
4558
}
46-
ret.push_back(CreateMonitor(static_cast<int>(ret.size()), i, devMode.dmPelsHeight, devMode.dmPelsWidth, devMode.dmPosition.x,
47-
devMode.dmPosition.y, name, scale));
59+
pAdapter->Release();
4860
}
61+
pFactory->Release();
4962
}
5063
return ret;
5164
}

src/windows/ThreadRunner.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ namespace SL {
6767
std::cout << "Starting to Capture on Monitor " << Name(monitor) << std::endl;
6868
std::cout << "Trying DirectX Desktop Duplication " << std::endl;
6969
#endif
70-
if (!TryCaptureMonitor<DXFrameProcessor>(data, monitor)) {//if DX is not supported, fallback to GDI capture
71-
#if defined _DEBUG || !defined NDEBUG
72-
std::cout << "DirectX Desktop Duplication not supprted, falling back to GDI Capturing . . ." << std::endl;
73-
#endif
70+
if (monitor.Adapter == -1)
71+
{
7472
TryCaptureMonitor<GDIFrameProcessor>(data, monitor);
7573
}
74+
else
75+
{
76+
TryCaptureMonitor<DXFrameProcessor>(data, monitor);
77+
}
7678
}
7779

7880
void RunCaptureWindow(std::shared_ptr<Thread_Data> data, Window wnd) {

0 commit comments

Comments
 (0)