#include "RenderTargetPool.h" #include namespace { void ConfigureRenderTargetTexture( unsigned width, unsigned height, GLenum internalFormat, GLenum pixelFormat, GLenum pixelType) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, pixelFormat, pixelType, NULL); } } bool RenderTargetPool::Create( RenderTargetId id, unsigned width, unsigned height, GLenum internalFormat, GLenum pixelFormat, GLenum pixelType, const char* errorPrefix, std::string& error) { RenderTarget& target = mTargets[TargetIndex(id)]; if (target.texture != 0 || target.framebuffer != 0) { error = std::string(errorPrefix) + " render target was already initialized."; return false; } glGenTextures(1, &target.texture); glBindTexture(GL_TEXTURE_2D, target.texture); ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &target.framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { error = std::string("Cannot initialize ") + errorPrefix + " framebuffer."; glBindFramebuffer(GL_FRAMEBUFFER, 0); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); target.width = width; target.height = height; target.internalFormat = internalFormat; target.pixelFormat = pixelFormat; target.pixelType = pixelType; return true; } bool RenderTargetPool::ReserveTemporaryTargets( std::size_t count, unsigned width, unsigned height, GLenum internalFormat, GLenum pixelFormat, GLenum pixelType, std::string& error) { if (mTemporaryTargets.size() == count) return true; DestroyTemporaryTargets(); mTemporaryTargets.resize(count); for (std::size_t index = 0; index < mTemporaryTargets.size(); ++index) { RenderTarget& target = mTemporaryTargets[index]; glGenTextures(1, &target.texture); glBindTexture(GL_TEXTURE_2D, target.texture); ConfigureRenderTargetTexture(width, height, internalFormat, pixelFormat, pixelType); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &target.framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, target.framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { error = "Cannot initialize temporary render target."; glBindFramebuffer(GL_FRAMEBUFFER, 0); return false; } target.width = width; target.height = height; target.internalFormat = internalFormat; target.pixelFormat = pixelFormat; target.pixelType = pixelType; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; } void RenderTargetPool::DestroyTemporaryTargets() { for (RenderTarget& target : mTemporaryTargets) { if (target.framebuffer != 0) glDeleteFramebuffers(1, &target.framebuffer); if (target.texture != 0) glDeleteTextures(1, &target.texture); } mTemporaryTargets.clear(); } void RenderTargetPool::Destroy() { for (RenderTarget& target : mTargets) { if (target.framebuffer != 0) glDeleteFramebuffers(1, &target.framebuffer); if (target.texture != 0) glDeleteTextures(1, &target.texture); target = RenderTarget(); } DestroyTemporaryTargets(); } const RenderTarget& RenderTargetPool::Target(RenderTargetId id) const { return mTargets[TargetIndex(id)]; }