nux-1.14.0
|
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 }