nux-1.16.0
GLDeviceFrameBufferObject.cpp
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     , GL_COLOR_ATTACHMENT1_EXT
00041     , GL_COLOR_ATTACHMENT2_EXT
00042     , GL_COLOR_ATTACHMENT3_EXT
00043   };
00044 
00046 // GLFramebufferObject
00048 
00049   GLFramebufferObject::GLFramebufferObject()
00050     :   m_fboId (0)
00051     ,   m_savedFboId (0)
00052   {
00053     m_fboId = _GenerateFboId();
00054     // Bind this FBO so that it actually gets created now
00055     _GuardedBind();
00056     _GuardedUnbind();
00057   }
00058 
00059   GLFramebufferObject::~GLFramebufferObject()
00060   {
00061     CHECKGL ( glDeleteFramebuffersEXT (1, (const GLuint *) &m_fboId) );
00062   }
00063 
00064   void GLFramebufferObject::Bind()
00065   {
00066     CHECKGL ( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, m_fboId) );
00067   }
00068 
00069   void GLFramebufferObject::Disable()
00070   {
00071     CHECKGL ( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
00072   }
00073 
00074   void
00075   GLFramebufferObject::AttachTexture ( GLenum attachment, GLenum texType,
00076                                        GLuint texId, int mipLevel, int zSlice)
00077   {
00078     _GuardedBind();
00079 
00080     if ( GetAttachedId (attachment) != texId )
00081     {
00082       _FramebufferTextureND ( attachment, texType,
00083                               texId, mipLevel, zSlice );
00084     }
00085     else
00086     {
00087 //        nuxError(TEXT("GLFramebufferObject::AttachTexture PERFORMANCE WARNING:\n
00088 //            \tRedundant bind of texture (id = %d).\n"), texId);
00089     }
00090 
00091     _GuardedUnbind();
00092   }
00093   void
00094   GLFramebufferObject::AttachTextures ( int numTextures, GLenum texTarget[], GLuint texId[],
00095                                         GLenum attachment[], int mipLevel[], int zSlice[] )
00096   {
00097     for (int i = 0; i < numTextures; ++i)
00098     {
00099       AttachTexture ( texTarget[i], texId[i],
00100                       attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
00101                       mipLevel ? mipLevel[i] : 0,
00102                       zSlice ? zSlice[i] : 0 );
00103     }
00104   }
00105 
00106 
00107   void
00108   GLFramebufferObject::AttachRenderBuffer ( GLenum attachment, GLuint buffId )
00109   {
00110     _GuardedBind();
00111 
00112     if ( GetAttachedId (attachment) != buffId )
00113     {
00114       CHECKGL ( glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT, attachment,
00115                 GL_RENDERBUFFER_EXT, buffId) );
00116     }
00117     else
00118     {
00119 //        nuxError(TEXT("GLFramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n
00120 //            \tRedundant bind of GLRenderbuffer (id = %d).\n"), buffId);
00121     }
00122 
00123     _GuardedUnbind();
00124   }
00125 
00126   void
00127   GLFramebufferObject::Unattach ( GLenum attachment )
00128   {
00129     _GuardedBind();
00130     GLenum type = GetAttachedType (attachment);
00131 
00132     switch (type)
00133     {
00134       case GL_NONE:
00135         break;
00136       case GL_RENDERBUFFER_EXT:
00137         AttachRenderBuffer ( attachment, 0 );
00138         break;
00139       case GL_TEXTURE:
00140         AttachTexture ( attachment, GL_TEXTURE_2D, 0 );
00141         break;
00142       default:
00143         std::cout << "GLFramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n";
00144     }
00145 
00146     _GuardedUnbind();
00147   }
00148 
00149   GLint GLFramebufferObject::GetMaxColorAttachments()
00150   {
00151     GLint maxAttach = 0;
00152     CHECKGL ( glGetIntegerv ( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach ) );
00153     return maxAttach;
00154   }
00155 
00156   GLuint GLFramebufferObject::_GenerateFboId()
00157   {
00158     GLuint id = 0;
00159     CHECKGL ( glGenFramebuffersEXT (1, &id) );
00160     return id;
00161   }
00162 
00163   void GLFramebufferObject::_GuardedBind()
00164   {
00165 #ifndef NUX_OPENGLES_20
00166     // Only binds if m_fboId is different than the currently bound FBO
00167     CHECKGL ( glGetIntegerv ( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ) );
00168 
00169     if (m_fboId != m_savedFboId)
00170     {
00171       CHECKGL ( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, m_fboId) );
00172     }
00173 #else
00174     CHECKGL ( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, m_fboId) );
00175 #endif
00176   }
00177 
00178   void GLFramebufferObject::_GuardedUnbind()
00179   {
00180     // Returns FBO binding to the previously enabled FBO
00181     if (m_savedFboId != m_fboId)
00182     {
00183       CHECKGL ( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, (GLuint) m_savedFboId) );
00184     }
00185   }
00186 
00187   void
00188   GLFramebufferObject::_FramebufferTextureND ( GLenum attachment, GLenum texType,
00189       GLuint texId, int mipLevel,
00190       int zSlice )
00191   {
00192     if (texType == GL_TEXTURE_2D)
00193     {
00194       // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
00195       CHECKGL ( glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT, attachment,
00196                                             texType, texId, mipLevel ) );
00197     }
00198     else if (texType == GL_TEXTURE_1D)
00199     {
00200       CHECKGL ( glFramebufferTexture1DEXT ( GL_FRAMEBUFFER_EXT, attachment,
00201                                             GL_TEXTURE_1D, texId, mipLevel ) );
00202     }
00203     else if (texType == GL_TEXTURE_3D)
00204     {
00205       CHECKGL ( glFramebufferTexture3DEXT ( GL_FRAMEBUFFER_EXT, attachment,
00206                                             GL_TEXTURE_3D, texId, mipLevel, zSlice ) );
00207     }
00208   }
00209 
00210   bool GLFramebufferObject::IsValid()
00211   {
00212     _GuardedBind();
00213 
00214     bool isOK = false;
00215 
00216     GLenum status;
00217     status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
00218     CHECKGL_MSG (glCheckFramebufferStatusEXT);
00219 
00220     switch (status)
00221     {
00222       case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
00223         isOK = true;
00224         break;
00225       case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00226         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT") );
00227         isOK = false;
00228         break;
00229       case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00230         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT") );
00231         isOK = false;
00232         break;
00233 // See issue (87) of http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
00234 //  case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
00235 //      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT"));
00236 //      isOK = false;
00237 //      break;
00238       case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00239         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT") );
00240         isOK = false;
00241         break;
00242       case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00243         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT") );
00244         isOK = false;
00245         break;
00246       case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00247         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT") );
00248         isOK = false;
00249         break;
00250       case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00251         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT") );
00252         isOK = false;
00253         break;
00254 //  case GL_FRAMEBUFFER_STATUS_ERROR_EXT:
00255 //      nuxError(TEXT("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_STATUS_ERROR_EXT"));
00256 //      isOK = false;
00257 //      break;
00258       case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00259         nuxError (TEXT ("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_UNSUPPORTED_EXT") );
00260         isOK = false;
00261         break;
00262       default:
00263         nuxError (TEXT ("[GLFramebufferObject::IsValid] Unknown ERROR") );
00264         isOK = false;
00265     }
00266 
00267     _GuardedUnbind();
00268     return isOK;
00269   }
00270 
00272   GLenum GLFramebufferObject::GetAttachedType ( GLenum attachment )
00273   {
00274     // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
00275     _GuardedBind();
00276     GLint type = 0;
00277     CHECKGL ( glGetFramebufferAttachmentParameterivEXT (GL_FRAMEBUFFER_EXT, attachment,
00278               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
00279               &type) );
00280     _GuardedUnbind();
00281     return GLenum (type);
00282   }
00283 
00284   GLuint GLFramebufferObject::GetAttachedId ( GLenum attachment )
00285   {
00286     _GuardedBind();
00287     GLint id = 0;
00288     CHECKGL ( glGetFramebufferAttachmentParameterivEXT (GL_FRAMEBUFFER_EXT, attachment,
00289               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
00290               &id) );
00291     _GuardedUnbind();
00292     return GLuint (id);
00293   }
00294 
00295   GLint GLFramebufferObject::GetAttachedMipLevel ( GLenum attachment )
00296   {
00297     _GuardedBind();
00298     GLint level = 0;
00299     CHECKGL ( glGetFramebufferAttachmentParameterivEXT (GL_FRAMEBUFFER_EXT, attachment,
00300               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
00301               &level) );
00302     _GuardedUnbind();
00303     return level;
00304   }
00305 
00306   GLint GLFramebufferObject::GetAttachedCubeFace ( GLenum attachment )
00307   {
00308     _GuardedBind();
00309     GLint level = 0;
00310     CHECKGL ( glGetFramebufferAttachmentParameterivEXT (GL_FRAMEBUFFER_EXT, attachment,
00311               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
00312               &level) );
00313     _GuardedUnbind();
00314     return level;
00315   }
00316 
00317   GLint GLFramebufferObject::GetAttachedZSlice ( GLenum attachment )
00318   {
00319     _GuardedBind();
00320     GLint slice = 0;
00321     CHECKGL ( glGetFramebufferAttachmentParameterivEXT (GL_FRAMEBUFFER_EXT, attachment,
00322               GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
00323               &slice) );
00324     _GuardedUnbind();
00325     return slice;
00326   }
00327 
00329 // GLRenderbuffer
00331 
00332 
00333   GLRenderbuffer::GLRenderbuffer()
00334     :   m_bufId (0)
00335   {
00336     m_bufId = _CreateBufferId();
00337   }
00338 
00339   GLRenderbuffer::GLRenderbuffer (GLenum internalFormat, int width, int height)
00340     : m_bufId (_CreateBufferId() )
00341   {
00342     Set (internalFormat, width, height);
00343   }
00344 
00345   GLRenderbuffer::~GLRenderbuffer()
00346   {
00347     CHECKGL ( glDeleteRenderbuffersEXT (1, &m_bufId) );
00348   }
00349 
00350   void GLRenderbuffer::Bind()
00351   {
00352     CHECKGL ( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, m_bufId) );
00353   }
00354 
00355   void GLRenderbuffer::Unbind()
00356   {
00357     CHECKGL ( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) );
00358   }
00359 
00360   void GLRenderbuffer::Set (GLenum internalFormat, int width, int height)
00361   {
00362     int maxSize = GLRenderbuffer::GetMaxSize();
00363 
00364     if (width > maxSize || height > maxSize )
00365     {
00366       std::cout << "GLRenderbuffer::GLRenderbuffer() ERROR: Size too big width=" << width << "height=" << height << "\n";
00367       return;
00368     }
00369 
00370     // Guarded bind
00371     GLint savedId = 0;
00372     CHECKGL ( glGetIntegerv ( GL_RENDERBUFFER_BINDING_EXT, &savedId ) );
00373 
00374     if (savedId != (GLint) m_bufId)
00375     {
00376       Bind();
00377     }
00378 
00379     // Allocate memory for renderBuffer
00380     CHECKGL ( glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, internalFormat, width, height ) );
00381 
00382     // Guarded unbind
00383     if (savedId != (GLint) m_bufId)
00384     {
00385       Unbind();
00386     }
00387   }
00388 
00389   GLuint GLRenderbuffer::GetId() const
00390   {
00391     return m_bufId;
00392   }
00393 
00394   GLint GLRenderbuffer::GetMaxSize()
00395   {
00396     GLint maxAttach = 0;
00397     CHECKGL ( glGetIntegerv ( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach ) );
00398     return maxAttach;
00399   }
00400 
00401   GLuint GLRenderbuffer::_CreateBufferId()
00402   {
00403     GLuint id = 0;
00404     CHECKGL ( glGenRenderbuffersEXT (1, &id) );
00405     return id;
00406   }
00407 
00408 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends