diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 41516a74c9fd8cd7aa49f1c6b497f2c8ed1b48ed..f12615344653326265e15004aab7b00087313500 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -71,6 +71,8 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
 
         layout.prop(rd, "display_mode", text="Display")
 
+        layout.prop(rd, "use_lock_interface")
+
 
 class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
     bl_label = "Dimensions"
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 913bdfd1521bcee927af34b61d09a5b4241262c9..29de575e8b8f0a7d81ef6126e17391bcdd6817bb 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5554,6 +5554,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
 	wm->winactive = NULL;
 	wm->initialized = 0;
 	wm->op_undo_depth = 0;
+	wm->is_interface_locked = 0;
 }
 
 static void lib_link_windowmanager(FileData *fd, Main *main)
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 4ff4150e06a03ae6667a94c3229c5cfa2b4ef2e7..e57474a04437cb861c126270d67fa0727a0bfddc 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";
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 38d19923c3d5337df4e356929fd2848703052f27..120e6f52d95c93a6fcc2337f0facb378885537e9 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -363,7 +363,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
 	ot->poll = space_image_main_area_poll;
 
 	/* flags */
-	ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+	ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS;
 	
 	/* properties */
 	RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -577,7 +577,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
 	ot->poll = space_image_main_area_poll;
 
 	/* flags */
-	ot->flag = OPTYPE_BLOCKING;
+	ot->flag = OPTYPE_BLOCKING | OPTYPE_LOCK_BYPASS;
 	
 	/* properties */
 	RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX,
@@ -640,6 +640,9 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->invoke = image_view_ndof_invoke;
+
+	/* flags */
+	ot->flag = OPTYPE_LOCK_BYPASS;
 }
 
 /********************** view all operator *********************/
@@ -817,6 +820,9 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
 	ot->exec = image_view_zoom_in_exec;
 	ot->poll = space_image_main_area_poll;
 
+	/* flags */
+	ot->flag = OPTYPE_LOCK_BYPASS;
+
 	/* properties */
 	RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -859,6 +865,9 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
 	ot->exec = image_view_zoom_out_exec;
 	ot->poll = space_image_main_area_poll;
 
+	/* flags */
+	ot->flag = OPTYPE_LOCK_BYPASS;
+
 	/* properties */
 	RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -901,6 +910,9 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
 	ot->exec = image_view_zoom_ratio_exec;
 	ot->poll = space_image_main_area_poll;
 
+	/* flags */
+	ot->flag = OPTYPE_LOCK_BYPASS;
+
 	/* properties */
 	RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX,
 	              "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 076dc9c7f59f2f911fe120aeb581c6ef65e6b375..177b687802d0df7c1cf238c732a92c103f9beb7c 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -432,7 +432,8 @@ typedef struct RenderData {
 	 * Render to image editor, fullscreen or to new window.
 	 */
 	short displaymode;
-	short pad7;
+	char use_lock_interface;
+	char pad7;
 
 	/**
 	 * Flags for render settings. Use bit-masking to access the settings.
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index ff43cc31b9aa162a5d0439e12f84ae6d591bf1c3..a17e416b5bdefbdd50e1382c196a078bc157006b 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -154,6 +154,9 @@ typedef struct wmWindowManager {
 
 	ListBase timers;                  /* active timers */
 	struct wmTimer *autosavetimer;    /* timer for auto save */
+
+	char is_interface_locked;		/* indicates whether interface is locked for user interaction */
+	char par[7];
 } wmWindowManager;
 
 /* wmWindowManager.initialized */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 4a544606f09955591204ebad882b179d68c12541..19d90ab752ba3af2aff5ad8ac14f42635b24ac79 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -4539,6 +4539,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Display", "Select where rendered images will be displayed");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
 
+	prop = RNA_def_property(srna, "use_lock_interface", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "use_lock_interface", 1);
+	RNA_def_property_ui_text(prop, "Lock Interface", "Lock interface during rendering in favor of giving more memory to the renderer");
+	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
 	prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
 	RNA_def_property_string_sdna(prop, NULL, "pic");
 	RNA_def_property_ui_text(prop, "Output Path",
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 32c0a1d8535c1be06109bc40fdc4c4809fa092d5..bc07f0ce6c0ea161769198e8da664846040716a5 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -290,5 +290,7 @@ struct Scene *RE_GetScene(struct Render *re);
 
 int RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override, struct ReportList *reports);
 
+bool RE_allow_render_generic_object(struct Object *ob);
+
 #endif /* __RE_PIPELINE_H__ */
 
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index ec2644e4d9b3d4e5467ff455c7af8df2a94e9e56..39bc571853aaa283dd2cc4bb438dbdd6c49f560c 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1602,6 +1602,18 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node)
 	return false;
 }
 
+bool RE_allow_render_generic_object(Object *ob)
+{
+	/* override not showing object when duplis are used with particles */
+	if (ob->transflag & OB_DUPLIPARTS) {
+		/* pass */  /* let particle system(s) handle showing vs. not showing */
+	}
+	else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
+		return false;
+	}
+	return true;
+}
+
 /* Issue here is that it's possible that object which is used by boolean,
  * array or shrinkwrap modifiers weren't displayed in the viewport before
  * rendering. This leads to situations when apply() of this modifiers
@@ -1619,18 +1631,6 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node)
 #define DEPSGRAPH_WORKAROUND_HACK
 
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-static bool allow_render_mesh_object(Object *ob)
-{
-	/* override not showing object when duplis are used with particles */
-	if (ob->transflag & OB_DUPLIPARTS) {
-		/* pass */  /* let particle system(s) handle showing vs. not showing */
-	}
-	else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
-		return false;
-	}
-	return true;
-}
-
 static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
 {
 	Scene *sce_iter;
@@ -1643,7 +1643,7 @@ static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
 		}
 
 		if (object->type == OB_MESH) {
-			if (allow_render_mesh_object(object)) {
+			if (RE_allow_render_generic_object(object)) {
 				ModifierData *md;
 				VirtualModifierData virtualModifierData;
 
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index c13731e2459f1fb4d78f2b8a4fed20cd9d6abbcf..a47018e21eb5792bd6814fc890a490ddb9e6c910 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -428,6 +428,9 @@ void        WM_main_playanim(int argc, const char **argv);
 /* debugging only, convenience function to write on crash */
 bool write_crash_blend(void);
 
+			/* Lock the interface for any communication */
+void        WM_set_locked_interface(struct wmWindowManager *wm, bool lock);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 83c17170f9eed90f2af3391c72382d261eb86bcc..8bbdd7bd736b7da183bf86e7098900af2c9096a1 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -134,6 +134,7 @@ struct ImBuf;
 								 * and don't make sense to be accessed from the
 								 * search menu, even if poll() returns TRUE.
 								 * currently only used for the search toolbox */
+#define OPTYPE_LOCK_BYPASS		128	/* Allow operator to run when interface is locked */
 
 /* context to call operator in for WM_operator_name_call */
 /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index be4064a375f68b2c61892ad07d24e259a2033453..6e2fcf159972d10fbf9805f0e06d9acd484876bc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1488,6 +1488,22 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
 	}
 }
 
+/* Check whether operator is allowed to run in case interface is locked,
+ * If interface is unlocked, will always return truth.
+ */
+static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot)
+{
+	wmWindowManager *wm = CTX_wm_manager(C);
+
+	if (wm->is_interface_locked) {
+		if ((ot->flag & OPTYPE_LOCK_BYPASS) == 0) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
 /* bad hacking event system... better restore event type for checking of KM_CLICK for example */
 /* XXX modal maps could use different method (ton) */
 static void wm_event_modalmap_end(wmEvent *event, bool dbl_click_disabled)
@@ -1514,7 +1530,12 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
 		wmOperator *op = handler->op;
 		wmOperatorType *ot = op->type;
 
-		if (ot->modal) {
+		if (!wm_operator_check_locked_interface(C, ot)) {
+			/* Interface is locked and pperator is not allowed to run,
+			 * nothing to do in this case.
+			 */
+		}
+		else if (ot->modal) {
 			/* we set context to where modal handler came from */
 			wmWindowManager *wm = CTX_wm_manager(C);
 			ScrArea *area = CTX_wm_area(C);
@@ -1587,7 +1608,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
 		wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0);
 
 		if (ot) {
-			retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+			if (wm_operator_check_locked_interface(C, ot)) {
+				retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+			}
 		}
 	}
 	/* Finished and pass through flag as handled */
@@ -1793,7 +1816,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 	        /* comment this out to flood the console! (if you really want to test) */
 	        !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
 	        ;
+#    define PRINT if (do_debug_handler) printf
+#else
+#  define PRINT(format, ...)
 #endif
+
 	wmWindowManager *wm = CTX_wm_manager(C);
 	wmEventHandler *handler, *nexthandler;
 	int action = WM_HANDLER_CONTINUE;
@@ -1829,28 +1856,16 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 				wmKeyMap *keymap = WM_keymap_active(wm, handler->keymap);
 				wmKeyMapItem *kmi;
 
-#ifndef NDEBUG
-				if (do_debug_handler) {
-					printf("%s:   checking '%s' ...", __func__, keymap->idname);
-				}
-#endif
+				PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
 
 				if (!keymap->poll || keymap->poll(C)) {
 
-#ifndef NDEBUG
-					if (do_debug_handler) {
-						printf("pass\n");
-					}
-#endif
+					PRINT("pass\n");
 
 					for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
 						if (wm_eventmatch(event, kmi)) {
 
-#ifndef NDEBUG
-							if (do_debug_handler) {
-								printf("%s:     item matched '%s'\n", __func__, kmi->idname);
-							}
-#endif
+							PRINT("%s:     item matched '%s'\n", __func__, kmi->idname);
 
 							/* weak, but allows interactive callback to not use rawkey */
 							event->keymap_idname = kmi->idname;
@@ -1869,32 +1884,28 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 									if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
 										printf("%s:       handled - and pass on! '%s'\n", __func__, kmi->idname);
 								
-#ifndef NDEBUG
-								if (do_debug_handler) {
-									printf("%s:       un-handled '%s'...", __func__, kmi->idname);
-								}
-#endif
+									PRINT("%s:       un-handled '%s'...", __func__, kmi->idname);
 							}
 						}
 					}
 				}
 				else {
-#ifndef NDEBUG
-					if (do_debug_handler) {
-						printf("fail\n");
-					}
-#endif
+					PRINT("fail\n");
 				}
 			}
 			else if (handler->ui_handle) {
-				action |= wm_handler_ui_call(C, handler, event, always_pass);
+				if (!wm->is_interface_locked) {
+					action |= wm_handler_ui_call(C, handler, event, always_pass);
+				}
 			}
 			else if (handler->type == WM_HANDLER_FILESELECT) {
-				/* screen context changes here */
-				action |= wm_handler_fileselect_call(C, handlers, handler, event);
+				if (!wm->is_interface_locked) {
+					/* screen context changes here */
+					action |= wm_handler_fileselect_call(C, handlers, handler, event);
+				}
 			}
 			else if (handler->dropboxes) {
-				if (event->type == EVT_DROP) {
+				if (!wm->is_interface_locked && event->type == EVT_DROP) {
 					wmDropBox *drop = handler->dropboxes->first;
 					for (; drop; drop = drop->next) {
 						/* other drop custom types allowed */
@@ -1960,6 +1971,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 	if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL))
 		wm_cursor_arrow_move(CTX_wm_window(C), event);
 
+#undef PRINT
+
 	return action;
 }
 
@@ -3277,3 +3290,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
 	WM_event_print(&event);
 #endif
 }
+
+void WM_set_locked_interface(wmWindowManager *wm, bool lock)
+{
+	/* This will prevent events from being handled while interface is locked
+	 *
+	 * Use a "local" flag for now, because currently no other areas could
+	 * benefit of locked interface anyway (aka using G.is_interface_locked
+	 * wouldn't be useful anywhere outside of window manager, so let's not
+	 * pollute global context with such an information for now).
+	 */
+	wm->is_interface_locked = lock ? 1 : 0;
+
+	/* This will prevent drawing regions which uses non-threadsafe data.
+	 * Currently it'll be just a 3D viewport.
+	 *
+	 * TODO(sergey): Make it different locked states, so different jobs
+	 *               could lock different areas of blender and allow
+	 *               interation with others?
+	 */
+	BKE_spacedata_draw_locks(lock);
+}