Files
GTASource/game/renderer/renderThread.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

894 lines
24 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// FILE : renderThread.cpp
// PURPOSE : stuff for setting up separate render thread & functions it requires
// AUTHOR : john w.
// CREATED : 1/8/06
//
/////////////////////////////////////////////////////////////////////////////////
//
// renderer/renderThread.cpp
//
// Copyright (C) 1999-2014 Rockstar Games. All Rights Reserved.
//
#include "renderthread.h"
#if __PPU
// PS3 headers
#include <cell/gcm.h>
#endif
// Rage headers
#include "fwscene/stores/imposedTextureDictionary.h"
#include "grcore/config.h"
#include "grcore/device.h"
#include "grmodel/geometry.h"
#include "grmodel/setup.h"
#include "grprofile/timebars.h"
#include "rmptfx/ptxmanager.h"
#include "rmptfx/ptxdrawlist.h"
#include "system/cache.h"
#include "system/criticalsection.h"
#include "system/param.h"
#include "system/xtl.h"
#include "breakableglass/bgdrawable.h"
#include "breakableglass/glassmanager.h"
#include "fwpheffects/ropemanager.h"
#include "fwpheffects/taskmanager.h"
#if __D3D
#include "system/d3d9.h"
#endif
#include "system/memory.h"
#if __PPU
#include "grcore/wrapper_gcm.h"
#include "system/replay.h"
#endif
#if RSG_PC && BUGSTAR_INTEGRATION_ACTIVE
#include "qa/BugstarInterface.h"
#endif // RSG_PC && BUGSTAR_INTEGRATION_ACTIVE
// Framework headers
#include "fwanimation/animdirector.h"
// Game headers
#include "audio/northaudioengine.h"
#include "audio/frontendaudioentity.h"
#include "camera/CamInterface.h"
#include "camera/viewports/ViewportManager.h"
#include "cutscene/CutSceneManagerNew.h"
#include "debug/bar.h"
#include "debug/BudgetDisplay.h"
#include "debug/Editing/LightEditing.h"
#include "debug/FrameDump.h"
#include "debug/textureviewer/textureviewer.h"
#include "frontend/credits.h"
#include "frontend/PauseMenu.h"
#include "frontend/WarningScreen.h"
#include "frontend/MiniMap.h"
#include "frontend/GolfTrail.h"
#include "frontend/profilesettings.h"
#include "frontend/loadingscreens.h"
#if RSG_PC
#include "Frontend/MousePointer.h"
#endif // #if RSG_PC
#include "Frontend/MultiplayerGamerTagHud.h"
#include "Frontend/VideoEditor/ui/Editor.h"
#include "network/Live/NetworkClan.h" //For deferred deletion of crew emblems
#include "physics/physics.h"
#include "peds/rendering/pedVariationPack.h"
#include "peds/Ped.h"
#include "performance/clearinghouse.h"
#include "renderer/DrawLists/drawListMgr.h"
#include "renderer/Lights/LODLights.h"
#include "renderer/renderListGroup.h"
#include "renderer/renderthread.h"
#include "renderer/Water.h"
#include "renderer/gtaDrawable.h"
#include "renderer/OcclusionQueries.h"
#include "renderer/RenderTargetMgr.h"
#include "renderer/RenderPhases/RenderPhaseCascadeShadows.h"
#include "renderer/RenderPhases/RenderPhaseStd.h"
#include "renderer/RenderPhases/RenderPhaseHeightMap.h"
#include "renderer/RenderPhases/RenderPhaseMirrorReflection.h"
#if RSG_PC
#include "renderer/River.h"
#endif
#include "renderer/PostProcessFX.h"
#include "renderer/PostProcessFXHelper.h"
#include "renderer/PlantsMgr.h"
#include "renderer/SpuPM/SpuPmMgr.h"
#include "renderer/ScreenshotManager.h"
#include "SaveLoad/savegame_autoload.h"
#include "SaveLoad/savegame_photo_manager.h"
#include "scene/lod/LodScale.h"
#include "scene/texLod.h"
#include "shaders/CustomShaderEffectTree.h"
#include "streaming/streamingengine.h"
#include "streaming/defragmentation.h"
#include "streaming/streamingdebug.h"
#include "system/controlMgr.h"
#include "system/system.h"
#include "system/gcmPerfmon.h"
#include "system/TamperActions.h"
#include "system/taskscheduler.h"
#include "system/ThreadPriorities.h"
#include "profile/cputrace.h"
#include "script/script.h"
#include "script/script_hud.h"
#include "Vfx/VisualEffects.h"
#include "Vfx/Misc/Coronas.h"
#include "vfx/misc/DistantLightsVertexBuffer.h"
#include "vfx/misc/Puddles.h"
#include "vfx/misc/LensFlare.h"
#include "Vfx/Particles/PtFxManager.h"
#include "text/Text.h"
#include "text/TextConversion.h"
#include "text/TextFile.h"
#include "text/TextFormat.h"
#include "shaders/ShaderEdit.h"
#include "peds/rendering/PedDamage.h"
#include "control/replay/ReplaySupportClasses.h"
#include "replaycoordinator/ReplayCoordinator.h"
#include "frontend/Scaleform/ScaleFormMgr.h"
#include "frontend/Scaleform/ScaleFormComplexObjectMgr.h"
#include "control/videorecording/videorecording.h"
#if NAVMESH_EXPORT
#include "pathserver/ExportCollision.h"
#endif
bool CGtaOldLoadingScreen::m_bForceLoadingScreen = false;
grcDepthStencilStateHandle CGtaOldLoadingScreen::m_depthState = grcStateBlock::DSS_Invalid;
#define FADEOUT_WITHOUT_LOADINGBAR (2.0f)
#if __PPU
#include <sys/event.h>
#include "grcore/wrapper_gcm.h"
#endif // __PPU
#if __WIN32PC
namespace rage {
XPARAM(d3dmt);
}
#endif
#if !__FINAL
PARAM(debugonfades, "[code] display debug info during fades");
#endif // !__FINAL
#if __BANK
extern void SetLastGenMode();
#endif // __BANK
namespace rage
{
extern bool g_PauseClothSimulation;
}
static sysTimer g_LoadingTimer;
static float g_fCurrentTimer = 0.0f;
CGtaRenderThreadGameInterface gGtaRenderThreadGameInterface;
// --- CRenderThreadInterface ------------------------------
// handle any setup & interface to the render thread proper
void CGtaRenderThreadGameInterface::ShutdownLevel(unsigned /*shutdownMode*/)
{
DRAWLISTMGR->ClothCleanup();
DRAWLISTMGR->CharClothCleanup();
}
#if RSG_PC
static void doRenderThreadFunction()
{
gRenderThreadInterface.DoRenderFunction();
}
#endif
void CGtaRenderThreadGameInterface::InitClass()
{
gRenderThreadInterface.SetGameInterface(&gGtaRenderThreadGameInterface);
#if RSG_PC
GRCDEVICE.RenderFunctionCallback = doRenderThreadFunction;
#endif
}
bool CGtaOldLoadingScreen::IsUsingLoadingRenderFunction()
{
if(gRenderThreadInterface.GetRenderFunction() == MakeFunctor(LoadingRenderFunction))
{
return true;
}
return false;
}
void CGtaRenderThreadGameInterface::PerformPtfxSafeModeOperations(BANK_ONLY(PtfxSafeModeOperationModeDebug ptfxSafeModeOperationDebug))
{
BANK_ONLY(if(ptfxSafeModeOperationDebug == PTFX_SAFE_MODE_OPERATION_DEBUG_ALL || ptfxSafeModeOperationDebug == PTFX_SAFE_MODE_OPERATION_DEBUG_CALLBACKEFFECTS))
{
PF_AUTO_PUSH_TIMEBAR("g_ptFxManager.BeginFrame");
//Let's perform the flip for particles in safe execution
g_ptFxManager.BeginFrame();
int numEffects = 0;
for(int i = 0; i < RMPTFXMGR.GetNumDrawLists(); i++)
{
numEffects += RMPTFXMGR.GetDrawList(i)->m_effectInstList.GetNumItems();
}
perfClearingHouse::SetValue(perfClearingHouse::PTFX, numEffects);
ptxPointPool &pointPool = RMPTFXMGR.GetPointPool();
perfClearingHouse::SetValue(perfClearingHouse::PARTICLES, pointPool.GetNumItemsActive());
}
BANK_ONLY(if(ptfxSafeModeOperationDebug == PTFX_SAFE_MODE_OPERATION_DEBUG_ALL || ptfxSafeModeOperationDebug == PTFX_SAFE_MODE_OPERATION_DEBUG_INSTANCE_SORTING))
{
#if PTFX_ALLOW_INSTANCE_SORTING
#if __DEV
// Yes, I know. But I promise we don't do any world::Add/Remove
CGameWorld::AllowDelete(true);
#endif
g_ptFxManager.GetSortedInterface().CleanUp(); // Post update cleanup.
if (CRenderPhaseDrawSceneInterface::GetRenderPhase())
{
g_ptFxManager.GetSortedInterface().AddToRenderList(CRenderPhaseDrawSceneInterface::GetRenderPhase()->GetRenderFlags(), CRenderPhaseDrawSceneInterface::GetRenderPhase()->GetEntityListIndex());
}
#if PTFX_RENDER_IN_MIRROR_REFLECTIONS
if(CRenderPhaseMirrorReflectionInterface::GetRenderPhase() BANK_ONLY( && !g_ptFxManager.GetGameDebugInterface().GetDisableRenderMirrorReflections()))
{
g_ptFxManager.GetSortedInterface().AddToRenderList(CRenderPhaseMirrorReflectionInterface::GetRenderPhase()->GetRenderFlags(), CRenderPhaseMirrorReflectionInterface::GetRenderPhase()->GetEntityListIndex());
}
#endif
#if __DEV
// Yes, I know. But I promise we don't do any world::Add/Remove
CGameWorld::AllowDelete(false);
#endif
#endif // PTFX_ALLOW_INSTANCE_SORTING
}
}
void CGtaRenderThreadGameInterface::PerformSafeModeOperations()
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Safe Execution", 1.0f);
if (fwTxd::GetCurrent())
{
TASKLOG_ONLY(s_TaskLog.Dump());
Quitf(ERR_GFX_RENDERTHREAD_TXD,"Someone forgot to pop a dictionary pointer!");
}
#if GTA_REPLAY
#if VIDEO_RECORDING_ENABLED
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("VideoRecording", 1.0f);
VideoRecording::Update();
}
#endif
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CReplayMgr", 1.0f);
CReplayMgr::ProcessRecord(fwTimer::GetReplayTimeInMilliseconds());
}
#endif // GTA_REPLAY
#if RSG_PC
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("UpdateFlowMaps", 1.0f);
River::UpdateFlowMaps();
}
#endif
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Lights::WaitForProcessVisibilityDependency", 1.0f);
Lights::WaitForProcessVisibilityDependency();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("UpdateHighQualityScreenshots", 1.0f);
// CHighQualityScreenshot::Update();
CPhotoManager::UpdateHighQualityScreenshots();
}
#if GTA_REPLAY
#if REPLAY_USE_PER_BLOCK_THUMBNAILS
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CReplayThumbnail", 1.0f);
CReplayThumbnail::ProcessQueueForPopulation();
}
#endif // REPLAY_USE_PER_BLOCK_THUMBNAILS
#endif // GTA_REPLAY
#if USE_GCMPERFMON
pm_Get();
#endif // USE_GCMPERFMON
#if __BANK
SetLastGenMode();
#endif // __BANK
#if __BANK
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Banks", 1.0f);
g_ShaderEdit::InstanceRef().ApplyUpdates();
Water::UpdateShaderEditVars();
CDebugTextureViewerInterface::Synchronise();
DebugEditing::LightEditing::Update();
CFrameDump::Update();
TheText.DeleteAllFlaggedEntriesFromDebugStringMap();
}
#endif // __BANK
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Synchronise", 1.0f);
CRenderPhaseCascadeShadowsInterface::Synchronise();
CParaboloidShadow::Synchronise();
PostFX::g_adaptation.Synchronise();
Lights::Synchronise();
CLODLights::Synchronise();
CutSceneManager::Synchronise();
}
#if RSG_PC
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CMousePointer", 1.0f);
CMousePointer::ResetMouseInput(); // reset mouse input before any scaleform or hud/frontend items
}
#endif // #if RSG_PC
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CDistantLightsVertexBuffer", 1.0f);
CDistantLightsVertexBuffer::FlipBuffers();
}
#if TREES_ENABLE_BRANCH_BEND_AND_TRI_WAVE_MICRO_MOVEMENTS
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CCustomShaderEffectTree", 1.0f);
CCustomShaderEffectTree::Synchronise();
}
#endif // TREES_ENABLE_BRANCH_BEND_AND_TRI_WAVE_MICRO_MOVEMENTS
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("GetRopeManager", 1.0f);
CPhysics::GetRopeManager()->SafeUpdate();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("ClothCleanup", 1.0f);
DRAWLISTMGR->ClothCleanup();
DRAWLISTMGR->CharClothCleanup();
}
if (!CSavegameAutoload::IsPerformingAutoLoadAtStartOfGame())
{
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CVisualEffects::UpdateSafe", 1.0f);
// safely update the visual effects
CVisualEffects::UpdateSafe();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("PHONEPHOTOEDITOR.UpdateSafe", 1.0f);
PHONEPHOTOEDITOR.UpdateSafe();
}
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CTaskScheduler::WaitOnResults", 1.0f);
CTaskScheduler::WaitOnResults();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("RenderTargets", 1.0f);
CRenderPhaseHeight *rp = CRenderPhaseHeight::GetPtFxGPUCollisionMap();
if( rp ) rp->SwapRenderTargets(); // swap doublebuffered heightmap
gRenderTargetMgr.CleanupNamedRenderTargets();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("PerformPtfxSafeModeOperations", 1.0f);
PerformPtfxSafeModeOperations(BANK_ONLY(PTFX_SAFE_MODE_OPERATION_DEBUG_ALL));
}
//Let's process Deferred Additions to render list here
//Because vehicle glass and Particles adds entities to the deferred list
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("ProcessDeferredAdditions", 1.0f);
CGtaRenderListGroup::ProcessDeferredAdditions();
}
#if USE_DEFRAGMENTATION // as late as possible to allow as much drawable spu work to finish, because in some cases we have to block until they're finished - KS
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Defragmentation", 1.0f);
#if __XENON && __MASTER
// HACK - Talk to Klaas before changing this
bool debuggerAttached = sysBootManager::GetChrome();
if (!debuggerAttached)
// HACK - Talk to Klaas before changing this
#endif // __XENON && __MASTER
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CTexLod::SetSwapStateAll", 1.0f);
// shitty way of solving this. Intercept the txd::place in order to fix up a single txd instance
CTexLod::SetSwapStateAll(false, true);
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("strStreamingEngine", 1.0f);
strStreamingEngine::GetDefragmentation()->Update();
}
#if __XENON && __MASTER
// HACK - Talk to Klaas before changing this
if (!debuggerAttached)
// HACK - Talk to Klaas before changing this
#endif // __XENON && __MASTER
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("SetSwapStateAll", 1.0f);
CTexLod::SetSwapStateAll(true, true);
}
}
#endif // USE_DEFRAGMENTATION
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("StartLocalEffectsUpdate", 1.0f);
// Signal the particle update thread to continue
g_ptFxManager.StartLocalEffectsUpdate();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("fwAnimDirector", 1.0f);
fwAnimDirector::UpdateClass();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("Water::FlipBuffers", 1.0f);
Water::FlipBuffers();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CPlantMgrWrapper", 1.0f);
CPlantMgrWrapper::UpdateSafeMode();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("OcclusionQueries", 1.0f);
OcclusionQueries::GatherQueryResults();
PuddlePassSingleton::GetInstance().GetQueriesResults();
CLensFlare::ProcessQuery();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("bgGlassManager", 1.0f);
// Glass
bgGlassManager::ProcessDeferredDeletes();
bgDrawable::EndFrame();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("SwapBuffers", 1.0f);
// Streaming (debug stuff)
CStreamingDebug::SwapBuffers();
if( !rage::g_PauseClothSimulation )
{
if( !fwTimer::IsGamePaused() )
{
grmGeometryQB::SwapBuffers();
}
#if GTA_REPLAY
// Replay ties some geometry to the secondary index - see ReplayClothPacketManager::ConnectToRealClothInstances()).
grmGeometryQB::SwapSecondaryBuffers();
#endif // GTA_REPLAY
CPhysics::GetClothManager()->ShiftBufferIndex();
}
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("GetRopeManager", 1.0f);
CPhysics::GetRopeManager()->ProcessShutdownList();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("GetClothInstanceTasksManager", 1.0f);
CPhysics::GetClothInstanceTasksManager()->WaitForTasks();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CScaleformMgr", 1.0f);
CTextFormat::EndFrame();
CScaleformMgr::UpdateAtEndOfFrame(true);
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CNewHud", 1.0f);
CNewHud::UpdateAtEndOfFrame();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CMiniMap", 1.0f);
CMiniMap::UpdateAtEndOfFrame();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CMultiplayerGamerTagHud", 1.0f);
CMultiplayerGamerTagHud::UpdateAtEndOfFrame();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("fwImposedTextureDictionary", 1.0f);
fwImposedTextureDictionary::RTUpdateCleanup();
}
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("MeshBlendManager", 1.0f);
MeshBlendManager::UpdateAtEndOfFrame();
}
#if __BANK
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("camInterface", 1.0f);
camInterface::UpdateAtEndOfFrame();
}
#endif // __BANK
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("timeWaited", 1.0f);
s32 timeWaitedForUpdate = gRenderThreadInterface.GetTimeWaitedForUpdate();
s32 timeWaitedForGpu = gRenderThreadInterface.GetTimeWaitedForGpu();
perfClearingHouse::SetValue(perfClearingHouse::WAIT_FOR_UPDATE, MAX(timeWaitedForUpdate - timeWaitedForGpu, 0));
perfClearingHouse::SetValue(perfClearingHouse::WAIT_FOR_GPU, timeWaitedForGpu);
#if RSG_PC
{
PF_AUTO_PUSH_TIMEBAR_BUDGETED("CSettingsManager", 1.0f);
CSettingsManager::GetInstance().SafeUpdate();
}
if (GRCDEVICE.UsingMultipleGPUs())
{
GRCDEVICE.CopyGPUIndex();
CPauseMenu::DecrementGPUCountDown();
}
else
{
CPauseMenu::DecrementGPUCountDown();
}
#elif RSG_DURANGO
CPauseMenu::DecrementGPUCountDown();
#endif
}
//@@: range CGTARENDERTHREADGAMEINTERFACE_PERFORMSAFEMODEOPERATIONS {
#if TAMPERACTIONS_ENABLED
TamperActions::PerformSafeModeOperations();
#endif
//@@: } CGTARENDERTHREADGAMEINTERFACE_PERFORMSAFEMODEOPERATIONS
}
void CGtaRenderThreadGameInterface::RenderThreadInit()
{
if(!CSpuPmMgr::Init())
{
AssertMsg(0, "\n Error creating custom workload!");
}
#if !__FINAL
gRenderThreadInterface.SetUpdateBufferThreadAccess(sysThreadType::THREAD_TYPE_UPDATE | SYS_THREAD_AUDIO | SYS_THREAD_PARTICLES);
#endif // !__FINAL
}
void CGtaRenderThreadGameInterface::RenderThreadShutdown()
{
#if SPUPMMGR_ENABLED
CSpuPmMgr::Shutdown();
#endif // SPUPMMGR_ENABLED
}
void CGtaRenderThreadGameInterface::DefaultPreRenderFunction()
{
PF_FRAMEINIT_TIMEBARS(gRenderThreadInterface.GetRenderThreadFrameNumber());
PF_START_TIMEBAR("DebugUpdate");
CDebug::RenderUpdate();
CShaderLib::SetGlobalTimer(float(2.0*PI*(double(fwTimer::GetTimeInMilliseconds())/1000.0)));
CShaderLib::SetGlobalShaderVariables();
#if SPUPMMGR_ENABLED
PF_START_TIMEBAR("SpuPmMgr update");
CSpuPmMgr::Update();
#endif // SPUPMMGR_ENABLED
}
void CGtaRenderThreadGameInterface::DefaultPostRenderFunction()
{
// clear any references to textures from the immediate mode shaders
CSprite2d::ClearRenderState();
#if RSG_PC && BUGSTAR_INTEGRATION_ACTIVE
qaBugstarInterface::HandleDelayedBugCreate();
#endif // RSG_PC && BUGSTAR_INTEGRATION_ACTIVE
}
// PURPOSE: this function is run regardless of whether the drawlists are run
void CGtaRenderThreadGameInterface::NonDefaultPostRenderFunction(bool bUpdateDone)
{
if(bUpdateDone)
CMiniMap_Common::RenderUpdate();
}
#if __WIN32
// PURPOSE: Flushes the Scaleform stuff that needs to be flushed even when the game/windows is locked
void CGtaRenderThreadGameInterface::FlushScaleformBuffers(void)
{
#if RSG_PC && RAGE_TIMEBARS
::rage::g_pfTB.SetDisableMoreTimeBars(true);
#endif
CScaleformComplexObjectMgr::SyncBuffers();
CScaleformMgr::BeginFrame();
CScaleformMgr::EndFrame();
#if RSG_PC && RAGE_TIMEBARS
::rage::g_pfTB.SetDisableMoreTimeBars(false);
#endif
}
#endif
void CGtaRenderThreadGameInterface::RenderFunctionChanged(RenderFn oldFn, RenderFn newFn)
{
// If render function was the loading thread then enable controls again
if(oldFn == MakeFunctor(CGtaOldLoadingScreen::LoadingRenderFunction))
{
CPed * pPlayer = CGameWorld::FindLocalPlayer();
if(pPlayer)
pPlayer->GetPlayerInfo()->EnableControlsLoadingScreen();
if (CWarningScreen::AllowUnpause())
{
fwTimer::EndUserPause();
}
}
// If render function is the loading thread then disable controls again
if(newFn == MakeFunctor(CGtaOldLoadingScreen::LoadingRenderFunction))
{
CPed * pPlayer = CGameWorld::FindLocalPlayer();
if(pPlayer)
pPlayer->GetPlayerInfo()->DisableControlsLoadingScreen();
}
if (!newFn) // only operator bool is defined, and NULL isn't always zero
{
// reset timers to ensure we always start at 0 next 'Loading...' time
if (g_fCurrentTimer != 0.0f)
{
g_LoadingTimer.Reset();
g_fCurrentTimer = 0.0f;
}
}
}
void CGtaRenderThreadGameInterface::Flush()
{
bool drawListsDone = gDrawListMgr->IsDrawListCreationDone();
if (!drawListsDone)
{
g_ptFxManager.BeginFrame();
}
DRAWLISTMGR->ClothCleanup();
DRAWLISTMGR->CharClothCleanup();
CTexLod::FlushMemRemaps();
}
void CGtaOldLoadingScreen::SetLoadingScreenIfRequired()
{
#if !__FINAL
if (PARAM_debugonfades.Get())
{
gRenderThreadInterface.SetDefaultRenderFunction();
}
else
#endif
{
if( CLoadingScreens::AreActive() ) // If the loading screens are active, then draw them above all else
{
gRenderThreadInterface.SetRenderFunction(MakeFunctor(CLoadingScreens::RenderLoadingScreens));
}
else if( (m_bForceLoadingScreen || // If faded out and credits not running then run faded out renderer
((!CPauseMenu::IsActive() && !CCredits::IsRunning() && !CWarningScreen::IsActive() && !CScriptHud::GetStopLoadingScreen() ) && // always display "loading..." if on a black screen and we are accessing the savegame stuff
camInterface::IsFadedOut() ) ) )
{
CGtaOldLoadingScreen::SetLoadingRenderFunction();
}
else
{
gRenderThreadInterface.SetDefaultRenderFunction();
}
}
}
void CGtaOldLoadingScreen::SetLoadingRenderFunction()
{
if(gRenderThreadInterface.GetRenderFunction() != MakeFunctor(LoadingRenderFunction))
{
g_LoadingTimer.Reset();
g_fCurrentTimer = 0.0f;
}
gRenderThreadInterface.SetRenderFunction(MakeFunctor(LoadingRenderFunction));
#if DEBUG_DRAW
if ( ::rage::bkManager::IsEnabled() )
{
CDebug::Update(); // update the debug here
}
#endif
}
void CGtaOldLoadingScreen::ForceLoadingRenderFunction(bool bForce)
{
m_bForceLoadingScreen = bForce;
if(m_bForceLoadingScreen)
{
CLoadingText::SetActive(true);
SetLoadingRenderFunction();
}
}
//
// name: CRenderThreadInterface::LoadingRenderFunction
// description: Render function that is called whenever screen is faded out
#if __PS3
namespace rage {
extern bool s_NeedWaitFlip;
}
#endif // __PS3
void CGtaOldLoadingScreen::Render()
{
// This is the actual draw function, do whatever you need to render your frame here
if( m_depthState == grcStateBlock::DSS_Invalid )
{ // Lazy init, yurk...
grcDepthStencilStateDesc desc;
desc.DepthEnable = false;
desc.DepthFunc = grcRSV::CMP_LESS;
m_depthState = grcStateBlock::CreateDepthStencilState(desc);
}
grcViewport vp;
vp.Ortho(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
grcViewport::SetCurrent(&vp);
grcStateBlock::SetBlendState(grcStateBlock::BS_Default);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
grcStateBlock::SetDepthStencilState(m_depthState);
grcLightState::SetEnabled(false);
grcWorldIdentity();
#if RSG_PC || RSG_DURANGO || RSG_ORBIS
GRCDEVICE.Clear( true, Color32(0,0,0,255), false, 1.0f, false, 0 );
#elif __PS3
GRCDEVICE.ClearRect(0, 0, vp.GetWidth(), vp.GetHeight(), true, Color32(0,0,0,255),false,1.0f,false,0);
#else //__PS3
GRCDEVICE.ClearRect(0, 0, vp.GetWidth(), vp.GetHeight(), 0.0f, Color32(0,0,0,255));
#endif //__PS3
if (CWarningScreen::IsActive()) // we may need to show warning messages on the "loading screens"
{
CWarningScreen::Render();
}
else
{
CScriptHud::DrawScriptSpritesAndRectangles(CRenderTargetMgr::RTI_MainScreen, SCRIPT_GFX_ORDER_AFTER_FADE);
CScriptHud::DrawScriptText(CRenderTargetMgr::RTI_MainScreen, SCRIPT_GFX_ORDER_AFTER_FADE);
// If loading render is blank then finish and exit function
if (!CScriptHud::bHideLoadingAnimThisFrame)
{
g_fCurrentTimer += g_LoadingTimer.GetTime();
}
else
{
g_fCurrentTimer = 0.0f;
CScriptHud::bHideLoadingAnimThisFrame = false;
}
g_LoadingTimer.Reset();
CLoadingText::UpdateAndRenderLoadingText(g_fCurrentTimer);
#if GTA_REPLAY
// replay editor requires logos on this fadeout loadingscreen & gamefeed
if (CVideoEditorUi::IsActive())
{
CVideoEditorUi::RenderLoadingScreenOverlay();
}
#endif // GTA_REPLAY
}
#if DEBUG_DRAW
#if DEBUG_DISPLAY_BAR
CDebug::RenderReleaseInfoToScreen();
#endif
#if DEBUG_PAD_INPUT
CDebug::RenderDebugScaleformInfo();
#endif
#endif
FINAL_DISPLAY_BAR_ONLY(CDebugBar::Render());
// clear any references to textures from the immediate mode shaders
CSprite2d::ClearRenderState();
// clear any ropes created and deleted during loading screens ( blame it on the vehicles generation code )
CPhysics::GetRopeManager()->ProcessShutdownList();
}
void CGtaOldLoadingScreen::LoadingRenderFunction()
{
#if NAVMESH_EXPORT
if(CNavMeshDataExporter::WillExportCollision())
return;
#endif
// add any draw setup required here
PF_FRAMEINIT_TIMEBARS(0);
#if __WIN32PC
GRCDEVICE.Manage();
if (!GRCDEVICE.IsReady())
return;
#endif
#if __PS3
s_NeedWaitFlip = true;
grcTextureFactory::GetInstance().BindDefaultRenderTargets();
#endif //__PS3
CSystem::BeginRender();
#if GTA_REPLAY
//add a check so we only do this when prepping a clip to be loaded
if(CReplayCoordinator::IsSettingUpFirstFrame())
{
# if GPU_DAMAGE_WRITE_ENABLED
CApplyDamage::DrawDamage();
# endif
// Prime the water height texture with the correct values for the first frame.
Water::UpdateDynamicGPU(true);
}
#endif
CRenderTargets::LockUIRenderTargets();
CGtaOldLoadingScreen::Render();
CRenderTargets::UnlockUIRenderTargets();
MeshBlendManager::RenderThreadUpdate();
PostFX::UpdateOnLoadingScreen();
CSystem::EndRender();
}