diff --git a/include/osgText/Text b/include/osgText/Text index d9d4c7c88..c5aea903e 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -280,9 +280,6 @@ public: virtual void accept(osg::PrimitiveFunctor& pf) const; - /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ - virtual void setThreadSafeRefUnref(bool threadSafe); - /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); diff --git a/include/osgText/Text3D b/include/osgText/Text3D index 584c100c3..4675aca06 100644 --- a/include/osgText/Text3D +++ b/include/osgText/Text3D @@ -91,10 +91,6 @@ class OSGTEXT_EXPORT Text3D : public osgText::TextBase /** accept a PrimtiveFunctor and call its methods to tell it about the interal primtives that this Drawable has.*/ virtual void accept(osg::PrimitiveFunctor& pf) const; - - /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ - virtual void setThreadSafeRefUnref(bool threadSafe); - /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); diff --git a/include/osgText/TextBase b/include/osgText/TextBase index 8a7f1e92d..753e72b05 100644 --- a/include/osgText/TextBase +++ b/include/osgText/TextBase @@ -253,8 +253,10 @@ public: /** Get the number of wrapped lines - only valid after computeGlyphRepresentation() has been called, returns 0 otherwise */ unsigned int getLineCount() const { return _lineCount; } - /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ - virtual void setThreadSafeRefUnref(bool threadSafe); + /** Immediately compile this \c Drawable into an OpenGL Display List/VertexBufferObjects. + * @note Operation is ignored if \c _useDisplayList is \c false or VertexBufferObjects are not used. + */ + virtual void compileGLObjects(osg::RenderInfo& renderInfo) const; /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); @@ -278,6 +280,12 @@ protected: virtual ~TextBase(); + void initArraysAndBuffers(); + +#ifdef NEW_APPROACH + osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo) const; +#endif + bool computeMatrix(osg::Matrix& matrix, osg::State* state=0) const; void positionCursor(const osg::Vec2 & endOfLine_coords, osg::Vec2 & cursor, unsigned int linelength); @@ -327,6 +335,9 @@ protected: void setupDecoration(); + osg::ref_ptr _vbo; + osg::ref_ptr _ebo; + Coords _coords; Coords _normals; ColorCoords _colorCoords; diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 787d21086..abbc559a3 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -1230,20 +1230,10 @@ void Text::accept(osg::PrimitiveFunctor& pf) const } } - -void Text::setThreadSafeRefUnref(bool threadSafe) -{ - TextBase::setThreadSafeRefUnref(threadSafe); - - getActiveFont()->setThreadSafeRefUnref(threadSafe); -} - void Text::resizeGLObjectBuffers(unsigned int maxSize) { TextBase::resizeGLObjectBuffers(maxSize); - getActiveFont()->resizeGLObjectBuffers(maxSize); - for(TextureGlyphQuadMap::iterator itr = _textureGlyphQuadMap.begin(); itr != _textureGlyphQuadMap.end(); ++itr) @@ -1252,13 +1242,10 @@ void Text::resizeGLObjectBuffers(unsigned int maxSize) } } - void Text::releaseGLObjects(osg::State* state) const { TextBase::releaseGLObjects(state); - getActiveFont()->releaseGLObjects(state); - for(TextureGlyphQuadMap::const_iterator itr = _textureGlyphQuadMap.begin(); itr != _textureGlyphQuadMap.end(); ++itr) @@ -1338,6 +1325,8 @@ void Text::drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, co const TexCoords& texcoords = _texcoords; const ColorCoords& colors = _colorCoords; + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + if (coords.valid() && !coords->empty()) { state.setVertexPointer(coords.get()); @@ -1353,7 +1342,7 @@ void Text::drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, co state.setColorPointer(colors.get()); } - glyphquad._primitives[0]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[0]->draw(state, usingVertexBufferObjects); } } @@ -1405,6 +1394,8 @@ void Text::drawTextWithBackdrop(osg::State& state, const osg::Vec4& colorMultipl state.setVertexPointer(_coords.get()); state.setTexCoordPointer( 0, _texcoords.get()); + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); titr!=_textureGlyphQuadMap.end(); ++titr) @@ -1436,7 +1427,7 @@ void Text::drawTextWithBackdrop(osg::State& state, const osg::Vec4& colorMultipl for( ; backdrop_index < max_backdrop_index; backdrop_index++) { - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } } @@ -1449,6 +1440,8 @@ void Text::renderWithPolygonOffset(osg::State& state, const osg::Vec4& colorMult { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + if (!osg::PolygonOffset::areFactorAndUnitsMultipliersSet()) { osg::PolygonOffset::setFactorAndUnitsMultipliersUsingBestGuessForDriver(); @@ -1491,7 +1484,7 @@ void Text::renderWithPolygonOffset(osg::State& state, const osg::Vec4& colorMult for( ; backdrop_index < max_backdrop_index; backdrop_index++) { glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), osg::PolygonOffset::getUnitsMultiplier() * (max_backdrop_index-backdrop_index) ); - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } // Reset the polygon offset so the foreground text is on top @@ -1511,6 +1504,8 @@ void Text::renderWithNoDepthBuffer(osg::State& state, const osg::Vec4& colorMult { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + glPushAttrib(GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); @@ -1547,7 +1542,7 @@ void Text::renderWithNoDepthBuffer(osg::State& state, const osg::Vec4& colorMult for( ; backdrop_index < max_backdrop_index; backdrop_index++) { - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } drawForegroundText(state, glyphquad, colorMultiplier); @@ -1564,6 +1559,8 @@ void Text::renderWithDepthRange(osg::State& state, const osg::Vec4& colorMultipl { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + // Hmmm, the man page says GL_VIEWPORT_BIT for Depth range (near and far) // but experimentally, GL_DEPTH_BUFFER_BIT for glDepthRange. // glPushAttrib(GL_VIEWPORT_BIT); @@ -1603,7 +1600,7 @@ void Text::renderWithDepthRange(osg::State& state, const osg::Vec4& colorMultipl { double offset = double(max_backdrop_index-backdrop_index)*0.0001; glDepthRange( offset, 1.0+offset); - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } glDepthRange(0.0, 1.0); @@ -1620,6 +1617,9 @@ void Text::renderWithDepthRange(osg::State& state, const osg::Vec4& colorMultipl void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMultiplier) const { #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) + + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + /* Here are the steps: * 1) Disable drawing color * 2) Enable the stencil buffer @@ -1693,11 +1693,11 @@ void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMult for( ; backdrop_index < max_backdrop_index; backdrop_index++) { - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } // Draw the foreground text - glyphquad._primitives[0]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[0]->draw(state, usingVertexBufferObjects); } @@ -1753,7 +1753,7 @@ void Text::renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMult for( ; backdrop_index < max_backdrop_index; backdrop_index++) { - glyphquad._primitives[backdrop_index]->draw(state, _useVertexBufferObjects); + glyphquad._primitives[backdrop_index]->draw(state, usingVertexBufferObjects); } drawForegroundText(state, glyphquad, colorMultiplier); diff --git a/src/osgText/Text3D.cpp b/src/osgText/Text3D.cpp index 3040193f0..d5d749a9f 100644 --- a/src/osgText/Text3D.cpp +++ b/src/osgText/Text3D.cpp @@ -214,7 +214,6 @@ String::iterator Text3D::computeLastCharacterOnLine(osg::Vec2& cursor, String::i void Text3D::copyAndOffsetPrimitiveSets(osg::Geometry::PrimitiveSetList& dest_PrimitiveSetList, osg::Geometry::PrimitiveSetList& src_PrimitiveSetList, unsigned int offset) { - for(osg::Geometry::PrimitiveSetList::const_iterator pitr = src_PrimitiveSetList.begin(); pitr != src_PrimitiveSetList.end(); ++pitr) @@ -222,6 +221,7 @@ void Text3D::copyAndOffsetPrimitiveSets(osg::Geometry::PrimitiveSetList& dest_Pr const osg::PrimitiveSet* src_primset = pitr->get(); osg::PrimitiveSet* dst_primset = osg::clone(src_primset, osg::CopyOp::DEEP_COPY_ALL); dst_primset->offsetIndices(offset); + dst_primset->setBufferObject(_ebo.get()); dest_PrimitiveSetList.push_back(dst_primset); } } @@ -389,8 +389,27 @@ void Text3D::computeGlyphRepresentation() computePositions(); - if (!_coords) _coords = new osg::Vec3Array; - if (!_normals) _normals = new osg::Vec3Array; + if (!_coords) + { + OSG_NOTICE<<"void Text3D::computeGlyphRepresentation() _coords = new osg::Vec3Array;"<setVertexBufferObject(_vbo.get()); + } + else + { + _coords->clear(); + } + + if (!_normals) + { + OSG_NOTICE<<"void Text3D::computeGlyphRepresentation() _normals = new osg::Vec3Array;"<setVertexBufferObject(_vbo.get()); + } + else + { + _normals->clear(); + } _frontPrimitiveSetList.clear(); _wallPrimitiveSetList.clear(); @@ -456,6 +475,8 @@ void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State & state = *renderInfo.getState(); + bool usingVertexBufferObjects = state.useVertexBufferObject(_supportsVertexBufferObjects && _useVertexBufferObjects); + // ** save the previous modelview matrix osg::Matrix previous_modelview(state.getModelViewMatrix()); @@ -494,7 +515,7 @@ void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const itr != _decorationPrimitives.end(); ++itr) { - (*itr)->draw(state, _useVertexBufferObjects); + (*itr)->draw(state, usingVertexBufferObjects); } } } @@ -523,21 +544,21 @@ void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const for(osg::Geometry::PrimitiveSetList::const_iterator itr=_frontPrimitiveSetList.begin(), end = _frontPrimitiveSetList.end(); itr!=end; ++itr) { - (*itr)->draw(state, false); + (*itr)->draw(state, usingVertexBufferObjects); } if (wallStateSet!=frontStateSet) state.apply(wallStateSet); for(osg::Geometry::PrimitiveSetList::const_iterator itr=_wallPrimitiveSetList.begin(), end = _wallPrimitiveSetList.end(); itr!=end; ++itr) { - (*itr)->draw(state, false); + (*itr)->draw(state, usingVertexBufferObjects); } if (backStateSet!=wallStateSet) state.apply(backStateSet); for(osg::Geometry::PrimitiveSetList::const_iterator itr=_backPrimitiveSetList.begin(), end = _backPrimitiveSetList.end(); itr!=end; ++itr) { - (*itr)->draw(state, false); + (*itr)->draw(state, usingVertexBufferObjects); } } @@ -548,27 +569,44 @@ void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const } } -void Text3D::setThreadSafeRefUnref(bool threadSafe) -{ - TextBase::setThreadSafeRefUnref(threadSafe); - - if (_font.valid()) _font->setThreadSafeRefUnref(threadSafe); -} - void Text3D::resizeGLObjectBuffers(unsigned int maxSize) { - OSG_INFO<<"Text3D::resizeGLObjectBuffers("<resizeGLObjectBuffers(maxSize); + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_frontPrimitiveSetList.begin(), end = _frontPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } + + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_wallPrimitiveSetList.begin(), end = _wallPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } + + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_backPrimitiveSetList.begin(), end = _backPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } } void Text3D::releaseGLObjects(osg::State* state) const { TextBase::releaseGLObjects(state); - if (_font.valid()) _font->releaseGLObjects(state); + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_frontPrimitiveSetList.begin(), end = _frontPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->releaseGLObjects(state); + } + + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_wallPrimitiveSetList.begin(), end = _wallPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->releaseGLObjects(state); + } + + for(osg::Geometry::PrimitiveSetList::const_iterator itr=_backPrimitiveSetList.begin(), end = _backPrimitiveSetList.end(); itr!=end; ++itr) + { + (*itr)->releaseGLObjects(state); + } } } diff --git a/src/osgText/TextBase.cpp b/src/osgText/TextBase.cpp index 6dad04dd1..fe4c96419 100644 --- a/src/osgText/TextBase.cpp +++ b/src/osgText/TextBase.cpp @@ -52,6 +52,8 @@ TextBase::TextBase(): setStateSet(Font::getDefaultFont()->getStateSet()); setUseDisplayList(false); setSupportsDisplayList(false); + + initArraysAndBuffers(); } TextBase::TextBase(const TextBase& textBase,const osg::CopyOp& copyop): @@ -78,12 +80,105 @@ TextBase::TextBase(const TextBase& textBase,const osg::CopyOp& copyop): _kerningType(textBase._kerningType), _lineCount(textBase._lineCount) { + initArraysAndBuffers(); } TextBase::~TextBase() { } +void TextBase::initArraysAndBuffers() +{ + _vbo = new osg::VertexBufferObject; + _ebo = new osg::ElementBufferObject; + + _coords = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + _normals = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + _colorCoords = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + _texcoords = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); + + _coords->setBufferObject(_vbo.get()); + _normals->setBufferObject(_vbo.get()); + _colorCoords->setBufferObject(_vbo.get()); + _texcoords->setBufferObject(_vbo.get()); +} + +#ifdef NEW_APPROACH +osg::VertexArrayState* TextBase::createVertexArrayState(osg::RenderInfo& renderInfo) const +{ + OSG_NOTICE<<"TextBase::createVertexArrayState()"<assignVertexArrayDispatcher(); + if (_colorCoords.valid()) vas->assignColorArrayDispatcher(); + if (_normals.valid()) vas->assignNormalArrayDispatcher(); + + if (_texcoords.valid()) vas->assignTexCoordArrayDispatcher(1); + + if (state.useVertexArrayObject(_useVertexArrayObject)) + { + OSG_NOTICE<<" Setup VertexArrayState to use VAO "<generateVertexArrayObject(); + } + else + { + // OSG_NOTICE<<" Setup VertexArrayState to without using VAO "<resizeGLObjectBuffers(maxSize); + + if (_coords.valid()) _coords->resizeGLObjectBuffers(maxSize); + if (_normals.valid()) _normals->resizeGLObjectBuffers(maxSize); + if (_colorCoords.valid()) _colorCoords->resizeGLObjectBuffers(maxSize); + if (_texcoords.valid()) _texcoords->resizeGLObjectBuffers(maxSize); + + for(Primitives::const_iterator itr = _decorationPrimitives.begin(); + itr != _decorationPrimitives.end(); + ++itr) + { + (*itr)->resizeGLObjectBuffers(maxSize); + } + + Drawable::resizeGLObjectBuffers(maxSize); +} + + +void TextBase::releaseGLObjects(osg::State* state) const +{ + if (_font.valid()) _font->releaseGLObjects(state); + + if (_coords.valid()) _coords->releaseGLObjects(state); + if (_normals.valid()) _normals->releaseGLObjects(state); + if (_colorCoords.valid()) _colorCoords->releaseGLObjects(state); + if (_texcoords.valid()) _texcoords->releaseGLObjects(state); + + for(Primitives::const_iterator itr = _decorationPrimitives.begin(); + itr != _decorationPrimitives.end(); + ++itr) + { + (*itr)->releaseGLObjects(state); + } + + Drawable::releaseGLObjects(state); +} + void TextBase::setColor(const osg::Vec4& color) { _color = color; @@ -491,22 +586,6 @@ bool TextBase::computeMatrix(osg::Matrix& matrix, osg::State* state) const return true; } -void TextBase::setThreadSafeRefUnref(bool threadSafe) -{ - Drawable::setThreadSafeRefUnref(threadSafe); -} - -void TextBase::resizeGLObjectBuffers(unsigned int maxSize) -{ - Drawable::resizeGLObjectBuffers(maxSize); -} - - -void TextBase::releaseGLObjects(osg::State* state) const -{ - Drawable::releaseGLObjects(state); -} - void TextBase::positionCursor(const osg::Vec2 & endOfLine_coords, osg::Vec2 & cursor, unsigned int linelength) { switch(_layout) @@ -643,6 +722,7 @@ void TextBase::setupDecoration() coords->push_back(c010); osg::ref_ptr primitives = new osg::DrawElementsUShort(GL_TRIANGLES); + primitives->setBufferObject(_ebo.get()); _decorationPrimitives.push_back(primitives); primitives->push_back(base); @@ -670,6 +750,7 @@ void TextBase::setupDecoration() coords->push_back(c010); osg::ref_ptr primitives = new osg::DrawElementsUShort(GL_LINE_LOOP); + primitives->setBufferObject(_ebo.get()); _decorationPrimitives.push_back(primitives); primitives->push_back(base); @@ -703,6 +784,7 @@ void TextBase::setupDecoration() osg::ref_ptr primitives = new osg::DrawElementsUShort(GL_LINES); + primitives->setBufferObject(_ebo.get()); _decorationPrimitives.push_back(primitives); // front loop @@ -764,6 +846,7 @@ void TextBase::setupDecoration() coords->push_back(vb); osg::ref_ptr primitives = new osg::DrawElementsUShort(GL_LINES); + primitives->setBufferObject(_ebo.get()); _decorationPrimitives.push_back(primitives); // front loop