Merge branch 'dev-7019' into 'master'

Fix improper access of stereo manager by other shared components

See merge request OpenMW/openmw!2437
revert-6246b479
psi29a 2 years ago
commit 2686e586e5

@ -145,20 +145,6 @@ namespace
private:
int mMaxTextureImageUnits = 0;
};
class InitializeStereoOperation final : public osg::GraphicsOperation
{
public:
InitializeStereoOperation()
: GraphicsOperation("InitializeStereoOperation", false)
{
}
void operator()(osg::GraphicsContext* graphicsContext) override
{
Stereo::Manager::instance().initializeStereo(graphicsContext);
}
};
}
void OMW::Engine::executeLocalScripts()
@ -609,10 +595,7 @@ void OMW::Engine::createWindow()
realizeOperations->add(mSelectColorFormatOperation);
if (Stereo::getStereo())
{
realizeOperations->add(new InitializeStereoOperation());
Stereo::setVertexBufferHint();
}
realizeOperations->add(new Stereo::InitializeStereoOperation());
mViewer->realize();
mGlMaxTextureImageUnits = identifyOp->getMaxTextureImageUnits();
@ -651,7 +634,9 @@ void OMW::Engine::prepareEngine()
mStateManager = std::make_unique<MWState::StateManager>(mCfgMgr.getUserDataPath() / "saves", mContentFiles);
mEnvironment.setStateManager(*mStateManager);
mStereoManager = std::make_unique<Stereo::Manager>(mViewer);
bool stereoEnabled
= Settings::Manager::getBool("stereo enabled", "Stereo") || osg::DisplaySettings::instance().get()->getStereo();
mStereoManager = std::make_unique<Stereo::Manager>(mViewer, stereoEnabled);
osg::ref_ptr<osg::Group> rootNode(new osg::Group);
mViewer->setSceneData(rootNode);

@ -30,7 +30,7 @@ namespace MWRender
mLuminanceCalculator.disable();
Shader::ShaderManager::DefineMap defines;
Stereo::Manager::instance().shaderStereoDefines(defines);
Stereo::shaderStereoDefines(defines);
mFallbackProgram = shaderManager.getProgram("fullscreen_tri");

@ -365,7 +365,7 @@ namespace MWRender
if (mSceneManager->getForceShaders())
{
Shader::ShaderManager::DefineMap defines = {};
Stereo::Manager::instance().shaderStereoDefines(defines);
Stereo::shaderStereoDefines(defines);
auto program = mSceneManager->getShaderManager().getProgram("sky", defines);
mEarlyRenderBinRoot->getOrCreateStateSet()->addUniform(new osg::Uniform("pass", -1));
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(

@ -33,7 +33,7 @@ namespace MWRender
mStateSet->setTextureAttributeAndModes(0, dummyTexture);
Shader::ShaderManager::DefineMap defines;
Stereo::Manager::instance().shaderStereoDefines(defines);
Stereo::shaderStereoDefines(defines);
mStateSet->setAttributeAndModes(new osg::BlendFunc, modeOff);
mStateSet->setAttributeAndModes(shaderManager.getProgram("depthclipped", defines), modeOn);

@ -695,7 +695,7 @@ namespace MWRender
defineMap["ripple_map_world_scale"] = std::to_string(RipplesSurface::mWorldScaleFactor);
defineMap["ripple_map_size"] = std::to_string(RipplesSurface::mRTTSize) + ".0";
Stereo::Manager::instance().shaderStereoDefines(defineMap);
Stereo::shaderStereoDefines(defineMap);
Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager();
osg::ref_ptr<osg::Program> program = shaderMgr.getProgram("water", defineMap);

@ -54,11 +54,14 @@ namespace SceneUtil
if (frameNumber > vdd->mFrameNumber)
{
apply(vdd->mCamera);
auto& sm = Stereo::Manager::instance();
if (sm.getEye(cv) == Stereo::Eye::Left)
applyLeft(vdd->mCamera);
if (sm.getEye(cv) == Stereo::Eye::Right)
applyRight(vdd->mCamera);
if (Stereo::getStereo())
{
auto& sm = Stereo::Manager::instance();
if (sm.getEye(cv) == Stereo::Eye::Left)
applyLeft(vdd->mCamera);
if (sm.getEye(cv) == Stereo::Eye::Right)
applyRight(vdd->mCamera);
}
vdd->mCamera->accept(*cv);
}
vdd->mFrameNumber = frameNumber;

@ -115,7 +115,9 @@ namespace SceneUtil
, mIndoorShadowCastingMask(indoorShadowCastingMask)
{
mShadowedScene->setShadowTechnique(mShadowTechnique);
Stereo::Manager::instance().setShadowTechnique(mShadowTechnique);
if (Stereo::getStereo())
Stereo::Manager::instance().setShadowTechnique(mShadowTechnique);
mShadowedScene->addChild(sceneRoot);
rootNode->addChild(mShadowedScene);
@ -132,7 +134,8 @@ namespace SceneUtil
ShadowManager::~ShadowManager()
{
Stereo::Manager::instance().setShadowTechnique(nullptr);
if (Stereo::getStereo())
Stereo::Manager::instance().setShadowTechnique(nullptr);
}
Shader::ShaderManager::DefineMap ShadowManager::getShadowDefines()

@ -42,12 +42,13 @@ namespace SceneUtil
{
auto stateset = getCvDependentStateset(cv);
apply(stateset, cv);
auto* sm = &Stereo::Manager::instance();
if (sm != nullptr)
if (Stereo::getStereo())
{
if (sm->getEye(cv) == Stereo::Eye::Left)
auto& sm = Stereo::Manager::instance();
if (sm.getEye(cv) == Stereo::Eye::Left)
applyLeft(stateset, cv);
if (sm->getEye(cv) == Stereo::Eye::Right)
if (sm.getEye(cv) == Stereo::Eye::Right)
applyRight(stateset, cv);
}

@ -711,7 +711,7 @@ namespace Shader
defineMap["softParticles"] = reqs.mSoftParticles ? "1" : "0";
Stereo::Manager::instance().shaderStereoDefines(defineMap);
Stereo::shaderStereoDefines(defineMap);
std::string shaderPrefix;
if (!node.getUserValue("shaderPrefix", shaderPrefix))

@ -74,12 +74,6 @@ namespace Stereo
return false;
}
if (!Settings::Manager::getBool("multiview", "Stereo"))
{
Log(Debug::Verbose) << "Disabling Multiview (disabled by config)";
return false;
}
if (!getMultiviewSupported(contextID))
{
return false;
@ -95,6 +89,8 @@ namespace Stereo
return true;
}
static bool sMultiview = false;
bool getMultiview(unsigned int contextID)
{
static bool multiView = getMultiviewImpl(contextID);
@ -112,16 +108,25 @@ namespace Stereo
return getMultiview(0);
}
void configureExtensions(unsigned int contextID)
void configureExtensions(unsigned int contextID, bool enableMultiview)
{
getTextureViewSupported(contextID);
getMultiviewSupported(contextID);
getMultiview(contextID);
if (enableMultiview)
{
sMultiview = getMultiview(contextID);
}
else
{
Log(Debug::Verbose) << "Disabling Multiview (disabled by config)";
sMultiview = false;
}
}
void setVertexBufferHint()
void setVertexBufferHint(bool enableMultiview)
{
if (getStereo() && Settings::Manager::getBool("multiview", "Stereo"))
if (getStereo() && enableMultiview)
{
auto* ds = osg::DisplaySettings::instance().get();
if (!Settings::Manager::getBool("allow display lists for multiview", "Stereo")

@ -34,10 +34,10 @@ namespace Stereo
//! Use the provided context to check what extensions are supported and configure use of multiview based on
//! extensions and settings.
void configureExtensions(unsigned int contextID);
void configureExtensions(unsigned int contextID, bool enableMultiview);
//! Sets the appropriate vertex buffer hint on OSG's display settings if needed
void setVertexBufferHint();
void setVertexBufferHint(bool enableMultiview);
//! Creates a Texture2D as a texture view into a Texture2DArray
osg::ref_ptr<osg::Texture2D> createTextureView_Texture2DFromTexture2DArray(

@ -105,6 +105,8 @@ namespace Stereo
Manager* mManager;
};
static bool sStereoEnabled = false;
static Manager* sInstance = nullptr;
Manager& Manager::instance()
@ -112,19 +114,7 @@ namespace Stereo
return *sInstance;
}
struct CustomViewCallback : public Manager::UpdateViewCallback
{
public:
CustomViewCallback();
void updateView(View& left, View& right) override;
private:
View mLeft;
View mRight;
};
Manager::Manager(osgViewer::Viewer* viewer)
Manager::Manager(osgViewer::Viewer* viewer, bool enableStereo)
: mViewer(viewer)
, mMainCamera(mViewer->getCamera())
, mUpdateCallback(new StereoUpdateCallback(this))
@ -137,29 +127,19 @@ namespace Stereo
if (sInstance)
throw std::logic_error("Double instance of Stereo::Manager");
sInstance = this;
if (Settings::Manager::getBool("use custom view", "Stereo"))
mUpdateViewCallback = std::make_shared<CustomViewCallback>();
if (Settings::Manager::getBool("use custom eye resolution", "Stereo"))
{
osg::Vec2i eyeResolution = osg::Vec2i();
eyeResolution.x() = Settings::Manager::getInt("eye resolution x", "Stereo View");
eyeResolution.y() = Settings::Manager::getInt("eye resolution y", "Stereo View");
overrideEyeResolution(eyeResolution);
}
sStereoEnabled = enableStereo;
}
Manager::~Manager() {}
void Manager::initializeStereo(osg::GraphicsContext* gc)
void Manager::initializeStereo(osg::GraphicsContext* gc, bool enableMultiview)
{
auto ci = gc->getState()->getContextID();
configureExtensions(ci, enableMultiview);
mMainCamera->addUpdateCallback(mUpdateCallback);
mFrustumManager = std::make_unique<StereoFrustumManager>(mViewer->getCamera());
auto ci = gc->getState()->getContextID();
configureExtensions(ci);
if (getMultiview())
setupOVRMultiView2Technique();
else
@ -168,7 +148,7 @@ namespace Stereo
updateStereoFramebuffer();
}
void Manager::shaderStereoDefines(Shader::ShaderManager::DefineMap& defines) const
void shaderStereoDefines(Shader::ShaderManager::DefineMap& defines)
{
if (getMultiview())
{
@ -399,41 +379,75 @@ namespace Stereo
bool getStereo()
{
static bool stereo = Settings::Manager::getBool("stereo enabled", "Stereo")
|| osg::DisplaySettings::instance().get()->getStereo();
return stereo;
return sStereoEnabled;
}
CustomViewCallback::CustomViewCallback()
Manager::CustomViewCallback::CustomViewCallback(View left, View right)
: mLeft(left)
, mRight(right)
{
mLeft.pose.position.x() = Settings::Manager::getDouble("left eye offset x", "Stereo View");
mLeft.pose.position.y() = Settings::Manager::getDouble("left eye offset y", "Stereo View");
mLeft.pose.position.z() = Settings::Manager::getDouble("left eye offset z", "Stereo View");
mLeft.pose.orientation.x() = Settings::Manager::getDouble("left eye orientation x", "Stereo View");
mLeft.pose.orientation.y() = Settings::Manager::getDouble("left eye orientation y", "Stereo View");
mLeft.pose.orientation.z() = Settings::Manager::getDouble("left eye orientation z", "Stereo View");
mLeft.pose.orientation.w() = Settings::Manager::getDouble("left eye orientation w", "Stereo View");
mLeft.fov.angleLeft = Settings::Manager::getDouble("left eye fov left", "Stereo View");
mLeft.fov.angleRight = Settings::Manager::getDouble("left eye fov right", "Stereo View");
mLeft.fov.angleUp = Settings::Manager::getDouble("left eye fov up", "Stereo View");
mLeft.fov.angleDown = Settings::Manager::getDouble("left eye fov down", "Stereo View");
mRight.pose.position.x() = Settings::Manager::getDouble("right eye offset x", "Stereo View");
mRight.pose.position.y() = Settings::Manager::getDouble("right eye offset y", "Stereo View");
mRight.pose.position.z() = Settings::Manager::getDouble("right eye offset z", "Stereo View");
mRight.pose.orientation.x() = Settings::Manager::getDouble("right eye orientation x", "Stereo View");
mRight.pose.orientation.y() = Settings::Manager::getDouble("right eye orientation y", "Stereo View");
mRight.pose.orientation.z() = Settings::Manager::getDouble("right eye orientation z", "Stereo View");
mRight.pose.orientation.w() = Settings::Manager::getDouble("right eye orientation w", "Stereo View");
mRight.fov.angleLeft = Settings::Manager::getDouble("right eye fov left", "Stereo View");
mRight.fov.angleRight = Settings::Manager::getDouble("right eye fov right", "Stereo View");
mRight.fov.angleUp = Settings::Manager::getDouble("right eye fov up", "Stereo View");
mRight.fov.angleDown = Settings::Manager::getDouble("right eye fov down", "Stereo View");
}
void CustomViewCallback::updateView(View& left, View& right)
void Manager::CustomViewCallback::updateView(View& left, View& right)
{
left = mLeft;
right = mRight;
}
InitializeStereoOperation::InitializeStereoOperation()
: GraphicsOperation("InitializeStereoOperation", false)
{
// Ideally, this would have belonged to the operator(). But the vertex buffer
// hint has to be set before realize is called on the osg viewer, and so has to
// be done here instead.
Stereo::setVertexBufferHint(Settings::Manager::getBool("multiview", "Stereo"));
}
void InitializeStereoOperation::operator()(osg::GraphicsContext* graphicsContext)
{
auto& sm = Stereo::Manager::instance();
if (Settings::Manager::getBool("use custom view", "Stereo"))
{
Stereo::View left;
Stereo::View right;
left.pose.position.x() = Settings::Manager::getDouble("left eye offset x", "Stereo View");
left.pose.position.y() = Settings::Manager::getDouble("left eye offset y", "Stereo View");
left.pose.position.z() = Settings::Manager::getDouble("left eye offset z", "Stereo View");
left.pose.orientation.x() = Settings::Manager::getDouble("left eye orientation x", "Stereo View");
left.pose.orientation.y() = Settings::Manager::getDouble("left eye orientation y", "Stereo View");
left.pose.orientation.z() = Settings::Manager::getDouble("left eye orientation z", "Stereo View");
left.pose.orientation.w() = Settings::Manager::getDouble("left eye orientation w", "Stereo View");
left.fov.angleLeft = Settings::Manager::getDouble("left eye fov left", "Stereo View");
left.fov.angleRight = Settings::Manager::getDouble("left eye fov right", "Stereo View");
left.fov.angleUp = Settings::Manager::getDouble("left eye fov up", "Stereo View");
left.fov.angleDown = Settings::Manager::getDouble("left eye fov down", "Stereo View");
right.pose.position.x() = Settings::Manager::getDouble("right eye offset x", "Stereo View");
right.pose.position.y() = Settings::Manager::getDouble("right eye offset y", "Stereo View");
right.pose.position.z() = Settings::Manager::getDouble("right eye offset z", "Stereo View");
right.pose.orientation.x() = Settings::Manager::getDouble("right eye orientation x", "Stereo View");
right.pose.orientation.y() = Settings::Manager::getDouble("right eye orientation y", "Stereo View");
right.pose.orientation.z() = Settings::Manager::getDouble("right eye orientation z", "Stereo View");
right.pose.orientation.w() = Settings::Manager::getDouble("right eye orientation w", "Stereo View");
right.fov.angleLeft = Settings::Manager::getDouble("right eye fov left", "Stereo View");
right.fov.angleRight = Settings::Manager::getDouble("right eye fov right", "Stereo View");
right.fov.angleUp = Settings::Manager::getDouble("right eye fov up", "Stereo View");
right.fov.angleDown = Settings::Manager::getDouble("right eye fov down", "Stereo View");
auto customViewCallback = std::make_shared<Stereo::Manager::CustomViewCallback>(left, right);
sm.setUpdateViewCallback(customViewCallback);
}
if (Settings::Manager::getBool("use custom eye resolution", "Stereo"))
{
osg::Vec2i eyeResolution = osg::Vec2i();
eyeResolution.x() = Settings::Manager::getInt("eye resolution x", "Stereo View");
eyeResolution.y() = Settings::Manager::getInt("eye resolution y", "Stereo View");
sm.overrideEyeResolution(eyeResolution);
}
sm.initializeStereo(graphicsContext, Settings::Manager::getBool("multiview", "Stereo"));
}
}

@ -39,6 +39,9 @@ namespace Stereo
bool getStereo();
//! Sets up any definitions necessary for stereo rendering
void shaderStereoDefines(Shader::ShaderManager::DefineMap& defines);
//! Class that provides tools for managing stereo mode
class Manager
{
@ -51,16 +54,37 @@ namespace Stereo
virtual void updateView(View& left, View& right) = 0;
};
//! An UpdateViewCallback that supplies a fixed, custom view. Useful for debugging purposes,
//! such as emulating a given HMD's view.
struct CustomViewCallback : public UpdateViewCallback
{
public:
CustomViewCallback(View left, View right);
void updateView(View& left, View& right) override;
private:
View mLeft;
View mRight;
};
//! Gets the singleton instance
static Manager& instance();
Manager(osgViewer::Viewer* viewer);
//! Constructor
//!
//! @Param viewer the osg viewer whose stereo should be managed.
//! @Param enableStereo whether or not stereo should be enabled.
//! @Param enableMultiview whether or not to make use of the GL_OVR_Multiview extension, if supported.
Manager(osgViewer::Viewer* viewer, bool enableStereo);
~Manager();
//! Called during update traversal
void update();
void initializeStereo(osg::GraphicsContext* gc);
//! Initializes all details of stereo if applicable. If the constructor was called with enableMultiview=true,
//! and the GL_OVR_Multiview extension is supported, Stereo::getMultiview() will return true after this call.
void initializeStereo(osg::GraphicsContext* gc, bool enableMultiview);
//! Callback that updates stereo configuration during the update pass
void setUpdateViewCallback(std::shared_ptr<UpdateViewCallback> cb);
@ -71,9 +95,6 @@ namespace Stereo
osg::Matrixd computeEyeProjection(int view, bool reverseZ) const;
osg::Matrixd computeEyeViewOffset(int view) const;
//! Sets up any definitions necessary for stereo rendering
void shaderStereoDefines(Shader::ShaderManager::DefineMap& defines) const;
const std::shared_ptr<MultiviewFramebuffer>& multiviewFramebuffer() { return mMultiviewFramebuffer; }
//! Sets rendering resolution of each eye to eyeResolution.
@ -131,6 +152,15 @@ namespace Stereo
osg::ref_ptr<Identifier> mIdentifierLeft = new Identifier();
osg::ref_ptr<Identifier> mIdentifierRight = new Identifier();
};
//! Performs stereo-specific initialization operations.
class InitializeStereoOperation final : public osg::GraphicsOperation
{
public:
InitializeStereoOperation();
void operator()(osg::GraphicsContext* graphicsContext) override;
};
}
#endif

@ -283,7 +283,7 @@ namespace Terrain
defineMap["specularMap"] = it->mSpecular ? "1" : "0";
defineMap["parallax"] = (it->mNormalMap && it->mParallax) ? "1" : "0";
defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0";
Stereo::Manager::instance().shaderStereoDefines(defineMap);
Stereo::shaderStereoDefines(defineMap);
stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));
stateset->addUniform(UniformCollection::value().mColorMode);

Loading…
Cancel
Save