mirror of
https://github.com/love2d/love.git
synced 2026-08-18 03:34:23 +02:00
Separated canvas texture creation code from FBO creation code
This commit is contained in:
@@ -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, ¤t_fbo);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user