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

Revision 13041, 55.8 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • 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            for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
632                itr != bufferAttachments.end();
633                ++itr)
634            {
635
636                osg::Camera::BufferComponent buffer = itr->first;
637                osg::Camera::Attachment& attachment = itr->second;
638                switch(buffer)
639                {
640                    case(osg::Camera::DEPTH_BUFFER):
641                    {
642                        traits->depth = 24;
643                        depthAttached = true;
644                        break;
645                    }
646                    case(osg::Camera::STENCIL_BUFFER):
647                    {
648                        traits->stencil = 8;
649                        break;
650                    }
651                    case(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER):
652                    {
653                        traits->depth = 24;
654                        depthAttached = true;
655                        traits->stencil = 8;
656                    }
657                    case(osg::Camera::COLOR_BUFFER):
658                    {
659                        if (attachment._internalFormat!=GL_NONE)
660                        {
661                            bufferFormat = attachment._internalFormat;
662                        }
663                        else
664                        {
665                            if (attachment._texture.valid())
666                            {
667                                pBufferTexture = attachment._texture.get();
668                                bufferFormat = attachment._texture->getInternalFormat();
669                            }
670                            else if (attachment._image.valid())
671                            {
672                                bufferFormat = attachment._image->getInternalTextureFormat();
673                            }
674                            else
675                            {
676                                bufferFormat = GL_RGBA;
677                            }
678                        }
679
680                        level = attachment._level;
681                        face = attachment._face;
682
683                        if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
684                        {
685                            traits->target = attachment._texture.valid() ? attachment._texture->getTextureTarget() : 0;
686                            traits->format = bufferFormat;
687                            traits->level = level;
688                            traits->face = face;
689                            traits->mipMapGeneration = attachment._mipMapGeneration;
690                        }
691                        break;
692                    }
693                    default:
694                    {
695                        if (renderTargetImplementation==osg::Camera::SEPERATE_WINDOW)
696                        {
697                            OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Window ";
698                        }
699                        else
700                        {
701                            OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";
702                        }
703
704                        OSG_NOTICE<<"does not support multiple color outputs."<<std::endl;
705                        break;
706                    }
707
708                }
709            }
710
711            if (!depthAttached)
712            {
713                traits->depth = 24;
714            }
715
716            if (!colorAttached)
717            {
718                if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;
719
720                traits->red = 8;
721                traits->green = 8;
722                traits->blue = 8;
723                traits->alpha = (bufferFormat==GL_RGBA) ? 8 : 0;
724            }
725
726            // share OpenGL objects if possible...
727            if (state.getGraphicsContext())
728            {
729                traits->sharedContext = state.getGraphicsContext();
730
731                const osg::GraphicsContext::Traits* sharedTraits = traits->sharedContext->getTraits();
732                if (sharedTraits)
733                {
734                    traits->hostName = sharedTraits->hostName;
735                    traits->displayNum = sharedTraits->displayNum;
736                    traits->screenNum = sharedTraits->screenNum;
737                }
738            }
739
740            // create the graphics context according to these traits.
741            context = osg::GraphicsContext::createGraphicsContext(traits.get());
742
743            if (context.valid() && context->realize())
744            {
745                OSG_INFO<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;
746
747                // successfully set up graphics context as requested,
748                // will assign this graphics context to the RenderStage and
749                // associated parameters.  Setting the graphics context will
750                // single this while loop to exit successful.
751                setGraphicsContext(context.get());
752
753                // how to do we detect that an attempt to set up RTT has failed??
754
755                setDrawBuffer(GL_FRONT);
756                setReadBuffer(GL_FRONT);
757
758                if (pBufferTexture && renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
759                {
760                   OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assign graphis context to Texture"<<std::endl;
761                   pBufferTexture->setReadPBuffer(context.get());
762                }
763                else
764                {
765                    OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assigning texture to RenderStage so that it does the copy"<<std::endl;
766                    setTexture(pBufferTexture, level, face);
767                }
768            }
769            else
770            {
771                OSG_INFO<<"Failed to acquire Graphics Context"<<std::endl;
772
773                if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT)
774                {
775                    // fallback to using standard PBuffer, this will allow this while loop to continue
776                    if (renderTargetImplementation<renderTargetFallback)
777                        renderTargetImplementation = renderTargetFallback;
778                    else
779                        renderTargetImplementation = osg::Camera::PIXEL_BUFFER;
780                }
781                else
782                {
783                    renderTargetImplementation = osg::Camera::FRAME_BUFFER;
784                }
785            }
786
787        }
788    }
789
790    // finally if all else has failed, then the frame buffer fallback will come in to play.
791    if (renderTargetImplementation==osg::Camera::FRAME_BUFFER)
792    {
793        OSG_INFO<<"Setting up osg::Camera::FRAME_BUFFER"<<std::endl;
794
795        for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();
796            itr != bufferAttachments.end();
797            ++itr)
798        {
799            // assign the texture...
800            if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);
801        }
802    }
803
804}
805
806void RenderStage::copyTexture(osg::RenderInfo& renderInfo)
807{
808    osg::State& state = *renderInfo.getState();
809
810    if ( _readBufferApplyMask )
811    {
812        #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
813            glReadBuffer(_readBuffer);
814        #endif
815    }
816
817    // need to implement texture cube map etc...
818    osg::Texture1D* texture1D = 0;
819    osg::Texture2D* texture2D = 0;
820    osg::Texture3D* texture3D = 0;
821    osg::TextureRectangle* textureRec = 0;
822    osg::TextureCubeMap* textureCubeMap = 0;
823
824    // use TexCopySubImage with the offset of the viewport into the texture
825    // note, this path mirrors the pbuffer and fbo means for updating the texture.
826    // Robert Osfield, 3rd August 2006.
827    if ((texture2D = dynamic_cast<osg::Texture2D*>(_texture.get())) != 0)
828    {
829        texture2D->copyTexSubImage2D(state,
830                                     static_cast<int>(_viewport->x()),
831                                     static_cast<int>(_viewport->y()),
832                                     static_cast<int>(_viewport->x()),
833                                     static_cast<int>(_viewport->y()),
834                                     static_cast<int>(_viewport->width()),
835                                     static_cast<int>(_viewport->height()));
836    }
837    else if ((textureRec = dynamic_cast<osg::TextureRectangle*>(_texture.get())) != 0)
838    {
839        textureRec->copyTexSubImage2D(state,
840                                     static_cast<int>(_viewport->x()),
841                                     static_cast<int>(_viewport->y()),
842                                     static_cast<int>(_viewport->x()),
843                                     static_cast<int>(_viewport->y()),
844                                     static_cast<int>(_viewport->width()),
845                                     static_cast<int>(_viewport->height()));
846    }
847    else if ((texture1D = dynamic_cast<osg::Texture1D*>(_texture.get())) != 0)
848    {
849        // need to implement
850        texture1D->copyTexSubImage1D(state,
851                                     static_cast<int>(_viewport->x()),
852                                     static_cast<int>(_viewport->x()),
853                                     static_cast<int>(_viewport->y()),
854                                     static_cast<int>(_viewport->width()));
855    }
856    else if ((texture3D = dynamic_cast<osg::Texture3D*>(_texture.get())) != 0)
857    {
858        // need to implement
859        texture3D->copyTexSubImage3D(state,
860                                     static_cast<int>(_viewport->x()),
861                                     static_cast<int>(_viewport->y()),
862                                     _face,
863                                     static_cast<int>(_viewport->x()),
864                                     static_cast<int>(_viewport->y()),
865                                     static_cast<int>(_viewport->width()),
866                                     static_cast<int>(_viewport->height()));
867    }
868    else if ((textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(_texture.get())) != 0)
869    {
870        // need to implement
871        textureCubeMap->copyTexSubImageCubeMap(state, _face,
872                                     static_cast<int>(_viewport->x()),
873                                     static_cast<int>(_viewport->y()),
874                                     static_cast<int>(_viewport->x()),
875                                     static_cast<int>(_viewport->y()),
876                                     static_cast<int>(_viewport->width()),
877                                     static_cast<int>(_viewport->height()));
878    }
879}
880
881void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, bool& doCopyTexture)
882{
883    struct SubFunc
884    {
885        static void applyReadFBO(bool& apply_read_fbo,
886            const FrameBufferObject* read_fbo, osg::State& state)
887        {
888            if (read_fbo->isMultisample())
889            {
890                OSG_WARN << "Attempting to read from a"
891                    " multisampled framebuffer object. Set a resolve"
892                    " framebuffer on the RenderStage to fix this." << std::endl;
893            }
894
895            if (apply_read_fbo)
896            {
897                // Bind the monosampled FBO to read from
898                read_fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
899                apply_read_fbo = false;
900            }
901        }
902    };
903
904    osg::State& state = *renderInfo.getState();
905
906    osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID(),true) : 0;
907    bool fbo_supported = fbo_ext && fbo_ext->isSupported();
908
909    bool using_multiple_render_targets = fbo_supported && _fbo->hasMultipleRenderingTargets();
910
911    if (!using_multiple_render_targets)
912    {
913        #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
914
915            if( getDrawBufferApplyMask() )
916                glDrawBuffer(_drawBuffer);
917
918            if( getReadBufferApplyMask() )
919                glReadBuffer(_readBuffer);
920
921        #endif
922    }
923
924    if (fbo_supported)
925    {
926        _fbo->apply(state);
927    }
928
929    // do the drawing itself.
930    RenderBin::draw(renderInfo,previous);
931
932
933    if(state.getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
934    {
935        if (state.checkGLErrors("after RenderBin::draw(..)"))
936        {
937            if ( fbo_ext )
938            {
939                GLenum fbstatus = fbo_ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
940                if ( fbstatus != GL_FRAMEBUFFER_COMPLETE_EXT )
941                {
942                    OSG_NOTICE<<"RenderStage::drawInner(,) FBO status = 0x"<<std::hex<<fbstatus<<std::dec<<std::endl;
943                }
944            }
945        }
946    }
947
948    const FrameBufferObject* read_fbo = fbo_supported ? _fbo.get() : 0;
949    bool apply_read_fbo = false;
950
951    if (fbo_supported && _resolveFbo.valid() && fbo_ext->glBlitFramebuffer)
952    {
953        GLbitfield blitMask = 0;
954        bool needToBlitColorBuffers = false;
955
956        //find which buffer types should be copied
957        for (FrameBufferObject::AttachmentMap::const_iterator
958            it = _resolveFbo->getAttachmentMap().begin(),
959            end =_resolveFbo->getAttachmentMap().end(); it != end; ++it)
960        {
961            switch (it->first)
962            {
963            case Camera::DEPTH_BUFFER:
964                blitMask |= GL_DEPTH_BUFFER_BIT;
965                break;
966            case Camera::STENCIL_BUFFER:
967                blitMask |= GL_STENCIL_BUFFER_BIT;
968                break;
969            case Camera::PACKED_DEPTH_STENCIL_BUFFER:
970                blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
971                break;
972            case Camera::COLOR_BUFFER:
973                blitMask |= GL_COLOR_BUFFER_BIT;
974                break;
975            default:
976                needToBlitColorBuffers = true;
977                break;
978            }
979        }
980
981        // Bind the resolve framebuffer to blit into.
982        _fbo->apply(state, FrameBufferObject::READ_FRAMEBUFFER);
983        _resolveFbo->apply(state, FrameBufferObject::DRAW_FRAMEBUFFER);
984
985        if (blitMask)
986        {
987            // Blit to the resolve framebuffer.
988            // Note that (with nvidia 175.16 windows drivers at least) if the read
989            // framebuffer is multisampled then the dimension arguments are ignored
990            // and the whole framebuffer is always copied.
991            fbo_ext->glBlitFramebuffer(
992                0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
993                0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
994                blitMask, GL_NEAREST);
995        }
996
997#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
998        if (needToBlitColorBuffers)
999        {
1000            for (FrameBufferObject::AttachmentMap::const_iterator
1001                it = _resolveFbo->getAttachmentMap().begin(),
1002                end =_resolveFbo->getAttachmentMap().end(); it != end; ++it)
1003            {
1004                osg::Camera::BufferComponent attachment = it->first;
1005                if (attachment >=osg::Camera::COLOR_BUFFER0)
1006                {
1007                    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
1008                    glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
1009
1010                    fbo_ext->glBlitFramebuffer(
1011                        0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
1012                        0, 0, static_cast<GLint>(_viewport->width()), static_cast<GLint>(_viewport->height()),
1013                        GL_COLOR_BUFFER_BIT, GL_NEAREST);
1014                }
1015            }
1016            // reset the read and draw buffers?  will comment out for now with the assumption that
1017            // the buffers will be set explictly when needed elsewhere.
1018            // glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1019            // glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
1020        }
1021#endif
1022
1023        apply_read_fbo = true;
1024        read_fbo = _resolveFbo.get();
1025
1026        using_multiple_render_targets = read_fbo->hasMultipleRenderingTargets();
1027    }
1028
1029    // now copy the rendered image to attached texture.
1030    if (doCopyTexture)
1031    {
1032        if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
1033        copyTexture(renderInfo);
1034    }
1035
1036    std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
1037    for(itr = _bufferAttachmentMap.begin();
1038        itr != _bufferAttachmentMap.end();
1039        ++itr)
1040    {
1041        if (itr->second._image.valid())
1042        {
1043            if (read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
1044
1045            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
1046
1047                if (using_multiple_render_targets)
1048                {
1049                    int attachment=itr->first;
1050                    if (attachment==osg::Camera::DEPTH_BUFFER || attachment==osg::Camera::STENCIL_BUFFER) {
1051                        // assume first buffer rendered to is the one we want
1052                        glReadBuffer(read_fbo->getMultipleRenderingTargets()[0]);
1053                    } else {
1054                        glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0));
1055                    }
1056                } else {
1057                    if (_readBuffer != GL_NONE)
1058                    {
1059                        glReadBuffer(_readBuffer);
1060                    }
1061                }
1062
1063            #endif
1064
1065            GLenum pixelFormat = itr->second._image->getPixelFormat();
1066            if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;
1067            if (pixelFormat==0) pixelFormat = GL_RGB;
1068
1069            GLenum dataType = itr->second._image->getDataType();
1070            if (dataType==0) dataType = _imageReadPixelDataType;
1071            if (dataType==0) dataType = GL_UNSIGNED_BYTE;
1072
1073            itr->second._image->readPixels(static_cast<int>(_viewport->x()),
1074                                           static_cast<int>(_viewport->y()),
1075                                           static_cast<int>(_viewport->width()),
1076                                           static_cast<int>(_viewport->height()),
1077                                           pixelFormat, dataType);
1078        }
1079    }
1080
1081    if (fbo_supported)
1082    {
1083        if (getDisableFboAfterRender())
1084        {
1085            // switch off the frame buffer object
1086            GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;
1087            fbo_ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
1088        }
1089
1090        doCopyTexture = true;
1091    }
1092
1093    if (fbo_supported && _camera)
1094    {
1095        // now generate mipmaps if they are required.
1096        const osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();
1097        for(osg::Camera::BufferAttachmentMap::const_iterator itr = bufferAttachments.begin();
1098            itr != bufferAttachments.end();
1099            ++itr)
1100        {
1101            if (itr->second._texture.valid() && itr->second._mipMapGeneration)
1102            {
1103                state.setActiveTextureUnit(0);
1104                state.applyTextureAttribute(0, itr->second._texture.get());
1105                fbo_ext->glGenerateMipmap(itr->second._texture->getTextureTarget());
1106            }
1107        }
1108    }
1109}
1110
1111struct DrawInnerOperation : public osg::Operation
1112{
1113    DrawInnerOperation(RenderStage* stage, osg::RenderInfo& renderInfo) :
1114        osg::Operation("DrawInnerStage",false),
1115        _stage(stage),
1116        _renderInfo(renderInfo) {}
1117
1118    virtual void operator () (osg::Object* object)
1119    {
1120        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1121        if (!context) return;
1122
1123        // OSG_NOTICE<<"DrawInnerOperation operator"<<std::endl;
1124        if (_stage && context)
1125        {
1126            RenderLeaf* previous = 0;
1127            bool doCopyTexture = false;
1128            _renderInfo.setState(context->getState());
1129            _stage->drawInner(_renderInfo, previous, doCopyTexture);
1130        }
1131    }
1132
1133    RenderStage* _stage;
1134    RenderInfo _renderInfo;
1135};
1136
1137
1138void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
1139{
1140    if (_stageDrawnThisFrame) return;
1141
1142    if(_initialViewMatrix.valid()) renderInfo.getState()->setInitialViewMatrix(_initialViewMatrix.get());
1143
1144    // push the stages camera so that drawing code can query it
1145    if (_camera) renderInfo.pushCamera(_camera);
1146
1147    _stageDrawnThisFrame = true;
1148
1149    if (_camera && _camera->getInitialDrawCallback())
1150    {
1151        // if we have a camera with a intial draw callback invoke it.
1152        (*(_camera->getInitialDrawCallback()))(renderInfo);
1153    }
1154
1155    // note, SceneView does call to drawPreRenderStages explicitly
1156    // so there is no need to call it here.
1157    drawPreRenderStages(renderInfo,previous);
1158
1159    if (_cameraRequiresSetUp)
1160    {
1161        runCameraSetUp(renderInfo);
1162    }
1163
1164    osg::State& state = *renderInfo.getState();
1165
1166    osg::State* useState = &state;
1167    osg::GraphicsContext* callingContext = state.getGraphicsContext();
1168    osg::GraphicsContext* useContext = callingContext;
1169    osg::OperationThread* useThread = 0;
1170    osg::RenderInfo useRenderInfo(renderInfo);
1171
1172    RenderLeaf* saved_previous = previous;
1173
1174    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1175    {
1176        // show we release the context so that others can use it?? will do so right
1177        // now as an experiment.
1178        callingContext->releaseContext();
1179
1180        // OSG_NOTICE<<"  enclosing state before - "<<state.getStateSetStackSize()<<std::endl;
1181
1182        useState = _graphicsContext->getState();
1183        useContext = _graphicsContext.get();
1184        useThread = useContext->getGraphicsThread();
1185        useRenderInfo.setState(useState);
1186
1187        // synchronize the frame stamps
1188        useState->setFrameStamp(const_cast<osg::FrameStamp*>(state.getFrameStamp()));
1189
1190        // map the DynamicObjectCount across to the new window
1191        useState->setDynamicObjectCount(state.getDynamicObjectCount());
1192        useState->setDynamicObjectRenderingCompletedCallback(state.getDynamicObjectRenderingCompletedCallback());
1193
1194        if (!useThread)
1195        {
1196            previous = 0;
1197            useContext->makeCurrent();
1198
1199            // OSG_NOTICE<<"  nested state before - "<<useState->getStateSetStackSize()<<std::endl;
1200        }
1201    }
1202
1203    unsigned int originalStackSize = useState->getStateSetStackSize();
1204
1205    if (_camera && _camera->getPreDrawCallback())
1206    {
1207        // if we have a camera with a pre draw callback invoke it.
1208        (*(_camera->getPreDrawCallback()))(renderInfo);
1209    }
1210
1211    bool doCopyTexture = _texture.valid() ?
1212                        (callingContext != useContext) :
1213                        false;
1214
1215    if (useThread)
1216    {
1217#if 1
1218        ref_ptr<osg::BlockAndFlushOperation> block = new osg::BlockAndFlushOperation;
1219
1220        useThread->add(new DrawInnerOperation( this, renderInfo ));
1221
1222        useThread->add(block.get());
1223
1224        // wait till the DrawInnerOperations is complete.
1225        block->block();
1226
1227        doCopyTexture = false;
1228
1229#else
1230        useThread->add(new DrawInnerOperation( this, renderInfo ), true);
1231
1232        doCopyTexture = false;
1233#endif
1234    }
1235    else
1236    {
1237        drawInner( useRenderInfo, previous, doCopyTexture);
1238
1239        if (useRenderInfo.getUserData() != renderInfo.getUserData())
1240        {
1241            renderInfo.setUserData(useRenderInfo.getUserData());
1242        }
1243
1244    }
1245
1246    if (useState != &state)
1247    {
1248        // reset the local State's DynamicObjectCount
1249        state.setDynamicObjectCount(useState->getDynamicObjectCount());
1250        useState->setDynamicObjectRenderingCompletedCallback(0);
1251    }
1252
1253
1254    // now copy the rendered image to attached texture.
1255    if (_texture.valid() && !doCopyTexture)
1256    {
1257        if (callingContext && useContext!= callingContext)
1258        {
1259            // make the calling context use the pbuffer context for reading.
1260            callingContext->makeContextCurrent(useContext);
1261        }
1262
1263        copyTexture(renderInfo);
1264    }
1265
1266    if (_camera && _camera->getPostDrawCallback())
1267    {
1268        // if we have a camera with a post draw callback invoke it.
1269        (*(_camera->getPostDrawCallback()))(renderInfo);
1270    }
1271
1272    if (_graphicsContext.valid() && _graphicsContext != callingContext)
1273    {
1274        useState->popStateSetStackToSize(originalStackSize);
1275
1276        if (!useThread)
1277        {
1278
1279
1280            // flush any command left in the useContex's FIFO
1281            // to ensure that textures are updated before main thread commenses.
1282            glFlush();
1283
1284
1285            useContext->releaseContext();
1286        }
1287    }
1288
1289    if (callingContext && useContext != callingContext)
1290    {
1291        // restore the graphics context.
1292
1293        previous = saved_previous;
1294
1295        // OSG_NOTICE<<"  nested state after - "<<useState->getStateSetStackSize()<<std::endl;
1296        // OSG_NOTICE<<"  enclosing state after - "<<state.getStateSetStackSize()<<std::endl;
1297
1298        callingContext->makeCurrent();
1299    }
1300
1301    // render all the post draw callbacks
1302    drawPostRenderStages(renderInfo,previous);
1303
1304    if (_camera && _camera->getFinalDrawCallback())
1305    {
1306        // if we have a camera with a final callback invoke it.
1307        (*(_camera->getFinalDrawCallback()))(renderInfo);
1308    }
1309
1310    // pop the render stages camera.
1311    if (_camera) renderInfo.popCamera();
1312}
1313
1314void RenderStage::drawImplementation(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
1315{
1316    osg::State& state = *renderInfo.getState();
1317
1318    if (!_viewport)
1319    {
1320        OSG_FATAL << "Error: cannot draw stage due to undefined viewport."<< std::endl;
1321        return;
1322    }
1323
1324    // set up the back buffer.
1325    state.applyAttribute(_viewport.get());
1326
1327    glScissor( static_cast<int>(_viewport->x()),
1328               static_cast<int>(_viewport->y()),
1329               static_cast<int>(_viewport->width()),
1330               static_cast<int>(_viewport->height()) );
1331    //cout << "    clearing "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1332    state.applyMode( GL_SCISSOR_TEST, true );
1333
1334    // glEnable( GL_DEPTH_TEST );
1335
1336    // set which color planes to operate on.
1337    if (_colorMask.valid()) _colorMask->apply(state);
1338    else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1339
1340    if (_clearMask & GL_COLOR_BUFFER_BIT)
1341    {
1342        glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
1343    }
1344
1345    if (_clearMask & GL_DEPTH_BUFFER_BIT)
1346    {
1347        #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
1348            glClearDepth( _clearDepth);
1349        #else
1350            glClearDepthf( _clearDepth);
1351        #endif
1352
1353        glDepthMask ( GL_TRUE );
1354        state.haveAppliedAttribute( osg::StateAttribute::DEPTH );
1355    }
1356
1357    if (_clearMask & GL_STENCIL_BUFFER_BIT)
1358    {
1359        glClearStencil( _clearStencil);
1360        glStencilMask ( ~0u );
1361        state.haveAppliedAttribute( osg::StateAttribute::STENCIL );
1362    }
1363
1364    #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
1365        if (_clearMask & GL_ACCUM_BUFFER_BIT)
1366        {
1367            glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
1368        }
1369    #endif
1370
1371
1372    glClear( _clearMask );
1373
1374    #ifdef USE_SCISSOR_TEST
1375        glDisable( GL_SCISSOR_TEST );
1376    #endif
1377
1378    #ifdef OSG_GL_MATRICES_AVAILABLE
1379        glMatrixMode( GL_MODELVIEW );
1380        glLoadIdentity();
1381    #endif
1382
1383    // apply the positional state.
1384    if (_inheritedPositionalStateContainer.valid())
1385    {
1386        _inheritedPositionalStateContainer->draw(state, previous, &_inheritedPositionalStateContainerMatrix);
1387    }
1388
1389    // apply the positional state.
1390    if (_renderStageLighting.valid())
1391    {
1392        _renderStageLighting->draw(state, previous, 0);
1393    }
1394
1395    // draw the children and local.
1396    RenderBin::drawImplementation(renderInfo,previous);
1397
1398    state.apply();
1399
1400}
1401
1402void RenderStage::drawPostRenderStages(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
1403{
1404    if (_postRenderList.empty()) return;
1405
1406    //cout << "Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1407    for(RenderStageList::iterator itr=_postRenderList.begin();
1408        itr!=_postRenderList.end();
1409        ++itr)
1410    {
1411        itr->second->draw(renderInfo,previous);
1412    }
1413    //cout << "Done Drawing prerendering stages "<<this<< "  "<<_viewport->x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<<std::endl;
1414}
1415
1416// Statistics features
1417bool RenderStage::getStats(Statistics& stats) const
1418{
1419    bool statsCollected = false;
1420
1421    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1422        pre_itr != _preRenderList.end();
1423        ++pre_itr)
1424    {
1425        if (pre_itr->second->getStats(stats))
1426        {
1427            statsCollected = true;
1428        }
1429    }
1430
1431    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1432        post_itr != _postRenderList.end();
1433        ++post_itr)
1434    {
1435        if (post_itr->second->getStats(stats))
1436        {
1437            statsCollected = true;
1438        }
1439    }
1440
1441    if (RenderBin::getStats(stats))
1442    {
1443        statsCollected = true;
1444    }
1445    return statsCollected;
1446}
1447
1448void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
1449{
1450    _bufferAttachmentMap[buffer]._image = image;
1451}
1452
1453unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const
1454{
1455    unsigned int count = 0;
1456
1457    for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
1458        pre_itr != _preRenderList.end();
1459        ++pre_itr)
1460    {
1461        count += pre_itr->second->computeNumberOfDynamicRenderLeaves();
1462    }
1463
1464    count += RenderBin::computeNumberOfDynamicRenderLeaves();
1465
1466    for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
1467        post_itr != _postRenderList.end();
1468        ++post_itr)
1469    {
1470        count += post_itr->second->computeNumberOfDynamicRenderLeaves();
1471    }
1472
1473    return count;
1474}
1475
1476
1477void RenderStage::setMultisampleResolveFramebufferObject(osg::FrameBufferObject* fbo)
1478{
1479    if (fbo && fbo->isMultisample())
1480    {
1481        OSG_WARN << "Resolve framebuffer must not be"
1482            " multisampled." << std::endl;
1483    }
1484    _resolveFbo = fbo;
1485}
1486
1487void RenderStage::collateReferencesToDependentCameras()
1488{
1489    _dependentCameras.clear();
1490
1491    for(RenderStageList::iterator itr = _preRenderList.begin();
1492        itr != _preRenderList.end();
1493        ++itr)
1494    {
1495        itr->second->collateReferencesToDependentCameras();
1496        osg::Camera* camera = itr->second->getCamera();
1497        if (camera) _dependentCameras.push_back(camera);
1498    }
1499
1500    for(RenderStageList::iterator itr = _postRenderList.begin();
1501        itr != _postRenderList.end();
1502        ++itr)
1503    {
1504        itr->second->collateReferencesToDependentCameras();
1505        osg::Camera* camera = itr->second->getCamera();
1506        if (camera) _dependentCameras.push_back(camera);
1507    }
1508}
1509
1510void RenderStage::clearReferencesToDependentCameras()
1511{
1512    for(RenderStageList::iterator itr = _preRenderList.begin();
1513        itr != _preRenderList.end();
1514        ++itr)
1515    {
1516        itr->second->collateReferencesToDependentCameras();
1517    }
1518
1519    for(RenderStageList::iterator itr = _postRenderList.begin();
1520        itr != _postRenderList.end();
1521        ++itr)
1522    {
1523        itr->second->collateReferencesToDependentCameras();
1524    }
1525
1526    _dependentCameras.clear();
1527}
1528
1529void RenderStage::releaseGLObjects(osg::State* state) const
1530{
1531    RenderBin::releaseGLObjects(state);
1532
1533    for(RenderStageList::const_iterator itr = _preRenderList.begin();
1534        itr != _preRenderList.end();
1535        ++itr)
1536    {
1537        itr->second->releaseGLObjects(state);
1538    }
1539
1540    for(RenderStageList::const_iterator itr = _postRenderList.begin();
1541        itr != _postRenderList.end();
1542        ++itr)
1543    {
1544        itr->second->releaseGLObjects(state);
1545    }
1546
1547    for(Cameras::const_iterator itr = _dependentCameras.begin();
1548        itr != _dependentCameras.end();
1549        ++itr)
1550    {
1551        (*itr)->releaseGLObjects(state);
1552    }
1553
1554    if (_texture.valid()) _texture->releaseGLObjects(state);
1555
1556    if (_fbo.valid()) _fbo->releaseGLObjects(state);
1557    if (_resolveFbo.valid()) _resolveFbo->releaseGLObjects(state);
1558    if (_graphicsContext.valid())  _graphicsContext->releaseGLObjects(state);
1559}
Note: See TracBrowser for help on using the browser.