source: OGRE/trunk/ogrenew/RenderSystems/GL/src/OgreGLFrameBufferObject.cpp @ 692

Revision 692, 8.2 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
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-2005 The OGRE Team
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-----------------------------------------------------------------------------
24*/
25
26#include "OgreGLFrameBufferObject.h"
27#include "OgreGLPixelFormat.h"
28#include "OgreLogManager.h"
29#include "OgreStringConverter.h"
30#include "OgreRoot.h"
31#include "OgreGLHardwarePixelBuffer.h"
32#include "OgreGLFBORenderTexture.h"
33
34namespace Ogre {
35
36//-----------------------------------------------------------------------------
37    GLFrameBufferObject::GLFrameBufferObject(GLFBOManager *manager):
38        mManager(manager)
39    {
40        /// Generate framebuffer object
41        glGenFramebuffersEXT(1, &mFB);
42        /// Initialise state
43        mDepth.buffer=0;
44        mStencil.buffer=0;
45        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
46        {
47            mColour[x].buffer=0;
48        }
49    }
50    GLFrameBufferObject::~GLFrameBufferObject()
51    {
52        mManager->releaseRenderBuffer(mDepth);
53        mManager->releaseRenderBuffer(mStencil);
54        /// Delete framebuffer object
55        glDeleteFramebuffersEXT(1, &mFB);       
56    }
57    void GLFrameBufferObject::bindSurface(size_t attachment, const GLSurfaceDesc &target)
58    {
59        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
60        mColour[attachment] = target;
61                // Re-initialise
62                if(mColour[0].buffer)
63                        initialise();
64    }
65    void GLFrameBufferObject::unbindSurface(size_t attachment)
66    {
67        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
68        mColour[attachment].buffer = 0;
69                // Re-initialise if buffer 0 still bound
70                if(mColour[0].buffer)
71                {
72                        initialise();
73                }
74    }
75    void GLFrameBufferObject::initialise()
76    {
77                // Release depth and stencil, if they were bound
78        mManager->releaseRenderBuffer(mDepth);
79        mManager->releaseRenderBuffer(mStencil);
80        /// First buffer must be bound
81        if(!mColour[0].buffer)
82        {
83            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
84            "Attachment 0 must have surface attached",
85                        "GLFrameBufferObject::initialise");
86        }
87        /// Bind FBO to frame buffer
88        bind();
89        /// Store basic stats
90        size_t width = mColour[0].buffer->getWidth();
91        size_t height = mColour[0].buffer->getHeight();
92        GLuint format = mColour[0].buffer->getGLFormat();
93        PixelFormat ogreFormat = mColour[0].buffer->getFormat();
94        /// Bind all attachment points to frame buffer
95        for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
96        {
97            if(mColour[x].buffer)
98            {
99                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
100                {
101                    std::stringstream ss;
102                    ss << "Attachment " << x << " has incompatible size ";
103                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
104                    ss << ". It must be of the same as the size of surface 0, ";
105                    ss << width << "x" << height;
106                    ss << ".";
107                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
108                }
109                if(mColour[x].buffer->getGLFormat() != format)
110                {
111                    std::stringstream ss;
112                    ss << "Attachment " << x << " has incompatible format.";
113                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLFrameBufferObject::initialise");
114                }
115                    mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColour[x].zoffset);
116            }
117            else
118            {
119                // Detach
120                glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+x,
121                    GL_RENDERBUFFER_EXT, 0);
122            }
123        }
124        /// Find suitable depth and stencil format that is compatible with colour format
125        GLenum depthFormat, stencilFormat;
126        mManager->getBestDepthStencil(ogreFormat, &depthFormat, &stencilFormat);
127       
128        /// Request surfaces
129        mDepth = mManager->requestRenderBuffer(depthFormat, width, height);
130                if (depthFormat == GL_DEPTH24_STENCIL8_EXT)
131                {
132                        // bind same buffer to depth and stencil attachments
133                        mStencil = mDepth;
134                }
135                else
136                {
137                        // separate stencil
138                        mStencil = mManager->requestRenderBuffer(stencilFormat, width, height);
139                }
140       
141        /// Attach/detach surfaces
142        if(mDepth.buffer)
143        {
144            mDepth.buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT_EXT, mDepth.zoffset);
145        }
146        else
147        {
148            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
149                GL_RENDERBUFFER_EXT, 0);
150        }
151        if(mStencil.buffer)
152        {
153            mStencil.buffer->bindToFramebuffer(GL_STENCIL_ATTACHMENT_EXT, mDepth.zoffset);
154        }
155        else
156        {
157            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
158                GL_RENDERBUFFER_EXT, 0);
159        }
160
161                /// Do glDrawBuffer calls
162                GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
163                GLsizei n=0;
164                for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
165                {
166                        // Fill attached colour buffers
167                        if(mColour[x].buffer)
168                        {
169                                bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
170                                // Keep highest used buffer + 1
171                                n = x+1;
172                        }
173                        else
174                        {
175                                bufs[x] = GL_NONE;
176                        }
177                }
178                if(glDrawBuffers)
179                {
180                        /// Drawbuffer extension supported, use it
181                        glDrawBuffers(n, bufs);
182                }
183                else
184                {
185                        /// In this case, the capabilities will not show more than 1 simultaneaous render target.
186                        glDrawBuffer(bufs[0]);
187                }
188                /// No read buffer, by default, if we want to read anyway we must not forget to set this.
189                glReadBuffer(GL_NONE);
190       
191        /// Check status
192        GLuint status;
193        status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
194       
195        /// Bind main buffer
196        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
197       
198        switch(status)
199        {
200        case GL_FRAMEBUFFER_COMPLETE_EXT:
201            // All is good
202            break;
203        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
204            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
205            "All framebuffer formats with this texture internal format unsupported",
206                        "GLFrameBufferObject::initialise");
207        default:
208            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
209            "Framebuffer incomplete or other FBO status error",
210                        "GLFrameBufferObject::initialise");
211        }
212       
213    }
214    void GLFrameBufferObject::bind()
215    {
216        /// Bind it to FBO
217        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
218    }
219    size_t GLFrameBufferObject::getWidth()
220    {
221        assert(mColour[0].buffer);
222        return mColour[0].buffer->getWidth();
223    }
224    size_t GLFrameBufferObject::getHeight()
225    {
226        assert(mColour[0].buffer);
227        return mColour[0].buffer->getHeight();
228    }
229    PixelFormat GLFrameBufferObject::getFormat()
230    {
231        assert(mColour[0].buffer);
232        return mColour[0].buffer->getFormat();
233    }
234//-----------------------------------------------------------------------------
235}
Note: See TracBrowser for help on using the repository browser.