[Bf-blender-cvs] [47b0327] decklink: BGE: RASOffScreen object reimplemented with Renderbuffers.

Benoit Bolsee noreply at git.blender.org
Thu Nov 5 18:58:21 CET 2015


Commit: 47b0327de1d205de2ce99d0d6b20cd6eec491069
Author: Benoit Bolsee
Date:   Thu Nov 5 18:32:37 2015 +0100
Branches: decklink
https://developer.blender.org/rB47b0327de1d205de2ce99d0d6b20cd6eec491069

BGE: RASOffScreen object reimplemented with Renderbuffers.

RASOffScreen was previously using GPUOffScreen object from the gpu library,
which in turn uses textures as render destinations, also when multisample is
requested. This is a problem for Intel integrated as they generally don't
support multisample textures.

ImageRender doesn't need textures as render destination: Renderbuffers are
sufficient because it only read pixels from the render with glReadPixels and
glCopyTexSubImage, both of which work with Renderbuffers.

Therefore, RASOffScreen is reimplemented with Renderbuffers and multisample
offscreen renders are now supported on Intel GMA. The gpu library is no
longer used. There is no API change.

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

M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
M	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h

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

diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
index decf921..570ff34 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
@@ -33,7 +33,7 @@
 #include "RAS_ICanvas.h"
 
 RAS_OpenGLOffScreen::RAS_OpenGLOffScreen(RAS_ICanvas *canvas)
-    :m_ofs(NULL), m_canvas(canvas), m_blitfbo(0), m_blittex(0), m_bound(false)
+    :m_canvas(canvas), m_depthrb(0), m_colorrb(0), m_fbo(0), m_blitfbo(0), m_blitrbo(0), m_bound(false)
 {
 	m_width = 0;
 	m_height = 0;
@@ -47,39 +47,91 @@ RAS_OpenGLOffScreen::~RAS_OpenGLOffScreen()
 
 bool RAS_OpenGLOffScreen::Create(int width, int height, int samples)
 {
-	char err_out[256];
 	GLenum status;
+	GLuint rbo[2], fbo;
+	int max_samples;
 
-	if (m_ofs)
+	if (m_fbo)
 	{
 		printf("RAS_OpenGLOffScreen::Create(): buffer exists already, destroy first\n");
 		return false;
 	}
 
-	m_ofs = GPU_offscreen_create(width, height, samples, err_out);
-	if (m_ofs == NULL)
+	if (!GLEW_EXT_framebuffer_object)
 	{
-		printf("RAS_OpenGLOffScreen::Create(): failed creating an offscreen buffer (%s)\n", err_out);
+		printf("RAS_OpenGLOffScreen::Create(): frame buffer not supported\n");
 		return false;
 	}
+	if (samples)
+	{
+		if (   !GLEW_EXT_framebuffer_multisample
+		    || !GLEW_EXT_framebuffer_blit)
+		{
+			samples = 0;
+		}
+	}
+	if (samples)
+	{
+		max_samples = 0;
+		glGetIntegerv(GL_MAX_SAMPLES_EXT , &max_samples);
+		if (samples > max_samples)
+			samples = max_samples;
+	}
+	fbo = 0;
+	glGenFramebuffersEXT(1, &fbo);
+	if (fbo == 0)
+	{
+		printf("RAS_OpenGLOffScreen::Create(): frame buffer creation failed: %d\n", (int)glGetError());
+		return false;
+	}
+	m_fbo = fbo;
+	rbo[0] = rbo[1] = 0;
+	//glGenTextures(2, rbo);
+	glGenRenderbuffersEXT(2, rbo);
+	if (rbo[0] == 0 || rbo[1] == 0)
+	{
+		printf("RAS_OpenGLOffScreen::Create(): render buffer creation failed: %d\n", (int)glGetError());
+		goto L_ERROR;
+	}
+	m_depthrb = rbo[0];
+	m_colorrb = rbo[1];
+	glBindRenderbufferEXT(GL_RENDERBUFFER, m_depthrb);
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT, width, height);
+	glBindRenderbufferEXT(GL_RENDERBUFFER, m_colorrb);
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
+	glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, m_depthrb);
+	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER, m_colorrb);
+
+	status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+	if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+		printf("RAS_OpenGLOffScreen::Create(): frame buffer incomplete: %d\n", (int)status);
+		goto L_ERROR;
+	}
 	m_width = width;
 	m_height = height;
 
-	if (GPU_offscreen_color_target(m_ofs) == GL_TEXTURE_2D_MULTISAMPLE)
+	if (samples > 0)
 	{
 		GLuint blit_tex;
 		GLuint blit_fbo;
 		// create a secondary FBO to blit to before the pixel can be read
 
-		/* create texture for new 'fbo_blit' */
-		glGenTextures(1, &blit_tex);
+		/* create render buffer for new 'fbo_blit' */
+		blit_tex = 0;
+		glGenRenderbuffersEXT(1, &blit_tex);
 		if (!blit_tex) {
-			printf("RAS_OpenGLOffScreen::Create(): failed creating a texture for multi-sample offscreen buffer\n");
+			printf("RAS_OpenGLOffScreen::Create(): failed creating a render buffer for multi-sample offscreen buffer\n");
 			goto L_ERROR;
 		}
-		m_blittex = blit_tex;
-		glBindTexture(GL_TEXTURE_2D, m_blittex);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		m_blitrbo = blit_tex;
+		glBindRenderbufferEXT(GL_RENDERBUFFER, m_blitrbo);
+		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 0, GL_RGBA8, width, height);
+		glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
 
 		/* write into new single-sample buffer */
 		glGenFramebuffersEXT(1, &blit_fbo);
@@ -88,16 +140,14 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples)
 			goto L_ERROR;
 		}
 		m_blitfbo = blit_fbo;
-		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, m_blitfbo);
-		glFramebufferTexture2DEXT(
-		        GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-		        GL_TEXTURE_2D, m_blittex, 0);
-		status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_blitfbo);
+		glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER, m_blitrbo);
+		status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
 		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			printf("RAS_OpenGLOffScreen::Create(): frame buffer for multi-sample offscreen buffer incomplete: %d\n", (int)status);
 			goto L_ERROR;
 		}
-		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-		glBindTexture(GL_TEXTURE_2D, 0);
 		// remember that multisample is enabled
 		m_samples = 1;
 	}
@@ -110,24 +160,45 @@ bool RAS_OpenGLOffScreen::Create(int width, int height, int samples)
 
 void RAS_OpenGLOffScreen::Destroy()
 {
-	if (m_ofs)
+	GLuint globj;
+	Unbind();
+	if (m_fbo)
+	{
+		globj = m_fbo;
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0);
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+		glDeleteFramebuffersEXT(1, &globj);
+		m_fbo = 0;
+	}
+	if (m_depthrb)
 	{
-		Unbind();
-		GPU_offscreen_free(m_ofs);
-		m_ofs = NULL;
+		globj = m_depthrb;
+		glDeleteRenderbuffers(1, &globj);
+		m_depthrb = 0;
 	}
-	if (m_blittex)
+	if (m_colorrb)
 	{
-		GLuint tex = m_blittex;
-		glDeleteTextures(1, &tex);
-		m_blittex = 0;
+		globj = m_colorrb;
+		glDeleteRenderbuffers(1, &globj);
+		m_colorrb = 0;
 	}
 	if (m_blitfbo)
 	{
-		GLuint fbo = m_blitfbo;
-		glDeleteFramebuffersEXT(1, &fbo);
+		globj = m_blitfbo;
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_blitfbo);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0);
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+		glDeleteFramebuffersEXT(1, &globj);
 		m_blitfbo = 0;
 	}
+	if (m_blitrbo)
+	{
+		globj = m_blitrbo;
+		glDeleteRenderbuffers(1, &globj);
+		m_blitrbo = 0;
+	}
 	m_width = 0;
 	m_height = 0;
 	m_samples = 0;
@@ -135,23 +206,33 @@ void RAS_OpenGLOffScreen::Destroy()
 
 void RAS_OpenGLOffScreen::Bind(RAS_OFS_BIND_MODE mode)
 {
-	if (m_ofs)
+	if (m_fbo)
 	{
 		if (mode == RAS_OFS_BIND_RENDER || !m_blitfbo)
-			GPU_offscreen_bind(m_ofs, false);
+		{
+			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+			glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+			glViewport(0, 0, m_width, m_height);
+			glDisable(GL_SCISSOR_TEST);
+		}
 		else
-			glBindFramebuffer(GL_READ_FRAMEBUFFER, m_blitfbo);
+		{
+			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_blitfbo);
+			glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+		}
 		m_bound = true;
 	}
 }
 
 void RAS_OpenGLOffScreen::Unbind()
 {
-	if (m_ofs && m_bound)
-	{
-		GPU_offscreen_unbind(m_ofs, false);
-		m_bound = false;
-	}
+	if (!m_bound)
+		return;
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+	glEnable(GL_SCISSOR_TEST);
+	glReadBuffer(GL_BACK);
+	m_bound = false;
 }
 
 void RAS_OpenGLOffScreen::Blit()
@@ -159,12 +240,12 @@ void RAS_OpenGLOffScreen::Blit()
 	if (m_bound && m_blitfbo)
 	{
 		// set the draw target to the secondary FBO, the read target is still the multisample FBO
-		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitfbo);
+		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, m_blitfbo);
 
 		// sample the primary
 		glBlitFramebufferEXT(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 
-		// make sur the next glReadPixels will read from the secondary buffer
-		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_blitfbo);
+		// make sure the next glReadPixels will read from the secondary buffer
+		glBindFramebufferEXT(GL_READ_FRAMEBUFFER, m_blitfbo);
 	}
 }
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
index 86c6dce..59bfd1b 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
@@ -32,10 +32,13 @@ class RAS_ICanvas;
 
 class RAS_OpenGLOffScreen : public RAS_IOffScreen
 {
-	GPUOffScreen *m_ofs;
 	RAS_ICanvas *m_canvas;
+	// these are GL objects
+	unsigned int m_depthrb;
+	unsigned int m_colorrb;
+	unsigned int m_fbo;
 	unsigned int m_blitfbo;
-	unsigned int m_blittex;
+	unsigned int m_blitrbo;
 	bool m_bound;
 
 public:




More information about the Bf-blender-cvs mailing list