diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-03-16 19:58:45 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-03-16 19:58:45 +0300 |
commit | f17dcf58c86274661a10cf4f95939deb63a02fa7 (patch) | |
tree | 94fc52b7e0d41d6cb806eaf5e0b0e604c20722c1 /source/blender/blenkernel/intern/image.c | |
parent | 735b444d74d41bf2cec1ab81e781283e79d9c3d6 (diff) |
Fixes for thread related render / compositing crashes:
* Viewer node could free image while it is being redrawn, viewer image
buffers now need acquire/release to be accessed as was already the
case for render results.
* The Composite node could free the image buffers outside of a lock,
also causing simultaneous redraw to crash.
* Especially on Windows, re-rendering could crash when drawing an image
that was freed. When RE_RenderInProgress was true it would access the
image buffer and simply return it while it could still contain a pointer
to a render result buffer that was already freed. I don't understand
why this case was there in the first place, so I've removed it.
Possibly fixes bugs #20174, #21418, #21391, #21394.
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 191 |
1 files changed, 90 insertions, 101 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ee3d685938b..f870fc1083b 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1932,113 +1932,93 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* always returns a single ibuf, also during render progress */ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r) { - Render *re= NULL; - RenderResult *rr= NULL; - + Render *re; + RenderResult rres; + float *rectf, *rectz; + unsigned int *rect; + float dither; + int channels, layer, pass; + ImBuf *ibuf; + + if(!(iuser && iuser->scene)) + return 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, RE_SLOT_VIEW); - rr= RE_AcquireResultRead(re); + re= RE_GetRender(iuser->scene->id.name, RE_SLOT_VIEW); + + channels= 4; + layer= (iuser)? iuser->layer: 0; + pass= (iuser)? iuser->pass: 0; + + /* this gives active layer, composite or seqence result */ + RE_AcquireResultImage(re, &rres); + rect= (unsigned int *)rres.rect32; + rectf= rres.rectf; + rectz= rres.rectz; + dither= iuser->scene->r.dither_intensity; + + /* get compo/seq result by default */ + if(rres.rectf && layer==0); + else if(rres.layers.first) { + RenderLayer *rl= BLI_findlink(&rres.layers, layer-(rres.rectf?1:0)); + if(rl) { + RenderPass *rpass; + + /* there's no combined pass, is in renderlayer itself */ + if(pass==0) { + rectf= rl->rectf; + } + else { + rpass= BLI_findlink(&rl->passes, pass-1); + if(rpass) { + channels= rpass->channels; + rectf= rpass->rect; + dither= 0.0f; /* don't dither passes */ + } + } - /* release is done in BKE_image_release_ibuf using lock_r */ - *lock_r= re; + for(rpass= rl->passes.first; rpass; rpass= rpass->next) + if(rpass->passtype == SCE_PASS_Z) + rectz= rpass->rect; + } } - - if(rr==NULL) - return NULL; - if(RE_RenderInProgress(re)) { - ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); - - /* make ibuf if needed, and initialize it */ - /* this only gets called when mutex locked */ - if(ibuf==NULL) { - ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - } - - return ibuf; + if(!(rectf || rect)) { + RE_ReleaseResultImage(re); + return NULL; } - else { - RenderResult rres; - float *rectf, *rectz; - unsigned int *rect; - float dither; - int channels, layer, pass; - - channels= 4; - layer= (iuser)? iuser->layer: 0; - pass= (iuser)? iuser->pass: 0; - - /* this gives active layer, composite or seqence result */ - RE_AcquireResultImage(RE_GetRender(iuser->scene->id.name, RE_SLOT_VIEW), &rres); - rect= (unsigned int *)rres.rect32; - rectf= rres.rectf; - rectz= rres.rectz; - dither= iuser->scene->r.dither_intensity; - - /* get compo/seq result by default */ - if(rr->rectf && layer==0); - else if(rr->layers.first) { - RenderLayer *rl= BLI_findlink(&rr->layers, layer-(rr->rectf?1:0)); - if(rl) { - RenderPass *rpass; - - /* there's no combined pass, is in renderlayer itself */ - if(pass==0) { - rectf= rl->rectf; - } - else { - rpass= BLI_findlink(&rl->passes, pass-1); - if(rpass) { - channels= rpass->channels; - rectf= rpass->rect; - dither= 0.0f; /* don't dither passes */ - } - } - for(rpass= rl->passes.first; rpass; rpass= rpass->next) - if(rpass->passtype == SCE_PASS_Z) - rectz= rpass->rect; - } - } - - if(rectf || rect) { - ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); - /* make ibuf if needed, and initialize it */ - if(ibuf==NULL) { - ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, 0, 0); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - } - ibuf->x= rr->rectx; - ibuf->y= rr->recty; - - if(ibuf->rect_float!=rectf || rect) /* ensure correct redraw */ - imb_freerectImBuf(ibuf); - if(rect) - ibuf->rect= rect; - - ibuf->rect_float= rectf; - ibuf->flags |= IB_rectfloat; - ibuf->channels= channels; - ibuf->zbuf_float= rectz; - ibuf->flags |= IB_zbuffloat; - ibuf->dither= dither; + /* make ibuf if needed, and initialize it */ + if(ibuf==NULL) { + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } + ibuf->x= rres.rectx; + ibuf->y= rres.recty; + + if(ibuf->rect_float!=rectf || rect) /* ensure correct redraw */ + imb_freerectImBuf(ibuf); + if(rect) + ibuf->rect= rect; + + ibuf->rect_float= rectf; + ibuf->flags |= IB_rectfloat; + ibuf->channels= channels; + ibuf->zbuf_float= rectz; + ibuf->flags |= IB_zbuffloat; + ibuf->dither= dither; - RE_ReleaseResultImage(re); + ima->ok= IMA_OK_LOADED; - ima->ok= IMA_OK_LOADED; - return ibuf; - } + /* release is done in BKE_image_release_ibuf using lock_r */ + *lock_r= re; - RE_ReleaseResultImage(re); - } - - return NULL; + return ibuf; } static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) @@ -2199,10 +2179,17 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) ibuf= image_get_render_result(ima, iuser, lock_r); } else if(ima->type==IMA_TYPE_COMPOSITE) { - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, 0, frame); + /* requires lock/unlock, otherwise don't return image */ + if(lock_r) { + /* unlock in BKE_image_release_ibuf */ + BLI_lock_thread(LOCK_VIEWER); + *lock_r= ima; + + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } } } } @@ -2220,9 +2207,11 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) void BKE_image_release_ibuf(Image *ima, void *lock) { - /* for getting image during threaded render, need to release */ - if(lock) - RE_ReleaseResult(lock); + /* for getting image during threaded render / compositing, need to release */ + if(lock == ima) + BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + else if(lock) + RE_ReleaseResultImage(lock); /* render result */ } ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) |