Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/OgreGLFrameBufferObject.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 8.4 KB
RevLine 
[1]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30#include "OgreGLFrameBufferObject.h"
31#include "OgreGLPixelFormat.h"
32#include "OgreLogManager.h"
33#include "OgreStringConverter.h"
34#include "OgreRoot.h"
35#include "OgreGLHardwarePixelBuffer.h"
36#include "OgreGLFBORenderTexture.h"
37
38namespace Ogre {
39
40//-----------------------------------------------------------------------------
41    GLFrameBufferObject::GLFrameBufferObject(GLFBOManager *manager):
42        mManager(manager)
43    {
44        /// Generate framebuffer object
45        glGenFramebuffersEXT(1, &mFB);
46        /// Initialise state
47        mDepth.buffer=0;
48        mStencil.buffer=0;
49        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
50        {
51            mColour[x].buffer=0;
52        }
53    }
54    GLFrameBufferObject::~GLFrameBufferObject()
55    {
56        mManager->releaseRenderBuffer(mDepth);
57        mManager->releaseRenderBuffer(mStencil);
58        /// Delete framebuffer object
59        glDeleteFramebuffersEXT(1, &mFB);       
60    }
61    void GLFrameBufferObject::bindSurface(size_t attachment, const GLSurfaceDesc &target)
62    {
63        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
64        mColour[attachment] = target;
65                // Re-initialise
66                if(mColour[0].buffer)
67                        initialise();
68    }
69    void GLFrameBufferObject::unbindSurface(size_t attachment)
70    {
71        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
72        mColour[attachment].buffer = 0;
73                // Re-initialise if buffer 0 still bound
74                if(mColour[0].buffer)
75                {
76                        initialise();
77                }
78    }
79    void GLFrameBufferObject::initialise()
80    {
81                // Release depth and stencil, if they were bound
82        mManager->releaseRenderBuffer(mDepth);
83        mManager->releaseRenderBuffer(mStencil);
84        /// First buffer must be bound
85        if(!mColour[0].buffer)
86        {
87            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
88            "Attachment 0 must have surface attached",
89                        "GLFrameBufferObject::initialise");
90        }
91        /// Bind FBO to frame buffer
92        bind();
93        /// Store basic stats
94        size_t width = mColour[0].buffer->getWidth();
95        size_t height = mColour[0].buffer->getHeight();
96        GLuint format = mColour[0].buffer->getGLFormat();
97        PixelFormat ogreFormat = mColour[0].buffer->getFormat();
98        /// Bind all attachment points to frame buffer
99        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
100        {
101            if(mColour[x].buffer)
102            {
103                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
104                {
105                    std::stringstream ss;
106                    ss << "Attachment " << x << " has incompatible size ";
107                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
108                    ss << ". It must be of the same as the size of surface 0, ";
109                    ss << width << "x" << height;
110                    ss << ".";
111                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
112                }
113                if(mColour[x].buffer->getGLFormat() != format)
114                {
115                    std::stringstream ss;
116                    ss << "Attachment " << x << " has incompatible format.";
117                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
118                }
119                    mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColour[x].zoffset);
120            }
121            else
122            {
123                // Detach
124                glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+x,
125                    GL_RENDERBUFFER_EXT, 0);
126            }
127        }
128        /// Find suitable depth and stencil format that is compatible with colour format
129        GLenum depthFormat, stencilFormat;
130        mManager->getBestDepthStencil(ogreFormat, &depthFormat, &stencilFormat);
131       
132        /// Request surfaces
133        mDepth = mManager->requestRenderBuffer(depthFormat, width, height);
134                if (depthFormat == GL_DEPTH24_STENCIL8_EXT)
135                {
136                        // bind same buffer to depth and stencil attachments
137            mManager->requestRenderBuffer(mDepth);
138                        mStencil = mDepth;
139                }
140                else
141                {
142                        // separate stencil
143                        mStencil = mManager->requestRenderBuffer(stencilFormat, width, height);
144                }
145       
146        /// Attach/detach surfaces
147        if(mDepth.buffer)
148        {
149            mDepth.buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT_EXT, mDepth.zoffset);
150        }
151        else
152        {
153            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
154                GL_RENDERBUFFER_EXT, 0);
155        }
156        if(mStencil.buffer)
157        {
158            mStencil.buffer->bindToFramebuffer(GL_STENCIL_ATTACHMENT_EXT, mStencil.zoffset);
159        }
160        else
161        {
162            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
163                GL_RENDERBUFFER_EXT, 0);
164        }
165
166                /// Do glDrawBuffer calls
167                GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
168                GLsizei n=0;
169                for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
170                {
171                        // Fill attached colour buffers
172                        if(mColour[x].buffer)
173                        {
174                                bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
175                                // Keep highest used buffer + 1
176                                n = x+1;
177                        }
178                        else
179                        {
180                                bufs[x] = GL_NONE;
181                        }
182                }
183                if(glDrawBuffers)
184                {
185                        /// Drawbuffer extension supported, use it
186                        glDrawBuffers(n, bufs);
187                }
188                else
189                {
190                        /// In this case, the capabilities will not show more than 1 simultaneaous render target.
191                        glDrawBuffer(bufs[0]);
192                }
193                /// No read buffer, by default, if we want to read anyway we must not forget to set this.
194                glReadBuffer(GL_NONE);
195       
196        /// Check status
197        GLuint status;
198        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
199       
200        /// Bind main buffer
201        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
202       
203        switch(status)
204        {
205        case GL_FRAMEBUFFER_COMPLETE_EXT:
206            // All is good
207            break;
208        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
209            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
210            "All framebuffer formats with this texture internal format unsupported",
211                        "GLFrameBufferObject::initialise");
212        default:
213            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
214            "Framebuffer incomplete or other FBO status error",
215                        "GLFrameBufferObject::initialise");
216        }
217       
218    }
219    void GLFrameBufferObject::bind()
220    {
221        /// Bind it to FBO
222        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
223    }
224    size_t GLFrameBufferObject::getWidth()
225    {
226        assert(mColour[0].buffer);
227        return mColour[0].buffer->getWidth();
228    }
229    size_t GLFrameBufferObject::getHeight()
230    {
231        assert(mColour[0].buffer);
232        return mColour[0].buffer->getHeight();
233    }
234    PixelFormat GLFrameBufferObject::getFormat()
235    {
236        assert(mColour[0].buffer);
237        return mColour[0].buffer->getFormat();
238    }
239//-----------------------------------------------------------------------------
240}
Note: See TracBrowser for help on using the repository browser.