Commits

vrld  committed bfc5e88

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.

  • Participants
  • Parent commits 243568a

Comments (0)

Files changed (2)

File src/modules/graphics/opengl/Canvas.cpp

 	// strategy for fbo creation, interchangable at runtime:
 	// none, opengl >= 3.0, extensions
 	struct FramebufferStrategy {
-		/// create a new framebuffer, stencilbuffer and texture
+		/// create a new framebuffer, depth_stencil and texture
 		/**
 		 * @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[in]  width         Width of framebuffer
 		 * @param[in]  height        Height of framebuffer
 		/// remove objects
 		/**
 		 * @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
 		 */
 		virtual void deleteFBO(GLuint, GLuint, GLuint) {}
 	};
 
 	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
 			GLint current_fbo;
 			glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
 
 			// create stencil buffer
-			glGenRenderbuffers(1, &stencilbuffer);
-			glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer);
-			glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, width, height);
+			glGenRenderbuffers(1, &depth_stencil);
+			glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
+			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
 			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
 			glGenTextures(1, &img);
 			glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo);
 			return status;
 		}
-		virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer,  GLuint img)
+		virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil,  GLuint img)
 		{
 			glDeleteTextures(1, &img);
-			glDeleteRenderbuffers(1, &stencilbuffer);
+			glDeleteRenderbuffers(1, &depth_stencil);
 			glDeleteFramebuffers(1, &framebuffer);
 		}
 
 
 	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;
 			glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo);
 			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
 
 			// create stencil buffer
-			glGenRenderbuffersEXT(1, &stencilbuffer);
-			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencilbuffer);
-			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height);
+			glGenRenderbuffersEXT(1, &depth_stencil);
+			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil);
+			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
 			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
 			glGenTextures(1, &img);
 			return status;
 		}
 
-		virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer, GLuint img)
+		virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
 		{
 			glDeleteTextures(1, &img);
-			glDeleteRenderbuffersEXT(1, &stencilbuffer);
+			glDeleteRenderbuffersEXT(1, &depth_stencil);
 			glDeleteFramebuffersEXT(1, &framebuffer);
 		}
 
 	
 	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) :
 		width(width), height(height)
 	{
 		vertices[2].s = 1;     vertices[2].t = 0;
 		vertices[3].s = 1;     vertices[3].t = 1;
 
-		if (!strategy) {
-			if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
-				strategy = &strategyGL3;
-			else if (GLEE_EXT_framebuffer_object)
-				strategy = &strategyEXT;
-			else
-				strategy = &strategyNone;
-		}
+		loadStrategy();
 
 		loadVolatile();
 	}
 
 	bool Canvas::isSupported()
 	{
-		if (!strategy) {
-			if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
-				strategy = &strategyGL3;
-			else if (GLEE_EXT_framebuffer_object)
-				strategy = &strategyEXT;
-			else
-				strategy = &strategyNone;
-		}
+		loadStrategy();
 		return (strategy != &strategyNone);
 	}
 
 		strategy->bindFBO(fbo);
 		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);
-		glClear(GL_COLOR_BUFFER_BIT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 		glPopAttrib();
 
 		strategy->bindFBO(previous);
 
 	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)
 			return false;
 
 	{
 		settings.filter = getFilter();
 		settings.wrap   = getWrap();
-		strategy->deleteFBO(fbo, stencilbuffer, img);
+		strategy->deleteFBO(fbo, depth_stencil, img);
 	}
 
 	int Canvas::getWidth()

File src/modules/graphics/opengl/Canvas.h

 		bool loadVolatile();
 		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:
 		friend class PixelEffect;
 		GLuint getTextureName() const { return img; }
 		GLsizei width;
 		GLsizei height;
 		GLuint fbo;
-		GLuint stencilbuffer;
+		GLuint depth_stencil;
 		GLuint img;
 
 		vertex vertices[4];