1 /* -*-c++-*- */
2 /* osgEarth - Geospatial SDK for OpenSceneGraph
3  * Copyright 2008-2014 Pelican Mapping
4  * http://osgearth.org
5  *
6  * osgEarth is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>
18  */
19 #include "LayerDrawable"
20 #include "TerrainRenderData"
21 
22 using namespace osgEarth::Drivers::RexTerrainEngine;
23 
24 #undef  LC
25 #define LC "[LayerDrawable] "
26 
27 
LayerDrawable()28 LayerDrawable::LayerDrawable() :
29 _renderType(Layer::RENDERTYPE_TERRAIN_SURFACE),
30 _drawOrder(0),
31 _layer(0L),
32 _visibleLayer(0L),
33 _imageLayer(0L),
34 _clearOsgState(false),
35 _draw(true)
36 {
37     setDataVariance(DYNAMIC);
38     setUseDisplayList(false);
39     setUseVertexBufferObjects(true);
40     _tiles.reserve(128);
41 }
42 
~LayerDrawable()43 LayerDrawable::~LayerDrawable()
44 {
45     // Drawable's DTOR will release GL objects on any attached stateset;
46     // we don't want that because our Layer stateset is shared and re-usable.
47     // So detach it before OSG has a chance to do so.
48     setStateSet(0L);
49 }
50 
51 namespace
52 {
53     // Hack State so we can dirty the texture attrs without dirtying the other
54     // attributes (as dirtyAllAttributes() would do.
55     struct StateEx : public osg::State
56     {
dirtyAllTextureAttributes__anon36e2559e0111::StateEx57         void dirtyAllTextureAttributes()
58         {
59             // dirtyAllTextureAttributes. (Don't call state->dirtyAllAttributes because that
60             // will mess up positional state attributes like light sources)
61             for (TextureAttributeMapList::iterator tamItr = _textureAttributeMapList.begin();
62                 tamItr != _textureAttributeMapList.end();
63                 ++tamItr)
64             {
65                 osg::State::AttributeMap& attributeMap = *tamItr;
66                 for (osg::State::AttributeMap::iterator aitr = attributeMap.begin();
67                     aitr != attributeMap.end();
68                     ++aitr)
69                 {
70                     osg::State::AttributeStack& as = aitr->second;
71                     as.last_applied_attribute = 0;
72                     as.changed = true;
73                 }
74             }
75         }
76     };
77 }
78 
79 
80 void
drawImplementation(osg::RenderInfo & ri) const81 LayerDrawable::drawImplementation(osg::RenderInfo& ri) const
82 {
83     //OE_INFO << LC << (_layer ? _layer->getName() : "[empty]") << " tiles=" << _tiles.size() << std::endl;
84 
85     // Get this context's state values:
86     PerContextDrawState& ds = _drawState->getPCDS(ri.getContextID());
87 
88     ds.refresh(ri, _drawState->_bindings);
89 
90     if (ds._layerUidUL >= 0)
91     {
92         GLint uid = _layer ? (GLint)_layer->getUID() : (GLint)-1;
93         ds._ext->glUniform1i(ds._layerUidUL, uid);
94     }
95     else
96     {
97         // This just means that the fragment shader for this layer doesn't use oe_layer_uid
98     }
99 
100     for (DrawTileCommands::const_iterator tile = _tiles.begin(); tile != _tiles.end(); ++tile)
101     {
102         tile->draw(ri, *_drawState, 0L);
103     }
104 
105     // If set, dirty all OSG state to prevent any leakage - this is sometimes
106     // necessary when doing custom OpenGL within a Drawable.
107     if (_clearOsgState)
108     {
109         // Dirty the texture attributes so OSG can properly reset them
110         // NOTE: cannot call state.dirtyAllAttributes, because that would invalidate
111         // positional state like light sources!
112         reinterpret_cast<StateEx*>(ri.getState())->dirtyAllTextureAttributes();
113 
114         // NOTE: this is a NOOP in OSG 3.5.x, but not in 3.4.x ... Later we will need to
115         // revisit whether to call disableAllVertexArrays() in 3.5.x instead.
116         ri.getState()->dirtyAllVertexArrays();
117 
118         // unbind local buffers when finished.
119         ds._ext->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
120         ds._ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
121 
122         // gw: no need to do this, in fact it will cause positional attributes
123         // (light clip planes and lights) to immediately be reapplied under the
124         // current MVM, which will by definition be wrong!)
125         //ri.getState()->apply();
126     }
127 }
128