diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-06-02 22:16:23 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-06-02 22:16:40 +0300 |
commit | 6c6c4da718c19443d2feef6fc8bde83cd37792a4 (patch) | |
tree | 2ba3f7da406cbbbde555024da0b592d0b330b4ba /source/blender/gpu/intern/gpu_texture.c | |
parent | bc6358a580081dfaf5e7711733c9cd9ba7b23eaa (diff) |
GPU: Fix texture being freed in threads without ogl context bound.
This is a dirty fix. A bit more cleaner approach would be to check if a
context is bound and delay the deletion only in this case.
Also we may want to do this orphan deletion at some other places than
wm_window_swap_buffers.
Diffstat (limited to 'source/blender/gpu/intern/gpu_texture.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 14d0b27bc28..d916b75417f 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -32,6 +32,8 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math_base.h" +#include "BLI_listbase.h" +#include "BLI_threads.h" #include "BKE_global.h" @@ -49,6 +51,9 @@ static struct GPUTextureGlobal { GPUTexture *invalid_tex_3D; } GG = {NULL, NULL, NULL}; +static ListBase g_orphaned_tex = {NULL, NULL}; +static ThreadMutex g_orphan_lock; + /* Maximum number of FBOs a texture can be attached to. */ #define GPU_TEX_MAX_FBO_ATTACHED 8 @@ -1083,6 +1088,16 @@ void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); } +static void gpu_texture_delete(GPUTexture *tex) +{ + if (tex->bindcode && !tex->fromblender) + glDeleteTextures(1, &tex->bindcode); + + gpu_texture_memory_footprint_remove(tex); + + MEM_freeN(tex); +} + void GPU_texture_free(GPUTexture *tex) { tex->refcount--; @@ -1097,13 +1112,37 @@ void GPU_texture_free(GPUTexture *tex) } } - if (tex->bindcode && !tex->fromblender) - glDeleteTextures(1, &tex->bindcode); + /* TODO(fclem): Check if the thread has an ogl context. */ + if (BLI_thread_is_main()) { + gpu_texture_delete(tex); + } + else{ + BLI_mutex_lock(&g_orphan_lock); + BLI_addtail(&g_orphaned_tex, BLI_genericNodeN(tex)); + BLI_mutex_unlock(&g_orphan_lock); + } + } +} - gpu_texture_memory_footprint_remove(tex); +void GPU_texture_init_orphans(void) +{ + BLI_mutex_init(&g_orphan_lock); +} - MEM_freeN(tex); +void GPU_texture_delete_orphans(void) +{ + BLI_mutex_lock(&g_orphan_lock); + LinkData *link; + while((link = BLI_pophead(&g_orphaned_tex))) { + gpu_texture_delete((GPUTexture *)link->data); } + BLI_mutex_unlock(&g_orphan_lock); +} + +void GPU_texture_exit_orphans(void) +{ + GPU_texture_delete_orphans(); + BLI_mutex_end(&g_orphan_lock); } void GPU_texture_ref(GPUTexture *tex) |