/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS #include #include #endif using namespace osg; // static cache of deleted display lists which can only // by completely deleted once the appropriate OpenGL context // is set. Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below. typedef std::list DisplayListList; typedef std::map DeletedDisplayListCache; #ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS static OpenThreads::Mutex s_mutex_deletedDisplayListCache; #endif static DeletedDisplayListCache s_deletedDisplayListCache; void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj) { if (globj!=0) { #ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); #endif // insert the globj into the cache for the appropriate context. s_deletedDisplayListCache[contextID].push_back(globj); } } /** flush all the cached display list which need to be deleted * in the OpenGL context related to contextID.*/ void Drawable::flushDeletedDisplayLists(unsigned int contextID,double /*currentTime*/, double& availableTime) { // if no time available don't try to flush objects. if (availableTime<=0.0) return; const osg::Timer& timer = *osg::Timer::instance(); osg::Timer_t start_tick = timer.tick(); double elapsedTime = 0.0; unsigned int noDeleted = 0; { #ifdef THREAD_SAFE_GLOBJECT_DELETE_LISTS OpenThreads::ScopedLock lock(s_mutex_deletedDisplayListCache); #endif DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID); if (citr!=s_deletedDisplayListCache.end()) { DisplayListList& dll = citr->second; for(DisplayListList::iterator ditr=dll.begin(); ditr!=dll.end() && elapsedTimesetNumChildrenRequiringUpdateTraversal((*itr)->getNumChildrenRequiringUpdateTraversal()+delta); } } } struct ComputeBound : public Drawable::PrimitiveFunctor { ComputeBound():_vertices(0) {} virtual void setVertexArray(unsigned int,const Vec2*) { notify(WARN)<<"ComputeBound does not support Vec2* vertex arrays"<0;--count,++vert) { _bb.expandBy(*vert); } } } virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices) { if (_vertices) { for(;count>0;--count,++indices) { _bb.expandBy(_vertices[*indices]); } } } virtual void drawElements(GLenum,GLsizei count,const GLushort* indices) { if (_vertices) { for(;count>0;--count,++indices) { _bb.expandBy(_vertices[*indices]); } } } virtual void drawElements(GLenum,GLsizei count,const GLuint* indices) { if (_vertices) { for(;count>0;--count,++indices) { _bb.expandBy(_vertices[*indices]); } } } virtual void begin(GLenum) {} virtual void vertex(const Vec2& vert) { _bb.expandBy(osg::Vec3(vert[0],vert[1],0.0f)); } virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); } virtual void vertex(const Vec4& vert) { if (vert[3]!=0.0f) _bb.expandBy(osg::Vec3(vert[0],vert[1],vert[2])/vert[3]); } virtual void vertex(float x,float y) { _bb.expandBy(x,y,1.0f); } virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); } virtual void vertex(float x,float y,float z,float w) { if (w!=0.0f) _bb.expandBy(x/w,y/w,z/w); } virtual void end() {} const Vec3* _vertices; BoundingBox _bb; }; bool Drawable::computeBound() const { ComputeBound cb; Drawable* non_const_this = const_cast(this); non_const_this->accept(cb); _bbox = cb._bb; _bbox_computed = true; return true; } void Drawable::setBound(const BoundingBox& bb) const { _bbox = bb; _bbox_computed = true; } ////////////////////////////////////////////////////////////////////////////// // // Extension support // typedef buffered_value< ref_ptr > BufferedExtensions; static BufferedExtensions s_extensions; Drawable::Extensions* Drawable::getExtensions(unsigned int contextID,bool createIfNotInitalized) { if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Drawable::Extensions; return s_extensions[contextID].get(); } void Drawable::setExtensions(unsigned int contextID,Extensions* extensions) { s_extensions[contextID] = extensions; } Drawable::Extensions::Extensions() { setupGLExtenions(); } Drawable::Extensions::Extensions(const Extensions& rhs): Referenced() { _isVertexProgramSupported = rhs._isVertexProgramSupported; _isSecondaryColorSupported = rhs._isSecondaryColorSupported; _isFogCoordSupported = rhs._isFogCoordSupported; _isMultiTexSupported = rhs._isMultiTexSupported; _isOcclusionQuerySupported = rhs._isOcclusionQuerySupported; _glFogCoordfv = rhs._glFogCoordfv; _glSecondaryColor3ubv = rhs._glSecondaryColor3ubv; _glSecondaryColor3fv = rhs._glSecondaryColor3fv; _glMultiTexCoord1f = rhs._glMultiTexCoord1f; _glMultiTexCoord2fv = rhs._glMultiTexCoord2fv; _glMultiTexCoord3fv = rhs._glMultiTexCoord3fv; _glMultiTexCoord4fv = rhs._glMultiTexCoord4fv; _glVertexAttrib1s = rhs._glVertexAttrib1s; _glVertexAttrib1f = rhs._glVertexAttrib1f; _glVertexAttrib2fv = rhs._glVertexAttrib2fv; _glVertexAttrib3fv = rhs._glVertexAttrib3fv; _glVertexAttrib4fv = rhs._glVertexAttrib4fv; _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv; _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv; _glGenBuffers = rhs._glGenBuffers; _glBindBuffer = rhs._glBindBuffer; _glBufferData = rhs._glBufferData; _glBufferSubData = rhs._glBufferSubData; _glDeleteBuffers = rhs._glDeleteBuffers; _glGenOcclusionQueries = rhs._glGenOcclusionQueries; _glDeleteOcclusionQueries = rhs._glDeleteOcclusionQueries; _glIsOcclusionQuery = rhs._glIsOcclusionQuery; _glBeginOcclusionQuery = rhs._glBeginOcclusionQuery; _glEndOcclusionQuery = rhs._glEndOcclusionQuery; _glGetOcclusionQueryiv = rhs._glGetOcclusionQueryiv; _glGetOcclusionQueryuiv = rhs._glGetOcclusionQueryuiv; _gl_gen_queries_arb = rhs._gl_gen_queries_arb; _gl_delete_queries_arb = rhs._gl_delete_queries_arb; _gl_is_query_arb = rhs._gl_is_query_arb; _gl_begin_query_arb = rhs._gl_begin_query_arb; _gl_end_query_arb = rhs._gl_end_query_arb; _gl_get_queryiv_arb = rhs._gl_get_queryiv_arb; _gl_get_query_objectiv_arb = rhs._gl_get_query_objectiv_arb; _gl_get_query_objectuiv_arb = rhs._gl_get_query_objectuiv_arb; } void Drawable::Extensions::lowestCommonDenominator(const Extensions& rhs) { if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false; if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false; if (!rhs._isFogCoordSupported) _isFogCoordSupported = false; if (!rhs._isMultiTexSupported) _isMultiTexSupported = false; if (!rhs._isOcclusionQuerySupported) _isOcclusionQuerySupported = false; if (!rhs._isARBOcclusionQuerySupported) _isARBOcclusionQuerySupported = false; if (!rhs._glFogCoordfv) _glFogCoordfv = 0; if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0; if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0; if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0; if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0; if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0; if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0; if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0; if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0; if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0; if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0; if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0; if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0; if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0; if (!rhs._glGenBuffers) _glGenBuffers = 0; if (!rhs._glBindBuffer) _glBindBuffer = 0; if (!rhs._glBufferData) _glBufferData = 0; if (!rhs._glBufferSubData) _glBufferSubData = 0; if (!rhs._glDeleteBuffers) _glDeleteBuffers = 0; if (!rhs._glGenOcclusionQueries) _glGenOcclusionQueries = 0; if (!rhs._glDeleteOcclusionQueries) _glDeleteOcclusionQueries = 0; if (!rhs._glIsOcclusionQuery) _glIsOcclusionQuery = 0; if (!rhs._glBeginOcclusionQuery) _glBeginOcclusionQuery = 0; if (!rhs._glEndOcclusionQuery) _glEndOcclusionQuery = 0; if (!rhs._glGetOcclusionQueryiv) _glGetOcclusionQueryiv = 0; if (!rhs._glGetOcclusionQueryuiv) _glGetOcclusionQueryuiv = 0; if (!rhs._gl_gen_queries_arb) _gl_gen_queries_arb = 0; if (!rhs._gl_delete_queries_arb) _gl_delete_queries_arb = 0; if (!rhs._gl_is_query_arb) _gl_is_query_arb = 0; if (!rhs._gl_begin_query_arb) _gl_begin_query_arb = 0; if (!rhs._gl_end_query_arb) _gl_end_query_arb = 0; if (!rhs._gl_get_queryiv_arb) _gl_get_queryiv_arb = 0; if (!rhs._gl_get_query_objectiv_arb) _gl_get_query_objectiv_arb = 0; if (!rhs._gl_get_query_objectuiv_arb) _gl_get_query_objectuiv_arb = 0; } void Drawable::Extensions::setupGLExtenions() { _isVertexProgramSupported = isGLExtensionSupported("GL_ARB_vertex_program"); _isSecondaryColorSupported = isGLExtensionSupported("GL_EXT_secondary_color"); _isFogCoordSupported = isGLExtensionSupported("GL_EXT_fog_coord"); _isMultiTexSupported = isGLExtensionSupported("GL_ARB_multitexture"); _isOcclusionQuerySupported = osg::isGLExtensionSupported( "GL_NV_occlusion_query" ); _isARBOcclusionQuerySupported = osg::isGLExtensionSupported( "GL_ARB_occlusion_query" ); _glFogCoordfv = ((FogCoordProc)osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT")); _glSecondaryColor3ubv = ((SecondaryColor3ubvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT")); _glSecondaryColor3fv = ((SecondaryColor3fvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT")); _glMultiTexCoord1f = ((MultiTexCoord1fProc)osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB")); _glMultiTexCoord2fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB")); _glMultiTexCoord3fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB")); _glMultiTexCoord4fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB")); _glVertexAttrib1s = ((VertexAttrib1sProc)osg::getGLExtensionFuncPtr("glVertexAttrib1s","glVertexAttrib1sARB")); _glVertexAttrib1f = ((VertexAttrib1fProc)osg::getGLExtensionFuncPtr("glVertexAttrib1f","glVertexAttrib1fARB")); _glVertexAttrib2fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib2fv","glVertexAttrib2fvARB")); _glVertexAttrib3fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib3fv","glVertexAttrib3fvARB")); _glVertexAttrib4fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4fv","glVertexAttrib4fvARB")); _glVertexAttrib4ubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4ubv","glVertexAttrib4ubvARB")); _glVertexAttrib4Nubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4Nubv","glVertexAttrib4NubvARB")); _glGenBuffers = ((GenBuffersProc)osg::getGLExtensionFuncPtr("glGenBuffers","glGenBuffersARB")); _glBindBuffer = ((BindBufferProc)osg::getGLExtensionFuncPtr("glBindBuffer","glBindBufferARB")); _glBufferData = ((BufferDataProc)osg::getGLExtensionFuncPtr("glBufferData","glBufferDataARB")); _glBufferSubData = ((BufferSubDataProc)osg::getGLExtensionFuncPtr("glBufferSubData","glBufferSubDataARB")); _glDeleteBuffers = ((DeleteBuffersProc)osg::getGLExtensionFuncPtr("glDeleteBuffers","glDeleteBuffersARB")); _glGenOcclusionQueries = ((GenOcclusionQueriesProc)osg::getGLExtensionFuncPtr("glGenOcclusionQueries","glGenOcclusionQueriesNV")); _glDeleteOcclusionQueries = ((DeleteOcclusionQueriesProc)osg::getGLExtensionFuncPtr("glDeleteOcclusionQueries","glDeleteOcclusionQueriesNV")); _glIsOcclusionQuery = ((IsOcclusionQueryProc)osg::getGLExtensionFuncPtr("glIsOcclusionQuery","_glIsOcclusionQueryNV")); _glBeginOcclusionQuery = ((BeginOcclusionQueryProc)osg::getGLExtensionFuncPtr("glBeginOcclusionQuery","glBeginOcclusionQueryNV")); _glEndOcclusionQuery = ((EndOcclusionQueryProc)osg::getGLExtensionFuncPtr("glEndOcclusionQuery","glEndOcclusionQueryNV")); _glGetOcclusionQueryiv = ((GetOcclusionQueryivProc)osg::getGLExtensionFuncPtr("glGetOcclusionQueryiv","glGetOcclusionQueryivNV")); _glGetOcclusionQueryuiv = ((GetOcclusionQueryuivProc)osg::getGLExtensionFuncPtr("glGetOcclusionQueryuiv","glGetOcclusionQueryuivNV")); _gl_gen_queries_arb = (GenQueriesProc)osg::getGLExtensionFuncPtr("glGenQueries", "glGenQueriesARB"); _gl_delete_queries_arb = (DeleteQueriesProc)osg::getGLExtensionFuncPtr("glDeleteQueries", "glDeleteQueriesARB"); _gl_is_query_arb = (IsQueryProc)osg::getGLExtensionFuncPtr("glIsQuery", "glIsQueryARB"); _gl_begin_query_arb = (BeginQueryProc)osg::getGLExtensionFuncPtr("glBeginQuery", "glBeginQueryARB"); _gl_end_query_arb = (EndQueryProc)osg::getGLExtensionFuncPtr("glEndQuery", "glEndQueryARB"); _gl_get_queryiv_arb = (GetQueryivProc)osg::getGLExtensionFuncPtr("glGetQueryiv", "glGetQueryivARB"); _gl_get_query_objectiv_arb = (GetQueryObjectivProc)osg::getGLExtensionFuncPtr("glGetQueryObjectiv","glGetQueryObjectivARB"); _gl_get_query_objectuiv_arb = (GetQueryObjectuivProc)osg::getGLExtensionFuncPtr("glGetQueryObjectuiv","glGetQueryObjectuivARB"); } void Drawable::Extensions::glFogCoordfv(const GLfloat* coord) const { if (_glFogCoordfv) { _glFogCoordfv(coord); } else { notify(WARN)<<"Error: glFogCoordfv not supported by OpenGL driver"<