Commit: ed59d03bfcac7e0b21c82febe6b6f2f786b62034
Author: Clément Foucault
Date:   Thu Jun 22 02:01:58 2017 +0200
Branches: blender2.8
https://developer.blender.org/rBed59d03bfcac7e0b21c82febe6b6f2f786b62034

GPUFramebuffer: Add recursive downsampling function.

This special case function enables rendering to a miplevel while using the 
miplevels above as texture input.
This is needed for some algorithm (i.e. creating a min-max depth pyramid 
texture).

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

M       source/blender/draw/intern/DRW_render.h
M       source/blender/draw/intern/draw_manager.c
M       source/blender/gpu/GPU_framebuffer.h
M       source/blender/gpu/intern/gpu_framebuffer.c

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

diff --git a/source/blender/draw/intern/DRW_render.h 
b/source/blender/draw/intern/DRW_render.h
index aa6b836be17..07e9abcbd47 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -202,6 +202,9 @@ void DRW_framebuffer_texture_layer_attach(struct 
GPUFrameBuffer *fb, struct GPUT
 void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct 
GPUTexture *tex, int slot, int face, int mip);
 void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
 void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct 
GPUFrameBuffer *fb_write, bool depth);
+void DRW_framebuffer_recursive_downsample(
+        struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+        void (*callback)(void *userData, int level), void *userData);
 void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *fb_read, int x, int 
y, int w, int h);
 void DRW_framebuffer_free(struct GPUFrameBuffer *fb);
 #define DRW_FRAMEBUFFER_FREE_SAFE(fb) do { \
diff --git a/source/blender/draw/intern/draw_manager.c 
b/source/blender/draw/intern/draw_manager.c
index d01f7f5823e..e390ab33c69 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2137,6 +2137,12 @@ void DRW_framebuffer_blit(struct GPUFrameBuffer 
*fb_read, struct GPUFrameBuffer
        GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
 }
 
+void DRW_framebuffer_recursive_downsample(
+        struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+        void (*callback)(void *userData, int level), void *userData)
+{
+       GPU_framebuffer_recursive_downsample(fb, tex, num_iter, callback, 
userData);
+}
 void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int 
x, int y, int w, int h)
 {
        glViewport(x, y, w, h);
diff --git a/source/blender/gpu/GPU_framebuffer.h 
b/source/blender/gpu/GPU_framebuffer.h
index 6778930f61c..a079d12b469 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -75,6 +75,10 @@ void GPU_framebuffer_blit(
         GPUFrameBuffer *fb_read, int read_slot,
         GPUFrameBuffer *fb_write, int write_slot, bool use_depth);
 
+void GPU_framebuffer_recursive_downsample(
+        GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+        void (*callback)(void *userData, int level), void *userData);
+
 /* GPU OffScreen
  * - wrapper around framebuffer and texture for simple offscreen drawing
  * - changes size if graphics card can't support it */
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c 
b/source/blender/gpu/intern/gpu_framebuffer.c
index d791f839e20..ddf0e83309c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -142,16 +142,7 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, 
GPUTexture *tex, int slo
        else
                attachment = GL_COLOR_ATTACHMENT0 + slot;
 
-#if defined(WITH_GL_PROFILE_COMPAT)
-       /* Workaround for Mac & Mesa compatibility profile, remove after we 
switch to core profile */
-       /* glFramebufferTexture was introduced in 3.2. It is *not* available in 
the ARB FBO extension */
-       if (GLEW_VERSION_3_2)
-               glFramebufferTexture(GL_FRAMEBUFFER, attachment, 
GPU_texture_opengl_bindcode(tex), mip); /* normal core call, same as below */
-       else
-               glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, 
GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), mip);
-#else
        glFramebufferTexture(GL_FRAMEBUFFER, attachment, 
GPU_texture_opengl_bindcode(tex), mip);
-#endif
 
        if (GPU_texture_depth(tex))
                fb->depthtex = tex;
@@ -250,16 +241,7 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
                attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
        }
 
-#if defined(WITH_GL_PROFILE_COMPAT)
-       /* Workaround for Mac & Mesa compatibility profile, remove after we 
switch to core profile */
-       /* glFramebufferTexture was introduced in 3.2. It is *not* available in 
the ARB FBO extension */
-       if (GLEW_VERSION_3_2)
-               glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0); /* 
normal core call, same as below */
-       else
-               glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, 
GPU_texture_target(tex), 0, 0);
-#else
        glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
-#endif
 
        GPU_texture_framebuffer_set(tex, NULL, -1);
 }
@@ -554,6 +536,63 @@ void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int 
read_slot, GPUFrameBuffer
        glDrawBuffer(GL_COLOR_ATTACHMENT0);
 }
 
+/**
+ * Use this if you need to custom downsample your texture and use the previous 
mip level as input.
+ * This function only takes care of the correct texture handling. It execute 
the callback for each texture level.
+ **/
+void GPU_framebuffer_recursive_downsample(
+        GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void 
(*callback)(void *userData, int level), void *userData)
+{
+       int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
+       GLenum attachment;
+
+       /* Manually setup framebuffer to not use GPU_texture_framebuffer_set() 
*/
+       glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+       GG.currentfb = fb->object;
+
+       if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+               attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+       else if (GPU_texture_depth(tex))
+               attachment = GL_DEPTH_ATTACHMENT;
+       else
+               attachment = GL_COLOR_ATTACHMENT0;
+
+       /* last bound prevails here, better allow explicit control here too */
+       glDrawBuffer(GL_COLOR_ATTACHMENT0);
+       glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+       for (int i=1; i < num_iter+1 && (current_dim[0] > 1 && current_dim[1] > 
1); i++) {
+
+               /* calculate next viewport size */
+               current_dim[0] /= 2;
+               current_dim[1] /= 2;
+
+               /* ensure that the viewport size is always at least 1x1 */
+               CLAMP_MIN(current_dim[0], 1);
+               CLAMP_MIN(current_dim[1], 1);
+
+               glViewport(0, 0, current_dim[0], current_dim[1]);
+
+               /* bind next level for rendering but first restrict fetches 
only to previous level */
+               GPU_texture_bind(tex, 0);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, i-1);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1);
+               GPU_texture_unbind(tex);
+
+               glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, 
GL_TEXTURE_2D, GPU_texture_opengl_bindcode(tex), i);
+
+               callback(userData, i);
+       }
+
+       glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+
+       /* reset mipmap level range for the depth image */
+       GPU_texture_bind(tex, 0);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_iter - 1);
+       GPU_texture_unbind(tex);
+}
+
 /* GPUOffScreen */
 
 struct GPUOffScreen {

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

Reply via email to