diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-10-27 10:51:10 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-10-27 14:06:14 +0300 |
commit | 5f0933f07a548719a850d9cac01aae6709b9dc0b (patch) | |
tree | e31af4de22de1ef037cc8fc6784d292dd5be32e3 /source/blender/editors/render/render_preview.c | |
parent | f11298692b93c79132b77d0795e6bd6080c62480 (diff) |
Fix T49829: Removal of custom icon previews during add-on unregister crashes Blender.
Issue was happening when removal of custom icons was done while they
were still being rendered by preview job.
Now add a 'deffered deletion' system, to prevent main thread to delete
preview image until loading thread is done with them.
Note that ideally, calling `ED_preview_kill_jobs()` on custom icon
removal would have been simpler, but we don't have easy access to
context here...
Diffstat (limited to 'source/blender/editors/render/render_preview.c')
-rw-r--r-- | source/blender/editors/render/render_preview.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index ddbf59b2cf7..87c08dc6583 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -1080,13 +1080,19 @@ static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress) { IconPreview *ip = (IconPreview *)customdata; - IconPreviewSize *cur_size = ip->sizes.first; + IconPreviewSize *cur_size; const bool use_new_shading = BKE_scene_use_new_shading_nodes(ip->scene); - while (cur_size) { + for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) { PreviewImage *prv = ip->owner; + + if (prv->tag & PRV_TAG_DEFFERED_DELETE) { + /* Non-thread-protected reading is not an issue here. */ + continue; + } + ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - const bool is_render = !prv->use_deferred; + const bool is_render = !(prv->tag & PRV_TAG_DEFFERED); /* construct shader preview from image size and previewcustomdata */ sp->scene = ip->scene; @@ -1117,8 +1123,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short common_preview_startjob(sp, stop, do_update, progress); shader_preview_free(sp); - - cur_size = cur_size->next; } } @@ -1147,6 +1151,15 @@ static void icon_preview_endjob(void *customdata) } #endif } + + if (ip->owner) { + PreviewImage *prv_img = ip->owner; + prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING; + if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) { + BLI_assert(prv_img->tag & PRV_TAG_DEFFERED); + BKE_previewimg_cached_release_pointer(prv_img); + } + } } static void icon_preview_free(void *customdata) @@ -1205,6 +1218,14 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r icon_preview_add_size(ip, rect, sizex, sizey); + /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */ + { + PreviewImage *prv_img = owner; + if (prv_img->tag & PRV_TAG_DEFFERED) { + prv_img->tag |= PRV_TAG_DEFFERED_RENDERING; + } + } + /* setup job */ WM_jobs_customdata_set(wm_job, ip, icon_preview_free); WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); |