root/OpenSceneGraph/branches/OpenSceneGraph-2.8.2/src/osgUtil/RenderStage.cpp @ 10664

Revision 10664, 48.8 kB (checked in by paulmartz, 5 years ago)

Add CMake-controllable option to avoid doing a glBlitFramebuffer into depth to resolve multisampling. This works arouns a hang on OS X with NVIDIA GeForce? 8800 and v1.5.49 drivers.

  • Property svn:mergeinfo set to /OpenSceneGraph/trunk/src/osgUtil/RenderStage.cpp:9822
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[1529]2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
[501]13#include <stdio.h>
[4438]14
[26]15#include <osg/Notify>
[4438]16#include <osg/Texture1D>
17#include <osg/Texture2D>
18#include <osg/Texture3D>
19#include <osg/TextureRectangle>
20#include <osg/TextureCubeMap>
[4642]21#include <osg/GLExtensions>
[5152]22#include <osg/GLU>
[4438]23
[2029]24#include <osgUtil/Statistics>
[26]25
[10]26#include <osgUtil/RenderStage>
27
[923]28
[10]29using namespace osg;
30using namespace osgUtil;
31
32// register a RenderStage prototype with the RenderBin prototype list.
33//RegisterRenderBinProxy<RenderStage> s_registerRenderStageProxy;
34
[4291]35RenderStage::RenderStage():
[8447]36    RenderBin(getDefaultRenderBinSortMode()),
37    _disableFboAfterRender(true)
[4291]38{
39    // point RenderBin's _stage to this to ensure that references to
40    // stage don't go tempted away to any other stage.
41    _stage = this;
42    _stageDrawnThisFrame = false;
43
[4438]44    _drawBuffer = GL_NONE;
45    _readBuffer = GL_NONE;
[4291]46    _clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
47    _clearColor.set(0.0f,0.0f,0.0f,0.0f);
48    _clearAccum.set(0.0f,0.0f,0.0f,0.0f);
49    _clearDepth = 1.0;
50    _clearStencil = 0;
[4438]51
[4911]52    _cameraRequiresSetUp = false;
[4438]53    _camera = 0;
54   
55    _level = 0;
56    _face = 0;
57   
58    _imageReadPixelFormat = GL_RGBA;
59    _imageReadPixelDataType = GL_UNSIGNED_BYTE;
[4291]60}
61
[1156]62RenderStage::RenderStage(SortMode mode):
[8447]63    RenderBin(mode),
64    _disableFboAfterRender(true)
[10]65{
66    // point RenderBin's _stage to this to ensure that references to
67    // stage don't go tempted away to any other stage.
68    _stage = this;
69    _stageDrawnThisFrame = false;
70
[4438]71    _drawBuffer = GL_NONE;
72    _readBuffer = GL_NONE;
[10]73    _clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
74    _clearColor.set(0.0f,0.0f,0.0f,0.0f);
75    _clearAccum.set(0.0f,0.0f,0.0f,0.0f);
76    _clearDepth = 1.0;
77    _clearStencil = 0;
[4438]78
[4911]79    _cameraRequiresSetUp = false;
[4438]80    _camera = 0;
81   
82    _level = 0;
83    _face = 0;
84   
85    _imageReadPixelFormat = GL_RGBA;
86    _imageReadPixelDataType = GL_UNSIGNED_BYTE;
[10]87}
88
[1156]89RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop):
90        RenderBin(rhs,copyop),
91        _stageDrawnThisFrame(false),
[4332]92        _preRenderList(rhs._preRenderList),
93        _postRenderList(rhs._postRenderList),
[1156]94        _viewport(rhs._viewport),
[4438]95        _drawBuffer(rhs._drawBuffer),
96        _readBuffer(rhs._readBuffer),
[1156]97        _clearMask(rhs._clearMask),
98        _colorMask(rhs._colorMask),
99        _clearColor(rhs._clearColor),
100        _clearAccum(rhs._clearAccum),
101        _clearDepth(rhs._clearDepth),
102        _clearStencil(rhs._clearStencil),
[4911]103        _cameraRequiresSetUp(rhs._cameraRequiresSetUp),
[4438]104        _camera(rhs._camera),
105        _level(rhs._level),
106        _face(rhs._face),
107        _imageReadPixelFormat(rhs._imageReadPixelFormat),
108        _imageReadPixelDataType(rhs._imageReadPixelDataType),
[9062]109        _disableFboAfterRender(rhs._disableFboAfterRender),
110        _renderStageLighting(rhs._renderStageLighting)
[1156]111{
[1162]112    _stage = this;
[1156]113}
114
115
[10]116RenderStage::~RenderStage()
117{
118}
119
120void RenderStage::reset()
121{
122    _stageDrawnThisFrame = false;
123   
124    if (_renderStageLighting.valid()) _renderStageLighting->reset();
125
[4697]126    for(RenderStageList::iterator pre_itr = _preRenderList.begin();
127        pre_itr != _preRenderList.end();
128        ++pre_itr)
129    {
[5524]130        pre_itr->second->reset();
[4697]131    }
132
[10]133    RenderBin::reset();
[4697]134
135    for(RenderStageList::iterator post_itr = _postRenderList.begin();
136        post_itr != _postRenderList.end();
137        ++post_itr)
138    {
[5524]139        post_itr->second->reset();
[4697]140    }
141
142    _preRenderList.clear();
143    _postRenderList.clear();
[10]144}
145
[4697]146void RenderStage::sort()
147{
148    for(RenderStageList::iterator pre_itr = _preRenderList.begin();
149        pre_itr != _preRenderList.end();
150        ++pre_itr)
151    {
[5524]152        pre_itr->second->sort();
[4697]153    }
154
155    RenderBin::sort();
156
157    for(RenderStageList::iterator post_itr = _postRenderList.begin();
158        post_itr != _postRenderList.end();
159        ++post_itr)
160    {
[5524]161        post_itr->second->sort();
[4697]162    }
163}
164
[5524]165void RenderStage::addPreRenderStage(RenderStage* rs, int order)
[10]166{
[5524]167    if (rs)
168    {
169        RenderStageList::iterator itr;
170        for(itr = _preRenderList.begin(); itr != _preRenderList.end(); ++itr) {
171            if(order < itr->first) {
172                break;
173            }
174        }
175        if(itr == _preRenderList.end()) {
176            _preRenderList.push_back(RenderStageOrderPair(order,rs));
177        } else {
178            _preRenderList.insert(itr,RenderStageOrderPair(order,rs));
179        }
180    }
[10]181}
[611]182
[5524]183void RenderStage::addPostRenderStage(RenderStage* rs, int order)
[4332]184{
[5524]185    if (rs)
186    {
187        RenderStageList::iterator itr;
188        for(itr = _postRenderList.begin(); itr != _postRenderList.end(); ++itr) {
189            if(order < itr->first) {
190                break;
191            }
192        }
193        if(itr == _postRenderList.end()) {
194            _postRenderList.push_back(RenderStageOrderPair(order,rs));
195        } else {
196            _postRenderList.insert(itr,RenderStageOrderPair(order,rs));
197        }
198    }
[4332]199}
200
[5573]201void RenderStage::drawPreRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[1163]202{
[4332]203    if (_preRenderList.empty()) return;
[1554]204   
205    //cout << "Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
[4332]206    for(RenderStageList::iterator itr=_preRenderList.begin();
207        itr!=_preRenderList.end();
[1163]208        ++itr)
209    {
[5573]210        itr->second->draw(renderInfo,previous);
[1163]211    }
[1554]212    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
[1163]213}
214
[4573]215
[5573]216void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
[4573]217{
218    _cameraRequiresSetUp = false;
219
220    if (!_camera) return;
221   
[8027]222    osg::State& state = *renderInfo.getState();
[5573]223
[8027]224    osg::Camera::RenderTargetImplementation renderTargetImplementation = _camera->getRenderTargetImplementation();
[5757]225    osg::Camera::RenderTargetImplementation renderTargetFallback = _camera->getRenderTargetFallback();
[4573]226
[7648]227    osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
[4574]228
[5389]229    // compute the required dimensions
[5884]230    int width = static_cast<int>(_viewport->x() + _viewport->width());
231    int height = static_cast<int>(_viewport->y() + _viewport->height());
[5389]232    int depth = 1;
[5757]233    osg::Camera::BufferAttachmentMap::iterator itr;
[7648]234    for(itr = bufferAttachments.begin();
235        itr != bufferAttachments.end();
[5389]236        ++itr)
237    {
238        width = osg::maximum(width,itr->second.width());
239        height = osg::maximum(height,itr->second.height());
240        depth = osg::maximum(depth,itr->second.depth());
241    }
242   
243    // osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp viewport "<<_viewport->x()<<" "<<_viewport->y()<<" "<<_viewport->width()<<" "<<_viewport->height()<<std::endl;
244    // osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp computed "<<width<<" "<<height<<" "<<depth<<std::endl;
245
[8032]246    // attach images that need to be copied after the stage is drawn.
[7648]247    for(itr = bufferAttachments.begin();
248        itr != bufferAttachments.end();
[4573]249        ++itr)
250    {
[4645]251        // if one exist attach image to the RenderStage.
252        if (itr->second._image.valid())
253        {
254            osg::Image* image = itr->second._image.get();
255            GLenum pixelFormat = image->getPixelFormat();
256            GLenum dataType = image->getDataType();
257
258            if (image->data()==0)
259            {
260                if (pixelFormat==0) pixelFormat = itr->second._internalFormat;
261                if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
262                if (pixelFormat==0) pixelFormat = GL_RGBA;
263
264                if (dataType==0) dataType = _imageReadPixelDataType;
265                if (dataType==0) dataType = GL_UNSIGNED_BYTE;
266            }
267
[5756]268            _bufferAttachmentMap[itr->first]._imageReadPixelFormat = pixelFormat;
269            _bufferAttachmentMap[itr->first]._imageReadPixelDataType = dataType;
270            _bufferAttachmentMap[itr->first]._image = image;
[4645]271        }
[4683]272       
273        if (itr->second._texture.valid())
274        {
275            osg::Texture* texture = itr->second._texture.get();
276            osg::Texture1D* texture1D = 0;
277            osg::Texture2D* texture2D = 0;
278            osg::Texture3D* texture3D = 0;
279            osg::TextureCubeMap* textureCubeMap = 0;
280            osg::TextureRectangle* textureRectangle = 0;
281            if (0 != (texture1D=dynamic_cast<osg::Texture1D*>(texture)))
282            {
283                if (texture1D->getTextureWidth()==0)
284                {
[5389]285                    texture1D->setTextureWidth(width);
[4683]286                }
287            }
288            else if (0 != (texture2D = dynamic_cast<osg::Texture2D*>(texture)))
289            {
290                if (texture2D->getTextureWidth()==0 || texture2D->getTextureHeight()==0)
291                {
[5389]292                    texture2D->setTextureSize(width,height);
[4683]293                }
294            }
295            else if (0 != (texture3D = dynamic_cast<osg::Texture3D*>(texture)))
296            {
297                if (texture3D->getTextureWidth()==0 || texture3D->getTextureHeight()==0 || texture3D->getTextureDepth()==0 )
298                {
299                    // note we dont' have the depth here, so we'll heave to assume that height and depth are the same..
[5389]300                    texture3D->setTextureSize(width,height,height);
[4683]301                }
302            }
303            else if (0 != (textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture)))
304            {
305                if (textureCubeMap->getTextureWidth()==0 || textureCubeMap->getTextureHeight()==0)
306                {
[5389]307                    textureCubeMap->setTextureSize(width,height);
[4683]308                }
309            }
310            else if (0 != (textureRectangle = dynamic_cast<osg::TextureRectangle*>(texture)))
311            {
312                if (textureRectangle->getTextureWidth()==0 || textureRectangle->getTextureHeight()==0)
313                {
[5389]314                    textureRectangle->setTextureSize(width,height);
[4683]315                }
316            }
317
318        }
[4573]319    }
[4574]320   
[8027]321    if (renderTargetImplementation==osg::Camera::FRAME_BUFFER_OBJECT)
[4573]322    {
[4954]323        osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(state.getContextID(),true);
[4573]324        bool fbo_supported = fbo_ext && fbo_ext->isSupported();
[4839]325       
326        if (fbo_supported && !_fbo)
[4573]327        {
[5757]328            osg::notify(osg::INFO)<<"Setting up osg::Camera::FRAME_BUFFER_OBJECT"<<std::endl;
[4642]329
[4834]330            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*(_camera->getDataChangeMutex()));
[4831]331
[4839]332            osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;
[8447]333            osg::ref_ptr<osg::FrameBufferObject> fbo_multisample;
334           
[4573]335            bool colorAttached = false;
336            bool depthAttached = false;
337            bool stencilAttached = false;
[8447]338            unsigned samples = 0;
339            unsigned colorSamples = 0;
340
341            if (fbo_ext->isMultisampleSupported())
342            {
343                for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
344                    itr != bufferAttachments.end();
345                    ++itr)
346                {
347                    osg::Camera::Attachment& attachment = itr->second;
348                    samples = maximum(samples, attachment._multisampleSamples);
[8764]349                    colorSamples = maximum(colorSamples, attachment._multisampleColorSamples);
[8447]350                }
351
352                if (colorSamples > samples)
353                {
354                    osg::notify(WARN) << "Multisample color samples must be less than or "
355                        "equal to samples. Setting color samples equal to samples." << std::endl;
356                    colorSamples = samples;
357                }
358
359                if (samples)
360                {
361                    fbo_multisample = new osg::FrameBufferObject;
362                }
363            }
[8032]364           
[7648]365            for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
366                itr != bufferAttachments.end();
[4573]367                ++itr)
368            {
369
[5757]370                osg::Camera::BufferComponent buffer = itr->first;
371                osg::Camera::Attachment& attachment = itr->second;
[4645]372               
[8308]373                if (attachment._texture.valid() || attachment._image.valid())
374                    fbo->setAttachment(buffer, osg::FrameBufferAttachment(attachment));
375                else
376                    fbo->setAttachment(buffer, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, attachment._internalFormat)));
[8447]377
378                if (fbo_multisample.valid())
379                {
380                    GLenum internalFormat = attachment._internalFormat;
381                    if (!internalFormat)
382                    {
383                        switch (buffer)
384                        {
385                        case Camera::DEPTH_BUFFER:
386                            internalFormat = GL_DEPTH_COMPONENT24;
387                            break;
388                        case Camera::STENCIL_BUFFER:
389                            internalFormat = GL_STENCIL_INDEX8_EXT;
390                            break;
[9239]391                        case Camera::PACKED_DEPTH_STENCIL_BUFFER:
392                            internalFormat = GL_DEPTH_STENCIL_EXT;
393                            break;
[9823]394
395                        // all other buffers are color buffers
[8447]396                        default:
[9823]397                            // setup the internal format based on attached texture if such exists, otherwise just default format
398                            if (attachment._texture)
399                                internalFormat = attachment._texture->getInternalFormat();
400                            else
401                                internalFormat = GL_RGBA;
[8447]402                            break;
403                        }
404                    }
405                    fbo_multisample->setAttachment(buffer,
406                        osg::FrameBufferAttachment(new osg::RenderBuffer(
407                        width, height, internalFormat,
408                        samples, colorSamples)));
409                }
[8136]410               
411                if (buffer==osg::Camera::DEPTH_BUFFER) depthAttached = true;
412                else if (buffer==osg::Camera::STENCIL_BUFFER) stencilAttached = true;
[9239]413                else if (buffer==osg::Camera::PACKED_DEPTH_STENCIL_BUFFER)
414                {
415                    depthAttached = true;
416                    stencilAttached = true;
417                }
[8139]418                else if (buffer>=osg::Camera::COLOR_BUFFER) colorAttached = true;
[9239]419               
[4573]420            }
421
422            if (!depthAttached)
423            {               
[8136]424                fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24)));
[8447]425                if (fbo_multisample.valid())
426                {
427                    fbo_multisample->setAttachment(osg::Camera::DEPTH_BUFFER,
428                        osg::FrameBufferAttachment(new osg::RenderBuffer(width,
429                        height, GL_DEPTH_COMPONENT24, samples, colorSamples)));
430                }
[4573]431            }
432
433            if (!colorAttached)
434            {               
[8136]435                fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB)));
[8447]436                if (fbo_multisample.valid())
437                {
438                    fbo_multisample->setAttachment(osg::Camera::COLOR_BUFFER,
439                        osg::FrameBufferAttachment(new osg::RenderBuffer(width,
440                        height, GL_RGB, samples, colorSamples)));
441                }
[4573]442            }
[4839]443
444            fbo->apply(state);
445           
446            GLenum status = fbo_ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
447           
448            if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
449            {
[9681]450                osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x"<<std::hex<<status<<std::dec<<std::endl;
[4839]451
452                fbo_supported = false;
453                fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
454                fbo = 0;
455               
456                // clean up.
457                double availableTime = 100.0f;
458                double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0;
459                osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
460                osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
461               
462
463            }
464            else
465            {
466                setDrawBuffer(GL_NONE);
467                setReadBuffer(GL_NONE);
[8032]468       
[4839]469                _fbo = fbo;
[8447]470
471                if (fbo_multisample.valid())
472                {
473                    fbo_multisample->apply(state);
474
475                    GLenum status = fbo_ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
476
477                    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
478                    {
479                        notify(NOTICE) << "RenderStage::runCameraSetUp(), "
480                            "multisample FBO setup failed, FBO status = 0x"
[9681]481                            << std::hex << status << std::dec << std::endl;
[8447]482
483                        fbo->apply(state);
484                        fbo_multisample = 0;
485                        _resolveFbo = 0;
486
487                        // clean up.
488                        double availableTime = 100.0f;
489                        double currentTime = state.getFrameStamp()?state.getFrameStamp()->getReferenceTime():0.0;
490                        osg::RenderBuffer::flushDeletedRenderBuffers(state.getContextID(),currentTime,availableTime);
491                        osg::FrameBufferObject::flushDeletedFrameBufferObjects(state.getContextID(),currentTime,availableTime);
492                    }
493                    else
494                    {
495                        _resolveFbo.swap(_fbo);
496                        _fbo = fbo_multisample;
497                    }
498                }
499                else
500                {
501                    _resolveFbo = 0;
502                }
[4839]503            }
[4573]504        }
[4839]505       
506        if (!fbo_supported)
507        {
[8027]508            if (renderTargetImplementation<renderTargetFallback)
509                renderTargetImplementation = renderTargetFallback;
[4839]510            else
[8027]511                renderTargetImplementation = osg::Camera::PIXEL_BUFFER_RTT;
[4839]512        }
[4573]513    }
514   
[4642]515    // check whether PBuffer-RTT is supported or not
[8027]516    if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT &&
[4964]517        !osg::isGLExtensionSupported(state.getContextID(), "WGL_ARB_render_texture"))
[4642]518    {   
[8027]519        if (renderTargetImplementation<renderTargetFallback)
520            renderTargetImplementation = renderTargetFallback;
[4642]521        else
[8027]522            renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
[4642]523    }
[4574]524
[7648]525    // if any of the renderTargetImplementations require a separate graphics context such as with pbuffer try in turn to
[4574]526    // set up, but if each level fails then resort to the next level down.   
527    while (!getGraphicsContext() &&
[8027]528           (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT ||
529            renderTargetImplementation==osg::Camera::PIXEL_BUFFER ||
530            renderTargetImplementation==osg::Camera::SEPERATE_WINDOW) )
[4573]531    {
532        osg::ref_ptr<osg::GraphicsContext> context = getGraphicsContext();
533        if (!context)
534        {
535
536            // set up the traits of the graphics context that we want
537            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
538
[5845]539            traits->width = width;
540            traits->height = height;
[5389]541
[5845]542            // osg::notify(osg::NOTICE)<<"traits = "<<traits->width<<" "<<traits->height<<std::endl;
[5389]543
[8027]544            traits->pbuffer = (renderTargetImplementation==osg::Camera::PIXEL_BUFFER || renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT);
545            traits->windowDecoration = (renderTargetImplementation==osg::Camera::SEPERATE_WINDOW);
546            traits->doubleBuffer = (renderTargetImplementation==osg::Camera::SEPERATE_WINDOW);
[4573]547
[4574]548            osg::Texture* pBufferTexture = 0;
[4573]549            GLenum bufferFormat = GL_NONE;
[4574]550            unsigned int level = 0;
551            unsigned int face = 0;
[4573]552
553            bool colorAttached = false;
554            bool depthAttached = false;
555            bool stencilAttached = false;
[7648]556            for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
557                itr != bufferAttachments.end();
[4573]558                ++itr)
559            {
560
[5757]561                osg::Camera::BufferComponent buffer = itr->first;
562                osg::Camera::Attachment& attachment = itr->second;
[4573]563                switch(buffer)
564                {
[5757]565                    case(osg::Camera::DEPTH_BUFFER):
[4573]566                    {
[5845]567                        traits->depth = 24;
[4573]568                        depthAttached = true;
569                        break;
570                    }
[5757]571                    case(osg::Camera::STENCIL_BUFFER):
[4573]572                    {
[5845]573                        traits->stencil = 8;
[4573]574                        stencilAttached = true;
575                        break;
576                    }
[9239]577                    case(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER):
578                    {
579                        traits->depth = 24;
580                        depthAttached = true;
581                        traits->stencil = 8;
582                        stencilAttached = true;
583                    }
[5757]584                    case(osg::Camera::COLOR_BUFFER):
[4573]585                    {
586                        if (attachment._internalFormat!=GL_NONE)
587                        {
588                            bufferFormat = attachment._internalFormat;
589                        }
590                        else
591                        {
592                            if (attachment._texture.valid())
593                            {
594                                pBufferTexture = attachment._texture.get();
595                                bufferFormat = attachment._texture->getInternalFormat();
596                            }
597                            else if (attachment._image.valid())
598                            {
599                                bufferFormat = attachment._image->getInternalTextureFormat();
600                            }
601                            else
602                            {
603                                bufferFormat = GL_RGBA;
604                            }
605                        }
606
[4574]607                        level = attachment._level;
608                        face = attachment._face;
609
[8027]610                        if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
[4573]611                        {
[7030]612                            traits->target = attachment._texture.valid() ? attachment._texture->getTextureTarget() : 0;
[7031]613                            traits->format = bufferFormat;
[5845]614                            traits->level = level;
615                            traits->face = face;
616                            traits->mipMapGeneration = attachment._mipMapGeneration;
[4573]617                        }
618                        break;
619                    }
620                    default:
621                    {
[8027]622                        if (renderTargetImplementation==osg::Camera::SEPERATE_WINDOW)
[4574]623                            osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Window ";
[4573]624                        else
[4574]625                            osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";
[4573]626
627                        osg::notify(osg::NOTICE)<<"does not support multiple color outputs."<<std::endl;
628                        break;
629                    }
630
631                }
632            }
633
634            if (!depthAttached)
635            {               
[5845]636                traits->depth = 24;
[4573]637            }
638
639            if (!colorAttached)
640            {               
641                if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
642
[5845]643                traits->red = 8;
644                traits->green = 8;
645                traits->blue = 8;
646                traits->alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
[4573]647            }
648
649            // share OpenGL objects if possible...
650            if (state.getGraphicsContext())
651            {
[5845]652                traits->sharedContext = state.getGraphicsContext();
[5427]653               
[5845]654                const osg::GraphicsContext::Traits* sharedTraits = traits->sharedContext->getTraits();
[5427]655                if (sharedTraits)
656                {
[5845]657                    traits->hostName = sharedTraits->hostName;
658                    traits->displayNum = sharedTraits->displayNum;
659                    traits->screenNum = sharedTraits->screenNum;
[5427]660                }
[4573]661            }
662
663            // create the graphics context according to these traits.
664            context = osg::GraphicsContext::createGraphicsContext(traits.get());
665
[4577]666            if (context.valid() && context->realize())
[4573]667            {
[4577]668                osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;
669
[4574]670                // successfully set up graphics context as requested,
671                // will assign this graphics context to the RenderStage and
672                // associated parameters.  Setting the graphics context will
673                // single this while loop to exit successful.
674                setGraphicsContext(context.get());
675               
676                // how to do we detect that an attempt to set up RTT has failed??
[4573]677
[4574]678                setDrawBuffer(GL_FRONT);
679                setReadBuffer(GL_FRONT);
[4573]680
[8027]681                if (pBufferTexture && renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
[4574]682                {
683                   osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Assign graphis context to Texture"<<std::endl;
684                   pBufferTexture->setReadPBuffer(context.get());
685                }
686                else
687                {
688                    osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Assigning texture to RenderStage so that it does the copy"<<std::endl;
689                    setTexture(pBufferTexture, level, face);
690                }
691            }
692            else
[4573]693            {
[7648]694                osg::notify(osg::INFO)<<"Failed to acquire Graphics Context"<<std::endl;
[4574]695               
[8027]696                if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
[4574]697                {
698                    // fallback to using standard PBuffer, this will allow this while loop to continue
[8027]699                    if (renderTargetImplementation<renderTargetFallback)
700                        renderTargetImplementation = renderTargetFallback;
[4642]701                    else
[8027]702                        renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
[4574]703                }
704                else 
705                {
[8027]706                    renderTargetImplementation = osg::Camera::FRAME_BUFFER;
[4574]707                }
[4573]708            }
709
710        }
711    }
712   
[4574]713    // finally if all else has failed, then the frame buffer fallback will come in to play.
[8027]714    if (renderTargetImplementation==osg::Camera::FRAME_BUFFER)
[4574]715    {
[5757]716        osg::notify(osg::INFO)<<"Setting up osg::Camera::FRAME_BUFFER"<<std::endl;
[4574]717
[7648]718        for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
719            itr != bufferAttachments.end();
[4574]720            ++itr)
721        {
722            // assign the texture...
723            if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
724        }
725    }
726
[4573]727}
728
[5573]729void RenderStage::copyTexture(osg::RenderInfo& renderInfo)
[10]730{
[5573]731    osg::State& state = *renderInfo.getState();
732
[4446]733    if (_readBuffer != GL_NONE)
734    {
735        glReadBuffer(_readBuffer);
736    }
[1554]737
[4446]738    // need to implement texture cube map etc...
739    osg::Texture1D* texture1D = 0;
740    osg::Texture2D* texture2D = 0;
741    osg::Texture3D* texture3D = 0;
742    osg::TextureRectangle* textureRec = 0;
743    osg::TextureCubeMap* textureCubeMap = 0;
[1554]744
[5389]745    // use TexCopySubImage with the offset of the viewport into the texture
746    // note, this path mirrors the pbuffer and fbo means for updating the texture.
747    // Robert Osfield, 3rd August 2006.
[4446]748    if ((texture2D = dynamic_cast<osg::Texture2D*>(_texture.get())) != 0)
[4438]749    {
[5884]750        texture2D->copyTexSubImage2D(state,
751                                     static_cast<int>(_viewport->x()),
752                                     static_cast<int>(_viewport->y()),
753                                     static_cast<int>(_viewport->x()),
754                                     static_cast<int>(_viewport->y()),
755                                     static_cast<int>(_viewport->width()),
756                                     static_cast<int>(_viewport->height()));
[5389]757    }
758    else if ((textureRec = dynamic_cast<osg::TextureRectangle*>(_texture.get())) != 0)
759    {
[5884]760        textureRec->copyTexSubImage2D(state,
761                                     static_cast<int>(_viewport->x()),
762                                     static_cast<int>(_viewport->y()),
763                                     static_cast<int>(_viewport->x()),
764                                     static_cast<int>(_viewport->y()),
765                                     static_cast<int>(_viewport->width()),
766                                     static_cast<int>(_viewport->height()));
[5389]767    }
768    else if ((texture1D = dynamic_cast<osg::Texture1D*>(_texture.get())) != 0)
769    {
770        // need to implement
[5884]771        texture1D->copyTexSubImage1D(state,
772                                     static_cast<int>(_viewport->x()),
773                                     static_cast<int>(_viewport->x()),
774                                     static_cast<int>(_viewport->y()),
775                                     static_cast<int>(_viewport->width()));
[5389]776    }
777    else if ((texture3D = dynamic_cast<osg::Texture3D*>(_texture.get())) != 0)
778    {
779        // need to implement
[5884]780        texture3D->copyTexSubImage3D(state,
781                                     static_cast<int>(_viewport->x()),
782                                     static_cast<int>(_viewport->y()),
783                                     _face,
784                                     static_cast<int>(_viewport->x()),
785                                     static_cast<int>(_viewport->y()),
786                                     static_cast<int>(_viewport->width()),
787                                     static_cast<int>(_viewport->height()));
[5389]788    }
789    else if ((textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(_texture.get())) != 0)
790    {
791        // need to implement
[5884]792        textureCubeMap->copyTexSubImageCubeMap(state, _face,
793                                     static_cast<int>(_viewport->x()),
794                                     static_cast<int>(_viewport->y()),
795                                     static_cast<int>(_viewport->x()),
796                                     static_cast<int>(_viewport->y()),
797                                     static_cast<int>(_viewport->width()),
798                                     static_cast<int>(_viewport->height()));
[5389]799    }
[4446]800}
[4438]801
[5573]802void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, bool& doCopyTexture)
[4446]803{
[8447]804    struct SubFunc
805    {
806        static void applyReadFBO(bool& apply_read_fbo,
807            const FrameBufferObject* read_fbo, osg::State& state)
808        {
809            if (read_fbo->isMultisample())
810            {
811                osg::notify(osg::WARN) << "Attempting to read from a"
812                    " multisampled framebuffer object. Set a resolve"
813                    " framebuffer on the RenderStage to fix this." << std::endl;
814            }
815
816            if (apply_read_fbo)
817            {
818                // Bind the monosampled FBO to read from
819                read_fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
820                apply_read_fbo = false;
821            }
822        }
823    };
824
[5573]825    osg::State& state = *renderInfo.getState();
826
[8102]827    osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID(),true) : 0;
828    bool fbo_supported = fbo_ext && fbo_ext->isSupported();
829
830    bool using_multiple_render_targets = fbo_supported && _fbo->hasMultipleRenderingTargets();
[4438]831   
[8032]832    if (!using_multiple_render_targets)
[4438]833    {
[8032]834        if (_drawBuffer != GL_NONE)
835        {   
836            glDrawBuffer(_drawBuffer);
837        }
838
839        if (_readBuffer != GL_NONE)
840        {
841            glReadBuffer(_readBuffer);
842        }
[4438]843    }
844
845    if (fbo_supported)
846    {
[4446]847        _fbo->apply(state);
[4438]848    }
849
850    // do the drawing itself.   
[5573]851    RenderBin::draw(renderInfo,previous);
[4332]852
[4438]853
[5133]854    if(state.getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
[4684]855    {
[5133]856        GLenum errorNo = glGetError();
857        if (errorNo!=GL_NO_ERROR)
858        {
[5152]859            const char* error = (char*)gluErrorString(errorNo);
860            if (error)  osg::notify(osg::NOTICE)<<"Warning: detected OpenGL error '"<<error<<"' after RenderBin::draw(,)"<<std::endl;
[9681]861            else        osg::notify(osg::NOTICE)<<"Warning: detected OpenGL errorNo= 0x"<<std::hex<<errorNo<<" after RenderBin::draw(,)"<<std::dec<<std::endl;
[5152]862
[9681]863            if (fbo_ext) osg::notify(osg::NOTICE)<<"RenderStage::drawInner(,) FBO status= 0x"<<std::hex<<fbo_ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)<<std::dec<<std::endl;
[5133]864        }
[4684]865    }
866
[8518]867    const FrameBufferObject* read_fbo = fbo_supported ? _fbo.get() : 0;
[8447]868    bool apply_read_fbo = false;
869
870    if (fbo_supported && _resolveFbo.valid() && fbo_ext->glBlitFramebufferEXT)
871    {
872        GLbitfield blitMask = 0;
873
874        //find which buffer types should be copied
875        for (FrameBufferObject::AttachmentMap::const_iterator
876            it = _resolveFbo->getAttachmentMap().begin(),
877            end =_resolveFbo->getAttachmentMap().end(); it != end; ++it)
878        {
879            switch (it->first)
880            {
881            case Camera::DEPTH_BUFFER:
[10664]882#ifndef OSG_MULTISAMPLE_FBO_RESOLVE_IGNORES_DEPTH
883                // This #define is a workaround for an OS X NVIDIA driver bug
884                // confirmed on GeForce 8800 with driver v1.5.49.
885                // If the glBlitFramebuffer mask includes depth, the OS X desktop
886                // will hang. The #define is controlled from CMake and should be
887                // set to ON to enable the workaround and avoid blitting depth.
[8447]888                blitMask |= GL_DEPTH_BUFFER_BIT;
[10664]889#endif
[8447]890                break;
891            case Camera::STENCIL_BUFFER:
892                blitMask |= GL_STENCIL_BUFFER_BIT;
893                break;
[9239]894            case Camera::PACKED_DEPTH_STENCIL_BUFFER:
895                blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
[8447]896            default:
897                blitMask |= GL_COLOR_BUFFER_BIT;
898                break;
899            }
900        }
901
902        // Bind the resolve framebuffer to blit into.
[9823]903        _fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
[8447]904        _resolveFbo->apply(state, FrameBufferObject::DRAW_FRAMEBUFFER);
905
906        // Blit to the resolve framebuffer.
907        // Note that (with nvidia 175.16 windows drivers at least) if the read
908        // framebuffer is multisampled then the dimension arguments are ignored
909        // and the whole framebuffer is always copied.
910        fbo_ext->glBlitFramebufferEXT(
911            0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
912            0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
913            blitMask, GL_NEAREST);
914
915        apply_read_fbo = true;
916        read_fbo = _resolveFbo.get();
917
918        using_multiple_render_targets = read_fbo->hasMultipleRenderingTargets();
919    }
920
[4438]921    // now copy the rendered image to attached texture.
[4446]922    if (doCopyTexture)
[4438]923    {
[8518]924        if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
[5573]925        copyTexture(renderInfo);
[4438]926    }
[8447]927
[5757]928    std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
[6221]929    for(itr = _bufferAttachmentMap.begin();
930        itr != _bufferAttachmentMap.end();
931        ++itr)
932    {
[8447]933        if (itr->second._image.valid())
934        {
[8518]935            if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
[4438]936
[8447]937            if (using_multiple_render_targets)
938            {
939                int attachment=itr->first;
940                if (attachment==osg::Camera::DEPTH_BUFFER || attachment==osg::Camera::STENCIL_BUFFER) {
941                    // assume first buffer rendered to is the one we want
942                    glReadBuffer(read_fbo->getMultipleRenderingTargets()[0]);
943                } else {
944                    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
945                }
946            } else {
947                if (_readBuffer != GL_NONE)
948                {
949                    glReadBuffer(_readBuffer);
950                }
951            }
[4645]952
[8447]953            GLenum pixelFormat = itr->second._image->getPixelFormat();
954            if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
955            if (pixelFormat==0) pixelFormat = GL_RGB;
[4646]956
[8447]957            GLenum dataType = itr->second._image->getDataType();
958            if (dataType==0) dataType = _imageReadPixelDataType;
959            if (dataType==0) dataType = GL_UNSIGNED_BYTE;       
[5756]960
[8447]961            itr->second._image->readPixels(static_cast<int>(_viewport->x()),
962                                           static_cast<int>(_viewport->y()),
963                                           static_cast<int>(_viewport->width()),
964                                           static_cast<int>(_viewport->height()),
965                                           pixelFormat, dataType);
966        }
967    }
968
[4438]969    if (fbo_supported)
970    {
[8447]971        if (getDisableFboAfterRender())
972        {
973            // switch off the frame buffer object
974            fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
975        }
[4446]976
977        doCopyTexture = true;
[4438]978    }
[8447]979
[4438]980    if (fbo_supported && _camera)
981    {
982        // now generate mipmaps if they are required.
[8447]983        const osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
984        for(osg::Camera::BufferAttachmentMap::const_iterator itr = bufferAttachments.begin();
985            itr != bufferAttachments.end();
[4438]986            ++itr)
987        {
988            if (itr->second._texture.valid() && itr->second._mipMapGeneration)
989            {
[4976]990                state.setActiveTextureUnit(0);
991                state.applyTextureAttribute(0, itr->second._texture.get());
992                fbo_ext->glGenerateMipmapEXT(itr->second._texture->getTextureTarget());
[4438]993            }
994        }
995    }
[4446]996}
[4438]997
[6088]998struct DrawInnerOperation : public osg::Operation
[4446]999{
[5573]1000    DrawInnerOperation(RenderStage* stage, osg::RenderInfo& renderInfo) :
[6088]1001        osg::Operation("DrawInnerStage",false),
[5573]1002        _stage(stage),
1003        _renderInfo(renderInfo) {}
[4446]1004
[6088]1005    virtual void operator () (osg::Object* object)
[4446]1006    {
[6088]1007        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1008        if (!context) return;
1009
[4446]1010        // osg::notify(osg::NOTICE)<<"DrawInnerOperation operator"<<std::endl;
1011        if (_stage && context)
1012        {
1013            RenderLeaf* previous = 0;
1014            bool doCopyTexture = false;
[5573]1015            _renderInfo.setState(context->getState());
1016            _stage->drawInner(_renderInfo, previous, doCopyTexture);
[4446]1017        }
1018    }
1019   
1020    RenderStage* _stage;
[5573]1021    RenderInfo _renderInfo;
[4446]1022};
1023
1024
[5573]1025void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[4446]1026{
1027    if (_stageDrawnThisFrame) return;
1028
[7896]1029    // push the stages camera so that drawing code can query it     
1030    if (_camera) renderInfo.pushCamera(_camera);
1031
[4446]1032    _stageDrawnThisFrame = true;
1033
[7896]1034    if (_camera && _camera->getInitialDrawCallback())
1035    {
1036        // if we have a camera with a intial draw callback invoke it.
1037        (*(_camera->getInitialDrawCallback()))(renderInfo);
1038    }
1039
[4446]1040    // note, SceneView does call to drawPreRenderStages explicitly
1041    // so there is no need to call it here.
[5573]1042    drawPreRenderStages(renderInfo,previous);
[4446]1043   
[4573]1044    if (_cameraRequiresSetUp)
1045    {
[5573]1046        runCameraSetUp(renderInfo);
[4573]1047    }
[4446]1048
[5573]1049    osg::State& state = *renderInfo.getState();
[4573]1050
[4446]1051    osg::State* useState = &state;
1052    osg::GraphicsContext* callingContext = state.getGraphicsContext();
1053    osg::GraphicsContext* useContext = callingContext;
[7108]1054    osg::OperationThread* useThread = 0;
[5573]1055    osg::RenderInfo useRenderInfo(renderInfo);
[7037]1056   
1057    RenderLeaf* saved_previous = previous;
[4446]1058
1059    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1060    {
1061        // show we release the context so that others can use it?? will do so right
1062        // now as an experiment.
1063        callingContext->releaseContext();
1064   
[7054]1065        // osg::notify(osg::NOTICE)<<"  enclosing state before - "<<state.getStateSetStackSize()<<std::endl;
1066
[4446]1067        useState = _graphicsContext->getState();
1068        useContext = _graphicsContext.get();
1069        useThread = useContext->getGraphicsThread();
[5573]1070        useRenderInfo.setState(useState);
[4446]1071       
[7648]1072        // synchronize the frame stamps
[5094]1073        useState->setFrameStamp(const_cast<osg::FrameStamp*>(state.getFrameStamp()));
[6206]1074
1075        // map the DynamicObjectCount across to the new window
[6194]1076        useState->setDynamicObjectCount(state.getDynamicObjectCount());
1077        useState->setDynamicObjectRenderingCompletedCallback(state.getDynamicObjectRenderingCompletedCallback());
[5094]1078       
[7037]1079        if (!useThread)
1080        {
1081            previous = 0;
1082            useContext->makeCurrent();
[7054]1083           
1084            // osg::notify(osg::NOTICE)<<"  nested state before - "<<useState->getStateSetStackSize()<<std::endl;
[7037]1085        }
[4446]1086    }
[6806]1087
[7054]1088    unsigned int originalStackSize = useState->getStateSetStackSize();
1089
[6806]1090    if (_camera && _camera->getPreDrawCallback())
1091    {
[7896]1092        // if we have a camera with a pre draw callback invoke it.
1093        (*(_camera->getPreDrawCallback()))(renderInfo);
[6806]1094    }
[4446]1095   
1096    bool doCopyTexture = _texture.valid() ?
1097                        (callingContext != useContext) :
1098                        false;
1099
1100    if (useThread)
1101    {
[7092]1102#if 1
1103        ref_ptr<osg::BlockAndFlushOperation> block = new osg::BlockAndFlushOperation;
1104   
1105        useThread->add(new DrawInnerOperation( this, renderInfo ));
1106       
1107        useThread->add(block.get());
1108       
1109        // wait till the DrawInnerOperations is complete.
1110        block->block();
1111       
1112        doCopyTexture = false;
1113       
1114#else
[5573]1115        useThread->add(new DrawInnerOperation( this, renderInfo ), true);
[4446]1116       
1117        doCopyTexture = false;
[7092]1118#endif       
[4446]1119    }
1120    else
1121    {
[5573]1122        drawInner( useRenderInfo, previous, doCopyTexture);
[5762]1123       
1124        if (useRenderInfo.getUserData() != renderInfo.getUserData())
1125        {
1126            renderInfo.setUserData(useRenderInfo.getUserData());
1127        }
1128       
[4446]1129    }
1130
[6194]1131    if (useState != &state)
1132    {
[6206]1133        // reset the local State's DynamicObjectCount
[6194]1134        state.setDynamicObjectCount(useState->getDynamicObjectCount());
1135        useState->setDynamicObjectRenderingCompletedCallback(0);
1136    }
[4446]1137
[6194]1138
[4446]1139    // now copy the rendered image to attached texture.
1140    if (_texture.valid() && !doCopyTexture)
1141    {
1142        if (callingContext && useContext!= callingContext)
1143        {
1144            // make the calling context use the pbuffer context for reading.
1145            callingContext->makeContextCurrent(useContext);
1146        }
1147
[5573]1148        copyTexture(renderInfo);
[4446]1149    }
1150
1151    if (_camera && _camera->getPostDrawCallback())
1152    {
1153        // if we have a camera with a post draw callback invoke it.
[7896]1154        (*(_camera->getPostDrawCallback()))(renderInfo);
[4446]1155    }
1156
1157    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1158    {
[7054]1159        useState->popStateSetStackToSize(originalStackSize);
1160
[6221]1161        if (!useThread)
1162        {
[7054]1163
1164
[6221]1165            // flush any command left in the useContex's FIFO
1166            // to ensure that textures are updated before main thread commenses.
1167            glFlush();
[7054]1168           
[6221]1169       
1170            useContext->releaseContext();
1171        }
[4446]1172    }
1173
[4438]1174    if (callingContext && useContext != callingContext)
1175    {
1176        // restore the graphics context.
[7037]1177       
1178        previous = saved_previous;
1179       
[7054]1180        // osg::notify(osg::NOTICE)<<"  nested state after - "<<useState->getStateSetStackSize()<<std::endl;
1181        // osg::notify(osg::NOTICE)<<"  enclosing state after - "<<state.getStateSetStackSize()<<std::endl;
1182
[4438]1183        callingContext->makeCurrent();
1184    }
1185
[7896]1186    // render all the post draw callbacks
[5573]1187    drawPostRenderStages(renderInfo,previous);
[7896]1188
1189    if (_camera && _camera->getFinalDrawCallback())
1190    {
1191        // if we have a camera with a final callback invoke it.
1192        (*(_camera->getFinalDrawCallback()))(renderInfo);
1193    }
1194
1195    // pop the render stages camera.
1196    if (_camera) renderInfo.popCamera();
[1223]1197}
1198
[5573]1199void RenderStage::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[1223]1200{
[5573]1201    osg::State& state = *renderInfo.getState();
[4831]1202
[26]1203    if (!_viewport)
1204    {
[597]1205        notify(FATAL) << "Error: cannot draw stage due to undefined viewport."<< std::endl;
[26]1206        return;
1207    }
[7122]1208
[10]1209    // set up the back buffer.
[611]1210    state.applyAttribute(_viewport.get());
[10]1211
[5884]1212    glScissor( static_cast<int>(_viewport->x()),
1213               static_cast<int>(_viewport->y()),
1214               static_cast<int>(_viewport->width()),
1215               static_cast<int>(_viewport->height()) );
[1554]1216    //cout << "    clearing "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
[10236]1217    state.applyMode( GL_SCISSOR_TEST, true );
[10]1218
1219    // glEnable( GL_DEPTH_TEST );
1220
[185]1221    // set which color planes to operate on.
1222    if (_colorMask.valid()) _colorMask->apply(state);
1223    else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1224
[10]1225    if (_clearMask & GL_COLOR_BUFFER_BIT)
[10236]1226    {
[10]1227        glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
[10236]1228    }
[10]1229
1230    if (_clearMask & GL_DEPTH_BUFFER_BIT)
[10236]1231    {
[10]1232        glClearDepth( _clearDepth);
[10236]1233        glDepthMask ( GL_TRUE );
1234        state.haveAppliedAttribute( osg::StateAttribute::DEPTH );
1235    }
[10]1236
1237    if (_clearMask & GL_STENCIL_BUFFER_BIT)
[10236]1238    {
[10]1239        glClearStencil( _clearStencil);
[10277]1240        glStencilMask ( ~0u );
[10236]1241        state.haveAppliedAttribute( osg::StateAttribute::STENCIL );
1242    }
[10]1243
1244    if (_clearMask & GL_ACCUM_BUFFER_BIT)
[10236]1245    {
[10]1246        glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
[10236]1247    }
[10]1248
1249
1250    glClear( _clearMask );
[2542]1251   
[10236]1252#ifdef USE_SCISSOR_TEST
[10]1253    glDisable( GL_SCISSOR_TEST );
1254#endif
1255
1256    glMatrixMode( GL_MODELVIEW );
1257    glLoadIdentity();
1258
[4395]1259    // apply the positional state.
[4492]1260    if (_inheritedPositionalStateContainer.valid())
[4395]1261    {
[4492]1262        _inheritedPositionalStateContainer->draw(state, previous, &_inheritedPositionalStateContainerMatrix);
[4395]1263    }
[10]1264
[4395]1265    // apply the positional state.
1266    if (_renderStageLighting.valid())
1267    {
1268        _renderStageLighting->draw(state, previous, 0);
1269    }
1270
[10]1271    // draw the children and local.
[5573]1272    RenderBin::drawImplementation(renderInfo,previous);
[10]1273
[5330]1274    state.apply();
[7122]1275
[10]1276}
[4332]1277
[5573]1278void RenderStage::drawPostRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[4332]1279{
1280    if (_postRenderList.empty()) return;
1281   
1282    //cout << "Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1283    for(RenderStageList::iterator itr=_postRenderList.begin();
1284        itr!=_postRenderList.end();
1285        ++itr)
1286    {
[5573]1287        itr->second->draw(renderInfo,previous);
[4332]1288    }
1289    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1290}
1291
[10]1292// Statistics features
[4933]1293bool RenderStage::getStats(Statistics& stats) const
[10]1294{
[4933]1295    bool statsCollected = false;
1296
1297    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1298        pre_itr != _preRenderList.end();
1299        ++pre_itr)
[673]1300    {
[5524]1301        if (pre_itr->second->getStats(stats))
[4933]1302        {
1303            statsCollected = true;
1304        }
[673]1305    }
[4933]1306
1307    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1308        post_itr != _postRenderList.end();
1309        ++post_itr)
1310    {
[5524]1311        if (post_itr->second->getStats(stats))
[4933]1312        {
1313            statsCollected = true;
1314        }
1315    }
1316       
1317    if (RenderBin::getStats(stats))
1318    {
1319        statsCollected = true;
1320    }
1321    return statsCollected;
[10]1322}
[5756]1323
[5757]1324void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
[5756]1325{
1326    _bufferAttachmentMap[buffer]._image = image;
1327}
[6069]1328
1329unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const
1330{
1331    unsigned int count = 0;
1332
1333    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1334        pre_itr != _preRenderList.end();
1335        ++pre_itr)
1336    {
1337        count += pre_itr->second->computeNumberOfDynamicRenderLeaves();
1338    }
1339
1340    count += RenderBin::computeNumberOfDynamicRenderLeaves();
1341
1342    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1343        post_itr != _postRenderList.end();
1344        ++post_itr)
1345    {
1346        count += post_itr->second->computeNumberOfDynamicRenderLeaves();
1347    }
1348   
1349    return count;
1350}
1351
[8447]1352
1353void osgUtil::RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo)
1354{
1355    if (fbo && fbo->isMultisample())
1356    {
1357        osg::notify(osg::WARN) << "Resolve framebuffer must not be"
1358            " multisampled." << std::endl;
1359    }
1360    _resolveFbo = fbo;
1361}
Note: See TracBrowser for help on using the browser.