Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DirectX multi-monitor support #966

Merged
merged 5 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/base/Grabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ public slots:

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

int getTargetSystemFrameDimension(int actualWidth, int actualHeight, int& targetSizeX, int& targetSizeY);

void processSystemFrameBGRA(uint8_t* source, int lineSize = 0, bool useLut = true);

void processSystemFrameBGR(uint8_t* source, int lineSize = 0);
Expand Down
75 changes: 59 additions & 16 deletions include/grabber/windows/DX/DxGrabber.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,61 @@
#include <vector>
#include <map>
#include <chrono>
#include <list>
#include <algorithm>
#endif

// util includes
#include <utils/PixelFormat.h>
#include <base/Grabber.h>
#include <utils/Components.h>

template <class T> void SafeRelease(T** ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}

struct DisplayHandle
{
QString name;
int warningCounter = 6;
bool wideGamut = false;
int actualDivide = -1, actualWidth = 0, actualHeight = 0;
uint targetMonitorNits = 0;
ID3D11Texture2D* d3dConvertTexture = nullptr;
ID3D11RenderTargetView* d3dRenderTargetView = nullptr;
ID3D11ShaderResourceView* d3dConvertTextureView = nullptr;
ID3D11VertexShader* d3dVertexShader = nullptr;
ID3D11PixelShader* d3dPixelShader = nullptr;
ID3D11Buffer* d3dBuffer = nullptr;
ID3D11SamplerState* d3dSampler = nullptr;
ID3D11InputLayout* d3dVertexLayout = nullptr;
IDXGIOutputDuplication* d3dDuplicate = nullptr;
ID3D11Texture2D* d3dSourceTexture = nullptr;
DXGI_OUTDUPL_DESC surfaceProperties{};

DisplayHandle() = default;
DisplayHandle(const DisplayHandle&) = delete;
~DisplayHandle()
{
SafeRelease(&d3dRenderTargetView);
SafeRelease(&d3dSourceTexture);
SafeRelease(&d3dConvertTextureView);
SafeRelease(&d3dConvertTexture);
SafeRelease(&d3dVertexShader);
SafeRelease(&d3dVertexLayout);
SafeRelease(&d3dPixelShader);
SafeRelease(&d3dSampler);
SafeRelease(&d3dBuffer);
SafeRelease(&d3dDuplicate);
printf("SmartPointer is removing: DisplayHandle for %s\n", QSTRING_CSTR(name));
};
};

class DxGrabber : public Grabber
{
Q_OBJECT
Expand Down Expand Up @@ -56,6 +104,13 @@ public slots:
void restart();

private:

const QString MULTI_MONITOR = "MULTI-MONITOR";

void captureFrame(DisplayHandle& display);

int captureFrame(DisplayHandle& display, Image<ColorRgb>& image);

QString GetSharedLut();

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

bool initDirectX(QString selectedDeviceName);

bool initShaders();
HRESULT deepScaledCopy(ID3D11Texture2D* source);
bool initShaders(DisplayHandle& display);
HRESULT deepScaledCopy(DisplayHandle& display, ID3D11Texture2D* source);

QString _configurationPath;
QTimer* _timer;
QTimer* _retryTimer;
int _warningCounter;
int _actualDivide;
bool _wideGamut;
bool _multiMonitor;

bool _dxRestartNow;
std::list<std::unique_ptr<DisplayHandle>> _handles;
ID3D11Device* _d3dDevice;
ID3D11DeviceContext* _d3dContext;
ID3D11Buffer* _d3dBuffer;
ID3D11SamplerState* _d3dSampler;
ID3D11InputLayout* _d3dVertexLayout;
ID3D11VertexShader* _d3dVertexShader;
ID3D11PixelShader* _d3dPixelShader;
ID3D11Texture2D* _d3dSourceTexture;
ID3D11Texture2D* _d3dConvertTexture;
ID3D11ShaderResourceView* _d3dConvertTextureView;
ID3D11RenderTargetView* _d3dRenderTargetView;
IDXGIOutputDuplication* _d3dDuplicate;
DXGI_OUTDUPL_DESC _surfaceProperties;
Image<ColorRgb> _cacheImage;
};
2 changes: 2 additions & 0 deletions include/image/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Image

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

void insertHorizontal(int x, Image<ColorSpace>& source);

unsigned width() const;

unsigned height() const;
Expand Down
9 changes: 9 additions & 0 deletions include/utils/PixelFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum class PixelFormat {
I420,
NV12,
MJPEG,
P010,
NO_CHANGE
};

Expand Down Expand Up @@ -42,6 +43,10 @@ inline PixelFormat parsePixelFormat(const QString& pixelFormat)
{
return PixelFormat::MJPEG;
}
else if (format.compare("p010") == 0)
{
return PixelFormat::P010;
}

return PixelFormat::NO_CHANGE;
}
Expand Down Expand Up @@ -73,6 +78,10 @@ inline QString pixelFormatToString(const PixelFormat& pixelFormat)
{
return "mjpeg";
}
else if (pixelFormat == PixelFormat::P010)
{
return "p010";
}

return "NO_CHANGE";
}
64 changes: 62 additions & 2 deletions sources/base/Grabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,24 @@ void Grabber::setEnabled(bool enable)

void Grabber::setMonitorNits(int nits)
{
_targetMonitorNits = nits;
if (_targetMonitorNits != nits)
{
_targetMonitorNits = nits;

Debug(_log, "Set nits to %i", _targetMonitorNits);

if (_initialized && !_blocked)
{
Debug(_log, "Restarting video grabber");
uninit();
start();
}
else
{
Info(_log, "Delayed restart of the grabber due to change of monitor nits value");
_restartNeeded = true;
}
}
}

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

void Grabber::enableHardwareAcceleration(bool hardware)
{
_hardware = hardware;
if (_hardware != hardware)
{
_hardware = hardware;

Debug(_log, "Set hardware acceleration to %s", _hardware ? "enabled" : "disabled");

if (_initialized && !_blocked)
{
Debug(_log, "Restarting video grabber");
uninit();
start();
}
else
{
Info(_log, "Delayed restart of the grabber due to change of the hardware acceleration");
_restartNeeded = true;
}
}
}

bool Grabber::trySetInput(int input)
Expand Down Expand Up @@ -518,6 +552,32 @@ int Grabber::getTargetSystemFrameDimension(int& targetSizeX, int& targetSizeY)
return divide;
}

int Grabber::getTargetSystemFrameDimension(int actualWidth, int actualHeight, int& targetSizeX, int& targetSizeY)
{
int realSizeX = actualWidth;
int realSizeY = actualHeight;

if (realSizeX <= 16 || realSizeY <= 16)
{
realSizeX = actualWidth;
realSizeY = actualHeight;
}

int checkWidth = realSizeX;
int divide = 1;

while (checkWidth > _width)
{
divide++;
checkWidth = realSizeX / divide;
}

targetSizeX = realSizeX / divide;
targetSizeY = realSizeY / divide;

return divide;
}

void Grabber::processSystemFrameBGRA(uint8_t* source, int lineSize, bool useLut)
{
int targetSizeX, targetSizeY;
Expand Down
3 changes: 3 additions & 0 deletions sources/grabber/linux/v4l2/V4L2Grabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ static const V4L2Grabber::HyperHdrFormat supportedFormats[] =
{ V4L2_PIX_FMT_YUV420, PixelFormat::I420 },
{ V4L2_PIX_FMT_NV12, PixelFormat::NV12 },
{ V4L2_PIX_FMT_MJPEG, PixelFormat::MJPEG }
#ifdef V4L2_PIX_FMT_P010
,{ V4L2_PIX_FMT_P010, PixelFormat::P010 }
#endif
};


Expand Down
Loading