diff options
author | Edmund Kapusniak <edmundmk> | 2018-06-11 21:50:14 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-06-11 22:10:24 +0300 |
commit | c08716d3eec06eb341b7e59a65875b1bdf70708e (patch) | |
tree | 94d5d5bd66db672c758bd6abc189a0c7603cb373 /source | |
parent | 9520fc0ff72cb510a0991889dcbbd2010c97c16e (diff) |
Fix crash with OpenGL rendering in multiple threads on macOS.
On macOS we must always go through BLI_thread_local_get/set().
Differential Revision: https://developer.blender.org/D3470
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 54 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_init_exit.c | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_private.h | 4 |
3 files changed, 44 insertions, 16 deletions
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index f86da2eb064..6e791f6ac07 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -42,7 +42,9 @@ #include "GPU_shader.h" #include "GPU_texture.h" -static ThreadLocal(GLuint) g_currentfb; +#include "intern/gpu_private.h" + +static ThreadLocal(void*) g_currentfb; typedef enum { GPU_FB_DEPTH_ATTACHMENT = 0, @@ -163,6 +165,26 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256]) } } +void gpu_framebuffer_module_init(void) +{ + BLI_thread_local_create(g_currentfb); +} + +void gpu_framebuffer_module_exit(void) +{ + BLI_thread_local_delete(g_currentfb); +} + +static uint gpu_framebuffer_current_get() +{ + return GET_UINT_FROM_POINTER(BLI_thread_local_get(g_currentfb)); +} + +static void gpu_framebuffer_current_set(uint object) +{ + BLI_thread_local_set(g_currentfb, SET_UINT_IN_POINTER(object)); +} + /* GPUFrameBuffer */ GPUFrameBuffer *GPU_framebuffer_create(void) @@ -188,8 +210,8 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb) /* This restores the framebuffer if it was bound */ glDeleteFramebuffers(1, &fb->object); - if (g_currentfb == fb->object) { - g_currentfb = 0; + if (gpu_framebuffer_current_get() == fb->object) { + gpu_framebuffer_current_set(0); } MEM_freeN(fb); @@ -341,7 +363,7 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; int numslots = 0; - BLI_assert(g_currentfb == fb->object); + BLI_assert(gpu_framebuffer_current_get() == fb->object); /* Update attachments */ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { @@ -385,10 +407,10 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) if (fb->object == 0) gpu_framebuffer_init(fb); - if (g_currentfb != fb->object) + if (gpu_framebuffer_current_get() != fb->object) glBindFramebuffer(GL_FRAMEBUFFER, fb->object); - g_currentfb = fb->object; + gpu_framebuffer_current_set(fb->object); if (fb->dirty_flag != 0) gpu_framebuffer_update_attachments(fb); @@ -409,20 +431,20 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) void GPU_framebuffer_restore(void) { - if (g_currentfb != 0) { + if (gpu_framebuffer_current_get() != 0) { glBindFramebuffer(GL_FRAMEBUFFER, 0); - g_currentfb = 0; + gpu_framebuffer_current_set(0); } } bool GPU_framebuffer_bound(GPUFrameBuffer *fb) { - return (fb->object == g_currentfb) && (fb->object != 0); + return (fb->object == gpu_framebuffer_current_get()) && (fb->object != 0); } unsigned int GPU_framebuffer_current_get(void) { - return g_currentfb; + return gpu_framebuffer_current_get(); } bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) @@ -513,7 +535,7 @@ void GPU_framebuffer_blit( { BLI_assert(blit_buffers != 0); - GLuint prev_fb = g_currentfb; + GLuint prev_fb = gpu_framebuffer_current_get(); /* Framebuffers must be up to date. This simplify this function. */ if (fb_read->dirty_flag != 0 || fb_read->object == 0) { @@ -573,7 +595,7 @@ void GPU_framebuffer_blit( } else { glBindFramebuffer(GL_FRAMEBUFFER, prev_fb); - g_currentfb = prev_fb; + gpu_framebuffer_current_set(prev_fb); } } @@ -586,13 +608,13 @@ void GPU_framebuffer_recursive_downsample( void (*callback)(void *userData, int level), void *userData) { /* Framebuffer must be up to date and bound. This simplify this function. */ - if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) { + if (gpu_framebuffer_current_get() != fb->object || fb->dirty_flag != 0 || fb->object == 0) { GPU_framebuffer_bind(fb); } /* HACK: We make the framebuffer appear not bound in order to * not trigger any error in GPU_texture_bind(). */ - GLuint prev_fb = g_currentfb; - g_currentfb = 0; + GLuint prev_fb = gpu_framebuffer_current_get(); + gpu_framebuffer_current_set(0); int i; int current_dim[2] = {fb->width, fb->height}; @@ -640,7 +662,7 @@ void GPU_framebuffer_recursive_downsample( } } - g_currentfb = prev_fb; + gpu_framebuffer_current_set(prev_fb); } /* GPUOffScreen */ diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 92ad9d81b6c..78d4f491b66 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -60,6 +60,7 @@ void GPU_init(void) GPU_texture_orphans_init(); GPU_material_orphans_init(); gpu_codegen_init(); + gpu_framebuffer_module_init(); if (G.debug & G_DEBUG_GPU) gpu_debug_init(); @@ -89,6 +90,7 @@ void GPU_exit(void) if (G.debug & G_DEBUG_GPU) gpu_debug_exit(); + gpu_framebuffer_module_exit(); gpu_codegen_exit(); gpu_extensions_exit(); /* must come last */ diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index 72627e3563e..996ba9c63a1 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -33,4 +33,8 @@ void gpu_extensions_exit(void); void gpu_debug_init(void); void gpu_debug_exit(void); +/* gpu_framebuffer.c */ +void gpu_framebuffer_module_init(void); +void gpu_framebuffer_module_exit(void); + #endif /* __GPU_PRIVATE_H__ */ |