diff --git a/include/osg/Camera b/include/osg/Camera index b2b2774ef..b1d5b538f 100644 --- a/include/osg/Camera +++ b/include/osg/Camera @@ -399,6 +399,96 @@ class OSG_EXPORT Camera : public Transform, public CullSettings const BufferAttachmentMap& getBufferAttachmentMap() const { return _bufferAttachmentMap; } + /** Explicit control over implicit allocation of buffers when using FBO. + Implicit buffers are automatically substituted when user have not attached such buffer. + + Camera may set up two FBOs: primary Render FBO and secondary Resolve FBO for multisample usage. + So in practive we have two masks defined for the Camera: + implicitBufferAttachmentRenderMask + implicitBufferAttachmentResolveMask + They can be set together by setImplicitBufferAttachmentMask method, or separately + by setImplicitBufferAttachmentRenderMask and setImplicitBufferAttachmentResolveMask. + + Camera defaults are USE_DISPLAY_SETTINGS_MASK which means that by default + Camera chooses to substitue buffer attachments as defined by DisplaySettings. + + Usually DisplaySettings implicit buffer attachment selection defaults to: DEPTH and COLOR + for both primary (Render) FBO and seconday Multisample (Resolve) FBO + ie: IMPLICT_DEPTH_BUFFER_ATTACHMENT | IMPLICIT_COLOR_BUFFER_ATTACHMENT + + If these masks are not changed and user did not attach depth buffer and/or color buffer + to Camera, then OSG implicitly substitues these buffers. + By default it does not implicitly allocate a stencil buffer. + Use implicti buffer attachment masks to override default behavior: + to turn off DEPTH or COLOR buffer substitution or to enforce STENCIL buffer substitution. + + Note that both values are ignored if not using FBO. + Note that the second mask value is ignored if not using MSFBO. + */ + enum ImplicitBufferAttachment + { + IMPLICIT_DEPTH_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_DEPTH_BUFFER_ATTACHMENT, + IMPLICIT_STENCIL_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_STENCIL_BUFFER_ATTACHMENT, + IMPLICIT_COLOR_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT, + USE_DISPLAY_SETTINGS_MASK = (~0) + }; + + typedef int ImplicitBufferAttachmentMask; + + void setImplicitBufferAttachmentMask(ImplicitBufferAttachmentMask renderMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT, ImplicitBufferAttachmentMask resolveMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT) + { + _implicitBufferAttachmentRenderMask = renderMask; + _implicitBufferAttachmentResolveMask = resolveMask; + } + + void setImplicitBufferAttachmentRenderMask(ImplicitBufferAttachmentMask implicitBufferAttachmentRenderMask) + { + _implicitBufferAttachmentRenderMask = implicitBufferAttachmentRenderMask; + } + + void setImplicitBufferAttachmentResolveMask(ImplicitBufferAttachmentMask implicitBufferAttachmentResolveMask) + { + _implicitBufferAttachmentResolveMask = implicitBufferAttachmentResolveMask; + } + + /** + Get mask selecting implict buffer attachments for Camera primary FBO + if effectiveMask parameter is set, method follows USE_DISPLAY_SETTINGS_MASK dependence and returns effective mask + if effectiveMask parameter is reset, method returns nominal mask set by the Camera + */ + ImplicitBufferAttachmentMask getImplicitBufferAttachmentRenderMask(bool effectiveMask = false) const + { + if( effectiveMask && _implicitBufferAttachmentRenderMask == USE_DISPLAY_SETTINGS_MASK ) + { + const DisplaySettings * ds = getDisplaySettings(); + if ( !ds ) ds = DisplaySettings::instance(); + return ds->getImplicitBufferAttachmentRenderMask(); + } + else + { + return _implicitBufferAttachmentRenderMask; + } + } + + /** + Get mask selecting implict buffer attachments for Camera secondary MULTISAMPLE FBO + if effectiveMask parameter is set, method follows USE_DISPLAY_SETTINGS_MASK dependence and returns effective mask + if effectiveMask parameter is reset, method returns nominal mask set by the Camera + */ + ImplicitBufferAttachmentMask getImplicitBufferAttachmentResolveMask(bool effectiveMask = false) const + { + if( effectiveMask && _implicitBufferAttachmentResolveMask == USE_DISPLAY_SETTINGS_MASK ) + { + const DisplaySettings * ds = getDisplaySettings(); + if ( !ds ) ds = DisplaySettings::instance(); + return ds->getImplicitBufferAttachmentRenderMask(); + } + else + { + return _implicitBufferAttachmentResolveMask; + } + } + /** Create a operation thread for this camera.*/ void createCameraThread(); @@ -559,6 +649,8 @@ class OSG_EXPORT Camera : public Transform, public CullSettings RenderTargetImplementation _renderTargetImplementation; RenderTargetImplementation _renderTargetFallback; BufferAttachmentMap _bufferAttachmentMap; + ImplicitBufferAttachmentMask _implicitBufferAttachmentRenderMask; + ImplicitBufferAttachmentMask _implicitBufferAttachmentResolveMask; ref_ptr _cameraThread; diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index dac274249..3a1a6cafe 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -206,6 +206,47 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced void setMaxBufferObjectPoolSize(unsigned int size) { _maxBufferObjectPoolSize = size; } unsigned int getMaxBufferObjectPoolSize() const { return _maxBufferObjectPoolSize; } + /** + Methods used to set and get defaults for Cameras implicit buffer attachments. + For more info: See description of Camera::setImplicitBufferAttachment method + + DisplaySettings implicit buffer attachment selection defaults to: DEPTH and COLOR + for both primary (Render) FBO and seconday Multisample (Resolve) FBO + ie: IMPLICT_DEPTH_BUFFER_ATTACHMENT | IMPLICIT_COLOR_BUFFER_ATTACHMENT + **/ + enum ImplicitBufferAttachment + { + IMPLICIT_DEPTH_BUFFER_ATTACHMENT = (1 << 0), + IMPLICIT_STENCIL_BUFFER_ATTACHMENT = (1 << 1), + IMPLICIT_COLOR_BUFFER_ATTACHMENT = (1 << 2), + DEFAULT_IMPLICIT_BUFFER_ATTACHMENT = IMPLICIT_COLOR_BUFFER_ATTACHMENT | IMPLICIT_DEPTH_BUFFER_ATTACHMENT + }; + + typedef int ImplicitBufferAttachmentMask; + + void setImplicitBufferAttachmentMask(ImplicitBufferAttachmentMask renderMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT, ImplicitBufferAttachmentMask resolveMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT ) + { + _implicitBufferAttachmentRenderMask = renderMask; + _implicitBufferAttachmentResolveMask = resolveMask; + } + + void setImplicitBufferAttachmentRenderMask(ImplicitBufferAttachmentMask implicitBufferAttachmentRenderMask) + { + _implicitBufferAttachmentRenderMask = implicitBufferAttachmentRenderMask; + } + + void setImplicitBufferAttachmentResolveMask(ImplicitBufferAttachmentMask implicitBufferAttachmentResolveMask) + { + _implicitBufferAttachmentResolveMask = implicitBufferAttachmentResolveMask; + } + + /** Get mask selecting default implict buffer attachments for Cameras primary FBOs. */ + ImplicitBufferAttachmentMask getImplicitBufferAttachmentRenderMask() const { return _implicitBufferAttachmentRenderMask; } + + /** Get mask selecting default implict buffer attachments for Cameras secondary MULTISAMPLE FBOs. */ + ImplicitBufferAttachmentMask getImplicitBufferAttachmentResolveMask() const { return _implicitBufferAttachmentResolveMask;} + + /** Set the hint of which OpenGL version to attempt to create a graphics context for.*/ void setGLContextVersion(const std::string& version) { _glContextVersion = version; } @@ -267,6 +308,9 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced unsigned int _maxTexturePoolSize; unsigned int _maxBufferObjectPoolSize; + + ImplicitBufferAttachmentMask _implicitBufferAttachmentRenderMask; + ImplicitBufferAttachmentMask _implicitBufferAttachmentResolveMask; std::string _glContextVersion; unsigned int _glContextFlags; diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp index 36f761d8a..487fb1256 100644 --- a/src/osg/Camera.cpp +++ b/src/osg/Camera.cpp @@ -31,7 +31,9 @@ Camera::Camera(): _drawBuffer(GL_NONE), _readBuffer(GL_NONE), _renderTargetImplementation(FRAME_BUFFER), - _renderTargetFallback(FRAME_BUFFER) + _renderTargetFallback(FRAME_BUFFER), + _implicitBufferAttachmentRenderMask( USE_DISPLAY_SETTINGS_MASK ), + _implicitBufferAttachmentResolveMask( USE_DISPLAY_SETTINGS_MASK ) { setStateSet(new StateSet); } @@ -60,6 +62,8 @@ Camera::Camera(const Camera& camera,const CopyOp& copyop): _renderTargetImplementation(camera._renderTargetImplementation), _renderTargetFallback(camera._renderTargetFallback), _bufferAttachmentMap(camera._bufferAttachmentMap), + _implicitBufferAttachmentRenderMask(camera._implicitBufferAttachmentRenderMask), + _implicitBufferAttachmentResolveMask(camera._implicitBufferAttachmentResolveMask), _initialDrawCallback(camera._initialDrawCallback), _preDrawCallback(camera._preDrawCallback), _postDrawCallback(camera._postDrawCallback), diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index 75d7f059e..31c10d7f1 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -84,6 +84,9 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs) _maxTexturePoolSize = vs._maxTexturePoolSize; _maxBufferObjectPoolSize = vs._maxBufferObjectPoolSize; + _implicitBufferAttachmentRenderMask = vs._implicitBufferAttachmentRenderMask; + _implicitBufferAttachmentResolveMask = vs._implicitBufferAttachmentResolveMask; + _glContextVersion = vs._glContextVersion; _glContextFlags = vs._glContextFlags; _glContextProfileMask = vs._glContextProfileMask; @@ -113,6 +116,10 @@ void DisplaySettings::merge(const DisplaySettings& vs) if (vs._maxTexturePoolSize>_maxTexturePoolSize) _maxTexturePoolSize = vs._maxTexturePoolSize; if (vs._maxBufferObjectPoolSize>_maxBufferObjectPoolSize) _maxBufferObjectPoolSize = vs._maxBufferObjectPoolSize; + + // these are bit masks so merging them is like logical or + _implicitBufferAttachmentRenderMask |= vs._implicitBufferAttachmentRenderMask; + _implicitBufferAttachmentResolveMask |= vs._implicitBufferAttachmentResolveMask; } void DisplaySettings::setDefaults() @@ -161,6 +168,8 @@ void DisplaySettings::setDefaults() _maxTexturePoolSize = 0; _maxBufferObjectPoolSize = 0; + _implicitBufferAttachmentRenderMask = DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + _implicitBufferAttachmentResolveMask = DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; _glContextVersion = "1.0"; _glContextFlags = 0; _glContextProfileMask = 0; @@ -206,9 +215,11 @@ static ApplicationUsageProxy DisplaySetting_e17(ApplicationUsage::ENVIRONMENTAL_ static ApplicationUsageProxy DisplaySetting_e18(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TEXTURE_POOL_SIZE ","Set the hint size of texture pool to manage."); static ApplicationUsageProxy DisplaySetting_e19(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUFFER_OBJECT_POOL_SIZE ","Set the hint size of vertex buffer object pool to manage."); static ApplicationUsageProxy DisplaySetting_e20(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FBO_POOL_SIZE ","Set the hint size of frame buffer object pool to manage."); -static ApplicationUsageProxy DisplaySetting_e21(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_VERSION ","Set the hint for the GL version to create contexts for."); -static ApplicationUsageProxy DisplaySetting_e22(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_FLAGS ","Set the hint for the GL context flags to use when creating contexts."); -static ApplicationUsageProxy DisplaySetting_e23(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_PROFILE_MASK ","Set the hint for the GL context profile mask to use when creating contexts."); +static ApplicationUsageProxy DisplaySetting_e21(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_IMPLICIT_BUFFER_ATTACHMENT_RENDER_MASK","OFF | DEFAULT | [~]COLOR | [~]DEPTH | [~]STENCIL. Substitute missing buffer attachments for render FBO"); +static ApplicationUsageProxy DisplaySetting_e22(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_IMPLICIT_BUFFER_ATTACHMENT_RESOLVE_MASK","OFF | DEFAULT | [~]COLOR | [~]DEPTH | [~]STENCIL. Substitute missing buffer attachments for resolve FBO"); +static ApplicationUsageProxy DisplaySetting_e23(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_VERSION ","Set the hint for the GL version to create contexts for."); +static ApplicationUsageProxy DisplaySetting_e24(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_FLAGS ","Set the hint for the GL context flags to use when creating contexts."); +static ApplicationUsageProxy DisplaySetting_e25(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_GL_CONTEXT_PROFILE_MASK ","Set the hint for the GL context profile mask to use when creating contexts."); void DisplaySettings::readEnvironmentalVariables() { @@ -416,6 +427,40 @@ void DisplaySettings::readEnvironmentalVariables() _maxBufferObjectPoolSize = atoi(ptr); } + + { // Read implicit buffer attachments combinations for both render and resolve mask + const char * variable[] = { + "OSG_IMPLICIT_BUFFER_ATTACHMENT_RENDER_MASK", + "OSG_IMPLICIT_BUFFER_ATTACHMENT_RESOLVE_MASK", + }; + + int * mask[] = { + &_implicitBufferAttachmentRenderMask, + &_implicitBufferAttachmentResolveMask, + }; + + for( unsigned int n = 0; n < sizeof( variable ) / sizeof( variable[0] ); n++ ) + { + const char* env = getenv( variable[n] ); + if ( !env ) continue; + std::string str(env); + + if(str.find("OFF")!=std::string::npos) *mask[n] = 0; + + if(str.find("~DEFAULT")!=std::string::npos) *mask[n] ^= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + else if(str.find("DEFAULT")!=std::string::npos) *mask[n] |= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + + if(str.find("~COLOR")!=std::string::npos) *mask[n] ^= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + else if(str.find("COLOR")!=std::string::npos) *mask[n] |= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + + if(str.find("~DEPTH")!=std::string::npos) *mask[n] ^= IMPLICIT_DEPTH_BUFFER_ATTACHMENT; + else if(str.find("DEPTH")!=std::string::npos) *mask[n] |= (int)IMPLICIT_DEPTH_BUFFER_ATTACHMENT; + + if(str.find("~STENCIL")!=std::string::npos) *mask[n] ^= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + else if(str.find("STENCIL")!=std::string::npos) *mask[n] |= (int)IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + } + } + if( (ptr = getenv("OSG_GL_VERSION")) != 0 || (ptr = getenv("OSG_GL_CONTEXT_VERSION")) != 0) { _glContextVersion = ptr; @@ -449,6 +494,8 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) arguments.getApplicationUsage()->addCommandLineOption("--samples ","Request a multisample visual"); arguments.getApplicationUsage()->addCommandLineOption("--cc","Request use of compile contexts and threads"); arguments.getApplicationUsage()->addCommandLineOption("--serialize-draw ","OFF | ON - set the serialization of draw dispatch"); + arguments.getApplicationUsage()->addCommandLineOption("--implicit-buffer-attachment-render-mask","OFF | DEFAULT | [~]COLOR | [~]DEPTH | [~]STENCIL. Substitute missing buffer attachments for render FBO"); + arguments.getApplicationUsage()->addCommandLineOption("--implicit-buffer-attachment-resolve-mask","OFF | DEFAULT | [~]COLOR | [~]DEPTH | [~]STENCIL. Substitute missing buffer attachments for resolve FBO"); arguments.getApplicationUsage()->addCommandLineOption("--gl-version ","Set the hint of which GL version to use when creating graphics contexts."); arguments.getApplicationUsage()->addCommandLineOption("--gl-flags ","Set the hint of which GL flags projfile mask to use when creating graphics contexts."); arguments.getApplicationUsage()->addCommandLineOption("--gl-profile-mask ","Set the hint of which GL context profile mask to use when creating graphics contexts."); @@ -523,6 +570,38 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) while(arguments.read("--texture-pool-size",_maxTexturePoolSize)) {} while(arguments.read("--buffer-object-pool-size",_maxBufferObjectPoolSize)) {} + { // Read implicit buffer attachments combinations for both render and resolve mask + const char* option[] = { + "--implicit-buffer-attachment-render-mask", + "--implicit-buffer-attachment-resolve-mask", + }; + + int * mask[] = { + &_implicitBufferAttachmentRenderMask, + &_implicitBufferAttachmentResolveMask, + }; + + for( unsigned int n = 0; n < sizeof( option ) / sizeof( option[0]); n++ ) + { + while(arguments.read( option[n],str)) + { + if(str.find("OFF")!=std::string::npos) *mask[n] = 0; + + if(str.find("~DEFAULT")!=std::string::npos) *mask[n] ^= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + else if(str.find("DEFAULT")!=std::string::npos) *mask[n] |= DEFAULT_IMPLICIT_BUFFER_ATTACHMENT; + + if(str.find("~COLOR")!=std::string::npos) *mask[n] ^= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + else if(str.find("COLOR")!=std::string::npos) *mask[n] |= IMPLICIT_COLOR_BUFFER_ATTACHMENT; + + if(str.find("~DEPTH")!=std::string::npos) *mask[n] ^= IMPLICIT_DEPTH_BUFFER_ATTACHMENT; + else if(str.find("DEPTH")!=std::string::npos) *mask[n] |= IMPLICIT_DEPTH_BUFFER_ATTACHMENT; + + if(str.find("~STENCIL")!=std::string::npos) *mask[n] ^= IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + else if(str.find("STENCIL")!=std::string::npos) *mask[n] |= IMPLICIT_STENCIL_BUFFER_ATTACHMENT; + } + } + } + while (arguments.read("--gl-version", _glContextVersion)) {} while (arguments.read("--gl-flags", _glContextFlags)) {} while (arguments.read("--gl-profile-mask", _glContextProfileMask)) {}