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

Revision 10277, 48.4 kB (checked in by robert, 4 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
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
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*/
13#include <stdio.h>
14
15#include <osg/Notify>
16#include <osg/Texture1D>
17#include <osg/Texture2D>
18#include <osg/Texture3D>
19#include <osg/TextureRectangle>
20#include <osg/TextureCubeMap>
21#include <osg/GLExtensions>
22#include <osg/GLU>
23
24#include <osgUtil/Statistics>
25
26#include <osgUtil/RenderStage>
27
28
29using namespace osg;
30using namespace osgUtil;
31
32// register a RenderStage prototype with the RenderBin prototype list.
33//RegisterRenderBinProxy<RenderStage> s_registerRenderStageProxy;
34
35RenderStage::RenderStage():
36    RenderBin(getDefaultRenderBinSortMode()),
37    _disableFboAfterRender(true)
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
44    _drawBuffer = GL_NONE;
45    _readBuffer = GL_NONE;
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;
51
52    _cameraRequiresSetUp = false;
53    _camera = 0;
54   
55    _level = 0;
56    _face = 0;
57   
58    _imageReadPixelFormat = GL_RGBA;
59    _imageReadPixelDataType = GL_UNSIGNED_BYTE;
60}
61
62RenderStage::RenderStage(SortMode mode):
63    RenderBin(mode),
64    _disableFboAfterRender(true)
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
71    _drawBuffer = GL_NONE;
72    _readBuffer = GL_NONE;
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;
78
79    _cameraRequiresSetUp = false;
80    _camera = 0;
81   
82    _level = 0;
83    _face = 0;
84   
85    _imageReadPixelFormat = GL_RGBA;
86    _imageReadPixelDataType = GL_UNSIGNED_BYTE;
87}
88
89RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop):
90        RenderBin(rhs,copyop),
91        _stageDrawnThisFrame(false),
92        _preRenderList(rhs._preRenderList),
93        _postRenderList(rhs._postRenderList),
94        _viewport(rhs._viewport),
95        _drawBuffer(rhs._drawBuffer),
96        _readBuffer(rhs._readBuffer),
97        _clearMask(rhs._clearMask),
98        _colorMask(rhs._colorMask),
99        _clearColor(rhs._clearColor),
100        _clearAccum(rhs._clearAccum),
101        _clearDepth(rhs._clearDepth),
102        _clearStencil(rhs._clearStencil),
103        _cameraRequiresSetUp(rhs._cameraRequiresSetUp),
104        _camera(rhs._camera),
105        _level(rhs._level),
106        _face(rhs._face),
107        _imageReadPixelFormat(rhs._imageReadPixelFormat),
108        _imageReadPixelDataType(rhs._imageReadPixelDataType),
109        _disableFboAfterRender(rhs._disableFboAfterRender),
110        _renderStageLighting(rhs._renderStageLighting)
111{
112    _stage = this;
113}
114
115
116RenderStage::~RenderStage()
117{
118}
119
120void RenderStage::reset()
121{
122    _stageDrawnThisFrame = false;
123   
124    if (_renderStageLighting.valid()) _renderStageLighting->reset();
125
126    for(RenderStageList::iterator pre_itr = _preRenderList.begin();
127        pre_itr != _preRenderList.end();
128        ++pre_itr)
129    {
130        pre_itr->second->reset();
131    }
132
133    RenderBin::reset();
134
135    for(RenderStageList::iterator post_itr = _postRenderList.begin();
136        post_itr != _postRenderList.end();
137        ++post_itr)
138    {
139        post_itr->second->reset();
140    }
141
142    _preRenderList.clear();
143    _postRenderList.clear();
144}
145
146void RenderStage::sort()
147{
148    for(RenderStageList::iterator pre_itr = _preRenderList.begin();
149        pre_itr != _preRenderList.end();
150        ++pre_itr)
151    {
152        pre_itr->second->sort();
153    }
154
155    RenderBin::sort();
156
157    for(RenderStageList::iterator post_itr = _postRenderList.begin();
158        post_itr != _postRenderList.end();
159        ++post_itr)
160    {
161        post_itr->second->sort();
162    }
163}
164
165void RenderStage::addPreRenderStage(RenderStage* rs, int order)
166{
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    }
181}
182
183void RenderStage::addPostRenderStage(RenderStage* rs, int order)
184{
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    }
199}
200
201void RenderStage::drawPreRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
202{
203    if (_preRenderList.empty()) return;
204   
205    //cout << "Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
206    for(RenderStageList::iterator itr=_preRenderList.begin();
207        itr!=_preRenderList.end();
208        ++itr)
209    {
210        itr->second->draw(renderInfo,previous);
211    }
212    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
213}
214
215
216void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
217{
218    _cameraRequiresSetUp = false;
219
220    if (!_camera) return;
221   
222    osg::State& state = *renderInfo.getState();
223
224    osg::Camera::RenderTargetImplementation renderTargetImplementation = _camera->getRenderTargetImplementation();
225    osg::Camera::RenderTargetImplementation renderTargetFallback = _camera->getRenderTargetFallback();
226
227    osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
228
229    // compute the required dimensions
230    int width = static_cast<int>(_viewport->x() + _viewport->width());
231    int height = static_cast<int>(_viewport->y() + _viewport->height());
232    int depth = 1;
233    osg::Camera::BufferAttachmentMap::iterator itr;
234    for(itr = bufferAttachments.begin();
235        itr != bufferAttachments.end();
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
246    // attach images that need to be copied after the stage is drawn.
247    for(itr = bufferAttachments.begin();
248        itr != bufferAttachments.end();
249        ++itr)
250    {
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
268            _bufferAttachmentMap[itr->first]._imageReadPixelFormat = pixelFormat;
269            _bufferAttachmentMap[itr->first]._imageReadPixelDataType = dataType;
270            _bufferAttachmentMap[itr->first]._image = image;
271        }
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                {
285                    texture1D->setTextureWidth(width);
286                }
287            }
288            else if (0 != (texture2D = dynamic_cast<osg::Texture2D*>(texture)))
289            {
290                if (texture2D->getTextureWidth()==0 || texture2D->getTextureHeight()==0)
291                {
292                    texture2D->setTextureSize(width,height);
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..
300                    texture3D->setTextureSize(width,height,height);
301                }
302            }
303            else if (0 != (textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture)))
304            {
305                if (textureCubeMap->getTextureWidth()==0 || textureCubeMap->getTextureHeight()==0)
306                {
307                    textureCubeMap->setTextureSize(width,height);
308                }
309            }
310            else if (0 != (textureRectangle = dynamic_cast<osg::TextureRectangle*>(texture)))
311            {
312                if (textureRectangle->getTextureWidth()==0 || textureRectangle->getTextureHeight()==0)
313                {
314                    textureRectangle->setTextureSize(width,height);
315                }
316            }
317
318        }
319    }
320   
321    if (renderTargetImplementation==osg::Camera::FRAME_BUFFER_OBJECT)
322    {
323        osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(state.getContextID(),true);
324        bool fbo_supported = fbo_ext && fbo_ext->isSupported();
325       
326        if (fbo_supported && !_fbo)
327        {
328            osg::notify(osg::INFO)<<"Setting up osg::Camera::FRAME_BUFFER_OBJECT"<<std::endl;
329
330            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*(_camera->getDataChangeMutex()));
331
332            osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;
333            osg::ref_ptr<osg::FrameBufferObject> fbo_multisample;
334           
335            bool colorAttached = false;
336            bool depthAttached = false;
337            bool stencilAttached = false;
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);
349                    colorSamples = maximum(colorSamples, attachment._multisampleColorSamples);
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            }
364           
365            for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
366                itr != bufferAttachments.end();
367                ++itr)
368            {
369
370                osg::Camera::BufferComponent buffer = itr->first;
371                osg::Camera::Attachment& attachment = itr->second;
372               
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)));
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;
391                        case Camera::PACKED_DEPTH_STENCIL_BUFFER:
392                            internalFormat = GL_DEPTH_STENCIL_EXT;
393                            break;
394
395                        // all other buffers are color buffers
396                        default:
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;
402                            break;
403                        }
404                    }
405                    fbo_multisample->setAttachment(buffer,
406                        osg::FrameBufferAttachment(new osg::RenderBuffer(
407                        width, height, internalFormat,
408                        samples, colorSamples)));
409                }
410               
411                if (buffer==osg::Camera::DEPTH_BUFFER) depthAttached = true;
412                else if (buffer==osg::Camera::STENCIL_BUFFER) stencilAttached = true;
413                else if (buffer==osg::Camera::PACKED_DEPTH_STENCIL_BUFFER)
414                {
415                    depthAttached = true;
416                    stencilAttached = true;
417                }
418                else if (buffer>=osg::Camera::COLOR_BUFFER) colorAttached = true;
419               
420            }
421
422            if (!depthAttached)
423            {               
424                fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24)));
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                }
431            }
432
433            if (!colorAttached)
434            {               
435                fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB)));
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                }
442            }
443
444            fbo->apply(state);
445           
446            GLenum status = fbo_ext->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
447           
448            if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
449            {
450                osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x"<<std::hex<<status<<std::dec<<std::endl;
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);
468       
469                _fbo = fbo;
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"
481                            << std::hex << status << std::dec << std::endl;
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                }
503            }
504        }
505       
506        if (!fbo_supported)
507        {
508            if (renderTargetImplementation<renderTargetFallback)
509                renderTargetImplementation = renderTargetFallback;
510            else
511                renderTargetImplementation = osg::Camera::PIXEL_BUFFER_RTT;
512        }
513    }
514   
515    // check whether PBuffer-RTT is supported or not
516    if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT &&
517        !osg::isGLExtensionSupported(state.getContextID(), "WGL_ARB_render_texture"))
518    {   
519        if (renderTargetImplementation<renderTargetFallback)
520            renderTargetImplementation = renderTargetFallback;
521        else
522            renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
523    }
524
525    // if any of the renderTargetImplementations require a separate graphics context such as with pbuffer try in turn to
526    // set up, but if each level fails then resort to the next level down.   
527    while (!getGraphicsContext() &&
528           (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT ||
529            renderTargetImplementation==osg::Camera::PIXEL_BUFFER ||
530            renderTargetImplementation==osg::Camera::SEPERATE_WINDOW) )
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
539            traits->width = width;
540            traits->height = height;
541
542            // osg::notify(osg::NOTICE)<<"traits = "<<traits->width<<" "<<traits->height<<std::endl;
543
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);
547
548            osg::Texture* pBufferTexture = 0;
549            GLenum bufferFormat = GL_NONE;
550            unsigned int level = 0;
551            unsigned int face = 0;
552
553            bool colorAttached = false;
554            bool depthAttached = false;
555            bool stencilAttached = false;
556            for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
557                itr != bufferAttachments.end();
558                ++itr)
559            {
560
561                osg::Camera::BufferComponent buffer = itr->first;
562                osg::Camera::Attachment& attachment = itr->second;
563                switch(buffer)
564                {
565                    case(osg::Camera::DEPTH_BUFFER):
566                    {
567                        traits->depth = 24;
568                        depthAttached = true;
569                        break;
570                    }
571                    case(osg::Camera::STENCIL_BUFFER):
572                    {
573                        traits->stencil = 8;
574                        stencilAttached = true;
575                        break;
576                    }
577                    case(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER):
578                    {
579                        traits->depth = 24;
580                        depthAttached = true;
581                        traits->stencil = 8;
582                        stencilAttached = true;
583                    }
584                    case(osg::Camera::COLOR_BUFFER):
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
607                        level = attachment._level;
608                        face = attachment._face;
609
610                        if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
611                        {
612                            traits->target = attachment._texture.valid() ? attachment._texture->getTextureTarget() : 0;
613                            traits->format = bufferFormat;
614                            traits->level = level;
615                            traits->face = face;
616                            traits->mipMapGeneration = attachment._mipMapGeneration;
617                        }
618                        break;
619                    }
620                    default:
621                    {
622                        if (renderTargetImplementation==osg::Camera::SEPERATE_WINDOW)
623                            osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Window ";
624                        else
625                            osg::notify(osg::NOTICE)<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";
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            {               
636                traits->depth = 24;
637            }
638
639            if (!colorAttached)
640            {               
641                if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
642
643                traits->red = 8;
644                traits->green = 8;
645                traits->blue = 8;
646                traits->alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
647            }
648
649            // share OpenGL objects if possible...
650            if (state.getGraphicsContext())
651            {
652                traits->sharedContext = state.getGraphicsContext();
653               
654                const osg::GraphicsContext::Traits* sharedTraits = traits->sharedContext->getTraits();
655                if (sharedTraits)
656                {
657                    traits->hostName = sharedTraits->hostName;
658                    traits->displayNum = sharedTraits->displayNum;
659                    traits->screenNum = sharedTraits->screenNum;
660                }
661            }
662
663            // create the graphics context according to these traits.
664            context = osg::GraphicsContext::createGraphicsContext(traits.get());
665
666            if (context.valid() && context->realize())
667            {
668                osg::notify(osg::INFO)<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;
669
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??
677
678                setDrawBuffer(GL_FRONT);
679                setReadBuffer(GL_FRONT);
680
681                if (pBufferTexture && renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
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
693            {
694                osg::notify(osg::INFO)<<"Failed to acquire Graphics Context"<<std::endl;
695               
696                if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
697                {
698                    // fallback to using standard PBuffer, this will allow this while loop to continue
699                    if (renderTargetImplementation<renderTargetFallback)
700                        renderTargetImplementation = renderTargetFallback;
701                    else
702                        renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
703                }
704                else 
705                {
706                    renderTargetImplementation = osg::Camera::FRAME_BUFFER;
707                }
708            }
709
710        }
711    }
712   
713    // finally if all else has failed, then the frame buffer fallback will come in to play.
714    if (renderTargetImplementation==osg::Camera::FRAME_BUFFER)
715    {
716        osg::notify(osg::INFO)<<"Setting up osg::Camera::FRAME_BUFFER"<<std::endl;
717
718        for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
719            itr != bufferAttachments.end();
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
727}
728
729void RenderStage::copyTexture(osg::RenderInfo& renderInfo)
730{
731    osg::State& state = *renderInfo.getState();
732
733    if (_readBuffer != GL_NONE)
734    {
735        glReadBuffer(_readBuffer);
736    }
737
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;
744
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.
748    if ((texture2D = dynamic_cast<osg::Texture2D*>(_texture.get())) != 0)
749    {
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()));
757    }
758    else if ((textureRec = dynamic_cast<osg::TextureRectangle*>(_texture.get())) != 0)
759    {
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()));
767    }
768    else if ((texture1D = dynamic_cast<osg::Texture1D*>(_texture.get())) != 0)
769    {
770        // need to implement
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()));
776    }
777    else if ((texture3D = dynamic_cast<osg::Texture3D*>(_texture.get())) != 0)
778    {
779        // need to implement
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()));
788    }
789    else if ((textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(_texture.get())) != 0)
790    {
791        // need to implement
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()));
799    }
800}
801
802void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, bool& doCopyTexture)
803{
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
825    osg::State& state = *renderInfo.getState();
826
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();
831   
832    if (!using_multiple_render_targets)
833    {
834        if (_drawBuffer != GL_NONE)
835        {   
836            glDrawBuffer(_drawBuffer);
837        }
838
839        if (_readBuffer != GL_NONE)
840        {
841            glReadBuffer(_readBuffer);
842        }
843    }
844
845    if (fbo_supported)
846    {
847        _fbo->apply(state);
848    }
849
850    // do the drawing itself.   
851    RenderBin::draw(renderInfo,previous);
852
853
854    if(state.getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
855    {
856        GLenum errorNo = glGetError();
857        if (errorNo!=GL_NO_ERROR)
858        {
859            const char* error = (char*)gluErrorString(errorNo);
860            if (error)  osg::notify(osg::NOTICE)<<"Warning: detected OpenGL error '"<<error<<"' after RenderBin::draw(,)"<<std::endl;
861            else        osg::notify(osg::NOTICE)<<"Warning: detected OpenGL errorNo= 0x"<<std::hex<<errorNo<<" after RenderBin::draw(,)"<<std::dec<<std::endl;
862
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;
864        }
865    }
866
867    const FrameBufferObject* read_fbo = fbo_supported ? _fbo.get() : 0;
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;
887            case Camera::PACKED_DEPTH_STENCIL_BUFFER:
888                blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
889            default:
890                blitMask |= GL_COLOR_BUFFER_BIT;
891                break;
892            }
893        }
894
895        // Bind the resolve framebuffer to blit into.
896        _fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
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
914    // now copy the rendered image to attached texture.
915    if (doCopyTexture)
916    {
917        if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
918        copyTexture(renderInfo);
919    }
920
921    std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
922    for(itr = _bufferAttachmentMap.begin();
923        itr != _bufferAttachmentMap.end();
924        ++itr)
925    {
926        if (itr->second._image.valid())
927        {
928            if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
929
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            }
945
946            GLenum pixelFormat = itr->second._image->getPixelFormat();
947            if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
948            if (pixelFormat==0) pixelFormat = GL_RGB;
949
950            GLenum dataType = itr->second._image->getDataType();
951            if (dataType==0) dataType = _imageReadPixelDataType;
952            if (dataType==0) dataType = GL_UNSIGNED_BYTE;       
953
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
962    if (fbo_supported)
963    {
964        if (getDisableFboAfterRender())
965        {
966            // switch off the frame buffer object
967            fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
968        }
969
970        doCopyTexture = true;
971    }
972
973    if (fbo_supported && _camera)
974    {
975        // now generate mipmaps if they are required.
976        const osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
977        for(osg::Camera::BufferAttachmentMap::const_iterator itr = bufferAttachments.begin();
978            itr != bufferAttachments.end();
979            ++itr)
980        {
981            if (itr->second._texture.valid() && itr->second._mipMapGeneration)
982            {
983                state.setActiveTextureUnit(0);
984                state.applyTextureAttribute(0, itr->second._texture.get());
985                fbo_ext->glGenerateMipmapEXT(itr->second._texture->getTextureTarget());
986            }
987        }
988    }
989}
990
991struct DrawInnerOperation : public osg::Operation
992{
993    DrawInnerOperation(RenderStage* stage, osg::RenderInfo& renderInfo) :
994        osg::Operation("DrawInnerStage",false),
995        _stage(stage),
996        _renderInfo(renderInfo) {}
997
998    virtual void operator () (osg::Object* object)
999    {
1000        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1001        if (!context) return;
1002
1003        // osg::notify(osg::NOTICE)<<"DrawInnerOperation operator"<<std::endl;
1004        if (_stage && context)
1005        {
1006            RenderLeaf* previous = 0;
1007            bool doCopyTexture = false;
1008            _renderInfo.setState(context->getState());
1009            _stage->drawInner(_renderInfo, previous, doCopyTexture);
1010        }
1011    }
1012   
1013    RenderStage* _stage;
1014    RenderInfo _renderInfo;
1015};
1016
1017
1018void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
1019{
1020    if (_stageDrawnThisFrame) return;
1021
1022    // push the stages camera so that drawing code can query it     
1023    if (_camera) renderInfo.pushCamera(_camera);
1024
1025    _stageDrawnThisFrame = true;
1026
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
1033    // note, SceneView does call to drawPreRenderStages explicitly
1034    // so there is no need to call it here.
1035    drawPreRenderStages(renderInfo,previous);
1036   
1037    if (_cameraRequiresSetUp)
1038    {
1039        runCameraSetUp(renderInfo);
1040    }
1041
1042    osg::State& state = *renderInfo.getState();
1043
1044    osg::State* useState = &state;
1045    osg::GraphicsContext* callingContext = state.getGraphicsContext();
1046    osg::GraphicsContext* useContext = callingContext;
1047    osg::OperationThread* useThread = 0;
1048    osg::RenderInfo useRenderInfo(renderInfo);
1049   
1050    RenderLeaf* saved_previous = previous;
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   
1058        // osg::notify(osg::NOTICE)<<"  enclosing state before - "<<state.getStateSetStackSize()<<std::endl;
1059
1060        useState = _graphicsContext->getState();
1061        useContext = _graphicsContext.get();
1062        useThread = useContext->getGraphicsThread();
1063        useRenderInfo.setState(useState);
1064       
1065        // synchronize the frame stamps
1066        useState->setFrameStamp(const_cast<osg::FrameStamp*>(state.getFrameStamp()));
1067
1068        // map the DynamicObjectCount across to the new window
1069        useState->setDynamicObjectCount(state.getDynamicObjectCount());
1070        useState->setDynamicObjectRenderingCompletedCallback(state.getDynamicObjectRenderingCompletedCallback());
1071       
1072        if (!useThread)
1073        {
1074            previous = 0;
1075            useContext->makeCurrent();
1076           
1077            // osg::notify(osg::NOTICE)<<"  nested state before - "<<useState->getStateSetStackSize()<<std::endl;
1078        }
1079    }
1080
1081    unsigned int originalStackSize = useState->getStateSetStackSize();
1082
1083    if (_camera && _camera->getPreDrawCallback())
1084    {
1085        // if we have a camera with a pre draw callback invoke it.
1086        (*(_camera->getPreDrawCallback()))(renderInfo);
1087    }
1088   
1089    bool doCopyTexture = _texture.valid() ?
1090                        (callingContext != useContext) :
1091                        false;
1092
1093    if (useThread)
1094    {
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
1108        useThread->add(new DrawInnerOperation( this, renderInfo ), true);
1109       
1110        doCopyTexture = false;
1111#endif       
1112    }
1113    else
1114    {
1115        drawInner( useRenderInfo, previous, doCopyTexture);
1116       
1117        if (useRenderInfo.getUserData() != renderInfo.getUserData())
1118        {
1119            renderInfo.setUserData(useRenderInfo.getUserData());
1120        }
1121       
1122    }
1123
1124    if (useState != &state)
1125    {
1126        // reset the local State's DynamicObjectCount
1127        state.setDynamicObjectCount(useState->getDynamicObjectCount());
1128        useState->setDynamicObjectRenderingCompletedCallback(0);
1129    }
1130
1131
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
1141        copyTexture(renderInfo);
1142    }
1143
1144    if (_camera && _camera->getPostDrawCallback())
1145    {
1146        // if we have a camera with a post draw callback invoke it.
1147        (*(_camera->getPostDrawCallback()))(renderInfo);
1148    }
1149
1150    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1151    {
1152        useState->popStateSetStackToSize(originalStackSize);
1153
1154        if (!useThread)
1155        {
1156
1157
1158            // flush any command left in the useContex's FIFO
1159            // to ensure that textures are updated before main thread commenses.
1160            glFlush();
1161           
1162       
1163            useContext->releaseContext();
1164        }
1165    }
1166
1167    if (callingContext && useContext != callingContext)
1168    {
1169        // restore the graphics context.
1170       
1171        previous = saved_previous;
1172       
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
1176        callingContext->makeCurrent();
1177    }
1178
1179    // render all the post draw callbacks
1180    drawPostRenderStages(renderInfo,previous);
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();
1190}
1191
1192void RenderStage::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
1193{
1194    osg::State& state = *renderInfo.getState();
1195
1196    if (!_viewport)
1197    {
1198        notify(FATAL) << "Error: cannot draw stage due to undefined viewport."<< std::endl;
1199        return;
1200    }
1201
1202    // set up the back buffer.
1203    state.applyAttribute(_viewport.get());
1204
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()) );
1209    //cout << "    clearing "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1210    state.applyMode( GL_SCISSOR_TEST, true );
1211
1212    // glEnable( GL_DEPTH_TEST );
1213
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
1218    if (_clearMask & GL_COLOR_BUFFER_BIT)
1219    {
1220        glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
1221    }
1222
1223    if (_clearMask & GL_DEPTH_BUFFER_BIT)
1224    {
1225        glClearDepth( _clearDepth);
1226        glDepthMask ( GL_TRUE );
1227        state.haveAppliedAttribute( osg::StateAttribute::DEPTH );
1228    }
1229
1230    if (_clearMask & GL_STENCIL_BUFFER_BIT)
1231    {
1232        glClearStencil( _clearStencil);
1233        glStencilMask ( ~0u );
1234        state.haveAppliedAttribute( osg::StateAttribute::STENCIL );
1235    }
1236
1237    if (_clearMask & GL_ACCUM_BUFFER_BIT)
1238    {
1239        glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
1240    }
1241
1242
1243    glClear( _clearMask );
1244   
1245#ifdef USE_SCISSOR_TEST
1246    glDisable( GL_SCISSOR_TEST );
1247#endif
1248
1249    glMatrixMode( GL_MODELVIEW );
1250    glLoadIdentity();
1251
1252    // apply the positional state.
1253    if (_inheritedPositionalStateContainer.valid())
1254    {
1255        _inheritedPositionalStateContainer->draw(state, previous, &_inheritedPositionalStateContainerMatrix);
1256    }
1257
1258    // apply the positional state.
1259    if (_renderStageLighting.valid())
1260    {
1261        _renderStageLighting->draw(state, previous, 0);
1262    }
1263
1264    // draw the children and local.
1265    RenderBin::drawImplementation(renderInfo,previous);
1266
1267    state.apply();
1268
1269}
1270
1271void RenderStage::drawPostRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
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    {
1280        itr->second->draw(renderInfo,previous);
1281    }
1282    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1283}
1284
1285// Statistics features
1286bool RenderStage::getStats(Statistics& stats) const
1287{
1288    bool statsCollected = false;
1289
1290    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1291        pre_itr != _preRenderList.end();
1292        ++pre_itr)
1293    {
1294        if (pre_itr->second->getStats(stats))
1295        {
1296            statsCollected = true;
1297        }
1298    }
1299
1300    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1301        post_itr != _postRenderList.end();
1302        ++post_itr)
1303    {
1304        if (post_itr->second->getStats(stats))
1305        {
1306            statsCollected = true;
1307        }
1308    }
1309       
1310    if (RenderBin::getStats(stats))
1311    {
1312        statsCollected = true;
1313    }
1314    return statsCollected;
1315}
1316
1317void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
1318{
1319    _bufferAttachmentMap[buffer]._image = image;
1320}
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
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.