diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-01-29 14:07:14 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-01-29 14:07:14 +0400 |
commit | a68ceb0af8ecc4c5df7a27b52814fcf0246ad36a (patch) | |
tree | 889f16eef97ef9462c141df0a2e373302c015be6 /source/blender/editors/render/render_internal.c | |
parent | 39eb314cb922b805e9126d5f0352f31c2f84f151 (diff) |
Option to lock the interface while rendering
Added function called WM_set_locked_interface which does
two things:
- Prevents event queue from being handled, so no operators
(see below) or values are even possible to run or change.
This prevents any kind of "destructive" action performed
from user while rendering.
- Locks interface refresh for regions which does have lock
set to truth in their template. Currently it's just a 3D
viewport, but in the future more regions could be considered
unsafe, or we could want to lock different parts of
interface when doing different jobs.
This is needed because 3D viewport could be using or changing
the same data as renderer currently uses, leading to threading
conflict.
Notifiers are still allowed to handle, so render progress is
seen on the screen, but would need to doublecheck on this, in
terms some notifiers could be changing the data.
For now interface locking happens for render job only in case
"Lock Interface" checkbox is enabled.
Other tools like backing would also benefit of this option.
It is possible to mark operator as safe to be used in locked
interface mode by adding OPTYPE_ALLOW_LOCKED bit to operator
template flags.
This bit is completely handled by wm_evem_system, not
with operator run routines, so it's still possible to
run operators from drivers and handlers.
Currently allowed image editor navigation and zooming.
Reviewers: brecht, campbellbarton
Reviewed By: campbellbarton
Differential Revision: https://developer.blender.org/D142
Diffstat (limited to 'source/blender/editors/render/render_internal.c')
-rw-r--r-- | source/blender/editors/render/render_internal.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4ff4150e06a..e57474a0443 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -58,6 +58,7 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_multires.h" +#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_sequencer.h" @@ -116,6 +117,7 @@ typedef struct RenderJob { ScrArea *sa; ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; + bool interface_locked; } RenderJob; /* called inside thread! */ @@ -662,6 +664,29 @@ static void render_endjob(void *rjv) BKE_image_release_ibuf(ima, ibuf, lock); } + + /* Finally unlock the user interface (if it was locked). */ + if (rj->interface_locked) { + Scene *scene; + + /* Interface was locked, so window manager couldn't have been changed + * and using one from Global will unlock exactly the same manager as + * was locked before running the job. + */ + WM_set_locked_interface(G.main->wm.first, false); + + /* We've freed all the derived caches before rendering, which is + * effectively the same as if we re-loaded the file. + * + * So let's not try being smart here and just reset all updated + * scene layers and use generic DAG_on_visible_update. + */ + for (scene = G.main->scene.first; scene; scene = scene->id.next) { + scene->lay_updated = 0; + } + + DAG_on_visible_update(G.main, false); + } } /* called by render, check job 'stop' value or the global */ @@ -687,10 +712,14 @@ static int render_break(void *UNUSED(rjv)) /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */ /* maybe need a way to get job send notifer? */ -static void render_drawlock(void *UNUSED(rjv), int lock) +static void render_drawlock(void *rjv, int lock) { - BKE_spacedata_draw_locks(lock); - + RenderJob *rj = rjv; + + /* If interface is locked, renderer callback shall do nothing. */ + if (!rj->interface_locked) { + BKE_spacedata_draw_locks(lock); + } } /* catch esc */ @@ -721,6 +750,36 @@ static void screen_render_cancel(bContext *C, wmOperator *op) WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); } +static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay) +{ + Object *object; + Scene *sce_iter; + Base *base; + + for (object = bmain->object.first; object; object = object->id.next) { + object->id.flag |= LIB_DOIT; + } + + for (SETLOOPER(scene, sce_iter, base)) { + if ((base->lay & renderlay) == 0) { + continue; + } + + if (RE_allow_render_generic_object(base->object)) { + base->object->id.flag &= ~LIB_DOIT; + } + } + + for (object = bmain->object.first; object; object = object->id.next) { + if ((object->id.flag & LIB_DOIT) == 0) { + continue; + } + object->id.flag &= ~LIB_DOIT; + + BKE_object_free_derived_caches(object); + } +} + /* using context, starts job */ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -832,6 +891,26 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->lay_override |= v3d->localvd->lay; } + /* Lock the user interface depending on render settings. */ + if (scene->r.use_lock_interface) { + int renderlay = rj->lay_override ? rj->lay_override : scene->lay; + + WM_set_locked_interface(CTX_wm_manager(C), true); + + /* Set flag interface need to be unlocked. + * + * This is so because we don't have copy of render settings + * accessible from render job and copy is needed in case + * of non-locked rendering, so we wouldn't try to unlock + * anything if option was initially unset but then was + * enabled during rendering. + */ + rj->interface_locked = true; + + /* Clean memory used by viewport? */ + clean_viewport_memory(rj->main, scene, renderlay); + } + /* setup job */ if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; else name = "Render"; |