This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions
+982
View File
@@ -0,0 +1,982 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#include "tier0/platform.h"
#include "appframework/ilaunchermgr.h"
#if defined( PLATFORM_PS3)
#include "ps3/ps3_helpers.h"
#endif
#include "tier0/platwindow.h"
#include "appframework/IAppSystemGroup.h"
#include "appframework/iappsystem.h"
#include "interface.h"
#include "filesystem.h"
#include "filesystem_init.h"
#include <algorithm>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
extern ILoggingListener *g_pDefaultLoggingListener;
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CAppSystemGroup::CAppSystemGroup( CAppSystemGroup *pAppSystemParent ) : m_SystemDict(false, 0, 16)
{
m_pParentAppSystem = pAppSystemParent;
}
//-----------------------------------------------------------------------------
// Actually loads a DLL
//-----------------------------------------------------------------------------
CSysModule *CAppSystemGroup::LoadModuleDLL( const char *pDLLName )
{
return Sys_LoadModule( pDLLName );
}
//-----------------------------------------------------------------------------
// Methods to load + unload DLLs
//-----------------------------------------------------------------------------
AppModule_t CAppSystemGroup::LoadModule( const char *pDLLName )
{
// Remove the extension when creating the name.
int nLen = Q_strlen( pDLLName ) + 1;
char *pModuleName = (char*)stackalloc( nLen );
Q_StripExtension( pDLLName, pModuleName, nLen );
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_pModuleName )
{
if ( !Q_stricmp( pModuleName, m_Modules[i].m_pModuleName ) )
return i;
}
}
CSysModule *pSysModule = LoadModuleDLL( pDLLName );
if (!pSysModule)
{
#ifdef _X360
Warning("AppFramework : Unable to load module %s! (err #%d)\n", pDLLName, GetLastError() );
#else
Warning("AppFramework : Unable to load module %s!\n", pDLLName );
#endif
return APP_MODULE_INVALID;
}
int nIndex = m_Modules.AddToTail();
m_Modules[nIndex].m_pModule = pSysModule;
m_Modules[nIndex].m_Factory = 0;
m_Modules[nIndex].m_pModuleName = (char*)malloc( nLen );
Q_strncpy( m_Modules[nIndex].m_pModuleName, pModuleName, nLen );
return nIndex;
}
int CAppSystemGroup::ReloadModule( const char * pDLLName )
{
// Remove the extension when creating the name.
int nLen = Q_strlen( pDLLName ) + 1;
char *pModuleName = (char*)stackalloc( nLen );
Q_StripExtension( pDLLName, pModuleName, nLen );
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
Module_t &module = m_Modules[i];
if ( module.m_pModuleName && !Q_stricmp( pModuleName, module.m_pModuleName ) )
{
// found the module, reload
Msg("Unloading module %s, dll %s\n", pModuleName, pDLLName );
Sys_UnloadModule( m_Modules[i].m_pModule );
Msg("Module %s unloaded, reloading\n", pModuleName );
CSysModule *pSysModule = NULL;
CreateInterfaceFn fnFactory = NULL;
while( !pSysModule )
{
pSysModule = LoadModuleDLL( pDLLName );
if( !pSysModule )
{
Warning("Cannot load, retrying in 5 seconds..\n");
ThreadSleep( 5000 );
}
fnFactory = Sys_GetFactory( pSysModule ) ;
if( !fnFactory )
{
Error( "Could not get factory from %s\n", pModuleName );
}
( *fnFactory )( "Reload Interface", NULL ); // let the CreateInterface function work and do after-reload stuff
}
Msg( "Reload complete, module %p->%p, factory %llx->%llx\n", module.m_pModule, pSysModule, (uint64)(uintp)module.m_Factory, (uint64)(uintp)fnFactory );
module.m_pModule = pSysModule;
if( module.m_Factory )
{ // don't reload factory pointer unless it was initialized to non-NULL
module.m_Factory = fnFactory;
}
return 0; // no error
}
}
Warning( "No such module: '%s' in appsystem @%p. Dumping available modules:\n", pModuleName, this );
for ( int i = 0; i < m_Modules.Count(); ++i )
{
Module_t &module = m_Modules[i];
#ifdef _PS3
Msg( "%25s %llx %p %6d %6d bytes\n", module.m_pModuleName, (uint64)module.m_Factory, module.m_pModule, ( ( PS3_PrxLoadParametersBase_t *)module.m_pModule )->sysPrxId, ( ( PS3_PrxLoadParametersBase_t *)module.m_pModule )->cbSize );
#else
Msg("%25s %p %p\n", module.m_pModuleName, (void*)module.m_Factory, module.m_pModule );
#endif
}
return m_pParentAppSystem ? m_pParentAppSystem->ReloadModule( pDLLName ) : -1;
}
AppModule_t CAppSystemGroup::LoadModule( CreateInterfaceFn factory )
{
if (!factory)
{
Warning("AppFramework : Unable to load module %p!\n", factory );
return APP_MODULE_INVALID;
}
// See if we already loaded it...
for ( int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_Factory )
{
if ( m_Modules[i].m_Factory == factory )
return i;
}
}
int nIndex = m_Modules.AddToTail();
m_Modules[nIndex].m_pModule = NULL;
m_Modules[nIndex].m_Factory = factory;
m_Modules[nIndex].m_pModuleName = NULL;
return nIndex;
}
void CAppSystemGroup::UnloadAllModules()
{
// NOTE: Iterate in reverse order so they are unloaded in opposite order
// from loading
for (int i = m_Modules.Count(); --i >= 0; )
{
if ( m_Modules[i].m_pModule )
{
Sys_UnloadModule( m_Modules[i].m_pModule );
}
if ( m_Modules[i].m_pModuleName )
{
free( m_Modules[i].m_pModuleName );
}
}
m_Modules.RemoveAll();
}
//-----------------------------------------------------------------------------
// Methods to add/remove various global singleton systems
//-----------------------------------------------------------------------------
IAppSystem *CAppSystemGroup::AddSystem( AppModule_t module, const char *pInterfaceName )
{
if (module == APP_MODULE_INVALID)
return NULL;
int nFoundIndex = m_SystemDict.Find( pInterfaceName );
if ( nFoundIndex != m_SystemDict.InvalidIndex() )
{
Warning("AppFramework : Attempted to add two systems with the same interface name %s!\n", pInterfaceName );
return m_Systems[ m_SystemDict[nFoundIndex] ];
}
Assert( (module >= 0) && (module < m_Modules.Count()) );
CreateInterfaceFn pFactory = m_Modules[module].m_pModule ? Sys_GetFactory( m_Modules[module].m_pModule ) : m_Modules[module].m_Factory;
int retval;
void *pSystem = pFactory( pInterfaceName, &retval );
if ((retval != IFACE_OK) || (!pSystem))
{
Warning("AppFramework : Unable to create system %s!\n", pInterfaceName );
return NULL;
}
IAppSystem *pAppSystem = static_cast<IAppSystem*>(pSystem);
int sysIndex = m_Systems.AddToTail( pAppSystem );
// Inserting into the dict will help us do named lookup later
MEM_ALLOC_CREDIT();
m_SystemDict.Insert( pInterfaceName, sysIndex );
return pAppSystem;
}
static const char *g_StageLookup[] =
{
"CREATION",
"LOADING DEPENDENCIES",
"CONNECTION",
"PREINITIALIZATION",
"INITIALIZATION",
"POSTINITIALIZATION",
"RUNNING",
"PRESHUTDOWN",
"SHUTDOWN",
"POSTSHUTDOWN",
"DISCONNECTION",
"DESTRUCTION",
};
void CAppSystemGroup::ReportStartupFailure( int nErrorStage, int nSysIndex )
{
COMPILE_TIME_ASSERT( APPSYSTEM_GROUP_STAGE_COUNT == ARRAYSIZE( g_StageLookup ) );
const char *pszStageDesc = "Unknown";
if ( nErrorStage >= 0 && nErrorStage < ( int )ARRAYSIZE( g_StageLookup ) )
{
pszStageDesc = g_StageLookup[ nErrorStage ];
}
const char *pszSystemName = "(Unknown)";
for ( int i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
if ( m_SystemDict[ i ] != nSysIndex )
continue;
pszSystemName = m_SystemDict.GetElementName( i );
break;
}
// Walk the dictionary
Warning( "System (%s) failed during stage %s\n", pszSystemName, pszStageDesc );
}
void CAppSystemGroup::AddSystem( IAppSystem *pAppSystem, const char *pInterfaceName )
{
if ( !pAppSystem )
return;
int sysIndex = m_Systems.AddToTail( pAppSystem );
// Inserting into the dict will help us do named lookup later
MEM_ALLOC_CREDIT();
m_SystemDict.Insert( pInterfaceName, sysIndex );
}
void CAppSystemGroup::RemoveAllSystems()
{
// NOTE: There's no deallcation here since we don't really know
// how the allocation has happened. We could add a deallocation method
// to the code in interface.h; although when the modules are unloaded
// the deallocation will happen anyways
m_Systems.RemoveAll();
m_SystemDict.RemoveAll();
}
//-----------------------------------------------------------------------------
// Simpler method of doing the LoadModule/AddSystem thing.
//-----------------------------------------------------------------------------
bool CAppSystemGroup::AddSystems( AppSystemInfo_t *pSystemList )
{
while ( pSystemList->m_pModuleName[0] )
{
AppModule_t module = LoadModule( pSystemList->m_pModuleName );
IAppSystem *pSystem = AddSystem( module, pSystemList->m_pInterfaceName );
if ( !pSystem )
{
Warning( "Unable to load interface %s from %s, requested from EXE.\n", pSystemList->m_pInterfaceName, pSystemList->m_pModuleName );
return false;
}
++pSystemList;
}
return true;
}
//-----------------------------------------------------------------------------
// Methods to find various global singleton systems
//-----------------------------------------------------------------------------
void *CAppSystemGroup::FindSystem( const char *pSystemName )
{
unsigned short i = m_SystemDict.Find( pSystemName );
if (i != m_SystemDict.InvalidIndex())
return m_Systems[m_SystemDict[i]];
// If it's not an interface we know about, it could be an older
// version of an interface, or maybe something implemented by
// one of the instantiated interfaces...
// QUESTION: What order should we iterate this in?
// It controls who wins if multiple ones implement the same interface
for ( i = 0; i < m_Systems.Count(); ++i )
{
void *pInterface = m_Systems[i]->QueryInterface( pSystemName );
if (pInterface)
return pInterface;
}
int nExternalCount = m_NonAppSystemFactories.Count();
for ( i = 0; i < nExternalCount; ++i )
{
void *pInterface = m_NonAppSystemFactories[i]( pSystemName, NULL );
if (pInterface)
return pInterface;
}
if ( m_pParentAppSystem )
{
void* pInterface = m_pParentAppSystem->FindSystem( pSystemName );
if ( pInterface )
return pInterface;
}
// No dice..
return NULL;
}
//-----------------------------------------------------------------------------
// Adds a factory to the system so other stuff can query it. Triggers a connect systems
//-----------------------------------------------------------------------------
void CAppSystemGroup::AddNonAppSystemFactory( CreateInterfaceFn fn )
{
m_NonAppSystemFactories.AddToTail( fn );
}
//-----------------------------------------------------------------------------
// Removes a factory, triggers a disconnect call if it succeeds
//-----------------------------------------------------------------------------
void CAppSystemGroup::RemoveNonAppSystemFactory( CreateInterfaceFn fn )
{
m_NonAppSystemFactories.FindAndRemove( fn );
}
//-----------------------------------------------------------------------------
// Causes the systems to reconnect to an interface
//-----------------------------------------------------------------------------
void CAppSystemGroup::ReconnectSystems( const char *pInterfaceName )
{
// Let the libraries regrab the specified interface
for (int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
pSystem->Reconnect( GetFactory(), pInterfaceName );
}
}
//-----------------------------------------------------------------------------
// Gets at the parent appsystem group
//-----------------------------------------------------------------------------
CAppSystemGroup *CAppSystemGroup::GetParent()
{
return m_pParentAppSystem;
}
//-----------------------------------------------------------------------------
// Deals with sorting dependencies and finding circular dependencies
//-----------------------------------------------------------------------------
void CAppSystemGroup::ComputeDependencies( LibraryDependencies_t &depend )
{
bool bDone = false;
while ( !bDone )
{
bDone = true;
// If i depends on j, then i depends on what j depends on
// Add secondary dependencies to i. We stop when no dependencies are added
int nCount = depend.GetNumStrings();
for ( int i = 0; i < nCount; ++i )
{
int nDependentCount = depend[i].GetNumStrings();
for ( int j = 0; j < nDependentCount; ++j )
{
int nIndex = depend.Find( depend[i].String( j ) );
if ( nIndex == UTL_INVAL_SYMBOL )
continue;
int nSecondaryDepCount = depend[nIndex].GetNumStrings();
for ( int k = 0; k < nSecondaryDepCount; ++k )
{
// Don't bother if we already contain the secondary dependency
const char *pSecondaryDependency = depend[nIndex].String( k );
if ( depend[i].Find( pSecondaryDependency ) != UTL_INVAL_SYMBOL )
continue;
// Check for circular dependency
if ( !Q_stricmp( pSecondaryDependency, depend.String( i ) ) )
{
Warning( "Encountered a circular dependency with library %s!\n", pSecondaryDependency );
continue;
}
bDone = false;
depend[i].AddString( pSecondaryDependency );
nDependentCount = depend[i].GetNumStrings();
}
}
}
}
}
//-----------------------------------------------------------------------------
// Sorts dependencies
//-----------------------------------------------------------------------------
CAppSystemGroup::LibraryDependencies_t *CAppSystemGroup::sm_pSortDependencies;
bool CAppSystemGroup::SortLessFunc( const int &left, const int &right )
{
const char *pLeftInterface = sm_pSortDependencies->String( left );
const char *pRightInterface = sm_pSortDependencies->String( right );
bool bRightDependsOnLeft = ( (*sm_pSortDependencies)[pRightInterface].Find( pLeftInterface ) != UTL_INVAL_SYMBOL );
return ( bRightDependsOnLeft );
}
void CAppSystemGroup::SortDependentLibraries( LibraryDependencies_t &depend )
{
int nCount = depend.GetNumStrings();
int *pIndices = (int*)stackalloc( depend.GetNumStrings() * sizeof(int) );
for ( int i = 0; i < nCount; ++i )
{
pIndices[i] = i;
}
// Sort by dependency. Can't use fancy stl algorithms here because the sort func isn't strongly transitive.
// Using lame bubble sort instead. We could speed this up using a proper depth-first graph walk, but it's not worth the effort.
sm_pSortDependencies = &depend;
bool bChanged = true;
while ( bChanged )
{
bChanged = false;
for ( int i = 1; i < nCount; i++ )
{
for ( int j = 0; j < i; j++ )
{
if ( SortLessFunc( pIndices[i], pIndices[j] ) )
{
int nTmp = pIndices[i];
pIndices[i] = pIndices[j];
pIndices[j] = nTmp;
bChanged = true;
}
}
}
}
sm_pSortDependencies = NULL;
// This logic will make it so it respects the specified initialization order
// in the face of no dependencies telling the system otherwise.
// Doing this just for safety to reduce the amount of changed code
bool bDone = false;
while ( !bDone )
{
bDone = true;
for ( int i = 1; i < nCount; ++i )
{
int nLeft = pIndices[i-1];
int nRight = pIndices[i];
if ( nRight > nLeft )
continue;
const char *pLeftInterface = depend.String( nLeft );
const char *pRightInterface = depend.String( nRight );
bool bRightDependsOnLeft = ( depend[pRightInterface].Find( pLeftInterface ) != UTL_INVAL_SYMBOL );
if ( bRightDependsOnLeft )
continue;
Assert ( UTL_INVAL_SYMBOL == depend[pRightInterface].Find( pLeftInterface ) );
V_swap( pIndices[i], pIndices[i-1] );
bDone = false;
}
}
// Reorder appsystem list + dictionary indexing
Assert( m_Systems.Count() == nCount );
int nTempSize = nCount * sizeof(IAppSystem*);
IAppSystem **pTemp = (IAppSystem**)stackalloc( nTempSize );
memcpy( pTemp, m_Systems.Base(), nTempSize );
for ( int i = 0; i < nCount; ++i )
{
m_Systems[i] = pTemp[ pIndices[i] ];
}
// Remap system indices
for ( uint16 i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
int j = 0;
for ( ; j < nCount; ++j )
{
if ( pIndices[j] == m_SystemDict[i] )
{
m_SystemDict[i] = j;
break;
}
}
Assert( j != nCount );
}
( void )stackfree( pTemp );
( void )stackfree( pIndices );
}
//-----------------------------------------------------------------------------
// Finds appsystem names
//-----------------------------------------------------------------------------
const char *CAppSystemGroup::FindSystemName( int nIndex )
{
for ( uint16 i = m_SystemDict.First(); i != m_SystemDict.InvalidIndex(); i = m_SystemDict.Next( i ) )
{
if ( m_SystemDict[i] == nIndex )
return m_SystemDict.GetElementName( i );
}
return NULL;
}
//-----------------------------------------------------------------------------
// Method to load all dependent systems
//-----------------------------------------------------------------------------
bool CAppSystemGroup::LoadDependentSystems()
{
LibraryDependencies_t dependencies;
// First, load dependencies.
for ( int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
const char *pInterfaceName = FindSystemName( i );
dependencies.AddString( pInterfaceName );
const AppSystemInfo_t *pDependencies = pSystem->GetDependencies();
if ( !pDependencies )
continue;
for ( ; pDependencies->m_pInterfaceName && pDependencies->m_pInterfaceName[0]; ++pDependencies )
{
dependencies[ pInterfaceName ].AddString( pDependencies->m_pInterfaceName );
CreateInterfaceFn factory = GetFactory();
if ( factory( pDependencies->m_pInterfaceName, NULL ) )
continue;
AppModule_t module = LoadModule( pDependencies->m_pModuleName );
IAppSystem *pSystem = AddSystem( module, pDependencies->m_pInterfaceName );
if ( !pSystem )
{
Warning( "Unable to load interface %s from %s (Dependency of %s)\n", pDependencies->m_pInterfaceName, pDependencies->m_pModuleName, pInterfaceName );
return false;
}
}
}
ComputeDependencies( dependencies );
SortDependentLibraries( dependencies );
return true;
}
//-----------------------------------------------------------------------------
// Method to connect/disconnect all systems
//-----------------------------------------------------------------------------
bool CAppSystemGroup::ConnectSystems()
{
// Let the libraries grab any other interfaces they may need
for (int i = 0; i < m_Systems.Count(); ++i )
{
IAppSystem *pSystem = m_Systems[i];
if ( !pSystem->Connect( GetFactory() ) )
{
ReportStartupFailure( CONNECTION, i );
return false;
}
}
return true;
}
void CAppSystemGroup::DisconnectSystems()
{
// Disconnect in reverse order of connection
for (int i = m_Systems.Count(); --i >= 0; )
{
m_Systems[i]->Disconnect();
}
}
//-----------------------------------------------------------------------------
// Method to initialize/shutdown all systems
//-----------------------------------------------------------------------------
InitReturnVal_t CAppSystemGroup::InitSystems()
{
for (int nSystemsInitialized = 0; nSystemsInitialized < m_Systems.Count(); ++nSystemsInitialized )
{
InitReturnVal_t nRetVal = m_Systems[nSystemsInitialized]->Init();
if ( nRetVal != INIT_OK )
{
for( int nSystemsRewind = nSystemsInitialized; nSystemsRewind-->0; )
{
m_Systems[nSystemsRewind]->Shutdown();
}
ReportStartupFailure( INITIALIZATION, nSystemsInitialized );
return nRetVal;
}
}
return INIT_OK;
}
void CAppSystemGroup::ShutdownSystems()
{
// Shutdown in reverse order of initialization
for (int i = m_Systems.Count(); --i >= 0; )
{
m_Systems[i]->Shutdown();
}
}
//-----------------------------------------------------------------------------
// Window management
//-----------------------------------------------------------------------------
void* CAppSystemGroup::CreateAppWindow( void *hInstance, const char *pTitle, bool bWindowed, int w, int h, bool bResizing )
{
#if defined( PLATFORM_WINDOWS ) || defined( PLATFORM_OSX )
int nFlags = 0;
if ( !bWindowed )
{
nFlags |= WINDOW_CREATE_FULLSCREEN;
}
if ( bResizing )
{
nFlags |= WINDOW_CREATE_RESIZING;
}
PlatWindow_t hWnd = Plat_CreateWindow( hInstance, pTitle, w, h, nFlags );
if ( hWnd == PLAT_WINDOW_INVALID )
return NULL;
int CenterX, CenterY;
Plat_GetDesktopResolution( &CenterX, &CenterY );
CenterX = ( CenterX - w ) / 2;
CenterY = ( CenterY - h ) / 2;
CenterX = (CenterX < 0) ? 0: CenterX;
CenterY = (CenterY < 0) ? 0: CenterY;
// In VCR modes, keep it in the upper left so mouse coordinates are always relative to the window.
Plat_SetWindowPos( hWnd, CenterX, CenterY );
return hWnd;
#elif defined( PLATFORM_OSX )
extern ICocoaMgr *g_pCocoaMgr;
g_pCocoaMgr->CreateGameWindow( pTitle, bWindowed, w, h );
return (void*)Sys_GetFactoryThis(); // Other stuff will query for ICocoaBridge out of this.
#elif defined( PLATFORM_LINUX )
#ifndef DEDICATED
// PBTODO
// extern IGLXMgr *g_pGLXMgr;
// g_pGLXMgr->CreateWindow( pTitle, bWindowed, w, h );
return (void*)Sys_GetFactoryThis(); // Other stuff will query for ICocoaBridge out of this.
#endif
#endif
return NULL;
}
void CAppSystemGroup::SetAppWindowTitle( void* hWnd, const char *pTitle )
{
Plat_SetWindowTitle( (PlatWindow_t)hWnd, pTitle );
}
//-----------------------------------------------------------------------------
// Returns the stage at which the app system group ran into an error
//-----------------------------------------------------------------------------
CAppSystemGroup::AppSystemGroupStage_t CAppSystemGroup::GetCurrentStage() const
{
return m_nCurrentStage;
}
//-----------------------------------------------------------------------------
// Gets at a factory that works just like FindSystem
//-----------------------------------------------------------------------------
// This function is used to make this system appear to the outside world to
// function exactly like the currently existing factory system
CAppSystemGroup *s_pCurrentAppSystem;
void *AppSystemCreateInterfaceFn(const char *pName, int *pReturnCode)
{
void *pInterface = s_pCurrentAppSystem->FindSystem( pName );
if ( pReturnCode )
{
*pReturnCode = pInterface ? IFACE_OK : IFACE_FAILED;
}
return pInterface;
}
//-----------------------------------------------------------------------------
// Gets at a class factory for the topmost appsystem group in an appsystem stack
//-----------------------------------------------------------------------------
CreateInterfaceFn CAppSystemGroup::GetFactory()
{
return AppSystemCreateInterfaceFn;
}
//-----------------------------------------------------------------------------
// Main application loop
//-----------------------------------------------------------------------------
int CAppSystemGroup::Run()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
// Load, connect, init
int nRetVal = OnStartup();
// NOTE: In case of OnStartup Failure
// On PS/3, not unloading the PRXes in order will cause crashes on quit, which is a TRC failure
// We probably should, but don't have to do this on all platforms, since it's not required to clean-up crash-free.
if ( m_nCurrentStage == RUNNING )
{
// Main loop implemented by the application
// FIXME: HACK workaround to avoid vgui porting
nRetVal = Main();
}
// Shutdown, disconnect, unload
OnShutdown();
// The factory now uses the parent's app system group
s_pCurrentAppSystem = GetParent();
return nRetVal;
}
//-----------------------------------------------------------------------------
// Virtual methods for override
//-----------------------------------------------------------------------------
int CAppSystemGroup::Startup()
{
return OnStartup();
}
void CAppSystemGroup::Shutdown()
{
return OnShutdown();
}
//-----------------------------------------------------------------------------
// Use this version in cases where you can't control the main loop and
// expect to be ticked
//-----------------------------------------------------------------------------
int CAppSystemGroup::OnStartup()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
// Call an installed application creation function
m_nCurrentStage = CREATION;
if ( !Create() )
return -1;
// Load dependent libraries
m_nCurrentStage = DEPENDENCIES;
if ( !LoadDependentSystems() )
return -1;
// Let all systems know about each other
m_nCurrentStage = CONNECTION;
if ( !ConnectSystems() )
return -1;
// Allow the application to do some work before init
m_nCurrentStage = PREINITIALIZATION;
if ( !PreInit() )
return -1;
// Call Init on all App Systems
m_nCurrentStage = INITIALIZATION;
int nRetVal = InitSystems();
if ( nRetVal != INIT_OK )
return -1;
m_nCurrentStage = POSTINITIALIZATION;
if ( !PostInit() )
return -1;
m_nCurrentStage = RUNNING;
return nRetVal;
}
void CAppSystemGroup::OnShutdown()
{
// The factory now uses this app system group
s_pCurrentAppSystem = this;
switch( m_nCurrentStage )
{
case RUNNING:
case POSTINITIALIZATION:
break;
case PREINITIALIZATION:
case INITIALIZATION:
goto disconnect;
case CREATION:
case DEPENDENCIES:
case CONNECTION:
goto destroy;
default:
break;
}
// Allow the application to do some work before shutdown
m_nCurrentStage = PRESHUTDOWN;
PreShutdown();
// Cal Shutdown on all App Systems
m_nCurrentStage = SHUTDOWN;
ShutdownSystems();
// Allow the application to do some work after shutdown
m_nCurrentStage = POSTSHUTDOWN;
PostShutdown();
disconnect:
// Systems should disconnect from each other
m_nCurrentStage = DISCONNECTION;
DisconnectSystems();
destroy:
// Unload all DLLs loaded in the AppCreate block
m_nCurrentStage = DESTRUCTION;
RemoveAllSystems();
// Have to do this because the logging listeners & response policies may live in modules which are being unloaded
// @TODO: this seems like a bad legacy practice... app systems should unload their spew handlers gracefully.
LoggingSystem_ResetCurrentLoggingState();
Assert( g_pDefaultLoggingListener != NULL );
LoggingSystem_RegisterLoggingListener( g_pDefaultLoggingListener );
UnloadAllModules();
// Call an installed application destroy function
Destroy();
}
//-----------------------------------------------------------------------------
//
// This class represents a group of app systems that are loaded through steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamAppSystemGroup::CSteamAppSystemGroup( IFileSystem *pFileSystem, CAppSystemGroup *pAppSystemParent )
{
m_pFileSystem = pFileSystem;
m_pGameInfoPath[0] = 0;
}
//-----------------------------------------------------------------------------
// Used by CSteamApplication to set up necessary pointers if we can't do it in the constructor
//-----------------------------------------------------------------------------
void CSteamAppSystemGroup::Setup( IFileSystem *pFileSystem, CAppSystemGroup *pParentAppSystem )
{
m_pFileSystem = pFileSystem;
m_pParentAppSystem = pParentAppSystem;
}
//-----------------------------------------------------------------------------
// Loads the module from Steam
//-----------------------------------------------------------------------------
CSysModule *CSteamAppSystemGroup::LoadModuleDLL( const char *pDLLName )
{
return m_pFileSystem->LoadModule( pDLLName );
}
//-----------------------------------------------------------------------------
// Returns the game info path
//-----------------------------------------------------------------------------
const char *CSteamAppSystemGroup::GetGameInfoPath() const
{
return m_pGameInfoPath;
}
//-----------------------------------------------------------------------------
// Sets up the search paths
//-----------------------------------------------------------------------------
bool CSteamAppSystemGroup::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
CFSSteamSetupInfo steamInfo;
steamInfo.m_pDirectoryName = pStartingDir;
steamInfo.m_bOnlyUseDirectoryName = bOnlyUseStartingDir;
steamInfo.m_bToolsMode = bIsTool;
steamInfo.m_bSetSteamDLLPath = true;
steamInfo.m_bSteam = m_pFileSystem->IsSteam();
if ( FileSystem_SetupSteamEnvironment( steamInfo ) != FS_OK )
return false;
CFSMountContentInfo fsInfo;
fsInfo.m_pFileSystem = m_pFileSystem;
fsInfo.m_bToolsMode = bIsTool;
fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath;
if ( FileSystem_MountContent( fsInfo ) != FS_OK )
return false;
// Finally, load the search paths for the "GAME" path.
CFSSearchPathsInit searchPathsInit;
searchPathsInit.m_pDirectoryName = steamInfo.m_GameInfoPath;
searchPathsInit.m_pFileSystem = fsInfo.m_pFileSystem;
if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK )
return false;
FileSystem_AddSearchPath_Platform( fsInfo.m_pFileSystem, steamInfo.m_GameInfoPath );
Q_strncpy( m_pGameInfoPath, steamInfo.m_GameInfoPath, sizeof(m_pGameInfoPath) );
return true;
}
+119
View File
@@ -0,0 +1,119 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/vguimatsysapp.h"
#include "vgui/IVGui.h"
#include "vgui/ISurface.h"
#include "vgui_controls/controls.h"
#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "tier0/dbg.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "tier3/tier3.h"
#include "inputsystem/iinputstacksystem.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVguiMatSysApp::CVguiMatSysApp()
{
m_hAppInputContext = INPUT_CONTEXT_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CVguiMatSysApp::Create()
{
if ( !BaseClass::Create() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
// NOTE: This has to occur before vgui2.dll so it replaces vgui2's surface implementation
{ "vguimatsurface.dll", VGUI_SURFACE_INTERFACE_VERSION },
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
return AddSystems( appSystems );
}
void CVguiMatSysApp::Destroy()
{
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CVguiMatSysApp::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
if ( !vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 ) )
return false;
if ( !g_pMatSystemSurface )
{
Warning( "CVguiMatSysApp::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
g_pMatSystemSurface->EnableWindowsMessages( true );
return true;
}
bool CVguiMatSysApp::PostInit()
{
if ( !BaseClass::PostInit() )
return false;
m_hAppInputContext = g_pInputStackSystem->PushInputContext();
InputContextHandle_t hVGuiInputContext = g_pInputStackSystem->PushInputContext();
g_pMatSystemSurface->SetInputContext( hVGuiInputContext );
g_pMatSystemSurface->EnableWindowsMessages( true );
return true;
}
void CVguiMatSysApp::PreShutdown()
{
g_pMatSystemSurface->EnableWindowsMessages( false );
g_pMatSystemSurface->SetInputContext( NULL );
if ( m_hAppInputContext != INPUT_CONTEXT_HANDLE_INVALID )
{
g_pInputStackSystem->PopInputContext(); // Vgui
g_pInputStackSystem->PopInputContext(); // App
}
BaseClass::PreShutdown();
}
void CVguiMatSysApp::PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
InputContextHandle_t CVguiMatSysApp::GetAppInputContext()
{
return m_hAppInputContext;
}
#endif // _WIN32
+235
View File
@@ -0,0 +1,235 @@
//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose: An application framework
//
//=============================================================================//
#include "appframework/AppFramework.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "interface.h"
#include "filesystem.h"
#include "appframework/IAppSystemGroup.h"
#include "filesystem_init.h"
#include "vstdlib/cvar.h"
#include "tier2/tier2.h"
#ifdef _X360
#include "xbox/xbox_win32stubs.h"
#include "xbox/xbox_console.h"
#include "xbox/xbox_launch.h"
#endif
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Globals...
//-----------------------------------------------------------------------------
void* s_HInstance;
static CSimpleWindowsLoggingListener s_SimpleWindowsLoggingListener;
static CSimpleLoggingListener s_SimpleLoggingListener;
ILoggingListener *g_pDefaultLoggingListener = &s_SimpleLoggingListener;
//-----------------------------------------------------------------------------
// HACK: Since I don't want to refit vgui yet...
//-----------------------------------------------------------------------------
void *GetAppInstance()
{
return s_HInstance;
}
//-----------------------------------------------------------------------------
// Sets the application instance, should only be used if you're not calling AppMain.
//-----------------------------------------------------------------------------
void SetAppInstance( void* hInstance )
{
s_HInstance = hInstance;
}
//-----------------------------------------------------------------------------
// Version of AppMain used by windows applications
//-----------------------------------------------------------------------------
int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleWindowsLoggingListener;
s_HInstance = hInstance;
#ifdef WIN32
// Prepend the module filename since most apps expect arg 0 to be that.
char szModuleFilename[MAX_PATH];
Plat_GetModuleFilename( szModuleFilename, sizeof( szModuleFilename ) );
int nAllocLen = strlen( lpCmdLine ) + strlen( szModuleFilename ) + 4;
char *pNewCmdLine = new char[nAllocLen]; // 2 for quotes, 1 for a space, and 1 for a null-terminator.
_snprintf( pNewCmdLine, nAllocLen, "\"%s\" %s", szModuleFilename, lpCmdLine );
// Setup ICommandLine.
CommandLine()->CreateCmdLine( pNewCmdLine );
delete [] pNewCmdLine;
#else
CommandLine()->CreateCmdLine( lpCmdLine );
#endif
return pAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Version of AppMain used by console applications
//-----------------------------------------------------------------------------
int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleLoggingListener;
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Used to startup/shutdown the application
//-----------------------------------------------------------------------------
int AppStartup( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleWindowsLoggingListener;
s_HInstance = hInstance;
CommandLine()->CreateCmdLine( lpCmdLine );
return pAppSystemGroup->Startup();
}
int AppStartup( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
g_pDefaultLoggingListener = &s_SimpleLoggingListener;
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Startup();
}
void AppShutdown( CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
pAppSystemGroup->Shutdown();
}
//-----------------------------------------------------------------------------
//
// Default implementation of an application meant to be run using Steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamApplication::CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup )
{
m_pChildAppSystemGroup = pAppSystemGroup;
m_pFileSystem = NULL;
m_bSteam = false;
}
//-----------------------------------------------------------------------------
// Create necessary interfaces
//-----------------------------------------------------------------------------
bool CSteamApplication::Create()
{
FileSystem_SetErrorMode( FS_ERRORMODE_AUTO );
char pFileSystemDLL[MAX_PATH];
if ( !GetFileSystemDLLName( pFileSystemDLL, MAX_PATH, m_bSteam ) )
return false;
FileSystem_SetupSteamInstallPath();
// Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
AddSystem( cvarModule, CVAR_INTERFACE_VERSION );
AppModule_t fileSystemModule = LoadModule( pFileSystemDLL );
m_pFileSystem = (IFileSystem*)AddSystem( fileSystemModule, FILESYSTEM_INTERFACE_VERSION );
if ( !m_pFileSystem )
{
if( !IsPS3() )
Error( "Unable to load %s", pFileSystemDLL );
return false;
}
return true;
}
bool CSteamApplication::GetFileSystemDLLName( char *pOut, int nMaxBytes, bool &bIsSteam )
{
return FileSystem_GetFileSystemDLLName( pOut, nMaxBytes, bIsSteam ) == FS_OK;
}
//-----------------------------------------------------------------------------
// The file system pointer is invalid at this point
//-----------------------------------------------------------------------------
void CSteamApplication::Destroy()
{
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Pre-init, shutdown
//-----------------------------------------------------------------------------
bool CSteamApplication::PreInit()
{
return true;
}
void CSteamApplication::PostShutdown()
{
}
//-----------------------------------------------------------------------------
// Run steam main loop
//-----------------------------------------------------------------------------
int CSteamApplication::Main()
{
// Now that Steam is loaded, we can load up main libraries through steam
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Run();
}
//-----------------------------------------------------------------------------
// Use this version in cases where you can't control the main loop and
// expect to be ticked
//-----------------------------------------------------------------------------
int CSteamApplication::Startup()
{
int nRetVal = BaseClass::Startup();
if ( GetCurrentStage() != RUNNING )
return nRetVal;
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Startup();
}
void CSteamApplication::Shutdown()
{
m_pChildAppSystemGroup->Shutdown();
BaseClass::Shutdown();
}
@@ -0,0 +1,40 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\AppSystemGroup.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Release output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\matsysapp.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\VguiMatSysApp.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Debug output file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Release output file: F:\csgo_64\cstrike15_src\appframework\WinApp.cpp
Containing unity file:
PCH file:
+61
View File
@@ -0,0 +1,61 @@
//-----------------------------------------------------------------------------
// APPFRAMEWORK.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$General
{
$AdditionalProjectDependencies "$BASE;togl" [!$IS_LIB_PROJECT && $GL]
}
$Compiler
{
$PreprocessorDefinitions "$BASE;VERSION_SAFE_STEAM_API_INTERFACES" [($WINDOWS && $GL) || $LINUXALL]
$PreprocessorDefinitions "$BASE;ALLOW_TEXT_MODE=1" [$CSTRIKE_TRUNK_BUILD||$CSTRIKE_STAGING_BUILD]
}
$Linker [$OSXALL && !$IS_LIB_PROJECT]
{
$SystemFrameworks "Carbon;OpenGL;Quartz;Cocoa;IOKit"
}
}
$Project "appframework"
{
$Folder "Source Files"
{
$File "AppSystemGroup.cpp"
$File "$SRCDIR\public\filesystem_init.cpp"
$File "VguiMatSysApp.cpp" [$WINDOWS]
$File "matsysapp.cpp" [$WINDOWS]
$File "WinApp.cpp" [$WINDOWS]
$File "posixapp.cpp" [$POSIX]
$File "sdlmgr.cpp" [$SDL]
$File "cocoamgr.mm" [!$SDL && $OSXALL]
$File "glmrendererinfo_osx.mm" [$SDL && $OSXALL]
}
$Folder "Interface"
{
$File "$SRCDIR\public\appframework\AppFramework.h"
$File "$SRCDIR\public\appframework\iappsystem.h"
$File "$SRCDIR\public\appframework\IAppSystemGroup.h"
$File "$SRCDIR\public\appframework\tier2app.h"
$File "$SRCDIR\public\appframework\tier3app.h"
$File "$SRCDIR\public\appframework\matsysapp.h"
$File "$SRCDIR\public\appframework\VguiMatSysApp.h"
$File "$SRCDIR\public\appframework\ilaunchermgr.h"
}
$Folder "Link Libraries"
{
$ImpLib togl [!$IS_LIB_PROJECT && $GL]
$ImpLib SDL2 [!$IS_LIB_PROJECT && $SDL]
}
}
+13
View File
@@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "appframework.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "appframework.vcxproj"
"1" "appframework.vcxproj.filters"
}
}
}
File diff suppressed because it is too large Load Diff
+630
View File
@@ -0,0 +1,630 @@
//========= Copyright 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
//===============================================================================
GLMRendererInfo::GLMRendererInfo( void )
{
m_display = NULL;
Q_memset( &m_info, 0, sizeof( m_info ) );
}
GLMRendererInfo::~GLMRendererInfo( void )
{
SDLAPP_FUNC;
if (m_display)
{
delete m_display;
m_display = NULL;
}
}
// !!! FIXME: sync this function with the Mac version in case anything important has changed.
void GLMRendererInfo::Init( GLMRendererInfoFields *info )
{
SDLAPP_FUNC;
m_info = *info;
m_display = NULL;
m_info.m_fullscreen = 0;
m_info.m_accelerated = 1;
m_info.m_windowed = 1;
m_info.m_ati = true;
m_info.m_atiNewer = true;
m_info.m_hasGammaWrites = true;
// If you haven't created a GL context by now (and initialized gGL), you're about to crash.
m_info.m_hasMixedAttachmentSizes = gGL->m_bHave_GL_ARB_framebuffer_object;
m_info.m_hasBGRA = gGL->m_bHave_GL_EXT_vertex_array_bgra;
// !!! FIXME: what do these do on the Mac?
m_info.m_hasNewFullscreenMode = false;
m_info.m_hasNativeClipVertexMode = true;
// if user disabled them
if (CommandLine()->FindParm("-glmdisableclipplanes"))
{
m_info.m_hasNativeClipVertexMode = false;
}
// or maybe enabled them..
if (CommandLine()->FindParm("-glmenableclipplanes"))
{
m_info.m_hasNativeClipVertexMode = true;
}
m_info.m_hasOcclusionQuery = gGL->m_bHave_GL_ARB_occlusion_query;
m_info.m_hasFramebufferBlit = gGL->m_bHave_GL_EXT_framebuffer_blit || gGL->m_bHave_GL_ARB_framebuffer_object;
GLint nMaxAniso = 0;
gGL->glGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &nMaxAniso );
m_info.m_maxAniso = clamp<int>( nMaxAniso, 0, 16 );
// We don't currently used bindable uniforms, but I've been experimenting with them so I might as well check this in just in case they turn out to be useful.
m_info.m_hasBindableUniforms = gGL->m_bHave_GL_EXT_bindable_uniform;
m_info.m_hasBindableUniforms = false; // !!! FIXME hardwiring this path to false until we see how to accelerate it properly
m_info.m_maxVertexBindableUniforms = 0;
m_info.m_maxFragmentBindableUniforms = 0;
m_info.m_maxBindableUniformSize = 0;
if (m_info.m_hasBindableUniforms)
{
gGL->glGetIntegerv(GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT, &m_info.m_maxVertexBindableUniforms);
gGL->glGetIntegerv(GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT, &m_info.m_maxFragmentBindableUniforms);
gGL->glGetIntegerv(GL_MAX_BINDABLE_UNIFORM_SIZE_EXT, &m_info.m_maxBindableUniformSize);
if ( ( m_info.m_maxVertexBindableUniforms < 1 ) || ( m_info.m_maxFragmentBindableUniforms < 1 ) || ( m_info.m_maxBindableUniformSize < ( sizeof( float ) * 4 * 256 ) ) )
{
m_info.m_hasBindableUniforms = false;
}
}
m_info.m_hasUniformBuffers = gGL->m_bHave_GL_ARB_uniform_buffer;
m_info.m_hasPerfPackage1 = true; // this flag is Mac-specific. We do slower things if you don't have Mac OS X 10.x.y or later. Linux always does the fast path!
//-------------------------------------------------------------------
// runtime options that aren't negotiable once set
m_info.m_hasDualShaders = CommandLine()->FindParm("-glmdualshaders") != 0;
//-------------------------------------------------------------------
// "can'ts "
#if defined( OSX )
m_info.m_cantBlitReliably = m_info.m_intel; //FIXME X3100&10.6.3 has problems blitting.. adjust this if bug fixed in 10.6.4
#else
// m_cantBlitReliably path doesn't work right now, and the Intel path is different for us on Linux/Win7 anyway
m_info.m_cantBlitReliably = false;
#endif
if (CommandLine()->FindParm("-glmenabletrustblit"))
{
m_info.m_cantBlitReliably = false; // we trust the blit, so set the cant-blit cap to false
}
if (CommandLine()->FindParm("-glmdisabletrustblit"))
{
m_info.m_cantBlitReliably = true; // we do not trust the blit, so set the cant-blit cap to true
}
// MSAA resolve issues
m_info.m_cantResolveFlipped = false;
#if defined( OSX )
m_info.m_cantResolveScaled = true; // generally true until new extension ships
#else
// DON'T just slam this to false and run without first testing with -gl_debug enabled on NVidia/AMD/etc.
// This path needs the m_bHave_GL_EXT_framebuffer_multisample_blit_scaled extension.
m_info.m_cantResolveScaled = true;
if ( gGL->m_bHave_GL_EXT_framebuffer_multisample_blit_scaled )
{
m_info.m_cantResolveScaled = false;
}
#endif
// gamma decode impacting shader codegen
m_info.m_costlyGammaFlips = false;
}
void GLMRendererInfo::PopulateDisplays()
{
SDLAPP_FUNC;
Assert( !m_display );
m_display = new GLMDisplayInfo;
// Populate display mode table.
m_display->PopulateModes();
}
void GLMRendererInfo::Dump( int which )
{
SDLAPP_FUNC;
GLMPRINTF(("\n #%d: GLMRendererInfo @ %p, renderer-id=(%08x) display-mask=%08x vram=%dMB",
which, this,
m_info.m_rendererID,
m_info.m_displayMask,
m_info.m_vidMemory >> 20
));
GLMPRINTF(("\n VendorID=%04x DeviceID=%04x Model=%s",
m_info.m_pciVendorID,
m_info.m_pciDeviceID,
m_info.m_pciModelString
));
m_display->Dump( which );
}
GLMDisplayDB::GLMDisplayDB ()
{
SDLAPP_FUNC;
m_renderer.m_display = NULL;
}
GLMDisplayDB::~GLMDisplayDB ( void )
{
SDLAPP_FUNC;
if ( m_renderer.m_display )
{
delete m_renderer.m_display;
m_renderer.m_display = NULL;
}
}
#ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
#endif
#ifndef GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
#endif
#ifndef GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX
#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
#endif
#ifndef GL_VBO_FREE_MEMORY_ATI
#define GL_VBO_FREE_MEMORY_ATI 0x87FB
#endif
#ifndef GL_TEXTURE_FREE_MEMORY_ATI
#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
#endif
#ifndef GL_RENDERBUFFER_FREE_MEMORY_ATI
#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
#endif
void GLMDisplayDB::PopulateRenderers( void )
{
SDLAPP_FUNC;
Assert( !m_renderer.m_display );
GLMRendererInfoFields fields;
memset( &fields, 0, sizeof(fields) );
// Assume 512MB of available video memory
fields.m_vidMemory = 512 * 1024 * 1024;
DebugPrintf( "GL_NVX_gpu_memory_info: %s\n", gGL->m_bHave_GL_NVX_gpu_memory_info ? "AVAILABLE" : "UNAVAILABLE" );
DebugPrintf( "GL_ATI_meminfo: %s\n", gGL->m_bHave_GL_ATI_meminfo ? "AVAILABLE" : "UNAVAILABLE" );
if ( gGL->m_bHave_GL_NVX_gpu_memory_info )
{
gGL->glGetError();
GLint nTotalDedicated = 0, nTotalAvail = 0, nCurrentAvail = 0;
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &nTotalDedicated );
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &nTotalAvail );
gGL->glGetIntegerv( GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &nCurrentAvail );
if ( gGL->glGetError() )
{
DebugPrintf( "GL_NVX_gpu_memory_info: Failed retrieving available GPU memory\n" );
}
else
{
DebugPrintf( "GL_NVX_gpu_memory_info: Total Dedicated: %u, Total Avail: %u, Current Avail: %u\n", nTotalDedicated, nTotalAvail, nCurrentAvail );
// Try to do something reasonable. Should we report dedicated or total available to the engine here?
// For now, just take the MAX of both.
uint64 nActualAvail = static_cast<uint64>( MAX( nTotalAvail, nTotalDedicated ) ) * 1024;
fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
}
}
else if ( gGL->m_bHave_GL_ATI_meminfo )
{
// As of 10/8/12 this extension is only available under Linux and Windows FireGL parts.
gGL->glGetError();
GLint nAvail[4] = { 0, 0, 0, 0 };
gGL->glGetIntegerv( GL_TEXTURE_FREE_MEMORY_ATI, nAvail );
if ( gGL->glGetError() )
{
DebugPrintf( "GL_ATI_meminfo: Failed retrieving available GPU memory\n" );
}
else
{
// param[0] - total memory free in the pool
// param[1] - largest available free block in the pool
// param[2] - total auxiliary memory free
// param[3] - largest auxiliary free block
DebugPrintf( "GL_ATI_meminfo: GL_TEXTURE_FREE_MEMORY_ATI: Total Free: %i, Largest Avail: %i, Total Aux: %i, Largest Aux Avail: %i\n",
nAvail[0], nAvail[1], nAvail[2], nAvail[3] );
uint64 nActualAvail = static_cast<uint64>( nAvail[0] ) * 1024;
fields.m_vidMemory = static_cast< GLint >( MIN( nActualAvail, 0x7FFFFFFF ) );
}
}
// Clamp the min amount of video memory to 256MB in case a query returned something bogus, or we interpreted it badly.
fields.m_vidMemory = MAX( fields.m_vidMemory, 128 * 1024 * 1024 );
fields.m_texMemory = fields.m_vidMemory;
fields.m_pciVendorID = GLM_OPENGL_VENDOR_ID;
fields.m_pciDeviceID = GLM_OPENGL_DEFAULT_DEVICE_ID;
if ( ( gGL->m_nDriverProvider == cGLDriverProviderIntel ) || ( gGL->m_nDriverProvider == cGLDriverProviderIntelOpenSource ) )
{
fields.m_pciDeviceID = GLM_OPENGL_LOW_PERF_DEVICE_ID;
}
/* fields.m_colorModes = (uint)-1;
fields.m_bufferModes = (uint)-1;
fields.m_depthModes = (uint)-1;
fields.m_stencilModes = (uint)-1;
fields.m_maxAuxBuffers = (uint)128;
fields.m_maxSampleBuffers = (uint)128;
fields.m_maxSamples = (uint)2048;
fields.m_sampleModes = (uint)128;
fields.m_sampleAlpha = (uint)32;
*/
GLint nMaxMultiSamples = 0;
gGL->glGetIntegerv( GL_MAX_SAMPLES_EXT, &nMaxMultiSamples );
fields.m_maxSamples = clamp<int>( nMaxMultiSamples, 0, 8 );
DebugPrintf( "GL_MAX_SAMPLES_EXT: %i\n", nMaxMultiSamples );
// We only have one GLMRendererInfo on Linux, unlike Mac OS X. Whatever libGL.so wants to do, we go with it.
m_renderer.Init( &fields );
// then go back and ask each renderer to populate its display info table.
m_renderer.PopulateDisplays();
}
void GLMDisplayDB::PopulateFakeAdapters( uint realRendererIndex ) // fake adapters = one real adapter times however many displays are on it
{
SDLAPP_FUNC;
Assert( realRendererIndex == 0 );
}
void GLMDisplayDB::Populate(void)
{
SDLAPP_FUNC;
this->PopulateRenderers();
this->PopulateFakeAdapters( 0 );
#if GLMDEBUG
this->Dump();
#endif
}
int GLMDisplayDB::GetFakeAdapterCount( void )
{
SDLAPP_FUNC;
return 1;
}
bool GLMDisplayDB::GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut )
{
SDLAPP_FUNC;
if (fakeAdapterIndex >= GetFakeAdapterCount() )
{
*rendererOut = 0;
*displayOut = 0;
return true; // fail
}
*rendererOut = 0;
*displayOut = 0;
bool rendResult = GetRendererInfo( *rendererOut, rendererInfoOut );
bool dispResult = GetDisplayInfo( *rendererOut, *displayOut, displayInfoOut );
return rendResult || dispResult;
}
int GLMDisplayDB::GetRendererCount( void )
{
SDLAPP_FUNC;
return 1;
}
bool GLMDisplayDB::GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMRendererInfoFields ) );
if (rendererIndex >= GetRendererCount())
return true; // fail
*infoOut = m_renderer.m_info;
return false;
}
int GLMDisplayDB::GetDisplayCount( int rendererIndex )
{
SDLAPP_FUNC;
if (rendererIndex >= GetRendererCount())
{
Assert( 0 );
return 0; // fail
}
return 1;
}
bool GLMDisplayDB::GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMDisplayInfoFields ) );
if (rendererIndex >= GetRendererCount())
return true; // fail
if (displayIndex >= GetDisplayCount(rendererIndex))
return true; // fail
*infoOut = m_renderer.m_display->m_info;
return false;
}
int GLMDisplayDB::GetModeCount( int rendererIndex, int displayIndex )
{
SDLAPP_FUNC;
if (rendererIndex >= GetRendererCount())
return 0; // fail
if (displayIndex >= GetDisplayCount(rendererIndex))
return 0; // fail
return m_renderer.m_display->m_modes->Count();
}
bool GLMDisplayDB::GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut )
{
SDLAPP_FUNC;
memset( infoOut, 0, sizeof( GLMDisplayModeInfoFields ) );
if ( rendererIndex >= GetRendererCount())
return true; // fail
if (displayIndex >= GetDisplayCount( rendererIndex ) )
return true; // fail
if ( modeIndex >= GetModeCount( rendererIndex, displayIndex ) )
return true; // fail
if ( modeIndex >= 0 )
{
GLMDisplayMode *displayModeInfo = m_renderer.m_display->m_modes->Element( modeIndex );
*infoOut = displayModeInfo->m_info;
}
else
{
const GLMDisplayInfoFields &info = m_renderer.m_display->m_info;
infoOut->m_modePixelWidth = info.m_displayPixelWidth;
infoOut->m_modePixelHeight = info.m_displayPixelHeight;
infoOut->m_modeRefreshHz = 0;
//return true; // fail
}
return false;
}
void GLMDisplayDB::Dump( void )
{
SDLAPP_FUNC;
GLMPRINTF(("\n GLMDisplayDB @ %p ",this ));
m_renderer.Dump( 0 );
}
//===============================================================================
GLMDisplayInfo::GLMDisplayInfo()
{
SDLAPP_FUNC;
m_modes = NULL;
int Width, Height;
GetLargestDisplaySize( Width, Height );
m_info.m_displayPixelWidth = ( uint )Width;
m_info.m_displayPixelHeight = ( uint )Height;
}
GLMDisplayInfo::~GLMDisplayInfo( void )
{
SDLAPP_FUNC;
}
extern "C" int DisplayModeSortFunction( GLMDisplayMode * const *A, GLMDisplayMode * const *B )
{
SDLAPP_FUNC;
int bigger = -1;
int smaller = 1; // adjust these for desired ordering
// check refreshrate - higher should win
if ( (*A)->m_info.m_modeRefreshHz > (*B)->m_info.m_modeRefreshHz )
{
return bigger;
}
else if ( (*A)->m_info.m_modeRefreshHz < (*B)->m_info.m_modeRefreshHz )
{
return smaller;
}
// check area - larger mode should win
int areaa = (*A)->m_info.m_modePixelWidth * (*A)->m_info.m_modePixelHeight;
int areab = (*B)->m_info.m_modePixelWidth * (*B)->m_info.m_modePixelHeight;
if ( areaa > areab )
{
return bigger;
}
else if ( areaa < areab )
{
return smaller;
}
return 0; // equal rank
}
void GLMDisplayInfo::PopulateModes( void )
{
SDLAPP_FUNC;
Assert( !m_modes );
m_modes = new CUtlVector< GLMDisplayMode* >;
int nummodes = SDL_GetNumVideoDisplays();
for ( int i = 0; i < nummodes; i++ )
{
SDL_Rect rect = { 0, 0, 0, 0 };
if ( !SDL_GetDisplayBounds( i, &rect ) && rect.w && rect.h )
{
m_modes->AddToTail( new GLMDisplayMode( rect.w, rect.h, 0 ) );
}
}
// Add a big pile of window resolutions.
static const struct
{
uint w;
uint h;
} s_Resolutions[] =
{
{ 640, 480 }, // 4x3
{ 800, 600 },
{ 1024, 768 },
{ 1152, 864 },
{ 1280, 960 },
{ 1600, 1200 },
{ 1920, 1440 },
{ 2048, 1536 },
{ 1280, 720 }, // 16x9
{ 1366, 768 },
{ 1600, 900 },
{ 1920, 1080 },
{ 720, 480 }, // 16x10
{ 1280, 800 },
{ 1680, 1050 },
{ 1920, 1200 },
{ 2560, 1600 },
};
for ( int i = 0; i < ARRAYSIZE( s_Resolutions ); i++ )
{
uint w = s_Resolutions[ i ].w;
uint h = s_Resolutions[ i ].h;
if ( ( w <= m_info.m_displayPixelWidth ) && ( h <= m_info.m_displayPixelHeight ) )
{
m_modes->AddToTail( new GLMDisplayMode( w, h, 0 ) );
if ( ( w * 2 <= m_info.m_displayPixelWidth ) && ( h * 2 < m_info.m_displayPixelHeight ) )
{
// Add double of everything also - Retina proofing hopefully.
m_modes->AddToTail( new GLMDisplayMode( w * 2, h * 2, 0 ) );
}
}
}
m_modes->Sort( DisplayModeSortFunction );
// remove dupes.
nummodes = m_modes->Count();
int i = 1; // not zero!
while (i < nummodes)
{
GLMDisplayModeInfoFields& info0 = m_modes->Element( i - 1 )->m_info;
GLMDisplayModeInfoFields& info1 = m_modes->Element( i )->m_info;
if ( ( info0.m_modePixelWidth == info1.m_modePixelWidth ) &&
( info0.m_modePixelHeight == info1.m_modePixelHeight ) &&
( info0.m_modeRefreshHz == info1.m_modeRefreshHz ) )
{
m_modes->Remove(i);
nummodes--;
}
else
{
i++;
}
}
}
void GLMDisplayInfo::Dump( int which )
{
SDLAPP_FUNC;
GLMPRINTF(("\n #%d: GLMDisplayInfo @ %08x, pixwidth=%d pixheight=%d",
which, (int)this, m_info.m_displayPixelWidth, m_info.m_displayPixelHeight ));
FOR_EACH_VEC( *m_modes, i )
{
( *m_modes )[i]->Dump(i);
}
}
File diff suppressed because it is too large Load Diff
+410
View File
@@ -0,0 +1,410 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/materialsystem2app.h"
#include "FileSystem.h"
#include "materialsystem2/IMaterialSystem2.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "filesystem_init.h"
#include "inputsystem/iinputsystem.h"
#include "tier2/tier2.h"
#include "rendersystem/irenderdevice.h"
#include "rendersystem/irenderhardwareconfig.h"
#include "vstdlib/jobthread.h"
//#include "videocfg/videocfg.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CMaterialSystem2App::CMaterialSystem2App()
{
m_RenderFactory = NULL;
m_hSwapChain = SWAP_CHAIN_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Creates render system
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::AddRenderSystem()
{
bool bIsVistaOrHigher = IsPlatformWindowsPC() && ( Plat_GetOSVersion() >= PLAT_OS_VERSION_VISTA );
const char *pShaderDLL = !IsPlatformX360() ? CommandLine()->ParmValue( "-rendersystemdll" ) : NULL;
if ( !pShaderDLL )
{
if ( IsPlatformWindowsPC() )
{
pShaderDLL = "rendersystemdx11.dll";
}
else if ( IsPlatformX360() )
{
pShaderDLL = "rendersystemdx9_360.dll";
}
else
{
pShaderDLL = "rendersystemgl.dll";
}
}
// Disallow dx11 on XP machines
if ( !bIsVistaOrHigher && !Q_stricmp( pShaderDLL, "rendersystemdx11.dll" ) )
{
pShaderDLL = "rendersystemdx9.dll";
}
AppModule_t module = LoadModule( pShaderDLL );
if ( module == APP_MODULE_INVALID )
{
if ( IsPlatformWindowsPC() )
{
pShaderDLL = "rendersystemdx9.dll";
module = LoadModule( pShaderDLL );
}
if ( module == APP_MODULE_INVALID )
{
pShaderDLL = "rendersystemempty.dll";
module = LoadModule( pShaderDLL );
if ( module == APP_MODULE_INVALID )
return false;
}
}
AddSystem( module, RENDER_DEVICE_MGR_INTERFACE_VERSION );
if ( IsPlatformX360() )
{
m_nRenderSystem = RENDER_SYSTEM_X360;
}
else if ( V_stristr( pShaderDLL, "rendersystemgl" ) != NULL )
{
m_nRenderSystem = RENDER_SYSTEM_GL;
}
else if ( V_stristr( pShaderDLL, "rendersystemdx11" ) != NULL )
{
m_nRenderSystem = RENDER_SYSTEM_DX11;
}
else
{
m_nRenderSystem = RENDER_SYSTEM_DX9;
}
return true;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::Create()
{
if ( !AddRenderSystem() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
{ "materialsystem2.dll", MATERIAL_SYSTEM2_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
if ( !AddSystems( appSystems ) )
return false;
const char *pNumThreadsString = CommandLine()->ParmValue( "-threads" );
if ( pNumThreadsString )
{
m_nThreadCount = atoi( pNumThreadsString );
}
else
{
const CPUInformation &cpuInfo = GetCPUInformation();
m_nThreadCount = cpuInfo.m_nLogicalProcessors - 1; // one core for main thread
}
if ( m_nThreadCount > 0 )
{
ThreadPoolStartParams_t sparms( false, m_nThreadCount );
g_pThreadPool->Start( sparms );
}
return true;
}
void CMaterialSystem2App::Destroy()
{
}
//-----------------------------------------------------------------------------
// Pump messages
//-----------------------------------------------------------------------------
void CMaterialSystem2App::AppPumpMessages()
{
g_pInputSystem->PollInputState();
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
if ( !BaseClass::SetupSearchPaths( pStartingDir, bOnlyUseStartingDir, bIsTool ) )
return false;
g_pFullFileSystem->AddSearchPath( GetGameInfoPath(), "SKIN", PATH_ADD_TO_HEAD );
return true;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
if ( !g_pFullFileSystem || !g_pMaterialSystem2 || !g_pRenderDeviceMgr || !g_pInputSystem )
{
Warning( "CMaterialSystem2App::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
// Needed to set up the device prior to Init() of other systems
g_pRenderDeviceMgr->InstallRenderDeviceSetup( this );
// Add paths...
// NOTE: Not sure if I should have this here or not. For now, my test
// is rendersystem test, which wants to do it itself.
// if ( !SetupSearchPaths( NULL, false, true ) )
// return false;
return true;
}
//-----------------------------------------------------------------------------
// Replace first underscore (if any) with \0 and return
// This handles special mods like tf_movies, l4d_movies, tf_comics
// As a result, such mods will use the gpu_level settings etc from the base mod
//-----------------------------------------------------------------------------
static void StripModSuffix( char *pModName )
{
int i = 0;
while ( pModName[i] != '\0' ) // Walk to the end of the string
{
if ( pModName[i] == '_') // If we hit an underscore
{
pModName[i] = '\0'; // Terminate the string here and bail out
return;
}
i++;
}
}
//-----------------------------------------------------------------------------
// Configures the application for the specific mod we're running
//-----------------------------------------------------------------------------
void CMaterialSystem2App::ApplyModSettings( )
{
/* PORTFIXME
char pModPath[MAX_PATH];
V_snprintf( pModPath, sizeof(pModPath), "" );
g_pFullFileSystem->GetSearchPath( "MOD", false, pModPath, sizeof( pModPath ) );
// Construct the mod name so we can use the mod-specific encrypted config files
char pModName[32];
V_StripTrailingSlash( pModPath );
V_FileBase( pModPath, pModName, sizeof( pModName ) );
StripModSuffix( pModName );
// Just use the highest levels in non-game apps
UpdateSystemLevel( CPU_LEVEL_HIGH, GPU_LEVEL_VERYHIGH, MEM_LEVEL_HIGH, GPU_MEM_LEVEL_HIGH, false, pModName );
*/
}
//-----------------------------------------------------------------------------
// Create our device + window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::CreateRenderDevice()
{
// Create a device for this adapter
int nAdapterCount = g_pRenderDeviceMgr->GetAdapterCount();
int nAdapter = CommandLine()->ParmValue( "-adapter", 0 );
if ( nAdapter >= nAdapterCount )
{
Warning( "Specified too high an adapter number on the commandline (%d/%d)!\n", nAdapter, nAdapterCount );
return false;
}
int nFlags = 0;
bool bResizing = !IsConsoleApp() && ( CommandLine()->CheckParm( "-resizing" ) != NULL );
if ( bResizing )
{
nFlags |= RENDER_CREATE_DEVICE_RESIZE_WINDOWS;
}
m_RenderFactory = g_pRenderDeviceMgr->CreateDevice( nAdapter, nFlags );
if ( !m_RenderFactory )
{
Warning( "Unable to set mode!\n" );
return false;
}
// Let other systems see the render device
AddNonAppSystemFactory( m_RenderFactory );
ReconnectSystems( RENDER_DEVICE_INTERFACE_VERSION );
ReconnectSystems( RENDER_HARDWARECONFIG_INTERFACE_VERSION );
g_pRenderDevice = (IRenderDevice*)m_RenderFactory( RENDER_DEVICE_INTERFACE_VERSION, NULL );
g_pRenderHardwareConfig = (IRenderHardwareConfig*)m_RenderFactory( RENDER_HARDWARECONFIG_INTERFACE_VERSION, NULL );
// Fixup the platform level
if ( m_nRenderSystem == RENDER_SYSTEM_DX11 )
{
if ( g_pRenderHardwareConfig->GetDXSupportLevel() < 100 )
{
m_nRenderSystem = RENDER_SYSTEM_DX9;
}
}
if ( !IsConsoleApp() )
return CreateMainWindow( bResizing );
return CreateMainConsoleWindow();
}
//-----------------------------------------------------------------------------
// Create our window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::PostInit( )
{
if ( !BaseClass::PostInit() )
return false;
// Set up mod settings
ApplyModSettings();
return true;
}
void CMaterialSystem2App::PreShutdown()
{
if ( g_pInputSystem )
{
g_pInputSystem->DetachFromWindow( );
}
if ( g_pRenderDevice )
{
g_pRenderDevice->DestroySwapChain( m_hSwapChain );
m_hSwapChain = SWAP_CHAIN_HANDLE_INVALID;
}
BaseClass::PreShutdown();
}
//-----------------------------------------------------------------------------
// Creates the main 3d window
//-----------------------------------------------------------------------------
bool CMaterialSystem2App::CreateMainWindow( bool bResizing )
{
// NOTE: This could be placed into a separate function
// Create a main 3d-capable window
int nWidth = 1280;
int nHeight = IsPlatformX360() ? 720 : 960;
bool bFullscreen = ( CommandLine()->CheckParm( "-fullscreen" ) != NULL );
const char *pArg;
if ( CommandLine()->CheckParm( "-width", &pArg ) )
{
nWidth = atoi( pArg );
}
if ( CommandLine()->CheckParm( "-height", &pArg ) )
{
nHeight = atoi( pArg );
}
m_hSwapChain = Create3DWindow( GetAppName(), nWidth, nHeight, bResizing, bFullscreen, true );
return ( m_hSwapChain != SWAP_CHAIN_HANDLE_INVALID );
}
bool CMaterialSystem2App::CreateMainConsoleWindow()
{
RenderDeviceInfo_t mode;
mode.m_DisplayMode.m_nWidth = 512;
mode.m_DisplayMode.m_nHeight = 512;
mode.m_DisplayMode.m_Format = IMAGE_FORMAT_RGBA8888;
mode.m_DisplayMode.m_nRefreshRateNumerator = 60;
mode.m_DisplayMode.m_nRefreshRateDenominator = 1;
mode.m_bFullscreen = false;
mode.m_nBackBufferCount = 1;
mode.m_bWaitForVSync = false;
#ifdef PLATFORM_WINDOWS_PC
m_hSwapChain = g_pRenderDevice->CreateSwapChain( Plat_GetShellWindow(), mode );
return ( m_hSwapChain != SWAP_CHAIN_HANDLE_INVALID );
#endif
return true;
}
//-----------------------------------------------------------------------------
// Creates a 3d-capable window
//-----------------------------------------------------------------------------
SwapChainHandle_t CMaterialSystem2App::Create3DWindow( const char *pTitle, int nWidth, int nHeight, bool bResizing, bool bFullscreen, bool bAcceptsInput )
{
PlatWindow_t hWnd = (PlatWindow_t)CreateAppWindow( GetAppInstance(), pTitle, !bFullscreen, nWidth, nHeight, bResizing );
if ( !hWnd )
return SWAP_CHAIN_HANDLE_INVALID;
// By default, everything will just use this one swap chain.
RenderDeviceInfo_t mode;
mode.m_DisplayMode.m_nWidth = nWidth;
mode.m_DisplayMode.m_nHeight = nHeight;
mode.m_DisplayMode.m_Format = IMAGE_FORMAT_RGBA8888;
mode.m_DisplayMode.m_nRefreshRateNumerator = 60;
mode.m_DisplayMode.m_nRefreshRateDenominator = 1;
mode.m_bFullscreen = bFullscreen;
mode.m_nBackBufferCount = bFullscreen ? 2 : 1;
mode.m_bWaitForVSync = ( CommandLine()->CheckParm( "-vsync" ) != NULL );
SwapChainHandle_t hSwapChain = g_pRenderDevice->CreateSwapChain( hWnd, mode );
if ( bAcceptsInput )
{
g_pInputSystem->AttachToWindow( (void*)hWnd );
}
return hSwapChain;
}
//-----------------------------------------------------------------------------
// Returns the window associated with a swap chain
//-----------------------------------------------------------------------------
PlatWindow_t CMaterialSystem2App::GetAppWindow()
{
if ( !m_hSwapChain || !g_pRenderDevice )
return PLAT_WINDOW_INVALID;
return g_pRenderDevice->GetSwapChainWindow( m_hSwapChain );
}
#endif // _WIN32
+267
View File
@@ -0,0 +1,267 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/matsysapp.h"
#include "FileSystem.h"
#include "materialsystem/IMaterialSystem.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "filesystem_init.h"
#include "inputsystem/iinputsystem.h"
#include "tier2/tier2.h"
#include "videocfg/videocfg.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CMatSysApp::CMatSysApp()
{
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CMatSysApp::Create()
{
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
if ( !AddSystems( appSystems ) )
return false;
IMaterialSystem *pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
if ( !pMaterialSystem )
{
Warning( "CMatSysApp::Create: Unable to connect to necessary interface!\n" );
return false;
}
pMaterialSystem->SetShaderAPI( "shaderapidx9.dll" );
return true;
}
void CMatSysApp::Destroy()
{
}
//-----------------------------------------------------------------------------
// Pump messages
//-----------------------------------------------------------------------------
void CMatSysApp::AppPumpMessages()
{
g_pInputSystem->PollInputState();
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CMatSysApp::SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool )
{
if ( !BaseClass::SetupSearchPaths( pStartingDir, bOnlyUseStartingDir, bIsTool ) )
return false;
g_pFullFileSystem->AddSearchPath( GetGameInfoPath(), "SKIN", PATH_ADD_TO_HEAD );
return true;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CMatSysApp::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
if ( !g_pFullFileSystem || !g_pMaterialSystem || !g_pInputSystem )
{
Warning( "CMatSysApp::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
// Add paths...
if ( !SetupSearchPaths( NULL, false, true ) )
return false;
const char *pArg;
int iWidth = 1024;
int iHeight = 768;
bool bWindowed = (CommandLine()->CheckParm( "-fullscreen" ) == NULL);
if (CommandLine()->CheckParm( "-width", &pArg ))
{
iWidth = atoi( pArg );
}
if (CommandLine()->CheckParm( "-height", &pArg ))
{
iHeight = atoi( pArg );
}
m_nWidth = iWidth;
m_nHeight = iHeight;
m_HWnd = CreateAppWindow( GetAppInstance(), GetAppName(), bWindowed, iWidth, iHeight, false );
if ( !m_HWnd )
return false;
g_pInputSystem->AttachToWindow( m_HWnd );
// NOTE: If we specifically wanted to use a particular shader DLL, we set it here...
//m_pMaterialSystem->SetShaderAPI( "shaderapidx8" );
// Get the adapter from the command line....
const char *pAdapterString;
int adapter = 0;
if (CommandLine()->CheckParm( "-adapter", &pAdapterString ))
{
adapter = atoi( pAdapterString );
}
int adapterFlags = 0;
if ( CommandLine()->CheckParm( "-ref" ) )
{
adapterFlags |= MATERIAL_INIT_REFERENCE_RASTERIZER;
}
if ( AppUsesReadPixels() )
{
adapterFlags |= MATERIAL_INIT_ALLOCATE_FULLSCREEN_TEXTURE;
}
g_pMaterialSystem->SetAdapter( adapter, adapterFlags );
return true;
}
void CMatSysApp::PostShutdown()
{
if ( g_pInputSystem )
{
g_pInputSystem->DetachFromWindow( );
}
BaseClass::PostShutdown();
}
//-----------------------------------------------------------------------------
// Gets the window size
//-----------------------------------------------------------------------------
int CMatSysApp::GetWindowWidth() const
{
return m_nWidth;
}
int CMatSysApp::GetWindowHeight() const
{
return m_nHeight;
}
//-----------------------------------------------------------------------------
// Returns the window
//-----------------------------------------------------------------------------
void* CMatSysApp::GetAppWindow()
{
return m_HWnd;
}
// Replace first underscore (if any) with \0 and return
// This handles special mods like tf_movies, l4d_movies, tf_comics
// As a result, such mods will use the gpu_level settings etc from the base mod
void StripModSuffix( char *pModName )
{
int i = 0;
while ( pModName[i] != '\0' ) // Walk to the end of the string
{
if ( pModName[i] == '_') // If we hit an underscore
{
pModName[i] = '\0'; // Terminate the string here and bail out
return;
}
i++;
}
}
//-----------------------------------------------------------------------------
// Sets the video mode
//-----------------------------------------------------------------------------
bool CMatSysApp::SetVideoMode( )
{
MaterialSystem_Config_t config;
if ( CommandLine()->CheckParm( "-fullscreen" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, false );
}
else
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
}
if ( CommandLine()->CheckParm( "-resizing" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, true );
}
if ( CommandLine()->CheckParm( "-mat_vsync" ) )
{
config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, false );
}
config.m_nAASamples = CommandLine()->ParmValue( "-mat_antialias", 1 );
config.m_nAAQuality = CommandLine()->ParmValue( "-mat_aaquality", 0 );
if ( CommandLine()->FindParm( "-csm_quality_level" ) )
{
int nCSMQuality = CommandLine()->ParmValue( "-csm_quality_level", CSMQUALITY_VERY_LOW );
config.m_nCSMQuality = (CSMQualityMode_t)clamp( nCSMQuality, CSMQUALITY_VERY_LOW, CSMQUALITY_TOTAL_MODES - 1 );
}
config.m_VideoMode.m_Width = config.m_VideoMode.m_Height = 0;
config.m_VideoMode.m_Format = IMAGE_FORMAT_BGRX8888;
config.m_VideoMode.m_RefreshRate = 0;
config.SetFlag( MATSYS_VIDCFG_FLAGS_STENCIL, true );
bool modeSet = g_pMaterialSystem->SetMode( m_HWnd, config );
if (!modeSet)
{
Error( "Unable to set mode\n" );
return false;
}
char pModPath[MAX_PATH];
V_snprintf( pModPath, sizeof(pModPath), "" );
g_pFullFileSystem->GetSearchPath( "MOD", false, pModPath, sizeof( pModPath ) );
// Construct the mod name so we can use the mod-specific encrypted config files
char pModName[32];
V_StripTrailingSlash( pModPath );
V_FileBase( pModPath, pModName, sizeof( pModName ) );
StripModSuffix( pModName );
// Just use the highest levels in non-game apps
UpdateSystemLevel( CPU_LEVEL_HIGH, GPU_LEVEL_VERYHIGH, MEM_LEVEL_HIGH, GPU_MEM_LEVEL_HIGH, false, pModName );
g_pMaterialSystem->OverrideConfig( config, false );
return true;
}
#endif // _WIN32
+180
View File
@@ -0,0 +1,180 @@
//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose: Pieces of the application framework, shared between POSIX systems (Mac OS X, Linux, etc)
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "appframework/AppFramework.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "interface.h"
#include "filesystem.h"
#include "appframework/IAppSystemGroup.h"
#include "filesystem_init.h"
#include "tier1/convar.h"
#include "vstdlib/cvar.h"
#include "togl/rendermechanism.h"
// NOTE: This has to be the last file included! (turned off below, since this is included like a header)
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Globals...
//-----------------------------------------------------------------------------
HINSTANCE s_HInstance;
static CSimpleLoggingListener s_SimpleLoggingListener;
ILoggingListener *g_pDefaultLoggingListener = &s_SimpleLoggingListener;
//-----------------------------------------------------------------------------
// HACK: Since I don't want to refit vgui yet...
//-----------------------------------------------------------------------------
void *GetAppInstance()
{
return s_HInstance;
}
//-----------------------------------------------------------------------------
// Sets the application instance, should only be used if you're not calling AppMain.
//-----------------------------------------------------------------------------
void SetAppInstance( void* hInstance )
{
s_HInstance = (HINSTANCE)hInstance;
}
//-----------------------------------------------------------------------------
// Version of AppMain used by windows applications
//-----------------------------------------------------------------------------
int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup )
{
Assert( 0 );
return -1;
}
static CNonFatalLoggingResponsePolicy s_NonFatalLoggingResponsePolicy;
//-----------------------------------------------------------------------------
// Version of AppMain used by console applications
//-----------------------------------------------------------------------------
int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup )
{
Assert( pAppSystemGroup );
LoggingSystem_SetLoggingResponsePolicy( &s_NonFatalLoggingResponsePolicy );
s_HInstance = NULL;
CommandLine()->CreateCmdLine( argc, argv );
return pAppSystemGroup->Run( );
}
//-----------------------------------------------------------------------------
//
// Default implementation of an application meant to be run using Steam
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSteamApplication::CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup )
{
m_pChildAppSystemGroup = pAppSystemGroup;
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Create necessary interfaces
//-----------------------------------------------------------------------------
bool CSteamApplication::Create( )
{
FileSystem_SetErrorMode( FS_ERRORMODE_NONE );
char pFileSystemDLL[MAX_PATH];
if ( FileSystem_GetFileSystemDLLName( pFileSystemDLL, MAX_PATH, m_bSteam ) != FS_OK )
return false;
// Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
AddSystem( cvarModule, CVAR_INTERFACE_VERSION );
AppModule_t fileSystemModule = LoadModule( pFileSystemDLL );
m_pFileSystem = (IFileSystem*)AddSystem( fileSystemModule, FILESYSTEM_INTERFACE_VERSION );
if ( !m_pFileSystem )
{
Error( "Unable to load %s", pFileSystemDLL );
return false;
}
return true;
}
bool CSteamApplication::GetFileSystemDLLName( char *pOut, int nMaxBytes, bool &bIsSteam )
{
return FileSystem_GetFileSystemDLLName( pOut, nMaxBytes, bIsSteam ) == FS_OK;
}
//-----------------------------------------------------------------------------
// The file system pointer is invalid at this point
//-----------------------------------------------------------------------------
void CSteamApplication::Destroy()
{
m_pFileSystem = NULL;
}
//-----------------------------------------------------------------------------
// Pre-init, shutdown
//-----------------------------------------------------------------------------
bool CSteamApplication::PreInit( )
{
return true;
}
void CSteamApplication::PostShutdown( )
{
}
//-----------------------------------------------------------------------------
// Run steam main loop
//-----------------------------------------------------------------------------
int CSteamApplication::Main( )
{
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Run( );
}
int CSteamApplication::Startup()
{
int nRetVal = BaseClass::Startup();
if ( GetCurrentStage() != NONE )
return nRetVal;
if ( FileSystem_SetBasePaths( m_pFileSystem ) != FS_OK )
return 0;
// Now that Steam is loaded, we can load up main libraries through steam
m_pChildAppSystemGroup->Setup( m_pFileSystem, this );
return m_pChildAppSystemGroup->Startup();
}
void CSteamApplication::Shutdown()
{
m_pChildAppSystemGroup->Shutdown();
BaseClass::Shutdown();
}
// Turn off memdbg macros (turned on up top) since this is included like a header
#include "tier0/memdbgoff.h"
File diff suppressed because it is too large Load Diff
+120
View File
@@ -0,0 +1,120 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifdef _WIN32
#include "appframework/vguimaterialsystem2app.h"
#include "vgui/IVGui.h"
#include "vgui/ISurface.h"
#include "vgui_controls/controls.h"
#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "tier0/dbg.h"
#include "vguirendersurface/ivguirendersurface.h"
#include "tier3/tier3.h"
#include "interfaces/interfaces.h"
#include "inputsystem/iinputstacksystem.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVGuiMaterialSystem2App::CVGuiMaterialSystem2App()
{
m_hAppInputContext = INPUT_CONTEXT_HANDLE_INVALID;
}
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CVGuiMaterialSystem2App::Create()
{
if ( !BaseClass::Create() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
// NOTE: This has to occur before vgui2.dll so it replaces vgui2's surface implementation
{ "vguirendersurface.dll", VGUI_SURFACE_INTERFACE_VERSION },
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
// Required to terminate the list
{ "", "" }
};
return AddSystems( appSystems );
}
void CVGuiMaterialSystem2App::Destroy()
{
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CVGuiMaterialSystem2App::PreInit( )
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
if ( !vgui::VGui_InitInterfacesList( "CVGuiMaterialSystem2App", &factory, 1 ) )
return false;
if ( !g_pVGuiRenderSurface )
{
Warning( "CVGuiMaterialSystem2App::PreInit: Unable to connect to necessary interface!\n" );
return false;
}
return true;
}
bool CVGuiMaterialSystem2App::PostInit()
{
if ( !BaseClass::PostInit() )
return false;
m_hAppInputContext = g_pInputStackSystem->PushInputContext();
InputContextHandle_t hVGuiInputContext = g_pInputStackSystem->PushInputContext();
g_pVGuiRenderSurface->SetInputContext( hVGuiInputContext );
g_pVGuiRenderSurface->EnableWindowsMessages( true );
return true;
}
void CVGuiMaterialSystem2App::PreShutdown()
{
g_pVGuiRenderSurface->EnableWindowsMessages( false );
g_pVGuiRenderSurface->SetInputContext( NULL );
if ( m_hAppInputContext != INPUT_CONTEXT_HANDLE_INVALID )
{
g_pInputStackSystem->PopInputContext(); // Vgui
g_pInputStackSystem->PopInputContext(); // App
}
BaseClass::PreShutdown();
}
void CVGuiMaterialSystem2App::PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
InputContextHandle_t CVGuiMaterialSystem2App::GetAppInputContext()
{
return m_hAppInputContext;
}
#endif // _WIN32
+1
View File
@@ -0,0 +1 @@
IMPORTANT: Do not remove the custom build step for this file