Merged changes in the trunk up to revision 26856.
[blender-staging.git] / source / blender / render / intern / source / pipeline.c
index e38f2416ca8af39e7d22bb62f42bd7142e9f6fda..72b147e992762f21d71feac1d6a16cf23d373abc 100644 (file)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2006 Blender Foundation.
  * All rights reserved.
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_writeavi.h"      /* <------ should be replaced once with generic movie module */
-#include "BKE_sequence.h"
+#include "BKE_sequencer.h"
 #include "BKE_pointcache.h"
+#include "BKE_animsys.h"       /* <------ should this be here?, needed for sequencer update */
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_rand.h"
 #include "BLI_threads.h"
@@ -66,6 +67,9 @@
 
 #include "RE_pipeline.h"
 
+#include "FRS_freestyle.h"
+#include "FRS_freestyle_config.h"
+
 /* internal */
 #include "render_types.h"
 #include "renderpipeline.h"
@@ -95,7 +99,7 @@
 - tiles, rect, baking
 - layers/tiles optionally to disk or directly in Render Result
 
-4) Composit Render Result
+4) Composite Render Result
 - also read external files etc
 
 5) Image Files
 /* ********* globals ******** */
 
 /* here we store all renders */
-static struct ListBase RenderList= {NULL, NULL};
+static struct {
+       ListBase renderlist;
+
+       /* render slots */
+       int viewslot, renderingslot;
+
+       /* commandline thread override */
+       int threads;
+} RenderGlobal = {{NULL, NULL}, 0, 0, -1}; 
 
 /* hardcopy of current render, used while rendering for speed */
 Render R;
 
-/* commandline thread override */
-static int commandline_threads= -1;
-
 /* ********* alloc and free ******** */
 
 
@@ -129,8 +138,8 @@ static void result_nothing(void *unused, RenderResult *rr) {}
 static void result_rcti_nothing(void *unused, RenderResult *rr, volatile struct rcti *rect) {}
 static void stats_nothing(void *unused, RenderStats *rs) {}
 static void int_nothing(void *unused, int val) {}
-static int void_nothing(void *unused) {return 0;}
 static void print_error(void *unused, char *str) {printf("ERROR: %s\n", str);}
+static int default_break(void *unused) {return G.afbreek == 1;}
 
 int RE_RenderInProgress(Render *re)
 {
@@ -213,22 +222,28 @@ static void free_render_result(ListBase *lb, RenderResult *rr)
 /* all layers except the active one get temporally pushed away */
 static void push_render_result(Render *re)
 {
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
        /* officially pushed result should be NULL... error can happen with do_seq */
        RE_FreeRenderResult(re->pushedresult);
        
        re->pushedresult= re->result;
        re->result= NULL;
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }
 
 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
 static void pop_render_result(Render *re)
 {
-       
        if(re->result==NULL) {
                printf("pop render result error; no current result!\n");
                return;
        }
+
        if(re->pushedresult) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
                if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) {
                        /* find which layer in pushedresult should be replaced */
                        SceneRenderLayer *srl;
@@ -255,6 +270,8 @@ static void pop_render_result(Render *re)
                
                RE_FreeRenderResult(re->pushedresult);
                re->pushedresult= NULL;
+
+               BLI_rw_mutex_unlock(&re->resultmutex);
        }
 }
 
@@ -300,6 +317,12 @@ static char *get_pass_name(int passtype, int channel)
                if(channel==2) return "Color.B";
                return "Color.A";
        }
+       if(passtype == SCE_PASS_EMIT) {
+               if(channel==-1) return "Emit";
+               if(channel==0) return "Emit.R";
+               if(channel==1) return "Emit.G";
+               return "Emit.B";
+       }
        if(passtype == SCE_PASS_DIFFUSE) {
                if(channel==-1) return "Diffuse";
                if(channel==0) return "Diffuse.R";
@@ -324,6 +347,18 @@ static char *get_pass_name(int passtype, int channel)
                if(channel==1) return "AO.G";
                return "AO.B";
        }
+       if(passtype == SCE_PASS_ENVIRONMENT) {
+               if(channel==-1) return "Environment";
+               if(channel==0) return "Environment.R";
+               if(channel==1) return "Environment.G";
+               return "Environment.B";
+       }
+       if(passtype == SCE_PASS_INDIRECT) {
+               if(channel==-1) return "Indirect";
+               if(channel==0) return "Indirect.R";
+               if(channel==1) return "Indirect.G";
+               return "Indirect.B";
+       }
        if(passtype == SCE_PASS_REFLECT) {
                if(channel==-1) return "Reflect";
                if(channel==0) return "Reflect.R";
@@ -350,6 +385,13 @@ static char *get_pass_name(int passtype, int channel)
                if(channel==-1) return "Mist";
                return "Mist.Z";
        }
+       if(passtype == SCE_PASS_RAYHITS)
+       {
+               if(channel==-1) return "Rayhits";
+               if(channel==0) return "Rayhits.R";
+               if(channel==1) return "Rayhits.G";
+               return "Rayhits.B";
+       }
        return "Unknown";
 }
 
@@ -374,6 +416,9 @@ static int passtype_from_name(char *str)
        if(strcmp(str, "Color")==0)
                return SCE_PASS_RGBA;
 
+       if(strcmp(str, "Emit")==0)
+               return SCE_PASS_EMIT;
+
        if(strcmp(str, "Diffuse")==0)
                return SCE_PASS_DIFFUSE;
 
@@ -386,6 +431,12 @@ static int passtype_from_name(char *str)
        if(strcmp(str, "AO")==0)
                return SCE_PASS_AO;
 
+       if(strcmp(str, "Environment")==0)
+               return SCE_PASS_ENVIRONMENT;
+
+       if(strcmp(str, "Indirect")==0)
+               return SCE_PASS_INDIRECT;
+
        if(strcmp(str, "Reflect")==0)
                return SCE_PASS_REFLECT;
 
@@ -401,12 +452,14 @@ static int passtype_from_name(char *str)
        if(strcmp(str, "Mist")==0)
                return SCE_PASS_MIST;
        
+       if(strcmp(str, "RayHits")==0)
+               return SCE_PASS_RAYHITS;
        return 0;
 }
 
 static void render_unique_exr_name(Render *re, char *str, int sample)
 {
-       char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE];
+       char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE];
        
        BLI_strncpy(di, G.sce, FILE_MAX);
        BLI_splitdirstring(di, fi);
@@ -528,7 +581,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
                rl->lay= srl->lay;
                rl->lay_zmask= srl->lay_zmask;
                rl->layflag= srl->layflag;
-               rl->passflag= srl->passflag;
+               rl->passflag= srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS;
                rl->pass_xor= srl->pass_xor;
                rl->light_override= srl->light_override;
                rl->mat_override= srl->mat_override;
@@ -554,12 +607,18 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_UV);
                if(srl->passflag  & SCE_PASS_RGBA)
                        render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA);
+               if(srl->passflag  & SCE_PASS_EMIT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT);
                if(srl->passflag  & SCE_PASS_DIFFUSE)
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
                if(srl->passflag  & SCE_PASS_SPEC)
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
                if(srl->passflag  & SCE_PASS_AO)
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
+               if(srl->passflag  & SCE_PASS_ENVIRONMENT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT);
+               if(srl->passflag  & SCE_PASS_INDIRECT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT);
                if(srl->passflag  & SCE_PASS_SHADOW)
                        render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
                if(srl->passflag  & SCE_PASS_REFLECT)
@@ -572,6 +631,8 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
                        render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
                if(srl->passflag  & SCE_PASS_MIST)
                        render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
+               if(rl->passflag & SCE_PASS_RAYHITS)
+                       render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
                
        }
        /* sss, previewrender and envmap don't do layers, so we make a default one */
@@ -596,6 +657,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
                rl->lay= (1<<20) -1;
                rl->layflag= 0x7FFF;    /* solid ztra halo strand */
                rl->passflag= SCE_PASS_COMBINED;
+               FRS_add_freestyle_config( srl );
                
                re->r.actlay= 0;
        }
@@ -868,33 +930,26 @@ static void renderresult_add_names(RenderResult *rr)
                        strcpy(rpass->name, get_pass_name(rpass->passtype, -1));
 }
 
-
-/* only for temp buffer files, makes exact copy of render result */
-static void read_render_result(Render *re, int sample)
+/* called for reading temp files, and for external engines */
+static int read_render_result_from_file(char *filename, RenderResult *rr)
 {
        RenderLayer *rl;
        RenderPass *rpass;
        void *exrhandle= IMB_exr_get_handle();
        int rectx, recty;
-       char str[FILE_MAX];
-       
-       RE_FreeRenderResult(re->result);
-       re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
 
-       render_unique_exr_name(re, str, sample);
-       if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) {
+       if(IMB_exr_begin_read(exrhandle, filename, &rectx, &recty)==0) {
                IMB_exr_close(exrhandle);
-               printf("cannot read: %s\n", str);
-               return;
+               return 0;
        }
        
-       printf("read exr tmp file: %s\n", str);
-       
-       if(re->result == NULL || rectx!=re->result->rectx || recty!=re->result->recty) {
+       if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) {
                printf("error in reading render result\n");
+               IMB_exr_close(exrhandle);
+               return 0;
        }
        else {
-               for(rl= re->result->layers.first; rl; rl= rl->next) {
+               for(rl= rr->layers.first; rl; rl= rl->next) {
                        
                        /* combined */
                        if(rl->rectf) {
@@ -914,21 +969,64 @@ static void read_render_result(Render *re, int sample)
                        
                }
                IMB_exr_read_channels(exrhandle);
-               renderresult_add_names(re->result);
+               renderresult_add_names(rr);
        }
        
        IMB_exr_close(exrhandle);
+
+       return 1;
+}
+
+/* only for temp buffer files, makes exact copy of render result */
+static void read_render_result(Render *re, int sample)
+{
+       char str[FILE_MAX];
+
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+       RE_FreeRenderResult(re->result);
+       re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
+
+       render_unique_exr_name(re, str, sample);
+       printf("read exr tmp file: %s\n", str);
+
+       if(!read_render_result_from_file(str, re->result))
+               printf("cannot read: %s\n", str);
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }
 
 /* *************************************************** */
 
-Render *RE_GetRender(const char *name)
+void RE_SetViewSlot(int slot)
+{
+       RenderGlobal.viewslot = slot;
+}
+
+int RE_GetViewSlot(void)
+{
+       return RenderGlobal.viewslot;
+}
+
+static int re_get_slot(int slot)
+{
+       if(slot == RE_SLOT_VIEW)
+               return RenderGlobal.viewslot;
+       else if(slot == RE_SLOT_RENDERING)
+               return (G.rendering)? RenderGlobal.renderingslot: RenderGlobal.viewslot;
+
+       return slot;
+}
+
+Render *RE_GetRender(const char *name, int slot)
 {
        Render *re;
+
+       slot= re_get_slot(slot);
        
        /* search for existing renders */
-       for(re= RenderList.first; re; re= re->next) {
-               if(strncmp(re->name, name, RE_MAXNAME)==0) {
+       for(re= RenderGlobal.renderlist.first; re; re= re->next) {
+               if(strncmp(re->name, name, RE_MAXNAME)==0 && re->slot==slot) {
                        break;
                }
        }
@@ -936,13 +1034,32 @@ Render *RE_GetRender(const char *name)
 }
 
 /* if you want to know exactly what has been done */
-RenderResult *RE_GetResult(Render *re)
+RenderResult *RE_AcquireResultRead(Render *re)
 {
-       if(re)
+       if(re) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
+               return re->result;
+       }
+
+       return NULL;
+}
+
+RenderResult *RE_AcquireResultWrite(Render *re)
+{
+       if(re) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                return re->result;
+       }
+
        return NULL;
 }
 
+void RE_ReleaseResult(Render *re)
+{
+       if(re)
+               BLI_rw_mutex_unlock(&re->resultmutex);
+}
+
 /* displist.c util.... */
 Scene *RE_GetScene(Render *re)
 {
@@ -963,38 +1080,49 @@ RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
 
 
 /* fill provided result struct with what's currently active or done */
-void RE_GetResultImage(Render *re, RenderResult *rr)
+void RE_AcquireResultImage(Render *re, RenderResult *rr)
 {
        memset(rr, 0, sizeof(RenderResult));
 
-       if(re && re->result) {
-               RenderLayer *rl;
-               
-               rr->rectx= re->result->rectx;
-               rr->recty= re->result->recty;
-               
-               rr->rectf= re->result->rectf;
-               rr->rectz= re->result->rectz;
-               rr->rect32= re->result->rect32;
-               
-               /* active layer */
-               rl= render_get_active_layer(re, re->result);
+       if(re) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
 
-               if(rl) {
-                       if(rr->rectf==NULL)
-                               rr->rectf= rl->rectf;
-                       if(rr->rectz==NULL)
-                               rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z);       
+               if(re->result) {
+                       RenderLayer *rl;
+                       
+                       rr->rectx= re->result->rectx;
+                       rr->recty= re->result->recty;
+                       
+                       rr->rectf= re->result->rectf;
+                       rr->rectz= re->result->rectz;
+                       rr->rect32= re->result->rect32;
+                       
+                       /* active layer */
+                       rl= render_get_active_layer(re, re->result);
+
+                       if(rl) {
+                               if(rr->rectf==NULL)
+                                       rr->rectf= rl->rectf;
+                               if(rr->rectz==NULL)
+                                       rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z);       
+                       }
                }
        }
 }
 
+void RE_ReleaseResultImage(Render *re)
+{
+       if(re)
+               BLI_rw_mutex_unlock(&re->resultmutex);
+}
+
 /* caller is responsible for allocating rect in correct size! */
 void RE_ResultGet32(Render *re, unsigned int *rect)
 {
        RenderResult rres;
        
-       RE_GetResultImage(re, &rres);
+       RE_AcquireResultImage(re, &rres);
+
        if(rres.rect32) 
                memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
        else if(rres.rectf) {
@@ -1002,49 +1130,62 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
                int tot= rres.rectx*rres.recty;
                char *cp= (char *)rect;
                
-               for(;tot>0; tot--, cp+=4, fp+=4) {
-                       cp[0] = FTOCHAR(fp[0]);
-                       cp[1] = FTOCHAR(fp[1]);
-                       cp[2] = FTOCHAR(fp[2]);
-                       cp[3] = FTOCHAR(fp[3]);
+               if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
+                       /* Finally convert back to sRGB rendered image */ 
+                       for(;tot>0; tot--, cp+=4, fp+=4) {
+                               cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0]));
+                               cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1]));
+                               cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2]));
+                               cp[3] = FTOCHAR(fp[3]);
+                       }
+               }
+               else {
+                       /* Color management is off : no conversion necessary */
+                       for(;tot>0; tot--, cp+=4, fp+=4) {
+                               cp[0] = FTOCHAR(fp[0]);
+                               cp[1] = FTOCHAR(fp[1]);
+                               cp[2] = FTOCHAR(fp[2]);
+                               cp[3] = FTOCHAR(fp[3]);
+                       }
                }
+
        }
        else
                /* else fill with black */
                memset(rect, 0, sizeof(int)*re->rectx*re->recty);
-}
 
+       RE_ReleaseResultImage(re);
+}
 
 RenderStats *RE_GetStats(Render *re)
 {
        return &re->i;
 }
 
-Render *RE_NewRender(const char *name)
+Render *RE_NewRender(const char *name, int slot)
 {
        Render *re;
+
+       slot= re_get_slot(slot);
        
        /* only one render per name exists */
-       re= RE_GetRender(name);
+       re= RE_GetRender(name, slot);
        if(re==NULL) {
                
                /* new render data struct */
                re= MEM_callocN(sizeof(Render), "new render");
-               BLI_addtail(&RenderList, re);
+               BLI_addtail(&RenderGlobal.renderlist, re);
                strncpy(re->name, name, RE_MAXNAME);
+               re->slot= slot;
+               BLI_rw_mutex_init(&re->resultmutex);
        }
        
-       /* prevent UI to draw old results */
-       RE_FreeRenderResult(re->result);
-       re->result= NULL;
-       re->result_ok= 0;
-       
        /* set default empty callbacks */
        re->display_init= result_nothing;
        re->display_clear= result_nothing;
        re->display_draw= result_rcti_nothing;
        re->timecursor= int_nothing;
-       re->test_break= void_nothing;
+       re->test_break= default_break;
        re->error= print_error;
        if(G.background)
                re->stats_draw= stats_background;
@@ -1062,6 +1203,7 @@ Render *RE_NewRender(const char *name)
 /* only call this while you know it will remove the link too */
 void RE_FreeRender(Render *re)
 {
+       BLI_rw_mutex_end(&re->resultmutex);
        
        free_renderdata_tables(re);
        free_sample_tables(re);
@@ -1069,15 +1211,15 @@ void RE_FreeRender(Render *re)
        RE_FreeRenderResult(re->result);
        RE_FreeRenderResult(re->pushedresult);
        
-       BLI_remlink(&RenderList, re);
+       BLI_remlink(&RenderGlobal.renderlist, re);
        MEM_freeN(re);
 }
 
 /* exit blender */
 void RE_FreeAllRender(void)
 {
-       while(RenderList.first) {
-               RE_FreeRender(RenderList.first);
+       while(RenderGlobal.renderlist.first) {
+               RE_FreeRender(RenderGlobal.renderlist.first);
        }
 }
 
@@ -1086,7 +1228,7 @@ void RE_FreeAllRender(void)
 
 /* what doesn't change during entire render sequence */
 /* disprect is optional, if NULL it assumes full window render */
-void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy, rcti *disprect)
+void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *srl, int winx, int winy, rcti *disprect)
 {
        re->ok= TRUE;   /* maybe flag */
        
@@ -1112,58 +1254,77 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy
                                                                                  (re->rectx < 16 || re->recty < 16) )) {
                re->error(re->erh, "Image too small");
                re->ok= 0;
+               return;
        }
-       else {
+
 #ifdef WITH_OPENEXR
-               if(re->r.scemode & R_FULL_SAMPLE)
-                       re->r.scemode |= R_EXR_TILE_FILE;       /* enable automatic */
-#else
-               /* can't do this without openexr support */
+       if(re->r.scemode & R_FULL_SAMPLE)
+               re->r.scemode |= R_EXR_TILE_FILE;       /* enable automatic */
+
+       /* Until use_border is made compatible with save_buffers/full_sample, render without the later instead of not rendering at all.*/
+       if(re->r.mode & R_BORDER) 
+       {
                re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE);
+       }
+
+#else
+       /* can't do this without openexr support */
+       re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE);
 #endif
-               
-               /* fullsample wants uniform osa levels */
-               if(source && (re->r.scemode & R_FULL_SAMPLE)) {
-                       /* but, if source has no full sample we disable it */
-                       if((source->r.scemode & R_FULL_SAMPLE)==0)
-                               re->r.scemode &= ~R_FULL_SAMPLE;
-                       else
-                               re->r.osa= re->osa= source->osa;
+       
+       /* fullsample wants uniform osa levels */
+       if(source && (re->r.scemode & R_FULL_SAMPLE)) {
+               /* but, if source has no full sample we disable it */
+               if((source->r.scemode & R_FULL_SAMPLE)==0)
+                       re->r.scemode &= ~R_FULL_SAMPLE;
+               else
+                       re->r.osa= re->osa= source->osa;
+       }
+       else {
+               /* check state variables, osa? */
+               if(re->r.mode & (R_OSA)) {
+                       re->osa= re->r.osa;
+                       if(re->osa>16) re->osa= 16;
                }
-               else {
-                       /* check state variables, osa? */
-                       if(re->r.mode & (R_OSA)) {
-                               re->osa= re->r.osa;
-                               if(re->osa>16) re->osa= 16;
-                       }
-                       else re->osa= 0;
+               else re->osa= 0;
+       }
+       
+       if (srl) {
+               int index = BLI_findindex(&re->r.layers, srl);
+               if (index != -1) {
+                       re->r.actlay = index;
+                       re->r.scemode |= (R_SINGLE_LAYER|R_COMP_RERENDER);
                }
-
-               /* always call, checks for gamma, gamma tables and jitter too */
-               make_sample_tables(re); 
+       }
                
-               /* if preview render, we try to keep old result */
-               if(re->r.scemode & R_PREVIEWBUTS) {
-                       if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty);
-                       else {
-                               RE_FreeRenderResult(re->result);
-                               re->result= NULL;
-                       }
-               }
+       /* always call, checks for gamma, gamma tables and jitter too */
+       make_sample_tables(re); 
+       
+       /* if preview render, we try to keep old result */
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
+       if(re->r.scemode & R_PREVIEWBUTS) {
+               if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty);
                else {
-                       
-                       /* make empty render result, so display callbacks can initialize */
                        RE_FreeRenderResult(re->result);
-                       re->result= MEM_callocN(sizeof(RenderResult), "new render result");
-                       re->result->rectx= re->rectx;
-                       re->result->recty= re->recty;
+                       re->result= NULL;
                }
+       }
+       else {
                
-               /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */
-               re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx);
-               
-               RE_init_threadcount(re);
+               /* make empty render result, so display callbacks can initialize */
+               RE_FreeRenderResult(re->result);
+               re->result= MEM_callocN(sizeof(RenderResult), "new render result");
+               re->result->rectx= re->rectx;
+               re->result->recty= re->recty;
        }
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
+       
+       /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */
+       re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx);
+       
+       RE_init_threadcount(re);
 }
 
 /* part of external api, not called for regular render pipeline */
@@ -1174,8 +1335,12 @@ void RE_SetDispRect (struct Render *re, rcti *disprect)
        re->recty= disprect->ymax-disprect->ymin;
        
        /* initialize render result */
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
        RE_FreeRenderResult(re->result);
        re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }
 
 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
@@ -1187,7 +1352,7 @@ void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
        re->clipend= clipend;
        re->r.mode &= ~R_ORTHO;
 
-       i_window(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
+       perspective_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend);
        
 }
 
@@ -1200,14 +1365,14 @@ void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
        re->clipend= clipend;
        re->r.mode |= R_ORTHO;
 
-       i_ortho(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
+       orthographic_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend);
 }
 
 void RE_SetView(Render *re, float mat[][4])
 {
        /* re->ok flag? */
-       Mat4CpyMat4(re->viewmat, mat);
-       Mat4Invert(re->viewinv, re->viewmat);
+       copy_m4_m4(re->viewmat, mat);
+       invert_m4_m4(re->viewinv, re->viewmat);
 }
 
 /* image and movie output has to move to either imbuf or kernel */
@@ -1335,11 +1500,15 @@ static void render_tile_processor(Render *re, int firsttile)
        if(re->test_break(re->tbh))
                return;
 
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
        /* hrmf... exception, this is used for preview render, re-entrant, so render result has to be re-used */
        if(re->result==NULL || re->result->layers.first==NULL) {
                if(re->result) RE_FreeRenderResult(re->result);
                re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
        }
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        re->stats_draw(re->sdh, &re->i);
  
@@ -1347,7 +1516,7 @@ static void render_tile_processor(Render *re, int firsttile)
                return;
        
        initparts(re);
-       
+
        /* assuming no new data gets added to dbase... */
        R= *re;
        
@@ -1374,7 +1543,7 @@ static void render_tile_processor(Render *re, int firsttile)
                                break;
                }
        }
-       
+
        freeparts(re);
 }
 
@@ -1430,7 +1599,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
                R.viewplane.xmin = viewplane->xmin + R.panodxv;
                R.viewplane.xmax = viewplane->xmax + R.panodxv;
                RE_SetWindow(re, &R.viewplane, R.clipsta, R.clipend);
-               Mat4CpyMat4(R.winmat, re->winmat);
+               copy_m4_m4(R.winmat, re->winmat);
                
                /* rotate database according to part coordinates */
                project_renderdata(re, projectverto, 1, -R.panodxp*phi, 1);
@@ -1512,17 +1681,21 @@ static void threaded_tile_processor(Render *re)
        rctf viewplane= re->viewplane;
        int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0;
        
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
        /* first step; free the entire render result, make new, and/or prepare exr buffer saving */
        if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
                RE_FreeRenderResult(re->result);
        
-               if(re->sss_points)
+               if(re->sss_points && render_display_draw_enabled(re))
                        re->result= new_render_result(re, &re->disprect, 0, 0);
                else if(re->r.scemode & R_FULL_SAMPLE)
                        re->result= new_full_sample_buffers_exr(re);
                else
                        re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE));
        }
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        if(re->result==NULL)
                return;
@@ -1530,7 +1703,7 @@ static void threaded_tile_processor(Render *re)
        /* warning; no return here without closing exr file */
        
        initparts(re);
-       
+
        if(re->result->exrhandle) {
                RenderResult *rr;
                char str[FILE_MAX];
@@ -1622,6 +1795,7 @@ static void threaded_tile_processor(Render *re)
        if(re->result->exrhandle) {
                RenderResult *rr;
 
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                save_empty_result_tiles(re);
                
                for(rr= re->result; rr; rr= rr->next) {
@@ -1631,6 +1805,8 @@ static void threaded_tile_processor(Render *re)
                
                free_render_result(&re->fullresult, re->result);
                re->result= NULL;
+
+               BLI_rw_mutex_unlock(&re->resultmutex);
                
                read_render_result(re, 0);
        }
@@ -1699,6 +1875,10 @@ static void do_render_3d(Render *re)
                if(!re->test_break(re->tbh))
                        add_halo_flare(re);
        
+       /* Freestyle  */
+       if( re->r.mode & R_EDGE_FRS && re->r.renderer==R_INTERN)
+               FRS_add_Freestyle(re);
+               
        /* free all render verts etc */
        RE_Database_Free(re);
 }
@@ -1793,28 +1973,30 @@ static void do_render_blur_3d(Render *re)
 {
        RenderResult *rres;
        float blurfac;
-       int blur= re->r.osa;
+       int blur= re->r.mblur_samples;
        
        /* create accumulation render result */
        rres= new_render_result(re, &re->disprect, 0, RR_USEMEM);
        
        /* do the blur steps */
        while(blur--) {
-               set_mblur_offs( re->r.blurfac*((float)(re->r.osa-blur))/(float)re->r.osa );
+               set_mblur_offs( re->r.blurfac*((float)(re->r.mblur_samples-blur))/(float)re->r.mblur_samples );
                
-               re->i.curblur= re->r.osa-blur;  /* stats */
+               re->i.curblur= re->r.mblur_samples-blur;        /* stats */
                
                do_render_3d(re);
                
-               blurfac= 1.0f/(float)(re->r.osa-blur);
+               blurfac= 1.0f/(float)(re->r.mblur_samples-blur);
                
                merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
                if(re->test_break(re->tbh)) break;
        }
        
        /* swap results */
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        RE_FreeRenderResult(re->result);
        re->result= rres;
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        set_mblur_offs(0.0f);
        re->i.curblur= 0;       /* stats */
@@ -1884,8 +2066,11 @@ static void do_render_fields_3d(Render *re)
                do_render_blur_3d(re);
        else
                do_render_3d(re);
+
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        rr1= re->result;
        re->result= NULL;
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        /* second field */
        if(!re->test_break(re->tbh)) {
@@ -1911,8 +2096,10 @@ static void do_render_fields_3d(Render *re)
        re->recty *= 2;
        re->disprect.ymin *= 2;
        re->disprect.ymax *= 2;
+
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
-       
+
        if(rr2) {
                if(re->r.mode & R_ODDFIELD)
                        merge_renderresult_fields(re->result, rr2, rr1);
@@ -1921,12 +2108,16 @@ static void do_render_fields_3d(Render *re)
                
                RE_FreeRenderResult(rr2);
        }
+
        RE_FreeRenderResult(rr1);
        
        re->i.curfield= 0;      /* stats */
        
        /* weak... the display callback wants an active renderlayer pointer... */
        re->result->renlay= render_get_active_layer(re, re->result);
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
+
        re->display_draw(re->ddh, re->result, NULL);
 }
 
@@ -1938,7 +2129,7 @@ static void load_backbuffer(Render *re)
                
                strcpy(name, re->r.backbuf);
                BLI_convertstringcode(name, G.sce);
-               BLI_convertstringframe(name, re->r.cfra);
+               BLI_convertstringframe(name, re->r.cfra, 0);
                
                if(re->backbuf) {
                        re->backbuf->id.us--;
@@ -1990,6 +2181,8 @@ static void do_render_fields_blur_3d(Render *re)
                        if((re->r.mode & R_CROP)==0) {
                                RenderResult *rres;
                                
+                               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
                                /* sub-rect for merge call later on */
                                re->result->tilerect= re->disprect;
                                
@@ -2010,9 +2203,16 @@ static void do_render_fields_blur_3d(Render *re)
                                /* weak... the display callback wants an active renderlayer pointer... */
                                re->result->renlay= render_get_active_layer(re, re->result);
                                
+                               BLI_rw_mutex_unlock(&re->resultmutex);
+               
                                re->display_init(re->dih, re->result);
                                re->display_draw(re->ddh, re->result, NULL);
                        }
+                       else {
+                               /* set offset (again) for use in compositor, disprect was manipulated. */
+                               re->result->xof= 0;
+                               re->result->yof= 0;
+                       }
                }
        }
 }
@@ -2023,7 +2223,7 @@ static void do_render_fields_blur_3d(Render *re)
 */
 static void render_scene(Render *re, Scene *sce, int cfra)
 {
-       Render *resc= RE_NewRender(sce->id.name);
+       Render *resc= RE_NewRender(sce->id.name, RE_SLOT_RENDERING);
        int winx= re->winx, winy= re->winy;
        
        sce->r.cfra= cfra;
@@ -2035,7 +2235,7 @@ static void render_scene(Render *re, Scene *sce, int cfra)
        }
        
        /* initial setup */
-       RE_InitState(resc, re, &sce->r, winx, winy, &re->disprect);
+       RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect);
        
        /* still unsure entity this... */
        resc->scene= sce;
@@ -2150,7 +2350,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                        Render *re1;
                        
                        tag_scenes_for_render(re);
-                       for(re1= RenderList.first; re1; re1= re1->next) {
+                       for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
                                if(re1->scene->id.flag & LIB_DOIT)
                                        if(re1->r.scemode & R_FULL_SAMPLE)
                                                read_render_result(re1, sample);
@@ -2166,7 +2366,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                }
                
                /* ensure we get either composited result or the active layer */
-               RE_GetResultImage(re, &rres);
+               RE_AcquireResultImage(re, &rres);
                
                /* accumulate with filter, and clip */
                mask= (1<<sample);
@@ -2177,6 +2377,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                        float *col= rres.rectf + 4*y*re->rectx;
                                
                        for(x=0; x<re->rectx; x++, rf+=4, col+=4) {
+                               /* clamping to 1.0 is needed for correct AA */
                                if(col[0]<0.0f) col[0]=0.0f; else if(col[0] > 1.0f) col[0]= 1.0f;
                                if(col[1]<0.0f) col[1]=0.0f; else if(col[1] > 1.0f) col[1]= 1.0f;
                                if(col[2]<0.0f) col[2]=0.0f; else if(col[2] > 1.0f) col[2]= 1.0f;
@@ -2185,6 +2386,8 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                        }
                }
                
+               RE_ReleaseResultImage(re);
+
                /* show stuff */
                if(sample!=re->osa-1) {
                        /* weak... the display callback wants an active renderlayer pointer... */
@@ -2196,9 +2399,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                        break;
        }
        
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        if(re->result->rectf) 
                MEM_freeN(re->result->rectf);
        re->result->rectf= rectf;
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }
 
 void RE_MergeFullSample(Render *re, Scene *sce, bNodeTree *ntree)
@@ -2240,6 +2445,7 @@ void RE_MergeFullSample(Render *re, Scene *sce, bNodeTree *ntree)
 static void do_render_composite_fields_blur_3d(Render *re)
 {
        bNodeTree *ntree= re->scene->nodetree;
+       int update_newframe=0;
        
        /* INIT seeding, compositor can use random texture */
        BLI_srandom(re->r.cfra);
@@ -2249,6 +2455,9 @@ static void do_render_composite_fields_blur_3d(Render *re)
                ntreeFreeCache(ntree);
                
                do_render_fields_blur_3d(re);
+       } else {
+               /* scene render process already updates animsys */
+               update_newframe = 1;
        }
        
        /* swap render result */
@@ -2274,12 +2483,17 @@ static void do_render_composite_fields_blur_3d(Render *re)
                                        ntree->sdh= re->sdh;
                                        ntree->tbh= re->tbh;
                                        /* in case it was never initialized */
+                                       R.sdh= re->sdh;
                                        R.stats_draw= re->stats_draw;
                                        
+                                       if (update_newframe)
+                                               scene_update_for_newframe(re->scene, re->scene->lay);
+                                       
                                        if(re->r.scemode & R_FULL_SAMPLE) 
                                                do_merge_fullsample(re, ntree);
-                                       else
+                                       else {
                                                ntreeCompositExecTree(ntree, &re->r, G.background==0);
+                                       }
                                        
                                        ntree->stats_draw= NULL;
                                        ntree->test_break= NULL;
@@ -2299,9 +2513,12 @@ static void do_render_composite_fields_blur_3d(Render *re)
 static void renderresult_stampinfo(Scene *scene)
 {
        RenderResult rres;
+       Render *re= RE_GetRender(scene->id.name, RE_SLOT_RENDERING);
+
        /* this is the basic trick to get the displayed float or char rect from render result */
-       RE_GetResultImage(RE_GetRender(scene->id.name), &rres);
+       RE_AcquireResultImage(re, &rres);
        BKE_stamp_buf(scene, (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
+       RE_ReleaseResultImage(re);
 }
 
 static void do_render_seq(Render * re)
@@ -2311,12 +2528,19 @@ static void do_render_seq(Render * re)
        RenderResult *rr = re->result;
        int cfra = re->r.cfra;
 
+       if(recurs_depth==0) {
+               /* otherwise sequencer animation isnt updated */
+               BKE_animsys_evaluate_all_animation(G.main, (float)cfra); // XXX, was frame_to_float(re->scene, cfra)
+       }
+
        recurs_depth++;
 
        ibuf= give_ibuf_seq(re->scene, rr->rectx, rr->recty, cfra, 0, 100.0);
 
        recurs_depth--;
        
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+
        if(ibuf) {
                if(ibuf->rect_float) {
                        if (!rr->rectf)
@@ -2346,7 +2570,7 @@ static void do_render_seq(Render * re)
                if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
                        Editing * ed = re->scene->ed;
                        if (ed) {
-                               free_imbuf_seq(&ed->seqbase, TRUE);
+                               free_imbuf_seq(re->scene, &ed->seqbase, TRUE);
                        }
                }
        }
@@ -2359,6 +2583,8 @@ static void do_render_seq(Render * re)
                else
                        rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
        }
+
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -2366,6 +2592,12 @@ static void do_render_seq(Render * re)
 /* main loop: doing sequence + fields + blur + 3d render + compositing */
 static void do_render_all_options(Render *re)
 {
+#ifdef DURIAN_CAMERA_SWITCH
+       Object *camera= scene_find_camera_switch(re->scene);
+       if(camera)
+               re->scene->camera= camera;
+#endif
+
        re->i.starttime= PIL_check_seconds_timer();
 
        /* ensure no images are in memory from previous animated sequences */
@@ -2378,14 +2610,15 @@ static void do_render_all_options(Render *re)
                
                re->stats_draw(re->sdh, &re->i);
                re->display_draw(re->ddh, re->result, NULL);
-               
        }
        else {
                do_render_composite_fields_blur_3d(re);
        }
        
        /* for UI only */
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        renderresult_add_names(re->result);
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
        
@@ -2420,10 +2653,6 @@ static int is_rendering_allowed(Render *re)
                        re->error(re->erh, "No border area selected.");
                        return 0;
                }
-               if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) {
-                       re->error(re->erh, "Border render and Buffer-save not supported yet");
-                       return 0;
-               }
        }
        
        if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) {
@@ -2523,7 +2752,7 @@ static void update_physics_cache(Render *re, Scene *scene, int anim_init)
        BKE_ptcache_make_cache(&baker);
 }
 /* evaluating scene options for general Blender render */
-static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int anim_init)
+static int render_initialize_from_scene(Render *re, Scene *scene, SceneRenderLayer *srl, int anim, int anim_init)
 {
        int winx, winy;
        rcti disprect;
@@ -2570,10 +2799,10 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int
                update_physics_cache(re, scene, anim_init);
        }
        
-       if(scene->r.scemode & R_SINGLE_LAYER)
+       if(srl || scene->r.scemode & R_SINGLE_LAYER)
                push_render_result(re);
        
-       RE_InitState(re, NULL, &scene->r, winx, winy, &disprect);
+       RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect);
        if(!re->ok)  /* if an error was printed, abort */
                return 0;
        
@@ -2590,29 +2819,32 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim, int
 }
 
 /* general Blender frame render call */
-void RE_BlenderFrame(Render *re, Scene *scene, int frame)
+void RE_BlenderFrame(Render *re, Scene *scene, SceneRenderLayer *srl, int frame)
 {
        /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
-       G.rendering= 1;
+       RenderGlobal.renderingslot= re->slot;
        re->result_ok= 0;
+       G.rendering= 1;
        
        scene->r.cfra= frame;
        
-       if(render_initialize_from_scene(re, scene, 0, 0)) {
+       if(render_initialize_from_scene(re, scene, srl, 0, 0)) {
                do_render_all_options(re);
        }
        
        /* UGLY WARNING */
-       G.rendering= 0;
        re->result_ok= 1;
+       G.rendering= 0;
+       RenderGlobal.renderingslot= RenderGlobal.viewslot;
 }
 
-static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
+static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports)
 {
        char name[FILE_MAX];
        RenderResult rres;
+       int ok= 1;
        
-       RE_GetResultImage(re, &rres);
+       RE_AcquireResultImage(re, &rres);
 
        /* write movie or image */
        if(BKE_imtype_is_movie(scene->r.imtype)) {
@@ -2623,14 +2855,14 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
                        dofree = 1;
                }
                RE_ResultGet32(re, (unsigned int *)rres.rect32);
-               mh->append_movie(&re->r, scene->r.cfra, rres.rect32, rres.rectx, rres.recty);
+               ok= mh->append_movie(&re->r, scene->r.cfra, rres.rect32, rres.rectx, rres.recty, reports);
                if(dofree) {
                        MEM_freeN(rres.rect32);
                }
                printf("Append frame %d", scene->r.cfra);
        } 
        else {
-               BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype);
+               BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION);
                
                if(re->r.imtype==R_MULTILAYER) {
                        if(re->result) {
@@ -2640,7 +2872,6 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
                }
                else {
                        ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
-                       int ok;
                        
                        /* if not exists, BKE_write_ibuf makes one */
                        ibuf->rect= (unsigned int *)rres.rect32;    
@@ -2649,15 +2880,23 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
                        
                        /* float factor for random dither, imbuf takes care of it */
                        ibuf->dither= scene->r.dither_intensity;
-                       /* gamma correct to sRGB color space */
-                       if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
-                               ibuf->profile = IB_PROFILE_SRGB;
+                       
+                       /* prepare to gamma correct to sRGB color space */
+                       if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
+                               /* sequence editor can generate 8bpc render buffers */
+                               if (ibuf->rect) {
+                                       ibuf->profile = IB_PROFILE_SRGB;
+                                       if (ELEM(scene->r.imtype, R_OPENEXR, R_RADHDR))
+                                               IMB_float_from_rect(ibuf);
+                               } else {                                
+                                       ibuf->profile = IB_PROFILE_LINEAR_RGB;
+                               }
+                       }
 
                        ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
                        
                        if(ok==0) {
                                printf("Render error: cannot save %s\n", name);
-                               G.afbreek=1;
                        }
                        else printf("Saved: %s", name);
                        
@@ -2665,7 +2904,7 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
                        if(ok && scene->r.imtype==R_OPENEXR && (scene->r.subimtype & R_PREVIEW_JPG)) {
                                if(BLI_testextensie(name, ".exr")) 
                                        name[strlen(name)-4]= 0;
-                               BKE_add_image_extension(scene, name, R_JPEG90);
+                               BKE_add_image_extension(name, R_JPEG90);
                                ibuf->depth= 24; 
                                BKE_write_ibuf(scene, ibuf, name, R_JPEG90, scene->r.subimtype, scene->r.quality);
                                printf("\nSaved: %s", name);
@@ -2676,13 +2915,17 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
                }
        }
        
+       RE_ReleaseResultImage(re);
+
        BLI_timestr(re->i.lastframetime, name);
        printf(" Time: %s\n", name);
        fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
+
+       return ok;
 }
 
 /* saves images to disk */
-void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
+void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra, ReportList *reports)
 {
        bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype);
        unsigned int lay;
@@ -2690,30 +2933,34 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
        int nfra;
        
        /* do not fully call for each frame, it initializes & pops output window */
-       if(!render_initialize_from_scene(re, scene, 0, 1))
+       if(!render_initialize_from_scene(re, scene, NULL, 0, 1))
                return;
        
        /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
        /* is also set by caller renderwin.c */
        G.rendering= 1;
+       RenderGlobal.renderingslot= re->slot;
        re->result_ok= 0;
        
        if(BKE_imtype_is_movie(scene->r.imtype))
-               mh->start_movie(scene, &re->r, re->rectx, re->recty);
-       
+               if(!mh->start_movie(scene, &re->r, re->rectx, re->recty, reports))
+                       G.afbreek= 1;
+
        if (mh->get_next_frame) {
                while (!(G.afbreek == 1)) {
-                       int nf = mh->get_next_frame(&re->r);
+                       int nf = mh->get_next_frame(&re->r, reports);
                        if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) {
                                scene->r.cfra = re->r.cfra = nf;
                                
                                do_render_all_options(re);
 
                                if(re->test_break(re->tbh) == 0) {
-                                       do_write_image_or_movie(re, scene, mh);
+                                       if(!do_write_image_or_movie(re, scene, mh, reports))
+                                               G.afbreek= 1;
                                }
                        } else {
-                               re->test_break(re->tbh);
+                               if(re->test_break(re->tbh))
+                                       G.afbreek= 1;
                        }
                }
        } else {
@@ -2721,7 +2968,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
                        char name[FILE_MAX];
                        
                        /* only border now, todo: camera lens. (ton) */
-                       render_initialize_from_scene(re, scene, 1, 0);
+                       render_initialize_from_scene(re, scene, NULL, 1, 0);
 
                        if(nfra!=scene->r.cfra) {
                                /*
@@ -2743,7 +2990,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
                        /* Touch/NoOverwrite options are only valid for image's */
                        if(BKE_imtype_is_movie(scene->r.imtype) == 0) {
                                if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
-                                       BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype);
+                                       BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION);
 
                                if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) {
                                        printf("skipping existing frame \"%s\"\n", name);
@@ -2760,8 +3007,12 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
                        do_render_all_options(re);
                        
                        if(re->test_break(re->tbh) == 0) {
-                               do_write_image_or_movie(re, scene, mh);
+                               if(!G.afbreek)
+                                       if(!do_write_image_or_movie(re, scene, mh, reports))
+                                               G.afbreek= 1;
                        }
+                       else
+                               G.afbreek= 1;
                
                        if(G.afbreek==1) {
                                /* remove touched file */
@@ -2785,6 +3036,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra)
        /* UGLY WARNING */
        G.rendering= 0;
        re->result_ok= 1;
+       RenderGlobal.renderingslot= RenderGlobal.viewslot;
 }
 
 /* note; repeated win/disprect calc... solve that nicer, also in compo */
@@ -2818,10 +3070,10 @@ void RE_ReadRenderResult(Scene *scene, Scene *scenode)
                scene= scenode;
        
        /* get render: it can be called from UI with draw callbacks */
-       re= RE_GetRender(scene->id.name);
+       re= RE_GetRender(scene->id.name, RE_SLOT_VIEW);
        if(re==NULL)
-               re= RE_NewRender(scene->id.name);
-       RE_InitState(re, NULL, &scene->r, winx, winy, &disprect);
+               re= RE_NewRender(scene->id.name, RE_SLOT_VIEW);
+       RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
        re->scene= scene;
        
        read_render_result(re, 0);
@@ -2830,9 +3082,9 @@ void RE_ReadRenderResult(Scene *scene, Scene *scenode)
 void RE_set_max_threads(int threads)
 {
        if (threads==0) {
-               commandline_threads = BLI_system_thread_count();
+               RenderGlobal.threads = BLI_system_thread_count();
        } else if(threads>=1 && threads<=BLENDER_MAX_THREADS) {
-               commandline_threads= threads;
+               RenderGlobal.threads= threads;
        } else {
                printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS);
        }
@@ -2840,9 +3092,9 @@ void RE_set_max_threads(int threads)
 
 void RE_init_threadcount(Render *re) 
 {
-        if(commandline_threads >= 1) { /* only set as an arg in background mode */
-               re->r.threads= MIN2(commandline_threads, BLENDER_MAX_THREADS);
-       } else if ((re->r.mode & R_FIXED_THREADS)==0 || commandline_threads == 0) { /* Automatic threads */
+       if(RenderGlobal.threads >= 1) { /* only set as an arg in background mode */
+               re->r.threads= MIN2(RenderGlobal.threads, BLENDER_MAX_THREADS);
+       } else if ((re->r.mode & R_FIXED_THREADS)==0 || RenderGlobal.threads == 0) { /* Automatic threads */
                re->r.threads = BLI_system_thread_count();
        }
 }
@@ -2944,7 +3196,7 @@ void RE_engine_update_stats(RenderEngine *engine, char *stats, char *info)
 
 /* loads in image into a result, size must match
  * x/y offsets are only used on a partial copy when dimensions dont match */
-void RE_layer_rect_from_file(RenderLayer *layer, ReportList *reports, char *filename, int x, int y)
+void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, char *filename)
 {
        ImBuf *ibuf = IMB_loadiffname(filename, IB_rect);
 
@@ -2955,7 +3207,7 @@ void RE_layer_rect_from_file(RenderLayer *layer, ReportList *reports, char *file
 
                        memcpy(layer->rectf, ibuf->rect_float, sizeof(float)*4*layer->rectx*layer->recty);
                } else {
-                       if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
+                       if ((ibuf->x >= layer->rectx) && (ibuf->y >= layer->recty)) {
                                ImBuf *ibuf_clip;
 
                                if(ibuf->rect_float==NULL)
@@ -2963,7 +3215,7 @@ void RE_layer_rect_from_file(RenderLayer *layer, ReportList *reports, char *file
 
                                ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat, 0);
                                if(ibuf_clip) {
-                                       IMB_rectcpy(ibuf_clip, ibuf, 0,0, x,y, layer->rectx, layer->recty);
+                                       IMB_rectcpy(ibuf_clip, ibuf, 0,0, 0,0, layer->rectx, layer->recty);
 
                                        memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float)*4*layer->rectx*layer->recty);
                                        IMB_freeImBuf(ibuf_clip);
@@ -2983,10 +3235,20 @@ void RE_layer_rect_from_file(RenderLayer *layer, ReportList *reports, char *file
                BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
        }
 }
+
+void RE_result_load_from_file(RenderResult *result, ReportList *reports, char *filename)
+{
+       if(!read_render_result_from_file(filename, result)) {
+               BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
+               return;
+       }
+}
+
 static void external_render_3d(Render *re, RenderEngineType *type)
 {
        RenderEngine engine;
 
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
                RE_FreeRenderResult(re->result);
        
@@ -2995,6 +3257,7 @@ static void external_render_3d(Render *re, RenderEngineType *type)
                else
                        re->result= new_render_result(re, &re->disprect, 0, 0); // XXX re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE));
        }
+       BLI_rw_mutex_unlock(&re->resultmutex);
        
        if(re->result==NULL)
                return;
@@ -3008,6 +3271,7 @@ static void external_render_3d(Render *re, RenderEngineType *type)
 
        free_render_result(&engine.fullresult, engine.fullresult.first);
 
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        if(re->result->exrhandle) {
                RenderResult *rr;
 
@@ -3023,5 +3287,6 @@ static void external_render_3d(Render *re, RenderEngineType *type)
                
                read_render_result(re, 0);
        }
+       BLI_rw_mutex_unlock(&re->resultmutex);
 }