ore untangling
This commit is contained in:
@@ -1,16 +1,13 @@
|
||||
#include "DeckLinkDisplayMode.h"
|
||||
#include "DeckLinkSession.h"
|
||||
#include "OpenGLComposite.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "GlRenderConstants.h"
|
||||
#include "OpenGLRenderPass.h"
|
||||
#include "OpenGLRenderPipeline.h"
|
||||
#include "OpenGLShaderPrograms.h"
|
||||
#include "OpenGLVideoIOBridge.h"
|
||||
#include "PngScreenshotWriter.h"
|
||||
#include "RenderEngine.h"
|
||||
#include "RuntimeParameterUtils.h"
|
||||
#include "RuntimeServices.h"
|
||||
#include "ShaderBuildQueue.h"
|
||||
#include "VideoBackend.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
@@ -97,8 +94,6 @@ JsonValue BuildOscCommitValue(const ShaderParameterDefinition& definition, const
|
||||
|
||||
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
||||
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
|
||||
mVideoIO(std::make_unique<DeckLinkSession>()),
|
||||
mRenderer(std::make_unique<OpenGLRenderer>()),
|
||||
mUseCommittedLayerStates(false),
|
||||
mScreenshotRequested(false)
|
||||
{
|
||||
@@ -106,22 +101,16 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
||||
mRuntimeHost = std::make_unique<RuntimeHost>();
|
||||
mRuntimeStore = std::make_unique<RuntimeStore>(*mRuntimeHost);
|
||||
mRuntimeSnapshotProvider = std::make_unique<RuntimeSnapshotProvider>(*mRuntimeHost);
|
||||
mRenderPipeline = std::make_unique<OpenGLRenderPipeline>(
|
||||
*mRenderer,
|
||||
mRenderEngine = std::make_unique<RenderEngine>(
|
||||
*mRuntimeHost,
|
||||
*mRuntimeSnapshotProvider,
|
||||
pMutex,
|
||||
hGLDC,
|
||||
hGLRC,
|
||||
[this]() { renderEffect(); },
|
||||
[this]() { ProcessScreenshotRequest(); },
|
||||
[this]() { paintGL(false); });
|
||||
mVideoIOBridge = std::make_unique<OpenGLVideoIOBridge>(
|
||||
*mVideoIO,
|
||||
*mRenderer,
|
||||
*mRenderPipeline,
|
||||
*mRuntimeHost,
|
||||
pMutex,
|
||||
hGLDC,
|
||||
hGLRC);
|
||||
mRenderPass = std::make_unique<OpenGLRenderPass>(*mRenderer);
|
||||
mShaderPrograms = std::make_unique<OpenGLShaderPrograms>(*mRenderer, *mRuntimeHost, *mRuntimeSnapshotProvider);
|
||||
mVideoBackend = std::make_unique<VideoBackend>(*mRenderEngine, mRuntimeHost->GetHealthTelemetry());
|
||||
mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider);
|
||||
mRuntimeServices = std::make_unique<RuntimeServices>();
|
||||
}
|
||||
@@ -132,8 +121,8 @@ OpenGLComposite::~OpenGLComposite()
|
||||
mRuntimeServices->Stop();
|
||||
if (mShaderBuildQueue)
|
||||
mShaderBuildQueue->Stop();
|
||||
mVideoIO->ReleaseResources();
|
||||
mRenderer->DestroyResources();
|
||||
if (mVideoBackend)
|
||||
mVideoBackend->ReleaseResources();
|
||||
|
||||
DeleteCriticalSection(&pMutex);
|
||||
}
|
||||
@@ -173,7 +162,7 @@ bool OpenGLComposite::InitVideoIO()
|
||||
}
|
||||
}
|
||||
|
||||
if (!mVideoIO->DiscoverDevicesAndModes(videoModes, initFailureReason))
|
||||
if (!mVideoBackend->DiscoverDevicesAndModes(videoModes, initFailureReason))
|
||||
{
|
||||
const char* title = initFailureReason == "Please install the Blackmagic DeckLink drivers to use the features of this application."
|
||||
? "This application requires the DeckLink drivers installed."
|
||||
@@ -182,7 +171,7 @@ bool OpenGLComposite::InitVideoIO()
|
||||
return false;
|
||||
}
|
||||
const bool outputAlphaRequired = mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured();
|
||||
if (!mVideoIO->SelectPreferredFormats(videoModes, outputAlphaRequired, initFailureReason))
|
||||
if (!mVideoBackend->SelectPreferredFormats(videoModes, outputAlphaRequired, initFailureReason))
|
||||
goto error;
|
||||
|
||||
if (! CheckOpenGLExtensions())
|
||||
@@ -197,38 +186,38 @@ bool OpenGLComposite::InitVideoIO()
|
||||
goto error;
|
||||
}
|
||||
|
||||
PublishVideoIOStatus(mVideoIO->OutputModelName().empty()
|
||||
PublishVideoIOStatus(mVideoBackend->OutputModelName().empty()
|
||||
? "DeckLink output device selected."
|
||||
: ("Selected output device: " + mVideoIO->OutputModelName()));
|
||||
: ("Selected output device: " + mVideoBackend->OutputModelName()));
|
||||
|
||||
// Resize window to match output video frame, but scale large formats down by half for viewing.
|
||||
if (mVideoIO->OutputFrameWidth() < 1920)
|
||||
resizeWindow(mVideoIO->OutputFrameWidth(), mVideoIO->OutputFrameHeight());
|
||||
if (mVideoBackend->OutputFrameWidth() < 1920)
|
||||
resizeWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight());
|
||||
else
|
||||
resizeWindow(mVideoIO->OutputFrameWidth() / 2, mVideoIO->OutputFrameHeight() / 2);
|
||||
resizeWindow(mVideoBackend->OutputFrameWidth() / 2, mVideoBackend->OutputFrameHeight() / 2);
|
||||
|
||||
if (!mVideoIO->ConfigureInput([this](const VideoIOFrame& frame) { mVideoIOBridge->VideoFrameArrived(frame); }, videoModes.input, initFailureReason))
|
||||
if (!mVideoBackend->ConfigureInput(videoModes.input, initFailureReason))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
if (!mVideoIO->HasInputDevice() && mRuntimeHost)
|
||||
if (!mVideoBackend->HasInputDevice() && mRuntimeHost)
|
||||
{
|
||||
mRuntimeHost->SetSignalStatus(false, mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), mVideoIO->InputDisplayModeName());
|
||||
mRuntimeHost->SetSignalStatus(false, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), mVideoBackend->InputDisplayModeName());
|
||||
}
|
||||
|
||||
if (!mVideoIO->ConfigureOutput([this](const VideoIOCompletion& completion) { mVideoIOBridge->PlayoutFrameCompleted(completion); }, videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
||||
if (!mVideoBackend->ConfigureOutput(videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
PublishVideoIOStatus(mVideoIO->StatusMessage());
|
||||
PublishVideoIOStatus(mVideoBackend->StatusMessage());
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (!initFailureReason.empty())
|
||||
MessageBoxA(NULL, initFailureReason.c_str(), "DeckLink initialization failed", MB_OK | MB_ICONERROR);
|
||||
mVideoIO->ReleaseResources();
|
||||
mVideoBackend->ReleaseResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -252,23 +241,21 @@ void OpenGLComposite::paintGL(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryEnterCriticalSection(&pMutex))
|
||||
if (!mRenderEngine->TryPresentToWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
|
||||
{
|
||||
ValidateRect(hGLWnd, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
mRenderer->PresentToWindow(hGLDC, mVideoIO->OutputFrameWidth(), mVideoIO->OutputFrameHeight());
|
||||
mLastPreviewPresentTime = std::chrono::steady_clock::now();
|
||||
ValidateRect(hGLWnd, NULL);
|
||||
LeaveCriticalSection(&pMutex);
|
||||
}
|
||||
|
||||
void OpenGLComposite::resizeGL(WORD width, WORD height)
|
||||
{
|
||||
// We don't set the project or model matrices here since the window data is copied directly from
|
||||
// an off-screen FBO in paintGL(). Just save the width and height for use in paintGL().
|
||||
mRenderer->ResizeView(width, height);
|
||||
mRenderEngine->ResizeView(width, height);
|
||||
}
|
||||
|
||||
void OpenGLComposite::resizeWindow(int width, int height)
|
||||
@@ -286,17 +273,17 @@ void OpenGLComposite::PublishVideoIOStatus(const std::string& statusMessage)
|
||||
return;
|
||||
|
||||
if (!statusMessage.empty())
|
||||
mVideoIO->SetStatusMessage(statusMessage);
|
||||
mVideoBackend->SetStatusMessage(statusMessage);
|
||||
|
||||
mRuntimeHost->SetVideoIOStatus(
|
||||
"decklink",
|
||||
mVideoIO->OutputModelName(),
|
||||
mVideoIO->SupportsInternalKeying(),
|
||||
mVideoIO->SupportsExternalKeying(),
|
||||
mVideoIO->KeyerInterfaceAvailable(),
|
||||
mVideoBackend->OutputModelName(),
|
||||
mVideoBackend->SupportsInternalKeying(),
|
||||
mVideoBackend->SupportsExternalKeying(),
|
||||
mVideoBackend->KeyerInterfaceAvailable(),
|
||||
mRuntimeStore ? mRuntimeStore->IsExternalKeyingConfigured() : false,
|
||||
mVideoIO->ExternalKeyingActive(),
|
||||
mVideoIO->StatusMessage());
|
||||
mVideoBackend->ExternalKeyingActive(),
|
||||
mVideoBackend->StatusMessage());
|
||||
}
|
||||
|
||||
bool OpenGLComposite::InitOpenGLState()
|
||||
@@ -319,41 +306,41 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
|
||||
// Prepare the runtime shader program generated from the active shader package.
|
||||
char compilerErrorMessage[1024];
|
||||
if (!mShaderPrograms->CompileDecodeShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
if (!mRenderEngine->CompileDecodeShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL decode shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
if (!mShaderPrograms->CompileOutputPackShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
if (!mRenderEngine->CompileOutputPackShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL output pack shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string rendererError;
|
||||
if (!mRenderer->InitializeResources(
|
||||
mVideoIO->InputFrameWidth(),
|
||||
mVideoIO->InputFrameHeight(),
|
||||
mVideoIO->CaptureTextureWidth(),
|
||||
mVideoIO->OutputFrameWidth(),
|
||||
mVideoIO->OutputFrameHeight(),
|
||||
mVideoIO->OutputPackTextureWidth(),
|
||||
if (!mRenderEngine->InitializeResources(
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mVideoBackend->CaptureTextureWidth(),
|
||||
mVideoBackend->OutputFrameWidth(),
|
||||
mVideoBackend->OutputFrameHeight(),
|
||||
mVideoBackend->OutputPackTextureWidth(),
|
||||
rendererError))
|
||||
{
|
||||
MessageBoxA(NULL, rendererError.c_str(), "OpenGL initialization error.", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mShaderPrograms->CompileLayerPrograms(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
if (!mRenderEngine->CompileLayerPrograms(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
||||
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||
mUseCommittedLayerStates = false;
|
||||
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
|
||||
broadcastRuntimeState();
|
||||
mRuntimeServices->BeginPolling(*mRuntimeHost);
|
||||
@@ -362,7 +349,7 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
|
||||
bool OpenGLComposite::Start()
|
||||
{
|
||||
return mVideoIO->Start();
|
||||
return mVideoBackend->Start();
|
||||
}
|
||||
|
||||
bool OpenGLComposite::Stop()
|
||||
@@ -370,8 +357,8 @@ bool OpenGLComposite::Stop()
|
||||
if (mRuntimeServices)
|
||||
mRuntimeServices->Stop();
|
||||
|
||||
const bool wasExternalKeyingActive = mVideoIO->ExternalKeyingActive();
|
||||
mVideoIO->Stop();
|
||||
const bool wasExternalKeyingActive = mVideoBackend->ExternalKeyingActive();
|
||||
mVideoBackend->Stop();
|
||||
if (wasExternalKeyingActive)
|
||||
PublishVideoIOStatus("External keying has been disabled.");
|
||||
|
||||
@@ -587,19 +574,19 @@ void OpenGLComposite::renderEffect()
|
||||
mOscOverlayStates.erase(overlayKey);
|
||||
};
|
||||
|
||||
const bool hasInputSource = mVideoIO->HasInputSource();
|
||||
const bool hasInputSource = mVideoBackend->HasInputSource();
|
||||
std::vector<RuntimeRenderState> layerStates;
|
||||
if (mUseCommittedLayerStates)
|
||||
{
|
||||
layerStates = mShaderPrograms->CommittedLayerStates();
|
||||
layerStates = mRenderEngine->CommittedLayerStates();
|
||||
applyOscOverlays(layerStates, false);
|
||||
if (mRuntimeSnapshotProvider)
|
||||
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
||||
}
|
||||
else if (mRuntimeSnapshotProvider)
|
||||
{
|
||||
const unsigned renderWidth = mVideoIO->InputFrameWidth();
|
||||
const unsigned renderHeight = mVideoIO->InputFrameHeight();
|
||||
const unsigned renderWidth = mVideoBackend->InputFrameWidth();
|
||||
const unsigned renderHeight = mVideoBackend->InputFrameHeight();
|
||||
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider->GetVersions();
|
||||
const bool renderStateCacheValid =
|
||||
!mCachedLayerRenderStates.empty() &&
|
||||
@@ -650,20 +637,14 @@ void OpenGLComposite::renderEffect()
|
||||
}
|
||||
}
|
||||
const unsigned historyCap = mRuntimeStore ? mRuntimeStore->GetConfiguredMaxTemporalHistoryFrames() : 0;
|
||||
mRenderPass->Render(
|
||||
mRenderEngine->RenderLayerStack(
|
||||
hasInputSource,
|
||||
layerStates,
|
||||
mVideoIO->InputFrameWidth(),
|
||||
mVideoIO->InputFrameHeight(),
|
||||
mVideoIO->CaptureTextureWidth(),
|
||||
mVideoIO->InputPixelFormat(),
|
||||
historyCap,
|
||||
[this](const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error) {
|
||||
return mShaderPrograms->UpdateTextBindingTexture(state, textBinding, error);
|
||||
},
|
||||
[this](const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable) {
|
||||
return mShaderPrograms->UpdateGlobalParamsBuffer(state, availableSourceHistoryLength, availableTemporalHistoryLength, feedbackAvailable);
|
||||
});
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mVideoBackend->CaptureTextureWidth(),
|
||||
mVideoBackend->InputPixelFormat(),
|
||||
historyCap);
|
||||
}
|
||||
|
||||
void OpenGLComposite::ProcessScreenshotRequest()
|
||||
@@ -671,21 +652,16 @@ void OpenGLComposite::ProcessScreenshotRequest()
|
||||
if (!mScreenshotRequested.exchange(false))
|
||||
return;
|
||||
|
||||
const unsigned width = mVideoIO ? mVideoIO->OutputFrameWidth() : 0;
|
||||
const unsigned height = mVideoIO ? mVideoIO->OutputFrameHeight() : 0;
|
||||
const unsigned width = mVideoBackend ? mVideoBackend->OutputFrameWidth() : 0;
|
||||
const unsigned height = mVideoBackend ? mVideoBackend->OutputFrameHeight() : 0;
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
std::vector<unsigned char> bottomUpPixels(static_cast<std::size_t>(width) * height * 4);
|
||||
std::vector<unsigned char> bottomUpPixels;
|
||||
if (!mRenderEngine->ReadOutputFrameRgba(width, height, bottomUpPixels))
|
||||
return;
|
||||
std::vector<unsigned char> topDownPixels(bottomUpPixels.size());
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer->OutputFramebuffer());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bottomUpPixels.data());
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
|
||||
for (unsigned y = 0; y < height; ++y)
|
||||
{
|
||||
@@ -752,7 +728,7 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
return true;
|
||||
|
||||
char compilerErrorMessage[1024] = {};
|
||||
if (!mShaderPrograms->CommitPreparedLayerPrograms(readyBuild, mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
if (!mRenderEngine->CommitPreparedLayerPrograms(readyBuild, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
mRuntimeStore->SetCompileStatus(false, compilerErrorMessage);
|
||||
mUseCommittedLayerStates = true;
|
||||
@@ -762,10 +738,10 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
}
|
||||
|
||||
mUseCommittedLayerStates = false;
|
||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
if (!mPreserveFeedbackOnNextShaderBuild)
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
@@ -780,13 +756,13 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
|
||||
void OpenGLComposite::RequestShaderBuild()
|
||||
{
|
||||
if (!mShaderBuildQueue || !mVideoIO)
|
||||
if (!mShaderBuildQueue || !mVideoBackend)
|
||||
return;
|
||||
|
||||
mUseCommittedLayerStates = true;
|
||||
if (mRuntimeHost)
|
||||
mRuntimeStore->ClearReloadRequest();
|
||||
mShaderBuildQueue->RequestBuild(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight());
|
||||
mShaderBuildQueue->RequestBuild(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight());
|
||||
}
|
||||
|
||||
void OpenGLComposite::broadcastRuntimeState()
|
||||
@@ -797,8 +773,8 @@ void OpenGLComposite::broadcastRuntimeState()
|
||||
|
||||
void OpenGLComposite::resetTemporalHistoryState()
|
||||
{
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
}
|
||||
|
||||
bool OpenGLComposite::CheckOpenGLExtensions()
|
||||
|
||||
Reference in New Issue
Block a user