#include "FBO.h"

FBOexception::FBOexception( void ): BasicException( "FBO exception - unable to create Frame Buffer Object.")
{
}


void FBO::setTexture( unsigned int texID )
{
	this->texID=texID;

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fboID);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texID, 0);
	//glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texID, 0);

	if ( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT )
	{
		throw FBOexception();
	}
	this->unbind();
}

void FBO::setSize( int width, int height )
{
	this->frameSizeX=width;
	this->frameSizeY=height;

	this->texID=0;

	glGenFramebuffersEXT(1, &this->fboID);
	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, this->fboID );

	glGenRenderbuffersEXT(1, &this->renderID);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->renderID);
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB8, width, height);
	//glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
	//glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->renderID);

	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT,this->renderID );

	if ( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT )
	{
		throw FBOexception();
	}

	this->unbind();
}

/*
Prepare the FBO for shadowing

glGenFramebuffersEXT(1, &m_FrameBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FrameBuffer);
GLuint l_RenderBuffer = 0;
glGenRenderbuffersEXT(1, &l_RenderBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, l_RenderBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB8, p_Size, p_Size);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, l_RenderBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

Use FBO

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShadowBuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, ShadowMap, 0);
glViewport(0, 0, ShadowMapWidth, ShadowMapHeight);
glClear(GL_DEPTH_BUFFER_BIT);
RenderShadowCasters();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glViewport(0, 0, ContextWidth, ContextHeight);
*/

FBO::FBO(int width, int height, int texID)
{
	this->setSize(width, height); 
	this->setTexture(texID); 
}
void FBO::clear(void)
{
	this->bind();

		glClear( GL_COLOR_BUFFER_BIT );
		glClear( GL_DEPTH_BUFFER_BIT );

	this->unbind();
}

void FBO::bind(void)
{
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fboID);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->renderID);	//>>BUG FIX ???
}

void FBO::unbind(void)
{
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);	//>>BUG FIX ???
}

FBO::~FBO(void)
{
	glDeleteFramebuffersEXT(1,  &this->fboID);
	glDeleteRenderbuffersEXT(1, &this->renderID);
}

unsigned int FBO::getTextureId(void) const
{
	return this->texID;
}

int FBO::getFrameSizeX(void) const
{
	return this->frameSizeX;
}
int FBO::getFrameSizeY(void) const
{
	return this->frameSizeY;
}


void FBOContext::makeCurrent(void)
{
	this->fbo->bind();
}
void FBOContext::doneCurrent(void)
{
	this->fbo->unbind();
}
void FBOContext::swapBuffers(void)
{
	//nedela nic (nelze swapovat buffery)
}
FBOContext::FBOContext( FBO *fbo)
{
	this->fbo=fbo;
}