Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/guardedalloc/intern/mallocn.c24
-rw-r--r--source/blender/blenkernel/BKE_image.h8
-rw-r--r--source/blender/blenkernel/intern/image.c61
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/sequence.c4
-rw-r--r--source/blender/blenlib/BLI_threads.h53
-rw-r--r--source/blender/blenlib/intern/threads.c94
-rw-r--r--source/blender/editors/include/ED_image.h5
-rw-r--r--source/blender/editors/render/render_preview.c23
-rw-r--r--source/blender/editors/screen/screen_ops.c21
-rw-r--r--source/blender/editors/screen/screendump.c2
-rw-r--r--source/blender/editors/space_file/writeimage.c14
-rw-r--r--source/blender/editors/space_image/image_buttons.c30
-rw-r--r--source/blender/editors/space_image/image_draw.c12
-rw-r--r--source/blender/editors/space_image/image_ops.c80
-rw-r--r--source/blender/editors/space_image/space_image.c71
-rw-r--r--source/blender/editors/space_node/node_draw.c12
-rw-r--r--source/blender/editors/space_node/node_edit.c9
-rw-r--r--source/blender/makesrna/intern/rna_image.c23
-rw-r--r--source/blender/makesrna/intern/rna_space.c14
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_composite.c7
-rw-r--r--source/blender/nodes/intern/CMP_nodes/CMP_image.c10
-rw-r--r--source/blender/nodes/intern/CMP_util.c9
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h7
-rw-r--r--source/blender/render/intern/include/render_types.h4
-rw-r--r--source/blender/render/intern/source/pipeline.c168
-rw-r--r--source/blender/render/intern/source/sss.c4
-rw-r--r--source/blender/windowmanager/WM_api.h4
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c33
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 */