Browse Source

Add guards to prevent fbo nesting

vrld 15 years ago
parent
commit
ce0006d04c

+ 16 - 2
src/modules/graphics/opengl/Framebuffer.cpp

@@ -8,6 +8,7 @@ namespace graphics
 namespace opengl
 {
 
+	bool Framebuffer::isGrabbing = false;
 	std::map<GLenum, const char*> Framebuffer::status_to_string;
 
 	Framebuffer::Framebuffer(int width, int height) :
@@ -89,19 +90,32 @@ namespace opengl
 		status_to_string[statusCode()];
 	}
 
-	void Framebuffer::grab()
+	bool Framebuffer::grab()
 	{
+		// don't allow nesting or forgetting Framebuffer::stop()
+		if (isGrabbing)
+			return false;
+
 		glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 		glClearColor(.0f, .0f, .0f, .0f);
 		glViewport(0, 0, width, height);
+		isGrabbing = true;
+
+		return true;
 	}
 
-	void Framebuffer::stop()
+	bool Framebuffer::stop()
 	{
+		if (!isGrabbing)
+			return false;
+
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
 		glPopAttrib();
+		isGrabbing = false;
+
+		return true;
 	}
 
 	void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const

+ 5 - 3
src/modules/graphics/opengl/Framebuffer.h

@@ -24,21 +24,23 @@ namespace opengl
 		GLenum statusCode() const { return status_; } //SERIOUS DISLIKE HERE
 		const char* statusMessage() const;
 
-		void grab();
-		void stop();
+		bool grab();
+		bool stop();
 
 		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
 
 	private:
+		static bool isGrabbing;
+
 		GLsizei width;
 		GLsizei height;
 		GLuint fbo;
 		GLuint depthbuffer;
 		GLuint img;
-		GLenum status_;
 
 		vertex vertices[4];
 
+		GLenum status_;
 		static std::map<GLenum, const char*> status_to_string;
 	};
 

+ 11 - 4
src/modules/graphics/opengl/wrap_Framebuffer.cpp

@@ -17,12 +17,16 @@ namespace opengl
 		if (!lua_isfunction(L, 2))
 			return luaL_error(L, "Need a function to render to fbo");
 
-		fbo->grab();
+		// prevent nesting
+		if (!fbo->grab())
+			return luaL_error(L, "Cannot grab screen. May be caused by nesting or forgetting to stop()");
 
 		lua_settop(L, 2); // make sure the function is on top of the stack
 		lua_pcall(L, 0, 0, 0);
 
-		fbo->stop();
+		// fbo can be stopped in function.
+		if (!fbo->stop())
+			return luaL_error(L, "Grabbing already stopped.");
 
 		return 0;
 	}
@@ -30,14 +34,17 @@ namespace opengl
 	int w_Framebuffer_grab(lua_State * L)
 	{
 		Framebuffer * fbo = luax_checkfbo(L, 1);
-		fbo->grab();
+		// prevent nesting
+		if (!fbo->grab())
+			return luaL_error(L, "Cannot grab screen. May be caused by nesting or forgetting to stop()");
 		return 0;
 	}
 
 	int w_Framebuffer_stop(lua_State * L)
 	{
 		Framebuffer * fbo = luax_checkfbo(L, 1);
-		fbo->stop();
+		if (!fbo->stop())
+			return luaL_error(L, "Grabbing already stopped.");
 		return 0;
 	}