From 4efa087cd1276f73cf5c96807a3ef9c8954a2266 Mon Sep 17 00:00:00 2001 From: timoore Date: Tue, 4 Dec 2007 22:38:40 +0000 Subject: [PATCH] Don't modify OSG Registry with file path To set a path when loading model files, use an osg ReaderWriter::Options object. Put locks in ModelRegistry::readNode and ModelRegistry::readImage to avoid conflicts when files are loaded from both the pager and the main thread. --- projects/VC7.1/SimGear.vcproj | 6 +++++ simgear/misc/Makefile.am | 6 +++-- simgear/misc/PathOptions.cxx | 33 ++++++++++++++++++++++++ simgear/misc/PathOptions.hxx | 30 ++++++++++++++++++++++ simgear/scene/material/mat.cxx | 2 +- simgear/scene/model/ModelRegistry.cxx | 25 +++++------------- simgear/scene/model/ModelRegistry.hxx | 19 ++++---------- simgear/scene/model/animation.cxx | 5 ++-- simgear/scene/model/animation.hxx | 7 +++-- simgear/scene/model/model.cxx | 37 +++++++++++++++------------ simgear/scene/model/model.hxx | 12 ++++++--- simgear/scene/model/shadanim.cxx | 6 +++-- simgear/scene/sky/cloud.cxx | 9 ++++--- simgear/scene/sky/moon.cxx | 8 ++++-- simgear/scene/sky/oursun.cxx | 19 ++++++-------- 15 files changed, 147 insertions(+), 77 deletions(-) create mode 100644 simgear/misc/PathOptions.cxx create mode 100644 simgear/misc/PathOptions.hxx diff --git a/projects/VC7.1/SimGear.vcproj b/projects/VC7.1/SimGear.vcproj index 69799c1e..596e6476 100755 --- a/projects/VC7.1/SimGear.vcproj +++ b/projects/VC7.1/SimGear.vcproj @@ -386,6 +386,12 @@ + + + + + +#include + +using namespace simgear; + +osgDB::ReaderWriter::Options* simgear::makeOptionsFromPath(const SGPath& path) +{ + using namespace osgDB; + ReaderWriter::Options *options + = new ReaderWriter::Options(*(Registry::instance()->getOptions())); + options->setDatabasePath(path.str()); + return options; +} diff --git a/simgear/misc/PathOptions.hxx b/simgear/misc/PathOptions.hxx new file mode 100644 index 00000000..9b14d6e8 --- /dev/null +++ b/simgear/misc/PathOptions.hxx @@ -0,0 +1,30 @@ +// PathOptions.hxx -- make an osgDB Options object from a path +// Copyright (C) 2007 Tim Moore timoore@redhat.com +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#ifndef PATHOPTIONSHXX +#define PATHOPTIONSHXX 1 + +#include +#include + +namespace simgear +{ +osgDB::ReaderWriter::Options* makeOptionsFromPath(const SGPath&); +} +#endif diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index fdccd511..94da1b5c 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -324,7 +324,7 @@ void SGMaterial::assignTexture( osg::StateSet *state, const std::string &fname, _tex_cache_iter = _tex_cache.find(fname); if (_tex_cache_iter == _tex_cache.end()) { - osg::Texture2D* texture = SGLoadTexture2D(fname, _wrapu, _wrapv, + osg::Texture2D* texture = SGLoadTexture2D(fname, 0, _wrapu, _wrapv, mipmap ? -1 : 0); texture->setMaxAnisotropy( SGGetTextureFilter()); state->setTextureAttributeAndModes(0, texture); diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index ab9e03ac..b2dfa1b6 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -18,6 +18,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ModelRegistry.hxx" +#include + #include #include #include @@ -202,11 +204,12 @@ ReaderWriter::ReadResult ModelRegistry::readImage(const string& fileName, const ReaderWriter::Options* opt) { + OpenThreads::ScopedLock lock(readerMutex); CallbackMap::iterator iter = imageCallbackMap.find(getFileExtension(fileName)); if (iter != imageCallbackMap.end() && iter->second.valid()) return iter->second->readImage(fileName, opt); - string absFileName = findDataFile(fileName); + string absFileName = findDataFile(fileName, opt); if (!fileExists(absFileName)) { SG_LOG(SG_IO, SG_ALERT, "Cannot find image file \"" << fileName << "\""); @@ -309,7 +312,7 @@ osg::Node* DefaultCopyPolicy::copy(osg::Node* model, const string& fileName, res->addObserver(databaseReference); // Update liveries - SGTextureUpdateVisitor liveryUpdate(getDataFilePathList()); + SGTextureUpdateVisitor liveryUpdate(opt->getDatabasePathList()); res->accept(liveryUpdate); return res; } @@ -319,7 +322,7 @@ string OSGSubstitutePolicy::substitute(const string& name, { string fileSansExtension = getNameLessExtension(name); string osgFileName = fileSansExtension + ".osg"; - string absFileName = findDataFile(osgFileName); + string absFileName = findDataFile(osgFileName, opt); return absFileName; } @@ -356,6 +359,7 @@ ReaderWriter::ReadResult ModelRegistry::readNode(const string& fileName, const ReaderWriter::Options* opt) { + OpenThreads::ScopedLock lock(readerMutex); Registry* registry = Registry::instance(); ReaderWriter::ReadResult res; Node* cached = 0; @@ -437,18 +441,3 @@ namespace { ModelRegistryCallbackProxy g_acRegister("ac"); } - - -ReaderWriter::ReadResult -OSGFileCallback::readImage(const string& fileName, - const ReaderWriter::Options* opt) -{ - return Registry::instance()->readImageImplementation(fileName, opt); -} - -ReaderWriter::ReadResult -OSGFileCallback::readNode(const string& fileName, - const ReaderWriter::Options* opt) -{ - return Registry::instance()->readNodeImplementation(fileName, opt); -} diff --git a/simgear/scene/model/ModelRegistry.hxx b/simgear/scene/model/ModelRegistry.hxx index 2c010297..e1429268 100644 --- a/simgear/scene/model/ModelRegistry.hxx +++ b/simgear/scene/model/ModelRegistry.hxx @@ -19,6 +19,8 @@ #ifndef _SG_MODELREGISTRY_HXX #define _SG_MODELREGISTRY_HXX 1 +#include + #include #include #include @@ -225,6 +227,9 @@ protected: CallbackMap imageCallbackMap; CallbackMap nodeCallbackMap; osg::ref_ptr _defaultCallback; + // Protect against simultaneous calls from main thread (MP models) + // and pager thread. + OpenThreads::ReentrantMutex readerMutex; }; // Callback that only loads the file without any caching or @@ -245,19 +250,5 @@ public: ->addNodeCallbackForExtension(extension, new T(extension)); } }; - -// Callback for file extensions that load files using the default OSG -// implementation. - -class OSGFileCallback : public osgDB::Registry::ReadFileCallback { -public: - virtual osgDB::ReaderWriter::ReadResult - readImage(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); - virtual osgDB::ReaderWriter::ReadResult - readNode(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); -}; - } #endif // _SG_MODELREGISTRY_HXX diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index ba4bb75e..d32308c2 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -501,7 +501,8 @@ SGAnimation::~SGAnimation() bool SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode, - SGPropertyNode* modelRoot) + SGPropertyNode* modelRoot, + const osgDB::ReaderWriter::Options* options) { std::string type = configNode->getStringValue("type", "none"); if (type == "alpha-test") { @@ -541,7 +542,7 @@ SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode, SGSelectAnimation animInst(configNode, modelRoot); animInst.apply(node); } else if (type == "shader") { - SGShaderAnimation animInst(configNode, modelRoot); + SGShaderAnimation animInst(configNode, modelRoot, options); animInst.apply(node); } else if (type == "textranslate" || type == "texrotate" || type == "texmultiple") { diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 4f3007df..61901e9b 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -74,7 +75,8 @@ public: virtual ~SGAnimation(); static bool animate(osg::Node* node, const SGPropertyNode* configNode, - SGPropertyNode* modelRoot); + SGPropertyNode* modelRoot, + const osgDB::ReaderWriter::Options* options); protected: void apply(osg::Node* node); @@ -352,7 +354,8 @@ private: class SGShaderAnimation : public SGAnimation { public: SGShaderAnimation(const SGPropertyNode* configNode, - SGPropertyNode* modelRoot); + SGPropertyNode* modelRoot, + const osgDB::ReaderWriter::Options* options); virtual osg::Group* createAnimationGroup(osg::Group& parent); private: class UpdateCallback; diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 4c49fd35..76d5a90f 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -37,9 +37,15 @@ SG_USING_STD(vector); osg::Texture2D* -SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int) +SGLoadTexture2D(const std::string& path, + const osgDB::ReaderWriter::Options* options, + bool wrapu, bool wrapv, int) { - osg::Image* image = osgDB::readImageFile(path); + osg::Image* image; + if (options) + image = osgDB::readImageFile(path, options); + else + image = osgDB::readImageFile(path); osg::ref_ptr texture = new osg::Texture2D; texture->setImage(image); texture->setDataVariance(osg::Object::STATIC); @@ -148,25 +154,26 @@ sgLoad3DModel( const string &fg_root, const string &path, } } - osgDB::FilePathList pathList = osgDB::getDataFilePathList(); - osgDB::Registry::instance()->initFilePathLists(); + osg::ref_ptr options + = new osgDB::ReaderWriter::Options(*osgDB::Registry::instance() + ->getOptions()); // Assume that textures are in // the same location as the XML file. if (!model) { - if (texturepath.extension() != "") + if (texturepath.extension() != "") texturepath = texturepath.dir(); - osgDB::Registry::instance()->getDataFilePathList().push_front(texturepath.str()); + options->setDatabasePath(texturepath.str()); + if (!externalTexturePath.str().empty()) + options->getDatabasePathList().push_back(externalTexturePath.str()); - model = osgDB::readNodeFile(modelpath.str()); - if (model == 0) - throw sg_io_exception("Failed to load 3D model", - sg_location(modelpath.str())); + model = osgDB::readNodeFile(modelpath.str(), options.get()); + if (model == 0) + throw sg_io_exception("Failed to load 3D model", + sg_location(modelpath.str())); } - osgDB::Registry::instance()->getDataFilePathList().push_front(externalTexturePath.str()); - // Set up the alignment node osg::ref_ptr alignmainmodel = new osg::MatrixTransform; alignmainmodel->addChild(model.get()); @@ -251,10 +258,8 @@ sgLoad3DModel( const string &fg_root, const string &path, animation_nodes = props.getChildren("animation"); for (unsigned i = 0; i < animation_nodes.size(); ++i) /// OSGFIXME: duh, why not only model????? - SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root); - - // restore old path list - osgDB::setDataFilePathList(pathList); + SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root, + options.get()); if (props.hasChild("debug-outfile")) { std::string outputfile = props.getStringValue("debug-outfile", diff --git a/simgear/scene/model/model.hxx b/simgear/scene/model/model.hxx index 29306f05..2f2b01af 100644 --- a/simgear/scene/model/model.hxx +++ b/simgear/scene/model/model.hxx @@ -20,6 +20,7 @@ SG_USING_STD(set); #include #include +#include #include #include @@ -82,14 +83,17 @@ sgMakeAnimation( osg::Node* model, osg::Texture2D* -SGLoadTexture2D(const std::string& path, bool wrapu = true, - bool wrapv = true, int mipmaplevels = -1); +SGLoadTexture2D(const std::string& path, + const osgDB::ReaderWriter::Options* options = 0, + bool wrapu = true, bool wrapv = true, int mipmaplevels = -1); inline osg::Texture2D* -SGLoadTexture2D(const SGPath& path, bool wrapu = true, bool wrapv = true, +SGLoadTexture2D(const SGPath& path, + const osgDB::ReaderWriter::Options* options = 0, + bool wrapu = true, bool wrapv = true, int mipmaplevels = -1) { - return SGLoadTexture2D(path.str(), wrapu, wrapv, mipmaplevels); + return SGLoadTexture2D(path.str(), options, wrapu, wrapv, mipmaplevels); } #endif // __MODEL_HXX diff --git a/simgear/scene/model/shadanim.cxx b/simgear/scene/model/shadanim.cxx index ec1403b1..f9b747e1 100644 --- a/simgear/scene/model/shadanim.cxx +++ b/simgear/scene/model/shadanim.cxx @@ -178,12 +178,14 @@ static void create_specular_highlights(osg::Node *node) SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode, - SGPropertyNode* modelRoot) : + SGPropertyNode* modelRoot, + const osgDB::ReaderWriter::Options* + options) : SGAnimation(configNode, modelRoot) { const SGPropertyNode* node = configNode->getChild("texture"); if (node) - _effect_texture = SGLoadTexture2D(node->getStringValue()); + _effect_texture = SGLoadTexture2D(node->getStringValue(), options); } namespace { diff --git a/simgear/scene/sky/cloud.cxx b/simgear/scene/sky/cloud.cxx index 5ff1b089..34361cd9 100644 --- a/simgear/scene/sky/cloud.cxx +++ b/simgear/scene/sky/cloud.cxx @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include "cloudfield.hxx" #include "cloud.hxx" +using namespace simgear; // #if defined(__MINGW32__) // #define isnan(x) _isnan(x) // #endif @@ -81,9 +83,10 @@ SGMakeState(const SGPath &path, const char* colorTexture, { osg::StateSet *stateSet = new osg::StateSet; - SGPath colorPath(path); - colorPath.append(colorTexture); - stateSet->setTextureAttribute(0, SGLoadTexture2D(colorPath)); + osg::ref_ptr options + = makeOptionsFromPath(path); + stateSet->setTextureAttribute(0, SGLoadTexture2D(colorTexture, + options.get())); stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); osg::TexEnv* texEnv = new osg::TexEnv; diff --git a/simgear/scene/sky/moon.cxx b/simgear/scene/sky/moon.cxx index 464b5a0f..211d96ca 100644 --- a/simgear/scene/sky/moon.cxx +++ b/simgear/scene/sky/moon.cxx @@ -46,10 +46,13 @@ #include #include #include +#include #include "sphere.hxx" #include "moon.hxx" +using namespace simgear; + // Constructor SGMoon::SGMoon( void ) : prev_moon_angle(-1) @@ -71,9 +74,10 @@ SGMoon::build( SGPath path, double moon_size ) { stateSet->setRenderBinDetails(-5, "RenderBin"); // set up the orb state - path.append( "moon.rgba" ); + osg::ref_ptr options + = makeOptionsFromPath(path); - osg::Texture2D* texture = SGLoadTexture2D(path); + osg::Texture2D* texture = SGLoadTexture2D("moon.rgba", options.get()); stateSet->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); osg::TexEnv* texEnv = new osg::TexEnv; texEnv->setMode(osg::TexEnv::MODULATE); diff --git a/simgear/scene/sky/oursun.cxx b/simgear/scene/sky/oursun.cxx index e2b5a59d..8a2cd6bd 100644 --- a/simgear/scene/sky/oursun.cxx +++ b/simgear/scene/sky/oursun.cxx @@ -41,10 +41,13 @@ #include #include +#include #include #include #include "oursun.hxx" +using namespace simgear; + // Constructor SGSun::SGSun( void ) { prev_sun_angle = -9999.0; @@ -63,8 +66,8 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) env_node = property_tree_Node; - SGPath ihalopath = path, ohalopath = path; - + osg::ref_ptr options + = makeOptionsFromPath(path); // build the ssg scene graph sub tree for the sky and connected // into the provide scene graph branch sun_transform = new osg::MatrixTransform; @@ -100,15 +103,13 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); - osg::Geode* geode = new osg::Geode; stateSet = geode->getOrCreateStateSet(); stateSet->setRenderBinDetails(-6, "RenderBin"); // set up the sun-state - path.append( "sun.rgba" ); - osg::Texture2D* texture = SGLoadTexture2D(path); + osg::Texture2D* texture = SGLoadTexture2D("sun.rgba", options.get()); stateSet->setTextureAttributeAndModes(0, texture); // Build scenegraph @@ -139,14 +140,12 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) sun_transform->addChild( geode ); - // set up the inner-halo state geode = new osg::Geode; stateSet = geode->getOrCreateStateSet(); stateSet->setRenderBinDetails(-7, "RenderBin"); - ihalopath.append( "inner_halo.rgba" ); - texture = SGLoadTexture2D(ihalopath); + texture = SGLoadTexture2D("inner_halo.rgba", options.get()); stateSet->setTextureAttributeAndModes(0, texture); // Build ssg structure @@ -177,7 +176,6 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) geode->addDrawable(geometry); sun_transform->addChild( geode ); - // set up the outer halo state @@ -185,8 +183,7 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) stateSet = geode->getOrCreateStateSet(); stateSet->setRenderBinDetails(-8, "RenderBin"); - ohalopath.append( "outer_halo.rgba" ); - texture = SGLoadTexture2D(ohalopath); + texture = SGLoadTexture2D("outer_halo.rgba", options.get()); stateSet->setTextureAttributeAndModes(0, texture); // Build ssg structure -- 2.39.5