Code refactoring: split render result related functions into separate file.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 5 Jan 2012 17:50:09 +0000 (17:50 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 5 Jan 2012 17:50:09 +0000 (17:50 +0000)
source/blender/render/CMakeLists.txt
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_result.h [new file with mode: 0644]
source/blender/render/intern/include/renderpipeline.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/render_result.c [new file with mode: 0644]
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/zbuf.c

index c7b27c3cd7ea6694dc36224076a260160553de66..51c5d49208e5811587a82317021f200aea13b5ed 100644 (file)
@@ -66,6 +66,7 @@ set(SRC
        intern/source/pointdensity.c
        intern/source/rayshade.c
        intern/source/rendercore.c
+       intern/source/render_result.c
        intern/source/render_texture.c
        intern/source/renderdatabase.c
        intern/source/shadbuf.c
@@ -96,6 +97,7 @@ set(SRC
        intern/include/rayintersection.h
        intern/include/raycounter.h
        intern/include/render_types.h
+       intern/include/render_result.h
        intern/include/rendercore.h
        intern/include/renderdatabase.h
        intern/include/renderpipeline.h
index 600d1a3c377a5cdd3d4f0417c51ac2b2d7cb556c..cc4136fcccc80e7b55d2e7f1507c21fda9df0377 100644 (file)
@@ -182,9 +182,6 @@ float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype);
 /* obligatory initialize call, disprect is optional */
 void RE_InitState (struct Render *re, struct Render *source, struct RenderData *rd, struct SceneRenderLayer *srl, int winx, int winy, rcti *disprect);
 
-/* use this to change disprect of active render */
-void RE_SetDispRect (struct Render *re, rcti *disprect);
-
 /* set up the viewplane/perspective matrix, three choices */
 struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
 void RE_SetCamera(struct Render *re, struct Object *camera);
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
new file mode 100644 (file)
index 0000000..93cbc6f
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/render/intern/include/render_result.h
+ *  \ingroup render
+ */
+
+#ifndef RENDER_RESULT_H
+#define RENDER_RESULT_H
+
+#define PASS_VECTOR_MAX        10000.0f
+
+#define RR_USE_MEM             0
+#define RR_USE_EXR             1
+
+struct ImBuf;
+struct ListBase;
+struct Render;
+struct RenderData;
+struct RenderLayer;
+struct RenderResult;
+struct Scene;
+struct rcti;
+
+/* New */
+
+struct RenderResult *render_result_new(struct Render *re,
+       struct rcti *partrct, int crop, int savebuffers);
+struct RenderResult *render_result_new_full_sample(struct Render *re,
+       struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers);
+
+struct RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty);
+
+/* Merge */
+
+void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
+
+/* Free */
+
+void render_result_free(struct RenderResult *rr);
+void render_result_free_list(struct ListBase *lb, struct RenderResult *rr);
+
+/* Single Layer Render */
+
+void render_result_single_layer_begin(struct Render *re);
+void render_result_single_layer_end(struct Render *re);
+
+/* EXR Tile File Render */
+
+void render_result_exr_file_begin(struct Render *re);
+void render_result_exr_file_end(struct Render *re);
+
+void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart);
+
+void render_result_exr_file_path(struct Scene *scene, int sample, char *filepath);
+int render_result_exr_file_read(struct Render *re, int sample);
+int render_result_exr_file_read_path(struct RenderResult *rr, const char *filepath);
+
+/* Combined Pixel Rect */
+
+struct ImBuf *render_result_rect_to_ibuf(struct RenderResult *rr, struct RenderData *rd);
+void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd,
+       struct ImBuf *ibuf);
+
+void render_result_rect_fill_zero(struct RenderResult *rr);
+void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd,
+       unsigned int *rect, int rectx, int recty);
+
+#endif /* RENDER_RESULT_H */
+
index fc46ea833097971d2e4efd0d5efeb39096af7667..9a87cf840125dfab68dad5ff6f44f65a6d62f446 100644 (file)
 #ifndef PIPELINE_H
 #define PIPELINE_H
 
-struct ListBase;
 struct Render;
-struct RenderResult;
 struct RenderLayer;
-struct rcti;
+struct RenderResult;
 
 struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr);
 float panorama_pixel_rot(struct Render *re);
 
-#define PASS_VECTOR_MAX        10000.0f
-
-#define RR_USEMEM      0
-
-struct RenderResult *new_render_result(struct Render *re, struct rcti *partrct, int crop, int savebuffers);
-void merge_render_result(struct RenderResult *rr, struct RenderResult *rrpart);
-void free_render_result(struct ListBase *lb, struct RenderResult *rr);
-
 #endif /* PIPELINE_H */
 
index 78215498a4745422334b08d90850ade1e45dd932..703ca23c15b1dd6e9e13ddf01940d3e0bea3e20c 100644 (file)
@@ -54,7 +54,7 @@
 #include "RE_pipeline.h"
 
 #include "render_types.h"
-#include "renderpipeline.h"
+#include "render_result.h"
 
 /* Render Engine Types */
 
@@ -168,7 +168,7 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
        disprect.ymin= y;
        disprect.ymax= y+h;
 
-       result= new_render_result(re, &disprect, 0, RR_USEMEM);
+       result= render_result_new(re, &disprect, 0, RR_USE_MEM);
        BLI_addtail(&engine->fullresult, result);
        
        result->tilerect.xmin += re->disprect.xmin;
@@ -198,7 +198,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
 
        /* merge. on break, don't merge in result for preview renders, looks nicer */
        if(!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
-               merge_render_result(re->result, result);
+               render_result_merge(re->result, result);
 
        /* draw */
        if(!re->test_break(re->tbh)) {
@@ -207,7 +207,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
        }
 
        /* free */
-       free_render_result(&engine->fullresult, result);
+       render_result_free_list(&engine->fullresult, result);
 }
 
 /* Cancel */
@@ -286,8 +286,9 @@ int RE_engine_render(Render *re, int do_all)
        /* create render result */
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
-               RE_FreeRenderResult(re->result);
-               re->result= new_render_result(re, &re->disprect, 0, 0);
+               if(re->result)
+                       render_result_free(re->result);
+               re->result= render_result_new(re, &re->disprect, 0, 0);
        }
        BLI_rw_mutex_unlock(&re->resultmutex);
        
@@ -316,7 +317,7 @@ int RE_engine_render(Render *re, int do_all)
        if(type->render)
                type->render(engine, re->scene);
 
-       free_render_result(&engine->fullresult, engine->fullresult.first);
+       render_result_free_list(&engine->fullresult, engine->fullresult.first);
 
        RE_engine_free(engine);
 
index 0068407a7df140a12c61644d952bdea2aa548aa6..f82287e86452ec514ceb6afc6778c10efa0ba8ff 100644 (file)
@@ -78,6 +78,7 @@
 #include "RE_pipeline.h"
 
 /* internal */
+#include "render_result.h"
 #include "render_types.h"
 #include "renderpipeline.h"
 #include "renderdatabase.h"
@@ -184,345 +185,7 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
 
 void RE_FreeRenderResult(RenderResult *res)
 {
-       if(res==NULL) return;
-
-       while(res->layers.first) {
-               RenderLayer *rl= res->layers.first;
-               
-               if(rl->rectf) MEM_freeN(rl->rectf);
-               /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
-               if(rl->acolrect) MEM_freeN(rl->acolrect);
-               if(rl->scolrect) MEM_freeN(rl->scolrect);
-               
-               while(rl->passes.first) {
-                       RenderPass *rpass= rl->passes.first;
-                       if(rpass->rect) MEM_freeN(rpass->rect);
-                       BLI_remlink(&rl->passes, rpass);
-                       MEM_freeN(rpass);
-               }
-               BLI_remlink(&res->layers, rl);
-               MEM_freeN(rl);
-       }
-       
-       if(res->rect32)
-               MEM_freeN(res->rect32);
-       if(res->rectz)
-               MEM_freeN(res->rectz);
-       if(res->rectf)
-               MEM_freeN(res->rectf);
-       if(res->text)
-               MEM_freeN(res->text);
-       
-       MEM_freeN(res);
-}
-
-/* version that's compatible with fullsample buffers */
-void free_render_result(ListBase *lb, RenderResult *rr)
-{
-       RenderResult *rrnext;
-       
-       for(; rr; rr= rrnext) {
-               rrnext= rr->next;
-               
-               if(lb && lb->first)
-                       BLI_remlink(lb, rr);
-               
-               RE_FreeRenderResult(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;
-                       RenderLayer *rlpush;
-                       RenderLayer *rl= re->result->layers.first;
-                       int nr;
-                       
-                       /* render result should be empty after this */
-                       BLI_remlink(&re->result->layers, rl);
-                       
-                       /* reconstruct render result layers */
-                       for(nr=0, srl= re->scene->r.layers.first; srl; srl= srl->next, nr++) {
-                               if(nr==re->r.actlay)
-                                       BLI_addtail(&re->result->layers, rl);
-                               else {
-                                       rlpush= RE_GetRenderLayer(re->pushedresult, srl->name);
-                                       if(rlpush) {
-                                               BLI_remlink(&re->pushedresult->layers, rlpush);
-                                               BLI_addtail(&re->result->layers, rlpush);
-                                       }
-                               }
-                       }
-               }
-               
-               RE_FreeRenderResult(re->pushedresult);
-               re->pushedresult= NULL;
-
-               BLI_rw_mutex_unlock(&re->resultmutex);
-       }
-}
-
-/* NOTE: OpenEXR only supports 32 chars for layer+pass names
-   In blender we now use max 10 chars for pass, max 20 for layer */
-static const char *get_pass_name(int passtype, int channel)
-{
-       
-       if(passtype == SCE_PASS_COMBINED) {
-               if(channel==-1) return "Combined";
-               if(channel==0) return "Combined.R";
-               if(channel==1) return "Combined.G";
-               if(channel==2) return "Combined.B";
-               return "Combined.A";
-       }
-       if(passtype == SCE_PASS_Z) {
-               if(channel==-1) return "Depth";
-               return "Depth.Z";
-       }
-       if(passtype == SCE_PASS_VECTOR) {
-               if(channel==-1) return "Vector";
-               if(channel==0) return "Vector.X";
-               if(channel==1) return "Vector.Y";
-               if(channel==2) return "Vector.Z";
-               return "Vector.W";
-       }
-       if(passtype == SCE_PASS_NORMAL) {
-               if(channel==-1) return "Normal";
-               if(channel==0) return "Normal.X";
-               if(channel==1) return "Normal.Y";
-               return "Normal.Z";
-       }
-       if(passtype == SCE_PASS_UV) {
-               if(channel==-1) return "UV";
-               if(channel==0) return "UV.U";
-               if(channel==1) return "UV.V";
-               return "UV.A";
-       }
-       if(passtype == SCE_PASS_RGBA) {
-               if(channel==-1) return "Color";
-               if(channel==0) return "Color.R";
-               if(channel==1) return "Color.G";
-               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";
-               if(channel==1) return "Diffuse.G";
-               return "Diffuse.B";
-       }
-       if(passtype == SCE_PASS_SPEC) {
-               if(channel==-1) return "Spec";
-               if(channel==0) return "Spec.R";
-               if(channel==1) return "Spec.G";
-               return "Spec.B";
-       }
-       if(passtype == SCE_PASS_SHADOW) {
-               if(channel==-1) return "Shadow";
-               if(channel==0) return "Shadow.R";
-               if(channel==1) return "Shadow.G";
-               return "Shadow.B";
-       }
-       if(passtype == SCE_PASS_AO) {
-               if(channel==-1) return "AO";
-               if(channel==0) return "AO.R";
-               if(channel==1) return "AO.G";
-               return "AO.B";
-       }
-       if(passtype == SCE_PASS_ENVIRONMENT) {
-               if(channel==-1) return "Env";
-               if(channel==0) return "Env.R";
-               if(channel==1) return "Env.G";
-               return "Env.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";
-               if(channel==1) return "Reflect.G";
-               return "Reflect.B";
-       }
-       if(passtype == SCE_PASS_REFRACT) {
-               if(channel==-1) return "Refract";
-               if(channel==0) return "Refract.R";
-               if(channel==1) return "Refract.G";
-               return "Refract.B";
-       }
-       if(passtype == SCE_PASS_INDEXOB) {
-               if(channel==-1) return "IndexOB";
-               return "IndexOB.X";
-       }
-       if(passtype == SCE_PASS_INDEXMA) {
-               if(channel==-1) return "IndexMA";
-               return "IndexMA.X";
-       }
-       if(passtype == SCE_PASS_MIST) {
-               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";
-}
-
-static int passtype_from_name(const char *str)
-{
-       
-       if(strcmp(str, "Combined")==0)
-               return SCE_PASS_COMBINED;
-
-       if(strcmp(str, "Depth")==0)
-               return SCE_PASS_Z;
-
-       if(strcmp(str, "Vector")==0)
-               return SCE_PASS_VECTOR;
-
-       if(strcmp(str, "Normal")==0)
-               return SCE_PASS_NORMAL;
-
-       if(strcmp(str, "UV")==0)
-               return SCE_PASS_UV;
-
-       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;
-
-       if(strcmp(str, "Spec")==0)
-               return SCE_PASS_SPEC;
-
-       if(strcmp(str, "Shadow")==0)
-               return SCE_PASS_SHADOW;
-       
-       if(strcmp(str, "AO")==0)
-               return SCE_PASS_AO;
-
-       if(strcmp(str, "Env")==0)
-               return SCE_PASS_ENVIRONMENT;
-
-       if(strcmp(str, "Indirect")==0)
-               return SCE_PASS_INDIRECT;
-
-       if(strcmp(str, "Reflect")==0)
-               return SCE_PASS_REFLECT;
-
-       if(strcmp(str, "Refract")==0)
-               return SCE_PASS_REFRACT;
-
-       if(strcmp(str, "IndexOB")==0)
-               return SCE_PASS_INDEXOB;
-
-       if(strcmp(str, "IndexMA")==0)
-               return SCE_PASS_INDEXMA;
-
-       if(strcmp(str, "Mist")==0)
-               return SCE_PASS_MIST;
-       
-       if(strcmp(str, "RayHits")==0)
-               return SCE_PASS_RAYHITS;
-       return 0;
-}
-
-static void scene_unique_exr_name(Scene *scene, char *str, int sample)
-{
-       char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE];
-       
-       BLI_strncpy(di, G.main->name, FILE_MAX);
-       BLI_splitdirstring(di, fi);
-       
-       if(sample==0)
-               BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name+2);
-       else
-               BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name+2, sample);
-
-       BLI_make_file_string("/", str, BLI_temporary_dir(), name);
-}
-
-static void render_unique_exr_name(Render *re, char *str, int sample)
-{
-       scene_unique_exr_name(re->scene, str, sample);
-}
-
-static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
-{
-       const char *typestr= get_pass_name(passtype, 0);
-       RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr);
-       int rectsize= rr->rectx*rr->recty*channels;
-       
-       BLI_addtail(&rl->passes, rpass);
-       rpass->passtype= passtype;
-       rpass->channels= channels;
-       rpass->rectx= rl->rectx;
-       rpass->recty= rl->recty;
-       
-       if(rr->exrhandle) {
-               int a;
-               for(a=0; a<channels; a++)
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
-       }
-       else {
-               float *rect;
-               int x;
-               
-               rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
-               
-               if(passtype==SCE_PASS_VECTOR) {
-                       /* initialize to max speed */
-                       rect= rpass->rect;
-                       for(x= rectsize-1; x>=0; x--)
-                               rect[x]= PASS_VECTOR_MAX;
-               }
-               else if(passtype==SCE_PASS_Z) {
-                       rect= rpass->rect;
-                       for(x= rectsize-1; x>=0; x--)
-                               rect[x]= 10e10;
-               }
-       }
+       render_result_free(res);
 }
 
 float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype)
@@ -547,140 +210,19 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
        return NULL;
 }
 
-/* called by main render as well for parts */
-/* will read info from Render *re to define layers */
-/* called in threads */
-/* re->winx,winy is coordinate space of entire image, partrct the part within */
-RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int savebuffers)
+RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty)
 {
-       RenderResult *rr;
-       RenderLayer *rl;
-       SceneRenderLayer *srl;
-       int rectx, recty, nr;
-       
-       rectx= partrct->xmax - partrct->xmin;
-       recty= partrct->ymax - partrct->ymin;
-       
-       if(rectx<=0 || recty<=0)
-               return NULL;
-       
-       rr= MEM_callocN(sizeof(RenderResult), "new render result");
-       rr->rectx= rectx;
-       rr->recty= recty;
-       rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop;
-       /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
-       rr->crop= crop;
-       
-       /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
-       rr->tilerect.xmin= partrct->xmin - re->disprect.xmin;
-       rr->tilerect.xmax= partrct->xmax - re->disprect.xmax;
-       rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
-       rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
-       
-       if(savebuffers) {
-               rr->exrhandle= IMB_exr_get_handle();
-       }
-       
-       /* check renderdata for amount of layers */
-       for(nr=0, srl= re->r.layers.first; srl; srl= srl->next, nr++) {
-               
-               if((re->r.scemode & R_SINGLE_LAYER) && nr!=re->r.actlay)
-                       continue;
-               if(srl->layflag & SCE_LAY_DISABLE)
-                       continue;
-               
-               rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
-               BLI_addtail(&rr->layers, rl);
-               
-               BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
-               rl->lay= srl->lay;
-               rl->lay_zmask= srl->lay_zmask;
-               rl->layflag= srl->layflag;
-               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;
-               rl->rectx= rectx;
-               rl->recty= recty;
-               
-               if(rr->exrhandle) {
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
-               }
-               else
-                       rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
-               
-               if(srl->passflag  & SCE_PASS_Z)
-                       render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
-               if(srl->passflag  & SCE_PASS_VECTOR)
-                       render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
-               if(srl->passflag  & SCE_PASS_NORMAL)
-                       render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
-               if(srl->passflag  & SCE_PASS_UV) 
-                       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)
-                       render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
-               if(srl->passflag  & SCE_PASS_REFRACT)
-                       render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
-               if(srl->passflag  & SCE_PASS_INDEXOB)
-                       render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
-               if(srl->passflag  & SCE_PASS_INDEXMA)
-                       render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
-               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 */
-       if(rr->layers.first==NULL) {
-               rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
-               BLI_addtail(&rr->layers, rl);
-               
-               rl->rectx= rectx;
-               rl->recty= recty;
-
-               /* duplicate code... */
-               if(rr->exrhandle) {
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
-                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
-               }
-               else
-                       rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
-               
-               /* note, this has to be in sync with scene.c */
-               rl->lay= (1<<20) -1;
-               rl->layflag= 0x7FFF;    /* solid ztra halo strand */
-               rl->passflag= SCE_PASS_COMBINED;
-               
-               re->r.actlay= 0;
-       }
-       
-       /* border render; calculate offset for use in compositor. compo is centralized coords */
-       rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2;
-       rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2;
+       return render_result_new_from_exr(exrhandle, rectx, recty);
+}
+
+RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
+{
+       RenderLayer *rl= BLI_findlink(&rr->layers, re->r.actlay);
        
-       return rr;
+       if(rl) 
+               return rl;
+       else 
+               return rr->layers.first;
 }
 
 static int render_scene_needs_vector(Render *re)
@@ -695,344 +237,6 @@ static int render_scene_needs_vector(Render *re)
        return 0;
 }
 
-static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
-{
-       int y, ofs, copylen, tilex, tiley;
-       
-       copylen= tilex= rrpart->rectx;
-       tiley= rrpart->recty;
-       
-       if(rrpart->crop) {      /* filters add pixel extra */
-               tile+= pixsize*(rrpart->crop + rrpart->crop*tilex);
-               
-               copylen= tilex - 2*rrpart->crop;
-               tiley -= 2*rrpart->crop;
-               
-               ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
-               target+= pixsize*ofs;
-       }
-       else {
-               ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
-               target+= pixsize*ofs;
-       }
-
-       copylen *= sizeof(float)*pixsize;
-       tilex *= pixsize;
-       ofs= pixsize*rr->rectx;
-
-       for(y=0; y<tiley; y++) {
-               memcpy(target, tile, copylen);
-               target+= ofs;
-               tile+= tilex;
-       }
-}
-
-/* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
-/* no test happens here if it fits... we also assume layers are in sync */
-/* is used within threads */
-void merge_render_result(RenderResult *rr, RenderResult *rrpart)
-{
-       RenderLayer *rl, *rlp;
-       RenderPass *rpass, *rpassp;
-       
-       for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
-               
-               /* combined */
-               if(rl->rectf && rlp->rectf)
-                       do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
-               
-               /* passes are allocated in sync */
-               for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) {
-                       do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
-               }
-       }
-}
-
-
-static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
-{
-       RenderLayer *rlp;
-       RenderPass *rpassp;
-       int offs, partx, party;
-       
-       BLI_lock_thread(LOCK_IMAGE);
-       
-       for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) {
-               
-               if(rrpart->crop) {      /* filters add pixel extra */
-                       offs= (rrpart->crop + rrpart->crop*rrpart->rectx);
-               }
-               else {
-                       offs= 0;
-               }
-               
-               /* combined */
-               if(rlp->rectf) {
-                       int a, xstride= 4;
-                       for(a=0; a<xstride; a++)
-                               IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
-                                                               xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs);
-               }
-               
-               /* passes are allocated in sync */
-               for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) {
-                       int a, xstride= rpassp->channels;
-                       for(a=0; a<xstride; a++)
-                               IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
-                                                                       xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs);
-               }
-               
-       }
-
-       party= rrpart->tilerect.ymin + rrpart->crop;
-       partx= rrpart->tilerect.xmin + rrpart->crop;
-       IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
-
-       BLI_unlock_thread(LOCK_IMAGE);
-
-}
-
-static void save_empty_result_tiles(Render *re)
-{
-       RenderPart *pa;
-       RenderResult *rr;
-       
-       for(rr= re->result; rr; rr= rr->next) {
-               IMB_exrtile_clear_channels(rr->exrhandle);
-               
-               for(pa= re->parts.first; pa; pa= pa->next) {
-                       if(pa->ready==0) {
-                               int party= pa->disprect.ymin - re->disprect.ymin + pa->crop;
-                               int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop;
-                               IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
-                       }
-               }
-       }
-}
-
-
-/* for passes read from files, these have names stored */
-static char *make_pass_name(RenderPass *rpass, int chan)
-{
-       static char name[16];
-       int len;
-       
-       BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
-       len= strlen(name);
-       name[len]= '.';
-       name[len+1]= rpass->chan_id[chan];
-       name[len+2]= 0;
-
-       return name;
-}
-
-/* filename already made absolute */
-/* called from within UI, saves both rendered result as a file-read result */
-int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
-{
-       RenderLayer *rl;
-       RenderPass *rpass;
-       void *exrhandle= IMB_exr_get_handle();
-       int success;
-
-       BLI_make_existing_file(filename);
-       
-       /* composite result */
-       if(rr->rectf) {
-               IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf);
-               IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1);
-               IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2);
-               IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3);
-       }
-       
-       /* add layers/passes and assign channels */
-       for(rl= rr->layers.first; rl; rl= rl->next) {
-               
-               /* combined */
-               if(rl->rectf) {
-                       int a, xstride= 4;
-                       for(a=0; a<xstride; a++)
-                               IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
-                                                                       xstride, xstride*rr->rectx, rl->rectf+a);
-               }
-               
-               /* passes are allocated in sync */
-               for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
-                       int a, xstride= rpass->channels;
-                       for(a=0; a<xstride; a++) {
-                               if(rpass->passtype)
-                                       IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
-                                                                               xstride, xstride*rr->rectx, rpass->rect+a);
-                               else
-                                       IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 
-                                                                               xstride, xstride*rr->rectx, rpass->rect+a);
-                       }
-               }
-       }
-
-       /* when the filename has no permissions, this can fail */
-       if(IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
-               IMB_exr_write_channels(exrhandle);
-               success= TRUE;
-       }
-       else {
-               /* TODO, get the error from openexr's exception */
-               BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console");
-               success= FALSE;
-       }
-       IMB_exr_close(exrhandle);
-
-       return success;
-}
-
-/* callbacks for RE_MultilayerConvert */
-static void *ml_addlayer_cb(void *base, char *str)
-{
-       RenderResult *rr= base;
-       RenderLayer *rl;
-       
-       rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
-       BLI_addtail(&rr->layers, rl);
-       
-       BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
-       return rl;
-}
-static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id)
-{
-       RenderLayer *rl= lay;   
-       RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass");
-       int a;
-       
-       BLI_addtail(&rl->passes, rpass);
-       rpass->channels= totchan;
-
-       rpass->passtype= passtype_from_name(str);
-       if(rpass->passtype==0) printf("unknown pass %s\n", str);
-       rl->passflag |= rpass->passtype;
-       
-       BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
-       /* channel id chars */
-       for(a=0; a<totchan; a++)
-               rpass->chan_id[a]= chan_id[a];
-       
-       rpass->rect= rect;
-}
-
-/* from imbuf, if a handle was returned we convert this to render result */
-RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty)
-{
-       RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result");
-       RenderLayer *rl;
-       RenderPass *rpass;
-       
-       rr->rectx= rectx;
-       rr->recty= recty;
-       
-       IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
-
-       for(rl=rr->layers.first; rl; rl=rl->next) {
-               rl->rectx= rectx;
-               rl->recty= recty;
-
-               for(rpass=rl->passes.first; rpass; rpass=rpass->next) {
-                       rpass->rectx= rectx;
-                       rpass->recty= recty;
-               }
-       }
-       
-       return rr;
-}
-
-/* called in end of render, to add names to passes... for UI only */
-static void renderresult_add_names(RenderResult *rr)
-{
-       RenderLayer *rl;
-       RenderPass *rpass;
-       
-       for(rl= rr->layers.first; rl; rl= rl->next)
-               for(rpass= rl->passes.first; rpass; rpass= rpass->next)
-                       BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
-}
-
-/* called for reading temp files, and for external engines */
-static int read_render_result_from_file(const char *filename, RenderResult *rr)
-{
-       RenderLayer *rl;
-       RenderPass *rpass;
-       void *exrhandle= IMB_exr_get_handle();
-       int rectx, recty;
-
-       if(IMB_exr_begin_read(exrhandle, filename, &rectx, &recty)==0) {
-               printf("failed being read %s\n", filename);
-               IMB_exr_close(exrhandle);
-               return 0;
-       }
-
-       if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) {
-               if(rr)
-                       printf("error in reading render result: dimensions don't match\n");
-               else
-                       printf("error in reading render result: NULL result pointer\n");
-               IMB_exr_close(exrhandle);
-               return 0;
-       }
-       else {
-               for(rl= rr->layers.first; rl; rl= rl->next) {
-                       
-                       /* combined */
-                       if(rl->rectf) {
-                               int a, xstride= 4;
-                               for(a=0; a<xstride; a++)
-                                       IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
-                                                                               xstride, xstride*rectx, rl->rectf+a);
-                       }
-                       
-                       /* passes are allocated in sync */
-                       for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
-                               int a, xstride= rpass->channels;
-                               for(a=0; a<xstride; a++)
-                                       IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
-                                                                               xstride, xstride*rectx, rpass->rect+a);
-                       }
-                       
-               }
-               IMB_exr_read_channels(exrhandle);
-               renderresult_add_names(rr);
-       }
-
-       IMB_exr_close(exrhandle);
-
-       return 1;
-}
-
-/* only for temp buffer files, makes exact copy of render result */
-static int read_render_result(Render *re, int sample)
-{
-       char str[FILE_MAX];
-       int success;
-
-       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)) {
-               success= TRUE;
-       }
-       else {
-               printf("cannot read: %s\n", str);
-               success= FALSE;
-
-       }
-
-       BLI_rw_mutex_unlock(&re->resultmutex);
-
-       return success;
-}
-
 /* *************************************************** */
 
 Render *RE_GetRender(const char *name)
@@ -1091,17 +295,6 @@ Scene *RE_GetScene(Render *re)
        return NULL;
 }
 
-RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
-{
-       RenderLayer *rl= BLI_findlink(&rr->layers, re->r.actlay);
-       
-       if(rl) 
-               return rl;
-       else 
-               return rr->layers.first;
-}
-
-
 /* fill provided result struct with what's currently active or done */
 void RE_AcquireResultImage(Render *re, RenderResult *rr)
 {
@@ -1148,23 +341,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
        RenderResult rres;
        
        RE_AcquireResultImage(re, &rres);
-
-       if(rres.rect32) {
-               memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
-       }
-       else if(rres.rectf) {
-               int profile_from= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-               int predivide= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-               int dither= 0;
-
-               IMB_buffer_byte_from_float((unsigned char*)rect, rres.rectf,
-                       4, dither, IB_PROFILE_SRGB, profile_from, predivide,
-                       rres.rectx, rres.recty, rres.rectx, rres.rectx);
-       }
-       else
-               /* else fill with black */
-               memset(rect, 0, sizeof(int)*re->rectx*re->recty);
-
+       render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty);
        RE_ReleaseResultImage(re);
 }
 
@@ -1222,8 +399,8 @@ void RE_FreeRender(Render *re)
        free_renderdata_tables(re);
        free_sample_tables(re);
        
-       RE_FreeRenderResult(re->result);
-       RE_FreeRenderResult(re->pushedresult);
+       render_result_free(re->result);
+       render_result_free(re->pushedresult);
        
        BLI_remlink(&RenderGlobal.renderlist, re);
        MEM_freeN(re);
@@ -1323,14 +500,14 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
        if(re->r.scemode & R_PREVIEWBUTS) {
                if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty);
                else {
-                       RE_FreeRenderResult(re->result);
+                       render_result_free(re->result);
                        re->result= NULL;
                }
        }
        else {
                
                /* make empty render result, so display callbacks can initialize */
-               RE_FreeRenderResult(re->result);
+               render_result_free(re->result);
                re->result= MEM_callocN(sizeof(RenderResult), "new render result");
                re->result->rectx= re->rectx;
                re->result->recty= re->recty;
@@ -1346,22 +523,6 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
        RE_init_threadcount(re);
 }
 
-/* part of external api, not called for regular render pipeline */
-void RE_SetDispRect (struct Render *re, rcti *disprect)
-{
-       re->disprect= *disprect;
-       re->rectx= disprect->xmax-disprect->xmin;
-       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)
 {
        /* re->ok flag? */
@@ -1456,24 +617,6 @@ static int render_display_draw_enabled(Render *re)
                return 1;
 }
 
-/* allocate osa new results for samples */
-static RenderResult *new_full_sample_buffers(Render *re, ListBase *lb, rcti *partrct, int crop)
-{
-       int a;
-       
-       if(re->osa==0)
-               return new_render_result(re, partrct, crop, RR_USEMEM);
-       
-       for(a=0; a<re->osa; a++) {
-               RenderResult *rr= new_render_result(re, partrct, crop, RR_USEMEM);
-               BLI_addtail(lb, rr);
-               rr->sample_nr= a;
-       }
-       
-       return lb->first;
-}
-
-
 /* the main thread call, renders an entire part */
 static void *do_part_thread(void *pa_v)
 {
@@ -1483,9 +626,9 @@ static void *do_part_thread(void *pa_v)
        if(R.test_break(R.tbh)==0) {
                
                if(!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
-                       pa->result= new_full_sample_buffers(&R, &pa->fullresult, &pa->disprect, pa->crop);
+                       pa->result= render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM);
                else
-                       pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM);
+                       pa->result= render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM);
 
                if(R.sss_points)
                        zbufshade_sss_tile(pa);
@@ -1496,16 +639,12 @@ static void *do_part_thread(void *pa_v)
                
                /* merge too on break! */
                if(R.result->exrhandle) {
-                       RenderResult *rr, *rrpart;
-                       
-                       for(rr= R.result, rrpart= pa->result; rr && rrpart; rr= rr->next, rrpart= rrpart->next)
-                               save_render_result_tile(rr, rrpart);
-                       
+                       render_result_exr_file_merge(R.result, pa->result);
                }
                else if(render_display_draw_enabled(&R)) {
                        /* on break, don't merge in result for preview renders, looks nicer */
                        if(R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS));
-                       else merge_render_result(R.result, pa->result);
+                       else render_result_merge(R.result, pa->result);
                }
        }
        
@@ -1629,20 +768,6 @@ static void print_part_stats(Render *re, RenderPart *pa)
        re->i.infostr= NULL;
 }
 
-/* make osa new results for samples */
-static RenderResult *new_full_sample_buffers_exr(Render *re)
-{
-       int a;
-       
-       for(a=0; a<re->osa; a++) {
-               RenderResult *rr= new_render_result(re, &re->disprect, 0, 1);
-               BLI_addtail(&re->fullresult, rr);
-               rr->sample_nr= a;
-       }
-       
-       return re->fullresult.first;
-}
-
 static void threaded_tile_processor(Render *re)
 {
        ListBase threads;
@@ -1654,14 +779,15 @@ static void threaded_tile_processor(Render *re)
 
        /* 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);
+               render_result_free(re->result);
        
                if(re->sss_points && render_display_draw_enabled(re))
-                       re->result= new_render_result(re, &re->disprect, 0, 0);
+                       re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
                else if(re->r.scemode & R_FULL_SAMPLE)
-                       re->result= new_full_sample_buffers_exr(re);
+                       re->result= render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
                else
-                       re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE));
+                       re->result= render_result_new(re, &re->disprect, 0,
+                               (re->r.scemode & R_EXR_TILE_FILE)? RR_USE_EXR: RR_USE_MEM);
        }
 
        BLI_rw_mutex_unlock(&re->resultmutex);
@@ -1673,17 +799,8 @@ static void threaded_tile_processor(Render *re)
        
        initparts(re);
 
-       if(re->result->exrhandle) {
-               RenderResult *rr;
-               char str[FILE_MAX];
-               
-               for(rr= re->result; rr; rr= rr->next) {
-                       render_unique_exr_name(re, str, rr->sample_nr);
-               
-                       printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
-                       IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
-               }
-       }
+       if(re->result->exrhandle)
+               render_result_exr_file_begin(re);
        
        BLI_init_threads(&threads, do_part_thread, re->r.threads);
        
@@ -1737,7 +854,7 @@ static void threaded_tile_processor(Render *re)
                                                re->display_draw(re->ddh, pa->result, NULL);
                                        print_part_stats(re, pa);
                                        
-                                       free_render_result(&pa->fullresult, pa->result);
+                                       render_result_free_list(&pa->fullresult, pa->result);
                                        pa->result= NULL;
                                        re->i.partsdone++;
                                        re->progress(re->prh, re->i.partsdone / (float)re->i.totpart);
@@ -1763,22 +880,9 @@ 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) {
-                       IMB_exr_close(rr->exrhandle);
-                       rr->exrhandle= NULL;
-               }
-               
-               free_render_result(&re->fullresult, re->result);
-               re->result= NULL;
-
+               render_result_exr_file_end(re);
                BLI_rw_mutex_unlock(&re->resultmutex);
-               
-               read_render_result(re, 0);
        }
        
        /* unset threadsafety */
@@ -1928,7 +1032,7 @@ static void do_render_blur_3d(Render *re)
        int blur= re->r.mblur_samples;
        
        /* create accumulation render result */
-       rres= new_render_result(re, &re->disprect, 0, RR_USEMEM);
+       rres= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
        
        /* do the blur steps */
        while(blur--) {
@@ -1946,7 +1050,7 @@ static void do_render_blur_3d(Render *re)
        
        /* swap results */
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-       RE_FreeRenderResult(re->result);
+       render_result_free(re->result);
        re->result= rres;
        BLI_rw_mutex_unlock(&re->resultmutex);
        
@@ -2053,7 +1157,7 @@ static void do_render_fields_3d(Render *re)
        re->disprect.ymax *= 2;
 
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-       re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
+       re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 
        if(rr2) {
                if(re->r.mode & R_ODDFIELD)
@@ -2061,10 +1165,10 @@ static void do_render_fields_3d(Render *re)
                else
                        merge_renderresult_fields(re->result, rr1, rr2);
                
-               RE_FreeRenderResult(rr2);
+               render_result_free(rr2);
        }
 
-       RE_FreeRenderResult(rr1);
+       render_result_free(rr1);
        
        re->i.curfield= 0;      /* stats */
        
@@ -2116,10 +1220,10 @@ static void do_render_fields_blur_3d(Render *re)
                                re->rectx= re->winx;
                                re->recty= re->winy;
                                
-                               rres= new_render_result(re, &re->disprect, 0, RR_USEMEM);
+                               rres= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
                                
-                               merge_render_result(rres, re->result);
-                               RE_FreeRenderResult(re->result);
+                               render_result_merge(rres, re->result);
+                               render_result_free(re->result);
                                re->result= rres;
                                
                                /* weak... the display callback wants an active renderlayer pointer... */
@@ -2302,8 +1406,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
                        if(re1->scene->id.flag & LIB_DOIT) {
                                if(re1->r.scemode & R_FULL_SAMPLE) {
-                                       if(sample)
-                                               read_render_result(re1, sample);
+                                       if(sample) {
+                                               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+                                               render_result_exr_file_read(re1, sample);
+                                               BLI_rw_mutex_unlock(&re->resultmutex);
+                                       }
                                        ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */
                                }
                        }
@@ -2432,8 +1539,8 @@ static void do_render_composite_fields_blur_3d(Render *re)
                /* ensure new result gets added, like for regular renders */
                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_result_free(re->result);
+               re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
 
                BLI_rw_mutex_unlock(&re->resultmutex);
                
@@ -2442,8 +1549,11 @@ static void do_render_composite_fields_blur_3d(Render *re)
        }
        
        /* swap render result */
-       if(re->r.scemode & R_SINGLE_LAYER)
-               pop_render_result(re);
+       if(re->r.scemode & R_SINGLE_LAYER) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+               render_result_single_layer_end(re);
+               BLI_rw_mutex_unlock(&re->resultmutex);
+       }
        
        if(!re->test_break(re->tbh)) {
                
@@ -2559,61 +1669,19 @@ static void do_render_seq(Render * re)
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 
        if(ibuf) {
-               if(ibuf->rect_float) {
-                       /* color management: when off ensure rectf is non-lin, since thats what the internal
-                        * render engine delivers */
-                       int profile_to= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-                       int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-                       int predivide= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-
-                       if (!rr->rectf)
-                               rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
-                       
-                       IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
-                               4, profile_to, profile_from, predivide,
-                               rr->rectx, rr->recty, rr->rectx, rr->rectx);
-                       
-                       /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
-                          can hang around when sequence render has rendered a 32 bits one before */
-                       if(rr->rect32) {
-                               MEM_freeN(rr->rect32);
-                               rr->rect32= NULL;
-                       }
-               }
-               else if(ibuf->rect) {
-                       if (!rr->rect32)
-                               rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
-
-                       memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
-
-                       /* if (ibuf->zbuf) { */
-                       /*      if (R.rectz) freeN(R.rectz); */
-                       /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
-                       /* } */
-
-                       /* Same things as above, old rectf can hang around from previous render. */
-                       if(rr->rectf) {
-                               MEM_freeN(rr->rectf);
-                               rr->rectf= NULL;
-                       }
-               }
+               /* copy ibuf into combined pixel rect */
+               render_result_rect_from_ibuf(rr, &re->r, ibuf);
                
                if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
                        Editing * ed = re->scene->ed;
-                       if (ed) {
+                       if (ed)
                                free_imbuf_seq(re->scene, &ed->seqbase, TRUE, TRUE);
-                       }
                }
                IMB_freeImBuf(ibuf);
        }
        else {
                /* render result is delivered empty in most cases, nevertheless we handle all cases */
-               if (rr->rectf)
-                       memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
-               else if (rr->rect32)
-                       memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
-               else
-                       rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
+               render_result_rect_fill_zero(rr);
        }
 
        BLI_rw_mutex_unlock(&re->resultmutex);
@@ -2655,11 +1723,6 @@ static void do_render_all_options(Render *re)
                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;
        
        re->stats_draw(re->sdh, &re->i);
@@ -2743,7 +1806,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
        if(scene->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) {
                char str[FILE_MAX];
                
-               scene_unique_exr_name(scene, str, 0);
+               render_result_exr_file_path(scene, 0, str);
                
                if (BLI_file_is_writable(str)==0) {
                        BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path");
@@ -2905,8 +1968,11 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc
                update_physics_cache(re, scene, anim_init);
        }
        
-       if(srl || scene->r.scemode & R_SINGLE_LAYER)
-               push_render_result(re);
+       if(srl || scene->r.scemode & R_SINGLE_LAYER) {
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+               render_result_single_layer_begin(re);
+               BLI_rw_mutex_unlock(&re->resultmutex);
+       }
        
        RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect);
        if(!re->ok)  /* if an error was printed, abort */
@@ -3003,37 +2069,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
                        }
                }
                else {
-                       int flags = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE)? IB_cm_predivide: 0;
-                       ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.im_format.planes, flags);
-                       
-                       /* if not exists, BKE_write_ibuf makes one */
-                       ibuf->rect= (unsigned int *)rres.rect32;    
-                       ibuf->rect_float= rres.rectf;
-                       ibuf->zbuf_float= rres.rectz;
-                       
-                       /* float factor for random dither, imbuf takes care of it */
-                       ibuf->dither= scene->r.dither_intensity;
-                       
-                       /* 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 (BKE_imtype_valid_depths(scene->r.im_format.imtype) & (R_IMF_CHAN_DEPTH_12|R_IMF_CHAN_DEPTH_16|R_IMF_CHAN_DEPTH_24|R_IMF_CHAN_DEPTH_32))
-                                               IMB_float_from_rect(ibuf);
-                               } else {                                
-                                       ibuf->profile = IB_PROFILE_LINEAR_RGB;
-                               }
-                       }
-
-                       /* color -> greyscale */
-                       /* editing directly would alter the render view */
-                       if(scene->r.im_format.planes == R_IMF_PLANES_BW) {
-                               ImBuf *ibuf_bw= IMB_dupImBuf(ibuf);
-                               IMB_color_to_bw(ibuf_bw);
-                               IMB_freeImBuf(ibuf);
-                               ibuf= ibuf_bw;
-                       }
+                       ImBuf *ibuf= render_result_rect_to_ibuf(&rres, &scene->r);
 
                        ok= BKE_write_ibuf_stamp(scene, camera, ibuf, name, &scene->r.im_format);
                        
@@ -3232,7 +2268,7 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
 int RE_ReadRenderResult(Scene *scene, Scene *scenode)
 {
        Render *re;
-       int winx, winy;
+       int winx, winy, success;
        rcti disprect;
        
        /* calculate actual render result and display size */
@@ -3263,7 +2299,11 @@ int RE_ReadRenderResult(Scene *scene, Scene *scenode)
        RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
        re->scene= scene;
        
-       return read_render_result(re, 0);
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+       success= render_result_exr_file_read(re, 0);
+       BLI_rw_mutex_unlock(&re->resultmutex);
+
+       return success;
 }
 
 void RE_set_max_threads(int threads)
@@ -3330,7 +2370,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
 
 void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename)
 {
-       if(!read_render_result_from_file(filename, result)) {
+       if(!render_result_exr_file_read_path(result, filename)) {
                BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
                return;
        }
index 41bfcb550681e5032a5735d4fa45cb8d72c8defb..42ad5fd15e567795b34b81aa2a27c8e8bf4317a7 100644 (file)
@@ -53,6 +53,7 @@
 
 #include "PIL_time.h"
 
+#include "render_result.h"
 #include "render_types.h"
 #include "renderpipeline.h"
 #include "rendercore.h"
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
new file mode 100644 (file)
index 0000000..e825c9d
--- /dev/null
@@ -0,0 +1,1021 @@
+/*  
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/render/intern/source/render_result.c
+ *  \ingroup render
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "intern/openexr/openexr_multi.h"
+
+#include "render_result.h"
+#include "render_types.h"
+
+/********************************** Free *************************************/
+
+void render_result_free(RenderResult *res)
+{
+       if(res==NULL) return;
+
+       while(res->layers.first) {
+               RenderLayer *rl= res->layers.first;
+               
+               if(rl->rectf) MEM_freeN(rl->rectf);
+               /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
+               if(rl->acolrect) MEM_freeN(rl->acolrect);
+               if(rl->scolrect) MEM_freeN(rl->scolrect);
+               
+               while(rl->passes.first) {
+                       RenderPass *rpass= rl->passes.first;
+                       if(rpass->rect) MEM_freeN(rpass->rect);
+                       BLI_remlink(&rl->passes, rpass);
+                       MEM_freeN(rpass);
+               }
+               BLI_remlink(&res->layers, rl);
+               MEM_freeN(rl);
+       }
+       
+       if(res->rect32)
+               MEM_freeN(res->rect32);
+       if(res->rectz)
+               MEM_freeN(res->rectz);
+       if(res->rectf)
+               MEM_freeN(res->rectf);
+       if(res->text)
+               MEM_freeN(res->text);
+       
+       MEM_freeN(res);
+}
+
+/* version that's compatible with fullsample buffers */
+void render_result_free_list(ListBase *lb, RenderResult *rr)
+{
+       RenderResult *rrnext;
+       
+       for(; rr; rr= rrnext) {
+               rrnext= rr->next;
+               
+               if(lb && lb->first)
+                       BLI_remlink(lb, rr);
+               
+               render_result_free(rr);
+       }
+}
+
+/********************************* Names *************************************/
+
+/* NOTE: OpenEXR only supports 32 chars for layer+pass names
+   In blender we now use max 10 chars for pass, max 20 for layer */
+static const char *get_pass_name(int passtype, int channel)
+{
+       
+       if(passtype == SCE_PASS_COMBINED) {
+               if(channel==-1) return "Combined";
+               if(channel==0) return "Combined.R";
+               if(channel==1) return "Combined.G";
+               if(channel==2) return "Combined.B";
+               return "Combined.A";
+       }
+       if(passtype == SCE_PASS_Z) {
+               if(channel==-1) return "Depth";
+               return "Depth.Z";
+       }
+       if(passtype == SCE_PASS_VECTOR) {
+               if(channel==-1) return "Vector";
+               if(channel==0) return "Vector.X";
+               if(channel==1) return "Vector.Y";
+               if(channel==2) return "Vector.Z";
+               return "Vector.W";
+       }
+       if(passtype == SCE_PASS_NORMAL) {
+               if(channel==-1) return "Normal";
+               if(channel==0) return "Normal.X";
+               if(channel==1) return "Normal.Y";
+               return "Normal.Z";
+       }
+       if(passtype == SCE_PASS_UV) {
+               if(channel==-1) return "UV";
+               if(channel==0) return "UV.U";
+               if(channel==1) return "UV.V";
+               return "UV.A";
+       }
+       if(passtype == SCE_PASS_RGBA) {
+               if(channel==-1) return "Color";
+               if(channel==0) return "Color.R";
+               if(channel==1) return "Color.G";
+               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";
+               if(channel==1) return "Diffuse.G";
+               return "Diffuse.B";
+       }
+       if(passtype == SCE_PASS_SPEC) {
+               if(channel==-1) return "Spec";
+               if(channel==0) return "Spec.R";
+               if(channel==1) return "Spec.G";
+               return "Spec.B";
+       }
+       if(passtype == SCE_PASS_SHADOW) {
+               if(channel==-1) return "Shadow";
+               if(channel==0) return "Shadow.R";
+               if(channel==1) return "Shadow.G";
+               return "Shadow.B";
+       }
+       if(passtype == SCE_PASS_AO) {
+               if(channel==-1) return "AO";
+               if(channel==0) return "AO.R";
+               if(channel==1) return "AO.G";
+               return "AO.B";
+       }
+       if(passtype == SCE_PASS_ENVIRONMENT) {
+               if(channel==-1) return "Env";
+               if(channel==0) return "Env.R";
+               if(channel==1) return "Env.G";
+               return "Env.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";
+               if(channel==1) return "Reflect.G";
+               return "Reflect.B";
+       }
+       if(passtype == SCE_PASS_REFRACT) {
+               if(channel==-1) return "Refract";
+               if(channel==0) return "Refract.R";
+               if(channel==1) return "Refract.G";
+               return "Refract.B";
+       }
+       if(passtype == SCE_PASS_INDEXOB) {
+               if(channel==-1) return "IndexOB";
+               return "IndexOB.X";
+       }
+       if(passtype == SCE_PASS_INDEXMA) {
+               if(channel==-1) return "IndexMA";
+               return "IndexMA.X";
+       }
+       if(passtype == SCE_PASS_MIST) {
+               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";
+}
+
+static int passtype_from_name(const char *str)
+{
+       
+       if(strcmp(str, "Combined")==0)
+               return SCE_PASS_COMBINED;
+
+       if(strcmp(str, "Depth")==0)
+               return SCE_PASS_Z;
+
+       if(strcmp(str, "Vector")==0)
+               return SCE_PASS_VECTOR;
+
+       if(strcmp(str, "Normal")==0)
+               return SCE_PASS_NORMAL;
+
+       if(strcmp(str, "UV")==0)
+               return SCE_PASS_UV;
+
+       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;
+
+       if(strcmp(str, "Spec")==0)
+               return SCE_PASS_SPEC;
+
+       if(strcmp(str, "Shadow")==0)
+               return SCE_PASS_SHADOW;
+       
+       if(strcmp(str, "AO")==0)
+               return SCE_PASS_AO;
+
+       if(strcmp(str, "Env")==0)
+               return SCE_PASS_ENVIRONMENT;
+
+       if(strcmp(str, "Indirect")==0)
+               return SCE_PASS_INDIRECT;
+
+       if(strcmp(str, "Reflect")==0)
+               return SCE_PASS_REFLECT;
+
+       if(strcmp(str, "Refract")==0)
+               return SCE_PASS_REFRACT;
+
+       if(strcmp(str, "IndexOB")==0)
+               return SCE_PASS_INDEXOB;
+
+       if(strcmp(str, "IndexMA")==0)
+               return SCE_PASS_INDEXMA;
+
+       if(strcmp(str, "Mist")==0)
+               return SCE_PASS_MIST;
+       
+       if(strcmp(str, "RayHits")==0)
+               return SCE_PASS_RAYHITS;
+       return 0;
+}
+
+/********************************** New **************************************/
+
+static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
+{
+       const char *typestr= get_pass_name(passtype, 0);
+       RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr);
+       int rectsize= rr->rectx*rr->recty*channels;
+       
+       BLI_addtail(&rl->passes, rpass);
+       rpass->passtype= passtype;
+       rpass->channels= channels;
+       rpass->rectx= rl->rectx;
+       rpass->recty= rl->recty;
+       BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+       
+       if(rr->exrhandle) {
+               int a;
+               for(a=0; a<channels; a++)
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
+       }
+       else {
+               float *rect;
+               int x;
+               
+               rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
+               
+               if(passtype==SCE_PASS_VECTOR) {
+                       /* initialize to max speed */
+                       rect= rpass->rect;
+                       for(x= rectsize-1; x>=0; x--)
+                               rect[x]= PASS_VECTOR_MAX;
+               }
+               else if(passtype==SCE_PASS_Z) {
+                       rect= rpass->rect;
+                       for(x= rectsize-1; x>=0; x--)
+                               rect[x]= 10e10;
+               }
+       }
+}
+
+/* called by main render as well for parts */
+/* will read info from Render *re to define layers */
+/* called in threads */
+/* re->winx,winy is coordinate space of entire image, partrct the part within */
+RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers)
+{
+       RenderResult *rr;
+       RenderLayer *rl;
+       SceneRenderLayer *srl;
+       int rectx, recty, nr;
+       
+       rectx= partrct->xmax - partrct->xmin;
+       recty= partrct->ymax - partrct->ymin;
+       
+       if(rectx<=0 || recty<=0)
+               return NULL;
+       
+       rr= MEM_callocN(sizeof(RenderResult), "new render result");
+       rr->rectx= rectx;
+       rr->recty= recty;
+       rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop;
+       /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
+       rr->crop= crop;
+       
+       /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
+       rr->tilerect.xmin= partrct->xmin - re->disprect.xmin;
+       rr->tilerect.xmax= partrct->xmax - re->disprect.xmax;
+       rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
+       rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
+       
+       if(savebuffers) {
+               rr->exrhandle= IMB_exr_get_handle();
+       }
+       
+       /* check renderdata for amount of layers */
+       for(nr=0, srl= re->r.layers.first; srl; srl= srl->next, nr++) {
+               
+               if((re->r.scemode & R_SINGLE_LAYER) && nr!=re->r.actlay)
+                       continue;
+               if(srl->layflag & SCE_LAY_DISABLE)
+                       continue;
+               
+               rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
+               rl->lay= srl->lay;
+               rl->lay_zmask= srl->lay_zmask;
+               rl->layflag= srl->layflag;
+               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;
+               rl->rectx= rectx;
+               rl->recty= recty;
+               
+               if(rr->exrhandle) {
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
+               }
+               else
+                       rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
+               
+               if(srl->passflag  & SCE_PASS_Z)
+                       render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
+               if(srl->passflag  & SCE_PASS_VECTOR)
+                       render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
+               if(srl->passflag  & SCE_PASS_NORMAL)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
+               if(srl->passflag  & SCE_PASS_UV) 
+                       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)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
+               if(srl->passflag  & SCE_PASS_REFRACT)
+                       render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
+               if(srl->passflag  & SCE_PASS_INDEXOB)
+                       render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
+               if(srl->passflag  & SCE_PASS_INDEXMA)
+                       render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
+               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 */
+       if(rr->layers.first==NULL) {
+               rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               rl->rectx= rectx;
+               rl->recty= recty;
+
+               /* duplicate code... */
+               if(rr->exrhandle) {
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
+                       IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
+               }
+               else
+                       rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
+               
+               /* note, this has to be in sync with scene.c */
+               rl->lay= (1<<20) -1;
+               rl->layflag= 0x7FFF;    /* solid ztra halo strand */
+               rl->passflag= SCE_PASS_COMBINED;
+               
+               re->r.actlay= 0;
+       }
+       
+       /* border render; calculate offset for use in compositor. compo is centralized coords */
+       rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2;
+       rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2;
+       
+       return rr;
+}
+
+/* allocate osa new results for samples */
+RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers)
+{
+       int a;
+       
+       if(re->osa==0)
+               return render_result_new(re, partrct, crop, savebuffers);
+       
+       for(a=0; a<re->osa; a++) {
+               RenderResult *rr= render_result_new(re, partrct, crop, savebuffers);
+               BLI_addtail(lb, rr);
+               rr->sample_nr= a;
+       }
+       
+       return lb->first;
+}
+
+/* callbacks for render_result_new_from_exr */
+static void *ml_addlayer_cb(void *base, char *str)
+{
+       RenderResult *rr= base;
+       RenderLayer *rl;
+       
+       rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
+       BLI_addtail(&rr->layers, rl);
+       
+       BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
+       return rl;
+}
+
+static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id)
+{
+       RenderLayer *rl= lay;   
+       RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass");
+       int a;
+       
+       BLI_addtail(&rl->passes, rpass);
+       rpass->channels= totchan;
+
+       rpass->passtype= passtype_from_name(str);
+       if(rpass->passtype==0) printf("unknown pass %s\n", str);
+       rl->passflag |= rpass->passtype;
+       
+       BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
+       /* channel id chars */
+       for(a=0; a<totchan; a++)
+               rpass->chan_id[a]= chan_id[a];
+       
+       rpass->rect= rect;
+}
+
+/* from imbuf, if a handle was returned we convert this to render result */
+RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
+{
+       RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result");
+       RenderLayer *rl;
+       RenderPass *rpass;
+       
+       rr->rectx= rectx;
+       rr->recty= recty;
+       
+       IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
+
+       for(rl=rr->layers.first; rl; rl=rl->next) {
+               rl->rectx= rectx;
+               rl->recty= recty;
+
+               for(rpass=rl->passes.first; rpass; rpass=rpass->next) {
+                       rpass->rectx= rectx;
+                       rpass->recty= recty;
+               }
+       }
+       
+       return rr;
+}
+
+/*********************************** Merge ***********************************/
+
+static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
+{
+       int y, ofs, copylen, tilex, tiley;
+       
+       copylen= tilex= rrpart->rectx;
+       tiley= rrpart->recty;
+       
+       if(rrpart->crop) {      /* filters add pixel extra */
+               tile+= pixsize*(rrpart->crop + rrpart->crop*tilex);
+               
+               copylen= tilex - 2*rrpart->crop;
+               tiley -= 2*rrpart->crop;
+               
+               ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
+               target+= pixsize*ofs;
+       }
+       else {
+               ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
+               target+= pixsize*ofs;
+       }
+
+       copylen *= sizeof(float)*pixsize;
+       tilex *= pixsize;
+       ofs= pixsize*rr->rectx;
+
+       for(y=0; y<tiley; y++) {
+               memcpy(target, tile, copylen);
+               target+= ofs;
+               tile+= tilex;
+       }
+}
+
+/* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
+/* no test happens here if it fits... we also assume layers are in sync */
+/* is used within threads */
+void render_result_merge(RenderResult *rr, RenderResult *rrpart)
+{
+       RenderLayer *rl, *rlp;
+       RenderPass *rpass, *rpassp;
+       
+       for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
+               
+               /* combined */
+               if(rl->rectf && rlp->rectf)
+                       do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
+               
+               /* passes are allocated in sync */
+               for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) {
+                       do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
+               }
+       }
+}
+
+/* for passes read from files, these have names stored */
+static char *make_pass_name(RenderPass *rpass, int chan)
+{
+       static char name[16];
+       int len;
+       
+       BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
+       len= strlen(name);
+       name[len]= '.';
+       name[len+1]= rpass->chan_id[chan];
+       name[len+2]= 0;
+
+       return name;
+}
+
+/* filename already made absolute */
+/* called from within UI, saves both rendered result as a file-read result */
+int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
+{
+       RenderLayer *rl;
+       RenderPass *rpass;
+       void *exrhandle= IMB_exr_get_handle();
+       int success;
+
+       BLI_make_existing_file(filename);
+       
+       /* composite result */
+       if(rr->rectf) {
+               IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf);
+               IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1);
+               IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2);
+               IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3);
+       }
+       
+       /* add layers/passes and assign channels */
+       for(rl= rr->layers.first; rl; rl= rl->next) {
+               
+               /* combined */
+               if(rl->rectf) {
+                       int a, xstride= 4;
+                       for(a=0; a<xstride; a++)
+                               IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
+                                                                       xstride, xstride*rr->rectx, rl->rectf+a);
+               }
+               
+               /* passes are allocated in sync */
+               for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
+                       int a, xstride= rpass->channels;
+                       for(a=0; a<xstride; a++) {
+                               if(rpass->passtype)
+                                       IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
+                                                                               xstride, xstride*rr->rectx, rpass->rect+a);
+                               else
+                                       IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 
+                                                                               xstride, xstride*rr->rectx, rpass->rect+a);
+                       }
+               }
+       }
+
+       /* when the filename has no permissions, this can fail */
+       if(IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
+               IMB_exr_write_channels(exrhandle);
+               success= TRUE;
+       }
+       else {
+               /* TODO, get the error from openexr's exception */
+               BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console");
+               success= FALSE;
+       }
+       IMB_exr_close(exrhandle);
+
+       return success;
+}
+
+/**************************** Single Layer Rendering *************************/
+
+void render_result_single_layer_begin(Render *re)
+{
+       /* all layers except the active one get temporally pushed away */
+
+       /* officially pushed result should be NULL... error can happen with do_seq */
+       RE_FreeRenderResult(re->pushedresult);
+       
+       re->pushedresult= re->result;
+       re->result= NULL;
+}
+
+/* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
+void render_result_single_layer_end(Render *re)
+{
+       SceneRenderLayer *srl;
+       RenderLayer *rlpush;
+       RenderLayer *rl;
+       int nr;
+
+       if(re->result==NULL) {
+               printf("pop render result error; no current result!\n");
+               return;
+       }
+
+       if(!re->pushedresult)
+               return;
+
+       if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) {
+               /* find which layer in re->pushedresult should be replaced */
+               rl= re->result->layers.first;
+               
+               /* render result should be empty after this */
+               BLI_remlink(&re->result->layers, rl);
+               
+               /* reconstruct render result layers */
+               for(nr=0, srl= re->scene->r.layers.first; srl; srl= srl->next, nr++) {
+                       if(nr==re->r.actlay)
+                               BLI_addtail(&re->result->layers, rl);
+                       else {
+                               rlpush= RE_GetRenderLayer(re->pushedresult, srl->name);
+                               if(rlpush) {
+                                       BLI_remlink(&re->pushedresult->layers, rlpush);
+                                       BLI_addtail(&re->result->layers, rlpush);
+                               }
+                       }
+               }
+       }
+
+       RE_FreeRenderResult(re->pushedresult);
+       re->pushedresult= NULL;
+}
+
+/************************* EXR Tile File Rendering ***************************/
+
+static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
+{
+       RenderLayer *rlp;
+       RenderPass *rpassp;
+       int offs, partx, party;
+       
+       BLI_lock_thread(LOCK_IMAGE);
+       
+       for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) {
+               
+               if(rrpart->crop) {      /* filters add pixel extra */
+                       offs= (rrpart->crop + rrpart->crop*rrpart->rectx);
+               }
+               else {
+                       offs= 0;
+               }
+               
+               /* combined */
+               if(rlp->rectf) {
+                       int a, xstride= 4;
+                       for(a=0; a<xstride; a++)
+                               IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
+                                                               xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs);
+               }
+               
+               /* passes are allocated in sync */
+               for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) {
+                       int a, xstride= rpassp->channels;
+                       for(a=0; a<xstride; a++)
+                               IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
+                                                                       xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs);
+               }
+               
+       }
+
+       party= rrpart->tilerect.ymin + rrpart->crop;
+       partx= rrpart->tilerect.xmin + rrpart->crop;
+       IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
+
+       BLI_unlock_thread(LOCK_IMAGE);
+}
+
+static void save_empty_result_tiles(Render *re)
+{
+       RenderPart *pa;
+       RenderResult *rr;
+       
+       for(rr= re->result; rr; rr= rr->next) {
+               IMB_exrtile_clear_channels(rr->exrhandle);
+               
+               for(pa= re->parts.first; pa; pa= pa->next) {
+                       if(pa->ready==0) {
+                               int party= pa->disprect.ymin - re->disprect.ymin + pa->crop;
+                               int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop;
+                               IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
+                       }
+               }
+       }
+}
+
+/* begin write of exr tile file */
+void render_result_exr_file_begin(Render *re)
+{
+       RenderResult *rr;
+       char str[FILE_MAX];
+       
+       for(rr= re->result; rr; rr= rr->next) {
+               render_result_exr_file_path(re->scene, rr->sample_nr, str);
+       
+               printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
+               IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
+       }
+}
+
+/* end write of exr tile file, read back first sample */
+void render_result_exr_file_end(Render *re)
+{
+       RenderResult *rr;
+
+       save_empty_result_tiles(re);
+       
+       for(rr= re->result; rr; rr= rr->next) {
+               IMB_exr_close(rr->exrhandle);
+               rr->exrhandle= NULL;
+       }
+       
+       render_result_free_list(&re->fullresult, re->result);
+       re->result= NULL;
+
+       render_result_exr_file_read(re, 0);
+}
+
+/* save part into exr file */
+void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
+{
+       for(; rr && rrpart; rr= rr->next, rrpart= rrpart->next)
+               save_render_result_tile(rr, rrpart);
+}
+
+/* path to temporary exr file */
+void render_result_exr_file_path(Scene *scene, int sample, char *filepath)
+{
+       char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE];
+       
+       BLI_strncpy(di, G.main->name, FILE_MAX);
+       BLI_splitdirstring(di, fi);
+       
+       if(sample==0)
+               BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name+2);
+       else
+               BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name+2, sample);
+
+       BLI_make_file_string("/", filepath, BLI_temporary_dir(), name);
+}
+
+/* only for temp buffer files, makes exact copy of render result */
+int render_result_exr_file_read(Render *re, int sample)
+{
+       char str[FILE_MAX];
+       int success;
+
+       RE_FreeRenderResult(re->result);
+       re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
+
+       render_result_exr_file_path(re->scene, sample, str);
+       printf("read exr tmp file: %s\n", str);
+
+       if(render_result_exr_file_read_path(re->result, str)) {
+               success= TRUE;
+       }
+       else {
+               printf("cannot read: %s\n", str);
+               success= FALSE;
+
+       }
+
+       return success;
+}
+
+/* called for reading temp files, and for external engines */
+int render_result_exr_file_read_path(RenderResult *rr, const char *filepath)
+{
+       RenderLayer *rl;
+       RenderPass *rpass;
+       void *exrhandle= IMB_exr_get_handle();
+       int rectx, recty;
+
+       if(IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty)==0) {
+               printf("failed being read %s\n", filepath);
+               IMB_exr_close(exrhandle);
+               return 0;
+       }
+
+       if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) {
+               if(rr)
+                       printf("error in reading render result: dimensions don't match\n");
+               else
+                       printf("error in reading render result: NULL result pointer\n");
+               IMB_exr_close(exrhandle);
+               return 0;
+       }
+
+       for(rl= rr->layers.first; rl; rl= rl->next) {
+               /* combined */
+               if(rl->rectf) {
+                       int a, xstride= 4;
+                       for(a=0; a<xstride; a++)
+                               IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
+                                                                       xstride, xstride*rectx, rl->rectf+a);
+               }
+               
+               /* passes are allocated in sync */
+               for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
+                       int a, xstride= rpass->channels;
+                       for(a=0; a<xstride; a++)
+                               IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
+                                                                       xstride, xstride*rectx, rpass->rect+a);
+
+                       BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
+               }
+       }
+
+       IMB_exr_read_channels(exrhandle);
+       IMB_exr_close(exrhandle);
+
+       return 1;
+}
+
+/*************************** Combined Pixel Rect *****************************/
+
+ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
+{
+       int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE)? IB_cm_predivide: 0;
+       ImBuf *ibuf= IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
+       
+       /* if not exists, BKE_write_ibuf makes one */
+       ibuf->rect= (unsigned int *)rr->rect32;    
+       ibuf->rect_float= rr->rectf;
+       ibuf->zbuf_float= rr->rectz;
+       
+       /* float factor for random dither, imbuf takes care of it */
+       ibuf->dither= rd->dither_intensity;
+       
+       /* prepare to gamma correct to sRGB color space */
+       if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
+               /* sequence editor can generate 8bpc render buffers */
+               if (ibuf->rect) {
+                       ibuf->profile = IB_PROFILE_SRGB;
+                       if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12|R_IMF_CHAN_DEPTH_16|R_IMF_CHAN_DEPTH_24|R_IMF_CHAN_DEPTH_32))
+                               IMB_float_from_rect(ibuf);
+               } else {                                
+                       ibuf->profile = IB_PROFILE_LINEAR_RGB;
+               }
+       }
+
+       /* color -> greyscale */
+       /* editing directly would alter the render view */
+       if(rd->im_format.planes == R_IMF_PLANES_BW) {
+               ImBuf *ibuf_bw= IMB_dupImBuf(ibuf);
+               IMB_color_to_bw(ibuf_bw);
+               IMB_freeImBuf(ibuf);
+               ibuf= ibuf_bw;
+       }
+
+       return ibuf;
+}
+
+void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf)
+{
+       if(ibuf->rect_float) {
+               /* color management: when off ensure rectf is non-lin, since thats what the internal
+                * render engine delivers */
+               int profile_to= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
+               int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
+               int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
+
+               if (!rr->rectf)
+                       rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
+               
+               IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
+                       4, profile_to, profile_from, predivide,
+                       rr->rectx, rr->recty, rr->rectx, rr->rectx);
+               
+               /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
+                  can hang around when sequence render has rendered a 32 bits one before */
+               if(rr->rect32) {
+                       MEM_freeN(rr->rect32);
+                       rr->rect32= NULL;
+               }
+       }
+       else if(ibuf->rect) {
+               if (!rr->rect32)
+                       rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
+
+               memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
+
+               /* Same things as above, old rectf can hang around from previous render. */
+               if(rr->rectf) {
+                       MEM_freeN(rr->rectf);
+                       rr->rectf= NULL;
+               }
+       }
+}
+
+void render_result_rect_fill_zero(RenderResult *rr)
+{
+       if (rr->rectf)
+               memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
+       else if (rr->rect32)
+               memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
+       else
+               rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
+}
+
+void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty)
+{
+       if(rr->rect32) {
+               memcpy(rect, rr->rect32, sizeof(int)*rr->rectx*rr->recty);
+       }
+       else if(rr->rectf) {
+               int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
+               int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
+               int dither= 0;
+
+               IMB_buffer_byte_from_float((unsigned char*)rect, rr->rectf,
+                       4, dither, IB_PROFILE_SRGB, profile_from, predivide,
+                       rr->rectx, rr->recty, rr->rectx, rr->rectx);
+       }
+       else
+               /* else fill with black */
+               memset(rect, 0, sizeof(int)*rectx*recty);
+}
+
index 96f9918891a9cdbe9548023d45b4fe67bb754a25..630acf3d88abd505486df3f71f103a89103aac62 100644 (file)
@@ -67,6 +67,7 @@
 #include "rayintersection.h"
 #include "rayobject.h"
 #include "renderpipeline.h"
+#include "render_result.h"
 #include "render_types.h"
 #include "renderdatabase.h"
 #include "occlusion.h"
index 8efe23c38f95987ba29526bb0afef5b1a9ba511c..c77a1309743c611bac429ceda7f08c17d0ae4154 100644 (file)
@@ -63,6 +63,7 @@
 /* local includes */
 #include "gammaCorrectionTables.h"
 #include "pixelblending.h"
+#include "render_result.h"
 #include "render_types.h"
 #include "renderpipeline.h"
 #include "renderdatabase.h"