[Bf-blender-cvs] [f7753bf97fd] blender-v2.83-release: GPU: Add GPU_texture_copy

Clément Foucault noreply at git.blender.org
Wed Apr 22 21:41:56 CEST 2020


Commit: f7753bf97fd38720bf1e91cd8179dd3227a7bb12
Author: Clément Foucault
Date:   Wed Apr 22 21:22:07 2020 +0200
Branches: blender-v2.83-release
https://developer.blender.org/rBf7753bf97fd38720bf1e91cd8179dd3227a7bb12

GPU: Add GPU_texture_copy

This allow to copy entire texture in a faster way than using framebuffer
blitting.

This uses ARB_copy_image extension if available and fallback to
glCopyTexSubImage2D for older gl version.

Both method should be as fast if not faster than the framebuffer blitting.

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

M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_texture.c

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

diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 892452a2738..d6e5866ae28 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -239,6 +239,8 @@ void GPU_texture_bind(GPUTexture *tex, int number);
 void GPU_texture_unbind(GPUTexture *tex);
 int GPU_texture_bound_number(GPUTexture *tex);
 
+void GPU_texture_copy(GPUTexture *dst, GPUTexture *src);
+
 void GPU_texture_generate_mipmap(GPUTexture *tex);
 void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
 void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 6d2d0f09a42..69ede4a9e13 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -88,6 +88,9 @@ struct GPUTexture {
 
   int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
   GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
+  /* Legacy workaround for texture copy. */
+  GLuint copy_fb;
+  GPUContext *copy_fb_ctx;
 };
 
 static uint gpu_get_bytesize(eGPUTextureFormat data_type);
@@ -1719,6 +1722,67 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
   gpu_texture_memory_footprint_add(tex);
 }
 
+/* Copy a texture content to a similar texture. Only Mip 0 is copied. */
+void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
+{
+  BLI_assert(dst->target == src->target);
+  BLI_assert(dst->w == src->w);
+  BLI_assert(dst->h == src->h);
+  BLI_assert(!GPU_texture_cube(src) && !GPU_texture_cube(dst));
+  /* TODO support array / 3D textures. */
+  BLI_assert(dst->d == 0);
+  BLI_assert(dst->format == src->format);
+
+  if (GLEW_ARB_copy_image) {
+    /* Opengl 4.3 */
+    glCopyImageSubData(src->bindcode,
+                       src->target,
+                       0,
+                       0,
+                       0,
+                       0,
+                       dst->bindcode,
+                       dst->target,
+                       0,
+                       0,
+                       0,
+                       0,
+                       src->w,
+                       src->h,
+                       1);
+  }
+  else {
+    /* Fallback for older GL. */
+    GLenum attachment = !GPU_texture_depth(src) ?
+                            GL_COLOR_ATTACHMENT0 :
+                            (GPU_texture_stencil(src) ? GL_DEPTH_STENCIL_ATTACHMENT :
+                                                        GL_DEPTH_ATTACHMENT);
+
+    if (src->copy_fb == 0) {
+      src->copy_fb = GPU_fbo_alloc();
+      src->copy_fb_ctx = GPU_context_active_get();
+
+      glBindFramebuffer(GL_READ_FRAMEBUFFER, src->copy_fb);
+      glFramebufferTexture(GL_READ_FRAMEBUFFER, attachment, src->bindcode, 0);
+
+      BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+    }
+    /* This means that this function can only be used in one context for each texture. */
+    BLI_assert(src->copy_fb_ctx == GPU_context_active_get());
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, src->copy_fb);
+    glReadBuffer(attachment);
+
+    /* WATCH: glCopyTexSubImage2D might clamp the values to the [0,1] range
+     * where glCopyImageSubData would not. */
+    glBindTexture(dst->target, dst->bindcode);
+    glCopyTexSubImage2D(dst->target, 0, 0, 0, 0, 0, src->w, src->h);
+
+    glBindTexture(dst->target, 0);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+  }
+}
+
 void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
 {
   WARN_NOT_BOUND(tex);
@@ -1838,6 +1902,9 @@ void GPU_texture_free(GPUTexture *tex)
     if (tex->bindcode) {
       GPU_tex_free(tex->bindcode);
     }
+    if (tex->copy_fb) {
+      GPU_fbo_free(tex->copy_fb, tex->copy_fb_ctx);
+    }
 
     gpu_texture_memory_footprint_remove(tex);



More information about the Bf-blender-cvs mailing list