Skip to content

Commit 7e94683

Browse files
authored
DirectX multi-monitor support (#966)
* Needed changes before multi-monitor support * Add multi-monitor and P010 detection * Initial multi-monitor support * Fix multi-monitor capturing
1 parent fa32e0f commit 7e94683

File tree

9 files changed

+454
-158
lines changed

9 files changed

+454
-158
lines changed

Diff for: include/base/Grabber.h

+2
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ public slots:
176176

177177
int getTargetSystemFrameDimension(int& targetSizeX, int& targetSizeY);
178178

179+
int getTargetSystemFrameDimension(int actualWidth, int actualHeight, int& targetSizeX, int& targetSizeY);
180+
179181
void processSystemFrameBGRA(uint8_t* source, int lineSize = 0, bool useLut = true);
180182

181183
void processSystemFrameBGR(uint8_t* source, int lineSize = 0);

Diff for: include/grabber/windows/DX/DxGrabber.h

+59-16
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,61 @@
1818
#include <vector>
1919
#include <map>
2020
#include <chrono>
21+
#include <list>
22+
#include <algorithm>
2123
#endif
2224

2325
// util includes
2426
#include <utils/PixelFormat.h>
2527
#include <base/Grabber.h>
2628
#include <utils/Components.h>
2729

30+
template <class T> void SafeRelease(T** ppT)
31+
{
32+
if (*ppT)
33+
{
34+
(*ppT)->Release();
35+
*ppT = NULL;
36+
}
37+
}
38+
39+
struct DisplayHandle
40+
{
41+
QString name;
42+
int warningCounter = 6;
43+
bool wideGamut = false;
44+
int actualDivide = -1, actualWidth = 0, actualHeight = 0;
45+
uint targetMonitorNits = 0;
46+
ID3D11Texture2D* d3dConvertTexture = nullptr;
47+
ID3D11RenderTargetView* d3dRenderTargetView = nullptr;
48+
ID3D11ShaderResourceView* d3dConvertTextureView = nullptr;
49+
ID3D11VertexShader* d3dVertexShader = nullptr;
50+
ID3D11PixelShader* d3dPixelShader = nullptr;
51+
ID3D11Buffer* d3dBuffer = nullptr;
52+
ID3D11SamplerState* d3dSampler = nullptr;
53+
ID3D11InputLayout* d3dVertexLayout = nullptr;
54+
IDXGIOutputDuplication* d3dDuplicate = nullptr;
55+
ID3D11Texture2D* d3dSourceTexture = nullptr;
56+
DXGI_OUTDUPL_DESC surfaceProperties{};
57+
58+
DisplayHandle() = default;
59+
DisplayHandle(const DisplayHandle&) = delete;
60+
~DisplayHandle()
61+
{
62+
SafeRelease(&d3dRenderTargetView);
63+
SafeRelease(&d3dSourceTexture);
64+
SafeRelease(&d3dConvertTextureView);
65+
SafeRelease(&d3dConvertTexture);
66+
SafeRelease(&d3dVertexShader);
67+
SafeRelease(&d3dVertexLayout);
68+
SafeRelease(&d3dPixelShader);
69+
SafeRelease(&d3dSampler);
70+
SafeRelease(&d3dBuffer);
71+
SafeRelease(&d3dDuplicate);
72+
printf("SmartPointer is removing: DisplayHandle for %s\n", QSTRING_CSTR(name));
73+
};
74+
};
75+
2876
class DxGrabber : public Grabber
2977
{
3078
Q_OBJECT
@@ -56,6 +104,13 @@ public slots:
56104
void restart();
57105

58106
private:
107+
108+
const QString MULTI_MONITOR = "MULTI-MONITOR";
109+
110+
void captureFrame(DisplayHandle& display);
111+
112+
int captureFrame(DisplayHandle& display, Image<ColorRgb>& image);
113+
59114
QString GetSharedLut();
60115

61116
void enumerateDevices(bool silent);
@@ -70,29 +125,17 @@ public slots:
70125

71126
bool initDirectX(QString selectedDeviceName);
72127

73-
bool initShaders();
74-
HRESULT deepScaledCopy(ID3D11Texture2D* source);
128+
bool initShaders(DisplayHandle& display);
129+
HRESULT deepScaledCopy(DisplayHandle& display, ID3D11Texture2D* source);
75130

76131
QString _configurationPath;
77132
QTimer* _timer;
78133
QTimer* _retryTimer;
79-
int _warningCounter;
80-
int _actualDivide;
81-
bool _wideGamut;
134+
bool _multiMonitor;
82135

83136
bool _dxRestartNow;
137+
std::list<std::unique_ptr<DisplayHandle>> _handles;
84138
ID3D11Device* _d3dDevice;
85139
ID3D11DeviceContext* _d3dContext;
86-
ID3D11Buffer* _d3dBuffer;
87-
ID3D11SamplerState* _d3dSampler;
88-
ID3D11InputLayout* _d3dVertexLayout;
89-
ID3D11VertexShader* _d3dVertexShader;
90-
ID3D11PixelShader* _d3dPixelShader;
91-
ID3D11Texture2D* _d3dSourceTexture;
92-
ID3D11Texture2D* _d3dConvertTexture;
93-
ID3D11ShaderResourceView* _d3dConvertTextureView;
94-
ID3D11RenderTargetView* _d3dRenderTargetView;
95-
IDXGIOutputDuplication* _d3dDuplicate;
96-
DXGI_OUTDUPL_DESC _surfaceProperties;
97140
Image<ColorRgb> _cacheImage;
98141
};

Diff for: include/image/Image.h

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Image
3030

3131
void gradientVBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t r, uint8_t g, uint8_t b);
3232

33+
void insertHorizontal(int x, Image<ColorSpace>& source);
34+
3335
unsigned width() const;
3436

3537
unsigned height() const;

Diff for: include/utils/PixelFormat.h

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum class PixelFormat {
1111
I420,
1212
NV12,
1313
MJPEG,
14+
P010,
1415
NO_CHANGE
1516
};
1617

@@ -42,6 +43,10 @@ inline PixelFormat parsePixelFormat(const QString& pixelFormat)
4243
{
4344
return PixelFormat::MJPEG;
4445
}
46+
else if (format.compare("p010") == 0)
47+
{
48+
return PixelFormat::P010;
49+
}
4550

4651
return PixelFormat::NO_CHANGE;
4752
}
@@ -73,6 +78,10 @@ inline QString pixelFormatToString(const PixelFormat& pixelFormat)
7378
{
7479
return "mjpeg";
7580
}
81+
else if (pixelFormat == PixelFormat::P010)
82+
{
83+
return "p010";
84+
}
7685

7786
return "NO_CHANGE";
7887
}

Diff for: sources/base/Grabber.cpp

+62-2
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,24 @@ void Grabber::setEnabled(bool enable)
101101

102102
void Grabber::setMonitorNits(int nits)
103103
{
104-
_targetMonitorNits = nits;
104+
if (_targetMonitorNits != nits)
105+
{
106+
_targetMonitorNits = nits;
107+
108+
Debug(_log, "Set nits to %i", _targetMonitorNits);
109+
110+
if (_initialized && !_blocked)
111+
{
112+
Debug(_log, "Restarting video grabber");
113+
uninit();
114+
start();
115+
}
116+
else
117+
{
118+
Info(_log, "Delayed restart of the grabber due to change of monitor nits value");
119+
_restartNeeded = true;
120+
}
121+
}
105122
}
106123

107124
void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom)
@@ -128,7 +145,24 @@ void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTo
128145

129146
void Grabber::enableHardwareAcceleration(bool hardware)
130147
{
131-
_hardware = hardware;
148+
if (_hardware != hardware)
149+
{
150+
_hardware = hardware;
151+
152+
Debug(_log, "Set hardware acceleration to %s", _hardware ? "enabled" : "disabled");
153+
154+
if (_initialized && !_blocked)
155+
{
156+
Debug(_log, "Restarting video grabber");
157+
uninit();
158+
start();
159+
}
160+
else
161+
{
162+
Info(_log, "Delayed restart of the grabber due to change of the hardware acceleration");
163+
_restartNeeded = true;
164+
}
165+
}
132166
}
133167

134168
bool Grabber::trySetInput(int input)
@@ -518,6 +552,32 @@ int Grabber::getTargetSystemFrameDimension(int& targetSizeX, int& targetSizeY)
518552
return divide;
519553
}
520554

555+
int Grabber::getTargetSystemFrameDimension(int actualWidth, int actualHeight, int& targetSizeX, int& targetSizeY)
556+
{
557+
int realSizeX = actualWidth;
558+
int realSizeY = actualHeight;
559+
560+
if (realSizeX <= 16 || realSizeY <= 16)
561+
{
562+
realSizeX = actualWidth;
563+
realSizeY = actualHeight;
564+
}
565+
566+
int checkWidth = realSizeX;
567+
int divide = 1;
568+
569+
while (checkWidth > _width)
570+
{
571+
divide++;
572+
checkWidth = realSizeX / divide;
573+
}
574+
575+
targetSizeX = realSizeX / divide;
576+
targetSizeY = realSizeY / divide;
577+
578+
return divide;
579+
}
580+
521581
void Grabber::processSystemFrameBGRA(uint8_t* source, int lineSize, bool useLut)
522582
{
523583
int targetSizeX, targetSizeY;

Diff for: sources/grabber/linux/v4l2/V4L2Grabber.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ static const V4L2Grabber::HyperHdrFormat supportedFormats[] =
6969
{ V4L2_PIX_FMT_YUV420, PixelFormat::I420 },
7070
{ V4L2_PIX_FMT_NV12, PixelFormat::NV12 },
7171
{ V4L2_PIX_FMT_MJPEG, PixelFormat::MJPEG }
72+
#ifdef V4L2_PIX_FMT_P010
73+
,{ V4L2_PIX_FMT_P010, PixelFormat::P010 }
74+
#endif
7275
};
7376

7477

0 commit comments

Comments
 (0)