diff options
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_effect_antialiasing.c | 14 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 67 |
3 files changed, 78 insertions, 5 deletions
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index 5c960acbd78..a7ddd1c547b 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -417,8 +417,10 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) { WORKBENCH_PrivateData *wpd = vedata->stl->wpd; WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_TextureList *txl = vedata->txl; WORKBENCH_PassList *psl = vedata->psl; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); if (wpd->taa_sample_len == 0) { /* AA disabled. */ @@ -438,12 +440,14 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) const bool taa_finished = wpd->taa_sample >= wpd->taa_sample_len; if (wpd->taa_sample == 0) { wpd->valid_history = true; + GPU_texture_copy(txl->history_buffer_tx, dtxl->color); /* In playback mode, we are sure the next redraw will not use the same viewmatrix. * In this case no need to save the depth buffer. */ - eGPUFrameBufferBits bits = GPU_COLOR_BIT | (!wpd->is_playback ? GPU_DEPTH_BIT : 0); - GPU_framebuffer_blit(dfbl->default_fb, 0, fbl->antialiasing_fb, 0, bits); + if (!wpd->is_playback) { + GPU_texture_copy(txl->depth_buffer_tx, dtxl->depth); + } if (workbench_in_front_history_needed(vedata)) { - GPU_framebuffer_blit(dfbl->in_front_fb, 0, fbl->antialiasing_in_front_fb, 0, GPU_DEPTH_BIT); + GPU_texture_copy(txl->depth_buffer_in_front_tx, dtxl->depth_in_front); } } else { @@ -453,9 +457,9 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) DRW_draw_pass(psl->aa_accum_ps); } /* Copy back the saved depth buffer for correct overlays. */ - GPU_framebuffer_blit(fbl->antialiasing_fb, 0, dfbl->default_fb, 0, GPU_DEPTH_BIT); + GPU_texture_copy(dtxl->depth, txl->depth_buffer_tx); if (workbench_in_front_history_needed(vedata)) { - GPU_framebuffer_blit(fbl->antialiasing_in_front_fb, 0, dfbl->in_front_fb, 0, GPU_DEPTH_BIT); + GPU_texture_copy(dtxl->depth_in_front, txl->depth_buffer_in_front_tx); } } 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); |