ffgl-core 0.2.6

FFGL plugin framework
Documentation
#include "FFGLFBO.h"

int FFGLFBO::Create(int _width,
                      int _height,
                      FFGLExtensions &e)
{
  int glWidth = 1;
  while (glWidth<_width) glWidth*=2;
  
  int glHeight = 1;
  while (glHeight<_height) glHeight*=2;
  
  m_width = _width;
  m_height = _height;
  m_glWidth = glWidth;
  m_glHeight = glHeight;
  m_glPixelFormat = GL_RGBA8;
  m_glTextureTarget = GL_TEXTURE_2D;

  m_glTextureHandle = 0;
  
  e.glGenFramebuffersEXT(1, &m_fboHandle);

  return 1;
}

int IsTextureResident(GLuint handle)
{
  GLboolean b;

  if (glAreTexturesResident(1, &handle, &b))  
    return 1;

  return 0;
}


int FFGLFBO::BindAsRenderTarget(FFGLExtensions &e)
{
  //make our fbo active
  e.glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboHandle);

  //make sure there's a valid depth buffer attached to it
  if (e.glIsRenderbufferEXT(m_depthBufferHandle)==0)
  {
    e.glGenRenderbuffersEXT(1, &m_depthBufferHandle);
    e.glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBufferHandle);
    e.glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_glWidth, m_glHeight);
  
    //attach our depth buffer to the fbo
    e.glFramebufferRenderbufferEXT(
      GL_FRAMEBUFFER_EXT,
      GL_DEPTH_ATTACHMENT_EXT,
      GL_RENDERBUFFER_EXT,
      m_depthBufferHandle);
  }

  //make sure we have a valid gl texture attached to it
  if (!IsTextureResident(m_glTextureHandle))
  {
    //get a new one
    glGenTextures(1,&m_glTextureHandle);

    //bind it for some initialization
    glBindTexture(m_glTextureTarget, m_glTextureHandle);

    //this only works if the FBO pixel format
    //is GL_RGBA8. other FBO pixel formats have to
    //define their texture differently
    GLuint pformat = GL_RGBA;
    GLuint ptype = GL_UNSIGNED_BYTE;

    glTexImage2D(
      m_glTextureTarget, //texture target
      0, //mipmap level
      m_glPixelFormat, //gl internal pixel format
      m_glWidth, //gl width
      m_glHeight, //gl height
      0, //no border
      pformat, //pixel format #2
      ptype, //pixel type
      NULL); //null texture image data pointer

    //for now, do not do mipmapping.
    //to do mipmapping, set this to 1, and after we've bound the texture,
    //we would need to call glGenerateMipmapEXT(m_textureTarget) to make sure
    //the mipmaps have been updated
    int do_mipmaps = 0;

    if (do_mipmaps)
      e.glGenerateMipmapEXT(m_glTextureTarget);

    glTexParameteri(m_glTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    if (do_mipmaps)
  	  glTexParameteri(m_glTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    else
      glTexParameteri(m_glTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    glTexParameteri(m_glTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(m_glTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    //unbind the texture
    glBindTexture(m_glTextureTarget, 0);

    //attach our texture to the FBO
    e.glFramebufferTexture2DEXT(
      GL_FRAMEBUFFER_EXT,
      GL_COLOR_ATTACHMENT0_EXT,
      m_glTextureTarget,
      m_glTextureHandle,
      0);
  }  

  GLenum status = e.glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );

  switch(status)
  {
  case GL_FRAMEBUFFER_COMPLETE_EXT:
	//no error
	break;

  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_UNSUPPORTED_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
	return 0;

  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
	//FFDebugMessage("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
	return 0;

  default:
	//FFDebugMessage("Unknown GL_FRAMEBUFFER error");
	return 0;		
  }

  return 1;
}

int FFGLFBO::UnbindAsRenderTarget(FFGLExtensions &e)
{
  e.glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  return 1;
}

FFGLTextureStruct FFGLFBO::GetTextureInfo()
{
  FFGLTextureStruct t;

  t.Width = m_width;
  t.Height = m_height;
  
  t.HardwareWidth = m_glWidth;
  t.HardwareHeight = m_glHeight;
  
  t.Handle = m_glTextureHandle;

  return t;
}


void FFGLFBO::FreeResources(FFGLExtensions &e)
{
  if (m_fboHandle)
  {
    e.glDeleteFramebuffersEXT(1, &m_fboHandle);
    m_fboHandle = 0;
  }

  if (m_depthBufferHandle)
  {
    e.glDeleteRenderBuffersEXT(1, &m_depthBufferHandle);
    m_depthBufferHandle = 0;
  }

  if (m_glTextureHandle)
  {
    glDeleteTextures(1, &m_glTextureHandle);
    m_glTextureHandle = 0;
  }
}