2006-07-18 23:21:48 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2003-01-22 00:45:36 +08:00
*
2005-02-02 23:08:55 +08:00
* 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
2003-01-22 00:45:36 +08:00
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
2005-02-02 23:08:55 +08:00
*
2003-01-22 00:45:36 +08:00
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2005-02-02 23:08:55 +08:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2003-01-22 00:45:36 +08:00
* OpenSceneGraph Public License for more details.
*/
2001-10-04 23:12:57 +08:00
2001-01-11 00:32:10 +08:00
#ifndef OSG_STATE
#define OSG_STATE 1
#include <osg/Export>
2014-12-10 18:38:12 +08:00
#include <osg/GLExtensions>
2001-09-20 05:08:56 +08:00
#include <osg/StateSet>
#include <osg/Matrix>
2005-04-04 18:08:15 +08:00
#include <osg/Uniform>
2007-05-01 14:28:20 +08:00
#include <osg/BufferObject>
2010-02-19 05:18:49 +08:00
#include <osg/Observer>
2010-11-11 00:58:58 +08:00
#include <osg/Timer>
2016-07-15 22:41:43 +08:00
#include <osg/VertexArrayState>
2001-09-20 05:08:56 +08:00
2010-06-25 01:15:27 +08:00
#include <osg/ShaderComposer>
2001-09-22 10:42:08 +08:00
#include <osg/FrameStamp>
2001-12-22 06:48:19 +08:00
#include <osg/DisplaySettings>
2002-06-03 23:39:41 +08:00
#include <osg/Polytope>
2003-06-24 23:40:09 +08:00
#include <osg/Viewport>
2016-10-11 22:14:14 +08:00
#include <osg/AttributeDispatchers>
2011-02-03 20:42:23 +08:00
#include <osg/GraphicsCostEstimator>
2001-09-22 10:42:08 +08:00
2010-12-02 22:13:54 +08:00
#include <iosfwd>
2001-09-20 05:08:56 +08:00
#include <vector>
#include <map>
2005-05-04 05:46:47 +08:00
#include <set>
2005-04-04 18:08:15 +08:00
#include <string>
2001-01-11 00:32:10 +08:00
2016-10-12 19:29:58 +08:00
#ifndef GL_TEXTURE0
#define GL_TEXTURE0 0x84C0
#endif
2005-01-08 03:00:40 +08:00
namespace osg {
2005-02-02 23:08:55 +08:00
/** macro for use with osg::StateAttribute::apply methods for detecting and
2010-04-24 00:35:44 +08:00
* reporting OpenGL error messages.*/
2001-09-20 05:08:56 +08:00
#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; \
}\
}
2005-07-20 23:55:07 +08:00
2006-09-19 04:54:48 +08:00
// forward declare GraphicsContext, View and State
2005-07-20 23:55:07 +08:00
class GraphicsContext;
2006-06-08 20:09:51 +08:00
/** Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings,
2010-04-24 00:35:44 +08:00
* 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()).
*/
2014-07-23 00:02:33 +08:00
class OSG_EXPORT State : public Referenced
2001-01-11 00:32:10 +08:00
{
public :
2005-02-02 23:08:55 +08:00
2001-09-20 05:08:56 +08:00
State();
2005-07-20 23:55:07 +08:00
2009-09-23 02:45:24 +08:00
/** Set the graphics context associated with that owns this State object.*/
2005-07-20 23:55:07 +08:00
void setGraphicsContext(GraphicsContext* context) { _graphicsContext = context; }
2009-09-23 02:45:24 +08:00
/** Get the graphics context associated with that owns this State object.*/
2005-07-20 23:55:07 +08:00
GraphicsContext* getGraphicsContext() { return _graphicsContext; }
2009-09-23 02:45:24 +08:00
/** Get the const graphics context associated with that owns this State object.*/
2005-07-20 23:55:07 +08:00
const GraphicsContext* getGraphicsContext() const { return _graphicsContext; }
2009-09-23 02:45:24 +08:00
2005-07-20 23:55:07 +08:00
/** Set the current OpenGL context uniqueID.
2011-06-27 18:19:44 +08:00
* The ContextID is used by classes like osg::StateAttribute's and osg::Drawable's to
2015-04-13 18:43:56 +08:00
* help manage separate OpenGL objects, such as display lists, vertex buffer objects
2012-03-22 01:36:20 +08:00
* and texture object for each graphics context. The ContextID simply acts as an index
2011-06-27 18:19:44 +08:00
* into arrays that these classes maintain for the purpose of storing GL object handles.
2012-03-22 01:36:20 +08:00
*
2011-06-27 18:19:44 +08:00
* Note, osgViewer::GraphicsWindow will automatically set up the ContextID for you,
* so you will rearely need to set this yourself.
2012-03-22 01:36:20 +08:00
*
2011-06-27 18:20:37 +08:00
* The exception is when creating your own graphics context, where you should set
2011-06-27 18:19:44 +08:00
* the ContextID uniquely for each graphics context.
2012-03-22 01:36:20 +08:00
*
2011-06-27 18:19:44 +08:00
* 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.
*/
2005-07-20 23:55:07 +08:00
inline void setContextID(unsigned int contextID) { _contextID=contextID; }
/** Get the current OpenGL context unique ID.*/
inline unsigned int getContextID() const { return _contextID; }
2001-09-20 05:08:56 +08:00
2010-06-25 01:15:27 +08:00
2014-12-02 19:10:23 +08:00
// ExtensionMap contains GL Extentsions objects used by StateAttribue to call OpenGL extensions/advanced features
typedef std::map<const std::type_info*, osg::ref_ptr<osg::Referenced> > ExtensionMap;
ExtensionMap _extensionMap;
2015-09-23 17:47:34 +08:00
/** Get a specific GL extensions object or GraphicsObjectManager, initialize if not already present.
2014-12-02 19:10:23 +08:00
* Note, must only be called from a the graphics context thread associated with this osg::State. */
template<typename T>
T* get()
{
const std::type_info* id(&typeid(T));
osg::ref_ptr<osg::Referenced>& ptr = _extensionMap[id];
if (!ptr)
{
ptr = new T(_contextID);
}
return static_cast<T*>(ptr.get());
}
2015-09-23 17:47:34 +08:00
/** Get a specific GL extensions object or GraphicsObjectManager if it already exists in the extension map.
2014-12-02 19:10:23 +08:00
* Note, safe to call outwith a the graphics context thread associated with this osg::State.
* Returns NULL if the desired extension object has not been created yet.*/
template<typename T>
2014-12-06 01:26:42 +08:00
const T* get() const
2014-12-02 19:10:23 +08:00
{
const std::type_info* id(&typeid(T));
ExtensionMap::const_iterator itr = _extensionMap.find(id);
if (itr==_extensionMap.end()) return 0;
else return itr->second.get();
}
2015-09-23 17:47:34 +08:00
/** Set a specific GL extensions object pr GraphicsObjectManager. */
template<typename T>
void set(T* ptr)
{
const std::type_info* id(&typeid(T));
_extensionMap[id] = ptr;
}
2014-12-02 19:10:23 +08:00
2018-03-05 22:39:07 +08:00
/* deprecated.*/
2010-07-06 00:32:58 +08:00
void setShaderCompositionEnabled(bool flag) { _shaderCompositionEnabled = flag; }
2018-03-05 22:39:07 +08:00
/* deprecated.*/
2010-07-06 00:32:58 +08:00
bool getShaderCompositionEnabled() const { return _shaderCompositionEnabled; }
2018-03-05 22:39:07 +08:00
/** deprecated.*/
2010-06-25 01:15:27 +08:00
void setShaderComposer(ShaderComposer* sc) { _shaderComposer = sc; }
2018-03-05 22:39:07 +08:00
/** deprecated.*/
2010-06-25 01:15:27 +08:00
ShaderComposer* getShaderComposer() { return _shaderComposer.get(); }
2018-03-05 22:39:07 +08:00
/** deprecated.*/
2010-06-25 01:15:27 +08:00
const ShaderComposer* getShaderComposer() const { return _shaderComposer.get(); }
2010-07-06 18:55:54 +08:00
/** Get the unform list in which to inject any uniforms that StateAttribute::apply(State&) methods provide.*/
StateSet::UniformList& getCurrentShaderCompositionUniformList() { return _currentShaderCompositionUniformList; }
2016-06-01 21:20:14 +08:00
/** Convenience method for StateAttribute::apply(State&) methods to pass on their uniforms to osg::State so it can apply them at the appropriate point.*/
2010-07-06 18:55:54 +08:00
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;
}
2010-06-25 01:15:27 +08:00
2004-09-14 01:19:05 +08:00
/** Push stateset onto state stack.*/
2001-09-20 05:08:56 +08:00
void pushStateSet(const StateSet* dstate);
2004-09-14 01:19:05 +08:00
/** Pop stateset off state stack.*/
2001-09-20 05:08:56 +08:00
void popStateSet();
2009-09-23 02:45:24 +08:00
2004-09-03 03:10:33 +08:00
/** pop all statesets off state stack, ensuring it is empty ready for the next frame.
2010-04-24 00:35:44 +08:00
* Note, to return OpenGL to default state, one should do any state.popAllStatSets(); state.apply().*/
2003-09-11 05:22:47 +08:00
void popAllStateSets();
2007-04-16 20:18:56 +08:00
/** Insert stateset onto state stack.*/
void insertStateSet(unsigned int pos,const StateSet* dstate);
/** Pop stateset off state stack.*/
void removeStateSet(unsigned int pos);
2009-09-23 02:45:24 +08:00
2007-01-27 19:13:01 +08:00
/** Get the number of StateSet's on the StateSet stack.*/
2009-01-30 18:55:28 +08:00
unsigned int getStateSetStackSize() { return static_cast<unsigned int>(_stateStateStack.size()); }
2009-09-23 02:45:24 +08:00
2007-01-27 19:13:01 +08:00
/** Pop StateSet's for the StateSet stack till its size equals the specified size.*/
void popStateSetStackToSize(unsigned int size) { while (_stateStateStack.size()>size) popStateSet(); }
typedef std::vector<const StateSet*> StateSetStack;
/** Get the StateSet stack.*/
StateSetStack& getStateSetStack() { return _stateStateStack; }
2009-09-23 02:45:24 +08:00
2003-09-11 05:22:47 +08:00
2004-09-14 01:19:05 +08:00
/** Copy the modes and attributes which capture the current state.*/
2001-10-23 06:02:47 +08:00
void captureCurrentState(StateSet& stateset) const;
2013-10-22 00:35:12 +08:00
/** Release all OpenGL objects associated cached by this osg::State object.*/
void releaseGLObjects();
2001-09-20 05:08:56 +08:00
/** reset the state object to an empty stack.*/
void reset();
2005-02-02 23:08:55 +08:00
2003-06-24 23:40:09 +08:00
inline const Viewport* getCurrentViewport() const
{
return static_cast<const Viewport*>(getLastAppliedAttribute(osg::StateAttribute::VIEWPORT));
}
2005-02-02 23:08:55 +08:00
2001-09-20 05:08:56 +08:00
2003-08-25 21:31:31 +08:00
void setInitialViewMatrix(const osg::RefMatrix* matrix);
2003-07-23 05:03:59 +08:00
inline const osg::Matrix& getInitialViewMatrix() const { return *_initialViewMatrix; }
2003-08-25 21:06:15 +08:00
inline const osg::Matrix& getInitialInverseViewMatrix() const { return _initialInverseViewMatrix; }
2003-07-23 05:03:59 +08:00
2009-10-17 00:26:27 +08:00
void applyProjectionMatrix(const osg::RefMatrix* matrix);
2009-10-09 21:39:11 +08:00
2009-10-17 00:26:27 +08:00
inline const osg::Matrix& getProjectionMatrix() const { return *_projection; }
2009-10-09 21:39:11 +08:00
2009-10-17 00:26:27 +08:00
void applyModelViewMatrix(const osg::RefMatrix* matrix);
2010-06-01 21:33:58 +08:00
void applyModelViewMatrix(const osg::Matrix&);
2002-03-30 01:26:40 +08:00
2009-10-17 00:26:27 +08:00
const osg::Matrix& getModelViewMatrix() const { return *_modelView; }
2002-03-30 01:26:40 +08:00
2009-10-11 14:05:19 +08:00
void setUseModelViewAndProjectionUniforms(bool flag) { _useModelViewAndProjectionUniforms = flag; }
bool getUseModelViewAndProjectionUniforms() const { return _useModelViewAndProjectionUniforms; }
2009-10-17 00:26:27 +08:00
void updateModelViewAndProjectionMatrixUniforms();
2009-10-09 21:39:11 +08:00
void applyModelViewAndProjectionUniformsIfRequired();
osg::Uniform* getModelViewMatrixUniform() { return _modelViewMatrixUniform.get(); }
osg::Uniform* getProjectionMatrixUniform() { return _projectionMatrixUniform.get(); }
osg::Uniform* getModelViewProjectionMatrixUniform() { return _modelViewProjectionMatrixUniform.get(); }
2009-10-17 00:26:27 +08:00
osg::Uniform* getNormalMatrixUniform() { return _normalMatrixUniform.get(); }
2009-10-09 21:39:11 +08:00
2002-03-30 01:26:40 +08:00
2002-06-03 23:39:41 +08:00
Polytope getViewFrustum() const;
2001-09-20 05:08:56 +08:00
2009-10-21 22:09:12 +08:00
2018-06-13 19:23:29 +08:00
void setUseVertexAttributeAliasing(bool flag);
2009-10-17 00:26:27 +08:00
bool getUseVertexAttributeAliasing() const { return _useVertexAttributeAliasing ; }
2009-10-21 22:09:12 +08:00
typedef std::vector<VertexAttribAlias> VertexAttribAliasList;
2013-06-26 21:00:12 +08:00
/** Reset the vertex attribute aliasing to osg's default. This method needs to be called before render anything unless you really know what you're doing !*/
2014-11-24 22:01:05 +08:00
void resetVertexAttributeAlias(bool compactAliasing=true, unsigned int numTextureUnits=8);
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing for "vertex". This method needs to be called before render anything unless you really know what you're doing !*/
void setVertexAlias(const VertexAttribAlias& alias) { _vertexAlias = alias; }
2009-10-21 22:09:12 +08:00
const VertexAttribAlias& getVertexAlias() { return _vertexAlias; }
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing for "normal". This method needs to be called before render anything unless you really know what you're doing !*/
void setNormalAlias(const VertexAttribAlias& alias) { _normalAlias = alias; }
2009-10-21 22:09:12 +08:00
const VertexAttribAlias& getNormalAlias() { return _normalAlias; }
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing for "color". This method needs to be called before render anything unless you really know what you're doing !*/
void setColorAlias(const VertexAttribAlias& alias) { _colorAlias = alias; }
2009-10-21 22:09:12 +08:00
const VertexAttribAlias& getColorAlias() { return _colorAlias; }
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing for "secondary color". This method needs to be called before render anything unless you really know what you're doing !*/
void setSecondaryColorAlias(const VertexAttribAlias& alias) { _secondaryColorAlias = alias; }
2009-10-21 22:09:12 +08:00
const VertexAttribAlias& getSecondaryColorAlias() { return _secondaryColorAlias; }
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing for "fog coord". This method needs to be called before render anything unless you really know what you're doing !*/
void setFogCoordAlias(const VertexAttribAlias& alias) { _fogCoordAlias = alias; }
2009-10-21 22:09:12 +08:00
const VertexAttribAlias& getFogCoordAlias() { return _fogCoordAlias; }
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute aliasing list for texture coordinates. This method needs to be called before render anything unless you really know what you're doing !*/
void setTexCoordAliasList(const VertexAttribAliasList& aliasList) { _texCoordAliasList = aliasList; }
const VertexAttribAliasList& getTexCoordAliasList() { return _texCoordAliasList; }
2009-10-21 22:09:12 +08:00
2013-06-26 21:00:12 +08:00
/** Set the vertex attribute binding list. This method needs to be called before render anything unless you really know what you're doing !*/
void setAttributeBindingList(const Program::AttribBindingList& attribBindingList) { _attributeBindingList = attribBindingList; }
2009-10-17 00:26:27 +08:00
const Program::AttribBindingList& getAttributeBindingList() { return _attributeBindingList; }
bool convertVertexShaderSourceToOsgBuiltIns(std::string& source) const;
2002-05-21 16:59:26 +08:00
/** Apply stateset.*/
2001-09-20 05:08:56 +08:00
void apply(const StateSet* dstate);
2005-02-02 23:08:55 +08:00
/** Updates the OpenGL state so that it matches the \c StateSet at the
2010-04-24 00:35:44 +08:00
* top of the stack of <tt>StateSet</tt>s maintained internally by a
* \c State.
*/
2001-09-20 05:08:56 +08:00
void apply();
2002-05-21 16:59:26 +08:00
2010-07-06 00:32:58 +08:00
/** Apply any shader composed state.*/
void applyShaderComposition();
2002-05-21 16:59:26 +08:00
2018-03-06 17:49:02 +08:00
void glDrawBuffer(GLenum buffer);
GLenum getDrawBuffer() const { return _drawBuffer; }
void glReadBuffer(GLenum buffer);
GLenum getReadBuffer() const { return _readBuffer; }
2006-02-22 22:31:13 +08:00
/** Set whether a particular OpenGL mode is valid in the current graphics context.
2010-04-24 00:35:44 +08:00
* Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
2006-02-22 22:31:13 +08:00
inline void setModeValidity(StateAttribute::GLMode mode,bool valid)
{
ModeStack& ms = _modeMap[mode];
ms.valid = valid;
}
/** Get whether a particular OpenGL mode is valid in the current graphics context.
2010-04-24 00:35:44 +08:00
* Use to disable OpenGL modes that are not supported by current graphics drivers/context.*/
2006-02-22 22:31:13 +08:00
inline bool getModeValidity(StateAttribute::GLMode mode)
{
ModeStack& ms = _modeMap[mode];
return ms.valid;
}
2004-08-07 17:42:19 +08:00
inline void setGlobalDefaultModeValue(StateAttribute::GLMode mode,bool enabled)
{
ModeStack& ms = _modeMap[mode];
ms.global_default_value = enabled;
}
inline bool getGlobalDefaultModeValue(StateAttribute::GLMode mode)
{
return _modeMap[mode].global_default_value;
}
2016-09-02 21:20:17 +08:00
inline bool getLastAppliedModeValue(StateAttribute::GLMode mode)
{
return _modeMap[mode].last_applied_value;
}
/** Proxy helper class for applyig a model in a local scope, with the preivous value being resotred automatically on leaving the scope that proxy was created.*/
struct ApplyModeProxy
{
inline ApplyModeProxy(osg::State& state, GLenum mode, bool value):_state(state), _mode(mode)
{
_previous_value = _state.getLastAppliedModeValue(mode);
_need_to_apply_value = (_previous_value!=value);
if (_need_to_apply_value) _state.applyMode(_mode, value);
}
inline ~ApplyModeProxy()
{
if (_need_to_apply_value) _state.applyMode(_mode, _previous_value);
}
osg::State& _state;
GLenum _mode;
bool _previous_value;
bool _need_to_apply_value;
};
2004-08-07 17:42:19 +08:00
2016-09-03 00:00:00 +08:00
struct ApplyTextureModeProxy
{
inline ApplyTextureModeProxy(osg::State& state, unsigned int unit, GLenum mode, bool value):_state(state), _unit(unit), _mode(mode)
{
_previous_value = _state.getLastAppliedTextureModeValue(_unit, _mode);
_need_to_apply_value = (_previous_value!=value);
if (_need_to_apply_value) _state.applyTextureMode(_unit, _mode, value);
}
inline ~ApplyTextureModeProxy()
{
if (_need_to_apply_value) _state.applyTextureMode(_unit, _mode, _previous_value);
}
osg::State& _state;
unsigned int _unit;
GLenum _mode;
bool _previous_value;
bool _need_to_apply_value;
};
2005-02-02 23:08:55 +08:00
/** Apply an OpenGL mode if required. This is a wrapper around
2010-04-24 00:35:44 +08:00
* \c glEnable() and \c glDisable(), that just actually calls these
* functions if the \c enabled flag is different than the current
* state.
* @return \c true if the state was actually changed. \c false
* otherwise. Notice that a \c false return does not indicate
* an error, it just means that the mode was already set to the
* same value as the \c enabled parameter.
2005-02-02 23:08:55 +08:00
*/
2002-09-02 20:31:35 +08:00
inline bool applyMode(StateAttribute::GLMode mode,bool enabled)
2002-05-21 16:59:26 +08:00
{
2002-05-22 18:04:28 +08:00
ModeStack& ms = _modeMap[mode];
2005-02-02 23:08:55 +08:00
ms.changed = true;
2002-05-22 18:04:28 +08:00
return applyMode(mode,enabled,ms);
2002-05-21 16:59:26 +08:00
}
2004-08-07 17:42:19 +08:00
inline void setGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
{
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
ModeStack& ms = modeMap[mode];
ms.global_default_value = enabled;
}
inline bool getGlobalDefaultTextureModeValue(unsigned int unit, StateAttribute::GLMode mode)
{
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
ModeStack& ms = modeMap[mode];
return ms.global_default_value;
}
2002-09-02 20:31:35 +08:00
inline bool applyTextureMode(unsigned int unit, StateAttribute::GLMode mode,bool enabled)
2002-07-07 22:40:41 +08:00
{
2010-01-08 00:49:12 +08:00
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
ModeStack& ms = modeMap[mode];
ms.changed = true;
return applyModeOnTexUnit(unit,mode,enabled,ms);
2002-07-07 22:40:41 +08:00
}
2002-05-21 16:59:26 +08:00
2016-09-02 21:20:17 +08:00
inline bool getLastAppliedTextureModeValue(unsigned int unit, StateAttribute::GLMode mode)
{
ModeMap& modeMap = getOrCreateTextureModeMap(unit);
ModeStack& ms = modeMap[mode];
return ms.last_applied_value;
}
2004-08-07 17:42:19 +08:00
inline void setGlobalDefaultAttribute(const StateAttribute* attribute)
{
2004-10-13 19:15:50 +08:00
AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
2004-08-07 17:42:19 +08:00
as.global_default_attribute = attribute;
}
2004-10-13 19:15:50 +08:00
inline const StateAttribute* getGlobalDefaultAttribute(StateAttribute::Type type, unsigned int member=0)
2004-08-07 17:42:19 +08:00
{
2004-10-13 19:15:50 +08:00
AttributeStack& as = _attributeMap[StateAttribute::TypeMemberPair(type,member)];
2004-08-07 17:42:19 +08:00
return as.global_default_attribute.get();
}
2002-05-21 16:59:26 +08:00
/** Apply an attribute if required. */
2002-09-02 20:31:35 +08:00
inline bool applyAttribute(const StateAttribute* attribute)
2002-05-21 16:59:26 +08:00
{
2004-10-13 19:15:50 +08:00
AttributeStack& as = _attributeMap[attribute->getTypeMemberPair()];
2002-05-22 18:04:28 +08:00
as.changed = true;
return applyAttribute(attribute,as);
2002-05-21 16:59:26 +08:00
}
2004-08-07 17:42:19 +08:00
inline void setGlobalDefaultTextureAttribute(unsigned int unit, const StateAttribute* attribute)
{
AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
2004-10-13 19:15:50 +08:00
AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
2004-08-07 17:42:19 +08:00
as.global_default_attribute = attribute;
}
2004-10-13 19:15:50 +08:00
inline const StateAttribute* getGlobalDefaultTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member = 0)
2004-08-07 17:42:19 +08:00
{
AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
2004-10-13 19:15:50 +08:00
AttributeStack& as = attributeMap[StateAttribute::TypeMemberPair(type,member)];
2004-08-07 17:42:19 +08:00
return as.global_default_attribute.get();
}
2002-09-02 20:31:35 +08:00
inline bool applyTextureAttribute(unsigned int unit, const StateAttribute* attribute)
2002-07-07 22:40:41 +08:00
{
2010-01-08 00:49:12 +08:00
AttributeMap& attributeMap = getOrCreateTextureAttributeMap(unit);
AttributeStack& as = attributeMap[attribute->getTypeMemberPair()];
as.changed = true;
return applyAttributeOnTexUnit(unit,attribute,as);
2002-07-07 22:40:41 +08:00
}
2005-02-02 23:08:55 +08:00
2002-05-21 16:59:26 +08:00
/** Mode has been set externally, update state to reflect this setting.*/
2002-09-02 20:31:35 +08:00
void haveAppliedMode(StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
2005-02-02 23:08:55 +08:00
2002-05-21 16:59:26 +08:00
/** Mode has been set externally, therefore dirty the associated mode in osg::State
2010-04-24 00:35:44 +08:00
* so it is applied on next call to osg::State::apply(..)*/
2002-09-02 20:31:35 +08:00
void haveAppliedMode(StateAttribute::GLMode mode);
2002-03-21 20:00:10 +08:00
2002-05-21 16:59:26 +08:00
/** Attribute has been applied externally, update state to reflect this setting.*/
2002-03-21 20:36:05 +08:00
void haveAppliedAttribute(const StateAttribute* attribute);
2002-03-21 20:00:10 +08:00
2012-03-22 01:36:20 +08:00
/** Attribute has been applied externally,
* and therefore this attribute type has been dirtied
2010-04-24 00:35:44 +08:00
* and will need to be re-applied on next osg::State.apply(..).
* note, if you have an osg::StateAttribute which you have applied externally
* then use the have_applied(attribute) method as this will cause the osg::State to
* track the current state more accurately and enable lazy state updating such
* that only changed state will be applied.*/
2004-10-13 19:15:50 +08:00
void haveAppliedAttribute(StateAttribute::Type type, unsigned int member=0);
2001-09-20 05:08:56 +08:00
2009-09-23 02:45:24 +08:00
/** Get whether the current specified mode is enabled (true) or disabled (false).*/
2002-09-02 20:31:35 +08:00
bool getLastAppliedMode(StateAttribute::GLMode mode) const;
2005-02-02 23:08:55 +08:00
2009-09-23 02:45:24 +08:00
/** Get the current specified attribute, return NULL if one has not yet been applied.*/
2004-10-13 19:15:50 +08:00
const StateAttribute* getLastAppliedAttribute(StateAttribute::Type type, unsigned int member=0) const;
2005-02-02 23:08:55 +08:00
2002-07-07 22:40:41 +08:00
/** texture Mode has been set externally, update state to reflect this setting.*/
2002-09-02 20:31:35 +08:00
void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
2005-02-02 23:08:55 +08:00
2002-07-07 22:40:41 +08:00
/** texture Mode has been set externally, therefore dirty the associated mode in osg::State
2010-04-24 00:35:44 +08:00
* so it is applied on next call to osg::State::apply(..)*/
2002-09-02 20:31:35 +08:00
void haveAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode);
2002-07-07 22:40:41 +08:00
/** texture Attribute has been applied externally, update state to reflect this setting.*/
void haveAppliedTextureAttribute(unsigned int unit, const StateAttribute* attribute);
2005-02-02 23:08:55 +08:00
/** texture Attribute has been applied externally,
2010-04-24 00:35:44 +08:00
* and therefore this attribute type has been dirtied
* and will need to be re-applied on next osg::State.apply(..).
* note, if you have an osg::StateAttribute which you have applied externally
* then use the have_applied(attribute) method as this will the osg::State to
* track the current state more accurately and enable lazy state updating such
* that only changed state will be applied.*/
2004-10-13 19:15:50 +08:00
void haveAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0);
2002-07-07 22:40:41 +08:00
2005-02-02 23:08:55 +08:00
/** Get whether the current specified texture mode is enabled (true) or disabled (false).*/
2002-09-02 20:31:35 +08:00
bool getLastAppliedTextureMode(unsigned int unit, StateAttribute::GLMode mode) const;
2005-02-02 23:08:55 +08:00
/** Get the current specified texture attribute, return NULL if one has not yet been applied.*/
2004-10-13 19:15:50 +08:00
const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0) const;
2002-07-07 22:40:41 +08:00
2016-07-15 22:41:43 +08:00
2003-01-19 23:28:08 +08:00
/** Dirty the modes previously applied in osg::State.*/
void dirtyAllModes();
/** Dirty the modes attributes previously applied in osg::State.*/
void dirtyAllAttributes();
2016-07-15 22:41:43 +08:00
2016-09-02 21:20:17 +08:00
/** Proxy helper class for applyig a VertexArrayState in a local scope, with the preivous value being resotred automatically on leaving the scope that proxy was created.*/
2016-07-23 23:33:39 +08:00
struct SetCurrentVertexArrayStateProxy
{
SetCurrentVertexArrayStateProxy(osg::State& state, VertexArrayState* vas):_state(state) { _state.setCurrentVertexArrayState(vas); }
2017-12-31 21:17:23 +08:00
~SetCurrentVertexArrayStateProxy() { _state.setCurrentToGlobalVertexArrayState(); }
2016-07-23 23:33:39 +08:00
osg::State& _state;
};
2016-07-15 22:41:43 +08:00
/** Set the CurrentVetexArrayState object that take which vertex arrays are bound.*/
2016-08-06 04:59:34 +08:00
void setCurrentVertexArrayState(VertexArrayState* vas) { _vas = vas; }
2016-07-15 22:41:43 +08:00
/** Get the CurrentVetexArrayState object that take which vertex arrays are bound.*/
2016-08-06 04:59:34 +08:00
VertexArrayState* getCurrentVertexArrayState() const { return _vas; }
2016-07-23 23:33:39 +08:00
2017-12-31 21:17:23 +08:00
/** Set the getCurrentVertexArrayState to the GlobalVertexArrayState.*/
void setCurrentToGlobalVertexArrayState() { _vas = _globalVertexArrayState.get(); }
2016-07-15 22:41:43 +08:00
2019-01-22 01:36:40 +08:00
/** Reset the CurrentVertexArrayObject if it's value equals the specificied vas - use when deleting a vas.*/
void resetCurrentVertexArrayStateOnMatch(VertexArrayState* vas) { if (_vas==vas) _vas = 0; }
2016-07-15 22:41:43 +08:00
2004-09-14 01:19:05 +08:00
/** disable the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
2002-09-13 21:50:58 +08:00
void disableAllVertexArrays();
2016-07-15 22:41:43 +08:00
2016-08-06 04:59:34 +08:00
void lazyDisablingOfVertexAttributes() { _vas->lazyDisablingOfVertexAttributes(); }
void applyDisablingOfVertexAttributes() { _vas->applyDisablingOfVertexAttributes(*this); }
2016-07-15 22:41:43 +08:00
2016-08-06 04:59:34 +08:00
void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _vas->setCurrentVertexBufferObject(vbo); }
const GLBufferObject* getCurrentVertexBufferObject() { return _vas->getCurrentVertexBufferObject(); }
2016-07-23 22:02:08 +08:00
2016-08-06 04:59:34 +08:00
void bindVertexBufferObject(osg::GLBufferObject* vbo) { _vas->bindVertexBufferObject(vbo); }
void unbindVertexBufferObject() { _vas->unbindVertexBufferObject(); }
2016-07-23 22:02:08 +08:00
2016-08-06 04:59:34 +08:00
void setCurrentElementBufferObject(osg::GLBufferObject* ebo) { _vas->setCurrentElementBufferObject(ebo); }
const GLBufferObject* getCurrentElementBufferObject() { return _vas->getCurrentElementBufferObject(); }
2016-07-23 22:02:08 +08:00
2016-08-06 04:59:34 +08:00
void bindElementBufferObject(osg::GLBufferObject* ebo) { _vas->bindElementBufferObject(ebo); }
void unbindElementBufferObject() { _vas->unbindElementBufferObject(); }
2007-05-01 14:28:20 +08:00
2009-10-02 04:19:42 +08:00
void setCurrentPixelBufferObject(osg::GLBufferObject* pbo) { _currentPBO = pbo; }
2017-03-13 19:44:34 +08:00
const GLBufferObject* getCurrentPixelBufferObject() const { return _currentPBO; }
2007-05-01 14:28:20 +08:00
2009-10-02 04:19:42 +08:00
inline void bindPixelBufferObject(osg::GLBufferObject* pbo)
2007-05-01 14:28:20 +08:00
{
2016-06-23 18:03:38 +08:00
if (pbo)
{
if (pbo == _currentPBO) return;
2007-05-01 14:28:20 +08:00
2016-06-23 18:03:38 +08:00
if (pbo->isDirty()) pbo->compileBuffer();
else pbo->bindBuffer();
2007-05-01 14:28:20 +08:00
2016-06-23 18:03:38 +08:00
_currentPBO = pbo;
}
else
{
unbindPixelBufferObject();
}
2007-05-01 14:28:20 +08:00
}
inline void unbindPixelBufferObject()
{
if (!_currentPBO) return;
2009-09-23 02:45:24 +08:00
2007-05-01 14:28:20 +08:00
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,0);
_currentPBO = 0;
}
2009-09-23 02:45:24 +08:00
2017-03-13 19:44:34 +08:00
2017-07-27 07:54:25 +08:00
inline void bindDrawIndirectBufferObject(osg::GLBufferObject* ibo)
{
if (ibo->isDirty())
{
ibo->compileBuffer();
_currentDIBO = ibo;
}
else if (ibo != _currentDIBO)
{
2017-07-27 18:00:41 +08:00
ibo->bindBuffer();
2017-07-27 07:54:25 +08:00
_currentDIBO = ibo;
}
}
inline void unbindDrawIndirectBufferObject()
{
if (!_currentDIBO) return;
_glBindBuffer(GL_DRAW_INDIRECT_BUFFER,0);
_currentDIBO = 0;
}
2017-03-13 19:44:34 +08:00
void setCurrentVertexArrayObject(GLuint vao) { _currentVAO = vao; }
GLuint getCurrentVertexArrayObject() const { return _currentVAO; }
inline void bindVertexArrayObject(const VertexArrayState* vas) { bindVertexArrayObject(vas->getVertexArrayObject()); }
inline void bindVertexArrayObject(GLuint vao) { if (_currentVAO!=vao) { _glExtensions->glBindVertexArray(vao); _currentVAO = vao; } }
inline void unbindVertexArrayObject() { if (_currentVAO!=0) { _glExtensions->glBindVertexArray(0); _currentVAO = 0; } }
2011-06-14 23:48:27 +08:00
typedef std::vector<GLushort> IndicesGLushort;
IndicesGLushort _quadIndicesGLushort[4];
typedef std::vector<GLuint> IndicesGLuint;
IndicesGLuint _quadIndicesGLuint[4];
2009-11-12 20:18:33 +08:00
2009-11-18 20:50:03 +08:00
void drawQuads(GLint first, GLsizei count, GLsizei primCount=0);
2009-09-23 02:45:24 +08:00
2009-01-06 22:55:49 +08:00
inline void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
if (primcount>=1 && _glDrawArraysInstanced!=0) _glDrawArraysInstanced(mode, first, count, primcount);
else glDrawArrays(mode, first, count);
}
2009-09-23 02:45:24 +08:00
2009-01-06 22:55:49 +08:00
inline void glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount )
{
if (primcount>=1 && _glDrawElementsInstanced!=0) _glDrawElementsInstanced(mode, count, type, indices, primcount);
else glDrawElements(mode, count, type, indices);
}
2007-05-01 14:28:20 +08:00
2009-10-17 00:26:27 +08:00
inline void Vertex(float x, float y, float z, float w=1.0f)
{
2009-10-25 19:52:01 +08:00
#if defined(OSG_GL_VERTEX_FUNCS_AVAILABLE) && !defined(OSG_GLES1_AVAILABLE)
2009-10-17 00:26:27 +08:00
if (_useVertexAttributeAliasing) _glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
else glVertex4f(x,y,z,w);
2009-10-25 19:52:01 +08:00
#else
_glVertexAttrib4f( _vertexAlias._location, x,y,z,w);
#endif
2009-10-17 00:26:27 +08:00
}
inline void Color(float r, float g, float b, float a=1.0f)
{
2009-10-25 19:52:01 +08:00
#ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
2009-10-17 00:26:27 +08:00
if (_useVertexAttributeAliasing) _glVertexAttrib4f( _colorAlias._location, r,g,b,a);
else glColor4f(r,g,b,a);
2009-10-25 19:52:01 +08:00
#else
_glVertexAttrib4f( _colorAlias._location, r,g,b,a);
#endif
2009-10-17 00:26:27 +08:00
}
void Normal(float x, float y, float z)
{
2009-10-25 19:52:01 +08:00
#ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
2009-10-17 00:26:27 +08:00
if (_useVertexAttributeAliasing) _glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
else glNormal3f(x,y,z);
2009-10-25 19:52:01 +08:00
#else
_glVertexAttrib4f( _normalAlias._location, x,y,z,0.0);
#endif
2009-10-17 00:26:27 +08:00
}
2009-10-21 03:34:24 +08:00
void TexCoord(float x, float y=0.0f, float z=0.0f, float w=1.0f)
2009-10-17 00:26:27 +08:00
{
2009-10-25 19:52:01 +08:00
#if !defined(OSG_GLES1_AVAILABLE)
#ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
else glTexCoord4f(x,y,z,w);
#else
_glVertexAttrib4f( _texCoordAliasList[0]._location, x,y,z,w);
#endif
#endif
2009-10-17 00:26:27 +08:00
}
2009-10-21 03:34:24 +08:00
void MultiTexCoord(unsigned int unit, float x, float y=0.0f, float z=0.0f, float w=1.0f)
2009-10-17 00:26:27 +08:00
{
2009-10-25 19:52:01 +08:00
#if !defined(OSG_GLES1_AVAILABLE)
#ifdef OSG_GL_VERTEX_FUNCS_AVAILABLE
if (_useVertexAttributeAliasing) _glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
else _glMultiTexCoord4f(GL_TEXTURE0+unit,x,y,z,w);
#else
_glVertexAttrib4f( _texCoordAliasList[unit]._location, x,y,z,w);
#endif
#endif
2009-10-17 00:26:27 +08:00
}
void VerteAttrib(unsigned int location, float x, float y=0.0f, float z=0.0f, float w=0.0f)
{
_glVertexAttrib4f( location, x,y,z,w);
}
2009-10-25 19:52:01 +08:00
/** Wrapper around glInterleavedArrays(..).
* also resets the internal array points and modes within osg::State to keep the other
* vertex array operations consistent. */
2016-08-06 04:59:34 +08:00
void setInterleavedArrays( GLenum format, GLsizei stride, const GLvoid* pointer) { _vas->setInterleavedArrays( *this, format, stride, pointer); }
2009-10-17 00:26:27 +08:00
2007-05-01 14:28:20 +08:00
/** Set the vertex pointer using an osg::Array, and manage any VBO that are required.*/
2016-08-06 04:59:34 +08:00
inline void setVertexPointer(const Array* array) { _vas->setVertexArray(*this, array); }
inline void setVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE) { _vas->setVertexArray( *this, size, type, stride, ptr, normalized); }
inline void disableVertexPointer() { _vas->disableVertexArray(*this); }
2005-02-02 23:08:55 +08:00
2002-07-07 22:40:41 +08:00
2016-08-06 04:59:34 +08:00
inline void setNormalPointer(const Array* array) { _vas->setNormalArray(*this, array); }
inline void setNormalPointer( GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE ) { _vas->setNormalArray( *this, type, stride, ptr, normalized); }
inline void disableNormalPointer() { _vas->disableNormalArray(*this); }
2002-09-13 21:50:58 +08:00
2016-08-06 04:59:34 +08:00
inline void setColorPointer(const Array* array) { _vas->setColorArray(*this, array); }
inline void setColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_TRUE ) { _vas->setColorArray(*this, size, type, stride, ptr, normalized); }
inline void disableColorPointer() { _vas->disableColorArray(*this); }
2007-05-01 14:28:20 +08:00
2016-08-06 04:59:34 +08:00
inline bool isSecondaryColorSupported() const { return _isSecondaryColorSupported; }
inline void setSecondaryColorPointer(const Array* array) { _vas->setSecondaryColorArray(*this, array); }
inline void disableSecondaryColorPointer() { _vas->disableSecondaryColorArray(*this); }
2002-07-07 22:40:41 +08:00
2016-08-06 04:59:34 +08:00
inline bool isFogCoordSupported() const { return _isFogCoordSupported; }
inline void setFogCoordPointer(const Array* array) { _vas->setFogCoordArray(*this, array); }
inline void disableFogCoordPointer() { _vas->disableFogCoordArray(*this); }
2002-07-07 22:40:41 +08:00
2016-08-06 04:59:34 +08:00
inline void setTexCoordPointer(unsigned int unit, const Array* array) { _vas->setTexCoordArray(*this, unit, array); }
inline void setTexCoordPointer( unsigned int unit, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized=GL_FALSE ) { _vas->setTexCoordArray(*this, unit, size, type, stride, ptr, normalized); }
inline void disableTexCoordPointer( unsigned int unit ) { _vas->disableTexCoordArray(*this, unit); }
inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit ) { _vas->disableTexCoordArrayAboveAndIncluding(*this, unit); }
2005-03-25 19:07:48 +08:00
2014-01-07 19:01:32 +08:00
/// For GL>=2.0 uses GL_MAX_TEXTURE_COORDS, for GL<2 uses GL_MAX_TEXTURE_UNITS
inline GLint getMaxTextureCoords() const { return _glMaxTextureCoords; }
/// For GL>=2.0 uses GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, for GL<2 uses GL_MAX_TEXTURE_UNITS
inline GLint getMaxTextureUnits() const { return _glMaxTextureUnits; }
2005-03-25 19:07:48 +08:00
/** Set the current texture unit, return true if selected,
2010-04-24 00:35:44 +08:00
* false if selection failed such as when multi texturing is not supported.
* note, only updates values that change.*/
2010-01-08 00:49:12 +08:00
inline bool setActiveTextureUnit( unsigned int unit );
2012-03-22 01:36:20 +08:00
2005-03-25 19:07:48 +08:00
/** Get the current texture unit.*/
unsigned int getActiveTextureUnit() const { return _currentActiveTextureUnit; }
2002-07-07 22:40:41 +08:00
2005-03-25 19:07:48 +08:00
/** Set the current tex coord array texture unit, return true if selected,
2010-04-24 00:35:44 +08:00
* false if selection failed such as when multi texturing is not supported.
* note, only updates values that change.*/
2005-03-25 19:07:48 +08:00
bool setClientActiveTextureUnit( unsigned int unit );
/** Get the current tex coord array texture unit.*/
2016-07-23 22:02:08 +08:00
unsigned int getClientActiveTextureUnit() const;
2005-02-02 23:08:55 +08:00
2016-08-06 04:59:34 +08:00
inline void setVertexAttribPointer(unsigned int unit, const Array* array) { _vas->setVertexAttribArray(*this, unit, array); }
inline void setVertexAttribLPointer(unsigned int unit, const Array* array) { _vas->setVertexAttribArray(*this, unit, array); }
inline void setVertexAttribIPointer(unsigned int unit, const Array* array) { _vas->setVertexAttribArray(*this, unit, array); }
2005-02-02 23:08:55 +08:00
2016-08-06 04:59:34 +08:00
inline void disableVertexAttribPointer( unsigned int index ) { _vas->disableVertexAttribArray(*this, index); }
inline void disableVertexAttribPointersAboveAndIncluding( unsigned int index ) { _vas->disableVertexAttribArray(*this, index); }
2005-02-02 23:08:55 +08:00
2016-08-05 05:00:58 +08:00
/** dirty the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/
void dirtyAllVertexArrays();
2003-05-07 21:13:13 +08:00
2016-08-09 00:57:20 +08:00
inline bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupported; }
2016-08-13 01:44:38 +08:00
inline bool useVertexBufferObject(bool useVBO) const { return _forceVertexBufferObject || (_isVertexBufferObjectSupported && useVBO); }
2003-06-30 05:41:57 +08:00
2016-08-06 04:59:34 +08:00
inline bool isVertexArrayObjectSupported() const { return _isVertexArrayObjectSupported; }
2016-08-13 01:44:38 +08:00
inline bool useVertexArrayObject(bool useVAO) const { return _forceVertexArrayObject || (_isVertexArrayObjectSupported && useVAO); }
2016-08-04 22:33:02 +08:00
2003-05-07 21:13:13 +08:00
2009-01-26 23:16:24 +08:00
inline void setLastAppliedProgramObject(const Program::PerContextProgram* program)
{
if (_lastAppliedProgramObject!=program)
{
2009-09-23 02:45:24 +08:00
_lastAppliedProgramObject = program;
2009-01-26 23:16:24 +08:00
}
}
inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
2005-04-13 20:00:28 +08:00
2010-11-25 20:30:38 +08:00
inline GLint getUniformLocation( unsigned int uniformNameID ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(uniformNameID) : -1; }
2011-01-12 01:18:44 +08:00
/**
* Alternative version of getUniformLocation( unsigned int uniformNameID )
* retrofited into OSG for backward compatibility with osgCal,
* after uniform ids were refactored from std::strings to GLints in OSG version 2.9.10.
2012-03-22 01:36:20 +08:00
*
* Drawbacks: This method is not particularly fast. It has to access mutexed static
2011-01-12 01:18:44 +08:00
* map of uniform ids. So don't overuse it or your app performance will suffer.
*/
inline GLint getUniformLocation( const std::string & uniformName ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(uniformName) : -1; }
2005-05-13 04:35:15 +08:00
inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; }
2005-04-13 20:00:28 +08:00
2009-05-12 13:49:36 +08:00
typedef std::pair<const StateAttribute*,StateAttribute::OverrideValue> AttributePair;
typedef std::vector<AttributePair> AttributeVec;
AttributeVec& getAttributeVec( const osg::StateAttribute* attribute )
{
AttributeStack& as = _attributeMap[ attribute->getTypeMemberPair() ];
return as.attributeVec;
}
2005-02-02 23:08:55 +08:00
2001-09-22 10:42:08 +08:00
/** Set the frame stamp for the current frame.*/
inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
2004-09-14 01:19:05 +08:00
/** Get the frame stamp for the current frame.*/
2007-08-02 19:02:47 +08:00
inline FrameStamp* getFrameStamp() { return _frameStamp.get(); }
/** Get the const frame stamp for the current frame.*/
2001-09-22 10:42:08 +08:00
inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
2005-02-02 23:08:55 +08:00
2004-09-03 03:10:33 +08:00
/** Set the DisplaySettings. Note, nothing is applied, the visual settings are just
2010-04-24 00:35:44 +08:00
* used in the State object to pass the current visual settings to Drawables
* during rendering. */
2001-12-22 06:48:19 +08:00
inline void setDisplaySettings(DisplaySettings* vs) { _displaySettings = vs; }
2005-02-02 23:08:55 +08:00
2017-09-19 01:09:15 +08:00
/** Get the const DisplaySettings */
2001-12-22 06:48:19 +08:00
inline const DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); }
2001-12-19 08:38:23 +08:00
2018-05-04 17:54:02 +08:00
/** Get the DisplaySettings that is current active DisplaySettings to be used by osg::State, - if DisplaySettings is not directly assigned then fallback to DisplaySettings::instance(). */
inline DisplaySettings* getActiveDisplaySettings() { return _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); }
2017-09-19 01:09:15 +08:00
/** Get the const DisplaySettings that is current active DisplaySettings to be used by osg::State, - if DisplaySettings is not directly assigned then fallback to DisplaySettings::instance(). */
inline const DisplaySettings* getActiveDisplaySettings() const { return _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get(); }
2005-02-02 23:08:55 +08:00
2003-03-11 23:25:49 +08:00
/** Set flag for early termination of the draw traversal.*/
void setAbortRenderingPtr(bool* abortPtr) { _abortRenderingPtr = abortPtr; }
2005-02-02 23:08:55 +08:00
/** Get flag for early termination of the draw traversal,
2010-04-24 00:35:44 +08:00
* if true steps should be taken to complete rendering early.*/
2003-03-11 23:25:49 +08:00
bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
2007-01-30 06:44:29 +08:00
struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
{
virtual void completed(osg::State*) = 0;
};
2009-09-23 02:45:24 +08:00
2007-01-30 06:44:29 +08:00
/** Set the callback to be called when the dynamic object count hits 0.*/
void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
2009-09-23 02:45:24 +08:00
2007-01-30 06:44:29 +08:00
/** Get the callback to be called when the dynamic object count hits 0.*/
DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
2009-09-23 02:45:24 +08:00
2007-01-30 06:44:29 +08:00
/** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
{
if (_dynamicObjectCount != count)
{
_dynamicObjectCount = count;
if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
{
_completeDynamicObjectRenderingCallback->completed(this);
}
}
}
/** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
2012-03-22 01:36:20 +08:00
/** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
2010-04-24 00:35:44 +08:00
* DynamicObjectRenderingCompletedCallback to inform of completion.*/
2007-01-30 06:44:29 +08:00
inline void decrementDynamicObjectCount()
{
--_dynamicObjectCount;
if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
{
_completeDynamicObjectRenderingCallback->completed(this);
}
2009-09-23 02:45:24 +08:00
}
void setMaxTexturePoolSize(unsigned int size);
unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }
2009-10-03 17:25:23 +08:00
void setMaxBufferObjectPoolSize(unsigned int size);
unsigned int getMaxBufferObjectPoolSize() const { return _maxBufferObjectPoolSize; }
2007-01-30 06:44:29 +08:00
2005-04-30 04:56:20 +08:00
enum CheckForGLErrors
{
2009-09-23 02:45:24 +08:00
/** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
2015-04-13 18:43:56 +08:00
is the fastest option since checking for errors does incur a small overhead.*/
2005-04-30 04:56:20 +08:00
NEVER_CHECK_GL_ERRORS,
2015-04-13 18:43:56 +08:00
/** ONCE_PER_FRAME means that OpenGL errors will be checked for once per
2005-04-30 04:56:20 +08:00
frame, the overhead is still small, but at least OpenGL errors that are occurring
will be caught, the reporting isn't fine grained enough for debugging purposes.*/
ONCE_PER_FRAME,
/** ONCE_PER_ATTRIBUTE means that OpenGL errors will be checked for after
every attribute is applied, allow errors to be directly associated with
particular operations which makes debugging much easier.*/
ONCE_PER_ATTRIBUTE
};
/** Set whether and how often OpenGL errors should be checked for.*/
void setCheckForGLErrors(CheckForGLErrors check) { _checkGLErrors = check; }
/** Get whether and how often OpenGL errors should be checked for.*/
CheckForGLErrors getCheckForGLErrors() const { return _checkGLErrors; }
2003-01-22 00:45:36 +08:00
2016-11-14 19:59:47 +08:00
bool checkGLErrors(const char* str1=0, const char* str2=0) const;
2003-01-22 00:45:36 +08:00
bool checkGLErrors(StateAttribute::GLMode mode) const;
bool checkGLErrors(const StateAttribute* attribute) const;
2002-03-19 05:56:00 +08:00
2010-07-11 01:14:59 +08:00
/** print out the internal details of osg::State - useful for debugging.*/
void print(std::ostream& fout) const;
2007-05-01 14:28:20 +08:00
2016-06-01 21:20:14 +08:00
/** Initialize extension used by osg::State.*/
2007-05-01 14:28:20 +08:00
void initializeExtensionProcs();
2011-02-03 20:42:23 +08:00
/** Get the helper class for dispatching osg::Arrays as OpenGL attribute data.*/
2016-10-11 22:14:14 +08:00
inline AttributeDispatchers& getAttributeDispatchers() { return _arrayDispatchers; }
2009-10-17 00:26:27 +08:00
2011-02-03 20:42:23 +08:00
/** Set the helper class that provides applications with estimate on how much different graphics operations will cost.*/
inline void setGraphicsCostEstimator(GraphicsCostEstimator* gce) { _graphicsCostEstimator = gce; }
/** Get the helper class that provides applications with estimate on how much different graphics operations will cost.*/
inline GraphicsCostEstimator* getGraphicsCostEstimator() { return _graphicsCostEstimator.get(); }
/** Get the cont helper class that provides applications with estimate on how much different graphics operations will cost.*/
inline const GraphicsCostEstimator* getGraphicsCostEstimator() const { return _graphicsCostEstimator.get(); }
2010-11-11 00:58:58 +08:00
/** Support for synchronizing the system time and the timestamp
* counter available with ARB_timer_query. Note that State
* doesn't update these values itself.
*/
Timer_t getStartTick() const { return _startTick; }
void setStartTick(Timer_t tick) { _startTick = tick; }
Timer_t getGpuTick() const { return _gpuTick; }
double getGpuTime() const
{
return osg::Timer::instance()->delta_s(_startTick, _gpuTick);
}
2014-04-23 17:08:26 +08:00
GLuint64 getGpuTimestamp() const { return _gpuTimestamp; }
2010-11-11 00:58:58 +08:00
2014-04-23 17:08:26 +08:00
void setGpuTimestamp(Timer_t tick, GLuint64 timestamp)
2010-11-11 00:58:58 +08:00
{
_gpuTick = tick;
_gpuTimestamp = timestamp;
}
int getTimestampBits() const { return _timestampBits; }
void setTimestampBits(int bits) { _timestampBits = bits; }
/** called by the GraphicsContext just before GraphicsContext::swapBuffersImplementation().*/
virtual void frameCompleted();
2003-01-22 00:45:36 +08:00
2001-09-20 05:08:56 +08:00
struct ModeStack
{
2005-04-13 20:00:28 +08:00
typedef std::vector<StateAttribute::GLModeValue> ValueVec;
2001-09-20 05:08:56 +08:00
ModeStack()
{
2006-02-22 22:31:13 +08:00
valid = true;
2001-09-20 05:08:56 +08:00
changed = false;
last_applied_value = false;
2001-10-15 22:07:54 +08:00
global_default_value = false;
2001-09-20 05:08:56 +08:00
}
2005-02-02 23:08:55 +08:00
2010-07-11 01:14:59 +08:00
void print(std::ostream& fout) const;
2006-02-22 22:31:13 +08:00
bool valid;
2001-09-20 05:08:56 +08:00
bool changed;
bool last_applied_value;
2001-10-15 22:07:54 +08:00
bool global_default_value;
2001-09-20 05:08:56 +08:00
ValueVec valueVec;
};
struct AttributeStack
{
AttributeStack()
{
changed = false;
last_applied_attribute = 0L;
2010-07-02 20:04:20 +08:00
last_applied_shadercomponent = 0L;
2001-10-15 22:07:54 +08:00
global_default_attribute = 0L;
2012-03-22 01:36:20 +08:00
2001-09-20 05:08:56 +08:00
}
2010-07-11 01:14:59 +08:00
void print(std::ostream& fout) const;
2001-10-15 22:07:54 +08:00
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
2001-09-20 05:08:56 +08:00
bool changed;
const StateAttribute* last_applied_attribute;
2010-07-02 20:04:20 +08:00
const ShaderComponent* last_applied_shadercomponent;
2004-08-07 17:42:19 +08:00
ref_ptr<const StateAttribute> global_default_attribute;
2001-09-20 05:08:56 +08:00
AttributeVec attributeVec;
};
2005-02-02 23:08:55 +08:00
2005-04-13 20:00:28 +08:00
struct UniformStack
{
typedef std::pair<const Uniform*,StateAttribute::OverrideValue> UniformPair;
typedef std::vector<UniformPair> UniformVec;
2005-05-10 21:56:05 +08:00
UniformStack() {}
2005-04-13 20:00:28 +08:00
2010-07-11 01:14:59 +08:00
void print(std::ostream& fout) const;
2005-04-13 20:00:28 +08:00
UniformVec uniformVec;
};
2015-02-11 01:04:02 +08:00
struct DefineStack
{
typedef std::vector<StateSet::DefinePair> DefineVec;
2015-08-11 01:42:05 +08:00
DefineStack():
changed(false) {}
2015-02-11 01:04:02 +08:00
void print(std::ostream& fout) const;
bool changed;
DefineVec defineVec;
};
struct DefineMap
{
DefineMap():
changed(false) {}
typedef std::map<std::string, DefineStack> DefineStackMap;
DefineStackMap map;
bool changed;
StateSet::DefineList currentDefines;
bool updateCurrentDefines();
};
2013-10-02 19:28:38 +08:00
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
typedef std::vector<ModeMap> TextureModeMapList;
typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
typedef std::vector<AttributeMap> TextureAttributeMapList;
2015-02-11 01:04:02 +08:00
typedef std::map<std::string, UniformStack> UniformMap;
2013-10-02 19:28:38 +08:00
2015-02-11 01:04:02 +08:00
typedef std::vector< ref_ptr<const Matrix> > MatrixStack;
2013-10-02 19:28:38 +08:00
2015-02-11 01:04:02 +08:00
inline const ModeMap& getModeMap() const {return _modeMap;}
inline const AttributeMap& getAttributeMap() const {return _attributeMap;}
inline const UniformMap& getUniformMap() const {return _uniformMap;}
inline DefineMap& getDefineMap() {return _defineMap;}
inline const DefineMap& getDefineMap() const {return _defineMap;}
inline const TextureModeMapList& getTextureModeMapList() const {return _textureModeMapList;}
inline const TextureAttributeMapList& getTextureAttributeMapList() const {return _textureAttributeMapList;}
std::string getDefineString(const osg::ShaderDefines& shaderDefines);
bool supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements);
bool supportsShaderRequirement(const std::string& shaderRequirement);
2005-04-13 20:00:28 +08:00
2013-10-02 01:01:21 +08:00
protected:
2013-10-02 19:28:38 +08:00
virtual ~State();
GraphicsContext* _graphicsContext;
unsigned int _contextID;
2016-07-23 23:33:39 +08:00
osg::ref_ptr<VertexArrayState> _globalVertexArrayState;
2016-08-06 04:59:34 +08:00
VertexArrayState* _vas;
2016-07-15 22:41:43 +08:00
2013-10-02 19:28:38 +08:00
bool _shaderCompositionEnabled;
bool _shaderCompositionDirty;
osg::ref_ptr<ShaderComposer> _shaderComposer;
osg::Program* _currentShaderCompositionProgram;
StateSet::UniformList _currentShaderCompositionUniformList;
ref_ptr<FrameStamp> _frameStamp;
2018-03-06 17:49:02 +08:00
GLenum _drawBuffer;
GLenum _readBuffer;
2013-10-02 19:28:38 +08:00
ref_ptr<const RefMatrix> _identity;
ref_ptr<const RefMatrix> _initialViewMatrix;
ref_ptr<const RefMatrix> _projection;
ref_ptr<const RefMatrix> _modelView;
ref_ptr<RefMatrix> _modelViewCache;
bool _useModelViewAndProjectionUniforms;
ref_ptr<Uniform> _modelViewMatrixUniform;
ref_ptr<Uniform> _projectionMatrixUniform;
ref_ptr<Uniform> _modelViewProjectionMatrixUniform;
ref_ptr<Uniform> _normalMatrixUniform;
Matrix _initialInverseViewMatrix;
ref_ptr<DisplaySettings> _displaySettings;
bool* _abortRenderingPtr;
CheckForGLErrors _checkGLErrors;
bool _useVertexAttributeAliasing;
VertexAttribAlias _vertexAlias;
VertexAttribAlias _normalAlias;
VertexAttribAlias _colorAlias;
VertexAttribAlias _secondaryColorAlias;
VertexAttribAlias _fogCoordAlias;
VertexAttribAliasList _texCoordAliasList;
Program::AttribBindingList _attributeBindingList;
void setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration);
2016-07-15 22:41:43 +08:00
2005-02-02 23:08:55 +08:00
/** Apply an OpenGL mode if required, passing in mode, enable flag and
2010-04-24 00:35:44 +08:00
* appropriate mode stack. This is a wrapper around \c glEnable() and
* \c glDisable(), that just actually calls these functions if the
* \c enabled flag is different than the current state.
* @return \c true if the state was actually changed. \c false
* otherwise. Notice that a \c false return does not indicate
* an error, it just means that the mode was already set to the
* same value as the \c enabled parameter.
2005-02-02 23:08:55 +08:00
*/
2002-09-02 20:31:35 +08:00
inline bool applyMode(StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
2001-09-20 05:08:56 +08:00
{
2006-02-22 22:31:13 +08:00
if (ms.valid && ms.last_applied_value != enabled)
2001-09-20 05:08:56 +08:00
{
ms.last_applied_value = enabled;
if (enabled) glEnable(mode);
else glDisable(mode);
2005-04-30 04:56:20 +08:00
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
2003-01-22 00:45:36 +08:00
2001-09-20 05:08:56 +08:00
return true;
}
else
return false;
}
2010-01-08 00:49:12 +08:00
inline bool applyModeOnTexUnit(unsigned int unit,StateAttribute::GLMode mode,bool enabled,ModeStack& ms)
{
if (ms.valid && ms.last_applied_value != enabled)
{
if (setActiveTextureUnit(unit))
{
ms.last_applied_value = enabled;
if (enabled) glEnable(mode);
else glDisable(mode);
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(mode);
return true;
}
else
return false;
}
else
return false;
}
2003-01-22 00:45:36 +08:00
2001-09-20 05:08:56 +08:00
/** apply an attribute if required, passing in attribute and appropriate attribute stack */
2002-09-02 20:31:35 +08:00
inline bool applyAttribute(const StateAttribute* attribute,AttributeStack& as)
2001-09-20 05:08:56 +08:00
{
if (as.last_applied_attribute != attribute)
{
2016-01-21 01:49:10 +08:00
if (!as.global_default_attribute.valid()) as.global_default_attribute = attribute->cloneType()->asStateAttribute();
2001-10-15 22:07:54 +08:00
2001-09-20 05:08:56 +08:00
as.last_applied_attribute = attribute;
attribute->apply(*this);
2005-02-02 23:08:55 +08:00
2010-07-02 20:04:20 +08:00
const ShaderComponent* sc = attribute->getShaderComponent();
if (as.last_applied_shadercomponent != sc)
{
as.last_applied_shadercomponent = sc;
_shaderCompositionDirty = true;
}
2005-04-30 04:56:20 +08:00
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
2005-02-02 23:08:55 +08:00
2001-09-20 05:08:56 +08:00
return true;
}
else
return false;
}
2010-01-08 00:49:12 +08:00
inline bool applyAttributeOnTexUnit(unsigned int unit,const StateAttribute* attribute,AttributeStack& as)
{
if (as.last_applied_attribute != attribute)
{
if (setActiveTextureUnit(unit))
{
2016-01-21 01:49:10 +08:00
if (!as.global_default_attribute.valid()) as.global_default_attribute = attribute->cloneType()->asStateAttribute();
2010-01-08 00:49:12 +08:00
as.last_applied_attribute = attribute;
attribute->apply(*this);
2010-07-11 01:14:59 +08:00
const ShaderComponent* sc = attribute->getShaderComponent();
if (as.last_applied_shadercomponent != sc)
{
as.last_applied_shadercomponent = sc;
_shaderCompositionDirty = true;
}
2010-01-08 00:49:12 +08:00
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(attribute);
return true;
}
else
return false;
}
else
return false;
}
2002-09-02 20:31:35 +08:00
inline bool applyGlobalDefaultAttribute(AttributeStack& as)
2001-10-15 22:07:54 +08:00
{
2001-10-15 22:29:40 +08:00
if (as.last_applied_attribute != as.global_default_attribute.get())
2001-10-15 22:07:54 +08:00
{
2001-10-15 22:29:40 +08:00
as.last_applied_attribute = as.global_default_attribute.get();
2003-01-22 00:45:36 +08:00
if (as.global_default_attribute.valid())
{
as.global_default_attribute->apply(*this);
2010-07-11 01:14:59 +08:00
const ShaderComponent* sc = as.global_default_attribute->getShaderComponent();
if (as.last_applied_shadercomponent != sc)
{
as.last_applied_shadercomponent = sc;
_shaderCompositionDirty = true;
}
2005-04-30 04:56:20 +08:00
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
2003-01-22 00:45:36 +08:00
}
2001-10-15 22:07:54 +08:00
return true;
}
else
return false;
}
2005-02-02 23:08:55 +08:00
2010-01-08 00:49:12 +08:00
inline bool applyGlobalDefaultAttributeOnTexUnit(unsigned int unit,AttributeStack& as)
{
if (as.last_applied_attribute != as.global_default_attribute.get())
{
if (setActiveTextureUnit(unit))
{
as.last_applied_attribute = as.global_default_attribute.get();
if (as.global_default_attribute.valid())
{
as.global_default_attribute->apply(*this);
2010-07-11 01:14:59 +08:00
const ShaderComponent* sc = as.global_default_attribute->getShaderComponent();
if (as.last_applied_shadercomponent != sc)
{
as.last_applied_shadercomponent = sc;
_shaderCompositionDirty = true;
}
2010-01-08 00:49:12 +08:00
if (_checkGLErrors==ONCE_PER_ATTRIBUTE) checkGLErrors(as.global_default_attribute.get());
}
return true;
}
else
return false;
}
else
return false;
}
2004-10-13 19:15:50 +08:00
ModeMap _modeMap;
AttributeMap _attributeMap;
2005-04-13 20:00:28 +08:00
UniformMap _uniformMap;
2015-02-11 01:04:02 +08:00
DefineMap _defineMap;
2002-07-09 17:35:42 +08:00
2004-10-13 19:15:50 +08:00
TextureModeMapList _textureModeMapList;
TextureAttributeMapList _textureAttributeMapList;
2005-02-02 23:08:55 +08:00
2005-04-13 20:00:28 +08:00
const Program::PerContextProgram* _lastAppliedProgramObject;
2005-04-04 18:08:15 +08:00
2005-04-13 20:00:28 +08:00
StateSetStack _stateStateStack;
2005-02-02 23:08:55 +08:00
2009-09-23 02:45:24 +08:00
unsigned int _maxTexturePoolSize;
2009-10-03 17:25:23 +08:00
unsigned int _maxBufferObjectPoolSize;
2009-09-23 02:45:24 +08:00
2003-05-07 21:13:13 +08:00
unsigned int _currentActiveTextureUnit;
unsigned int _currentClientActiveTextureUnit;
2009-10-02 04:19:42 +08:00
GLBufferObject* _currentPBO;
2017-07-27 07:54:25 +08:00
GLBufferObject* _currentDIBO;
2017-03-13 19:44:34 +08:00
GLuint _currentVAO;
2007-05-01 14:28:20 +08:00
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
inline ModeMap& getOrCreateTextureModeMap(unsigned int unit)
2005-02-02 23:08:55 +08:00
{
2002-07-09 17:35:42 +08:00
if (unit>=_textureModeMapList.size()) _textureModeMapList.resize(unit+1);
return _textureModeMapList[unit];
}
inline AttributeMap& getOrCreateTextureAttributeMap(unsigned int unit)
2005-02-02 23:08:55 +08:00
{
2002-07-09 17:35:42 +08:00
if (unit>=_textureAttributeMapList.size()) _textureAttributeMapList.resize(unit+1);
return _textureAttributeMapList[unit];
}
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
2005-05-10 21:56:05 +08:00
inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
2015-02-11 01:04:02 +08:00
inline void pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList);
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
2005-05-10 21:56:05 +08:00
inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
2015-02-11 01:04:02 +08:00
inline void popDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList);
2002-07-09 17:35:42 +08:00
inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
2005-05-10 21:56:05 +08:00
inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
2015-02-11 01:04:02 +08:00
inline void applyDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList);
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
inline void applyModeMap(ModeMap& modeMap);
inline void applyAttributeMap(AttributeMap& attributeMap);
2005-05-10 21:56:05 +08:00
inline void applyUniformMap(UniformMap& uniformMap);
2002-07-09 17:35:42 +08:00
2010-01-08 00:49:12 +08:00
inline void applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void applyModeMapOnTexUnit(unsigned int unit,ModeMap& modeMap);
inline void applyAttributeMapOnTexUnit(unsigned int unit,AttributeMap& attributeMap);
2002-09-02 20:31:35 +08:00
void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode,StateAttribute::GLModeValue value);
void haveAppliedMode(ModeMap& modeMap,StateAttribute::GLMode mode);
2002-07-09 17:35:42 +08:00
void haveAppliedAttribute(AttributeMap& attributeMap,const StateAttribute* attribute);
2004-10-13 19:15:50 +08:00
void haveAppliedAttribute(AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member);
2002-09-02 20:31:35 +08:00
bool getLastAppliedMode(const ModeMap& modeMap,StateAttribute::GLMode mode) const;
2004-10-13 19:15:50 +08:00
const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type, unsigned int member) const;
2002-07-09 17:35:42 +08:00
2010-06-01 21:33:58 +08:00
void loadModelViewMatrix();
2002-11-13 19:09:55 +08:00
2016-08-09 00:57:20 +08:00
bool _isSecondaryColorSupported;
bool _isFogCoordSupported;
bool _isVertexBufferObjectSupported;
2016-08-04 22:33:02 +08:00
bool _isVertexArrayObjectSupported;
2016-08-13 01:44:38 +08:00
bool _forceVertexBufferObject;
bool _forceVertexArrayObject;
2016-08-04 22:33:02 +08:00
2010-04-29 05:22:44 +08:00
typedef void (GL_APIENTRY * ActiveTextureProc) (GLenum texture);
typedef void (GL_APIENTRY * FogCoordPointerProc) (GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (GL_APIENTRY * SecondaryColorPointerProc) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (GL_APIENTRY * MultiTexCoord4fProc) (GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (GL_APIENTRY * VertexAttrib4fProc)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (GL_APIENTRY * VertexAttrib4fvProc)(GLuint index, const GLfloat *v);
typedef void (GL_APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
2013-06-28 18:51:22 +08:00
typedef void (GL_APIENTRY * VertexAttribIPointerProc) (unsigned int, GLint, GLenum, GLsizei stride, const GLvoid *pointer);
typedef void (GL_APIENTRY * VertexAttribLPointerProc) (unsigned int, GLint, GLenum, GLsizei stride, const GLvoid *pointer);
2010-04-29 05:22:44 +08:00
typedef void (GL_APIENTRY * EnableVertexAttribProc) (unsigned int);
typedef void (GL_APIENTRY * DisableVertexAttribProc) (unsigned int);
typedef void (GL_APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
typedef void (GL_APIENTRY * DrawArraysInstancedProc)( GLenum mode, GLint first, GLsizei count, GLsizei primcount );
typedef void (GL_APIENTRY * DrawElementsInstancedProc)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount );
2006-08-03 00:14:17 +08:00
bool _extensionProcsInitialized;
2007-05-15 19:25:14 +08:00
GLint _glMaxTextureCoords;
GLint _glMaxTextureUnits;
2006-08-03 00:14:17 +08:00
ActiveTextureProc _glClientActiveTexture;
ActiveTextureProc _glActiveTexture;
2009-10-17 00:26:27 +08:00
MultiTexCoord4fProc _glMultiTexCoord4f;
VertexAttrib4fProc _glVertexAttrib4f;
VertexAttrib4fvProc _glVertexAttrib4fv;
2006-08-03 00:14:17 +08:00
FogCoordPointerProc _glFogCoordPointer;
SecondaryColorPointerProc _glSecondaryColorPointer;
VertexAttribPointerProc _glVertexAttribPointer;
2013-06-28 18:51:22 +08:00
VertexAttribIPointerProc _glVertexAttribIPointer;
VertexAttribLPointerProc _glVertexAttribLPointer;
2006-08-03 00:14:17 +08:00
EnableVertexAttribProc _glEnableVertexAttribArray;
DisableVertexAttribProc _glDisableVertexAttribArray;
2007-05-01 14:28:20 +08:00
BindBufferProc _glBindBuffer;
2009-01-06 22:55:49 +08:00
DrawArraysInstancedProc _glDrawArraysInstanced;
DrawElementsInstancedProc _glDrawElementsInstanced;
2006-08-03 00:14:17 +08:00
2014-12-10 18:38:12 +08:00
osg::ref_ptr<GLExtensions> _glExtensions;
2014-12-05 00:22:31 +08:00
2007-01-30 06:44:29 +08:00
unsigned int _dynamicObjectCount;
osg::ref_ptr<DynamicObjectRenderingCompletedCallback> _completeDynamicObjectRenderingCallback;
2009-09-23 02:45:24 +08:00
2016-10-11 22:14:14 +08:00
AttributeDispatchers _arrayDispatchers;
2011-02-03 20:42:23 +08:00
osg::ref_ptr<GraphicsCostEstimator> _graphicsCostEstimator;
2012-03-22 01:36:20 +08:00
2010-11-11 00:58:58 +08:00
Timer_t _startTick;
Timer_t _gpuTick;
2014-04-23 17:08:26 +08:00
GLuint64 _gpuTimestamp;
int _timestampBits;
2001-01-11 00:32:10 +08:00
};
2002-07-09 17:35:42 +08:00
inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
for(StateSet::ModeList::const_iterator mitr=modeList.begin();
mitr!=modeList.end();
++mitr)
{
2004-09-03 03:10:33 +08:00
// get the mode stack for incoming GLmode {mitr->first}.
2002-07-09 17:35:42 +08:00
ModeStack& ms = modeMap[mitr->first];
if (ms.valueVec.empty())
{
2004-09-03 03:10:33 +08:00
// first pair so simply push incoming pair to back.
2002-07-09 17:35:42 +08:00
ms.valueVec.push_back(mitr->second);
}
2005-02-02 23:08:55 +08:00
else if ((ms.valueVec.back() & StateAttribute::OVERRIDE) && !(mitr->second & StateAttribute::PROTECTED)) // check the existing override flag
2002-07-09 17:35:42 +08:00
{
2004-09-03 03:10:33 +08:00
// push existing back since override keeps the previous value.
2002-07-09 17:35:42 +08:00
ms.valueVec.push_back(ms.valueVec.back());
}
2005-02-02 23:08:55 +08:00
else
2002-07-09 17:35:42 +08:00
{
2004-09-03 03:10:33 +08:00
// no override on so simply push incoming pair to back.
2002-07-09 17:35:42 +08:00
ms.valueVec.push_back(mitr->second);
}
ms.changed = true;
}
}
inline void State::pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
aitr!=attributeList.end();
++aitr)
{
2004-09-03 03:10:33 +08:00
// get the attribute stack for incoming type {aitr->first}.
2002-07-09 17:35:42 +08:00
AttributeStack& as = attributeMap[aitr->first];
if (as.attributeVec.empty())
{
2004-09-03 03:10:33 +08:00
// first pair so simply push incoming pair to back.
2002-07-09 17:35:42 +08:00
as.attributeVec.push_back(
2009-05-12 13:49:36 +08:00
AttributePair(aitr->second.first.get(),aitr->second.second));
2002-07-09 17:35:42 +08:00
}
2005-02-02 23:08:55 +08:00
else if ((as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
2002-07-09 17:35:42 +08:00
{
2004-09-03 03:10:33 +08:00
// push existing back since override keeps the previous value.
2002-07-09 17:35:42 +08:00
as.attributeVec.push_back(as.attributeVec.back());
}
2005-02-02 23:08:55 +08:00
else
2002-07-09 17:35:42 +08:00
{
2004-09-03 03:10:33 +08:00
// no override on so simply push incoming pair to back.
2002-07-09 17:35:42 +08:00
as.attributeVec.push_back(
2009-05-12 13:49:36 +08:00
AttributePair(aitr->second.first.get(),aitr->second.second));
2002-07-09 17:35:42 +08:00
}
as.changed = true;
}
}
2005-05-10 21:56:05 +08:00
inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
{
for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
aitr!=uniformList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
UniformStack& us = uniformMap[aitr->first];
if (us.uniformVec.empty())
{
// first pair so simply push incoming pair to back.
us.uniformVec.push_back(
UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
}
else if ((us.uniformVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
{
// push existing back since override keeps the previous value.
us.uniformVec.push_back(us.uniformVec.back());
}
else
{
// no override on so simply push incoming pair to back.
us.uniformVec.push_back(
UniformStack::UniformPair(aitr->second.first.get(),aitr->second.second));
}
}
}
2015-02-11 01:04:02 +08:00
inline void State::pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList)
{
for(StateSet::DefineList::const_iterator aitr=defineList.begin();
aitr!=defineList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
DefineStack& ds = defineMap.map[aitr->first];
DefineStack::DefineVec& dv = ds.defineVec;
if (dv.empty())
{
// first pair so simply push incoming pair to back.
dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second));
ds.changed = true;
defineMap.changed = true;
}
else if ((ds.defineVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
{
// push existing back since override keeps the previous value.
ds.defineVec.push_back(ds.defineVec.back());
}
else
{
// no override on so simply push incoming pair to back.
dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second));
// if the back of the stack has changed since the last then mark it as changed.
2017-07-31 20:38:18 +08:00
bool changed = (dv[dv.size()-2] != dv.back());
2015-02-11 01:04:02 +08:00
if (changed)
{
ds.changed = true;
defineMap.changed = true;
}
}
}
}
2002-07-09 17:35:42 +08:00
inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
for(StateSet::ModeList::const_iterator mitr=modeList.begin();
mitr!=modeList.end();
++mitr)
{
2004-09-03 03:10:33 +08:00
// get the mode stack for incoming GLmode {mitr->first}.
2002-07-09 17:35:42 +08:00
ModeStack& ms = modeMap[mitr->first];
if (!ms.valueVec.empty())
{
ms.valueVec.pop_back();
}
ms.changed = true;
}
}
inline void State::popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
for(StateSet::AttributeList::const_iterator aitr=attributeList.begin();
aitr!=attributeList.end();
++aitr)
{
2004-09-03 03:10:33 +08:00
// get the attribute stack for incoming type {aitr->first}.
2002-07-09 17:35:42 +08:00
AttributeStack& as = attributeMap[aitr->first];
if (!as.attributeVec.empty())
{
as.attributeVec.pop_back();
}
as.changed = true;
}
}
2005-05-10 21:56:05 +08:00
inline void State::popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
{
for(StateSet::UniformList::const_iterator aitr=uniformList.begin();
aitr!=uniformList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
UniformStack& us = uniformMap[aitr->first];
if (!us.uniformVec.empty())
{
us.uniformVec.pop_back();
}
}
}
2015-02-11 01:04:02 +08:00
inline void State::popDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList)
{
for(StateSet::DefineList::const_iterator aitr=defineList.begin();
aitr!=defineList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
DefineStack& ds = defineMap.map[aitr->first];
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty())
{
// if the stack has less than 2 entries or new back vs old back are different then mark the DefineStack as changed
2017-07-31 20:38:18 +08:00
if ((dv.size() < 2) || (dv[dv.size()-2] != dv.back()))
2015-02-11 01:04:02 +08:00
{
ds.changed = true;
defineMap.changed = true;
}
dv.pop_back();
}
}
}
2002-07-09 17:35:42 +08:00
inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
ModeMap::iterator this_mitr=modeMap.begin();
while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
{
if (this_mitr->first<ds_mitr->first)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(this_mitr->first,ms.global_default_value,ms);
}
}
++this_mitr;
}
else if (ds_mitr->first<this_mitr->first)
{
2005-02-02 23:08:55 +08:00
// ds_mitr->first is a new mode, therefore
2002-07-09 17:35:42 +08:00
// need to insert a new mode entry for ds_mistr->first.
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyMode(ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
++ds_mitr;
}
else
{
2004-09-03 03:10:33 +08:00
// this_mitr & ds_mitr refer to the same mode, check the override
// if any otherwise just apply the incoming mode.
2002-07-09 17:35:42 +08:00
ModeStack& ms = this_mitr->second;
2002-08-05 20:40:24 +08:00
if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
2002-07-09 17:35:42 +08:00
{
2004-09-14 01:19:05 +08:00
// override is on, just treat as a normal apply on modes.
2002-07-09 17:35:42 +08:00
if (ms.changed)
{
ms.changed = false;
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
}
else
{
2004-09-03 03:10:33 +08:00
// no override on or no previous entry, therefore consider incoming mode.
2002-07-09 17:35:42 +08:00
bool new_value = ds_mitr->second & StateAttribute::ON;
if (applyMode(ds_mitr->first,new_value,ms))
{
ms.changed = true;
}
}
++this_mitr;
++ds_mitr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
this_mitr!=modeMap.end();
++this_mitr)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(this_mitr->first,ms.global_default_value,ms);
}
}
2005-02-02 23:08:55 +08:00
}
2002-07-09 17:35:42 +08:00
2004-09-03 03:10:33 +08:00
// iterator over the remaining incoming modes to apply any new mode.
2002-07-09 17:35:42 +08:00
for(;
ds_mitr!=modeList.end();
++ds_mitr)
{
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyMode(ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
}
}
2010-01-08 00:49:12 +08:00
inline void State::applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList)
{
StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
ModeMap::iterator this_mitr=modeMap.begin();
while (this_mitr!=modeMap.end() && ds_mitr!=modeList.end())
{
if (this_mitr->first<ds_mitr->first)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyModeOnTexUnit(unit,this_mitr->first,ms.global_default_value,ms);
}
}
++this_mitr;
}
else if (ds_mitr->first<this_mitr->first)
{
// ds_mitr->first is a new mode, therefore
// need to insert a new mode entry for ds_mistr->first.
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
++ds_mitr;
}
else
{
// this_mitr & ds_mitr refer to the same mode, check the override
// if any otherwise just apply the incoming mode.
ModeStack& ms = this_mitr->second;
if (!ms.valueVec.empty() && (ms.valueVec.back() & StateAttribute::OVERRIDE) && !(ds_mitr->second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on modes.
if (ms.changed)
{
ms.changed = false;
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
}
}
else
{
// no override on or no previous entry, therefore consider incoming mode.
bool new_value = ds_mitr->second & StateAttribute::ON;
if (applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms))
{
ms.changed = true;
}
}
++this_mitr;
++ds_mitr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
this_mitr!=modeMap.end();
++this_mitr)
{
// note GLMode = this_mitr->first
ModeStack& ms = this_mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyModeOnTexUnit(unit,this_mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyModeOnTexUnit(unit,this_mitr->first,ms.global_default_value,ms);
}
}
}
// iterator over the remaining incoming modes to apply any new mode.
for(;
ds_mitr!=modeList.end();
++ds_mitr)
{
ModeStack& ms = modeMap[ds_mitr->first];
bool new_value = ds_mitr->second & StateAttribute::ON;
applyModeOnTexUnit(unit,ds_mitr->first,new_value,ms);
// will need to disable this mode on next apply so set it to changed.
ms.changed = true;
}
}
2002-07-09 17:35:42 +08:00
inline void State::applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
AttributeMap::iterator this_aitr=attributeMap.begin();
while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
{
if (this_aitr->first<ds_aitr->first)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
}
++this_aitr;
}
else if (ds_aitr->first<this_aitr->first)
{
2005-02-02 23:08:55 +08:00
// ds_aitr->first is a new attribute, therefore
2004-09-14 01:19:05 +08:00
// need to insert a new attribute entry for ds_aitr->first.
2002-07-09 17:35:42 +08:00
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttribute(new_attr,as);
as.changed = true;
++ds_aitr;
}
else
{
2004-09-03 03:10:33 +08:00
// this_mitr & ds_mitr refer to the same attribute, check the override
// if any otherwise just apply the incoming attribute
2002-07-09 17:35:42 +08:00
AttributeStack& as = this_aitr->second;
2002-08-05 20:40:24 +08:00
if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
2002-07-09 17:35:42 +08:00
{
2005-04-13 20:00:28 +08:00
// override is on, just treat as a normal apply on attribute.
2002-07-09 17:35:42 +08:00
if (as.changed)
{
as.changed = false;
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
}
else
{
2005-04-13 20:00:28 +08:00
// no override on or no previous entry, therefore consider incoming attribute.
2002-07-09 17:35:42 +08:00
const StateAttribute* new_attr = ds_aitr->second.first.get();
if (applyAttribute(new_attr,as))
{
as.changed = true;
}
}
++this_aitr;
++ds_aitr;
}
}
2005-04-13 20:00:28 +08:00
// iterator over the remaining state attributes to apply any previous changes.
2002-07-09 17:35:42 +08:00
for(;
this_aitr!=attributeMap.end();
++this_aitr)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
}
2005-02-02 23:08:55 +08:00
}
2002-07-09 17:35:42 +08:00
2005-04-13 20:00:28 +08:00
// iterator over the remaining incoming attribute to apply any new attribute.
2002-07-09 17:35:42 +08:00
for(;
ds_aitr!=attributeList.end();
++ds_aitr)
{
2005-02-02 23:08:55 +08:00
// ds_aitr->first is a new attribute, therefore
2004-09-14 01:19:05 +08:00
// need to insert a new attribute entry for ds_aitr->first.
2002-07-09 17:35:42 +08:00
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttribute(new_attr,as);
// will need to update this attribute on next apply so set it to changed.
as.changed = true;
}
}
2010-01-08 00:49:12 +08:00
inline void State::applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList)
{
StateSet::AttributeList::const_iterator ds_aitr=attributeList.begin();
AttributeMap::iterator this_aitr=attributeMap.begin();
while (this_aitr!=attributeMap.end() && ds_aitr!=attributeList.end())
{
if (this_aitr->first<ds_aitr->first)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttributeOnTexUnit(unit,new_attr,as);
}
else
{
applyGlobalDefaultAttributeOnTexUnit(unit,as);
}
}
++this_aitr;
}
else if (ds_aitr->first<this_aitr->first)
{
// ds_aitr->first is a new attribute, therefore
// need to insert a new attribute entry for ds_aitr->first.
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttributeOnTexUnit(unit,new_attr,as);
as.changed = true;
++ds_aitr;
}
else
{
// this_mitr & ds_mitr refer to the same attribute, check the override
// if any otherwise just apply the incoming attribute
AttributeStack& as = this_aitr->second;
if (!as.attributeVec.empty() && (as.attributeVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on attribute.
if (as.changed)
{
as.changed = false;
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttributeOnTexUnit(unit,new_attr,as);
}
}
else
{
// no override on or no previous entry, therefore consider incoming attribute.
const StateAttribute* new_attr = ds_aitr->second.first.get();
if (applyAttributeOnTexUnit(unit,new_attr,as))
{
as.changed = true;
}
}
++this_aitr;
++ds_aitr;
}
}
// iterator over the remaining state attributes to apply any previous changes.
for(;
this_aitr!=attributeMap.end();
++this_aitr)
{
// note attribute type = this_aitr->first
AttributeStack& as = this_aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttributeOnTexUnit(unit,new_attr,as);
}
else
{
applyGlobalDefaultAttributeOnTexUnit(unit,as);
}
}
}
// iterator over the remaining incoming attribute to apply any new attribute.
for(;
ds_aitr!=attributeList.end();
++ds_aitr)
{
// ds_aitr->first is a new attribute, therefore
// need to insert a new attribute entry for ds_aitr->first.
AttributeStack& as = attributeMap[ds_aitr->first];
const StateAttribute* new_attr = ds_aitr->second.first.get();
applyAttributeOnTexUnit(unit,new_attr,as);
// will need to update this attribute on next apply so set it to changed.
as.changed = true;
}
}
2005-05-10 21:56:05 +08:00
inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList)
{
if (!_lastAppliedProgramObject) return;
StateSet::UniformList::const_iterator ds_aitr=uniformList.begin();
UniformMap::iterator this_aitr=uniformMap.begin();
while (this_aitr!=uniformMap.end() && ds_aitr!=uniformList.end())
{
if (this_aitr->first<ds_aitr->first)
{
// note attribute type = this_aitr->first
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty())
{
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
++this_aitr;
}
else if (ds_aitr->first<this_aitr->first)
{
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
++ds_aitr;
}
else
{
// this_mitr & ds_mitr refer to the same attribute, check the override
// if any otherwise just apply the incoming attribute
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty() && (as.uniformVec.back().second & StateAttribute::OVERRIDE) && !(ds_aitr->second.second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on uniform.
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
else
{
// no override on or no previous entry, therefore consider incoming attribute.
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
}
++this_aitr;
++ds_aitr;
}
}
// iterator over the remaining state attributes to apply any previous changes.
for(;
this_aitr!=uniformMap.end();
++this_aitr)
{
// note attribute type = this_aitr->first
UniformStack& as = this_aitr->second;
if (!as.uniformVec.empty())
{
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
}
// iterator over the remaining incoming attribute to apply any new attribute.
for(;
ds_aitr!=uniformList.end();
++ds_aitr)
{
_lastAppliedProgramObject->apply(*(ds_aitr->second.first.get()));
}
}
2015-02-11 01:04:02 +08:00
inline void State::applyDefineList(DefineMap& defineMap, const StateSet::DefineList& defineList)
{
StateSet::DefineList::const_iterator dl_itr = defineList.begin();
DefineMap::DefineStackMap::iterator dm_itr = defineMap.map.begin();
defineMap.changed = false;
defineMap.currentDefines.clear();
while (dm_itr!=defineMap.map.end() && dl_itr!=defineList.end())
{
if (dm_itr->first<dl_itr->first)
{
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
++dm_itr;
}
else if (dl_itr->first<dm_itr->first)
{
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
++dl_itr;
}
else
{
// this_mitr & ds_mitr refer to the same mode, check the override
// if any otherwise just apply the incoming mode.
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::OVERRIDE)!=0 && !(dl_itr->second.second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on modes.
if ((dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
}
else
{
// no override on or no previous entry, therefore consider incoming mode.
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
}
++dm_itr;
++dl_itr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
dm_itr!=defineMap.map.end();
++dm_itr)
{
// note GLMode = this_mitr->first
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
}
// iterator over the remaining incoming modes to apply any new mode.
for(;
dl_itr!=defineList.end();
++dl_itr)
{
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
}
}
2002-07-09 17:35:42 +08:00
inline void State::applyModeMap(ModeMap& modeMap)
{
for(ModeMap::iterator mitr=modeMap.begin();
mitr!=modeMap.end();
++mitr)
{
// note GLMode = mitr->first
ModeStack& ms = mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyMode(mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyMode(mitr->first,ms.global_default_value,ms);
}
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
}
2005-02-02 23:08:55 +08:00
}
2002-07-09 17:35:42 +08:00
}
2010-01-08 00:49:12 +08:00
inline void State::applyModeMapOnTexUnit(unsigned int unit,ModeMap& modeMap)
{
for(ModeMap::iterator mitr=modeMap.begin();
mitr!=modeMap.end();
++mitr)
{
// note GLMode = mitr->first
ModeStack& ms = mitr->second;
if (ms.changed)
{
ms.changed = false;
if (!ms.valueVec.empty())
{
bool new_value = ms.valueVec.back() & StateAttribute::ON;
applyModeOnTexUnit(unit,mitr->first,new_value,ms);
}
else
{
// assume default of disabled.
applyModeOnTexUnit(unit,mitr->first,ms.global_default_value,ms);
}
}
}
}
2002-07-09 17:35:42 +08:00
inline void State::applyAttributeMap(AttributeMap& attributeMap)
{
for(AttributeMap::iterator aitr=attributeMap.begin();
aitr!=attributeMap.end();
++aitr)
{
AttributeStack& as = aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttribute(new_attr,as);
}
else
{
applyGlobalDefaultAttribute(as);
}
2005-02-02 23:08:55 +08:00
2002-07-09 17:35:42 +08:00
}
2005-02-02 23:08:55 +08:00
}
2002-07-09 17:35:42 +08:00
}
2010-01-08 00:49:12 +08:00
inline void State::applyAttributeMapOnTexUnit(unsigned int unit,AttributeMap& attributeMap)
{
for(AttributeMap::iterator aitr=attributeMap.begin();
aitr!=attributeMap.end();
++aitr)
{
AttributeStack& as = aitr->second;
if (as.changed)
{
as.changed = false;
if (!as.attributeVec.empty())
{
const StateAttribute* new_attr = as.attributeVec.back().first;
applyAttributeOnTexUnit(unit,new_attr,as);
}
else
{
applyGlobalDefaultAttributeOnTexUnit(unit,as);
}
}
}
}
2005-05-10 21:56:05 +08:00
inline void State::applyUniformMap(UniformMap& uniformMap)
{
if (!_lastAppliedProgramObject) return;
for(UniformMap::iterator aitr=uniformMap.begin();
aitr!=uniformMap.end();
++aitr)
{
UniformStack& as = aitr->second;
if (!as.uniformVec.empty())
{
_lastAppliedProgramObject->apply(*as.uniformVec.back().first);
}
}
}
2010-01-08 00:49:12 +08:00
inline bool State::setActiveTextureUnit( unsigned int unit )
{
if (unit!=_currentActiveTextureUnit)
{
if (_glActiveTexture && unit < (unsigned int)(maximum(_glMaxTextureCoords,_glMaxTextureUnits)) )
{
_glActiveTexture(GL_TEXTURE0+unit);
_currentActiveTextureUnit = unit;
}
else
{
return unit==0;
}
}
return true;
}
2006-09-19 04:54:48 +08:00
2016-08-05 05:00:58 +08:00
2014-12-05 00:22:31 +08:00
// forward declare speciailization of State::get() method
2014-12-10 18:38:12 +08:00
template<> inline GLExtensions* State::get<GLExtensions>() { return _glExtensions.get(); }
template<> inline const GLExtensions* State::get<GLExtensions>() const { return _glExtensions.get(); }
2015-09-23 17:47:34 +08:00
template<> inline void State::set<GLExtensions>(GLExtensions* ptr) { _glExtensions = ptr; }
2014-12-05 00:22:31 +08:00
2002-02-03 20:33:41 +08:00
}
2001-01-11 00:32:10 +08:00
#endif