diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 13ac8b14edf..8c0bbb66911 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -42,6 +42,9 @@ extern "C" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" + +#define WITH_OPENEXR +#include "openexr_multi.h" } #include @@ -333,103 +336,213 @@ short imb_save_openexr(struct ImBuf *ibuf, char *name, int flags) /* ********************* Tile file support ************************************ */ -typedef struct ExrTileHandle { - TiledOutputFile *file; +typedef struct ExrHandle { + InputFile *ifile; + TiledOutputFile *tofile; + OutputFile *ofile; int tilex, tiley; int width, height; ListBase channels; -} ExrTileHandle; +} ExrHandle; -typedef struct ExrTileChannel { - struct ExrTileChannel *next, *prev; - char *name; +#define CHANMAXNAME 64 +typedef struct ExrChannel { + struct ExrChannel *next, *prev; + char name[2*CHANMAXNAME + 1]; int xstride, ystride; float *rect; -} ExrTileChannel; +} ExrChannel; /* not threaded! write one tiled file at a time */ -void *imb_exrtile_get_handle(void) +void *IMB_exr_get_handle(void) { - static ExrTileHandle data; + static ExrHandle data; + + memset(&data, sizeof(ExrHandle), 0); - data.channels.first= data.channels.last= NULL; return &data; } -void imb_exrtile_add_channel(void *handle, char *channame) +/* still clumsy name handling, layers/channels can be ordered as list in list later */ +void IMB_exr_add_channel(void *handle, const char *layname, const char *channame) { - ExrTileHandle *data= (ExrTileHandle *)handle; - ExrTileChannel *echan; + ExrHandle *data= (ExrHandle *)handle; + ExrChannel *echan; - echan= (ExrTileChannel *)MEM_callocN(sizeof(ExrTileChannel), "exr tile channel"); - echan->name= channame; + echan= (ExrChannel *)MEM_callocN(sizeof(ExrChannel), "exr tile channel"); + + if(layname) { + char lay[CHANMAXNAME], chan[CHANMAXNAME]; + strncpy(lay, layname, CHANMAXNAME-1); + strncpy(chan, channame, CHANMAXNAME-1); + + sprintf(echan->name, "%s.%s", lay, chan); + } + else + strncpy(echan->name, channame, 2*CHANMAXNAME); + printf("added channel %s\n", echan->name); BLI_addtail(&data->channels, echan); } -void imb_exrtile_begin_write(void *handle, char *filename, int width, int height, int tilex, int tiley) +void IMB_exr_begin_write(void *handle, char *filename, int width, int height) { - ExrTileHandle *data= (ExrTileHandle *)handle; + ExrHandle *data= (ExrHandle *)handle; Header header (width, height); - ExrTileChannel *echan; + ExrChannel *echan; + + data->width= width; + data->height= height; + + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) + header.channels().insert (echan->name, Channel (FLOAT)); + + header.insert ("comments", StringAttribute ("Blender MultiChannel")); + + data->ofile = new OutputFile(filename, header); +} + +void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height, int tilex, int tiley) +{ + ExrHandle *data= (ExrHandle *)handle; + Header header (width, height); + ExrChannel *echan; data->tilex= tilex; data->tiley= tiley; data->width= width; data->height= height; - for(echan= (ExrTileChannel *)data->channels.first; echan; echan= echan->next) + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) header.channels().insert (echan->name, Channel (FLOAT)); header.setTileDescription (TileDescription (tilex, tiley, ONE_LEVEL)); + header.lineOrder() = RANDOM_Y, + header.compression() = NO_COMPRESSION; - header.insert ("comments", StringAttribute ("Blender RenderResult")); + header.insert ("comments", StringAttribute ("Blender MultiChannel")); - data->file = new TiledOutputFile(filename, header); + data->tofile = new TiledOutputFile(filename, header); } - -void imb_exrtile_set_channel(void *handle, char *channame, int xstride, int ystride, float *rect) +int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) { - ExrTileHandle *data= (ExrTileHandle *)handle; - ExrTileChannel *echan; + ExrHandle *data= (ExrHandle *)handle; - for(echan= (ExrTileChannel *)data->channels.first; echan; echan= echan->next) - if(strcmp(echan->name, channame)==0) + data->ifile = new InputFile(filename); + if(data->ifile) { + Box2i dw = data->ifile->header().dataWindow(); + data->width= *width = dw.max.x - dw.min.x + 1; + data->height= *height = dw.max.y - dw.min.y + 1; + + const ChannelList &channels = data->ifile->header().channels(); + + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) + IMB_exr_add_channel(data, NULL, i.name()); + + return 1; + } + return 0; +} + +/* still clumsy name handling, layers/channels can be ordered as list in list later */ +void IMB_exr_set_channel(void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) +{ + ExrHandle *data= (ExrHandle *)handle; + ExrChannel *echan; + char name[2*CHANMAXNAME + 1]; + + if(layname) { + char lay[CHANMAXNAME], chan[CHANMAXNAME]; + strncpy(lay, layname, CHANMAXNAME-1); + strncpy(chan, channame, CHANMAXNAME-1); + + sprintf(name, "%s.%s", lay, chan); + } + else + strncpy(name, channame, 2*CHANMAXNAME); + + + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) + if(strcmp(echan->name, name)==0) break; + if(echan) { echan->xstride= xstride; echan->ystride= ystride; echan->rect= rect; } else - printf("imb_exrtile_set_channel error\n"); + printf("IMB_exrtile_set_channel error %s\n", name); } -void imb_exrtile_write_channels(void *handle, int partx, int party) +void IMB_exrtile_write_channels(void *handle, int partx, int party) { - ExrTileHandle *data= (ExrTileHandle *)handle; + ExrHandle *data= (ExrHandle *)handle; FrameBuffer frameBuffer; - ExrTileChannel *echan; + ExrChannel *echan; - for(echan= (ExrTileChannel *)data->channels.first; echan; echan= echan->next) { + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) { float *rect= echan->rect - echan->xstride*partx - echan->ystride*party; frameBuffer.insert (echan->name, Slice (FLOAT, (char *)rect, echan->xstride*sizeof(float), echan->ystride*sizeof(float))); } - data->file->setFrameBuffer (frameBuffer); + data->tofile->setFrameBuffer (frameBuffer); printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); - data->file->writeTile (partx/data->tilex, party/data->tiley); + data->tofile->writeTile (partx/data->tilex, party/data->tiley); } -void imb_exrtile_close(void *handle) +void IMB_exr_write_channels(void *handle) { - ExrTileHandle *data= (ExrTileHandle *)handle; + ExrHandle *data= (ExrHandle *)handle; + FrameBuffer frameBuffer; + ExrChannel *echan; - delete data->file; + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) + frameBuffer.insert (echan->name, Slice (FLOAT, (char *)echan->rect, + echan->xstride*sizeof(float), echan->ystride*sizeof(float))); + + data->ofile->setFrameBuffer (frameBuffer); + data->ofile->writePixels (data->height); + +} + +void IMB_exr_read_channels(void *handle) +{ + ExrHandle *data= (ExrHandle *)handle; + FrameBuffer frameBuffer; + ExrChannel *echan; + + for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) { + /* no datawindow correction needed */ + if(echan->rect) + frameBuffer.insert (echan->name, Slice (FLOAT, (char *)echan->rect, + echan->xstride*sizeof(float), echan->ystride*sizeof(float))); + } + + data->ifile->setFrameBuffer (frameBuffer); + data->ifile->readPixels (0, data->height-1); +} + + +void IMB_exr_close(void *handle) +{ + ExrHandle *data= (ExrHandle *)handle; + ExrChannel *echan; + + if(data->ifile) + delete data->ifile; + else if(data->ofile) + delete data->ofile; + else if(data->tofile) + delete data->tofile; + + data->ifile= NULL; + data->ofile= NULL; + data->tofile= NULL; BLI_freelistN(&data->channels); } @@ -473,11 +586,9 @@ static int exr_has_zbuffer(InputFile *file) static int exr_is_renderresult(InputFile *file) { const StringAttribute *comments= file->header().findTypedAttribute("comments"); - if(comments) { - - if(comments->value() == "Blender RenderResult") + if(comments) + if(comments->value() == "Blender MultiChannel") return 1; - } return 0; } @@ -529,7 +640,8 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) /* 1.0 is fill value */ frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); - if(exr_has_zbuffer(file)) { + if(exr_has_zbuffer(file)) + { float *firstz; addzbuffloatImBuf(ibuf); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index a82713b6595..7572dbcb292 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -1,15 +1,12 @@ /** * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * 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 @@ -20,14 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * The Original Code is Copyright (C) 2005 Blender Foundation * All rights reserved. * * The Original Code is: all of this file. * - * Contributor(s): Austin Benesh. + * Contributor(s): Austin Benesh. Ton Roosendaal. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #ifndef _OPENEXR_API_H @@ -37,8 +34,8 @@ extern "C" { #endif -#define OPENEXR_FLOATRGB 0x1 -#define OPENEXR_ZBUF 0x2 +#define OPENEXR_FLOATRGB 0x1 +#define OPENEXR_ZBUF 0x2 #include @@ -53,15 +50,6 @@ short imb_save_openexr (struct ImBuf *ibuf, char *name, int flags); struct ImBuf *imb_load_openexr (unsigned char *mem, int size, int flags); - -void * imb_exrtile_get_handle (void); -void imb_exrtile_add_channel (void *handle, char *channame); -void imb_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley); -void imb_exrtile_set_channel (void *handle, char *channame, int xstride, int ystride, float *rect); -void imb_exrtile_write_channels (void *handle, int partx, int party); -void imb_exrtile_close (void *handle); - - #ifdef __cplusplus } #endif diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h new file mode 100644 index 00000000000..ff71aab5f3c --- /dev/null +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Ton Roosendaal. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _OPENEXR_MULTI_H +#define _OPENEXR_MULTI_H + +/* experiment with more advanced exr api */ + +#ifdef WITH_OPENEXR +void * IMB_exr_get_handle (void); +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame); + +int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height); +void IMB_exr_begin_write (void *handle, char *filename, int width, int height); +void IMB_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley); + +void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect); + +void IMB_exr_read_channels (void *handle); +void IMB_exr_write_channels (void *handle); +void IMB_exrtile_write_channels (void *handle, int partx, int party); + +void IMB_exr_close (void *handle); + +#else + +/* ugly... but we only use it on pipeline.c, render module, now */ + +void * IMB_exr_get_handle (void) {return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame) {} + +int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height) {return 0;} +void IMB_exr_begin_write (void *handle, char *filename, int width, int height) {} +void IMB_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley) {} + +void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) {} + +void IMB_exr_read_channels (void *handle) {} +void IMB_exr_write_channels (void *handle) {} +void IMB_exrtile_write_channels (void *handle, int partx, int party) {} + +void IMB_exr_close (void *handle) {} + +#endif + + + +#endif /* __OPENEXR_MULTI_H */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index b1dfb53e357..ad3d93cd908 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -58,7 +58,7 @@ typedef struct Render Render; typedef struct RenderPass { struct RenderPass *next, *prev; - int passtype; + int passtype, channels; float *rect; } RenderPass; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index b76e5343dfd..64780b1b831 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -332,15 +332,14 @@ typedef struct LampRen /* **************** defines ********************* */ -/* mode flag is same as for renderdata */ -/* flag */ +/* R.r.mode flag is same as for renderdata */ + +/* R.flag */ #define R_ZTRA 1 #define R_HALO 2 #define R_SEC_FIELD 4 #define R_LAMPHALO 8 -#define R_RENDERING 16 -#define R_ANIMRENDER 32 -#define R_REDRAW_PRV 64 +#define R_FILEBUFFER 16 /* vlakren->flag (vlak = face in dutch) char!!! */ #define R_SMOOTH 1 diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index c95442fc97d..a1e5108d3d6 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -51,13 +51,16 @@ #include "PIL_time.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "intern/openexr/openexr_api.h" + +#include "intern/openexr/openexr_multi.h" #include "RE_pipeline.h" #include "radio.h" #include "BSE_sequence.h" /* <----------------- bad!!! */ +#include "SDL_thread.h" + /* internal */ #include "render_types.h" #include "renderpipeline.h" @@ -68,9 +71,6 @@ #include "shadbuf.h" #include "zbuf.h" -#include "SDL_thread.h" -#include "SDL_mutex.h" - /* render flow 1) Initialize state @@ -105,7 +105,8 @@ static struct ListBase RenderList= {NULL, NULL}; /* hardcopy of current render, used while rendering for speed */ Render R; -void *exrhandle= NULL; +static SDL_mutex *exrtile_lock= NULL; + /* ********* alloc and free ******** */ @@ -156,7 +157,7 @@ static void free_render_result(RenderResult *res) if(rl->rectf) MEM_freeT(rl->rectf); while(rl->passes.first) { RenderPass *rpass= rl->passes.first; - MEM_freeT(rpass->rect); + if(rpass->rect) MEM_freeT(rpass->rect); BLI_remlink(&rl->passes, rpass); MEM_freeT(rpass); } @@ -174,23 +175,90 @@ static void free_render_result(RenderResult *res) MEM_freeT(res); } -static void render_layer_add_pass(RenderLayer *rl, int rectsize, int passtype, char *mallocstr) +static char *get_pass_name(int passtype, int channel) { - RenderPass *rpass= MEM_mallocT(sizeof(RenderPass), mallocstr); + + if(passtype == SCE_PASS_COMBINED) { + if(channel==0) return "Combined.R"; + else if(channel==1) return "Combined.G"; + else if(channel==2) return "Combined.B"; + else return "Combined.A"; + } + if(passtype == SCE_PASS_Z) + return "Z"; + if(passtype == SCE_PASS_VECTOR) { + if(channel==0) return "Vector.X"; + else if(channel==1) return "Vector.Y"; + else if(channel==2) return "Vector.Z"; + else return "Vector.W"; + } + if(passtype == SCE_PASS_NORMAL) { + if(channel==0) return "Normal.X"; + else if(channel==1) return "Normal.Y"; + else return "Normal.Z"; + } + if(passtype == SCE_PASS_RGBA) { + if(channel==0) return "Color.R"; + else if(channel==1) return "Color.G"; + else if(channel==2) return "Color.B"; + else return "Color.A"; + } + if(passtype == SCE_PASS_DIFFUSE) { + if(channel==0) return "Diffuse.R"; + else if(channel==1) return "Diffuse.G"; + else return "Diffuse.B"; + } + if(passtype == SCE_PASS_SPEC) { + if(channel==0) return "Spec.R"; + else if(channel==1) return "Spec.G"; + else return "Spec.B"; + } + if(passtype == SCE_PASS_SHADOW) { + if(channel==0) return "Shadow.R"; + else if(channel==1) return "Shadow.G"; + else return "Shadow.B"; + } + if(passtype == SCE_PASS_AO) { + if(channel==0) return "AO.R"; + else if(channel==1) return "AO.G"; + else return "AO.B"; + } + if(passtype == SCE_PASS_RAY) { + if(channel==0) return "Ray.R"; + else if(channel==1) return "Ray.G"; + else return "Ray.B"; + } + return "Unknown"; +} + +static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) +{ + char *typestr= get_pass_name(passtype, 0); + RenderPass *rpass= MEM_callocT(sizeof(RenderPass), typestr); + int rectsize= rr->rectx*rr->recty*channels; BLI_addtail(&rl->passes, rpass); rpass->passtype= passtype; - if(passtype==SCE_PASS_VECTOR) { - float *rect; - int x; - - /* initialize to max speed */ - rect= rpass->rect= MEM_mapallocT(sizeof(float)*rectsize, mallocstr); - for(x= rectsize-1; x>=0; x--) - rect[x]= PASS_VECTOR_MAX; + rpass->channels= channels; + + if(rr->exrhandle) { + int a; + for(a=0; aexrhandle, rl->name, get_pass_name(passtype, a)); + } + else { + if(passtype==SCE_PASS_VECTOR) { + float *rect; + int x; + + /* initialize to max speed */ + rect= rpass->rect= MEM_mapallocT(sizeof(float)*rectsize, typestr); + for(x= rectsize-1; x>=0; x--) + rect[x]= PASS_VECTOR_MAX; + } + else + rpass->rect= MEM_mapallocT(sizeof(float)*rectsize, typestr); } - else - rpass->rect= MEM_mapallocT(sizeof(float)*rectsize, mallocstr); } float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) @@ -203,10 +271,11 @@ float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) return NULL; } + /* called by main render as well for parts */ /* will read info from Render *re to define layers */ /* called in threads */ -/* winrct is coordinate rect of entire image, partrct the part within */ +/* re->winx,winy is coordinate space of entire image, partrct the part within */ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) { RenderResult *rr; @@ -232,6 +301,11 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) rr->tilerect.ymin= partrct->ymin - re->disprect.ymin; rr->tilerect.ymax= partrct->ymax - re->disprect.ymax; + /* this flag needs cleared immediate after result was made */ + if(re->flag & R_FILEBUFFER) { + 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++) { @@ -246,26 +320,33 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) rl->layflag= srl->layflag; rl->passflag= srl->passflag; - rl->rectf= MEM_mapallocT(rectx*recty*sizeof(float)*4, "layer float rgba"); + if(rr->exrhandle) { + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R"); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G"); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B"); + IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A"); + } + else + rl->rectf= MEM_mapallocT(rectx*recty*sizeof(float)*4, "Combined rgba"); if(srl->passflag & SCE_PASS_Z) - render_layer_add_pass(rl, rectx*recty, SCE_PASS_Z, "Layer float Z"); + render_layer_add_pass(rr, rl, 1, SCE_PASS_Z); if(srl->passflag & SCE_PASS_VECTOR) - render_layer_add_pass(rl, rectx*recty*4, SCE_PASS_VECTOR, "layer float Vector"); + render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR); if(srl->passflag & SCE_PASS_NORMAL) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_NORMAL, "layer float Normal"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL); if(srl->passflag & SCE_PASS_RGBA) - render_layer_add_pass(rl, rectx*recty*4, SCE_PASS_RGBA, "layer float Color"); + render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); if(srl->passflag & SCE_PASS_DIFFUSE) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_DIFFUSE, "layer float Diffuse"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); if(srl->passflag & SCE_PASS_SPEC) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_SPEC, "layer float Spec"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); if(srl->passflag & SCE_PASS_SHADOW) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_SHADOW, "layer float Shadow"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); if(srl->passflag & SCE_PASS_AO) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_AO, "layer float AO"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); if(srl->passflag & SCE_PASS_RAY) - render_layer_add_pass(rl, rectx*recty*3, SCE_PASS_RAY, "layer float Mirror"); + render_layer_add_pass(rr, rl, 3, SCE_PASS_RAY); } /* previewrender and envmap don't do layers, so we make a default one */ @@ -346,19 +427,7 @@ static void merge_render_result(RenderResult *rr, RenderResult *rrpart) /* passes are allocated in sync */ for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) { - switch(rpass->passtype) { - case SCE_PASS_Z: - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 1); - break; - case SCE_PASS_VECTOR: - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 4); - break; - case SCE_PASS_RGBA: - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 4); - break; - default: - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, 3); - } + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); } } } @@ -366,11 +435,13 @@ static void merge_render_result(RenderResult *rr, RenderResult *rrpart) static void save_render_result_tile(Render *re, RenderPart *pa) { -#ifdef WITH_OPENEXR RenderResult *rrpart= pa->result; RenderLayer *rlp; + RenderPass *rpassp; int offs, partx, party; + if(exrtile_lock) SDL_mutexP(exrtile_lock); + for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) { if(rrpart->crop) { /* filters add pixel extra */ @@ -384,18 +455,69 @@ static void save_render_result_tile(Render *re, RenderPart *pa) /* combined */ if(rlp->rectf) { - int xstride= 4; - imb_exrtile_set_channel(exrhandle, "R", xstride, xstride*pa->rectx, rlp->rectf + xstride*offs); - imb_exrtile_set_channel(exrhandle, "G", xstride, xstride*pa->rectx, rlp->rectf+1 + xstride*offs); - imb_exrtile_set_channel(exrhandle, "B", xstride, xstride*pa->rectx, rlp->rectf+2 + xstride*offs); - imb_exrtile_set_channel(exrhandle, "A", xstride, xstride*pa->rectx, rlp->rectf+3 + xstride*offs); - - imb_exrtile_write_channels(exrhandle, partx, party); - } + int a, xstride= 4; + for(a=0; aresult->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), + xstride, xstride*pa->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; aresult->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), + xstride, xstride*pa->rectx, rpassp->rect+a + xstride*offs); + } + } -#endif + + IMB_exrtile_write_channels(re->result->exrhandle, partx, party); + + if(exrtile_lock) SDL_mutexV(exrtile_lock); + } +static void read_render_result(Render *re) +{ + RenderLayer *rl; + RenderPass *rpass; + void *exrhandle= IMB_exr_get_handle(); + int rectx, recty; + + free_render_result(re->result); + re->result= new_render_result(re, &re->disprect, 0); + + IMB_exr_begin_read(exrhandle, "/tmp/render.exr", &rectx, &recty); + if(rectx!=re->result->rectx || recty!=re->result->recty) { + printf("error in reading render result\n"); + } + else { + for(rl= re->result->layers.first; rl; rl= rl->next) { + + /* combined */ + if(rl->rectf) { + int a, xstride= 4; + for(a=0; aname, 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; aname, get_pass_name(rpass->passtype, a), + xstride, xstride*rectx, rpass->rect+a); + } + + } + printf("before read\n"); + IMB_exr_read_channels(exrhandle); + printf("after read\n"); + } + + IMB_exr_close(exrhandle); +} /* *************************************************** */ @@ -590,7 +712,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect /* initialize render result */ free_render_result(re->result); re->result= new_render_result(re, &re->disprect, 0); - + /* single layer render disables composit */ if(re->r.scemode & R_SINGLE_LAYER) re->r.scemode &= ~R_DOCOMP; @@ -701,8 +823,11 @@ static int do_part_thread(void *pa_v) else zbufshade_tile(pa); - /* merge too on break! */ - merge_render_result(R.result, pa->result); + /* merge too on break! */ + if(R.result->exrhandle) + save_render_result_tile(&R, pa); + else + merge_render_result(R.result, pa->result); } pa->ready= 1; @@ -805,13 +930,19 @@ static void threaded_tile_processor(Render *re) { ListBase threads; RenderPart *pa, *nextpa; - int maxthreads, rendering=1, counter= 1, drawtimer=0; + RenderResult *rr= re->result; + int maxthreads, rendering=1, counter= 1, drawtimer=0, hasdrawn; - if(re->result==NULL) + if(rr==NULL) return; if(re->test_break()) return; + if(rr->exrhandle) { + IMB_exrtile_begin_write(rr->exrhandle, "/tmp/render.exr", rr->rectx, rr->recty, rr->rectx/re->r.xparts, rr->recty/re->r.yparts); + exrtile_lock = SDL_CreateMutex(); + } + if(re->r.mode & R_THREADS) maxthreads= 2; else maxthreads= 1; @@ -844,37 +975,45 @@ static void threaded_tile_processor(Render *re) /* check for ready ones to display, and if we need to continue */ rendering= 0; + hasdrawn= 0; for(pa= re->parts.first; pa; pa= pa->next) { if(pa->ready) { if(pa->result) { BLI_remove_thread(&threads, pa); + re->display_draw(pa->result, NULL); print_part_stats(re, pa); - if(exrhandle) save_render_result_tile(re, pa); - free_render_result(pa->result); pa->result= NULL; re->i.partsdone++; - drawtimer= 0; + hasdrawn= 1; } } else { rendering= 1; if(pa->nr && pa->result && drawtimer>20) { re->display_draw(pa->result, &pa->result->renrect); - drawtimer= 0; + hasdrawn= 1; } } } - + if(hasdrawn) + drawtimer= 0; + /* on break, wait for all slots to get freed */ if( (g_break=re->test_break()) && BLI_available_threads(&threads)==maxthreads) rendering= 0; } - /* restore threadsafety */ + if(rr->exrhandle) { + if(exrtile_lock) SDL_DestroyMutex(exrtile_lock); + IMB_exr_close(rr->exrhandle); + read_render_result(re); + } + + /* unset threadsafety */ g_break= 0; BLI_end_threads(&threads); @@ -1158,7 +1297,9 @@ static int render_initialize_from_scene(Render *re, Scene *scene) disprect.ymax= winy; } +/* if(G.rt) re->flag |= R_FILEBUFFER; */ RE_InitState(re, &scene->r, winx, winy, &disprect); + re->flag &= ~R_FILEBUFFER; re->scene= scene; if(!is_rendering_allowed(re)) @@ -1167,15 +1308,6 @@ static int render_initialize_from_scene(Render *re, Scene *scene) re->display_init(re->result); re->display_clear(re->result); - if(0) { - exrhandle= imb_exrtile_get_handle(); - imb_exrtile_add_channel(exrhandle, "R"); - imb_exrtile_add_channel(exrhandle, "G"); - imb_exrtile_add_channel(exrhandle, "B"); - imb_exrtile_add_channel(exrhandle, "A"); - imb_exrtile_begin_write(exrhandle, "/tmp/render.exr", winx, winy, winx/scene->r.xparts, winy/scene->r.yparts); - } - return 1; } @@ -1189,11 +1321,6 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) if(render_initialize_from_scene(re, scene)) { do_render_final(re); -#ifdef WITH_OPENEXR - if(exrhandle) - imb_exrtile_close(exrhandle); -#endif - exrhandle= NULL; } } diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 1333e1f177f..dd54d014c5c 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2182,7 +2182,7 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) Scene *oldsce; unsigned int *rectot; int oldcfra, doseq; - int redisplay= (!G.background && !(R.flag & R_RENDERING)); + int redisplay= (!G.background && !G.rendering); oldsce= G.scene; if(seq->scene!=G.scene) set_scene_bg(seq->scene);