mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
Cleaned up love.graphics.Framebuffer code, using GLee to check for support instead
This commit is contained in:
@@ -1,183 +1,18 @@
|
|||||||
#include "Framebuffer.h"
|
#include "Framebuffer.h"
|
||||||
#include <common/Matrix.h>
|
#include <common/Matrix.h>
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// functions to get opengl capabilities at runtime
|
|
||||||
vector<string> tokenize(const string& str)
|
|
||||||
{
|
|
||||||
vector<string> tokens;
|
|
||||||
|
|
||||||
istringstream iss( str );
|
|
||||||
copy(istream_iterator<string>(iss), istream_iterator<string>(),
|
|
||||||
back_inserter< vector<string> >(tokens));
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getOpenGLVersionNumber()
|
|
||||||
{
|
|
||||||
vector<string> tokens = tokenize( (const char*)glGetString(GL_VERSION) );
|
|
||||||
stringstream toNumber( tokens.at(0) );
|
|
||||||
|
|
||||||
double version;
|
|
||||||
toNumber >> version;
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasFramebufferExtension()
|
|
||||||
{
|
|
||||||
vector<string> ext = tokenize( (const char*)glGetString(GL_EXTENSIONS) );
|
|
||||||
return find(ext.begin(), ext.end(), "GL_EXT_framebuffer_object") != ext.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// strategy for fbo creation, interchangable at runtime:
|
|
||||||
// none, opengl >= 3.0, extensions
|
|
||||||
struct FramebufferStrategy {
|
|
||||||
/// create a new framebuffer, depthbuffer and texture
|
|
||||||
/**
|
|
||||||
* @param[out] framebuffer Framebuffer name
|
|
||||||
* @param[out] depthbuffer Depthbuffer name
|
|
||||||
* @param[out] img Texture name
|
|
||||||
* @param[in] width Width of framebuffer
|
|
||||||
* @param[in] height Height of framebuffer
|
|
||||||
* @return Creation status
|
|
||||||
*/
|
|
||||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
|
||||||
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
|
|
||||||
/// remove objects
|
|
||||||
/**
|
|
||||||
* @param[in] framebuffer Framebuffer name
|
|
||||||
* @param[in] depthbuffer Depthbuffer name
|
|
||||||
* @param[in] img Texture name
|
|
||||||
*/
|
|
||||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img) {}
|
|
||||||
virtual void bindFBO(GLuint framebuffer) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef GL_VERSION_3_0
|
|
||||||
struct FramebufferStrategyGL3 : public FramebufferStrategy {
|
|
||||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
|
||||||
{
|
|
||||||
// generate depth buffer
|
|
||||||
glGenRenderbuffers(1, &depthbuffer);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
|
|
||||||
// generate texture save target
|
|
||||||
glGenTextures(1, &img);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, img);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// create framebuffer
|
|
||||||
glGenFramebuffers(1, &framebuffer);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
||||||
GL_TEXTURE_2D, img, 0);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
||||||
GL_RENDERBUFFER, depthbuffer);
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
||||||
|
|
||||||
// unbind buffers and texture
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &img);
|
|
||||||
glDeleteRenderbuffers(1, &depthbuffer);
|
|
||||||
glDeleteFramebuffers(1, &framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void bindFBO(GLuint framebuffer)
|
|
||||||
{
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct FramebufferStrategyEXT : public FramebufferStrategy {
|
|
||||||
|
|
||||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
|
||||||
{
|
|
||||||
// generate depth buffer
|
|
||||||
glGenRenderbuffersEXT(1, &depthbuffer);
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
|
|
||||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
|
||||||
|
|
||||||
// generate texture save target
|
|
||||||
glGenTextures(1, &img);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, img);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// create framebuffer
|
|
||||||
glGenFramebuffersEXT(1, &framebuffer);
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
|
||||||
GL_TEXTURE_2D, img, 0);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
|
||||||
GL_RENDERBUFFER_EXT, depthbuffer);
|
|
||||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
|
||||||
|
|
||||||
// unbind buffers and texture
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &img);
|
|
||||||
glDeleteRenderbuffersEXT(1, &depthbuffer);
|
|
||||||
glDeleteFramebuffersEXT(1, &framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void bindFBO(GLuint framebuffer)
|
|
||||||
{
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FramebufferStrategy* strategy = NULL;
|
|
||||||
|
|
||||||
FramebufferStrategy strategyNone;
|
|
||||||
#ifdef GL_VERSION_3_0
|
|
||||||
FramebufferStrategyGL3 strategyGL3;
|
|
||||||
#endif
|
|
||||||
FramebufferStrategyEXT strategyEXT;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
namespace opengl
|
namespace opengl
|
||||||
{
|
{
|
||||||
Framebuffer* Framebuffer::current = NULL;
|
Framebuffer* Framebuffer::current = NULL;
|
||||||
|
|
||||||
Framebuffer::Framebuffer(int width, int height) :
|
Framebuffer::Framebuffer(int width, int height) :
|
||||||
width(width), height(height)
|
width(width), height(height)
|
||||||
{
|
{
|
||||||
|
strategy = NULL;
|
||||||
|
|
||||||
// world coordinates
|
// world coordinates
|
||||||
vertices[0].x = 0; vertices[0].y = 0;
|
vertices[0].x = 0; vertices[0].y = 0;
|
||||||
@@ -192,17 +27,12 @@ namespace opengl
|
|||||||
vertices[3].s = 1; vertices[3].t = 1;
|
vertices[3].s = 1; vertices[3].t = 1;
|
||||||
|
|
||||||
if (!strategy) {
|
if (!strategy) {
|
||||||
#ifdef GL_VERSION_3_0
|
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
|
||||||
if (getOpenGLVersionNumber() >= 3.0)
|
|
||||||
strategy = &strategyGL3;
|
strategy = &strategyGL3;
|
||||||
else if (hasFramebufferExtension())
|
else if (GLEE_EXT_framebuffer_object)
|
||||||
#else
|
strategy = &strategyEXT;
|
||||||
if (hasFramebufferExtension())
|
|
||||||
#endif
|
|
||||||
strategy = &strategyEXT;
|
|
||||||
else
|
else
|
||||||
strategy = &strategyNone;
|
strategy = &strategyNone;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadVolatile();
|
loadVolatile();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <image/Image.h>
|
#include <image/Image.h>
|
||||||
#include <image/ImageData.h>
|
#include <image/ImageData.h>
|
||||||
#include <common/math.h>
|
#include <common/math.h>
|
||||||
#include <map>
|
|
||||||
#include "GLee.h"
|
#include "GLee.h"
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
@@ -15,6 +14,120 @@ namespace graphics
|
|||||||
{
|
{
|
||||||
namespace opengl
|
namespace opengl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// strategy for fbo creation, interchangable at runtime:
|
||||||
|
// none, opengl >= 3.0, extensions
|
||||||
|
struct FramebufferStrategy {
|
||||||
|
/// create a new framebuffer, depthbuffer and texture
|
||||||
|
/**
|
||||||
|
* @param[out] framebuffer Framebuffer name
|
||||||
|
* @param[out] depthbuffer Depthbuffer name
|
||||||
|
* @param[out] img Texture name
|
||||||
|
* @param[in] width Width of framebuffer
|
||||||
|
* @param[in] height Height of framebuffer
|
||||||
|
* @return Creation status
|
||||||
|
*/
|
||||||
|
virtual GLenum createFBO(GLuint&, GLuint&, GLuint&, int, int)
|
||||||
|
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
|
||||||
|
/// remove objects
|
||||||
|
/**
|
||||||
|
* @param[in] framebuffer Framebuffer name
|
||||||
|
* @param[in] depthbuffer Depthbuffer name
|
||||||
|
* @param[in] img Texture name
|
||||||
|
*/
|
||||||
|
virtual void deleteFBO(GLuint, GLuint, GLuint) {}
|
||||||
|
virtual void bindFBO(GLuint) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FramebufferStrategyGL3 : public FramebufferStrategy {
|
||||||
|
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
||||||
|
{
|
||||||
|
// generate depth buffer
|
||||||
|
glGenRenderbuffers(1, &depthbuffer);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
|
// generate texture save target
|
||||||
|
glGenTextures(1, &img);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, img);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||||
|
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// create framebuffer
|
||||||
|
glGenFramebuffers(1, &framebuffer);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_TEXTURE_2D, img, 0);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||||
|
GL_RENDERBUFFER, depthbuffer);
|
||||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
|
||||||
|
// unbind buffers and texture
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &img);
|
||||||
|
glDeleteRenderbuffers(1, &depthbuffer);
|
||||||
|
glDeleteFramebuffers(1, &framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void bindFBO(GLuint framebuffer)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FramebufferStrategyEXT : public FramebufferStrategy {
|
||||||
|
|
||||||
|
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
||||||
|
{
|
||||||
|
// generate depth buffer
|
||||||
|
glGenRenderbuffersEXT(1, &depthbuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
// generate texture save target
|
||||||
|
glGenTextures(1, &img);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, img);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||||
|
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// create framebuffer
|
||||||
|
glGenFramebuffersEXT(1, &framebuffer);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||||
|
GL_TEXTURE_2D, img, 0);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||||
|
GL_RENDERBUFFER_EXT, depthbuffer);
|
||||||
|
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
|
||||||
|
// unbind buffers and texture
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &img);
|
||||||
|
glDeleteRenderbuffersEXT(1, &depthbuffer);
|
||||||
|
glDeleteFramebuffersEXT(1, &framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void bindFBO(GLuint framebuffer)
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Framebuffer : public Drawable, public Volatile
|
class Framebuffer : public Drawable, public Volatile
|
||||||
{
|
{
|
||||||
@@ -46,6 +159,14 @@ namespace opengl
|
|||||||
vertex vertices[4];
|
vertex vertices[4];
|
||||||
|
|
||||||
GLenum status;
|
GLenum status;
|
||||||
|
|
||||||
|
FramebufferStrategy* strategy;
|
||||||
|
|
||||||
|
FramebufferStrategy strategyNone;
|
||||||
|
|
||||||
|
FramebufferStrategyGL3 strategyGL3;
|
||||||
|
|
||||||
|
FramebufferStrategyEXT strategyEXT;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // opengl
|
} // opengl
|
||||||
|
|||||||
Reference in New Issue
Block a user