diff --git a/Core/Code/Controllers/mitkCoreActivator.cpp b/Core/Code/Controllers/mitkCoreActivator.cpp index be55e61c1e..445295a536 100644 --- a/Core/Code/Controllers/mitkCoreActivator.cpp +++ b/Core/Code/Controllers/mitkCoreActivator.cpp @@ -1,209 +1,308 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderingManager.h" #include "mitkPlanePositionManager.h" #include #include -//#include +#include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include +#include void HandleMicroServicesMessages(us::MsgType type, const char* msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string& programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for(int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } +class ShaderRepositoryTracker : public us::ServiceTracker +{ + +public: + + ShaderRepositoryTracker() + : Superclass(us::GetModuleContext()) + { + } + + virtual void Close() + { + us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); + Superclass::Close(); + } + + virtual void Open() + { + us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); + Superclass::Open(); + } + +private: + + typedef us::ServiceTracker Superclass; + + TrackedType AddingService(const ServiceReferenceType &reference) + { + mitk::IShaderRepository* shaderRepo = Superclass::AddingService(reference); + if (shaderRepo) + { + // Add all existing shaders from modules to the new shader repository. + // If the shader repository is registered in a modules activator, the + // GetLoadedModules() function call below will also return the module + // which is currently registering the repository. The HandleModuleEvent + // method contains code to avoid double registrations due to a fired + // ModuleEvent::LOADED event after the activators Load() method finished. + std::vector modules = us::ModuleRegistry::GetLoadedModules(); + for (std::vector::const_iterator iter = modules.begin(), + endIter = modules.end(); iter != endIter; ++iter) + { + this->AddModuleShaderToRepository(*iter, shaderRepo); + } + + m_ShaderRepositories.push_back(shaderRepo); + } + return shaderRepo; + } + + void RemovedService(const ServiceReferenceType& /*reference*/, TrackedType tracked) + { + m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked), + m_ShaderRepositories.end()); + } + + void HandleModuleEvent(const us::ModuleEvent moduleEvent) + { + if (moduleEvent.GetType() == us::ModuleEvent::LOADED) + { + std::vector shaderRepos; + for (std::map > >::const_iterator shaderMapIter = m_ModuleIdToShaderIds.begin(), + shaderMapEndIter = m_ModuleIdToShaderIds.end(); shaderMapIter != shaderMapEndIter; ++shaderMapIter) + { + if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end()) + { + shaderRepos.push_back(shaderMapIter->first); + } + } + AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos); + } + else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) + { + RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories); + } + } + + void AddModuleShadersToRepositories(us::Module* module, const std::vector& shaderRepos) + { + // search and load shader files + std::vector shaderResources = module->FindResources("Shaders", "*.xml", true); + for (std::vector::iterator i = shaderResources.begin(); + i != shaderResources.end(); ++i) + { + if (*i) + { + us::ModuleResourceStream rs(*i); + for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), + shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) + { + int id = (*shaderRepoIter)->LoadShader(rs, i->GetBaseName()); + if (id >= 0) + { + m_ModuleIdToShaderIds[*shaderRepoIter][module->GetModuleId()].push_back(id); + } + } + rs.seekg(0, std::ios_base::beg); + } + } + } + + void AddModuleShaderToRepository(us::Module* module, mitk::IShaderRepository* shaderRepo) + { + std::vector shaderRepos; + shaderRepos.push_back(shaderRepo); + this->AddModuleShadersToRepositories(module, shaderRepos); + } + + void RemoveModuleShadersFromRepositories(us::Module* module, + const std::vector& shaderRepos) + { + for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), + shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) + { + std::map >& moduleIdToShaderIds = m_ModuleIdToShaderIds[*shaderRepoIter]; + std::map >::iterator shaderIdsIter = + moduleIdToShaderIds.find(module->GetModuleId()); + if (shaderIdsIter != moduleIdToShaderIds.end()) + { + for (std::vector::iterator idIter = shaderIdsIter->second.begin(); + idIter != shaderIdsIter->second.end(); ++idIter) + { + (*shaderRepoIter)->UnloadShader(*idIter); + } + moduleIdToShaderIds.erase(shaderIdsIter); + } + } + } + +private: + + // Maps to each shader repository a map containing module ids and related + // shader registration ids + std::map > > m_ModuleIdToShaderIds; + std::vector m_ShaderRepositories; +}; + /* * This is the module activator for the "Mitk" module. It registers core services * like ... */ class MitkCoreActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } //m_RenderingManager = mitk::RenderingManager::New(); //context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_CoreDataNodeReader.reset(new mitk::CoreDataNodeReader); context->RegisterService(m_CoreDataNodeReader.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); - context->AddModuleListener(this, &MitkCoreActivator::HandleModuleEvent); + m_ShaderRepositoryTracker.Open(); /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ } void Unload(us::ModuleContext* ) { // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. + + m_ShaderRepositoryTracker.Close(); } private: - void HandleModuleEvent(const us::ModuleEvent moduleEvent); - - std::map > moduleIdToShaderIds; + ShaderRepositoryTracker m_ShaderRepositoryTracker; //mitk::RenderingManager::Pointer m_RenderingManager; std::auto_ptr m_PlanePositionManager; std::auto_ptr m_CoreDataNodeReader; std::auto_ptr m_PropertyAliases; std::auto_ptr m_PropertyDescriptions; std::auto_ptr m_PropertyExtensions; std::auto_ptr m_PropertyFilters; }; -void MitkCoreActivator::HandleModuleEvent(const us::ModuleEvent moduleEvent) -{ - if (moduleEvent.GetType() == us::ModuleEvent::LOADED) - { - // search and load shader files - std::vector shaderResoruces = - moduleEvent.GetModule()->FindResources("Shaders", "*.xml", true); - for (std::vector::iterator i = shaderResoruces.begin(); - i != shaderResoruces.end(); ++i) - { - if (*i) - { - us::ModuleResourceStream rs(*i); -// int id = m_ShaderRepository->LoadShader(rs, i->GetBaseName()); -// if (id >= 0) -// { -// moduleIdToShaderIds[moduleEvent.GetModule()->GetModuleId()].push_back(id); -// } - } - } - } - else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) - { - std::map >::iterator shaderIdsIter = - moduleIdToShaderIds.find(moduleEvent.GetModule()->GetModuleId()); - if (shaderIdsIter != moduleIdToShaderIds.end()) - { -// for (std::vector::iterator idIter = shaderIdsIter->second.begin(); -// idIter != shaderIdsIter->second.end(); ++idIter) -// { -// m_ShaderRepository->UnloadShader(*idIter); -// } -// moduleIdToShaderIds.erase(shaderIdsIter); - } - } - - -} - US_EXPORT_MODULE_ACTIVATOR(Mitk, MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE("Mitk", "Mitk")