Fix #22123 and #22124: some problems with mutex locks, also tweak to

how removing opengl textures from outside main thread is done so it
happens as part of the main loop.
This commit is contained in:
Brecht Van Lommel 2010-04-25 10:49:13 +00:00
parent 6c3317612e
commit 3f12beb4d0
6 changed files with 35 additions and 30 deletions

View File

@ -65,7 +65,8 @@ int BLI_system_thread_count(void); /* gets the number of threads the system can
#define LOCK_PREVIEW 1
#define LOCK_VIEWER 2
#define LOCK_CUSTOM1 3
#define LOCK_RCACHE 2
#define LOCK_RCACHE 4
#define LOCK_OPENGL 5
void BLI_lock_thread(int type);
void BLI_unlock_thread(int type);
@ -73,7 +74,7 @@ void BLI_unlock_thread(int type);
/* Mutex Lock */
typedef pthread_mutex_t ThreadMutex;
#define BLI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER;
#define BLI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
void BLI_mutex_init(ThreadMutex *mutex);
void BLI_mutex_lock(ThreadMutex *mutex);

View File

@ -108,6 +108,7 @@ static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
static int thread_levels= 0; /* threads can be invoked inside threads */
@ -344,6 +345,8 @@ void BLI_lock_thread(int type)
pthread_mutex_lock(&_custom1_lock);
else if (type==LOCK_RCACHE)
pthread_mutex_lock(&_rcache_lock);
else if (type==LOCK_OPENGL)
pthread_mutex_lock(&_opengl_lock);
}
void BLI_unlock_thread(int type)
@ -356,8 +359,8 @@ void BLI_unlock_thread(int type)
pthread_mutex_unlock(&_viewer_lock);
else if(type==LOCK_CUSTOM1)
pthread_mutex_unlock(&_custom1_lock);
else if(type==LOCK_RCACHE)
pthread_mutex_unlock(&_rcache_lock);
else if(type==LOCK_OPENGL)
pthread_mutex_unlock(&_opengl_lock);
}
/* Mutex Locks */

View File

@ -122,6 +122,9 @@ void GPU_free_images(void);
void GPU_free_smoke(struct SmokeModifierData *smd);
void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(void);
#ifdef __cplusplus
}
#endif

View File

@ -784,42 +784,36 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
smd->domain->tex_shadow = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->shadow);
}
ListBase image_free_queue = {NULL, NULL};
static ThreadMutex queuelock = BLI_MUTEX_INITIALIZER;
static ListBase image_free_queue = {NULL, NULL};
static void flush_queued_free(void)
{
Image *ima, *imanext;
BLI_mutex_lock(&queuelock);
ima = image_free_queue.first;
image_free_queue.first = image_free_queue.last = NULL;
for (; ima; ima=imanext) {
imanext = (Image*)ima->id.next;
GPU_free_image(ima);
MEM_freeN(ima);
}
BLI_mutex_unlock(&queuelock);
}
static void queue_image_for_free(Image *ima)
static void gpu_queue_image_for_free(Image *ima)
{
Image *cpy = MEM_dupallocN(ima);
BLI_mutex_lock(&queuelock);
BLI_lock_thread(LOCK_OPENGL);
BLI_addtail(&image_free_queue, cpy);
BLI_mutex_unlock(&queuelock);
BLI_unlock_thread(LOCK_OPENGL);
}
void GPU_free_unused_buffers(void)
{
Image *ima;
BLI_lock_thread(LOCK_OPENGL);
for(ima=image_free_queue.first; ima; ima=ima->id.next)
GPU_free_image(ima);
BLI_freelistN(&image_free_queue);
BLI_unlock_thread(LOCK_OPENGL);
}
void GPU_free_image(Image *ima)
{
if (!BLI_thread_is_main()) {
queue_image_for_free(ima);
if(!BLI_thread_is_main()) {
gpu_queue_image_for_free(ima);
return;
} else if (image_free_queue.first) {
flush_queued_free();
}
/* free regular image binding */

View File

@ -48,6 +48,7 @@
#include "ED_screen.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "WM_api.h"
@ -695,6 +696,8 @@ void wm_draw_update(bContext *C)
wmWindowManager *wm= CTX_wm_manager(C);
wmWindow *win;
int drawmethod;
GPU_free_unused_buffers();
for(win= wm->windows.first; win; win= win->next) {
if(win->drawmethod != U.wmdrawmethod) {

View File

@ -312,6 +312,7 @@ void WM_exit(bContext *C)
}
GPU_buffer_pool_free(0);
GPU_free_unused_buffers();
GPU_extensions_exit();
// if (copybuf) MEM_freeN(copybuf);