Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-01-05 21:50:09 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-01-05 21:50:09 +0400
commitde4befb0756fd65ab92c6b00ca15c324dc513d52 (patch)
tree002c9ad54612fcf8bf3250bb7ae950a6b5f6d136 /source/blender/render/intern
parent015b64be2a5d62d495b43cf74a255f95e0b02721 (diff)
Code refactoring: split render result related functions into separate file.
Diffstat (limited to 'source/blender/render/intern')
-rw-r--r--source/blender/render/intern/include/render_result.h94
-rw-r--r--source/blender/render/intern/include/renderpipeline.h12
-rw-r--r--source/blender/render/intern/source/external_engine.c15
-rw-r--r--source/blender/render/intern/source/pipeline.c1098
-rw-r--r--source/blender/render/intern/source/rayshade.c1
-rw-r--r--source/blender/render/intern/source/render_result.c1021
-rw-r--r--source/blender/render/intern/source/rendercore.c1
-rw-r--r--source/blender/render/intern/source/zbuf.c1
8 files changed, 1196 insertions, 1047 deletions
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
new file mode 100644
index 00000000000..93cbc6fe9c9
--- /dev/null
+++ b/source/blender/render/intern/include/render_result.h
@@ -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 */
+
diff --git a/source/blender/render/intern/include/renderpipeline.h b/source/blender/render/intern/include/renderpipeline.h
index fc46ea83309..9a87cf84012 100644
--- a/source/blender/render/intern/include/renderpipeline.h
+++ b/source/blender/render/intern/include/renderpipeline.h
@@ -33,22 +33,12 @@
#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 */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 78215498a47..703ca23c15b 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -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);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 0068407a7df..f82287e8645 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -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;
}
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 41bfcb55068..42ad5fd15e5 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -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
index 00000000000..e825c9d842e
--- /dev/null
+++ b/source/blender/render/intern/source/render_result.c
@@ -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);
+}
+
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 96f9918891a..630acf3d88a 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -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"
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 8efe23c38f9..c77a1309743 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -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"