Skip to content
State 101 KiB
Newer Older
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSG_STATE
#define OSG_STATE 1

#include <osg/Export>
#include <osg/StateSet>
#include <osg/Matrix>
#include <osg/Uniform>
#include <osg/BufferObject>
#include <osg/Observer>
#include <osg/Timer>

#include <osg/ShaderComposer>
#include <osg/FrameStamp>
#include <osg/DisplaySettings>
#include <osg/Polytope>
#include <osg/Viewport>
#include <osg/GLBeginEndAdapter>
#include <osg/ArrayDispatchers>
#include <osg/GraphicsCostEstimator>

#include <iosfwd>
#include <vector>
#include <map>
#include <set>
#include <string>

#ifndef GL_FOG_COORDINATE_ARRAY
    #ifdef GL_FOG_COORDINATE_ARRAY_EXT
        #define GL_FOG_COORDINATE_ARRAY GL_FOG_COORDINATE_ARRAY_EXT
    #else
        #define GL_FOG_COORDINATE_ARRAY 0x8457
    #endif
#endif

#ifndef GL_SECONDARY_COLOR_ARRAY
    #ifdef GL_SECONDARY_COLOR_ARRAY_EXT
        #define GL_SECONDARY_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY_EXT
    #else
        #define GL_SECONDARY_COLOR_ARRAY 0x845E
    #endif
#endif

#if !defined(GL_EXT_timer_query) && !defined(OSG_GL3_AVAILABLE)
    #ifdef _WIN32
        typedef          __int64 GLint64EXT;
        typedef unsigned __int64 GLuint64EXT;
    #else
        typedef long long int GLint64EXT;
        typedef unsigned long long int GLuint64EXT;
    #endif
#endif

namespace osg {

/** macro for use with osg::StateAttribute::apply methods for detecting and
  * reporting OpenGL error messages.*/
#define OSG_GL_DEBUG(message) \
    if (state.getFineGrainedErrorDetection()) \
    { \
        GLenum errorNo = glGetError(); \
        if (errorNo!=GL_NO_ERROR) \
        { \
            osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<" "<<message<<endl; \
        }\
    }


// forward declare GraphicsContext, View and State
class GraphicsContext;

class VertexAttribAlias
{
    public:
        VertexAttribAlias():
            _location(0) {}

        VertexAttribAlias(const VertexAttribAlias& rhs):
            _location(rhs._location),
            _glName(rhs._glName),
            _osgName(rhs._osgName),
            _declaration(rhs._declaration) {}

        VertexAttribAlias(GLuint location, const std::string glName, const std::string osgName, const std::string& declaration):
            _location(location),
            _glName(glName),
            _osgName(osgName),
            _declaration(declaration) {}

        GLuint      _location;
        std::string _glName;
        std::string _osgName;
        std::string _declaration;
};


/** Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings,
  * implements lazy state updating and provides accessors for querying the current state.
  * The venerable Red Book says that "OpenGL is a state machine", and this class
  * represents the OpenGL state in OSG. Furthermore, \c State also has other
  * important features:
  * - It works as a stack of states (see \c pushStateSet() and
  *   \c popStateSet()). Manipulating this stack of OpenGL states manually is
  *   seldom needed, since OSG does this in the most common situations.
  * - It implements lazy state updating. This means that, if one requests a
  *   state change and that particular state is already in the requested state,
  *   no OpenGL call will be made. This ensures that the OpenGL pipeline is not
  *   stalled by unnecessary state changes.
  * - It allows to query the current OpenGL state without calls to \c glGet*(),
  *   which typically stall the graphics pipeline (see, for instance,
  *   \c captureCurrentState() and \c getModelViewMatrix()).
  */
class OSG_EXPORT State : public Referenced, public Observer
{
    public :

        State();


        /** Set the graphics context associated with that owns this State object.*/
        void setGraphicsContext(GraphicsContext* context) { _graphicsContext = context; }

        /** Get the graphics context associated with that owns this State object.*/
        GraphicsContext* getGraphicsContext() { return _graphicsContext; }

        /** Get the const graphics context associated with that owns this State object.*/
        const GraphicsContext* getGraphicsContext() const { return _graphicsContext; }


        /** Set the current OpenGL context uniqueID.
         *  The ContextID is used by classes like osg::StateAttribute's and osg::Drawable's to
         *  help manage seperate OpenGL objects, such as display lists, vertex buffer objects
         *  and texture object for each graphics context. The ContextID simply acts as an index 
         *  into arrays that these classes maintain for the purpose of storing GL object handles.
         * 
         *  Note, osgViewer::GraphicsWindow will automatically set up the ContextID for you,
         *  so you will rearely need to set this yourself.
         * 
         *  The exception is when creating your own graphics context, where you should set
         *  the ContextID uniquely for each graphics context.
         * 
         *  Typical settings for ContextID are 0,1,2,3... up to the maximum
         *  number of graphics contexts you have set up. By default contextID is 0.
         */
        inline void setContextID(unsigned int contextID) { _contextID=contextID; }

        /** Get the current OpenGL context unique ID.*/
        inline unsigned int getContextID() const { return _contextID; }


        /* Set whether shader composition is enabled.*/
        void setShaderCompositionEnabled(bool flag) { _shaderCompositionEnabled = flag; }

        /* Get whether shader composition is enabled.*/
        bool getShaderCompositionEnabled() const { return _shaderCompositionEnabled; }

        /** Set the ShaderComposor object that implements shader composition.*/
        void setShaderComposer(ShaderComposer* sc) { _shaderComposer = sc; }

        /** Get the ShaderComposor object.*/
        ShaderComposer* getShaderComposer() { return _shaderComposer.get(); }

        /** Get the const ShaderComposor object.*/
        const ShaderComposer* getShaderComposer() const { return _shaderComposer.get(); }

        /** Get the unform list in which to inject any uniforms that StateAttribute::apply(State&) methods provide.*/
        StateSet::UniformList& getCurrentShaderCompositionUniformList() { return _currentShaderCompositionUniformList; }

        /** Convinience method for StateAttribute:::apply(State&) methods to pass on their uniforms to osg::State so it can apply them at the appropriate point.*/
        void applyShaderCompositionUniform(const osg::Uniform* uniform, StateAttribute::OverrideValue value=StateAttribute::ON)
        {
            StateSet::RefUniformPair& up = _currentShaderCompositionUniformList[uniform->getName()];
            up.first = const_cast<Uniform*>(uniform);
            up.second = value;
        }


        /** Push stateset onto state stack.*/
        void pushStateSet(const StateSet* dstate);

        /** Pop stateset off state stack.*/
        void popStateSet();

        /** pop all statesets off state stack, ensuring it is empty ready for the next frame.
          * Note, to return OpenGL to default state, one should do any state.popAllStatSets(); state.apply().*/
        void popAllStateSets();

        /** Insert stateset onto state stack.*/
Loading
Loading full blame...