Blender V2.61 - r43446

render_result.c

Go to the documentation of this file.
00001 /*  
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version. 
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2006 Blender Foundation.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00033 #include <stdio.h>
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "BKE_image.h"
00039 #include "BKE_global.h"
00040 #include "BKE_main.h"
00041 #include "BKE_report.h"
00042 #include "BKE_utildefines.h"
00043 
00044 #include "BLI_fileops.h"
00045 #include "BLI_listbase.h"
00046 #include "BLI_path_util.h"
00047 #include "BLI_string.h"
00048 #include "BLI_threads.h"
00049 #include "BLI_utildefines.h"
00050 
00051 #include "IMB_imbuf.h"
00052 #include "IMB_imbuf_types.h"
00053 
00054 #include "intern/openexr/openexr_multi.h"
00055 
00056 #include "render_result.h"
00057 #include "render_types.h"
00058 
00059 /********************************** Free *************************************/
00060 
00061 void render_result_free(RenderResult *res)
00062 {
00063     if(res==NULL) return;
00064 
00065     while(res->layers.first) {
00066         RenderLayer *rl= res->layers.first;
00067         
00068         if(rl->rectf) MEM_freeN(rl->rectf);
00069         /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
00070         if(rl->acolrect) MEM_freeN(rl->acolrect);
00071         if(rl->scolrect) MEM_freeN(rl->scolrect);
00072         
00073         while(rl->passes.first) {
00074             RenderPass *rpass= rl->passes.first;
00075             if(rpass->rect) MEM_freeN(rpass->rect);
00076             BLI_remlink(&rl->passes, rpass);
00077             MEM_freeN(rpass);
00078         }
00079         BLI_remlink(&res->layers, rl);
00080         MEM_freeN(rl);
00081     }
00082     
00083     if(res->rect32)
00084         MEM_freeN(res->rect32);
00085     if(res->rectz)
00086         MEM_freeN(res->rectz);
00087     if(res->rectf)
00088         MEM_freeN(res->rectf);
00089     if(res->text)
00090         MEM_freeN(res->text);
00091     
00092     MEM_freeN(res);
00093 }
00094 
00095 /* version that's compatible with fullsample buffers */
00096 void render_result_free_list(ListBase *lb, RenderResult *rr)
00097 {
00098     RenderResult *rrnext;
00099     
00100     for(; rr; rr= rrnext) {
00101         rrnext= rr->next;
00102         
00103         if(lb && lb->first)
00104             BLI_remlink(lb, rr);
00105         
00106         render_result_free(rr);
00107     }
00108 }
00109 
00110 /********************************* Names *************************************/
00111 
00112 /* NOTE: OpenEXR only supports 32 chars for layer+pass names
00113    In blender we now use max 10 chars for pass, max 20 for layer */
00114 static const char *get_pass_name(int passtype, int channel)
00115 {
00116     
00117     if(passtype == SCE_PASS_COMBINED) {
00118         if(channel==-1) return "Combined";
00119         if(channel==0) return "Combined.R";
00120         if(channel==1) return "Combined.G";
00121         if(channel==2) return "Combined.B";
00122         return "Combined.A";
00123     }
00124     if(passtype == SCE_PASS_Z) {
00125         if(channel==-1) return "Depth";
00126         return "Depth.Z";
00127     }
00128     if(passtype == SCE_PASS_VECTOR) {
00129         if(channel==-1) return "Vector";
00130         if(channel==0) return "Vector.X";
00131         if(channel==1) return "Vector.Y";
00132         if(channel==2) return "Vector.Z";
00133         return "Vector.W";
00134     }
00135     if(passtype == SCE_PASS_NORMAL) {
00136         if(channel==-1) return "Normal";
00137         if(channel==0) return "Normal.X";
00138         if(channel==1) return "Normal.Y";
00139         return "Normal.Z";
00140     }
00141     if(passtype == SCE_PASS_UV) {
00142         if(channel==-1) return "UV";
00143         if(channel==0) return "UV.U";
00144         if(channel==1) return "UV.V";
00145         return "UV.A";
00146     }
00147     if(passtype == SCE_PASS_RGBA) {
00148         if(channel==-1) return "Color";
00149         if(channel==0) return "Color.R";
00150         if(channel==1) return "Color.G";
00151         if(channel==2) return "Color.B";
00152         return "Color.A";
00153     }
00154     if(passtype == SCE_PASS_EMIT) {
00155         if(channel==-1) return "Emit";
00156         if(channel==0) return "Emit.R";
00157         if(channel==1) return "Emit.G";
00158         return "Emit.B";
00159     }
00160     if(passtype == SCE_PASS_DIFFUSE) {
00161         if(channel==-1) return "Diffuse";
00162         if(channel==0) return "Diffuse.R";
00163         if(channel==1) return "Diffuse.G";
00164         return "Diffuse.B";
00165     }
00166     if(passtype == SCE_PASS_SPEC) {
00167         if(channel==-1) return "Spec";
00168         if(channel==0) return "Spec.R";
00169         if(channel==1) return "Spec.G";
00170         return "Spec.B";
00171     }
00172     if(passtype == SCE_PASS_SHADOW) {
00173         if(channel==-1) return "Shadow";
00174         if(channel==0) return "Shadow.R";
00175         if(channel==1) return "Shadow.G";
00176         return "Shadow.B";
00177     }
00178     if(passtype == SCE_PASS_AO) {
00179         if(channel==-1) return "AO";
00180         if(channel==0) return "AO.R";
00181         if(channel==1) return "AO.G";
00182         return "AO.B";
00183     }
00184     if(passtype == SCE_PASS_ENVIRONMENT) {
00185         if(channel==-1) return "Env";
00186         if(channel==0) return "Env.R";
00187         if(channel==1) return "Env.G";
00188         return "Env.B";
00189     }
00190     if(passtype == SCE_PASS_INDIRECT) {
00191         if(channel==-1) return "Indirect";
00192         if(channel==0) return "Indirect.R";
00193         if(channel==1) return "Indirect.G";
00194         return "Indirect.B";
00195     }
00196     if(passtype == SCE_PASS_REFLECT) {
00197         if(channel==-1) return "Reflect";
00198         if(channel==0) return "Reflect.R";
00199         if(channel==1) return "Reflect.G";
00200         return "Reflect.B";
00201     }
00202     if(passtype == SCE_PASS_REFRACT) {
00203         if(channel==-1) return "Refract";
00204         if(channel==0) return "Refract.R";
00205         if(channel==1) return "Refract.G";
00206         return "Refract.B";
00207     }
00208     if(passtype == SCE_PASS_INDEXOB) {
00209         if(channel==-1) return "IndexOB";
00210         return "IndexOB.X";
00211     }
00212     if(passtype == SCE_PASS_INDEXMA) {
00213         if(channel==-1) return "IndexMA";
00214         return "IndexMA.X";
00215     }
00216     if(passtype == SCE_PASS_MIST) {
00217         if(channel==-1) return "Mist";
00218         return "Mist.Z";
00219     }
00220     if(passtype == SCE_PASS_RAYHITS)
00221     {
00222         if(channel==-1) return "Rayhits";
00223         if(channel==0) return "Rayhits.R";
00224         if(channel==1) return "Rayhits.G";
00225         return "Rayhits.B";
00226     }
00227     return "Unknown";
00228 }
00229 
00230 static int passtype_from_name(const char *str)
00231 {
00232     
00233     if(strcmp(str, "Combined")==0)
00234         return SCE_PASS_COMBINED;
00235 
00236     if(strcmp(str, "Depth")==0)
00237         return SCE_PASS_Z;
00238 
00239     if(strcmp(str, "Vector")==0)
00240         return SCE_PASS_VECTOR;
00241 
00242     if(strcmp(str, "Normal")==0)
00243         return SCE_PASS_NORMAL;
00244 
00245     if(strcmp(str, "UV")==0)
00246         return SCE_PASS_UV;
00247 
00248     if(strcmp(str, "Color")==0)
00249         return SCE_PASS_RGBA;
00250 
00251     if(strcmp(str, "Emit")==0)
00252         return SCE_PASS_EMIT;
00253 
00254     if(strcmp(str, "Diffuse")==0)
00255         return SCE_PASS_DIFFUSE;
00256 
00257     if(strcmp(str, "Spec")==0)
00258         return SCE_PASS_SPEC;
00259 
00260     if(strcmp(str, "Shadow")==0)
00261         return SCE_PASS_SHADOW;
00262     
00263     if(strcmp(str, "AO")==0)
00264         return SCE_PASS_AO;
00265 
00266     if(strcmp(str, "Env")==0)
00267         return SCE_PASS_ENVIRONMENT;
00268 
00269     if(strcmp(str, "Indirect")==0)
00270         return SCE_PASS_INDIRECT;
00271 
00272     if(strcmp(str, "Reflect")==0)
00273         return SCE_PASS_REFLECT;
00274 
00275     if(strcmp(str, "Refract")==0)
00276         return SCE_PASS_REFRACT;
00277 
00278     if(strcmp(str, "IndexOB")==0)
00279         return SCE_PASS_INDEXOB;
00280 
00281     if(strcmp(str, "IndexMA")==0)
00282         return SCE_PASS_INDEXMA;
00283 
00284     if(strcmp(str, "Mist")==0)
00285         return SCE_PASS_MIST;
00286     
00287     if(strcmp(str, "RayHits")==0)
00288         return SCE_PASS_RAYHITS;
00289     return 0;
00290 }
00291 
00292 /********************************** New **************************************/
00293 
00294 static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
00295 {
00296     const char *typestr= get_pass_name(passtype, 0);
00297     RenderPass *rpass= MEM_callocN(sizeof(RenderPass), typestr);
00298     int rectsize= rr->rectx*rr->recty*channels;
00299     
00300     BLI_addtail(&rl->passes, rpass);
00301     rpass->passtype= passtype;
00302     rpass->channels= channels;
00303     rpass->rectx= rl->rectx;
00304     rpass->recty= rl->recty;
00305     BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
00306     
00307     if(rr->exrhandle) {
00308         int a;
00309         for(a=0; a<channels; a++)
00310             IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
00311     }
00312     else {
00313         float *rect;
00314         int x;
00315         
00316         rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
00317         
00318         if(passtype==SCE_PASS_VECTOR) {
00319             /* initialize to max speed */
00320             rect= rpass->rect;
00321             for(x= rectsize-1; x>=0; x--)
00322                 rect[x]= PASS_VECTOR_MAX;
00323         }
00324         else if(passtype==SCE_PASS_Z) {
00325             rect= rpass->rect;
00326             for(x= rectsize-1; x>=0; x--)
00327                 rect[x]= 10e10;
00328         }
00329     }
00330 }
00331 
00332 /* called by main render as well for parts */
00333 /* will read info from Render *re to define layers */
00334 /* called in threads */
00335 /* re->winx,winy is coordinate space of entire image, partrct the part within */
00336 RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers)
00337 {
00338     RenderResult *rr;
00339     RenderLayer *rl;
00340     SceneRenderLayer *srl;
00341     int rectx, recty, nr;
00342     
00343     rectx= partrct->xmax - partrct->xmin;
00344     recty= partrct->ymax - partrct->ymin;
00345     
00346     if(rectx<=0 || recty<=0)
00347         return NULL;
00348     
00349     rr= MEM_callocN(sizeof(RenderResult), "new render result");
00350     rr->rectx= rectx;
00351     rr->recty= recty;
00352     rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop;
00353     /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
00354     rr->crop= crop;
00355     
00356     /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
00357     rr->tilerect.xmin= partrct->xmin - re->disprect.xmin;
00358     rr->tilerect.xmax= partrct->xmax - re->disprect.xmax;
00359     rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
00360     rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
00361     
00362     if(savebuffers) {
00363         rr->exrhandle= IMB_exr_get_handle();
00364     }
00365     
00366     /* check renderdata for amount of layers */
00367     for(nr=0, srl= re->r.layers.first; srl; srl= srl->next, nr++) {
00368         
00369         if((re->r.scemode & R_SINGLE_LAYER) && nr!=re->r.actlay)
00370             continue;
00371         if(srl->layflag & SCE_LAY_DISABLE)
00372             continue;
00373         
00374         rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
00375         BLI_addtail(&rr->layers, rl);
00376         
00377         BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
00378         rl->lay= srl->lay;
00379         rl->lay_zmask= srl->lay_zmask;
00380         rl->layflag= srl->layflag;
00381         rl->passflag= srl->passflag; // for debugging: srl->passflag|SCE_PASS_RAYHITS;
00382         rl->pass_xor= srl->pass_xor;
00383         rl->light_override= srl->light_override;
00384         rl->mat_override= srl->mat_override;
00385         rl->rectx= rectx;
00386         rl->recty= recty;
00387         
00388         if(rr->exrhandle) {
00389             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
00390             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
00391             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
00392             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
00393         }
00394         else
00395             rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
00396         
00397         if(srl->passflag  & SCE_PASS_Z)
00398             render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
00399         if(srl->passflag  & SCE_PASS_VECTOR)
00400             render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
00401         if(srl->passflag  & SCE_PASS_NORMAL)
00402             render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
00403         if(srl->passflag  & SCE_PASS_UV) 
00404             render_layer_add_pass(rr, rl, 3, SCE_PASS_UV);
00405         if(srl->passflag  & SCE_PASS_RGBA)
00406             render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA);
00407         if(srl->passflag  & SCE_PASS_EMIT)
00408             render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT);
00409         if(srl->passflag  & SCE_PASS_DIFFUSE)
00410             render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
00411         if(srl->passflag  & SCE_PASS_SPEC)
00412             render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
00413         if(srl->passflag  & SCE_PASS_AO)
00414             render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
00415         if(srl->passflag  & SCE_PASS_ENVIRONMENT)
00416             render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT);
00417         if(srl->passflag  & SCE_PASS_INDIRECT)
00418             render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT);
00419         if(srl->passflag  & SCE_PASS_SHADOW)
00420             render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
00421         if(srl->passflag  & SCE_PASS_REFLECT)
00422             render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
00423         if(srl->passflag  & SCE_PASS_REFRACT)
00424             render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
00425         if(srl->passflag  & SCE_PASS_INDEXOB)
00426             render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
00427         if(srl->passflag  & SCE_PASS_INDEXMA)
00428             render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
00429         if(srl->passflag  & SCE_PASS_MIST)
00430             render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
00431         if(rl->passflag & SCE_PASS_RAYHITS)
00432             render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
00433         
00434     }
00435     /* sss, previewrender and envmap don't do layers, so we make a default one */
00436     if(rr->layers.first==NULL) {
00437         rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
00438         BLI_addtail(&rr->layers, rl);
00439         
00440         rl->rectx= rectx;
00441         rl->recty= recty;
00442 
00443         /* duplicate code... */
00444         if(rr->exrhandle) {
00445             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
00446             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
00447             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
00448             IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
00449         }
00450         else
00451             rl->rectf= MEM_mapallocN(rectx*recty*sizeof(float)*4, "Combined rgba");
00452         
00453         /* note, this has to be in sync with scene.c */
00454         rl->lay= (1<<20) -1;
00455         rl->layflag= 0x7FFF;    /* solid ztra halo strand */
00456         rl->passflag= SCE_PASS_COMBINED;
00457         
00458         re->r.actlay= 0;
00459     }
00460     
00461     /* border render; calculate offset for use in compositor. compo is centralized coords */
00462     rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2;
00463     rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2;
00464     
00465     return rr;
00466 }
00467 
00468 /* allocate osa new results for samples */
00469 RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers)
00470 {
00471     int a;
00472     
00473     if(re->osa==0)
00474         return render_result_new(re, partrct, crop, savebuffers);
00475     
00476     for(a=0; a<re->osa; a++) {
00477         RenderResult *rr= render_result_new(re, partrct, crop, savebuffers);
00478         BLI_addtail(lb, rr);
00479         rr->sample_nr= a;
00480     }
00481     
00482     return lb->first;
00483 }
00484 
00485 /* callbacks for render_result_new_from_exr */
00486 static void *ml_addlayer_cb(void *base, char *str)
00487 {
00488     RenderResult *rr= base;
00489     RenderLayer *rl;
00490     
00491     rl= MEM_callocN(sizeof(RenderLayer), "new render layer");
00492     BLI_addtail(&rr->layers, rl);
00493     
00494     BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
00495     return rl;
00496 }
00497 
00498 static void ml_addpass_cb(void *UNUSED(base), void *lay, char *str, float *rect, int totchan, char *chan_id)
00499 {
00500     RenderLayer *rl= lay;   
00501     RenderPass *rpass= MEM_callocN(sizeof(RenderPass), "loaded pass");
00502     int a;
00503     
00504     BLI_addtail(&rl->passes, rpass);
00505     rpass->channels= totchan;
00506 
00507     rpass->passtype= passtype_from_name(str);
00508     if(rpass->passtype==0) printf("unknown pass %s\n", str);
00509     rl->passflag |= rpass->passtype;
00510     
00511     BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
00512     /* channel id chars */
00513     for(a=0; a<totchan; a++)
00514         rpass->chan_id[a]= chan_id[a];
00515     
00516     rpass->rect= rect;
00517 }
00518 
00519 /* from imbuf, if a handle was returned we convert this to render result */
00520 RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
00521 {
00522     RenderResult *rr= MEM_callocN(sizeof(RenderResult), "loaded render result");
00523     RenderLayer *rl;
00524     RenderPass *rpass;
00525     
00526     rr->rectx= rectx;
00527     rr->recty= recty;
00528     
00529     IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
00530 
00531     for(rl=rr->layers.first; rl; rl=rl->next) {
00532         rl->rectx= rectx;
00533         rl->recty= recty;
00534 
00535         for(rpass=rl->passes.first; rpass; rpass=rpass->next) {
00536             rpass->rectx= rectx;
00537             rpass->recty= recty;
00538         }
00539     }
00540     
00541     return rr;
00542 }
00543 
00544 /*********************************** Merge ***********************************/
00545 
00546 static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
00547 {
00548     int y, ofs, copylen, tilex, tiley;
00549     
00550     copylen= tilex= rrpart->rectx;
00551     tiley= rrpart->recty;
00552     
00553     if(rrpart->crop) {  /* filters add pixel extra */
00554         tile+= pixsize*(rrpart->crop + rrpart->crop*tilex);
00555         
00556         copylen= tilex - 2*rrpart->crop;
00557         tiley -= 2*rrpart->crop;
00558         
00559         ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
00560         target+= pixsize*ofs;
00561     }
00562     else {
00563         ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
00564         target+= pixsize*ofs;
00565     }
00566 
00567     copylen *= sizeof(float)*pixsize;
00568     tilex *= pixsize;
00569     ofs= pixsize*rr->rectx;
00570 
00571     for(y=0; y<tiley; y++) {
00572         memcpy(target, tile, copylen);
00573         target+= ofs;
00574         tile+= tilex;
00575     }
00576 }
00577 
00578 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
00579 /* no test happens here if it fits... we also assume layers are in sync */
00580 /* is used within threads */
00581 void render_result_merge(RenderResult *rr, RenderResult *rrpart)
00582 {
00583     RenderLayer *rl, *rlp;
00584     RenderPass *rpass, *rpassp;
00585     
00586     for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
00587         
00588         /* combined */
00589         if(rl->rectf && rlp->rectf)
00590             do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
00591         
00592         /* passes are allocated in sync */
00593         for(rpass= rl->passes.first, rpassp= rlp->passes.first; rpass && rpassp; rpass= rpass->next, rpassp= rpassp->next) {
00594             do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
00595         }
00596     }
00597 }
00598 
00599 /* for passes read from files, these have names stored */
00600 static char *make_pass_name(RenderPass *rpass, int chan)
00601 {
00602     static char name[16];
00603     int len;
00604     
00605     BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
00606     len= strlen(name);
00607     name[len]= '.';
00608     name[len+1]= rpass->chan_id[chan];
00609     name[len+2]= 0;
00610 
00611     return name;
00612 }
00613 
00614 /* filename already made absolute */
00615 /* called from within UI, saves both rendered result as a file-read result */
00616 int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
00617 {
00618     RenderLayer *rl;
00619     RenderPass *rpass;
00620     void *exrhandle= IMB_exr_get_handle();
00621     int success;
00622 
00623     BLI_make_existing_file(filename);
00624     
00625     /* composite result */
00626     if(rr->rectf) {
00627         IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4*rr->rectx, rr->rectf);
00628         IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4*rr->rectx, rr->rectf+1);
00629         IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4*rr->rectx, rr->rectf+2);
00630         IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4*rr->rectx, rr->rectf+3);
00631     }
00632     
00633     /* add layers/passes and assign channels */
00634     for(rl= rr->layers.first; rl; rl= rl->next) {
00635         
00636         /* combined */
00637         if(rl->rectf) {
00638             int a, xstride= 4;
00639             for(a=0; a<xstride; a++)
00640                 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
00641                                     xstride, xstride*rr->rectx, rl->rectf+a);
00642         }
00643         
00644         /* passes are allocated in sync */
00645         for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
00646             int a, xstride= rpass->channels;
00647             for(a=0; a<xstride; a++) {
00648                 if(rpass->passtype)
00649                     IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
00650                                         xstride, xstride*rr->rectx, rpass->rect+a);
00651                 else
00652                     IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 
00653                                         xstride, xstride*rr->rectx, rpass->rect+a);
00654             }
00655         }
00656     }
00657 
00658     /* when the filename has no permissions, this can fail */
00659     if(IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
00660         IMB_exr_write_channels(exrhandle);
00661         success= TRUE;
00662     }
00663     else {
00664         /* TODO, get the error from openexr's exception */
00665         BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console");
00666         success= FALSE;
00667     }
00668     IMB_exr_close(exrhandle);
00669 
00670     return success;
00671 }
00672 
00673 /**************************** Single Layer Rendering *************************/
00674 
00675 void render_result_single_layer_begin(Render *re)
00676 {
00677     /* all layers except the active one get temporally pushed away */
00678 
00679     /* officially pushed result should be NULL... error can happen with do_seq */
00680     RE_FreeRenderResult(re->pushedresult);
00681     
00682     re->pushedresult= re->result;
00683     re->result= NULL;
00684 }
00685 
00686 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
00687 void render_result_single_layer_end(Render *re)
00688 {
00689     SceneRenderLayer *srl;
00690     RenderLayer *rlpush;
00691     RenderLayer *rl;
00692     int nr;
00693 
00694     if(re->result==NULL) {
00695         printf("pop render result error; no current result!\n");
00696         return;
00697     }
00698 
00699     if(!re->pushedresult)
00700         return;
00701 
00702     if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) {
00703         /* find which layer in re->pushedresult should be replaced */
00704         rl= re->result->layers.first;
00705         
00706         /* render result should be empty after this */
00707         BLI_remlink(&re->result->layers, rl);
00708         
00709         /* reconstruct render result layers */
00710         for(nr=0, srl= re->scene->r.layers.first; srl; srl= srl->next, nr++) {
00711             if(nr==re->r.actlay)
00712                 BLI_addtail(&re->result->layers, rl);
00713             else {
00714                 rlpush= RE_GetRenderLayer(re->pushedresult, srl->name);
00715                 if(rlpush) {
00716                     BLI_remlink(&re->pushedresult->layers, rlpush);
00717                     BLI_addtail(&re->result->layers, rlpush);
00718                 }
00719             }
00720         }
00721     }
00722 
00723     RE_FreeRenderResult(re->pushedresult);
00724     re->pushedresult= NULL;
00725 }
00726 
00727 /************************* EXR Tile File Rendering ***************************/
00728 
00729 static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
00730 {
00731     RenderLayer *rlp;
00732     RenderPass *rpassp;
00733     int offs, partx, party;
00734     
00735     BLI_lock_thread(LOCK_IMAGE);
00736     
00737     for(rlp= rrpart->layers.first; rlp; rlp= rlp->next) {
00738         
00739         if(rrpart->crop) {  /* filters add pixel extra */
00740             offs= (rrpart->crop + rrpart->crop*rrpart->rectx);
00741         }
00742         else {
00743             offs= 0;
00744         }
00745         
00746         /* combined */
00747         if(rlp->rectf) {
00748             int a, xstride= 4;
00749             for(a=0; a<xstride; a++)
00750                 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
00751                                 xstride, xstride*rrpart->rectx, rlp->rectf+a + xstride*offs);
00752         }
00753         
00754         /* passes are allocated in sync */
00755         for(rpassp= rlp->passes.first; rpassp; rpassp= rpassp->next) {
00756             int a, xstride= rpassp->channels;
00757             for(a=0; a<xstride; a++)
00758                 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
00759                                     xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs);
00760         }
00761         
00762     }
00763 
00764     party= rrpart->tilerect.ymin + rrpart->crop;
00765     partx= rrpart->tilerect.xmin + rrpart->crop;
00766     IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
00767 
00768     BLI_unlock_thread(LOCK_IMAGE);
00769 }
00770 
00771 static void save_empty_result_tiles(Render *re)
00772 {
00773     RenderPart *pa;
00774     RenderResult *rr;
00775     
00776     for(rr= re->result; rr; rr= rr->next) {
00777         IMB_exrtile_clear_channels(rr->exrhandle);
00778         
00779         for(pa= re->parts.first; pa; pa= pa->next) {
00780             if(pa->ready==0) {
00781                 int party= pa->disprect.ymin - re->disprect.ymin + pa->crop;
00782                 int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop;
00783                 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
00784             }
00785         }
00786     }
00787 }
00788 
00789 /* begin write of exr tile file */
00790 void render_result_exr_file_begin(Render *re)
00791 {
00792     RenderResult *rr;
00793     char str[FILE_MAX];
00794     
00795     for(rr= re->result; rr; rr= rr->next) {
00796         render_result_exr_file_path(re->scene, rr->sample_nr, str);
00797     
00798         printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
00799         IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
00800     }
00801 }
00802 
00803 /* end write of exr tile file, read back first sample */
00804 void render_result_exr_file_end(Render *re)
00805 {
00806     RenderResult *rr;
00807 
00808     save_empty_result_tiles(re);
00809     
00810     for(rr= re->result; rr; rr= rr->next) {
00811         IMB_exr_close(rr->exrhandle);
00812         rr->exrhandle= NULL;
00813     }
00814     
00815     render_result_free_list(&re->fullresult, re->result);
00816     re->result= NULL;
00817 
00818     render_result_exr_file_read(re, 0);
00819 }
00820 
00821 /* save part into exr file */
00822 void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
00823 {
00824     for(; rr && rrpart; rr= rr->next, rrpart= rrpart->next)
00825         save_render_result_tile(rr, rrpart);
00826 }
00827 
00828 /* path to temporary exr file */
00829 void render_result_exr_file_path(Scene *scene, int sample, char *filepath)
00830 {
00831     char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE];
00832     
00833     BLI_strncpy(di, G.main->name, FILE_MAX);
00834     BLI_splitdirstring(di, fi);
00835     
00836     if(sample==0)
00837         BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name+2);
00838     else
00839         BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name+2, sample);
00840 
00841     BLI_make_file_string("/", filepath, BLI_temporary_dir(), name);
00842 }
00843 
00844 /* only for temp buffer files, makes exact copy of render result */
00845 int render_result_exr_file_read(Render *re, int sample)
00846 {
00847     char str[FILE_MAX];
00848     int success;
00849 
00850     RE_FreeRenderResult(re->result);
00851     re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
00852 
00853     render_result_exr_file_path(re->scene, sample, str);
00854     printf("read exr tmp file: %s\n", str);
00855 
00856     if(render_result_exr_file_read_path(re->result, str)) {
00857         success= TRUE;
00858     }
00859     else {
00860         printf("cannot read: %s\n", str);
00861         success= FALSE;
00862 
00863     }
00864 
00865     return success;
00866 }
00867 
00868 /* called for reading temp files, and for external engines */
00869 int render_result_exr_file_read_path(RenderResult *rr, const char *filepath)
00870 {
00871     RenderLayer *rl;
00872     RenderPass *rpass;
00873     void *exrhandle= IMB_exr_get_handle();
00874     int rectx, recty;
00875 
00876     if(IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty)==0) {
00877         printf("failed being read %s\n", filepath);
00878         IMB_exr_close(exrhandle);
00879         return 0;
00880     }
00881 
00882     if(rr == NULL || rectx!=rr->rectx || recty!=rr->recty) {
00883         if(rr)
00884             printf("error in reading render result: dimensions don't match\n");
00885         else
00886             printf("error in reading render result: NULL result pointer\n");
00887         IMB_exr_close(exrhandle);
00888         return 0;
00889     }
00890 
00891     for(rl= rr->layers.first; rl; rl= rl->next) {
00892         /* combined */
00893         if(rl->rectf) {
00894             int a, xstride= 4;
00895             for(a=0; a<xstride; a++)
00896                 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
00897                                     xstride, xstride*rectx, rl->rectf+a);
00898         }
00899         
00900         /* passes are allocated in sync */
00901         for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
00902             int a, xstride= rpass->channels;
00903             for(a=0; a<xstride; a++)
00904                 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
00905                                     xstride, xstride*rectx, rpass->rect+a);
00906 
00907             BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
00908         }
00909     }
00910 
00911     IMB_exr_read_channels(exrhandle);
00912     IMB_exr_close(exrhandle);
00913 
00914     return 1;
00915 }
00916 
00917 /*************************** Combined Pixel Rect *****************************/
00918 
00919 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
00920 {
00921     int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE)? IB_cm_predivide: 0;
00922     ImBuf *ibuf= IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
00923     
00924     /* if not exists, BKE_write_ibuf makes one */
00925     ibuf->rect= (unsigned int *)rr->rect32;    
00926     ibuf->rect_float= rr->rectf;
00927     ibuf->zbuf_float= rr->rectz;
00928     
00929     /* float factor for random dither, imbuf takes care of it */
00930     ibuf->dither= rd->dither_intensity;
00931     
00932     /* prepare to gamma correct to sRGB color space */
00933     if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
00934         /* sequence editor can generate 8bpc render buffers */
00935         if (ibuf->rect) {
00936             ibuf->profile = IB_PROFILE_SRGB;
00937             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))
00938                 IMB_float_from_rect(ibuf);
00939         } else {                
00940             ibuf->profile = IB_PROFILE_LINEAR_RGB;
00941         }
00942     }
00943 
00944     /* color -> greyscale */
00945     /* editing directly would alter the render view */
00946     if(rd->im_format.planes == R_IMF_PLANES_BW) {
00947         ImBuf *ibuf_bw= IMB_dupImBuf(ibuf);
00948         IMB_color_to_bw(ibuf_bw);
00949         IMB_freeImBuf(ibuf);
00950         ibuf= ibuf_bw;
00951     }
00952 
00953     return ibuf;
00954 }
00955 
00956 void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf)
00957 {
00958     if(ibuf->rect_float) {
00959         /* color management: when off ensure rectf is non-lin, since thats what the internal
00960          * render engine delivers */
00961         int profile_to= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
00962         int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
00963         int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
00964 
00965         if (!rr->rectf)
00966             rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
00967         
00968         IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
00969             4, profile_to, profile_from, predivide,
00970             rr->rectx, rr->recty, rr->rectx, rr->rectx);
00971         
00972         /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
00973            can hang around when sequence render has rendered a 32 bits one before */
00974         if(rr->rect32) {
00975             MEM_freeN(rr->rect32);
00976             rr->rect32= NULL;
00977         }
00978     }
00979     else if(ibuf->rect) {
00980         if (!rr->rect32)
00981             rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
00982 
00983         memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
00984 
00985         /* Same things as above, old rectf can hang around from previous render. */
00986         if(rr->rectf) {
00987             MEM_freeN(rr->rectf);
00988             rr->rectf= NULL;
00989         }
00990     }
00991 }
00992 
00993 void render_result_rect_fill_zero(RenderResult *rr)
00994 {
00995     if (rr->rectf)
00996         memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
00997     else if (rr->rect32)
00998         memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
00999     else
01000         rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
01001 }
01002 
01003 void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty)
01004 {
01005     if(rr->rect32) {
01006         memcpy(rect, rr->rect32, sizeof(int)*rr->rectx*rr->recty);
01007     }
01008     else if(rr->rectf) {
01009         int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
01010         int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
01011         int dither= 0;
01012 
01013         IMB_buffer_byte_from_float((unsigned char*)rect, rr->rectf,
01014             4, dither, IB_PROFILE_SRGB, profile_from, predivide,
01015             rr->rectx, rr->recty, rr->rectx, rr->rectx);
01016     }
01017     else
01018         /* else fill with black */
01019         memset(rect, 0, sizeof(int)*rectx*recty);
01020 }
01021