From 1785dd2c015c337879259ea6fe1cc144dd501153 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:02:15 +0100 Subject: [PATCH] Needed changes before multi-monitor support --- include/grabber/windows/DX/DxGrabber.h | 66 ++++++++-- sources/grabber/windows/DX/DxGrabber.cpp | 157 ++++++++++------------- 2 files changed, 123 insertions(+), 100 deletions(-) diff --git a/include/grabber/windows/DX/DxGrabber.h b/include/grabber/windows/DX/DxGrabber.h index 74cbe9915..609b5abb2 100644 --- a/include/grabber/windows/DX/DxGrabber.h +++ b/include/grabber/windows/DX/DxGrabber.h @@ -18,6 +18,8 @@ #include #include #include + #include + #include #endif // util includes @@ -25,6 +27,50 @@ #include #include +template void SafeRelease(T** ppT) +{ + if (*ppT) + { + (*ppT)->Release(); + *ppT = NULL; + } +} + +struct DisplayHandle +{ + QString name; + 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 @@ -56,6 +102,9 @@ public slots: void restart(); private: + + void captureFrame(DisplayHandle& display); + QString GetSharedLut(); void enumerateDevices(bool silent); @@ -70,29 +119,18 @@ 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 _dxRestartNow; + std::list> _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 _cacheImage; }; diff --git a/sources/grabber/windows/DX/DxGrabber.cpp b/sources/grabber/windows/DX/DxGrabber.cpp index a1d817795..e19da8d99 100644 --- a/sources/grabber/windows/DX/DxGrabber.cpp +++ b/sources/grabber/windows/DX/DxGrabber.cpp @@ -58,38 +58,18 @@ #define CLEAR(x) memset(&(x), 0, sizeof(x)) #define MAX_WARNINGS 6 -template void SafeRelease(T** ppT) -{ - if (*ppT) - { - (*ppT)->Release(); - *ppT = NULL; - } -} - DxGrabber::DxGrabber(const QString& device, const QString& configurationPath) : Grabber(configurationPath, "DX11_SYSTEM:" + device.left(14)) , _configurationPath(configurationPath) , _timer(new QTimer(this)) , _retryTimer(new QTimer(this)) , _warningCounter(MAX_WARNINGS) - , _actualDivide(-1) , _wideGamut(false) , _dxRestartNow(false) , _d3dDevice(nullptr) , _d3dContext(nullptr) - , _d3dBuffer(nullptr) - , _d3dSampler(nullptr) - , _d3dVertexLayout(nullptr) - , _d3dVertexShader(nullptr) - , _d3dPixelShader(nullptr) - , _d3dSourceTexture(nullptr) - , _d3dConvertTexture(nullptr) - , _d3dConvertTextureView(nullptr) - , _d3dRenderTargetView(nullptr) - , _d3dDuplicate(nullptr) { _timer->setTimerType(Qt::PreciseTimer); connect(_timer, &QTimer::timeout, this, &DxGrabber::grabFrame); @@ -149,21 +129,11 @@ void DxGrabber::uninit() Debug(_log, "Uninit grabber: %s", QSTRING_CSTR(_deviceName)); } - SafeRelease(&_d3dRenderTargetView); - SafeRelease(&_d3dSourceTexture); - SafeRelease(&_d3dConvertTextureView); - SafeRelease(&_d3dConvertTexture); - SafeRelease(&_d3dVertexShader); - SafeRelease(&_d3dVertexLayout); - SafeRelease(&_d3dPixelShader); - SafeRelease(&_d3dSampler); - SafeRelease(&_d3dBuffer); - SafeRelease(&_d3dDuplicate); + _handles.clear(); SafeRelease(&_d3dContext); SafeRelease(&_d3dDevice); _warningCounter = MAX_WARNINGS; - _actualDivide = -1; _initialized = false; if (_dxRestartNow) @@ -342,7 +312,9 @@ bool DxGrabber::initDirectX(QString selectedDeviceName) DXGI_OUTPUT_DESC oDesc; pOutput->GetDesc(&oDesc); - exitNow = (QString::fromWCharArray(oDesc.DeviceName) + "|" + QString::fromWCharArray(pDesc.Description)) == selectedDeviceName; + QString currentName = (QString::fromWCharArray(oDesc.DeviceName) + "|" + QString::fromWCharArray(pDesc.Description)); + + exitNow = (currentName == selectedDeviceName); if (exitNow) { @@ -399,13 +371,16 @@ bool DxGrabber::initDirectX(QString selectedDeviceName) _wideGamut = false; } + std::unique_ptr display = std::make_unique(); + + display->name = currentName; if (_hardware && _wideGamut) { Info(_log, "Using wide gamut for HDR. Target SDR brightness: %i nits", _targetMonitorNits); std::vector wideFormat({ DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R10G10B10A2_UNORM }); - status = pOutput6->DuplicateOutput1(_d3dDevice, 0, static_cast(wideFormat.size()), wideFormat.data(), &_d3dDuplicate); + status = pOutput6->DuplicateOutput1(_d3dDevice, 0, static_cast(wideFormat.size()), wideFormat.data(), &display->d3dDuplicate); if (!CHECK(status)) { @@ -419,40 +394,40 @@ bool DxGrabber::initDirectX(QString selectedDeviceName) Info(_log, "Using BGRA format"); DXGI_FORMAT rgbFormat = DXGI_FORMAT_B8G8R8A8_UNORM; - status = pOutput6->DuplicateOutput1(_d3dDevice, 0, 1, &rgbFormat, &_d3dDuplicate); + status = pOutput6->DuplicateOutput1(_d3dDevice, 0, 1, &rgbFormat, &display->d3dDuplicate); } if (CHECK(status)) { - CLEAR(_surfaceProperties); - _d3dDuplicate->GetDesc(&_surfaceProperties); + CLEAR(display->surfaceProperties); + display->d3dDuplicate->GetDesc(&display->surfaceProperties); - Info(_log, "Surface format: %i", _surfaceProperties.ModeDesc.Format); + Info(_log, "Surface format: %i", display->surfaceProperties.ModeDesc.Format); - int targetSizeX = _surfaceProperties.ModeDesc.Width, targetSizeY = _surfaceProperties.ModeDesc.Height; + int targetSizeX = display->surfaceProperties.ModeDesc.Width, targetSizeY = display->surfaceProperties.ModeDesc.Height; if (_hardware) { - _actualWidth = targetSizeX; - _actualHeight = targetSizeY; + display->actualWidth = targetSizeX; + display->actualHeight = targetSizeY; if (!_wideGamut) { - int maxSize = std::max((_actualWidth - _cropLeft - _cropRight), (_actualHeight - _cropTop - _cropBottom)); + int maxSize = std::max((display->actualWidth - _cropLeft - _cropRight), (display->actualHeight - _cropTop - _cropBottom)); - _actualDivide = 0; + display->actualDivide = 0; while (maxSize > _width) { - _actualDivide++; + display->actualDivide++; maxSize >>= 1; } - targetSizeX = _surfaceProperties.ModeDesc.Width >> _actualDivide; - targetSizeY = _surfaceProperties.ModeDesc.Height >> _actualDivide; + targetSizeX = display->surfaceProperties.ModeDesc.Width >> display->actualDivide; + targetSizeY = display->surfaceProperties.ModeDesc.Height >> display->actualDivide; } else { - _actualDivide = -1; + display->actualDivide = -1; getTargetSystemFrameDimension(targetSizeX, targetSizeY); } } @@ -470,22 +445,23 @@ bool DxGrabber::initDirectX(QString selectedDeviceName) sourceTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; sourceTextureDesc.MiscFlags = 0; sourceTextureDesc.BindFlags = 0; - if (CHECK(_d3dDevice->CreateTexture2D(&sourceTextureDesc, NULL, &_d3dSourceTexture))) + if (CHECK(_d3dDevice->CreateTexture2D(&sourceTextureDesc, NULL, &display->d3dSourceTexture))) { _actualVideoFormat = PixelFormat::XRGB; - _actualWidth = sourceTextureDesc.Width; - _actualHeight = sourceTextureDesc.Height; + display->actualWidth = _actualWidth = sourceTextureDesc.Width; + display->actualHeight = _actualHeight = sourceTextureDesc.Height; loadLutFile(PixelFormat::RGB24); - _frameByteSize = _actualWidth * _actualHeight * 4; - _lineLength = _actualWidth * 4; + _frameByteSize = display->actualWidth * display->actualHeight * 4; + _lineLength = display->actualWidth * 4; if (_hardware) { - result = initShaders(); + result = initShaders(*display); if (result) { - Info(_log, "The DX11 device has been initialized. Hardware acceleration is enabled"); + Info(_log, "The DX11 device has been initialized. Hardware acceleration is enabled"); + _handles.emplace_back(std::move(display)); } else { @@ -537,16 +513,16 @@ bool DxGrabber::initDirectX(QString selectedDeviceName) return result; } -bool DxGrabber::initShaders() +bool DxGrabber::initShaders(DisplayHandle& display) { HRESULT status; std::unique_ptr descConvert; - if (_actualDivide < 0) + if (display.actualDivide < 0) descConvert = std::make_unique( DXGI_FORMAT_B8G8R8A8_UNORM, - _actualWidth, _actualHeight, + display.actualWidth, display.actualHeight, 1, 1, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, @@ -556,9 +532,9 @@ bool DxGrabber::initShaders() else descConvert = std::make_unique( DXGI_FORMAT_B8G8R8A8_UNORM, - _surfaceProperties.ModeDesc.Width, _surfaceProperties.ModeDesc.Height, + display.surfaceProperties.ModeDesc.Width, display.surfaceProperties.ModeDesc.Height, 1, - _actualDivide + 1, + display.actualDivide + 1, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, @@ -566,19 +542,19 @@ bool DxGrabber::initShaders() 0, D3D11_RESOURCE_MISC_GENERATE_MIPS); - status = _d3dDevice->CreateTexture2D(descConvert.get(), nullptr, &_d3dConvertTexture); + status = _d3dDevice->CreateTexture2D(descConvert.get(), nullptr, &display.d3dConvertTexture); if (CHECK(status)) { - if (_actualDivide < 0) + if (display.actualDivide < 0) { CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc( D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_B8G8R8A8_UNORM); - status = _d3dDevice->CreateRenderTargetView(_d3dConvertTexture, &rtvDesc, &_d3dRenderTargetView); + status = _d3dDevice->CreateRenderTargetView(display.d3dConvertTexture, &rtvDesc, &display.d3dRenderTargetView); if (CHECK(status)) { - _d3dContext->OMSetRenderTargets(1, &_d3dRenderTargetView, NULL); + _d3dContext->OMSetRenderTargets(1, &display.d3dRenderTargetView, NULL); } else Error(_log, "CreateRenderTargetView failed. Reason: %x", status); @@ -592,7 +568,7 @@ bool DxGrabber::initShaders() shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shaderDesc.Texture2D.MipLevels = descConvert->MipLevels;; - status = _d3dDevice->CreateShaderResourceView(_d3dConvertTexture, &shaderDesc, &_d3dConvertTextureView); + status = _d3dDevice->CreateShaderResourceView(display.d3dConvertTexture, &shaderDesc, &display.d3dConvertTextureView); return CHECK(status); } } @@ -601,10 +577,10 @@ bool DxGrabber::initShaders() if (CHECK(status)) { - status = _d3dDevice->CreateVertexShader(g_VertexShaderHyperHDR, sizeof(g_VertexShaderHyperHDR), nullptr, &_d3dVertexShader); + status = _d3dDevice->CreateVertexShader(g_VertexShaderHyperHDR, sizeof(g_VertexShaderHyperHDR), nullptr, &display.d3dVertexShader); if (CHECK(status)) { - _d3dContext->VSSetShader(_d3dVertexShader, NULL, 0); + _d3dContext->VSSetShader(display.d3dVertexShader, NULL, 0); _d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); } else @@ -613,10 +589,10 @@ bool DxGrabber::initShaders() if (CHECK(status)) { - status = _d3dDevice->CreatePixelShader(g_PixelShaderHyperHDR, sizeof(g_PixelShaderHyperHDR), nullptr, &_d3dPixelShader); + status = _d3dDevice->CreatePixelShader(g_PixelShaderHyperHDR, sizeof(g_PixelShaderHyperHDR), nullptr, &display.d3dPixelShader); if (CHECK(status)) { - _d3dContext->PSSetShader(_d3dPixelShader, NULL, 0); + _d3dContext->PSSetShader(display.d3dPixelShader, NULL, 0); } else Error(_log, "Could not create pixel shaders. Reason: %x", status); @@ -627,9 +603,9 @@ bool DxGrabber::initShaders() D3D11_INPUT_ELEMENT_DESC layout[] = { {"SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; UINT numElements = ARRAYSIZE(layout); - status = _d3dDevice->CreateInputLayout(layout, numElements, g_VertexShaderHyperHDR, sizeof(g_VertexShaderHyperHDR), &_d3dVertexLayout); + status = _d3dDevice->CreateInputLayout(layout, numElements, g_VertexShaderHyperHDR, sizeof(g_VertexShaderHyperHDR), &display.d3dVertexLayout); if (CHECK(status)) - _d3dContext->IASetInputLayout(_d3dVertexLayout); + _d3dContext->IASetInputLayout(display.d3dVertexLayout); else Error(_log, "Could not create vertex layout. Reason: %x", status); } @@ -646,16 +622,16 @@ bool DxGrabber::initShaders() sDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sDesc.MinLOD = 0; sDesc.MaxLOD = D3D11_FLOAT32_MAX; - status = _d3dDevice->CreateSamplerState(&sDesc, &_d3dSampler); + status = _d3dDevice->CreateSamplerState(&sDesc, &display.d3dSampler); if (CHECK(status)) - _d3dContext->PSSetSamplers(0, 1, &_d3dSampler); + _d3dContext->PSSetSamplers(0, 1, &display.d3dSampler); else Error(_log, "Could not create the sampler. Reason: %x", status); } if (CHECK(status)) { - DirectX::XMFLOAT4 params = { static_cast(_targetMonitorNits), 18.8515625f - 18.6875f * _targetMonitorNits, 0.0, 0.0 }; + DirectX::XMFLOAT4 params = { static_cast(display.targetMonitorNits), 18.8515625f - 18.6875f * display.targetMonitorNits, 0.0, 0.0 }; D3D11_BUFFER_DESC cbDesc; CLEAR(cbDesc); @@ -668,11 +644,11 @@ bool DxGrabber::initShaders() CLEAR(initData); initData.pSysMem = ¶ms; - status = _d3dDevice->CreateBuffer(&cbDesc, &initData, &_d3dBuffer); + status = _d3dDevice->CreateBuffer(&cbDesc, &initData, &display.d3dBuffer); if (CHECK(status)) { - _d3dContext->VSSetConstantBuffers(0, 1, &_d3dBuffer); + _d3dContext->VSSetConstantBuffers(0, 1, &display.d3dBuffer); } else Error(_log, "Could not create constant buffer. Reason: %x", status); @@ -699,15 +675,15 @@ bool DxGrabber::initShaders() return false; } -HRESULT DxGrabber::deepScaledCopy(ID3D11Texture2D* source) +HRESULT DxGrabber::deepScaledCopy(DisplayHandle& display, ID3D11Texture2D* source) { HRESULT status = S_OK; - if (_actualDivide >= 0) + if (display.actualDivide >= 0) { - _d3dContext->CopySubresourceRegion(_d3dConvertTexture, 0, 0, 0, 0, source, 0, NULL); - _d3dContext->GenerateMips(_d3dConvertTextureView); - _d3dContext->CopySubresourceRegion(_d3dSourceTexture, 0, 0, 0, 0, _d3dConvertTexture, _actualDivide, NULL); + _d3dContext->CopySubresourceRegion(display.d3dConvertTexture, 0, 0, 0, 0, source, 0, NULL); + _d3dContext->GenerateMips(display.d3dConvertTextureView); + _d3dContext->CopySubresourceRegion(display.d3dSourceTexture, 0, 0, 0, 0, display.d3dConvertTexture, display.actualDivide, NULL); } else { @@ -742,18 +718,27 @@ HRESULT DxGrabber::deepScaledCopy(ID3D11Texture2D* source) _d3dContext->PSSetShaderResources(0, 1, &rv); _d3dContext->Draw(4, 0); - _d3dContext->CopyResource(_d3dSourceTexture, _d3dConvertTexture); + _d3dContext->CopyResource(display.d3dSourceTexture, display.d3dConvertTexture); SafeRelease(&rv); } return status; } + void DxGrabber::grabFrame() +{ + if (_handles.size() > 0) + { + captureFrame(*_handles.front()); + } +} + +void DxGrabber::captureFrame(DisplayHandle& display) { DXGI_OUTDUPL_FRAME_INFO infoFrame{}; IDXGIResource* resourceDesktop = nullptr; - auto status = _d3dDuplicate->AcquireNextFrame(0, &infoFrame, &resourceDesktop); + auto status = display.d3dDuplicate->AcquireNextFrame(0, &infoFrame, &resourceDesktop); if (CHECK(status)) { @@ -768,17 +753,17 @@ void DxGrabber::grabFrame() { if (_hardware) { - status = deepScaledCopy(texDesktop); + status = deepScaledCopy(display, texDesktop); } else { - _d3dContext->CopyResource(_d3dSourceTexture, texDesktop); + _d3dContext->CopyResource(display.d3dSourceTexture, texDesktop); } - if (CHECK(status) && CHECK(_d3dContext->Map(_d3dSourceTexture, 0, D3D11_MAP_READ, 0, &internalMap))) + if (CHECK(status) && CHECK(_d3dContext->Map(display.d3dSourceTexture, 0, D3D11_MAP_READ, 0, &internalMap))) { processSystemFrameBGRA((uint8_t*)internalMap.pData, (int)internalMap.RowPitch, !(_hardware && _wideGamut)); - _d3dContext->Unmap(_d3dSourceTexture, 0); + _d3dContext->Unmap(display.d3dSourceTexture, 0); } SafeRelease(&texDesktop); @@ -815,7 +800,7 @@ void DxGrabber::grabFrame() SafeRelease(&resourceDesktop); - _d3dDuplicate->ReleaseFrame(); + display.d3dDuplicate->ReleaseFrame(); if (_dxRestartNow) {