//=========== (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