diff options
| author | degasus <wickmarkus@web.de> | 2013-01-09 11:00:26 +0100 |
|---|---|---|
| committer | degasus <wickmarkus@web.de> | 2013-01-09 11:00:26 +0100 |
| commit | bff02b3b7348c36d54acd7823ddeef66ec996350 (patch) | |
| tree | 597a6453c11c56c857990607cbeadc2edc00452d /Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp | |
| parent | b7906b49c98ffaf29a5c9e25cfbabec16b7f4a8d (diff) | |
| parent | 84debc17d530dc3324c06a971d61fadf1cedf1e4 (diff) | |
Merge branch 'arb_framebuffer' into GLSL-master
Conflicts:
Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp
Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
Diffstat (limited to 'Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp')
| -rw-r--r-- | Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp | 232 |
1 files changed, 65 insertions, 167 deletions
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp index a2dbedc472..c74e10a2b5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp @@ -26,13 +26,6 @@ namespace OGL { -extern bool s_bHaveFramebufferBlit; // comes from Render.cpp. ugly. - -static GLuint s_VBO = 0; -static GLuint s_VAO = 0; -static MathUtil::Rectangle<float> s_cached_sourcerc; -static MathUtil::Rectangle<float> s_cached_drawrc; - int FramebufferManager::m_targetWidth; int FramebufferManager::m_targetHeight; int FramebufferManager::m_msaaSamples; @@ -47,7 +40,7 @@ GLuint FramebufferManager::m_resolvedFramebuffer; GLuint FramebufferManager::m_resolvedColorTexture; GLuint FramebufferManager::m_resolvedDepthTexture; -GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode +GLuint FramebufferManager::m_xfbFramebuffer; FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) { @@ -58,15 +51,6 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_resolvedColorTexture = 0; m_resolvedDepthTexture = 0; m_xfbFramebuffer = 0; - - s_cached_sourcerc.bottom = -1; - s_cached_sourcerc.left = -1; - s_cached_sourcerc.right = -1; - s_cached_sourcerc.top = -1; - s_cached_drawrc.bottom = -1; - s_cached_drawrc.left = -1; - s_cached_drawrc.right = -1; - s_cached_drawrc.top = -1; m_targetWidth = targetWidth; m_targetHeight = targetHeight; @@ -87,7 +71,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms // Create EFB target. - glGenFramebuffersEXT(1, &m_efbFramebuffer); + glGenFramebuffers(1, &m_efbFramebuffer); if (m_msaaSamples <= 1) { @@ -98,20 +82,20 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms m_efbColor = glObj[0]; m_efbDepth = glObj[1]; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE, m_efbColor); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE, m_efbDepth); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glBindTexture(GL_TEXTURE_RECTANGLE, 0); // Bind target textures to the EFB framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_efbColor, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_efbDepth, 0); GL_REPORT_FBO_ERROR(); } @@ -124,87 +108,66 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms // Create EFB target renderbuffers. GLuint glObj[2]; - glGenRenderbuffersEXT(2, glObj); + glGenRenderbuffers(2, glObj); m_efbColor = glObj[0]; m_efbDepth = glObj[1]; - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor); + glBindRenderbuffer(GL_RENDERBUFFER, m_efbColor); if (m_msaaCoverageSamples) - glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); + glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); else - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth); + glBindRenderbuffer(GL_RENDERBUFFER, m_efbDepth); if (m_msaaCoverageSamples) - glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); + glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); else - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); // Bind target renderbuffers to EFB framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_efbColor); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_efbDepth); GL_REPORT_FBO_ERROR(); // Create resolved targets for transferring multisampled EFB to texture. - glGenFramebuffersEXT(1, &m_resolvedFramebuffer); + glGenFramebuffers(1, &m_resolvedFramebuffer); glGenTextures(2, glObj); m_resolvedColorTexture = glObj[0]; m_resolvedDepthTexture = glObj[1]; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedColorTexture); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glBindTexture(GL_TEXTURE_RECTANGLE, 0); // Bind resolved textures to resolved framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_resolvedColorTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture, 0); GL_REPORT_FBO_ERROR(); // Return to EFB framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); } // Create XFB framebuffer; targets will be created elsewhere. - glGenFramebuffersEXT(1, &m_xfbFramebuffer); - - // Generate VBO & VAO - and initialize the VAO for "Draw" - glGenBuffers(1, &s_VBO); - glGenVertexArrays(1, &s_VAO); - glBindBuffer(GL_ARRAY_BUFFER, s_VBO); - glBindVertexArray(s_VAO); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 6*sizeof(GLfloat), NULL); - - glClientActiveTexture(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 6*sizeof(GLfloat), (GLfloat*)NULL+2); - - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 6*sizeof(GLfloat), (GLfloat*)NULL+4); - - // TODO: this after merging with graphic_update - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + glGenFramebuffers(1, &m_xfbFramebuffer); // EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f glViewport(0, 0, m_targetWidth, m_targetHeight); @@ -216,9 +179,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms FramebufferManager::~FramebufferManager() { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteBuffers(1, &s_VBO); - glDeleteVertexArrays(1, &s_VAO); + glBindFramebuffer(GL_FRAMEBUFFER, 0); GLuint glObj[3]; @@ -227,7 +188,7 @@ FramebufferManager::~FramebufferManager() glObj[0] = m_efbFramebuffer; glObj[1] = m_resolvedFramebuffer; glObj[2] = m_xfbFramebuffer; - glDeleteFramebuffersEXT(3, glObj); + glDeleteFramebuffers(3, glObj); m_efbFramebuffer = 0; m_xfbFramebuffer = 0; @@ -242,7 +203,7 @@ FramebufferManager::~FramebufferManager() if (m_msaaSamples <= 1) glDeleteTextures(2, glObj); else - glDeleteRenderbuffersEXT(2, glObj); + glDeleteRenderbuffers(2, glObj); m_efbColor = 0; m_efbDepth = 0; } @@ -262,16 +223,16 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc) targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); // Resolve. - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); - glBlitFramebufferEXT( + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer); + glBlitFramebuffer( targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, GL_COLOR_BUFFER_BIT, GL_NEAREST ); // Return to EFB. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); return m_resolvedColorTexture; } @@ -292,16 +253,16 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc) targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight); // Resolve. - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); - glBlitFramebufferEXT( + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer); + glBlitFramebuffer( targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, targetRc.left, targetRc.top, targetRc.right, targetRc.bottom, GL_DEPTH_BUFFER_BIT, GL_NEAREST ); // Return to EFB. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer); return m_resolvedDepthTexture; } @@ -322,7 +283,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c void FramebufferManager::SetFramebuffer(GLuint fb) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer()); + glBindFramebuffer(GL_FRAMEBUFFER, fb != 0 ? fb : GetEFBFramebuffer()); } // Apply AA if enabled @@ -340,43 +301,11 @@ void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc, const MathUtil::Rectangle<float> &drawrc, int width, int height) const { // Texture map xfbSource->texture onto the main buffer + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, texture, 0); + glBlitFramebuffer(sourcerc.left, sourcerc.bottom, sourcerc.right, sourcerc.top, + drawrc.left, drawrc.bottom, drawrc.right, drawrc.top, + GL_COLOR_BUFFER_BIT, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - - if(!(s_cached_sourcerc == sourcerc) || !(s_cached_drawrc == drawrc)) { - GLfloat vertices[] = { - drawrc.left, drawrc.bottom, - sourcerc.left, sourcerc.bottom, - 0.0f, 0.0f, - drawrc.left, drawrc.top, - sourcerc.left, sourcerc.top, - 0.0f, 1.0f, - drawrc.right, drawrc.top, - sourcerc.right, sourcerc.top, - 1.0f, 1.0f, - drawrc.right, drawrc.bottom, - sourcerc.right, sourcerc.bottom, - 1.0f, 0.0f - }; - glBindBuffer(GL_ARRAY_BUFFER, s_VBO); - glBufferData(GL_ARRAY_BUFFER, 2*4*3*sizeof(GLfloat), vertices, GL_STREAM_DRAW); - - // TODO: this after merging with graphic_update - glBindBuffer(GL_ARRAY_BUFFER, 0); - - s_cached_sourcerc = sourcerc; - s_cached_drawrc = drawrc; - } - - glBindVertexArray(s_VAO); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - // TODO: this after merging with graphic_update - glBindVertexArray(0); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - GL_REPORT_ERRORD(); } @@ -388,46 +317,25 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) void XFBSource::CopyEFB(float Gamma) { // Copy EFB data to XFB and restore render target again + glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); -#if 0 - if (m_msaaSamples <= 1) -#else - if (!s_bHaveFramebufferBlit) -#endif - { - // Just copy the EFB directly. - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer()); - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0); + // Bind texture. + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, texture, 0); + GL_REPORT_FBO_ERROR(); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - } - else - { - // OpenGL cannot copy directly from a multisampled framebuffer, so use - // EXT_framebuffer_blit. + glBlitFramebuffer( + 0, 0, texWidth, texHeight, + 0, 0, texWidth, texHeight, + GL_COLOR_BUFFER_BIT, GL_NEAREST + ); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer()); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::GetXFBFramebuffer()); + // Unbind texture. + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, 0, 0); - // Bind texture. - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture, 0); - GL_REPORT_FBO_ERROR(); + // Return to EFB. + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer()); - glBlitFramebufferEXT( - 0, 0, texWidth, texHeight, - 0, 0, texWidth, texHeight, - GL_COLOR_BUFFER_BIT, GL_NEAREST - ); - - // Unbind texture. - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); - - // Return to EFB. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer()); - } } XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height) @@ -436,20 +344,10 @@ XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, un glGenTextures(1, &texture); -#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible. - if (m_msaaSamples > 1) -#else - if (s_bHaveFramebufferBlit) -#endif - { - // In MSAA mode, allocate the texture image here. In non-MSAA mode, - // the image will be allocated by glCopyTexImage2D (later). - - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE, texture); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - } + glBindTexture(GL_TEXTURE_RECTANGLE, 0); return new XFBSource(texture); } |
