root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osgUtil/RenderStage.cpp @ 10277

Revision 10277, 48.4 kB (checked in by robert, 6 years ago)

Fixed glStencilMask setting.

  • 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:
882                blitMask |= GL_DEPTH_BUFFER_BIT;
883                break;
884            case Camera::STENCIL_BUFFER:
885                blitMask |= GL_STENCIL_BUFFER_BIT;
886                break;
[9239]887            case Camera::PACKED_DEPTH_STENCIL_BUFFER:
888                blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
[8447]889            default:
890                blitMask |= GL_COLOR_BUFFER_BIT;
891                break;
892            }
893        }
894
895        // Bind the resolve framebuffer to blit into.
[9823]896        _fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
[8447]897        _resolveFbo->apply(state, FrameBufferObject::DRAW_FRAMEBUFFER);
898
899        // Blit to the resolve framebuffer.
900        // Note that (with nvidia 175.16 windows drivers at least) if the read
901        // framebuffer is multisampled then the dimension arguments are ignored
902        // and the whole framebuffer is always copied.
903        fbo_ext->glBlitFramebufferEXT(
904            0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
905            0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
906            blitMask, GL_NEAREST);
907
908        apply_read_fbo = true;
909        read_fbo = _resolveFbo.get();
910
911        using_multiple_render_targets = read_fbo->hasMultipleRenderingTargets();
912    }
913
[4438]914    // now copy the rendered image to attached texture.
[4446]915    if (doCopyTexture)
[4438]916    {
[8518]917        if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
[5573]918        copyTexture(renderInfo);
[4438]919    }
[8447]920
[5757]921    std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
[6221]922    for(itr = _bufferAttachmentMap.begin();
923        itr != _bufferAttachmentMap.end();
924        ++itr)
925    {
[8447]926        if (itr->second._image.valid())
927        {
[8518]928            if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
[4438]929
[8447]930            if (using_multiple_render_targets)
931            {
932                int attachment=itr->first;
933                if (attachment==osg::Camera::DEPTH_BUFFER || attachment==osg::Camera::STENCIL_BUFFER) {
934                    // assume first buffer rendered to is the one we want
935                    glReadBuffer(read_fbo->getMultipleRenderingTargets()[0]);
936                } else {
937                    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
938                }
939            } else {
940                if (_readBuffer != GL_NONE)
941                {
942                    glReadBuffer(_readBuffer);
943                }
944            }
[4645]945
[8447]946            GLenum pixelFormat = itr->second._image->getPixelFormat();
947            if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
948            if (pixelFormat==0) pixelFormat = GL_RGB;
[4646]949
[8447]950            GLenum dataType = itr->second._image->getDataType();
951            if (dataType==0) dataType = _imageReadPixelDataType;
952            if (dataType==0) dataType = GL_UNSIGNED_BYTE;       
[5756]953
[8447]954            itr->second._image->readPixels(static_cast<int>(_viewport->x()),
955                                           static_cast<int>(_viewport->y()),
956                                           static_cast<int>(_viewport->width()),
957                                           static_cast<int>(_viewport->height()),
958                                           pixelFormat, dataType);
959        }
960    }
961
[4438]962    if (fbo_supported)
963    {
[8447]964        if (getDisableFboAfterRender())
965        {
966            // switch off the frame buffer object
967            fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
968        }
[4446]969
970        doCopyTexture = true;
[4438]971    }
[8447]972
[4438]973    if (fbo_supported && _camera)
974    {
975        // now generate mipmaps if they are required.
[8447]976        const osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
977        for(osg::Camera::BufferAttachmentMap::const_iterator itr = bufferAttachments.begin();
978            itr != bufferAttachments.end();
[4438]979            ++itr)
980        {
981            if (itr->second._texture.valid() && itr->second._mipMapGeneration)
982            {
[4976]983                state.setActiveTextureUnit(0);
984                state.applyTextureAttribute(0, itr->second._texture.get());
985                fbo_ext->glGenerateMipmapEXT(itr->second._texture->getTextureTarget());
[4438]986            }
987        }
988    }
[4446]989}
[4438]990
[6088]991struct DrawInnerOperation : public osg::Operation
[4446]992{
[5573]993    DrawInnerOperation(RenderStage* stage, osg::RenderInfo& renderInfo) :
[6088]994        osg::Operation("DrawInnerStage",false),
[5573]995        _stage(stage),
996        _renderInfo(renderInfo) {}
[4446]997
[6088]998    virtual void operator () (osg::Object* object)
[4446]999    {
[6088]1000        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1001        if (!context) return;
1002
[4446]1003        // osg::notify(osg::NOTICE)<<"DrawInnerOperation operator"<<std::endl;
1004        if (_stage && context)
1005        {
1006            RenderLeaf* previous = 0;
1007            bool doCopyTexture = false;
[5573]1008            _renderInfo.setState(context->getState());
1009            _stage->drawInner(_renderInfo, previous, doCopyTexture);
[4446]1010        }
1011    }
1012   
1013    RenderStage* _stage;
[5573]1014    RenderInfo _renderInfo;
[4446]1015};
1016
1017
[5573]1018void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[4446]1019{
1020    if (_stageDrawnThisFrame) return;
1021
[7896]1022    // push the stages camera so that drawing code can query it     
1023    if (_camera) renderInfo.pushCamera(_camera);
1024
[4446]1025    _stageDrawnThisFrame = true;
1026
[7896]1027    if (_camera && _camera->getInitialDrawCallback())
1028    {
1029        // if we have a camera with a intial draw callback invoke it.
1030        (*(_camera->getInitialDrawCallback()))(renderInfo);
1031    }
1032
[4446]1033    // note, SceneView does call to drawPreRenderStages explicitly
1034    // so there is no need to call it here.
[5573]1035    drawPreRenderStages(renderInfo,previous);
[4446]1036   
[4573]1037    if (_cameraRequiresSetUp)
1038    {
[5573]1039        runCameraSetUp(renderInfo);
[4573]1040    }
[4446]1041
[5573]1042    osg::State& state = *renderInfo.getState();
[4573]1043
[4446]1044    osg::State* useState = &state;
1045    osg::GraphicsContext* callingContext = state.getGraphicsContext();
1046    osg::GraphicsContext* useContext = callingContext;
[7108]1047    osg::OperationThread* useThread = 0;
[5573]1048    osg::RenderInfo useRenderInfo(renderInfo);
[7037]1049   
1050    RenderLeaf* saved_previous = previous;
[4446]1051
1052    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1053    {
1054        // show we release the context so that others can use it?? will do so right
1055        // now as an experiment.
1056        callingContext->releaseContext();
1057   
[7054]1058        // osg::notify(osg::NOTICE)<<"  enclosing state before - "<<state.getStateSetStackSize()<<std::endl;
1059
[4446]1060        useState = _graphicsContext->getState();
1061        useContext = _graphicsContext.get();
1062        useThread = useContext->getGraphicsThread();
[5573]1063        useRenderInfo.setState(useState);
[4446]1064       
[7648]1065        // synchronize the frame stamps
[5094]1066        useState->setFrameStamp(const_cast<osg::FrameStamp*>(state.getFrameStamp()));
[6206]1067
1068        // map the DynamicObjectCount across to the new window
[6194]1069        useState->setDynamicObjectCount(state.getDynamicObjectCount());
1070        useState->setDynamicObjectRenderingCompletedCallback(state.getDynamicObjectRenderingCompletedCallback());
[5094]1071       
[7037]1072        if (!useThread)
1073        {
1074            previous = 0;
1075            useContext->makeCurrent();
[7054]1076           
1077            // osg::notify(osg::NOTICE)<<"  nested state before - "<<useState->getStateSetStackSize()<<std::endl;
[7037]1078        }
[4446]1079    }
[6806]1080
[7054]1081    unsigned int originalStackSize = useState->getStateSetStackSize();
1082
[6806]1083    if (_camera && _camera->getPreDrawCallback())
1084    {
[7896]1085        // if we have a camera with a pre draw callback invoke it.
1086        (*(_camera->getPreDrawCallback()))(renderInfo);
[6806]1087    }
[4446]1088   
1089    bool doCopyTexture = _texture.valid() ?
1090                        (callingContext != useContext) :
1091                        false;
1092
1093    if (useThread)
1094    {
[7092]1095#if 1
1096        ref_ptr<osg::BlockAndFlushOperation> block = new osg::BlockAndFlushOperation;
1097   
1098        useThread->add(new DrawInnerOperation( this, renderInfo ));
1099       
1100        useThread->add(block.get());
1101       
1102        // wait till the DrawInnerOperations is complete.
1103        block->block();
1104       
1105        doCopyTexture = false;
1106       
1107#else
[5573]1108        useThread->add(new DrawInnerOperation( this, renderInfo ), true);
[4446]1109       
1110        doCopyTexture = false;
[7092]1111#endif       
[4446]1112    }
1113    else
1114    {
[5573]1115        drawInner( useRenderInfo, previous, doCopyTexture);
[5762]1116       
1117        if (useRenderInfo.getUserData() != renderInfo.getUserData())
1118        {
1119            renderInfo.setUserData(useRenderInfo.getUserData());
1120        }
1121       
[4446]1122    }
1123
[6194]1124    if (useState != &state)
1125    {
[6206]1126        // reset the local State's DynamicObjectCount
[6194]1127        state.setDynamicObjectCount(useState->getDynamicObjectCount());
1128        useState->setDynamicObjectRenderingCompletedCallback(0);
1129    }
[4446]1130
[6194]1131
[4446]1132    // now copy the rendered image to attached texture.
1133    if (_texture.valid() && !doCopyTexture)
1134    {
1135        if (callingContext && useContext!= callingContext)
1136        {
1137            // make the calling context use the pbuffer context for reading.
1138            callingContext->makeContextCurrent(useContext);
1139        }
1140
[5573]1141        copyTexture(renderInfo);
[4446]1142    }
1143
1144    if (_camera && _camera->getPostDrawCallback())
1145    {
1146        // if we have a camera with a post draw callback invoke it.
[7896]1147        (*(_camera->getPostDrawCallback()))(renderInfo);
[4446]1148    }
1149
1150    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1151    {
[7054]1152        useState->popStateSetStackToSize(originalStackSize);
1153
[6221]1154        if (!useThread)
1155        {
[7054]1156
1157
[6221]1158            // flush any command left in the useContex's FIFO
1159            // to ensure that textures are updated before main thread commenses.
1160            glFlush();
[7054]1161           
[6221]1162       
1163            useContext->releaseContext();
1164        }
[4446]1165    }
1166
[4438]1167    if (callingContext && useContext != callingContext)
1168    {
1169        // restore the graphics context.
[7037]1170       
1171        previous = saved_previous;
1172       
[7054]1173        // osg::notify(osg::NOTICE)<<"  nested state after - "<<useState->getStateSetStackSize()<<std::endl;
1174        // osg::notify(osg::NOTICE)<<"  enclosing state after - "<<state.getStateSetStackSize()<<std::endl;
1175
[4438]1176        callingContext->makeCurrent();
1177    }
1178
[7896]1179    // render all the post draw callbacks
[5573]1180    drawPostRenderStages(renderInfo,previous);
[7896]1181
1182    if (_camera && _camera->getFinalDrawCallback())
1183    {
1184        // if we have a camera with a final callback invoke it.
1185        (*(_camera->getFinalDrawCallback()))(renderInfo);
1186    }
1187
1188    // pop the render stages camera.
1189    if (_camera) renderInfo.popCamera();
[1223]1190}
1191
[5573]1192void RenderStage::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[1223]1193{
[5573]1194    osg::State& state = *renderInfo.getState();
[4831]1195
[26]1196    if (!_viewport)
1197    {
[597]1198        notify(FATAL) << "Error: cannot draw stage due to undefined viewport."<< std::endl;
[26]1199        return;
1200    }
[7122]1201
[10]1202    // set up the back buffer.
[611]1203    state.applyAttribute(_viewport.get());
[10]1204
[5884]1205    glScissor( static_cast<int>(_viewport->x()),
1206               static_cast<int>(_viewport->y()),
1207               static_cast<int>(_viewport->width()),
1208               static_cast<int>(_viewport->height()) );
[1554]1209    //cout << "    clearing "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
[10236]1210    state.applyMode( GL_SCISSOR_TEST, true );
[10]1211
1212    // glEnable( GL_DEPTH_TEST );
1213
[185]1214    // set which color planes to operate on.
1215    if (_colorMask.valid()) _colorMask->apply(state);
1216    else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1217
[10]1218    if (_clearMask & GL_COLOR_BUFFER_BIT)
[10236]1219    {
[10]1220        glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
[10236]1221    }
[10]1222
1223    if (_clearMask & GL_DEPTH_BUFFER_BIT)
[10236]1224    {
[10]1225        glClearDepth( _clearDepth);
[10236]1226        glDepthMask ( GL_TRUE );
1227        state.haveAppliedAttribute( osg::StateAttribute::DEPTH );
1228    }
[10]1229
1230    if (_clearMask & GL_STENCIL_BUFFER_BIT)
[10236]1231    {
[10]1232        glClearStencil( _clearStencil);
[10277]1233        glStencilMask ( ~0u );
[10236]1234        state.haveAppliedAttribute( osg::StateAttribute::STENCIL );
1235    }
[10]1236
1237    if (_clearMask & GL_ACCUM_BUFFER_BIT)
[10236]1238    {
[10]1239        glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
[10236]1240    }
[10]1241
1242
1243    glClear( _clearMask );
[2542]1244   
[10236]1245#ifdef USE_SCISSOR_TEST
[10]1246    glDisable( GL_SCISSOR_TEST );
1247#endif
1248
1249    glMatrixMode( GL_MODELVIEW );
1250    glLoadIdentity();
1251
[4395]1252    // apply the positional state.
[4492]1253    if (_inheritedPositionalStateContainer.valid())
[4395]1254    {
[4492]1255        _inheritedPositionalStateContainer->draw(state, previous, &_inheritedPositionalStateContainerMatrix);
[4395]1256    }
[10]1257
[4395]1258    // apply the positional state.
1259    if (_renderStageLighting.valid())
1260    {
1261        _renderStageLighting->draw(state, previous, 0);
1262    }
1263
[10]1264    // draw the children and local.
[5573]1265    RenderBin::drawImplementation(renderInfo,previous);
[10]1266
[5330]1267    state.apply();
[7122]1268
[10]1269}
[4332]1270
[5573]1271void RenderStage::drawPostRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
[4332]1272{
1273    if (_postRenderList.empty()) return;
1274   
1275    //cout << "Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1276    for(RenderStageList::iterator itr=_postRenderList.begin();
1277        itr!=_postRenderList.end();
1278        ++itr)
1279    {
[5573]1280        itr->second->draw(renderInfo,previous);
[4332]1281    }
1282    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1283}
1284
[10]1285// Statistics features
[4933]1286bool RenderStage::getStats(Statistics& stats) const
[10]1287{
[4933]1288    bool statsCollected = false;
1289
1290    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1291        pre_itr != _preRenderList.end();
1292        ++pre_itr)
[673]1293    {
[5524]1294        if (pre_itr->second->getStats(stats))
[4933]1295        {
1296            statsCollected = true;
1297        }
[673]1298    }
[4933]1299
1300    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1301        post_itr != _postRenderList.end();
1302        ++post_itr)
1303    {
[5524]1304        if (post_itr->second->getStats(stats))
[4933]1305        {
1306            statsCollected = true;
1307        }
1308    }
1309       
1310    if (RenderBin::getStats(stats))
1311    {
1312        statsCollected = true;
1313    }
1314    return statsCollected;
[10]1315}
[5756]1316
[5757]1317void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
[5756]1318{
1319    _bufferAttachmentMap[buffer]._image = image;
1320}
[6069]1321
1322unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const
1323{
1324    unsigned int count = 0;
1325
1326    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1327        pre_itr != _preRenderList.end();
1328        ++pre_itr)
1329    {
1330        count += pre_itr->second->computeNumberOfDynamicRenderLeaves();
1331    }
1332
1333    count += RenderBin::computeNumberOfDynamicRenderLeaves();
1334
1335    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1336        post_itr != _postRenderList.end();
1337        ++post_itr)
1338    {
1339        count += post_itr->second->computeNumberOfDynamicRenderLeaves();
1340    }
1341   
1342    return count;
1343}
1344
[8447]1345
1346void osgUtil::RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo)
1347{
1348    if (fbo && fbo->isMultisample())
1349    {
1350        osg::notify(osg::WARN) << "Resolve framebuffer must not be"
1351            " multisampled." << std::endl;
1352    }
1353    _resolveFbo = fbo;
1354}
Note: See TracBrowser for help on using the browser.