root/OpenSceneGraph/trunk/src/osgUtil/RenderStage.cpp @ 12552

Revision 12552, 56.5 kB (checked in by robert, 3 years ago)

Added GLES version checks to prevent build problems under GLES1 and GLES2

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