[Bf-blender-cvs] [a2bebb0] decklink: BGE: asynchronous render with ImageRender new render() method

Benoit Bolsee noreply at git.blender.org
Tue Nov 3 17:41:19 CET 2015


Commit: a2bebb088095343af9af3a4799d46b6328ae84d7
Author: Benoit Bolsee
Date:   Tue Nov 3 17:37:50 2015 +0100
Branches: decklink
https://developer.blender.org/rBa2bebb088095343af9af3a4799d46b6328ae84d7

BGE: asynchronous render with ImageRender new render() method

usage:
ir = bge.texture.ImageRender(..)
ir.render()
ir.refresh(buffer)

===================================================================

M	source/gameengine/Rasterizer/RAS_IOffScreen.h
M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
M	source/gameengine/VideoTexture/ImageRender.cpp
M	source/gameengine/VideoTexture/ImageRender.h

===================================================================

diff --git a/source/gameengine/Rasterizer/RAS_IOffScreen.h b/source/gameengine/Rasterizer/RAS_IOffScreen.h
index 0acf1bb..6063d90 100644
--- a/source/gameengine/Rasterizer/RAS_IOffScreen.h
+++ b/source/gameengine/Rasterizer/RAS_IOffScreen.h
@@ -46,6 +46,10 @@ struct Image;
 class RAS_IOffScreen
 {
 public:
+	enum RAS_OFS_BIND_MODE {
+		RAS_OFS_BIND_RENDER = 0,
+		RAS_OFS_BIND_READ,
+	};
 	int		m_width;
 	int     m_height;
 	int	    m_samples;
@@ -54,7 +58,7 @@ public:
 
 	virtual bool Create(int width, int height, int samples) = 0;
 	virtual void Destroy() = 0;
-	virtual void Bind() = 0;
+	virtual void Bind(RAS_OFS_BIND_MODE mode) = 0;
 	virtual void Blit() = 0;
 	virtual void Unbind() = 0;
 
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
index bde6764..decf921 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
@@ -133,11 +133,14 @@ void RAS_OpenGLOffScreen::Destroy()
 	m_samples = 0;
 }
 
-void RAS_OpenGLOffScreen::Bind()
+void RAS_OpenGLOffScreen::Bind(RAS_OFS_BIND_MODE mode)
 {
 	if (m_ofs)
 	{
-		GPU_offscreen_bind(m_ofs, false);
+		if (mode == RAS_OFS_BIND_RENDER || !m_blitfbo)
+			GPU_offscreen_bind(m_ofs, false);
+		else
+			glBindFramebuffer(GL_READ_FRAMEBUFFER, m_blitfbo);
 		m_bound = true;
 	}
 }
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
index 63ac02f..86c6dce 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
@@ -44,7 +44,7 @@ public:
 
 	bool Create(int width, int height, int samples);
 	void Destroy();
-	void Bind();
+	void Bind(RAS_OFS_BIND_MODE mode);
 	void Blit();
 	void Unbind();
 };
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index e3e3551..776cae1 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -68,6 +68,7 @@ ExpDesc MirrorTooSmallDesc(MirrorTooSmall, "Mirror is too small");
 ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera, PyRASOffScreen * offscreen) :
     ImageViewport(offscreen),
     m_render(true),
+    m_done(false),
     m_scene(scene),
     m_camera(camera),
     m_owncamera(false),
@@ -133,24 +134,26 @@ void ImageRender::setBackgroundFromScene (KX_Scene *scene)
 void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int format)
 {
 	// render the scene from the camera
-	if (!Render())
+	if (!m_done)
 	{
-		m_avail = false;
-		return;
+		if (!Render())
+		{
+			return;
+		}
+	}
+	else if (m_offscreen)
+	{
+		m_offscreen->ofs->Bind(RAS_IOffScreen::RAS_OFS_BIND_READ);
 	}
-
-	// In case multisample is active, blit the FBO
-	if (m_offscreen)
-		m_offscreen->ofs->Blit();
 
 	// get image from viewport (or FBO)
 	ImageViewport::calcViewport(texId, ts, format);
-	// restore OpenGL state
-	m_canvas->EndFrame();
 	if (m_offscreen)
 	{
 		m_offscreen->ofs->Unbind();
 	}
+	// so that next time we render again
+	m_done = false;
 }
 
 bool ImageRender::Render()
@@ -238,7 +241,7 @@ bool ImageRender::Render()
 	if (m_offscreen)
 	{
 		// bind the fbo and set the viewport to full size
-		m_offscreen->ofs->Bind();
+		m_offscreen->ofs->Bind(RAS_IOffScreen::RAS_OFS_BIND_RENDER);
 		// this is needed to stop crashing in canvas check
 		m_canvas->UpdateViewPort(0, 0, m_offscreen->ofs->GetWidth(), m_offscreen->ofs->GetHeight());
 	}
@@ -345,10 +348,25 @@ bool ImageRender::Render()
 
 	// restore the canvas area now that the render is completed
 	m_canvas->GetWindowArea() = area;
+	m_canvas->EndFrame();
 
+	// In case multisample is active, blit the FBO
+	if (m_offscreen)
+		m_offscreen->ofs->Blit();
+	// remember that we have done render
+	m_done = true;
+	// the image is not available at this stage
+	m_avail = false;
 	return true;
 }
 
+void ImageRender::Unbind()
+{
+	if (m_offscreen)
+	{
+		m_offscreen->ofs->Unbind();
+	}
+}
 
 // cast Image pointer to ImageRender
 inline ImageRender * getImageRender (PyImage *self)
@@ -411,6 +429,24 @@ static int ImageRender_init(PyObject *pySelf, PyObject *args, PyObject *kwds)
 	return 0;
 }
 
+// refresh image
+static PyObject *ImageRender_render(PyImage *self)
+{
+	ImageRender *imageRender = getImageRender(self);
+
+	if (!imageRender)
+	{
+		PyErr_SetString(PyExc_TypeError, "Incomplete ImageRender() object");
+		return NULL;
+	}
+	if (!imageRender->Render())
+	{
+		Py_RETURN_FALSE;
+	}
+	imageRender->Unbind();
+	Py_RETURN_TRUE;
+}
+
 
 // get background color
 static PyObject *getBackground (PyImage *self, void *closure)
@@ -450,6 +486,7 @@ static int setBackground(PyImage *self, PyObject *value, void *closure)
 static PyMethodDef imageRenderMethods[] =
 { // methods from ImageBase class
 	{"refresh", (PyCFunction)Image_refresh, METH_VARARGS, "Refresh image - invalidate its current content after optionally transferring its content to a target buffer"},
+	{"render", (PyCFunction)ImageRender_render, METH_NOARGS, "Render scene - run before refresh() to performs asynchronous render"},
 	{NULL}
 };
 // attributes structure
@@ -640,6 +677,7 @@ static PyGetSetDef imageMirrorGetSets[] =
 ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObject *mirror, RAS_IPolyMaterial *mat) :
     ImageViewport(),
     m_render(false),
+    m_done(false),
     m_scene(scene),
     m_offscreen(NULL),
     m_observer(observer),
diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h
index 5b7c789..cc4c862 100644
--- a/source/gameengine/VideoTexture/ImageRender.h
+++ b/source/gameengine/VideoTexture/ImageRender.h
@@ -64,10 +64,16 @@ public:
 	float getClip (void) { return m_clip; }
 	/// set whole buffer use
 	void setClip (float clip) { m_clip = clip; }
+	/// render frame (public so that it is accessible from python)
+	bool Render();
+	/// in case fbo is used, method to unbind
+	void Unbind();
 
 protected:
 	/// true if ready to render
 	bool m_render;
+	/// is render done already?
+	bool m_done;
 	/// rendered scene
 	KX_Scene * m_scene;
 	/// camera for render
@@ -103,9 +109,6 @@ protected:
 	/// render 3d scene to image
 	virtual void calcViewport (unsigned int texId, double ts, unsigned int format);
 
-	bool Render();
-	void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam);
-	void RenderFrame(KX_Scene* scene, KX_Camera* cam);
 	void setBackgroundFromScene(KX_Scene *scene);
 	void SetWorldSettings(KX_WorldInfo* wi);
 };




More information about the Bf-blender-cvs mailing list