diff --git a/CMake/Templates/plugins.cfg.in b/CMake/Templates/plugins.cfg.in index 3f160cf9ba2..c1ba1c4ef97 100644 --- a/CMake/Templates/plugins.cfg.in +++ b/CMake/Templates/plugins.cfg.in @@ -4,11 +4,11 @@ PluginFolder=@OGRE_PLUGIN_DIR_REL@ # Define plugins -@OGRE_COMMENT_RENDERSYSTEM_METAL@ Plugin=RenderSystem_Metal -@OGRE_COMMENT_RENDERSYSTEM_D3D11@ Plugin=RenderSystem_Direct3D11 -@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ Plugin=RenderSystem_GL3Plus -@OGRE_COMMENT_RENDERSYSTEM_GLES@ Plugin=RenderSystem_GLES -@OGRE_COMMENT_RENDERSYSTEM_GLES2@ Plugin=RenderSystem_GLES2 +@OGRE_COMMENT_RENDERSYSTEM_METAL@ PluginOptional=RenderSystem_Metal +@OGRE_COMMENT_RENDERSYSTEM_D3D11@ PluginOptional=RenderSystem_Direct3D11 +@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ PluginOptional=RenderSystem_GL3Plus +@OGRE_COMMENT_RENDERSYSTEM_GLES@ PluginOptional=RenderSystem_GLES +@OGRE_COMMENT_RENDERSYSTEM_GLES2@ PluginOptional=RenderSystem_GLES2 # If you add another RenderSystem make sure Vulkan is the last one or you might encounter issues on nVidia cards. -@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ Plugin=RenderSystem_Vulkan +@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ PluginOptional=RenderSystem_Vulkan @OGRE_COMMENT_PLUGIN_PARTICLEFX@ Plugin=Plugin_ParticleFX diff --git a/CMake/Templates/plugins_d.cfg.in b/CMake/Templates/plugins_d.cfg.in index bcc3e1c2a3b..1011519dbb7 100644 --- a/CMake/Templates/plugins_d.cfg.in +++ b/CMake/Templates/plugins_d.cfg.in @@ -4,11 +4,11 @@ PluginFolder=@OGRE_PLUGIN_DIR_DBG@ # Define plugins -@OGRE_COMMENT_RENDERSYSTEM_D3D11@ Plugin=RenderSystem_Direct3D11_d -@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ Plugin=RenderSystem_GL3Plus_d -@OGRE_COMMENT_RENDERSYSTEM_GLES@ Plugin=RenderSystem_GLES_d -@OGRE_COMMENT_RENDERSYSTEM_GLES2@ Plugin=RenderSystem_GLES2_d -@OGRE_COMMENT_RENDERSYSTEM_METAL@ Plugin=RenderSystem_Metal_d +@OGRE_COMMENT_RENDERSYSTEM_D3D11@ PluginOptional=RenderSystem_Direct3D11_d +@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ PluginOptional=RenderSystem_GL3Plus_d +@OGRE_COMMENT_RENDERSYSTEM_GLES@ PluginOptional=RenderSystem_GLES_d +@OGRE_COMMENT_RENDERSYSTEM_GLES2@ PluginOptional=RenderSystem_GLES2_d +@OGRE_COMMENT_RENDERSYSTEM_METAL@ PluginOptional=RenderSystem_Metal_d # If you add another RenderSystem make sure Vulkan is the last one or you might encounter issues on nVidia cards. -@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ Plugin=RenderSystem_Vulkan_d +@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ PluginOptional=RenderSystem_Vulkan_d @OGRE_COMMENT_PLUGIN_PARTICLEFX@ Plugin=Plugin_ParticleFX_d diff --git a/OgreMain/include/OgreDynLib.h b/OgreMain/include/OgreDynLib.h index 139229fcb42..07dd6dfdec6 100644 --- a/OgreMain/include/OgreDynLib.h +++ b/OgreMain/include/OgreDynLib.h @@ -99,14 +99,18 @@ namespace Ogre { ~DynLib(); /** Load the library + @param bOptional When true, we will skip it if it fails to initialize */ - void load(); + void load( const bool bOptional ); /** Unload the library */ void unload(); /// Get the name of the library const String& getName(void) const { return mName; } + /// Returns true if it's successfully loaded + bool isLoaded(void) const; + /** Returns the address of the given symbol from the loaded library. @param diff --git a/OgreMain/include/OgreDynLibManager.h b/OgreMain/include/OgreDynLibManager.h index 127411c4348..9e43cf608b4 100644 --- a/OgreMain/include/OgreDynLibManager.h +++ b/OgreMain/include/OgreDynLibManager.h @@ -72,8 +72,10 @@ namespace Ogre { /** Loads the passed library. @param filename The name of the library. The extension can be omitted. + @param bOptional + When true, we will skip it if it fails to initialize */ - DynLib* load(const String& filename); + DynLib *load( const String &filename, const bool bOptional ); /** Unloads the passed library. @param lib diff --git a/OgreMain/include/OgreRoot.h b/OgreMain/include/OgreRoot.h index 1714d29700b..5ce441d0fb9 100644 --- a/OgreMain/include/OgreRoot.h +++ b/OgreMain/include/OgreRoot.h @@ -711,8 +711,9 @@ namespace Ogre method which instantiates a Plugin subclass and calls Root::installPlugin. It should also implement dllStopPlugin (see Root::unloadPlugin) @param pluginName Name of the plugin library to load + @param bOptional When true, we will skip it if it fails to initialize */ - void loadPlugin(const String& pluginName); + void loadPlugin(const String& pluginName, const bool bOptional); /** Manually unloads a Plugin contained in a DLL / DSO. @remarks diff --git a/OgreMain/src/OgreDynLib.cpp b/OgreMain/src/OgreDynLib.cpp index 3802292218b..4457089e26a 100644 --- a/OgreMain/src/OgreDynLib.cpp +++ b/OgreMain/src/OgreDynLib.cpp @@ -68,7 +68,7 @@ namespace Ogre { } //----------------------------------------------------------------------- - void DynLib::load() + void DynLib::load( const bool bOptional ) { // Log library load LogManager::getSingleton().logMessage("Loading library " + mName); @@ -105,11 +105,21 @@ namespace Ogre { } #endif if( !mInst ) - OGRE_EXCEPT( - Exception::ERR_INTERNAL_ERROR, - "Could not load dynamic library " + mName + - ". System Error: " + dynlibError(), - "DynLib::load" ); + { + if( !bOptional ) + { + OGRE_EXCEPT( + Exception::ERR_INTERNAL_ERROR, + "Could not load dynamic library " + mName + ". System Error: " + dynlibError(), + "DynLib::load" ); + } + else + { + LogManager::getSingleton().logMessage( "Could not load optional dynamic library " + + mName + ". System Error: " + dynlibError(), + LML_CRITICAL ); + } + } } //----------------------------------------------------------------------- @@ -118,17 +128,19 @@ namespace Ogre { // Log library unload LogManager::getSingleton().logMessage("Unloading library " + mName); - if( DYNLIB_UNLOAD( mInst ) ) + if( mInst ) { - OGRE_EXCEPT( - Exception::ERR_INTERNAL_ERROR, - "Could not unload dynamic library " + mName + - ". System Error: " + dynlibError(), - "DynLib::unload"); + if( DYNLIB_UNLOAD( mInst ) ) + { + OGRE_EXCEPT( + Exception::ERR_INTERNAL_ERROR, + "Could not unload dynamic library " + mName + ". System Error: " + dynlibError(), + "DynLib::unload" ); + } } - } - + //----------------------------------------------------------------------- + bool DynLib::isLoaded( void ) const { return mInst != NULL; } //----------------------------------------------------------------------- void* DynLib::getSymbol( const String& strName ) const throw() { @@ -185,7 +197,11 @@ namespace Ogre { #endif return ret; #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_FREEBSD - return String(dlerror()); + const char *errorStr = dlerror(); + if( errorStr ) + return String( errorStr ); + else + return String( "" ); #else return String(""); #endif diff --git a/OgreMain/src/OgreDynLibManager.cpp b/OgreMain/src/OgreDynLibManager.cpp index 0661ff3b64c..9ce4bb9309e 100644 --- a/OgreMain/src/OgreDynLibManager.cpp +++ b/OgreMain/src/OgreDynLibManager.cpp @@ -49,17 +49,17 @@ namespace Ogre { } //----------------------------------------------------------------------- - DynLib* DynLibManager::load( const String& filename) + DynLib *DynLibManager::load( const String &filename, const bool bOptional ) { - DynLibList::iterator i = mLibList.find(filename); - if (i != mLibList.end()) + DynLibList::iterator i = mLibList.find( filename ); + if( i != mLibList.end() ) { return i->second; } else { - DynLib* pLib = OGRE_NEW DynLib(filename); - pLib->load(); + DynLib *pLib = OGRE_NEW DynLib( filename ); + pLib->load( bOptional ); mLibList[filename] = pLib; return pLib; } diff --git a/OgreMain/src/OgreRoot.cpp b/OgreMain/src/OgreRoot.cpp index d4b2f665255..6bfae2df1fb 100644 --- a/OgreMain/src/OgreRoot.cpp +++ b/OgreMain/src/OgreRoot.cpp @@ -1203,23 +1203,22 @@ namespace Ogre { //----------------------------------------------------------------------- void Root::loadPlugins( const String& pluginsfile ) { - StringVector pluginList; - String pluginDir; ConfigFile cfg; - try { + try + { cfg.load( pluginsfile ); } - catch (Exception) + catch( Exception ) { - LogManager::getSingleton().logMessage(pluginsfile + " not found, automatic plugin loading disabled."); + LogManager::getSingleton().logMessage( pluginsfile + + " not found, automatic plugin loading disabled." ); return; } - pluginDir = cfg.getSetting("PluginFolder"); // Ignored on Mac OS X, uses Resources/ directory - pluginList = cfg.getMultiSetting("Plugin"); - - if (!pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\') + String pluginDir = + cfg.getSetting( "PluginFolder" ); // Ignored on Mac OS X, uses Resources/ directory + if( !pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\' ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT pluginDir += "\\"; @@ -1228,11 +1227,22 @@ namespace Ogre { #endif } - for( StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it ) { - loadPlugin(pluginDir + (*it)); + // First load optional plugins (which tend to be all RenderSystems) + const StringVector pluginList = cfg.getMultiSetting( "PluginOptional" ); + for( StringVector::const_iterator it = pluginList.begin(); it != pluginList.end(); ++it ) + { + loadPlugin( pluginDir + ( *it ), true ); + } + } + { + // Then load non-optional plugins (which tend to depend on RenderSystems) + const StringVector pluginList = cfg.getMultiSetting( "Plugin" ); + for( StringVector::const_iterator it = pluginList.begin(); it != pluginList.end(); ++it ) + { + loadPlugin( pluginDir + ( *it ), false ); + } } - } //----------------------------------------------------------------------- void Root::shutdownPlugins(void) @@ -1256,18 +1266,21 @@ namespace Ogre { { #if OGRE_PLATFORM != OGRE_PLATFORM_NACL && OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN // unload dynamic libs first - for (PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i) + for( PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i ) { - // Call plugin shutdown - #ifdef __GNUC__ - __extension__ - #endif - DLL_STOP_PLUGIN pFunc = reinterpret_cast((*i)->getSymbol("dllStopPlugin")); - // this will call uninstallPlugin - pFunc(); + if( ( *i )->isLoaded() ) + { + // Call plugin shutdown +# ifdef __GNUC__ + __extension__ +# endif + DLL_STOP_PLUGIN pFunc = + reinterpret_cast( ( *i )->getSymbol( "dllStopPlugin" ) ); + // this will call uninstallPlugin + pFunc(); + } // Unload library & destroy - DynLibManager::getSingleton().unload(*i); - + DynLibManager::getSingleton().unload( *i ); } mPluginLibs.clear(); @@ -1459,29 +1472,52 @@ namespace Ogre { } //----------------------------------------------------------------------- - void Root::loadPlugin(const String& pluginName) + void Root::loadPlugin( const String &pluginName, const bool bOptional ) { #if OGRE_PLATFORM != OGRE_PLATFORM_NACL && OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN // Load plugin library - DynLib* lib = DynLibManager::getSingleton().load( pluginName ); + DynLib* lib = DynLibManager::getSingleton().load( pluginName, bOptional ); + // Store for later unload // Check for existence, because if called 2+ times DynLibManager returns existing entry if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end()) { mPluginLibs.push_back(lib); - // Call startup function - #ifdef __GNUC__ - __extension__ - #endif - DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin"); + if( lib->isLoaded() ) + { + // Call startup function +# ifdef __GNUC__ + __extension__ +# endif + DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol( "dllStartPlugin" ); - if (!pFunc) - OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName, - "Root::loadPlugin"); + if( !pFunc ) + { + OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, + "Cannot find symbol dllStartPlugin in library " + pluginName, + "Root::loadPlugin" ); + } - // This must call installPlugin - pFunc(); + try + { + // This must call installPlugin + pFunc(); + } + catch( Exception &e ) + { + if( !bOptional ) + { + throw; + } + else + { + LogManager::getSingleton().logMessage( + "Optional Plugin " + pluginName + " failed with exception:", LML_CRITICAL ); + LogManager::getSingleton().logMessage( e.getFullDescription(), LML_CRITICAL ); + } + } + } } #endif } @@ -1495,19 +1531,21 @@ namespace Ogre { { if ((*i)->getName() == pluginName) { - // Call plugin shutdown - #ifdef __GNUC__ - __extension__ - #endif - DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin"); - // this must call uninstallPlugin - pFunc(); + if( ( *i )->isLoaded() ) + { + // Call plugin shutdown +# ifdef __GNUC__ + __extension__ +# endif + DLL_STOP_PLUGIN pFunc = ( DLL_STOP_PLUGIN )( *i )->getSymbol( "dllStopPlugin" ); + // this must call uninstallPlugin + pFunc(); + } // Unload library (destroyed by DynLibManager) - DynLibManager::getSingleton().unload(*i); - mPluginLibs.erase(i); + DynLibManager::getSingleton().unload( *i ); + mPluginLibs.erase( i ); return; } - } #endif } diff --git a/PlugIns/ParticleFX/src/OgreParticleFX.cpp b/PlugIns/ParticleFX/src/OgreParticleFX.cpp index e0fd2391672..552b8dfb2a2 100644 --- a/PlugIns/ParticleFX/src/OgreParticleFX.cpp +++ b/PlugIns/ParticleFX/src/OgreParticleFX.cpp @@ -35,7 +35,12 @@ namespace Ogre { ParticleFXPlugin* plugin; //----------------------------------------------------------------------- - extern "C" void _OgreParticleFXExport dllStartPlugin(void) throw() + +# if __cplusplus >= 201103L + extern "C" void _OgreParticleFXExport dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreParticleFXExport dllStartPlugin( void ) throw( Exception ) +# endif { plugin = OGRE_NEW ParticleFXPlugin(); Root::getSingleton().installPlugin(plugin); diff --git a/RenderSystems/Direct3D11/src/OgreD3D11EngineDll.cpp b/RenderSystems/Direct3D11/src/OgreD3D11EngineDll.cpp index 494f06524af..c2d7e36257d 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11EngineDll.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11EngineDll.cpp @@ -33,7 +33,11 @@ namespace Ogre { D3D11Plugin* plugin; - extern "C" void _OgreD3D11Export dllStartPlugin(void) throw() +# if __cplusplus >= 201103L + extern "C" void _OgreD3D11Export dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreD3D11Export dllStartPlugin( void ) throw( Exception ) +# endif { plugin = new D3D11Plugin(); Root::getSingleton().installPlugin(plugin); diff --git a/RenderSystems/GL3Plus/src/OgreGL3PlusEngineDll.cpp b/RenderSystems/GL3Plus/src/OgreGL3PlusEngineDll.cpp index d1e6036bd81..783b77b288a 100644 --- a/RenderSystems/GL3Plus/src/OgreGL3PlusEngineDll.cpp +++ b/RenderSystems/GL3Plus/src/OgreGL3PlusEngineDll.cpp @@ -35,7 +35,11 @@ namespace Ogre { static GL3PlusPlugin* plugin; - extern "C" void _OgreGL3PlusExport dllStartPlugin(void) throw() +# if __cplusplus >= 201103L + extern "C" void _OgreGL3PlusExport dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreD3D11Export dllStartPlugin( void ) throw( Exception ) +# endif { plugin = OGRE_NEW GL3PlusPlugin(); Root::getSingleton().installPlugin(plugin); diff --git a/RenderSystems/Metal/src/OgreMetalEngineDll.mm b/RenderSystems/Metal/src/OgreMetalEngineDll.mm index b1fc3580b2c..d8173d1fddd 100644 --- a/RenderSystems/Metal/src/OgreMetalEngineDll.mm +++ b/RenderSystems/Metal/src/OgreMetalEngineDll.mm @@ -36,7 +36,11 @@ of this software and associated documentation files (the "Software"), to deal { static MetalPlugin* plugin; - extern "C" void _OgreMetalExport dllStartPlugin(void) throw() +# if __cplusplus >= 201103L + extern "C" void _OgreMetalExport dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreMetalExport dllStartPlugin( void ) throw( Exception ) +# endif { plugin = OGRE_NEW MetalPlugin(); Root::getSingleton().installPlugin(plugin); diff --git a/RenderSystems/NULL/src/OgreNULLEngineDll.cpp b/RenderSystems/NULL/src/OgreNULLEngineDll.cpp index 9f93cd2f82c..9990b75cfeb 100644 --- a/RenderSystems/NULL/src/OgreNULLEngineDll.cpp +++ b/RenderSystems/NULL/src/OgreNULLEngineDll.cpp @@ -35,7 +35,11 @@ namespace Ogre { static NULLPlugin* plugin; - extern "C" void _OgreNULLExport dllStartPlugin(void) throw() +# if __cplusplus >= 201103L + extern "C" void _OgreNULLExport dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreNULLExport dllStartPlugin( void ) throw( Exception ) +# endif { plugin = OGRE_NEW NULLPlugin(); Root::getSingleton().installPlugin(plugin); diff --git a/RenderSystems/Vulkan/src/OgreVulkanEngineDll.cpp b/RenderSystems/Vulkan/src/OgreVulkanEngineDll.cpp index 0ed9d6d2447..2b846e4dc53 100644 --- a/RenderSystems/Vulkan/src/OgreVulkanEngineDll.cpp +++ b/RenderSystems/Vulkan/src/OgreVulkanEngineDll.cpp @@ -35,7 +35,11 @@ namespace Ogre { static VulkanPlugin *plugin; - extern "C" void _OgreVulkanExport dllStartPlugin( void ) throw() +# if __cplusplus >= 201103L + extern "C" void _OgreVulkanExport dllStartPlugin( void ) noexcept( false ) +# else + extern "C" void _OgreVulkanExport dllStartPlugin( void ) throw( Exception ) +# endif { plugin = OGRE_NEW VulkanPlugin(); Root::getSingleton().installPlugin( plugin ); diff --git a/Samples/2.0/Tutorials/EmptyProject/CMake/Dependencies/OGRE.cmake b/Samples/2.0/Tutorials/EmptyProject/CMake/Dependencies/OGRE.cmake index 4b4e0068c1f..83cd1c712a7 100644 --- a/Samples/2.0/Tutorials/EmptyProject/CMake/Dependencies/OGRE.cmake +++ b/Samples/2.0/Tutorials/EmptyProject/CMake/Dependencies/OGRE.cmake @@ -48,9 +48,9 @@ macro( findPluginAndSetPath BUILD_TYPE CFG_VARIABLE LIBRARY_NAME ) if( EXISTS ${REAL_LIB_PATH} ) # DLL Exists, set the variable for Plugins.cfg if( ${BUILD_TYPE} STREQUAL "Debug" ) - set( ${CFG_VARIABLE} "Plugin=${LIBRARY_NAME}_d" ) + set( ${CFG_VARIABLE} "PluginOptional=${LIBRARY_NAME}_d" ) else() - set( ${CFG_VARIABLE} "Plugin=${LIBRARY_NAME}" ) + set( ${CFG_VARIABLE} "PluginOptional=${LIBRARY_NAME}" ) endif() # Copy the DLLs to the folders.