Another take at issue #294, which should fix issues with nVidia cards.

According to http://www.opengl.org/wiki/Image_Formats#Depth_stencil_formats, no driver really supported an individial stencil attachment. Combined depth/stencil buffers have support since OpenGL 3.0 or with the packed_depth_stencil extension.
This commit is contained in:
vrld
2011-09-08 16:09:10 +02:00
parent 4f0028050d
commit 65f8bcd375
2 changed files with 39 additions and 58 deletions
+38 -36
View File
@@ -14,10 +14,10 @@ namespace opengl
// strategy for fbo creation, interchangable at runtime: // strategy for fbo creation, interchangable at runtime:
// none, opengl >= 3.0, extensions // none, opengl >= 3.0, extensions
struct FramebufferStrategy { struct FramebufferStrategy {
/// create a new framebuffer, stencilbuffer and texture /// create a new framebuffer, depth_stencil and texture
/** /**
* @param[out] framebuffer Framebuffer name * @param[out] framebuffer Framebuffer name
* @param[out] stencilbuffer Stencilbuffer name * @param[out] depth_stencil Name for packed depth and stencil buffer
* @param[out] img Texture name * @param[out] img Texture name
* @param[in] width Width of framebuffer * @param[in] width Width of framebuffer
* @param[in] height Height of framebuffer * @param[in] height Height of framebuffer
@@ -28,7 +28,7 @@ namespace opengl
/// remove objects /// remove objects
/** /**
* @param[in] framebuffer Framebuffer name * @param[in] framebuffer Framebuffer name
* @param[in] stencilbuffer Stencilbuffer name * @param[in] depth_stencil Name for packed depth and stencil buffer
* @param[in] img Texture name * @param[in] img Texture name
*/ */
virtual void deleteFBO(GLuint, GLuint, GLuint) {} virtual void deleteFBO(GLuint, GLuint, GLuint) {}
@@ -36,7 +36,7 @@ namespace opengl
}; };
struct FramebufferStrategyGL3 : public FramebufferStrategy { struct FramebufferStrategyGL3 : public FramebufferStrategy {
virtual GLenum createFBO(GLuint& framebuffer, GLuint& stencilbuffer, GLuint& img, int width, int height) virtual GLenum createFBO(GLuint& framebuffer, GLuint& depth_stencil, GLuint& img, int width, int height)
{ {
// get currently bound fbo to reset to it later // get currently bound fbo to reset to it later
GLint current_fbo; GLint current_fbo;
@@ -47,11 +47,13 @@ namespace opengl
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// create stencil buffer // create stencil buffer
glGenRenderbuffers(1, &stencilbuffer); glGenRenderbuffers(1, &depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, width, height); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencilbuffer); GL_RENDERBUFFER, depth_stencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil);
// generate texture save target // generate texture save target
glGenTextures(1, &img); glGenTextures(1, &img);
@@ -72,10 +74,10 @@ namespace opengl
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo); glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo);
return status; return status;
} }
virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer, GLuint img) virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
{ {
glDeleteTextures(1, &img); glDeleteTextures(1, &img);
glDeleteRenderbuffers(1, &stencilbuffer); glDeleteRenderbuffers(1, &depth_stencil);
glDeleteFramebuffers(1, &framebuffer); glDeleteFramebuffers(1, &framebuffer);
} }
@@ -87,7 +89,7 @@ namespace opengl
struct FramebufferStrategyEXT : public FramebufferStrategy { struct FramebufferStrategyEXT : public FramebufferStrategy {
virtual GLenum createFBO(GLuint& framebuffer, GLuint& stencilbuffer, GLuint& img, int width, int height) virtual GLenum createFBO(GLuint& framebuffer, GLuint& depth_stencil, GLuint& img, int width, int height)
{ {
GLint current_fbo; GLint current_fbo;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo);
@@ -97,11 +99,13 @@ namespace opengl
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
// create stencil buffer // create stencil buffer
glGenRenderbuffersEXT(1, &stencilbuffer); glGenRenderbuffersEXT(1, &depth_stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencilbuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, stencilbuffer); GL_RENDERBUFFER_EXT, depth_stencil);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_stencil);
// generate texture save target // generate texture save target
glGenTextures(1, &img); glGenTextures(1, &img);
@@ -123,10 +127,10 @@ namespace opengl
return status; return status;
} }
virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer, GLuint img) virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
{ {
glDeleteTextures(1, &img); glDeleteTextures(1, &img);
glDeleteRenderbuffersEXT(1, &stencilbuffer); glDeleteRenderbuffersEXT(1, &depth_stencil);
glDeleteFramebuffersEXT(1, &framebuffer); glDeleteFramebuffersEXT(1, &framebuffer);
} }
@@ -146,6 +150,18 @@ namespace opengl
Canvas* Canvas::current = NULL; Canvas* Canvas::current = NULL;
static void loadStrategy()
{
if (!strategy) {
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
strategy = &strategyGL3;
else if (GLEE_EXT_framebuffer_object && GLEE_EXT_packed_depth_stencil)
strategy = &strategyEXT;
else
strategy = &strategyNone;
}
}
Canvas::Canvas(int width, int height) : Canvas::Canvas(int width, int height) :
width(width), height(height) width(width), height(height)
{ {
@@ -166,14 +182,7 @@ namespace opengl
vertices[2].s = 1; vertices[2].t = 0; vertices[2].s = 1; vertices[2].t = 0;
vertices[3].s = 1; vertices[3].t = 1; vertices[3].s = 1; vertices[3].t = 1;
if (!strategy) { loadStrategy();
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
strategy = &strategyGL3;
else if (GLEE_EXT_framebuffer_object)
strategy = &strategyEXT;
else
strategy = &strategyNone;
}
loadVolatile(); loadVolatile();
} }
@@ -189,14 +198,7 @@ namespace opengl
bool Canvas::isSupported() bool Canvas::isSupported()
{ {
if (!strategy) { loadStrategy();
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
strategy = &strategyGL3;
else if (GLEE_EXT_framebuffer_object)
strategy = &strategyEXT;
else
strategy = &strategyNone;
}
return (strategy != &strategyNone); return (strategy != &strategyNone);
} }
@@ -260,7 +262,7 @@ namespace opengl
strategy->bindFBO(fbo); strategy->bindFBO(fbo);
glPushAttrib(GL_COLOR_BUFFER_BIT); glPushAttrib(GL_COLOR_BUFFER_BIT);
glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, (float)c.a/255.0f); glClearColor((float)c.r/255.0f, (float)c.g/255.0f, (float)c.b/255.0f, (float)c.a/255.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glPopAttrib(); glPopAttrib();
strategy->bindFBO(previous); strategy->bindFBO(previous);
@@ -369,7 +371,7 @@ namespace opengl
bool Canvas::loadVolatile() bool Canvas::loadVolatile()
{ {
status = strategy->createFBO(fbo, stencilbuffer, img, width, height); status = strategy->createFBO(fbo, depth_stencil, img, width, height);
if (status != GL_FRAMEBUFFER_COMPLETE) if (status != GL_FRAMEBUFFER_COMPLETE)
return false; return false;
@@ -385,7 +387,7 @@ namespace opengl
{ {
settings.filter = getFilter(); settings.filter = getFilter();
settings.wrap = getWrap(); settings.wrap = getWrap();
strategy->deleteFBO(fbo, stencilbuffer, img); strategy->deleteFBO(fbo, depth_stencil, img);
} }
int Canvas::getWidth() int Canvas::getWidth()
+1 -22
View File
@@ -49,27 +49,6 @@ namespace opengl
bool loadVolatile(); bool loadVolatile();
void unloadVolatile(); void unloadVolatile();
/// Unbind the current canvas on construction and rebind it upon destruction.
// Exception safe temporary unbinding/rebinding for techniques that require
// the default canvas to work (e.g. stencils).
// XXX: If a canvas is switched between creating and destroying an unbinder
// object, the canvas will not be switched back.
struct TemporaryUnbinder
{
Canvas * canvas;
inline TemporaryUnbinder() : canvas(Canvas::current)
{
if (NULL != canvas)
Canvas::bindDefaultCanvas();
}
inline ~TemporaryUnbinder()
{
if (NULL != canvas && NULL == Canvas::current)
canvas->startGrab();
}
};
private: private:
friend class PixelEffect; friend class PixelEffect;
GLuint getTextureName() const { return img; } GLuint getTextureName() const { return img; }
@@ -77,7 +56,7 @@ namespace opengl
GLsizei width; GLsizei width;
GLsizei height; GLsizei height;
GLuint fbo; GLuint fbo;
GLuint stencilbuffer; GLuint depth_stencil;
GLuint img; GLuint img;
vertex vertices[4]; vertex vertices[4];