bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) { // Create the context m_context = new Context; // Create the framebuffer object GLuint frameBuffer = 0; glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer)); m_frameBuffer = static_cast<unsigned int>(frameBuffer); if (!m_frameBuffer) { err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl; return false; } glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer)); // Create the depth buffer if requested if (depthBuffer) { GLuint depth = 0; glCheck(GLEXT_glGenRenderbuffers(1, &depth)); m_depthBuffer = static_cast<unsigned int>(depth); if (!m_depthBuffer) { err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl; return false; } glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer)); glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height)); glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer)); } // Link the texture to the frame buffer glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0)); // A final check, just to be sure... GLenum status; glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)); if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE) { glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0)); err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl; return false; } return true; }
void Texture::update(const Texture& texture, unsigned int x, unsigned int y) { assert(x + texture.m_size.x <= m_size.x); assert(y + texture.m_size.x <= m_size.y); if (!m_texture || !texture.m_texture) return; #ifndef SFML_OPENGL_ES { TransientContextLock lock; // Make sure that extensions are initialized priv::ensureExtensionsInit(); } if (GLEXT_framebuffer_object && GLEXT_framebuffer_blit) { TransientContextLock lock; // Save the current bindings so we can restore them after we are done GLint readFramebuffer = 0; GLint drawFramebuffer = 0; glCheck(glGetIntegerv(GLEXT_GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer)); glCheck(glGetIntegerv(GLEXT_GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer)); // Create the framebuffers GLuint sourceFrameBuffer = 0; GLuint destFrameBuffer = 0; glCheck(GLEXT_glGenFramebuffers(1, &sourceFrameBuffer)); glCheck(GLEXT_glGenFramebuffers(1, &destFrameBuffer)); if (!sourceFrameBuffer || !destFrameBuffer) { err() << "Cannot copy texture, failed to create a frame buffer object" << std::endl; return; } // Link the source texture to the source frame buffer glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, sourceFrameBuffer)); glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_READ_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_texture, 0)); // Link the destination texture to the destination frame buffer glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, destFrameBuffer)); glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_DRAW_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0)); // A final check, just to be sure... GLenum sourceStatus; glCheck(sourceStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_READ_FRAMEBUFFER)); GLenum destStatus; glCheck(destStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_DRAW_FRAMEBUFFER)); if ((sourceStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE) && (destStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE)) { // Blit the texture contents from the source to the destination texture glCheck(GLEXT_glBlitFramebuffer(0, 0, texture.m_size.x, texture.m_size.y, x, y, x + texture.m_size.x, y + texture.m_size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST)); } else { err() << "Cannot copy texture, failed to link texture to frame buffer" << std::endl; } // Restore previously bound framebuffers glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, readFramebuffer)); glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, drawFramebuffer)); // Delete the framebuffers glCheck(GLEXT_glDeleteFramebuffers(1, &sourceFrameBuffer)); glCheck(GLEXT_glDeleteFramebuffers(1, &destFrameBuffer)); return; } #endif // SFML_OPENGL_ES update(texture.copyToImage(), x, y); }