ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

framebuffer.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/textconsole.h"
00024 #include "common/util.h"
00025 
00026 #if defined(USE_OPENGL) && !defined(AMIGAOS)
00027 
00028 #if defined(SDL_BACKEND) && !defined(USE_GLEW) && !defined(USE_GLES2)
00029 #define GL_GLEXT_PROTOTYPES // For the GL_EXT_framebuffer_object extension
00030 #include "graphics/opengl/framebuffer.h"
00031 #ifndef GL_ARB_framebuffer_object
00032 #define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
00033 #define GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
00034 #define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
00035 #define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
00036 #define GL_RENDERBUFFER GL_RENDERBUFFER_EXT
00037 #define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
00038 #define GL_STENCIL_INDEX8 GL_STENCIL_INDEX8_EXT
00039 #define GL_DEPTH24_STENCIL8 0x88F0
00040 #define GL_READ_FRAMEBUFFER 0x8CA8
00041 #define GL_DRAW_FRAMEBUFFER 0x8CA9
00042 #endif // defined(GL_ARB_framebuffer_object)
00043 #include "backends/platform/sdl/sdl-sys.h"
00044 #else
00045 #include "graphics/opengl/framebuffer.h"
00046 #endif
00047 
00048 #include "graphics/opengl/context.h"
00049 
00050 #ifdef USE_GLES2
00051 #define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
00052 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
00053 #endif
00054 
00055 namespace OpenGL {
00056 
00057 #if defined(SDL_BACKEND) && !defined(USE_GLEW) && !defined(USE_GLES2)
00058 static bool framebuffer_object_functions = false;
00059 static PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebuffer;
00060 static PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbuffer;
00061 static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus;
00062 static PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffers;
00063 static PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffers;
00064 static PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbuffer;
00065 static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2D;
00066 static PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffers;
00067 static PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffers;
00068 static PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorage;
00069 typedef void (* PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
00070 static PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisample;
00071 typedef void (* PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
00072 static PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebuffer;
00073 
00074 
00075 static void grabFramebufferObjectPointers() {
00076     if (framebuffer_object_functions)
00077         return;
00078     framebuffer_object_functions = true;
00079 
00080     union {
00081         void *obj_ptr;
00082         void (APIENTRY *func_ptr)();
00083     } u;
00084     // We're casting from an object pointer to a function pointer, the
00085     // sizes need to be the same for this to work.
00086     assert(sizeof(u.obj_ptr) == sizeof(u.func_ptr));
00087     u.obj_ptr = SDL_GL_GetProcAddress("glBlitFramebuffer");
00088     glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC)u.func_ptr;
00089     u.obj_ptr = SDL_GL_GetProcAddress("glBindFramebuffer");
00090     glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)u.func_ptr;
00091     u.obj_ptr = SDL_GL_GetProcAddress("glBindRenderbuffer");
00092     glBindRenderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)u.func_ptr;
00093     u.obj_ptr = SDL_GL_GetProcAddress("glCheckFramebufferStatus");
00094     glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)u.func_ptr;
00095     u.obj_ptr = SDL_GL_GetProcAddress("glDeleteFramebuffers");
00096     glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)u.func_ptr;
00097     u.obj_ptr = SDL_GL_GetProcAddress("glDeleteRenderbuffers");
00098     glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)u.func_ptr;
00099     u.obj_ptr = SDL_GL_GetProcAddress("glFramebufferRenderbuffer");
00100     glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)u.func_ptr;
00101     u.obj_ptr = SDL_GL_GetProcAddress("glFramebufferTexture2D");
00102     glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)u.func_ptr;
00103     u.obj_ptr = SDL_GL_GetProcAddress("glGenFramebuffers");
00104     glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)u.func_ptr;
00105     u.obj_ptr = SDL_GL_GetProcAddress("glGenRenderbuffers");
00106     glGenRenderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)u.func_ptr;
00107     u.obj_ptr = SDL_GL_GetProcAddress("glRenderbufferStorage");
00108     glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)u.func_ptr;
00109     u.obj_ptr = SDL_GL_GetProcAddress("glRenderbufferStorageMultisample");
00110     glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)u.func_ptr;
00111 }
00112 #endif // defined(SDL_BACKEND) && !defined(USE_GLEW) && !defined(USE_GLES2)
00113 
00114 
00115 
00116 static bool usePackedBuffer() {
00117     return OpenGLContext.packedDepthStencilSupported;
00118 }
00119 static bool useDepthComponent24() {
00120     return OpenGLContext.OESDepth24;
00121 }
00122 
00123 FrameBuffer::FrameBuffer(uint width, uint height) :
00124         Texture(width, height) {
00125     if (!OpenGLContext.framebufferObjectSupported) {
00126         error("FrameBuffer Objects are not supported by the current OpenGL context");
00127     }
00128 
00129 #if defined(SDL_BACKEND) && !defined(USE_GLEW) && !defined(USE_GLES2)
00130     grabFramebufferObjectPointers();
00131 #endif
00132 
00133     init();
00134 }
00135 
00136 FrameBuffer::FrameBuffer(GLuint texture_name, uint width, uint height, uint texture_width, uint texture_height) :
00137         Texture(texture_name, width, height, texture_width, texture_height) {
00138     init();
00139 }
00140 
00141 FrameBuffer::~FrameBuffer() {
00142     glDeleteRenderbuffers(2, _renderBuffers);
00143     glDeleteFramebuffers(1, &_frameBuffer);
00144 }
00145 
00146 void FrameBuffer::init() {
00147     glGenFramebuffers(1, &_frameBuffer);
00148     glGenRenderbuffers(2, _renderBuffers);
00149 
00150     glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
00151     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
00152 
00153     if (usePackedBuffer()) {
00154         glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
00155         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, _texWidth, _texHeight);
00156         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
00157         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
00158         glBindRenderbuffer(GL_RENDERBUFFER, 0);
00159     } else {
00160         glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
00161         glRenderbufferStorage(GL_RENDERBUFFER, useDepthComponent24() ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, _texWidth, _texHeight);
00162         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
00163 
00164         glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
00165         glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, _texWidth, _texHeight);
00166         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
00167         glBindRenderbuffer(GL_RENDERBUFFER, 0);
00168     }
00169 
00170     glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
00171     GLenum status=glCheckFramebufferStatus(GL_FRAMEBUFFER);
00172     if (status != GL_FRAMEBUFFER_COMPLETE)
00173         error("Framebuffer is not complete! status: %d", status);
00174 
00175     glBindTexture(GL_TEXTURE_2D, 0);
00176     glBindFramebuffer(GL_FRAMEBUFFER, 0);
00177 }
00178 
00179 void FrameBuffer::attach() {
00180     glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
00181     glViewport(0,0, _width, _height);
00182 
00183     glClearColor(0, 0, 0, 1.0f);
00184     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00185 }
00186 
00187 void FrameBuffer::detach() {
00188     glBindFramebuffer(GL_FRAMEBUFFER, 0);
00189 }
00190 
00191 #if !defined(USE_GLES2) && !defined(AMIGAOS)
00192 MultiSampleFrameBuffer::MultiSampleFrameBuffer(uint width, uint height, int samples)
00193         : FrameBuffer(width,height) {
00194     if (!OpenGLContext.framebufferObjectMultisampleSupported) {
00195         error("The current OpenGL context does not support multisample framebuffer objects!");
00196     }
00197 
00198     if (samples > OpenGLContext.multisampleMaxSamples) {
00199         warning("Requested anti-aliasing with '%d' samples, but the current OpenGL context supports '%d' samples at most",
00200                 samples, OpenGLContext.multisampleMaxSamples);
00201     }
00202 
00203     _msSamples = MIN(samples, OpenGLContext.multisampleMaxSamples);
00204 
00205     init();
00206 }
00207 
00208 MultiSampleFrameBuffer::~MultiSampleFrameBuffer() {
00209     glDeleteRenderbuffers(1, &_msColorId);
00210     glDeleteRenderbuffers(1, &_msDepthId);
00211     glBindFramebuffer(GL_FRAMEBUFFER, 0);
00212     glDeleteFramebuffers(1, &_msFrameBufferId);
00213 }
00214 
00215 void MultiSampleFrameBuffer::init() {
00216     glGenFramebuffers(1, &_msFrameBufferId);
00217     glBindFramebuffer(GL_FRAMEBUFFER, _msFrameBufferId);
00218 
00219     glGenRenderbuffers(1, &_msColorId);
00220     glBindRenderbuffer(GL_RENDERBUFFER, _msColorId);
00221     glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_RGBA8, getTexWidth(), getTexHeight());
00222 
00223     glGenRenderbuffers(1, &_msDepthId);
00224     glBindRenderbuffer(GL_RENDERBUFFER, _msDepthId);
00225     glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_DEPTH24_STENCIL8, getTexWidth(), getTexHeight());
00226 
00227     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _msColorId);
00228     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
00229     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
00230 
00231     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
00232     if (status != GL_FRAMEBUFFER_COMPLETE)
00233         error("Framebuffer is not complete! status: %d", status);
00234 
00235     glBindFramebuffer(GL_FRAMEBUFFER, 0);
00236 }
00237 
00238 void MultiSampleFrameBuffer::attach() {
00239     glBindFramebuffer(GL_READ_FRAMEBUFFER, getFrameBufferName());
00240     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _msFrameBufferId);
00241     glViewport(0,0, getWidth(), getHeight());
00242 
00243     glClearColor(0, 0, 0, 1.0f);
00244     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00245 }
00246 
00247 void MultiSampleFrameBuffer::detach() {
00248     glBindFramebuffer(GL_READ_FRAMEBUFFER, _msFrameBufferId);
00249     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFrameBufferName());
00250     glBlitFramebuffer(0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
00251     glBindFramebuffer(GL_FRAMEBUFFER, 0);
00252 }
00253 
00254 #endif // !defined(USE_GLES2) && !defined(AMIGAOS)
00255 
00256 } // End of namespace OpenGL
00257 
00258 #endif


Generated on Sat Apr 20 2019 05:02:40 for ResidualVM by doxygen 1.7.1
curved edge   curved edge