diff options
29 files changed, 594 insertions, 213 deletions
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index 3b5f6a0caf9..ca7f2a4d506 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -688,17 +688,35 @@ static const char *check_memlist(MemHead *memh) uintptr_t MEM_get_memory_in_use(void) { - return mem_in_use; + uintptr_t _mem_in_use; + + mem_lock_thread(); + _mem_in_use= mem_in_use; + mem_unlock_thread(); + + return _mem_in_use; } uintptr_t MEM_get_mapped_memory_in_use(void) { - return mmap_in_use; + uintptr_t _mmap_in_use; + + mem_lock_thread(); + _mmap_in_use= mmap_in_use; + mem_unlock_thread(); + + return _mmap_in_use; } int MEM_get_memory_blocks_in_use(void) { - return totblock; + int _totblock; + + mem_lock_thread(); + _totblock= totblock; + mem_unlock_thread(); + + return _totblock; } /* eof */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 47ab6f324d3..85c3c716b8b 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -107,6 +107,11 @@ struct RenderResult; /* always call to make signals work */ struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); +/* same as above, but can be used to retrieve images being rendered in + * a thread safe way, always call both acquire and release */ +struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); +void BKE_image_release_ibuf(struct Image *ima, void *lock); + /* returns existing Image when filename/type is same (frame optional) */ struct Image *BKE_add_image_file(const char *name, int frame); @@ -135,7 +140,8 @@ void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); /* for multilayer images as well as for render-viewer */ -struct RenderResult *BKE_image_get_renderresult(struct Scene *scene, struct Image *ima); +struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima); +void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima); /* goes over all textures that use images */ void BKE_image_free_all_textures(void); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9953540bbcf..09d150341b2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1564,15 +1564,22 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return rpass; } -RenderResult *BKE_image_get_renderresult(struct Scene *scene, Image *ima) +RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, Image *ima) { if(ima->rr) return ima->rr; - if(ima->type==IMA_TYPE_R_RESULT) - return RE_GetResult(RE_GetRender(scene->id.name)); + else if(ima->type==IMA_TYPE_R_RESULT) + return RE_AcquireResultRead(RE_GetRender(scene->id.name)); return NULL; } +void BKE_image_release_renderresult(struct Scene *scene, Image *ima) +{ + if(ima->rr); + else if(ima->type==IMA_TYPE_R_RESULT) + RE_ReleaseResult(RE_GetRender(scene->id.name)); +} + /* after imbuf load, openexr type can return with a exrhandle open */ /* in that case we have to build a render-result */ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) @@ -1873,16 +1880,25 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* showing RGBA result itself (from compo/sequence) or like exr, using layers etc */ /* always returns a single ibuf, also during render progress */ -static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r) { Render *re= NULL; RenderResult *rr= NULL; + /* if we the caller is not going to release the lock, don't give the image */ + if(!lock_r) + return NULL; + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); - rr= RE_GetResult(re); + rr= RE_AcquireResultRead(re); + + /* release is done in BKE_image_release_ibuf using lock_r */ + *lock_r= re; } - if(rr==NULL) return NULL; + + if(rr==NULL) + return NULL; if(RE_RenderInProgress(re)) { ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); @@ -1893,6 +1909,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } + return ibuf; } else { @@ -1907,7 +1924,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ - RE_GetResultImage(RE_GetRender(iuser->scene->id.name), &rres); + RE_AcquireResultImage(RE_GetRender(iuser->scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; dither= iuser->scene->r.dither_intensity; @@ -1954,10 +1971,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf->zbuf_float= rres.rectz; ibuf->flags |= IB_zbuffloat; ibuf->dither= dither; - + + RE_ReleaseResultImage(re); + ima->ok= IMA_OK_LOADED; return ibuf; } + + RE_ReleaseResultImage(re); } return NULL; @@ -2011,8 +2032,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame } /* Checks optional ImageUser and verifies/creates ImBuf. */ -/* returns ibuf */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* use this one if you want to get a render result in progress, + * if not, use BKE_image_get_ibuf which doesn't require a release */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf= NULL; float color[] = {0, 0, 0, 1}; @@ -2028,6 +2050,9 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. * That means, the last two steps must be, 1) add the ibuf to the list and * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ + + if(lock_r) + *lock_r= NULL; /* quick reject tests */ if(ima==NULL) @@ -2103,8 +2128,9 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) } else if(ima->source == IMA_SRC_VIEWER) { if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely */ - ibuf= image_get_render_result(ima, iuser); + /* always verify entirely, and potentially + returns pointer to release later */ + ibuf= image_get_render_result(ima, iuser, lock_r); } else if(ima->type==IMA_TYPE_COMPOSITE) { /* Composite Viewer, all handled in compositor */ @@ -2126,6 +2152,17 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) return ibuf; } +void BKE_image_release_ibuf(Image *ima, void *lock) +{ + /* for getting image during threaded render, need to release */ + if(lock) + RE_ReleaseResult(lock); +} + +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + return BKE_image_acquire_ibuf(ima, iuser, NULL); +} void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 90ea53d4364..aa12894feb9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1953,6 +1953,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group) if(ns->data) { printf("freed leftover buffer from stack\n"); free_compbuf(ns->data); + ns->data= NULL; } } } diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 7f3e2789232..b80df60e726 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -2067,7 +2067,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int if(rendering) BLI_strncpy(sce->id.name+2, scenename, 64); - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); if(rres.rectf) { se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); @@ -2080,6 +2080,8 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); } + + RE_ReleaseResultImage(re); BIF_end_render_callbacks(); diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 8babb5fe780..ace9ddd729f 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -31,14 +31,15 @@ #ifndef BLI_THREADS_H #define BLI_THREADS_H -/* one custom lock available now. can be extended */ -#define LOCK_IMAGE 0 -#define LOCK_CUSTOM1 1 +#include <pthread.h> /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 8 struct ListBase; + +/* Threading API */ + void BLI_init_threads (struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); int BLI_available_thread_index(struct ListBase *threadbase); @@ -48,18 +49,46 @@ void BLI_remove_thread_index(struct ListBase *threadbase, int index); void BLI_remove_threads(struct ListBase *threadbase); void BLI_end_threads (struct ListBase *threadbase); -void BLI_lock_thread (int type); -void BLI_unlock_thread (int type); +/* System Information */ + +int BLI_system_thread_count(void); /* gets the number of threads the system can make use of */ + +/* Global Mutex Locks + * + * One custom lock available now. can be extended. */ + +#define LOCK_IMAGE 0 +#define LOCK_PREVIEW 1 +#define LOCK_CUSTOM1 2 + +void BLI_lock_thread(int type); +void BLI_unlock_thread(int type); + +/* Mutex Lock */ + +typedef pthread_mutex_t ThreadMutex; + +void BLI_mutex_init(ThreadMutex *mutex); +void BLI_mutex_lock(ThreadMutex *mutex); +void BLI_mutex_unlock(ThreadMutex *mutex); +void BLI_mutex_end(ThreadMutex *mutex); -int BLI_system_thread_count( void ); /* gets the number of threads the system can make use of */ +/* Read/Write Mutex Lock */ - /* exported by preview render, it has to ensure render buffers are not freed while draw */ -void BLI_lock_malloc_thread(void); -void BLI_unlock_malloc_thread(void); +#define THREAD_LOCK_READ 1 +#define THREAD_LOCK_WRITE 2 -/* ThreadedWorker is a simple tool for dispatching work to a limited number of threads in a transparent - * fashion from the caller's perspective - * */ +typedef pthread_rwlock_t ThreadRWMutex; + +void BLI_rw_mutex_init(ThreadRWMutex *mutex); +void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode); +void BLI_rw_mutex_unlock(ThreadRWMutex *mutex); +void BLI_rw_mutex_end(ThreadRWMutex *mutex); + +/* ThreadedWorker + * + * A simple tool for dispatching work to a limited number of threads + * in a transparent fashion from the caller's perspective. */ struct ThreadedWorker; diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index ce9f9adeb90..b5c6a5a3b4e 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -98,6 +98,7 @@ A sample loop can look like this (pseudo c); ************************************************ */ static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER; static int thread_levels= 0; /* threads can be invoked inside threads */ @@ -112,12 +113,12 @@ typedef struct ThreadSlot { int avail; } ThreadSlot; -void BLI_lock_malloc_thread(void) +static void BLI_lock_malloc_thread(void) { pthread_mutex_lock(&_malloc_lock); } -void BLI_unlock_malloc_thread(void) +static void BLI_unlock_malloc_thread(void) { pthread_mutex_unlock(&_malloc_lock); } @@ -143,7 +144,9 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot) tslot->avail= 1; } - MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + if(thread_levels == 0) + MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + thread_levels++; } } @@ -252,21 +255,7 @@ void BLI_end_threads(ListBase *threadbase) } } -void BLI_lock_thread(int type) -{ - if (type==LOCK_IMAGE) - pthread_mutex_lock(&_image_lock); - else if (type==LOCK_CUSTOM1) - pthread_mutex_lock(&_custom1_lock); -} - -void BLI_unlock_thread(int type) -{ - if (type==LOCK_IMAGE) - pthread_mutex_unlock(&_image_lock); - else if(type==LOCK_CUSTOM1) - pthread_mutex_unlock(&_custom1_lock); -} +/* System Information */ /* how many threads are native on this system? */ int BLI_system_thread_count( void ) @@ -300,6 +289,75 @@ int BLI_system_thread_count( void ) return t; } +/* Global Mutex Locks */ + +void BLI_lock_thread(int type) +{ + if (type==LOCK_IMAGE) + pthread_mutex_lock(&_image_lock); + else if (type==LOCK_PREVIEW) + pthread_mutex_lock(&_preview_lock); + else if (type==LOCK_CUSTOM1) + pthread_mutex_lock(&_custom1_lock); +} + +void BLI_unlock_thread(int type) +{ + if (type==LOCK_IMAGE) + pthread_mutex_unlock(&_image_lock); + else if (type==LOCK_PREVIEW) + pthread_mutex_unlock(&_preview_lock); + else if(type==LOCK_CUSTOM1) + pthread_mutex_unlock(&_custom1_lock); +} + +/* Mutex Locks */ + +void BLI_mutex_init(ThreadMutex *mutex) +{ + pthread_mutex_init(mutex, NULL); +} + +void BLI_mutex_lock(ThreadMutex *mutex) +{ + pthread_mutex_lock(mutex); +} + +void BLI_mutex_unlock(ThreadMutex *mutex) +{ + pthread_mutex_unlock(mutex); +} + +void BLI_mutex_end(ThreadMutex *mutex) +{ + pthread_mutex_destroy(mutex); +} + +/* Read/Write Mutex Lock */ + +void BLI_rw_mutex_init(ThreadRWMutex *mutex) +{ + pthread_rwlock_init(mutex, NULL); +} + +void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode) +{ + if(mode == THREAD_LOCK_READ) + pthread_rwlock_rdlock(mutex); + else + pthread_rwlock_wrlock(mutex); +} + +void BLI_rw_mutex_unlock(ThreadRWMutex *mutex) +{ + pthread_rwlock_unlock(mutex); +} + +void BLI_rw_mutex_end(ThreadRWMutex *mutex) +{ + pthread_rwlock_destroy(mutex); +} + /* ************************************************ */ typedef struct ThreadedWorker { diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index a4263f7bd77..41a83a34ee4 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -38,7 +38,10 @@ struct uiBlock; struct Image *ED_space_image(struct SpaceImage *sima); void ED_space_image_set(struct bContext *C, struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima); -struct ImBuf *ED_space_image_buffer(struct SpaceImage *sima); +struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r); +void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock); +int ED_space_image_has_buffer(struct SpaceImage *sima); + void ED_space_image_size(struct SpaceImage *sima, int *width, int *height); void ED_space_image_aspect(struct SpaceImage *sima, float *aspx, float *aspy); void ED_space_image_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 7dc04a47c51..4a671e4d2ba 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -446,6 +446,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre /* uses ROUNDBOX button in block to get the rect */ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect) { + Render *re; RenderResult rres; char name[32]; int gamma_correct=0; @@ -470,7 +471,8 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int } } - RE_GetResultImage(RE_GetRender(name), &rres); + re= RE_GetRender(name); + RE_AcquireResultImage(re, &rres); if(rres.rectf) { @@ -482,10 +484,13 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int glTranslatef(offx, 0, 0); glaDrawPixelsSafe_to32(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, rres.rectf, gamma_correct); glPopMatrix(); + + RE_ReleaseResultImage(re); return 1; } } + RE_ReleaseResultImage(re); return 0; } @@ -1100,13 +1105,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r wmJob *steve; ShaderPreview *sp; - /* XXX ugly global still, but we can't do preview while rendering */ - if(G.rendering) { - printf("abort icon because rendering\n"); - return; - } - - steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner); + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, WM_JOB_EXCL_RENDER); sp= MEM_callocN(sizeof(ShaderPreview), "shader preview"); /* customdata for preview thread */ @@ -1131,13 +1130,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M wmJob *steve; ShaderPreview *sp; - /* XXX ugly global still, but we can't do preview while rendering */ - if(G.rendering) { - printf("abort shader because rendering\n"); - return; - } - - steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner); + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, WM_JOB_EXCL_RENDER); sp= MEM_callocN(sizeof(ShaderPreview), "shader preview"); /* customdata for preview thread */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index ae3f74403f2..7f2084d5a76 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2703,18 +2703,13 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs) } /* called inside thread! */ -static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect) +static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect) { - RenderJob *rj= rjv; - ImBuf *ibuf; float x1, y1, *rectf= NULL; int ymin, ymax, xmin, xmax; int rymin, rxmin; char *rectc; - ibuf= BKE_image_get_ibuf(rj->image, &rj->iuser); - if(ibuf==NULL) return; - /* if renrect argument, we only refresh scanlines */ if(renrect) { /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */ @@ -2814,6 +2809,18 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec *(rj->do_update)= 1; } +static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect) +{ + RenderJob *rj= rjv; + ImBuf *ibuf; + void *lock; + + ibuf= BKE_image_acquire_ibuf(rj->image, &rj->iuser, &lock); + if(ibuf) + image_buffer_rect_update(rj, rr, ibuf, renrect); + BKE_image_release_ibuf(rj->image, lock); +} + static void render_startjob(void *rjv, short *stop, short *do_update) { RenderJob *rj= rjv; @@ -2897,7 +2904,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) rj->iuser.ok= 1; /* setup job */ - steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene); + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY); WM_jobs_customdata(steve, rj, render_freejob); WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0); WM_jobs_callbacks(steve, render_startjob, NULL, NULL); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index fb3da4a5353..81c3f4d6814 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -284,7 +284,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update) static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen= CTX_wm_screen(C); - wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen); + wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen, 0); ScreenshotJob *sj= MEM_callocN(sizeof(ScreenshotJob), "screenshot job"); /* setup sj */ diff --git a/source/blender/editors/space_file/writeimage.c b/source/blender/editors/space_file/writeimage.c index 994f38320f2..045c790b9cd 100644 --- a/source/blender/editors/space_file/writeimage.c +++ b/source/blender/editors/space_file/writeimage.c @@ -115,15 +115,18 @@ static void save_rendered_image_cb_real(char *name, int confirm) if(overwrite) { if(scene->r.imtype==R_MULTILAYER) { - RenderResult *rr= RE_GetResult(RE_GetRender(scene->id.name)); + Render *re= RE_GetRender(scene->id.name); + RenderResult *rr= RE_AcquireResultRead(re); if(rr) RE_WriteRenderResult(rr, str, scene->r.quality); + RE_ReleaseResult(re); } else { + Render *re= RE_GetRender(scene->id.name); RenderResult rres; ImBuf *ibuf; - RE_GetResultImage(RE_GetRender(scene->id.name), &rres); + RE_AcquireResultImage(re, &rres); waitcursor(1); /* from screen.c */ @@ -137,6 +140,8 @@ static void save_rendered_image_cb_real(char *name, int confirm) BKE_write_ibuf(scene, ibuf, str, scene->r.imtype, scene->r.subimtype, scene->r.quality); IMB_freeImBuf(ibuf); /* imbuf knows rects are not part of ibuf */ + + RE_ReleaseResultImage(re); } strcpy(G.ima, name); @@ -231,9 +236,10 @@ void BIF_save_rendered_image(char *name) /* calls fileselect */ void BIF_save_rendered_image_fs(Scene *scene) { + Render *re= RE_GetRender(scene->id.name); RenderResult rres; - RE_GetResultImage(RE_GetRender(scene->id.name), &rres); + RE_AcquireResultImage(re, &rres); if(!rres.rectf && !rres.rect32) { error("No image rendered"); @@ -250,6 +256,8 @@ void BIF_save_rendered_image_fs(Scene *scene) save_image_filesel_str(scene, str); activate_fileselect(FILE_SPECIAL, str, G.ima, save_rendered_image_cb); } + + RE_ReleaseResultImage(re); } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index bdf3e9416b9..67fb95b1f6b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -204,11 +204,7 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) /* this function gets the values for cursor and vertex number buttons */ static void image_transform_but_attr(SpaceImage *sima, int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/ { - ImBuf *ibuf= ED_space_image_buffer(sima); - if(ibuf) { - *imx= ibuf->x; - *imy= ibuf->y; - } + ED_space_image_size(sima, imx, imy); if (sima->flag & SI_COORDFLOATS) { *step= 1; @@ -497,9 +493,8 @@ void brush_buttons(const bContext *C, uiBlock *block, short fromsima, static int image_panel_poll(const bContext *C, PanelType *pt) { SpaceImage *sima= CTX_wm_space_image(C); - ImBuf *ibuf= ED_space_image_buffer(sima); - return (ibuf != NULL); + return ED_space_image_has_buffer(sima); } static void image_panel_curves(const bContext *C, Panel *pa) @@ -509,8 +504,9 @@ static void image_panel_curves(const bContext *C, Panel *pa) ImBuf *ibuf; PointerRNA simaptr; int levels; + void *lock; - ibuf= ED_space_image_buffer(sima); + ibuf= ED_space_image_acquire_buffer(sima, &lock); if(ibuf) { if(sima->cumap==NULL) @@ -522,6 +518,8 @@ static void image_panel_curves(const bContext *C, Panel *pa) RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr); uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels); } + + ED_space_image_release_buffer(sima, lock); } #if 0 @@ -923,6 +921,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propn uiBlock *block; uiBut *but; char str[128]; + void *lock; if(!ptr->data) return; @@ -953,8 +952,9 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propn uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); if(ima->source == IMA_SRC_VIEWER) { - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(ima, ibuf, str); + BKE_image_release_ibuf(ima, lock); uiItemL(layout, ima->id.name+2, 0); uiItemL(layout, str, 0); @@ -981,7 +981,10 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propn } else if(ima->type==IMA_TYPE_R_RESULT) { /* browse layer/passes */ - uiblock_layer_pass_arrow_buttons(layout, RE_GetResult(RE_GetRender(scene->id.name)), iuser); + Render *re= RE_GetRender(scene->id.name); + RenderResult *rr= RE_AcquireResultRead(re); + uiblock_layer_pass_arrow_buttons(layout, rr, iuser); + RE_ReleaseResult(re); } } else { @@ -1010,8 +1013,9 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propn uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser); } else if(ima->source != IMA_SRC_GENERATED) { - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(ima, ibuf, str); + BKE_image_release_ibuf(ima, lock); uiItemL(layout, str, 0); } @@ -1081,10 +1085,12 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser /* render layers and passes */ if(ima && iuser) { - rr= BKE_image_get_renderresult(scene, ima); + rr= BKE_image_acquire_renderresult(scene, ima); if(rr) uiblock_layer_pass_buttons(layout, rr, iuser, 160); + + BKE_image_release_renderresult(scene, ima); } } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index fa736a29ce8..a42fec30c45 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -533,11 +533,14 @@ void draw_image_grease_pencil(bContext *C, short onlyv2d) if (onlyv2d) { /* assume that UI_view2d_ortho(C) has been called... */ SpaceImage *sima= (SpaceImage *)CTX_wm_space_data(C); - ImBuf *ibuf= ED_space_image_buffer(sima); + void *lock; + ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); /* draw grease-pencil ('image' strokes) */ //if (sima->flag & SI_DISPGP) draw_gpencil_2dimage(C, ibuf); + + ED_space_image_release_buffer(sima, lock); } else { /* assume that UI_view2d_restore(C) has been called... */ @@ -654,6 +657,7 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) ImBuf *ibuf; float zoomx, zoomy; int show_viewer, show_render; + void *lock; /* XXX can we do this in refresh? */ #if 0 @@ -675,11 +679,9 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) } #endif - /* put scene context variable in iuser */ - sima->iuser.scene= scene; /* retrieve the image and information about it */ ima= ED_space_image(sima); - ibuf= ED_space_image_buffer(sima); + ibuf= ED_space_image_acquire_buffer(sima, &lock); ED_space_image_zoom(sima, ar, &zoomx, &zoomy); show_viewer= (ima && ima->source == IMA_SRC_VIEWER); @@ -718,5 +720,7 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) } } #endif + + ED_space_image_release_buffer(sima, lock); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 317a058d20e..89427ba8535 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -112,7 +112,7 @@ static int space_image_poll(bContext *C) { SpaceImage *sima= CTX_wm_space_image(C); if(sima && sima->spacetype==SPACE_IMAGE) - if(ED_space_image_buffer(sima)) + if(ED_space_image_has_buffer(sima)) return 1; return 0; } @@ -121,10 +121,15 @@ static int space_image_file_exists_poll(bContext *C) { if(space_image_poll(C)) { SpaceImage *sima= CTX_wm_space_image(C); - ImBuf *ibuf= ED_space_image_buffer(sima); + ImBuf *ibuf; + void *lock; + int poll; - if(ibuf && BLI_exists(ibuf->name) && BLI_is_writable(ibuf->name)) - return 1; + ibuf= ED_space_image_acquire_buffer(sima, &lock); + poll= (ibuf && BLI_exists(ibuf->name) && BLI_is_writable(ibuf->name)); + ED_space_image_release_buffer(sima, lock); + + return poll; } return 0; } @@ -388,7 +393,6 @@ static int view_all_exec(bContext *C, wmOperator *op) ARegion *ar; Scene *scene; Object *obedit; - ImBuf *ibuf; float aspx, aspy, zoomx, zoomy, w, h; int width, height; @@ -398,7 +402,6 @@ static int view_all_exec(bContext *C, wmOperator *op) scene= (Scene*)CTX_data_scene(C); obedit= CTX_data_edit_object(C); - ibuf= ED_space_image_buffer(sima); ED_space_image_size(sima, &width, &height); ED_space_image_aspect(sima, &aspx, &aspy); @@ -445,7 +448,6 @@ static int view_selected_exec(bContext *C, wmOperator *op) Scene *scene; Object *obedit; Image *ima; - ImBuf *ibuf; float size, min[2], max[2], d[2]; int width, height; @@ -456,7 +458,6 @@ static int view_selected_exec(bContext *C, wmOperator *op) obedit= CTX_data_edit_object(C); ima= ED_space_image(sima); - ibuf= ED_space_image_buffer(sima); ED_space_image_size(sima, &width, &height); /* get bounds */ @@ -730,7 +731,8 @@ void IMAGE_OT_replace(wmOperatorType *ot) static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOperator *op, char *name) { Image *ima= ED_space_image(sima); - ImBuf *ibuf= ED_space_image_buffer(sima); + void *lock; + ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); int len; if (ibuf) { @@ -751,7 +753,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOpera WM_cursor_wait(1); if(sima->imtypenr==R_MULTILAYER) { - RenderResult *rr= BKE_image_get_renderresult(scene, ima); + RenderResult *rr= BKE_image_acquire_renderresult(scene, ima); if(rr) { RE_WriteRenderResult(rr, name, scene->r.quality); @@ -765,6 +767,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOpera } else BKE_report(op->reports, RPT_ERROR, "Did not write, no Multilayer Image"); + BKE_image_release_renderresult(scene, ima); } else if (BKE_write_ibuf(scene, ibuf, name, sima->imtypenr, scene->r.subimtype, scene->r.quality)) { BLI_strncpy(ima->name, name, sizeof(ima->name)); @@ -792,6 +795,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, Scene *scene, wmOpera WM_cursor_wait(0); } + + ED_space_image_release_buffer(sima, lock); } static int save_as_exec(bContext *C, wmOperator *op) @@ -816,8 +821,9 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceImage *sima= CTX_wm_space_image(C); Image *ima = ED_space_image(sima); - ImBuf *ibuf= ED_space_image_buffer(sima); Scene *scene= CTX_data_scene(C); + ImBuf *ibuf; + void *lock; if(RNA_property_is_set(op->ptr, "path")) return save_as_exec(C, op); @@ -826,6 +832,8 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_CANCELLED; /* always opens fileselect */ + ibuf= ED_space_image_acquire_buffer(sima, &lock); + if(ibuf) { /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */ if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER)) @@ -842,10 +850,14 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event) // XXX note: we can give default menu enums to operator for this image_filesel(C, op, ibuf->name); + + ED_space_image_release_buffer(sima, lock); return OPERATOR_RUNNING_MODAL; } + ED_space_image_release_buffer(sima, lock); + return OPERATOR_CANCELLED; } @@ -874,12 +886,16 @@ static int save_exec(bContext *C, wmOperator *op) { SpaceImage *sima= CTX_wm_space_image(C); Image *ima = ED_space_image(sima); - ImBuf *ibuf= ED_space_image_buffer(sima); + void *lock; + ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); Scene *scene= CTX_data_scene(C); + RenderResult *rr; char name[FILE_MAX]; - if(!ima || !ibuf) + if(!ima || !ibuf) { + ED_space_image_release_buffer(sima, lock); return OPERATOR_CANCELLED; + } /* if exists, saves over without fileselect */ @@ -888,14 +904,21 @@ static int save_exec(bContext *C, wmOperator *op) BLI_strncpy(name, G.ima, FILE_MAX); if(BLI_exists(name) && BLI_is_writable(name)) { - if(BKE_image_get_renderresult(scene, ima)) + rr= BKE_image_acquire_renderresult(scene, ima); + + if(rr) sima->imtypenr= R_MULTILAYER; else sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype); + + BKE_image_release_renderresult(scene, ima); + ED_space_image_release_buffer(sima, lock); save_image_doit(C, sima, scene, op, name); } else { + ED_space_image_release_buffer(sima, lock); + BKE_report(op->reports, RPT_ERROR, "Can not save image."); return OPERATOR_CANCELLED; } @@ -1110,9 +1133,8 @@ static int pack_test(bContext *C, wmOperator *op) static int pack_exec(bContext *C, wmOperator *op) { - SpaceImage *sima= CTX_wm_space_image(C); - Image *ima= ED_space_image(sima); - ImBuf *ibuf= ED_space_image_buffer(sima); + Image *ima= CTX_data_edit_image(C); + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); int as_png= RNA_boolean_get(op->ptr, "as_png"); if(!pack_test(C, op)) @@ -1133,8 +1155,8 @@ static int pack_exec(bContext *C, wmOperator *op) static int pack_invoke(bContext *C, wmOperator *op, wmEvent *event) { - SpaceImage *sima= CTX_wm_space_image(C); - ImBuf *ibuf= ED_space_image_buffer(sima); + Image *ima= CTX_data_edit_image(C); + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); uiPopupMenu *pup; uiLayout *layout; int as_png= RNA_boolean_get(op->ptr, "as_png"); @@ -1294,6 +1316,7 @@ typedef struct ImageSampleInfo { ARegionType *art; void *draw_handle; int x, y; + int channels; char col[4]; float colf[4]; @@ -1310,14 +1333,9 @@ typedef struct ImageSampleInfo { static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) { - SpaceImage *sima= CTX_wm_space_image(C); - ImBuf *ibuf= ED_space_image_buffer(sima); ImageSampleInfo *info= arg_info; - if(ibuf == NULL) - return; - - draw_image_info(ar, ibuf->channels, info->x, info->y, info->colp, + draw_image_info(ar, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); } @@ -1325,13 +1343,16 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) { SpaceImage *sima= CTX_wm_space_image(C); ARegion *ar= CTX_wm_region(C); - ImBuf *ibuf= ED_space_image_buffer(sima); + void *lock; + ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); ImageSampleInfo *info= op->customdata; float fx, fy; int x, y; - if(ibuf == NULL) + if(ibuf == NULL) { + ED_space_image_release_buffer(sima, lock); return; + } x= event->x - ar->winrct.xmin; y= event->y - ar->winrct.ymin; @@ -1348,6 +1369,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->x= x; info->y= y; info->draw= 1; + info->channels= ibuf->channels; info->colp= NULL; info->colfp= NULL; @@ -1424,6 +1446,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) else info->draw= 0; + ED_space_image_release_buffer(sima, lock); ED_area_tag_redraw(CTX_wm_area(C)); } @@ -1440,10 +1463,9 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceImage *sima= CTX_wm_space_image(C); ARegion *ar= CTX_wm_region(C); - ImBuf *ibuf= ED_space_image_buffer(sima); ImageSampleInfo *info; - if(ibuf == NULL) + if(!ED_space_image_has_buffer(sima)) return OPERATOR_CANCELLED; info= MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 55b910cf6b4..4cf59c9a28e 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -328,7 +328,7 @@ static int image_context(const bContext *C, const char *member, bContextDataResu /************************** main region ***************************/ /* sets up the fields of the View2D from zoom and offset */ -static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *scene) +static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar) { Image *ima= ED_space_image(sima); float x1, y1, w, h; @@ -336,24 +336,9 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *sce #if 0 if(image_preview_active(curarea, &width, &height)); -#endif - if(sima->image) { - ImBuf *ibuf= ED_space_image_buffer(sima); - - if(ibuf) { - width= ibuf->x; - height= ibuf->y; - } - else if(sima->image->type==IMA_TYPE_R_RESULT) { - /* not very important, just nice */ - width= (scene->r.xsch*scene->r.size)/100; - height= (scene->r.ysch*scene->r.size)/100; - } - else - ED_space_image_size(sima, &width, &height); - } else - ED_space_image_size(sima, &width, &height); +#endif + ED_space_image_size(sima, &width, &height); w= width; h= height; @@ -431,9 +416,12 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) UI_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); - + + /* put scene context variable in iuser */ + sima->iuser.scene= scene; + /* we set view2d from own zoom and offset each time */ - image_main_area_set_view2d(sima, ar, scene); + image_main_area_set_view2d(sima, ar); /* we draw image in pixelspace */ draw_image_main(sima, ar, scene); @@ -621,7 +609,7 @@ void ED_space_image_set(bContext *C, SpaceImage *sima, Scene *scene, Object *obe } } -ImBuf *ED_space_image_buffer(SpaceImage *sima) +ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) { ImBuf *ibuf; @@ -631,7 +619,7 @@ ImBuf *ED_space_image_buffer(SpaceImage *sima) return BIF_render_spare_imbuf(); else #endif - ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + ibuf= BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r); if(ibuf && (ibuf->rect || ibuf->rect_float)) return ibuf; @@ -640,11 +628,32 @@ ImBuf *ED_space_image_buffer(SpaceImage *sima) return NULL; } -void ED_image_size(Image *ima, int *width, int *height) +void ED_space_image_release_buffer(SpaceImage *sima, void *lock) +{ + if(sima && sima->image) + BKE_image_release_ibuf(sima->image, lock); +} + +int ED_space_image_has_buffer(SpaceImage *sima) { ImBuf *ibuf; + void *lock; + int has_buffer; - ibuf= (ima)? BKE_image_get_ibuf(ima, NULL): NULL; + ibuf= ED_space_image_acquire_buffer(sima, &lock); + has_buffer= (ibuf != NULL); + ED_space_image_release_buffer(sima, lock); + + return has_buffer; +} + +void ED_image_size(Image *ima, int *width, int *height) +{ + ImBuf *ibuf= NULL; + void *lock; + + if(ima) + ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock); if(ibuf && ibuf->x > 0 && ibuf->y > 0) { *width= ibuf->x; @@ -654,24 +663,36 @@ void ED_image_size(Image *ima, int *width, int *height) *width= 256; *height= 256; } + + if(ima) + BKE_image_release_ibuf(ima, lock); } void ED_space_image_size(SpaceImage *sima, int *width, int *height) { + Scene *scene= sima->iuser.scene; ImBuf *ibuf; + void *lock; - ibuf= ED_space_image_buffer(sima); + ibuf= ED_space_image_acquire_buffer(sima, &lock); if(ibuf && ibuf->x > 0 && ibuf->y > 0) { *width= ibuf->x; *height= ibuf->y; } + else if(sima->image && sima->image->type==IMA_TYPE_R_RESULT && scene) { + /* not very important, just nice */ + *width= (scene->r.xsch*scene->r.size)/100; + *height= (scene->r.ysch*scene->r.size)/100; + } /* I know a bit weak... but preview uses not actual image size */ // XXX else if(image_preview_active(sima, width, height)); else { *width= 256; *height= 256; } + + ED_space_image_release_buffer(sima, lock); } void ED_image_aspect(Image *ima, float *aspx, float *aspy) diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index c7e458b9e87..3fc91fea914 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -48,8 +48,9 @@ #include "DNA_text_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_threads.h" #include "MEM_guardedalloc.h" #include "BKE_context.h" @@ -187,6 +188,8 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) /* preview rect? */ if(node->flag & NODE_PREVIEW) { /* only recalculate size when there's a preview actually, otherwise we use stored result */ + BLI_lock_thread(LOCK_PREVIEW); + if(node->preview && node->preview->rect) { float aspect= 1.0f; @@ -222,6 +225,8 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) node->prvr.ymin= dy - oldh; dy= node->prvr.ymin - NODE_DYS/2; } + + BLI_unlock_thread(LOCK_PREVIEW); } /* XXX ugly hack, typeinfo for group is generated */ @@ -836,9 +841,12 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN } /* preview */ - if(node->flag & NODE_PREVIEW) + if(node->flag & NODE_PREVIEW) { + BLI_lock_thread(LOCK_PREVIEW); if(node->preview && node->preview->rect) node_draw_preview(node->preview, &node->prvr); + BLI_unlock_thread(LOCK_PREVIEW); + } uiEndBlock(C, node->block); uiDrawBlock(C, node->block); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 5a89851d65b..50a99650ec0 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -152,7 +152,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update) { CompoJob *cj= cjv; bNodeTree *ntree= cj->localtree; - + if(cj->scene->use_nodes==0) return; @@ -176,8 +176,11 @@ static void compo_startjob(void *cjv, short *stop, short *do_update) void snode_composite_job(const bContext *C, ScrArea *sa) { SpaceNode *snode= sa->spacedata.first; - wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa); - CompoJob *cj= MEM_callocN(sizeof(CompoJob), "compo job"); + wmJob *steve; + CompoJob *cj; + + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, WM_JOB_EXCL_RENDER); + cj= MEM_callocN(sizeof(CompoJob), "compo job"); /* customdata for preview thread */ cj->scene= CTX_data_scene(C); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 4c2689d4f64..521756b8539 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -84,8 +84,9 @@ static void rna_Image_fields_update(bContext *C, PointerRNA *ptr) { Image *ima= ptr->id.data; ImBuf *ibuf; + void *lock; - ibuf= BKE_image_get_ibuf(ima, NULL); + ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock); if(ibuf) { short nr= 0; @@ -96,6 +97,8 @@ static void rna_Image_fields_update(bContext *C, PointerRNA *ptr) if(nr) BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); } + + BKE_image_release_ibuf(ima, lock); } static void rna_Image_reload_update(bContext *C, PointerRNA *ptr) @@ -157,14 +160,22 @@ static int rna_Image_has_data_get(PointerRNA *ptr) static int rna_Image_depth_get(PointerRNA *ptr) { Image *im= (Image*)ptr->data; - ImBuf *ibuf= BKE_image_get_ibuf(im, NULL); + ImBuf *ibuf; + void *lock; + int depth; + + ibuf= BKE_image_acquire_ibuf(im, NULL, &lock); - if (!ibuf) return 0; + if(!ibuf) + depth= 0; + else if(ibuf->rect_float) + depth= 128; + else + depth= ibuf->depth; - if (ibuf->rect_float) - return 128; + BKE_image_release_ibuf(im, lock); - return ibuf->depth; + return depth; } #else diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index df956670eb3..422283c940f 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -191,7 +191,8 @@ static EnumPropertyItem dc_z_items[] = {DC_RGB, DC_Z, DC_LCMS, DC_ZERO}; static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *C, PointerRNA *ptr, int *free) { SpaceImage *sima= (SpaceImage*)ptr->data; - ImBuf *ibuf= ED_space_image_buffer(sima); + ImBuf *ibuf; + void *lock; int zbuf, alpha; if(C==NULL) { @@ -199,9 +200,13 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *C, P return dc_all_items; } + ibuf= ED_space_image_acquire_buffer(sima, &lock); + alpha= ibuf && (ibuf->channels == 4); zbuf= ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels==1)); + ED_space_image_release_buffer(sima, lock); + if(alpha && zbuf) return dc_all_items; else if(alpha) @@ -215,8 +220,13 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *C, P static void rna_SpaceImageEditor_curves_update(bContext *C, PointerRNA *ptr) { SpaceImage *sima= (SpaceImage*)ptr->data; + ImBuf *ibuf; + void *lock; + + ibuf= ED_space_image_acquire_buffer(sima, &lock); + curvemapping_do_ibuf(sima->cumap, ibuf); + ED_space_image_release_buffer(sima, lock); - curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima)); WM_event_add_notifier(C, NC_IMAGE, sima->image); } diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_composite.c b/source/blender/nodes/intern/CMP_nodes/CMP_composite.c index ee9545c3196..800cccc2bfc 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_composite.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_composite.c @@ -50,7 +50,8 @@ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **i RenderData *rd= data; if(scene && (rd->scemode & R_DOCOMP)) { - RenderResult *rr= RE_GetResult(RE_GetRender(scene->id.name)); + Render *re= RE_GetRender(scene->id.name); + RenderResult *rr= RE_AcquireResultWrite(re); if(rr) { CompBuf *outbuf, *zbuf=NULL; @@ -78,11 +79,15 @@ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **i rr->rectf= outbuf->rect; outbuf->malloc= 0; free_compbuf(outbuf); + + RE_ReleaseResult(re); /* signal for imageviewer to refresh (it converts to byte rects...) */ BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); return; } + else + RE_ReleaseResult(re); } } if(in[0]->data) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_image.c b/source/blender/nodes/intern/CMP_nodes/CMP_image.c index 5f444357776..00be52a81aa 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_image.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_image.c @@ -350,11 +350,12 @@ void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { Scene *sce= (Scene *)node->id; + Render *re= (sce)? RE_GetRender(sce->id.name): NULL; RenderData *rd= data; RenderResult *rr= NULL; - if(sce) - rr= RE_GetResult(RE_GetRender(sce->id.name)); + if(re) + rr= RE_AcquireResultRead(re); if(rr) { SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); @@ -389,7 +390,10 @@ static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, } } } - } + } + + if(re) + RE_ReleaseResult(re); }; diff --git a/source/blender/nodes/intern/CMP_util.c b/source/blender/nodes/intern/CMP_util.c index b396d5549d7..075eefb4368 100644 --- a/source/blender/nodes/intern/CMP_util.c +++ b/source/blender/nodes/intern/CMP_util.c @@ -614,7 +614,9 @@ void generate_preview(bNode *node, CompBuf *stackbuf) if(stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return; stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA); - + + BLI_lock_thread(LOCK_PREVIEW); + if(stackbuf->x > stackbuf->y) { preview->xsize= 140; preview->ysize= (140*stackbuf->y)/stackbuf->x; @@ -628,14 +630,15 @@ void generate_preview(bNode *node, CompBuf *stackbuf) cbuf= generate_procedural_preview(stackbuf_use, preview->xsize, preview->ysize); else cbuf= scalefast_compbuf(stackbuf_use, preview->xsize, preview->ysize); - + /* this ensures free-compbuf does the right stuff */ SWAP(float *, cbuf->rect, node->preview->rect); + + BLI_unlock_thread(LOCK_PREVIEW); free_compbuf(cbuf); if(stackbuf_use!=stackbuf) free_compbuf(stackbuf_use); - } } diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index bf02af6ac36..56a81ac6b43 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -157,8 +157,11 @@ void RE_FreeAllRender (void); /* get results and statistics */ void RE_FreeRenderResult(struct RenderResult *rr); -struct RenderResult *RE_GetResult(struct Render *re); -void RE_GetResultImage(struct Render *re, struct RenderResult *rr); +struct RenderResult *RE_AcquireResultRead(struct Render *re); +struct RenderResult *RE_AcquireResultWrite(struct Render *re); +void RE_ReleaseResult(struct Render *re); +void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr); +void RE_ReleaseResultImage(struct Render *re); struct RenderStats *RE_GetStats(struct Render *re); void RE_ResultGet32(struct Render *re, unsigned int *rect); struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index e50e498228d..96306be31c8 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -121,6 +121,10 @@ struct Render RenderResult *pushedresult; /* a list of RenderResults, for fullsample */ ListBase fullresult; + /* read/write mutex, all internal code that writes to re->result must use a + write lock, all external code must use a read lock. internal code is assumed + to not conflict with writes, so no lock used for that */ + ThreadRWMutex resultmutex; /* window size, display rect, viewplane */ int winx, winy; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 68b6f9e524c..077f826b1ef 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -213,11 +213,15 @@ static void free_render_result(ListBase *lb, RenderResult *rr) /* all layers except the active one get temporally pushed away */ static void push_render_result(Render *re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* officially pushed result should be NULL... error can happen with do_seq */ RE_FreeRenderResult(re->pushedresult); re->pushedresult= re->result; re->result= NULL; + + BLI_rw_mutex_unlock(&re->resultmutex); } /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */ @@ -229,6 +233,8 @@ static void pop_render_result(Render *re) return; } if(re->pushedresult) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) { /* find which layer in pushedresult should be replaced */ SceneRenderLayer *srl; @@ -255,6 +261,8 @@ static void pop_render_result(Render *re) RE_FreeRenderResult(re->pushedresult); re->pushedresult= NULL; + + BLI_rw_mutex_unlock(&re->resultmutex); } } @@ -920,6 +928,8 @@ static void read_render_result(Render *re, int sample) { char str[FILE_MAX]; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); @@ -928,6 +938,8 @@ static void read_render_result(Render *re, int sample) if(!read_render_result_from_file(str, re->result)) printf("cannot read: %s\n", str); + + BLI_rw_mutex_unlock(&re->resultmutex); } /* *************************************************** */ @@ -946,13 +958,32 @@ Render *RE_GetRender(const char *name) } /* if you want to know exactly what has been done */ -RenderResult *RE_GetResult(Render *re) +RenderResult *RE_AcquireResultRead(Render *re) { - if(re) + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); return re->result; + } + return NULL; } +RenderResult *RE_AcquireResultWrite(Render *re) +{ + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + return re->result; + } + + return NULL; +} + +void RE_ReleaseResult(Render *re) +{ + if(re) + BLI_rw_mutex_unlock(&re->resultmutex); +} + /* displist.c util.... */ Scene *RE_GetScene(Render *re) { @@ -973,38 +1004,49 @@ RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) /* fill provided result struct with what's currently active or done */ -void RE_GetResultImage(Render *re, RenderResult *rr) +void RE_AcquireResultImage(Render *re, RenderResult *rr) { memset(rr, 0, sizeof(RenderResult)); - if(re && re->result) { - RenderLayer *rl; - - rr->rectx= re->result->rectx; - rr->recty= re->result->recty; - - rr->rectf= re->result->rectf; - rr->rectz= re->result->rectz; - rr->rect32= re->result->rect32; - - /* active layer */ - rl= render_get_active_layer(re, re->result); + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); - if(rl) { - if(rr->rectf==NULL) - rr->rectf= rl->rectf; - if(rr->rectz==NULL) - rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); + if(re->result) { + RenderLayer *rl; + + rr->rectx= re->result->rectx; + rr->recty= re->result->recty; + + rr->rectf= re->result->rectf; + rr->rectz= re->result->rectz; + rr->rect32= re->result->rect32; + + /* active layer */ + rl= render_get_active_layer(re, re->result); + + if(rl) { + if(rr->rectf==NULL) + rr->rectf= rl->rectf; + if(rr->rectz==NULL) + rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); + } } } } +void RE_ReleaseResultImage(Render *re) +{ + if(re) + BLI_rw_mutex_unlock(&re->resultmutex); +} + /* caller is responsible for allocating rect in correct size! */ void RE_ResultGet32(Render *re, unsigned int *rect) { RenderResult rres; - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); + if(rres.rect32) memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty); else if(rres.rectf) { @@ -1022,6 +1064,8 @@ void RE_ResultGet32(Render *re, unsigned int *rect) else /* else fill with black */ memset(rect, 0, sizeof(int)*re->rectx*re->recty); + + RE_ReleaseResultImage(re); } @@ -1042,12 +1086,15 @@ Render *RE_NewRender(const char *name) re= MEM_callocN(sizeof(Render), "new render"); BLI_addtail(&RenderList, re); strncpy(re->name, name, RE_MAXNAME); + BLI_rw_mutex_init(&re->resultmutex); } /* prevent UI to draw old results */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); RE_FreeRenderResult(re->result); re->result= NULL; re->result_ok= 0; + BLI_rw_mutex_unlock(&re->resultmutex); /* set default empty callbacks */ re->display_init= result_nothing; @@ -1072,6 +1119,7 @@ Render *RE_NewRender(const char *name) /* only call this while you know it will remove the link too */ void RE_FreeRender(Render *re) { + BLI_rw_mutex_end(&re->resultmutex); free_renderdata_tables(re); free_sample_tables(re); @@ -1153,6 +1201,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy make_sample_tables(re); /* if preview render, we try to keep old result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->r.scemode & R_PREVIEWBUTS) { if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty); else { @@ -1168,6 +1218,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy re->result->rectx= re->rectx; re->result->recty= re->recty; } + + BLI_rw_mutex_unlock(&re->resultmutex); /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); @@ -1184,8 +1236,12 @@ void RE_SetDispRect (struct Render *re, rcti *disprect) re->recty= disprect->ymax-disprect->ymin; /* initialize render result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); + + BLI_rw_mutex_unlock(&re->resultmutex); } void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) @@ -1345,11 +1401,15 @@ static void render_tile_processor(Render *re, int firsttile) if(re->test_break(re->tbh)) return; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* hrmf... exception, this is used for preview render, re-entrant, so render result has to be re-used */ if(re->result==NULL || re->result->layers.first==NULL) { if(re->result) RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); } + + BLI_rw_mutex_unlock(&re->resultmutex); re->stats_draw(re->sdh, &re->i); @@ -1357,7 +1417,7 @@ static void render_tile_processor(Render *re, int firsttile) return; initparts(re); - + /* assuming no new data gets added to dbase... */ R= *re; @@ -1384,7 +1444,7 @@ static void render_tile_processor(Render *re, int firsttile) break; } } - + freeparts(re); } @@ -1522,6 +1582,8 @@ static void threaded_tile_processor(Render *re) rctf viewplane= re->viewplane; int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); @@ -1533,6 +1595,8 @@ static void threaded_tile_processor(Render *re) else re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); } + + BLI_rw_mutex_unlock(&re->resultmutex); if(re->result==NULL) return; @@ -1540,7 +1604,7 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ initparts(re); - + if(re->result->exrhandle) { RenderResult *rr; char str[FILE_MAX]; @@ -1629,6 +1693,8 @@ static void threaded_tile_processor(Render *re) } + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->result->exrhandle) { RenderResult *rr; @@ -1644,6 +1710,8 @@ static void threaded_tile_processor(Render *re) read_render_result(re, 0); } + + BLI_rw_mutex_unlock(&re->resultmutex); /* unset threadsafety */ g_break= 0; @@ -1823,8 +1891,10 @@ static void do_render_blur_3d(Render *re) } /* swap results */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); RE_FreeRenderResult(re->result); re->result= rres; + BLI_rw_mutex_unlock(&re->resultmutex); set_mblur_offs(0.0f); re->i.curblur= 0; /* stats */ @@ -1894,8 +1964,11 @@ static void do_render_fields_3d(Render *re) do_render_blur_3d(re); else do_render_3d(re); + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); rr1= re->result; re->result= NULL; + BLI_rw_mutex_unlock(&re->resultmutex); /* second field */ if(!re->test_break(re->tbh)) { @@ -1921,8 +1994,11 @@ static void do_render_fields_3d(Render *re) re->recty *= 2; re->disprect.ymin *= 2; re->disprect.ymax *= 2; + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); - + RE_FreeRenderResult(rr1); + if(rr2) { if(re->r.mode & R_ODDFIELD) merge_renderresult_fields(re->result, rr2, rr1); @@ -1931,12 +2007,14 @@ static void do_render_fields_3d(Render *re) RE_FreeRenderResult(rr2); } - RE_FreeRenderResult(rr1); re->i.curfield= 0; /* stats */ /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay= render_get_active_layer(re, re->result); + + BLI_rw_mutex_unlock(&re->resultmutex); + re->display_draw(re->ddh, re->result, NULL); } @@ -2000,6 +2078,8 @@ static void do_render_fields_blur_3d(Render *re) if((re->r.mode & R_CROP)==0) { RenderResult *rres; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* sub-rect for merge call later on */ re->result->tilerect= re->disprect; @@ -2020,6 +2100,8 @@ static void do_render_fields_blur_3d(Render *re) /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay= render_get_active_layer(re, re->result); + BLI_rw_mutex_unlock(&re->resultmutex); + re->display_init(re->dih, re->result); re->display_draw(re->ddh, re->result, NULL); } @@ -2176,7 +2258,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } /* ensure we get either composited result or the active layer */ - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); /* accumulate with filter, and clip */ mask= (1<<sample); @@ -2195,6 +2277,8 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } } + RE_ReleaseResultImage(re); + /* show stuff */ if(sample!=re->osa-1) { /* weak... the display callback wants an active renderlayer pointer... */ @@ -2206,9 +2290,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) break; } + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result->rectf) MEM_freeN(re->result->rectf); re->result->rectf= rectf; + BLI_rw_mutex_unlock(&re->resultmutex); } void RE_MergeFullSample(Render *re, Scene *sce, bNodeTree *ntree) @@ -2309,9 +2395,12 @@ static void do_render_composite_fields_blur_3d(Render *re) static void renderresult_stampinfo(Scene *scene) { RenderResult rres; + Render *re= RE_GetRender(scene->id.name); + /* this is the basic trick to get the displayed float or char rect from render result */ - RE_GetResultImage(RE_GetRender(scene->id.name), &rres); + RE_AcquireResultImage(re, &rres); BKE_stamp_buf(scene, (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); + RE_ReleaseResultImage(re); } static void do_render_seq(Render * re) @@ -2327,6 +2416,8 @@ static void do_render_seq(Render * re) recurs_depth--; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(ibuf) { if(ibuf->rect_float) { if (!rr->rectf) @@ -2369,6 +2460,8 @@ static void do_render_seq(Render * re) else rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); } + + BLI_rw_mutex_unlock(&re->resultmutex); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -2388,14 +2481,15 @@ static void do_render_all_options(Render *re) re->stats_draw(re->sdh, &re->i); re->display_draw(re->ddh, re->result, NULL); - } else { do_render_composite_fields_blur_3d(re); } /* for UI only */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); renderresult_add_names(re->result); + BLI_rw_mutex_unlock(&re->resultmutex); re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; @@ -2622,7 +2716,7 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) char name[FILE_MAX]; RenderResult rres; - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); /* write movie or image */ if(BKE_imtype_is_movie(scene->r.imtype)) { @@ -2686,6 +2780,8 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) } } + RE_ReleaseResultImage(re); + BLI_timestr(re->i.lastframetime, name); printf(" Time: %s\n", name); fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */ @@ -2723,7 +2819,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) do_write_image_or_movie(re, scene, mh); } } else { - re->test_break(re->tbh); + if(re->test_break(re->tbh)) + G.afbreek= 1; } } } else { @@ -2769,9 +2866,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) do_render_all_options(re); - if(re->test_break(re->tbh) == 0) { + if(re->test_break(re->tbh) == 0) do_write_image_or_movie(re, scene, mh); - } + else + G.afbreek= 1; if(G.afbreek==1) { /* remove touched file */ @@ -3006,6 +3104,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) { RenderEngine engine; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); @@ -3014,6 +3113,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) else re->result= new_render_result(re, &re->disprect, 0, 0); // XXX re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); } + BLI_rw_mutex_unlock(&re->resultmutex); if(re->result==NULL) return; @@ -3027,6 +3127,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) free_render_result(&engine.fullresult, engine.fullresult.first); + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result->exrhandle) { RenderResult *rr; @@ -3042,5 +3143,6 @@ static void external_render_3d(Render *re, RenderEngineType *type) read_render_result(re, 0); } + BLI_rw_mutex_unlock(&re->resultmutex); } diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 29f4d7729fe..a416c2d2764 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -862,6 +862,7 @@ static void sss_create_tree_mat(Render *re, Material *mat) setting them back, maybe we need to create our own Render? */ /* do SSS preprocessing render */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); rr= re->result; osa= re->osa; osaflag= re->r.mode & R_OSA; @@ -875,13 +876,16 @@ static void sss_create_tree_mat(Render *re, Material *mat) if(!(re->r.scemode & R_PREVIEWBUTS)) re->result= NULL; + BLI_rw_mutex_unlock(&re->resultmutex); RE_TileProcessor(re, 0, 1); + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(!(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); re->result= rr; } + BLI_rw_mutex_unlock(&re->resultmutex); re->i.partsdone= partsdone; re->sss_mat= NULL; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 69c96d0d89d..489f27990cd 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -226,8 +226,10 @@ void WM_set_framebuffer_index_color(int index); int WM_framebuffer_to_index(unsigned int col); /* threaded Jobs Manager */ +#define WM_JOB_PRIORITY 1 +#define WM_JOB_EXCL_RENDER 2 -struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void *owner); +struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void *owner, int flag); int WM_jobs_test(struct wmWindowManager *wm, void *owner); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index bef3268920d..9e16ce4082f 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -107,6 +107,7 @@ struct wmJob { /* internal */ void *owner; + int flag; short suspended, running, ready, do_update, stop; /* once running, we store this separately */ @@ -123,7 +124,7 @@ struct wmJob { /* returns current or adds new job, but doesnt run it */ /* every owner only gets a single job, adding a new one will stop running stop and when stopped it starts the new one */ -wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner) +wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, int flag) { wmJob *steve; @@ -137,6 +138,7 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner) BLI_addtail(&wm->jobs, steve); steve->win= win; steve->owner= owner; + steve->flag= flag; } return steve; @@ -198,20 +200,25 @@ static void *do_job_thread(void *job_v) } /* dont allow same startjob to be executed twice */ -static void wm_jobs_test_suspend(wmWindowManager *wm, wmJob *test) +static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test) { wmJob *steve; + int suspend= 0; - for(steve= wm->jobs.first; steve; steve= steve->next) - if(steve!=test) - if(steve->running) - if(steve->startjob==test->startjob) - break; - - if(steve) - test->suspended= 1; - else - test->suspended= 0; + for(steve= wm->jobs.first; steve; steve= steve->next) { + if(steve==test || !steve->running) continue; + if(steve->startjob!=test->startjob && !(test->flag & WM_JOB_EXCL_RENDER)) continue; + if((test->flag & WM_JOB_EXCL_RENDER) && !(steve->flag & WM_JOB_EXCL_RENDER)) continue; + + suspend= 1; + + /* if this job has higher priority, stop others */ + if(test->flag & WM_JOB_PRIORITY) + steve->stop= 1; + } + + /* possible suspend ourselfs, waiting for other jobs, or de-suspend */ + test->suspended= suspend; } /* if job running, the same owner gave it a new job */ @@ -225,7 +232,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *steve) else { if(steve->customdata && steve->startjob) { - wm_jobs_test_suspend(wm, steve); + wm_jobs_test_suspend_stop(wm, steve); if(steve->suspended==0) { /* copy to ensure proper free in end */ |