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

Revision 11264, 48.8 kB (checked in by paulmartz, 4 years ago)

2.8 branch: Mergine recent changes to FBX. Revisions in this commit: r11251, r11252, r11262.

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