Browse Source

Fix of http://bitbucket.org/bartbes/love-fbo/issue/7

Move fbo:grab() to love.graphics.setRenderTarget( fbo )
Move fbo:stop() to love.graphics.setRenderTarget( nil )

Rename fbo:render( func ) to fbo:renderTo( func )
vrld 15 years ago
parent
commit
320ac05fd1

+ 30 - 14
src/modules/graphics/opengl/Framebuffer.cpp

@@ -7,8 +7,8 @@ namespace graphics
 {
 namespace opengl
 {
+	Framebuffer* Framebuffer::current = NULL;
 
-	bool Framebuffer::isGrabbing = false;
 	Framebuffer::Framebuffer(int width, int height) :
 		width(width), height(height)
 	{
@@ -47,7 +47,7 @@ namespace opengl
 				GL_TEXTURE_2D, img, 0);
 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
 				GL_RENDERBUFFER, depthbuffer);
-		status_ = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 
 		// unbind buffers and texture
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -55,37 +55,53 @@ namespace opengl
 
 	Framebuffer::~Framebuffer()
 	{
+		// reset framebuffer if still using this one
+		if (current == this)
+			stopGrab();
+
+		// clear fbo
 		glDeleteTextures(1, &fbo);
 		glDeleteRenderbuffers(1, &depthbuffer);
 		glDeleteFramebuffers(1, &img);
 	}
 
-	bool Framebuffer::grab()
+	void Framebuffer::bindDefaultBuffer()
+	{
+		if (current != NULL)
+			current->stopGrab();
+	}
+
+	void Framebuffer::startGrab()
 	{
-		// don't allow nesting or forgetting Framebuffer::stop()
-		if (isGrabbing)
-			return false;
+		// already grabbing
+		if (current == this)
+			return;
+
+		// cleanup after previous fbo
+		if (current != NULL)
+			glPopAttrib();
 
+		// bind buffer and clear screen
 		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;
+		// indicate
+		current = this;
 	}
 
-	bool Framebuffer::stop()
+	void Framebuffer::stopGrab()
 	{
-		if (!isGrabbing)
-			return false;
+		// i am not grabbing. leave me alone
+		if (current != this)
+			return;
 
+		// bind default
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
 		glPopAttrib();
-		isGrabbing = false;
-
-		return true;
+		current = NULL;
 	}
 
 	void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const

+ 8 - 6
src/modules/graphics/opengl/Framebuffer.h

@@ -20,16 +20,18 @@ namespace opengl
 		Framebuffer(int width, int height);
 		virtual ~Framebuffer();
 
-		unsigned int getStatus() const { return status_; }
+		unsigned int getStatus() const { return status; }
 
-		bool grab();
-		bool stop();
+		static Framebuffer* current;
+		static void bindDefaultBuffer();
+
+		void startGrab();
+		void stopGrab();
 
 		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
 
-	private:
-		static bool isGrabbing;
 
+	private:
 		GLsizei width;
 		GLsizei height;
 		GLuint fbo;
@@ -38,7 +40,7 @@ namespace opengl
 
 		vertex vertices[4];
 
-		GLenum status_;
+		GLenum status;
 	};
 
 } // opengl

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

@@ -11,51 +11,29 @@ namespace opengl
 		return luax_checktype<Framebuffer>(L, idx, "Framebuffer", GRAPHICS_FRAMEBUFFER_T);
 	}
 
-	int w_Framebuffer_render(lua_State * L)
+	int w_Framebuffer_renderTo(lua_State * L)
 	{
+		// As startGrab() clears the framebuffer, better not allow
+		// grabbing inside another grabbing
+		if (Framebuffer::current != NULL) {
+			Framebuffer::bindDefaultBuffer();
+			return luaL_error(L, "Current render target not the default framebuffer!");
+		}
+
 		Framebuffer * fbo = luax_checkfbo(L, 1);
 		if (!lua_isfunction(L, 2))
 			return luaL_error(L, "Need a function to render to fbo");
 
-		// prevent nesting
-		if (!fbo->grab()) {
-			fbo->stop(); // stop grabbing so errormessage is shown
-			return luaL_error(L, "Framebuffer:grab(): Cannot grab screen. Be sure to match every Framebuffer:grab() with Framebuffer:stop().");
-		}
-
+		fbo->startGrab();
 		lua_settop(L, 2); // make sure the function is on top of the stack
 		lua_call(L, 0, 0);
+		fbo->stopGrab();
 
-		// fbo can be stopped in function.
-		if (!fbo->stop())
-			return luaL_error(L, "Framebuffer:render(): Screengrabbing already stopped.");
-
-		return 0;
-	}
-
-	int w_Framebuffer_grab(lua_State * L)
-	{
-		Framebuffer * fbo = luax_checkfbo(L, 1);
-		// prevent nesting
-		if (!fbo->grab()) {
-			fbo->stop(); // stop grabbing so errormessage is shown
-			return luaL_error(L, "Framebuffer:grab(): Cannot grab screen. Be sure to match every Framebuffer:grab() with Framebuffer:stop().");
-		}
-		return 0;
-	}
-
-	int w_Framebuffer_stop(lua_State * L)
-	{
-		Framebuffer * fbo = luax_checkfbo(L, 1);
-		if (!fbo->stop())
-			return luaL_error(L, "Framebuffer:stop(): Screengrabbing already stopped.");
 		return 0;
 	}
 
 	static const luaL_Reg functions[] = {
-		{ "render", w_Framebuffer_render },
-		{ "grab", w_Framebuffer_grab },
-		{ "stop", w_Framebuffer_stop },
+		{ "renderTo", w_Framebuffer_renderTo },
 		{ 0, 0 }
 	};
 

+ 1 - 3
src/modules/graphics/opengl/wrap_Framebuffer.h

@@ -13,9 +13,7 @@ namespace opengl
 {
 	//see Framebuffer.h
 	Framebuffer * luax_checkfbo(lua_State * L, int idx);
-	int w_Framebuffer_render(lua_State * L);
-	int w_Framebuffer_bind(lua_State * L);
-	int w_Framebuffer_unbind(lua_State * L);
+	int w_Framebuffer_renderTo(lua_State * L);
 	int luaopen_framebuffer(lua_State * L);
 
 } // opengl

+ 16 - 0
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -595,6 +595,21 @@ namespace opengl
 		return 1;
 	}
 
+	int w_setRenderTarget(lua_State * L)
+	{
+		// called with nil -> reset to default buffer
+		if (lua_isnil(L, 1)) {
+			Framebuffer::bindDefaultBuffer();
+			return 0;
+		}
+
+		Framebuffer * fbo = luax_checkfbo(L, 1);
+		// this unbinds the previous fbo
+		fbo->startGrab();
+
+		return 0;
+	}
+
 	/**
 	* Draws an Image at the specified coordinates, with rotation and
 	* scaling along both axes.
@@ -885,6 +900,7 @@ namespace opengl
 		{ "getPointStyle", w_getPointStyle },
 		{ "getMaxPointSize", w_getMaxPointSize },
 		{ "newScreenshot", w_newScreenshot },
+		{ "setRenderTarget", w_setRenderTarget },
 
 		{ "draw", w_draw },
 		{ "drawq", w_drawq },

+ 1 - 0
src/modules/graphics/opengl/wrap_Graphics.h

@@ -84,6 +84,7 @@ namespace opengl
 	int w_getPointStyle(lua_State * L);
 	int w_getMaxPointSize(lua_State * L);
 	int w_newScreenshot(lua_State * L);
+	int w_setRenderTarget(lua_State * L);
 	int w_draw(lua_State * L);
 	int w_drawq(lua_State * L);
 	int w_drawTest(lua_State * L);