Render & Compositing Thread Fixes
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 30 Sep 2009 18:18:32 +0000 (18:18 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 30 Sep 2009 18:18:32 +0000 (18:18 +0000)
* Rendering twice or more could crash layer/pass buttons.
* Compositing would crash while drawing the image.
* Rendering animations could also crash drawing the image.
* Compositing could crash
* Starting to rendering while preview render / compo was
  still running could crash.
* Exiting while rendering an animation would not abort the
  renderer properly, making Blender seemingly freeze.
* Fixes theoretically possible issue with setting malloc
  lock with nested threads.
* Drawing previews inside nodes could crash when those nodes
  were being rendered at the same time.

There's more crashes, manipulating the scene data or undo can
still crash, this commit only focuses on making sure the image
buffer and render result access is thread safe.

Implementation:
* Rather than assuming the render result does not get freed
  during render, which seems to be quite difficult to do given
  that e.g. the compositor is allowed to change the size of
  the buffer or output different passes, the render result is
  now protected with a read/write mutex.
* The read/write mutex allows multiple readers (and pixel
  writers) at the same time, but only allows one writer to
  manipulate the data structure.
* Added BKE_image_acquire_ibuf/BKE_image_release_ibuf to access
  images being rendered, cases where this is not needed (most
  code) can still use BKE_image_get_ibuf.
* The job manager now allows only one rendering job at the same
  time, rather than the G.rendering check which was not reliable.

29 files changed:
intern/guardedalloc/intern/mallocn.c
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/sequence.c
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/intern/threads.c
source/blender/editors/include/ED_image.h
source/blender/editors/render/render_preview.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/screen/screendump.c
source/blender/editors/space_file/writeimage.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_space.c
source/blender/nodes/intern/CMP_nodes/CMP_composite.c
source/blender/nodes/intern/CMP_nodes/CMP_image.c
source/blender/nodes/intern/CMP_util.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/sss.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_jobs.c

index 3b5f6a0caf9c99676ddfcf68db4ac545a301068e..ca7f2a4d5067bc97a443b411f93e106c0c76e73a 100644 (file)
@@ -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 */
index 47ab6f324d30f911503be0ce19dd80ea7520f0f5..85c3c716b8b713e91a955cea6a53c95a61fa4ec6 100644 (file)
@@ -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);
index 9953540bbcf318f72d24664c4203658ecf4cbf18..09d150341b2df51d24561c3b659dbf91af489d5a 100644 (file)
@@ -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)
 {
index 90ea53d4364f7e31c837e748489f2193f8a1ec08..aa12894feb99e21880bdb28acc661e9491d13a04 100644 (file)
@@ -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;
                        }
                }
        }
index 7f3e2789232b6decd57f6aecdbec9fb370dbfa83..b80df60e726464f6c47f12097498fef37005198b 100644 (file)
@@ -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();
                        
index 8babb5fe780130a0f56f82ccc9e54c161f05eb55..ace9ddd729faaddeda1d635258649f1b9ea43981 100644 (file)
 #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;
 
index ce9f9adeb90cf1007cbaf8e2280c30bfe11cd02f..b5c6a5a3b4edb419707670cc66ccf1251c707162 100644 (file)
@@ -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 {
index a4263f7bd77ad74d029cced1f3d2d9e35e7dffc6..41a83a34ee4fa2007252740117f4ffbe8ce0ba2c 100644 (file)
@@ -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);
index 7dc04a47c511ad5b8a2f99fad14404d56e809c85..4a671e4d2ba55d3e6fcad0f3bd0950ef4d29f2b0 100644 (file)
@@ -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 */
index ae3f74403f2ea6ecca18bb5d95012811aaac9791..7f2084d5a76d10ad870afc4f977b8f7d55b6d95d 100644 (file)
@@ -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);
index fb3da4a53539a39d5ff57103cbc681f377d7ba53..81c3f4d68144ffe8a8e5584d5933715d670f5ffc 100644 (file)
@@ -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 */
index 994f38320f25d7052a568690f48671b7699b50d6..045c790b9cde7de8d50edcc3c4fda56d4352d1c6 100644 (file)
@@ -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);
 }
 
 
index bdf3e9416b9f290a64afe292bc3f2bfb589d619e..67fb95b1f6bd7bf7015b594249b50baf0c4430ae 100644 (file)
@@ -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);
        }
 }
 
index fa736a29ce8a56d2fbf3ece310ca7acfc2afca34..a42fec30c4592a95a37455f01319c99967ecfe0a 100644 (file)
@@ -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);
 }
 
index 317a058d20eea59061ad8da3fabf09bb6593e830..89427ba8535d6878d9c111480e6c685a9b9d1b64 100644 (file)
@@ -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");
index 55b910cf6b4c1b4942d3a4483272487c8267aff8..4cf59c9a28e6859865001d47772b5676e69f6366 100644 (file)
@@ -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)
index c7e458b9e870451f44f6d65751ec876e3664828f..3fc91fea91446e51e3656e2987aebf0dc2288d91 100644 (file)
@@ -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);
index 5a89851d65bcc76d4e35185bffe5bb48570b1cb5..50a99650ec093fd51e83453156697fb6adec931d 100644 (file)
@@ -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);
index 4c2689d4f64b4be8206fe2307f77b9159991616e..521756b8539160569acd8d9e9ba53b91b1fc5aa8 100644 (file)
@@ -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
index df956670eb3cdde28b99d6d250e22324dd65eeab..422283c940f3465c595e8495c12c7ee295be6f70 100644 (file)
@@ -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);
 }
 
index ee9545c31963e1ce047b3becf68307abe8b2dba9..800cccc2bfcacc283413ce4f9def36f4924d3ae4 100644 (file)
@@ -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)
index 5f44435777640a8b9a799075328294e5b974752a..00be52a81aaee138887bf4bb86beb7bfb02418eb 100644 (file)
@@ -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);
 };
 
 
index b396d5549d7731539739a9b693006303d000699e..075eefb4368697804c5ee45096df26426b50fdfa 100644 (file)
@@ -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);
-
        }
 }
 
index bf02af6ac36873576bb63c34f60e010309264e1c..56a81ac6b438697c8e67b9726138a12ded3e59e1 100644 (file)
@@ -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);
index e50e498228d6ed82c735393afc7442698e09edf5..96306be31c80f43c092fccfad1ac8efa18a27885 100644 (file)
@@ -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;
index 68b6f9e524caee1d33d518d6d28c906137c843a5..077f826b1ef2df3c3826e316ecc748e9f4f9f42e 100644 (file)
@@ -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);
 }
 
index 29f4d7729fe07d818dea1c1dddf876903a1e9019..a416c2d27648102a592bcecdb296ac73e593d0e6 100644 (file)
@@ -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;
index 69c96d0d89d06b3c3f89397e3736e5b8b2ac7f34..489f27990cda756526904f1ad9de09deb9eec319 100644 (file)
@@ -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);
 
index bef3268920d68b2ecee6b1cb85e38390559f5da7..9e16ce4082fba54cdfb51a7ca53501ee284a7b25 100644 (file)
@@ -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 */