[Bf-blender-cvs] [309b4ad] decklink: BGE: multisample FBO supported in bge.render.offscreenCreate()
Benoit Bolsee
noreply at git.blender.org
Mon Nov 2 13:19:12 CET 2015
Commit: 309b4ad8407f3c2af3190cf61c36609f690936c6
Author: Benoit Bolsee
Date: Mon Nov 2 13:15:50 2015 +0100
Branches: decklink
https://developer.blender.org/rB309b4ad8407f3c2af3190cf61c36609f690936c6
BGE: multisample FBO supported in bge.render.offscreenCreate()
3rd optional argument to offScreenCreate() to specify the number of
multi-sample. If the GPU does not support MSAA on FBO, this is ignored.
No other change in the API.
===================================================================
M source/blender/gpu/GPU_extensions.h
M source/blender/gpu/intern/gpu_extensions.c
M source/gameengine/Ketsji/KX_PythonInit.cpp
M source/gameengine/Rasterizer/RAS_IOffScreen.h
M source/gameengine/Rasterizer/RAS_IRasterizer.h
M source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
M source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
M source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
M source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
M source/gameengine/VideoTexture/ImageRender.cpp
===================================================================
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 685ae59..1ae6474 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -189,6 +189,7 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+int GPU_offscreen_color_target(const GPUOffScreen *ofs);
/* Builtin/Non-generated shaders */
typedef enum GPUProgramType {
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e1dff03..8567dd2 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -1621,6 +1621,11 @@ int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
return ofs->color->bindcode;
}
+int GPU_offscreen_color_target(const GPUOffScreen *ofs)
+{
+ return ofs->color->target;
+}
+
/* GPUShader */
struct GPUShader {
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index b01073e..6effb71 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -1501,10 +1501,11 @@ static PyGetSetDef RASOffScreen_getseters[] = {
static int PyRASOffScreen__tp_init(PyRASOffScreen *self, PyObject *args, PyObject *kwargs)
{
- int width, height;
- const char *keywords[] = {"width", "height", NULL};
+ int width, height, samples;
+ const char *keywords[] = {"width", "height", "samples", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:RASOffscreen", (char **)keywords, &width, &height)) {
+ samples = 0;
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:RASOffscreen", (char **)keywords, &width, &height, &samples)) {
return -1;
}
@@ -1518,12 +1519,17 @@ static int PyRASOffScreen__tp_init(PyRASOffScreen *self, PyObject *args, PyObjec
return -1;
}
+ if (samples < 0) {
+ PyErr_SetString(PyExc_ValueError, "negative 'samples' given");
+ return -1;
+ }
+
if (!gp_Rasterizer)
{
PyErr_SetString(PyExc_SystemError, "no rasterizer");
return -1;
}
- self->ofs = gp_Rasterizer->CreateOffScreen(width, height);
+ self->ofs = gp_Rasterizer->CreateOffScreen(width, height, samples);
if (!self->ofs) {
PyErr_SetString(PyExc_SystemError, "creation failed");
return -1;
@@ -1586,8 +1592,10 @@ static PyObject *gPyOffScreenCreate(PyObject *UNUSED(self), PyObject *args)
{
int width;
int height;
+ int samples;
- if (!PyArg_ParseTuple(args, "ii:offscreen_create", &width, &height))
+ samples = 0;
+ if (!PyArg_ParseTuple(args, "ii|i:offscreen_create", &width, &height, &samples))
return NULL;
return PyObject_CallObject((PyObject *) &PyRASOffScreen_Type, args);
diff --git a/source/gameengine/Rasterizer/RAS_IOffScreen.h b/source/gameengine/Rasterizer/RAS_IOffScreen.h
index d1caf14..0acf1bb 100644
--- a/source/gameengine/Rasterizer/RAS_IOffScreen.h
+++ b/source/gameengine/Rasterizer/RAS_IOffScreen.h
@@ -48,16 +48,19 @@ class RAS_IOffScreen
public:
int m_width;
int m_height;
+ int m_samples;
virtual ~RAS_IOffScreen() {}
- virtual bool Create(int width, int height) = 0;
+ virtual bool Create(int width, int height, int samples) = 0;
virtual void Destroy() = 0;
virtual void Bind() = 0;
+ virtual void Blit() = 0;
virtual void Unbind() = 0;
virtual int GetWidth() { return m_width; }
virtual int GetHeight() { return m_height; }
+ virtual int GetSamples() { return m_samples; }
};
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index 72242bb..062795c 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -262,7 +262,7 @@ public:
* Create an offscreen render buffer that can be used as target for render.
* For the time being, it is only used in VideoTexture for custom render.
*/
- virtual RAS_IOffScreen *CreateOffScreen(int width, int height) = 0;
+ virtual RAS_IOffScreen *CreateOffScreen(int width, int height, int samples) = 0;
/**
* SwapBuffers swaps the back buffer with the front buffer.
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
index 0585637..bde6764 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
@@ -33,10 +33,11 @@
#include "RAS_ICanvas.h"
RAS_OpenGLOffScreen::RAS_OpenGLOffScreen(RAS_ICanvas *canvas)
- :m_ofs(NULL), m_canvas(canvas), m_bound(false)
+ :m_ofs(NULL), m_canvas(canvas), m_blitfbo(0), m_blittex(0), m_bound(false)
{
m_width = 0;
m_height = 0;
+ m_samples = 0;
}
RAS_OpenGLOffScreen::~RAS_OpenGLOffScreen()
@@ -44,9 +45,10 @@ RAS_OpenGLOffScreen::~RAS_OpenGLOffScreen()
Destroy();
}
-bool RAS_OpenGLOffScreen::Create(int width, int height)
+bool RAS_OpenGLOffScreen::Create(int width, int height, int samples)
{
char err_out[256];
+ GLenum status;
if (m_ofs)
{
@@ -54,7 +56,7 @@ bool RAS_OpenGLOffScreen::Create(int width, int height)
return false;
}
- m_ofs = GPU_offscreen_create(width, height, 0, err_out);
+ m_ofs = GPU_offscreen_create(width, height, samples, err_out);
if (m_ofs == NULL)
{
printf("RAS_OpenGLOffScreen::Create(): failed creating an offscreen buffer (%s)\n", err_out);
@@ -62,7 +64,48 @@ bool RAS_OpenGLOffScreen::Create(int width, int height)
}
m_width = width;
m_height = height;
+
+ if (GPU_offscreen_color_target(m_ofs) == GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ 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);
+ if (!blit_tex) {
+ printf("RAS_OpenGLOffScreen::Create(): failed creating a texture 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);
+
+ /* write into new single-sample buffer */
+ glGenFramebuffersEXT(1, &blit_fbo);
+ if (!blit_fbo) {
+ printf("RAS_OpenGLOffScreen::Create(): failed creating a FBO for multi-sample offscreen buffer\n");
+ 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);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto L_ERROR;
+ }
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ // remember that multisample is enabled
+ m_samples = 1;
+ }
return true;
+
+ L_ERROR:
+ Destroy();
+ return false;
}
void RAS_OpenGLOffScreen::Destroy()
@@ -73,8 +116,21 @@ void RAS_OpenGLOffScreen::Destroy()
GPU_offscreen_free(m_ofs);
m_ofs = NULL;
}
+ if (m_blittex)
+ {
+ GLuint tex = m_blittex;
+ glDeleteTextures(1, &tex);
+ m_blittex = 0;
+ }
+ if (m_blitfbo)
+ {
+ GLuint fbo = m_blitfbo;
+ glDeleteFramebuffersEXT(1, &fbo);
+ m_blitfbo = 0;
+ }
m_width = 0;
m_height = 0;
+ m_samples = 0;
}
void RAS_OpenGLOffScreen::Bind()
@@ -95,3 +151,17 @@ void RAS_OpenGLOffScreen::Unbind()
}
}
+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);
+
+ // 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);
+ }
+}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
index 8494e99..63ac02f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.h
@@ -34,14 +34,17 @@ class RAS_OpenGLOffScreen : public RAS_IOffScreen
{
GPUOffScreen *m_ofs;
RAS_ICanvas *m_canvas;
+ unsigned int m_blitfbo;
+ unsigned int m_blittex;
bool m_bound;
public:
RAS_OpenGLOffScreen(RAS_ICanvas *canvas);
~RAS_OpenGLOffScreen();
- bool Create(int width, int height);
+ bool Create(int width, int height, int samples);
void Destroy();
void Bind();
+ void Blit();
void Unbind();
};
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 6dff495..18913f6 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -609,13 +609,13 @@ float RAS_OpenGLRasterizer::GetFocalLength()
return m_focallength;
}
-RAS_IOffScreen *RAS_OpenGLRasterizer::CreateOffScreen(int width, int height)
+RAS_IOffScreen *RAS_OpenGLRasterizer::CreateOffScreen(int width, int height, int samples)
{
RAS_IOffScreen *ofs;
ofs = new RAS_OpenGLOffScreen(m_2DCanvas);
- if (!ofs->Create(width, height))
+ if (!ofs->Create(width, height, samples))
{
delete ofs;
return NULL;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 55e67a8..44eaeae 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -183,7 +183,7 @@ public:
virtual float GetEyeSeparation();
virtual void SetFocalLength(const float focallength);
virtual float GetFocalLength();
- virtual RAS_IOffScreen *CreateOffScreen(int width, int height);
+ virtual RAS_IOffScreen *Cre
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list