Back to index

nux  3.0.0
GLDeviceFrameBufferObject.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GpuDevice.h"
00025 #include "GLDeviceObjects.h"
00026 #include "GLResourceManager.h"
00027 
00028 #include "GLTextureResourceManager.h"
00029 #include "GLVertexResourceManager.h"
00030 #include "GLDeviceFrameBufferObject.h"
00031 #include "GLTemplatePrimitiveBuffer.h"
00032 #include "GraphicsEngine.h"
00033 
00034 namespace nux
00035 {
00036 
00037   GLenum AttachmentBuffer[] =
00038   {
00039     GL_COLOR_ATTACHMENT0_EXT
00040 #ifndef NUX_OPENGLES_20 // GLES 2.0 only supports one color attachment
00041     , GL_COLOR_ATTACHMENT1_EXT
00042     , GL_COLOR_ATTACHMENT2_EXT
00043     , GL_COLOR_ATTACHMENT3_EXT
00044 #endif
00045   };
00046 
00048 // GLFramebufferObject
00050 
00051   GLFramebufferObject::GLFramebufferObject()
00052     :   m_fboId(0)
00053     ,   m_savedFboId(0)
00054   {
00055     m_fboId = _GenerateFboId();
00056     // Bind this FBO so that it actually gets created now
00057     _GuardedBind();
00058     _GuardedUnbind();
00059   }
00060 
00061   GLFramebufferObject::~GLFramebufferObject()
00062   {
00063     CHECKGL(glDeleteFramebuffersEXT(1, (const GLuint *) &m_fboId));
00064   }
00065 
00066   void GLFramebufferObject::Bind()
00067   {
00068     CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
00069   }
00070 
00071   void GLFramebufferObject::Disable()
00072   {
00073     CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
00074   }
00075 
00076   void
00077   GLFramebufferObject::AttachTexture( GLenum attachment, GLenum texType,
00078                                        GLuint texId, int mipLevel, int zSlice)
00079   {
00080     _GuardedBind();
00081 
00082     if ( GetAttachedId(attachment) != texId )
00083     {
00084       _FramebufferTextureND( attachment, texType,
00085                               texId, mipLevel, zSlice );
00086     }
00087     else
00088     {
00089 //        nuxError("GLFramebufferObject::AttachTexture PERFORMANCE WARNING:\n
00090 //            \tRedundant bind of texture(id = %d).\n"), texId);
00091     }
00092 
00093     _GuardedUnbind();
00094   }
00095   void
00096   GLFramebufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[],
00097                                         GLenum attachment[], int mipLevel[], int zSlice[] )
00098   {
00099     for (int i = 0; i < numTextures; ++i)
00100     {
00101       AttachTexture( texTarget[i], texId[i],
00102                       attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
00103                       mipLevel ? mipLevel[i] : 0,
00104                       zSlice ? zSlice[i] : 0 );
00105     }
00106   }
00107 
00108 
00109   void
00110   GLFramebufferObject::AttachRenderBuffer( GLenum attachment, GLuint buffId )
00111   {
00112     _GuardedBind();
00113 
00114     if ( GetAttachedId(attachment) != buffId )
00115     {
00116       CHECKGL(glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment,
00117                 GL_RENDERBUFFER_EXT, buffId));
00118     }
00119     else
00120     {
00121 //        nuxError(TEXT("GLFramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n
00122 //            \tRedundant bind of GLRenderbuffer(id = %d).\n"), buffId);
00123     }
00124 
00125     _GuardedUnbind();
00126   }
00127 
00128   void
00129   GLFramebufferObject::Unattach( GLenum attachment )
00130   {
00131     _GuardedBind();
00132     GLenum type = GetAttachedType(attachment);
00133 
00134     switch(type)
00135     {
00136       case GL_NONE:
00137         break;
00138       case GL_RENDERBUFFER_EXT:
00139         AttachRenderBuffer( attachment, 0 );
00140         break;
00141       case GL_TEXTURE:
00142         AttachTexture( attachment, GL_TEXTURE_2D, 0 );
00143         break;
00144       default:
00145         std::cout << "GLFramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n";
00146     }
00147 
00148     _GuardedUnbind();
00149   }
00150 
00151   GLint GLFramebufferObject::GetMaxColorAttachments()
00152   {
00153 #ifndef NUX_OPENGLES_20
00154     GLint maxAttach = 0;
00155     CHECKGL(glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach ));
00156     return maxAttach;
00157 #else
00158     return 1;
00159 #endif
00160   }
00161 
00162   GLuint GLFramebufferObject::_GenerateFboId()
00163   {
00164     GLuint id = 0;
00165     CHECKGL(glGenFramebuffersEXT(1, &id));
00166     return id;
00167   }
00168 
00169   void GLFramebufferObject::_GuardedBind()
00170   {
00171 #ifndef NUX_OPENGLES_20
00172     // Only binds if m_fboId is different than the currently bound FBO
00173     CHECKGL(glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
00174 
00175     if (m_fboId != m_savedFboId)
00176     {
00177       CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
00178     }
00179 #else
00180     // Only binds if m_fboId is different than the currently bound FBO
00181     CHECKGL(glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
00182 
00183     if (m_fboId != m_savedFboId)
00184     {
00185       CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
00186     }
00187 #endif
00188   }
00189 
00190   void GLFramebufferObject::_GuardedUnbind()
00191   {
00192     // Returns FBO binding to the previously enabled FBO
00193     if (m_savedFboId != m_fboId)
00194     {
00195       CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint) m_savedFboId));
00196     }
00197   }
00198 
00199   void
00200   GLFramebufferObject::_FramebufferTextureND( GLenum attachment, GLenum texType,
00201       GLuint texId, int mipLevel,
00202       int zSlice )
00203   {
00204     if (texType == GL_TEXTURE_2D)
00205     {
00206       // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
00207       CHECKGL(glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment,
00208                                             texType, texId, mipLevel ));
00209     }
00210 #ifndef NUX_OPENGLES_20
00211     else if (texType == GL_TEXTURE_1D)
00212     {
00213       CHECKGL(glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment,
00214                                             GL_TEXTURE_1D, texId, mipLevel ));
00215     }
00216     else if (texType == GL_TEXTURE_3D)
00217     {
00218       CHECKGL(glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment,
00219                                             GL_TEXTURE_3D, texId, mipLevel, zSlice ));
00220     }
00221 #endif
00222   }
00223 
00224   bool GLFramebufferObject::IsValid()
00225   {
00226     _GuardedBind();
00227 
00228     bool isOK = false;
00229 
00230     GLenum status;
00231     status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00232     CHECKGL_MSG(glCheckFramebufferStatusEXT);
00233 
00234     switch(status)
00235     {
00236       case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
00237         isOK = true;
00238         break;
00239       case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00240         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
00241         isOK = false;
00242         break;
00243       case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00244         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
00245         isOK = false;
00246         break;
00247 // See issue(87) of http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
00248 //  case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
00249 //      nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT");
00250 //      isOK = false;
00251 //      break;
00252       case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00253         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
00254         isOK = false;
00255         break;
00256 #ifndef NUX_OPENGLES_20
00257       case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00258         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
00259         isOK = false;
00260         break;
00261       case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00262         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
00263         isOK = false;
00264         break;
00265       case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00266         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
00267         isOK = false;
00268         break;
00269 #endif
00270 //  case GL_FRAMEBUFFER_STATUS_ERROR_EXT:
00271 //      nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_STATUS_ERROR_EXT");
00272 //      isOK = false;
00273 //      break;
00274       case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00275         nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_UNSUPPORTED_EXT");
00276         isOK = false;
00277         break;
00278       default:
00279         nuxError("[GLFramebufferObject::IsValid] Unknown ERROR");
00280         isOK = false;
00281     }
00282 
00283     _GuardedUnbind();
00284     return isOK;
00285   }
00286 
00288   GLenum GLFramebufferObject::GetAttachedType( GLenum attachment )
00289   {
00290     // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
00291     _GuardedBind();
00292     GLint type = 0;
00293     CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
00294               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
00295               &type));
00296     _GuardedUnbind();
00297     return GLenum(type);
00298   }
00299 
00300   GLuint GLFramebufferObject::GetAttachedId( GLenum attachment )
00301   {
00302     _GuardedBind();
00303     GLint id = 0;
00304     CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
00305               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
00306               &id));
00307     _GuardedUnbind();
00308     return GLuint(id);
00309   }
00310 
00311   GLint GLFramebufferObject::GetAttachedMipLevel( GLenum attachment )
00312   {
00313     _GuardedBind();
00314     GLint level = 0;
00315     CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
00316               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
00317               &level));
00318     _GuardedUnbind();
00319     return level;
00320   }
00321 
00322   GLint GLFramebufferObject::GetAttachedCubeFace( GLenum attachment )
00323   {
00324     _GuardedBind();
00325     GLint level = 0;
00326 #ifndef NUX_OPENGLES_20
00327     CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
00328               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
00329               &level));
00330 #endif
00331     _GuardedUnbind();
00332     return level;
00333   }
00334 
00335   GLint GLFramebufferObject::GetAttachedZSlice( GLenum attachment )
00336   {
00337     _GuardedBind();
00338     GLint slice = 0;
00339 #ifndef NUX_OPENGLES_20
00340     CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
00341               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
00342               &slice));
00343 #endif
00344     _GuardedUnbind();
00345     return slice;
00346   }
00347 
00349 // GLRenderbuffer
00351 
00352 
00353   GLRenderbuffer::GLRenderbuffer()
00354     :   m_bufId(0)
00355   {
00356     m_bufId = _CreateBufferId();
00357   }
00358 
00359   GLRenderbuffer::GLRenderbuffer(GLenum internalFormat, int width, int height)
00360     : m_bufId(_CreateBufferId())
00361   {
00362     Set(internalFormat, width, height);
00363   }
00364 
00365   GLRenderbuffer::~GLRenderbuffer()
00366   {
00367     CHECKGL(glDeleteRenderbuffersEXT(1, &m_bufId));
00368   }
00369 
00370   void GLRenderbuffer::Bind()
00371   {
00372     CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId));
00373   }
00374 
00375   void GLRenderbuffer::Unbind()
00376   {
00377     CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
00378   }
00379 
00380   void GLRenderbuffer::Set(GLenum internalFormat, int width, int height)
00381   {
00382     int maxSize = GLRenderbuffer::GetMaxSize();
00383 
00384     if (width > maxSize || height > maxSize )
00385     {
00386       std::cout << "GLRenderbuffer::GLRenderbuffer() ERROR: Size too big width=" << width << "height=" << height << "\n";
00387       return;
00388     }
00389 
00390     // Guarded bind
00391     GLint savedId = 0;
00392     CHECKGL(glGetIntegerv( GL_RENDERBUFFER_BINDING_EXT, &savedId ));
00393 
00394     if (savedId != (GLint) m_bufId)
00395     {
00396       Bind();
00397     }
00398 
00399     // Allocate memory for renderBuffer
00400     CHECKGL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height ));
00401 
00402     // Guarded unbind
00403     if (savedId != (GLint) m_bufId)
00404     {
00405       Unbind();
00406     }
00407   }
00408 
00409   GLuint GLRenderbuffer::GetId() const
00410   {
00411     return m_bufId;
00412   }
00413 
00414   GLint GLRenderbuffer::GetMaxSize()
00415   {
00416     GLint maxAttach = 0;
00417     CHECKGL(glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach ));
00418     return maxAttach;
00419   }
00420 
00421   GLuint GLRenderbuffer::_CreateBufferId()
00422   {
00423     GLuint id = 0;
00424     CHECKGL(glGenRenderbuffersEXT(1, &id));
00425     return id;
00426   }
00427 
00428 }