Separated canvas texture creation code from FBO creation code

This commit is contained in:
Alex Szpakowski
2014-01-13 01:47:06 -04:00
parent fda005c5ff
commit 113093e4fc
2 changed files with 65 additions and 80 deletions
+64 -79
View File
@@ -42,14 +42,11 @@ struct FramebufferStrategy
/// create a new framebuffer and texture /// create a new framebuffer and texture
/** /**
* @param[out] framebuffer Framebuffer name * @param[out] framebuffer Framebuffer name
* @param[out] img Texture name * @param[in] texture Texture name
* @param[in] width Width of framebuffer
* @param[in] height Height of framebuffer
* @param[in] texture_type Type of the canvas texture.
* @return Creation status * @return Creation status
*/ */
virtual GLenum createFBO(GLuint &, GLuint &, int, int, Canvas::TextureType) virtual GLenum createFBO(GLuint &, GLuint)
{ {
return GL_FRAMEBUFFER_UNSUPPORTED; return GL_FRAMEBUFFER_UNSUPPORTED;
} }
@@ -70,9 +67,8 @@ struct FramebufferStrategy
/** /**
* @param[in] framebuffer Framebuffer name * @param[in] framebuffer Framebuffer name
* @param[in] depth_stencil Name for packed depth and stencil buffer * @param[in] depth_stencil Name for packed depth and stencil buffer
* @param[in] img Texture name
*/ */
virtual void deleteFBO(GLuint, GLuint, GLuint) {} virtual void deleteFBO(GLuint, GLuint) {}
virtual void bindFBO(GLuint) {} virtual void bindFBO(GLuint) {}
/// attach additional canvases to the active framebuffer for rendering /// attach additional canvases to the active framebuffer for rendering
@@ -87,7 +83,7 @@ struct FramebufferStrategy
struct FramebufferStrategyGL3 : public FramebufferStrategy struct FramebufferStrategyGL3 : public FramebufferStrategy
{ {
virtual GLenum createFBO(GLuint &framebuffer, GLuint &img, int width, int height, Canvas::TextureType texture_type) virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
{ {
// get currently bound fbo to reset to it later // get currently bound fbo to reset to it later
GLint current_fbo; GLint current_fbo;
@@ -97,32 +93,8 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
glGenFramebuffers(1, &framebuffer); glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// generate texture save target
GLint internalFormat;
GLenum format;
switch (texture_type)
{
case Canvas::TYPE_HDR:
internalFormat = GL_RGBA16F;
format = GL_FLOAT;
break;
case Canvas::TYPE_NORMAL:
default:
internalFormat = GL_RGBA8;
format = GL_UNSIGNED_BYTE;
}
glGenTextures(1, &img);
gl.bindTexture(img);
Texture::Filter filter = Texture::getDefaultFilter();
gl.setTextureFilter(filter);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
0, GL_RGBA, format, NULL);
gl.bindTexture(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, img, 0); GL_TEXTURE_2D, texture, 0);
// check status // check status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -149,9 +121,8 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
} }
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img) virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
{ {
gl.deleteTexture(img);
if (depth_stencil != 0) if (depth_stencil != 0)
glDeleteRenderbuffers(1, &depth_stencil); glDeleteRenderbuffers(1, &depth_stencil);
if (framebuffer != 0) if (framebuffer != 0)
@@ -198,7 +169,7 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
struct FramebufferStrategyPackedEXT : public FramebufferStrategy struct FramebufferStrategyPackedEXT : public FramebufferStrategy
{ {
virtual GLenum createFBO(GLuint &framebuffer, GLuint &img, int width, int height, Canvas::TextureType texture_type) virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
{ {
GLint current_fbo; GLint current_fbo;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo);
@@ -207,32 +178,8 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
glGenFramebuffersEXT(1, &framebuffer); glGenFramebuffersEXT(1, &framebuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
// generate texture save target
GLint internalFormat;
GLenum format;
switch (texture_type)
{
case Canvas::TYPE_HDR:
internalFormat = GL_RGBA16F;
format = GL_FLOAT;
break;
case Canvas::TYPE_NORMAL:
default:
internalFormat = GL_RGBA8;
format = GL_UNSIGNED_BYTE;
}
glGenTextures(1, &img);
gl.bindTexture(img);
Texture::Filter filter = Texture::getDefaultFilter();
gl.setTextureFilter(filter);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
0, GL_RGBA, format, NULL);
gl.bindTexture(0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, img, 0); GL_TEXTURE_2D, texture, 0);
// check status // check status
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
@@ -259,9 +206,8 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT; return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
} }
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img) virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
{ {
gl.deleteTexture(img);
if (depth_stencil != 0) if (depth_stencil != 0)
glDeleteRenderbuffersEXT(1, &depth_stencil); glDeleteRenderbuffersEXT(1, &depth_stencil);
if (framebuffer != 0) if (framebuffer != 0)
@@ -327,9 +273,9 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
bool isSupported() bool isSupported()
{ {
GLuint fb = 0, stencil = 0, img = 0; GLuint fb = 0, stencil = 0;
GLenum status = createFBO(fb, img, 2, 2, Canvas::TYPE_NORMAL); GLenum status = createFBO(fb, 0);
deleteFBO(fb, stencil, img); deleteFBO(fb, stencil);
return status == GL_FRAMEBUFFER_COMPLETE; return status == GL_FRAMEBUFFER_COMPLETE;
} }
}; };
@@ -367,8 +313,8 @@ static int maxDrawBuffers = 0;
Canvas::Canvas(int width, int height, TextureType texture_type) Canvas::Canvas(int width, int height, TextureType texture_type)
: fbo(0) : fbo(0)
, texture(0)
, depth_stencil(0) , depth_stencil(0)
, img(0)
, texture_type(texture_type) , texture_type(texture_type)
{ {
this->width = width; this->width = width;
@@ -413,7 +359,7 @@ Canvas::~Canvas()
bool Canvas::loadVolatile() bool Canvas::loadVolatile()
{ {
fbo = depth_stencil = img = 0; fbo = depth_stencil = texture = 0;
// glTexImage2D is guaranteed to error in this case. // glTexImage2D is guaranteed to error in this case.
if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize()) if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize())
@@ -422,20 +368,59 @@ bool Canvas::loadVolatile()
return false; return false;
} }
status = strategy->createFBO(fbo, img, width, height, texture_type); glGenTextures(1, &texture);
if (status != GL_FRAMEBUFFER_COMPLETE) gl.bindTexture(texture);
return false;
setFilter(filter); setFilter(filter);
setWrap(wrap); setWrap(wrap);
GLint internalformat;
GLenum textype;
switch (texture_type)
{
case TYPE_HDR:
internalformat = GL_RGBA16F;
textype = GL_FLOAT;
break;
case TYPE_NORMAL:
default:
internalformat = GL_RGBA8;
textype = GL_UNSIGNED_BYTE;
}
while (glGetError() != GL_NO_ERROR)
/* Clear the error buffer. */;
glTexImage2D(GL_TEXTURE_2D,
0,
internalformat,
width, height,
0,
GL_RGBA,
textype,
nullptr);
if (glGetError() != GL_NO_ERROR)
{
status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
return false;
}
status = strategy->createFBO(fbo, texture);
if (status != GL_FRAMEBUFFER_COMPLETE)
return false;
clear(Color(0, 0, 0, 0)); clear(Color(0, 0, 0, 0));
return true; return true;
} }
void Canvas::unloadVolatile() void Canvas::unloadVolatile()
{ {
strategy->deleteFBO(fbo, depth_stencil, img); strategy->deleteFBO(fbo, depth_stencil);
fbo = depth_stencil = img = 0;
gl.deleteTexture(texture);
fbo = depth_stencil = texture = 0;
for (size_t i = 0; i < attachedCanvases.size(); i++) for (size_t i = 0; i < attachedCanvases.size(); i++)
attachedCanvases[i]->release(); attachedCanvases[i]->release();
@@ -449,7 +434,7 @@ void Canvas::drawv(const Matrix &t, const Vertex *v) const
glMultMatrixf((const GLfloat *)t.getElements()); glMultMatrixf((const GLfloat *)t.getElements());
gl.bindTexture(img); gl.bindTexture(texture);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -486,25 +471,25 @@ void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy
void Canvas::setFilter(const Texture::Filter &f) void Canvas::setFilter(const Texture::Filter &f)
{ {
filter = f; filter = f;
gl.bindTexture(img); gl.bindTexture(texture);
gl.setTextureFilter(filter); gl.setTextureFilter(filter);
} }
void Canvas::setWrap(const Texture::Wrap &w) void Canvas::setWrap(const Texture::Wrap &w)
{ {
wrap = w; wrap = w;
gl.bindTexture(img); gl.bindTexture(texture);
gl.setTextureWrap(wrap); gl.setTextureWrap(wrap);
} }
GLuint Canvas::getGLTexture() const GLuint Canvas::getGLTexture() const
{ {
return img; return texture;
} }
void Canvas::predraw() const void Canvas::predraw() const
{ {
gl.bindTexture(img); gl.bindTexture(texture);
} }
void Canvas::setupGrab() void Canvas::setupGrab()
+1 -1
View File
@@ -113,8 +113,8 @@ public:
private: private:
GLuint fbo; GLuint fbo;
GLuint texture;
GLuint depth_stencil; GLuint depth_stencil;
GLuint img;
TextureType texture_type; TextureType texture_type;