diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-09-30 22:18:32 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-09-30 22:18:32 +0400 |
commit | b466286c3e0e64860299a4737b9cb13c8fc15618 (patch) | |
tree | 8fd9918ecb93eb8ba44eab113360f62efe1f18d6 /source/blender/editors/space_image | |
parent | 727745bd49592e1b90f0ce9cb78556404ba518ca (diff) |
Render & Compositing Thread Fixes
* 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.
Diffstat (limited to 'source/blender/editors/space_image')
-rw-r--r-- | source/blender/editors/space_image/image_buttons.c | 30 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_draw.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 80 | ||||
-rw-r--r-- | source/blender/editors/space_image/space_image.c | 71 |
4 files changed, 123 insertions, 70 deletions
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) |