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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to