186 lines
5.1 KiB
C++
186 lines
5.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "StreamingPauseRendering.h"
|
|
#include "Layout/Margin.h"
|
|
#include "ViewportClient.h"
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "RenderingThread.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "EngineGlobals.h"
|
|
#include "CanvasTypes.h"
|
|
#include "Rendering/RenderingCommon.h"
|
|
#include "Widgets/SBoxPanel.h"
|
|
#include "Widgets/SViewport.h"
|
|
#include "Slate/SceneViewport.h"
|
|
#include "Slate/SlateTextures.h"
|
|
#include "MoviePlayer.h"
|
|
#include "Widgets/Images/SThrobber.h"
|
|
|
|
|
|
IMPLEMENT_MODULE(FStreamingPauseRenderingModule, StreamingPauseRendering);
|
|
|
|
class FBackgroundView : public ISlateViewport
|
|
{
|
|
public:
|
|
FBackgroundView(FTextureRHIRef RenderTargetTexture, FIntPoint InSize)
|
|
: RenderTarget( new FSlateRenderTargetRHI(RenderTargetTexture, InSize.X, InSize.Y))
|
|
, Size(InSize)
|
|
{
|
|
BeginInitResource(RenderTarget);
|
|
}
|
|
|
|
~FBackgroundView()
|
|
{
|
|
ReleaseResourceAndFlush(RenderTarget);
|
|
delete RenderTarget;
|
|
}
|
|
|
|
/* ISlateViewport interface. */
|
|
virtual FIntPoint GetSize() const override
|
|
{
|
|
return Size;
|
|
}
|
|
|
|
virtual FSlateShaderResource* GetViewportRenderTargetTexture() const override
|
|
{
|
|
return RenderTarget;
|
|
}
|
|
|
|
virtual bool RequiresVsync() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
FSlateRenderTargetRHI* RenderTarget;
|
|
FIntPoint Size;
|
|
};
|
|
|
|
static TAutoConsoleVariable<int32> CVarRenderLastFrameInStreamingPause(
|
|
TEXT("r.RenderLastFrameInStreamingPause"),
|
|
1,
|
|
TEXT("If 1 the previous frame is displayed during streaming pause. If zero the screen is left black."),
|
|
ECVF_RenderThreadSafe);
|
|
|
|
|
|
FStreamingPauseRenderingModule::FStreamingPauseRenderingModule()
|
|
: SceneViewport(nullptr)
|
|
, ViewportWidget(nullptr)
|
|
, BackgroundView(nullptr)
|
|
, bMovieWasStarted(false)
|
|
{ }
|
|
|
|
|
|
void FStreamingPauseRenderingModule::StartupModule()
|
|
{
|
|
BeginDelegate.BindRaw(this, &FStreamingPauseRenderingModule::BeginStreamingPause);
|
|
EndDelegate.BindRaw(this, &FStreamingPauseRenderingModule::EndStreamingPause);
|
|
check(GEngine);
|
|
GEngine->RegisterBeginStreamingPauseRenderingDelegate(&BeginDelegate);
|
|
GEngine->RegisterEndStreamingPauseRenderingDelegate(&EndDelegate);
|
|
}
|
|
|
|
|
|
void FStreamingPauseRenderingModule::ShutdownModule()
|
|
{
|
|
BeginDelegate.Unbind();
|
|
EndDelegate.Unbind();
|
|
if( GEngine )
|
|
{
|
|
GEngine->RegisterBeginStreamingPauseRenderingDelegate(nullptr);
|
|
GEngine->RegisterEndStreamingPauseRenderingDelegate(nullptr);
|
|
}
|
|
}
|
|
|
|
|
|
void FStreamingPauseRenderingModule::BeginStreamingPause( FViewport* GameViewport )
|
|
{
|
|
// If a movie is already playing don't bother starting one
|
|
if (IsMoviePlayerEnabled() && (GetMoviePlayer()->IsInitialized() && !GetMoviePlayer()->IsMovieCurrentlyPlaying()))
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FStreamingPauseRenderingModule::BeginStreamingPause);
|
|
|
|
check(GameViewport);
|
|
|
|
//Create the viewport widget and add a throbber.
|
|
ViewportWidget = SNew(SViewport)
|
|
.EnableGammaCorrection(false);
|
|
|
|
ViewportWidget->SetContent
|
|
(
|
|
SNew(SVerticalBox)
|
|
+SVerticalBox::Slot()
|
|
.VAlign(VAlign_Bottom)
|
|
.HAlign(HAlign_Right)
|
|
.Padding(FMargin(10.0f))
|
|
[
|
|
SNew(SThrobber)
|
|
]
|
|
);
|
|
|
|
//Render the current scene to a new viewport.
|
|
FIntPoint SizeXY = GameViewport->GetSizeXY();
|
|
bool bRenderLastFrame = CVarRenderLastFrameInStreamingPause.GetValueOnGameThread() != 0;
|
|
bRenderLastFrame = bRenderLastFrame && !(GEngine->StereoRenderingDevice.IsValid() && GameViewport->IsStereoRenderingAllowed());
|
|
|
|
if(SizeXY.X > 0 && SizeXY.Y > 0 && bRenderLastFrame)
|
|
{
|
|
FViewportClient* ViewportClient = GameViewport->GetClient();
|
|
|
|
SceneViewport = MakeShareable(new FSceneViewport(ViewportClient, ViewportWidget));
|
|
|
|
SceneViewport->UpdateViewportRHI(false, SizeXY.X, SizeXY.Y, EWindowMode::Fullscreen, PF_Unknown);
|
|
|
|
SceneViewport->EnqueueBeginRenderFrame(false);
|
|
|
|
FCanvas Canvas(SceneViewport.Get(), nullptr, ViewportClient->GetWorld(), ViewportClient->GetWorld()->GetFeatureLevel());
|
|
{
|
|
ViewportClient->Draw(SceneViewport.Get(), &Canvas);
|
|
}
|
|
Canvas.Flush_GameThread();
|
|
|
|
FViewport* Viewport = SceneViewport.Get();
|
|
ENQUEUE_RENDER_COMMAND(EndDrawingCommand)(
|
|
[Viewport](FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
Viewport->EndRenderFrame(RHICmdList, false, false);
|
|
});
|
|
|
|
BackgroundView = MakeShareable(new FBackgroundView(SceneViewport->GetRenderTargetTexture(), SizeXY));
|
|
ViewportWidget->SetViewportInterface(BackgroundView.ToSharedRef());
|
|
|
|
}
|
|
|
|
|
|
//Create the loading screen and begin rendering the widget.
|
|
FLoadingScreenAttributes LoadingScreen;
|
|
LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;
|
|
LoadingScreen.WidgetLoadingScreen = ViewportWidget; // SViewport from above
|
|
GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
|
|
GetMoviePlayer()->PlayMovie();
|
|
|
|
// We started playing a movie
|
|
bMovieWasStarted = true;
|
|
}
|
|
}
|
|
|
|
void FStreamingPauseRenderingModule::EndStreamingPause()
|
|
{
|
|
// Only wait for the movie to finish if we were the one to start it.
|
|
if(bMovieWasStarted)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FStreamingPauseRenderingModule::EndStreamingPause);
|
|
|
|
//Stop rendering the loading screen and resume
|
|
GetMoviePlayer()->WaitForMovieToFinish();
|
|
|
|
ViewportWidget = nullptr;
|
|
SceneViewport = nullptr;
|
|
BackgroundView = nullptr;
|
|
|
|
FlushRenderingCommands();
|
|
|
|
bMovieWasStarted = false;
|
|
}
|
|
}
|