Blender V2.61 - r43446

pipeline.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 
00034 #include <math.h>
00035 #include <limits.h>
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include <stddef.h>
00039 
00040 #include "DNA_group_types.h"
00041 #include "DNA_image_types.h"
00042 #include "DNA_node_types.h"
00043 #include "DNA_object_types.h"
00044 #include "DNA_scene_types.h"
00045 #include "DNA_sequence_types.h"
00046 #include "DNA_userdef_types.h"
00047 
00048 #include "MEM_guardedalloc.h"
00049 
00050 #include "BKE_animsys.h"    /* <------ should this be here?, needed for sequencer update */
00051 #include "BKE_camera.h"
00052 #include "BKE_global.h"
00053 #include "BKE_image.h"
00054 #include "BKE_main.h"
00055 #include "BKE_node.h"
00056 #include "BKE_pointcache.h"
00057 #include "BKE_report.h"
00058 #include "BKE_scene.h"
00059 #include "BKE_sequencer.h"
00060 #include "BKE_utildefines.h"
00061 #include "BKE_writeavi.h"   /* <------ should be replaced once with generic movie module */
00062 
00063 #include "BLI_math.h"
00064 #include "BLI_listbase.h"
00065 #include "BLI_string.h"
00066 #include "BLI_path_util.h"
00067 #include "BLI_fileops.h"
00068 #include "BLI_rand.h"
00069 #include "BLI_callbacks.h"
00070 
00071 #include "PIL_time.h"
00072 #include "IMB_imbuf.h"
00073 #include "IMB_imbuf_types.h"
00074 
00075 #include "RE_engine.h"
00076 #include "RE_pipeline.h"
00077 
00078 /* internal */
00079 #include "render_result.h"
00080 #include "render_types.h"
00081 #include "renderpipeline.h"
00082 #include "renderdatabase.h"
00083 #include "rendercore.h"
00084 #include "initrender.h"
00085 #include "shadbuf.h"
00086 #include "pixelblending.h"
00087 #include "zbuf.h"
00088 
00089 
00090 /* render flow
00091 
00092 1) Initialize state
00093 - state data, tables
00094 - movie/image file init
00095 - everything that doesn't change during animation
00096 
00097 2) Initialize data
00098 - camera, world, matrices
00099 - make render verts, faces, halos, strands
00100 - everything can change per frame/field
00101 
00102 3) Render Processor
00103 - multiple layers
00104 - tiles, rect, baking
00105 - layers/tiles optionally to disk or directly in Render Result
00106 
00107 4) Composite Render Result
00108 - also read external files etc
00109 
00110 5) Image Files
00111 - save file or append in movie
00112 
00113 */
00114 
00115 
00116 /* ********* globals ******** */
00117 
00118 /* here we store all renders */
00119 static struct {
00120     ListBase renderlist;
00121 
00122     /* commandline thread override */
00123     int threads;
00124 } RenderGlobal = {{NULL, NULL}, -1}; 
00125 
00126 /* hardcopy of current render, used while rendering for speed */
00127 Render R;
00128 
00129 /* ********* alloc and free ******** */
00130 
00131 static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override);
00132 
00133 static volatile int g_break= 0;
00134 static int thread_break(void *UNUSED(arg))
00135 {
00136     return g_break;
00137 }
00138 
00139 /* default callbacks, set in each new render */
00140 static void result_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr)) {}
00141 static void result_rcti_nothing(void *UNUSED(arg), RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) {}
00142 static void stats_nothing(void *UNUSED(arg), RenderStats *UNUSED(rs)) {}
00143 static void float_nothing(void *UNUSED(arg), float UNUSED(val)) {}
00144 static int default_break(void *UNUSED(arg)) {return G.afbreek == 1;}
00145 
00146 static void stats_background(void *UNUSED(arg), RenderStats *rs)
00147 {
00148     uintptr_t mem_in_use, mmap_in_use, peak_memory;
00149     float megs_used_memory, mmap_used_memory, megs_peak_memory;
00150 
00151     mem_in_use= MEM_get_memory_in_use();
00152     mmap_in_use= MEM_get_mapped_memory_in_use();
00153     peak_memory = MEM_get_peak_memory();
00154 
00155     megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
00156     mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
00157     megs_peak_memory = (peak_memory)/(1024.0*1024.0);
00158 
00159     fprintf(stdout, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra,
00160             megs_used_memory, mmap_used_memory, megs_peak_memory);
00161 
00162     if(rs->curfield)
00163         fprintf(stdout, "Field %d ", rs->curfield);
00164     if(rs->curblur)
00165         fprintf(stdout, "Blur %d ", rs->curblur);
00166 
00167     if(rs->infostr) {
00168         fprintf(stdout, "| %s", rs->infostr);
00169     }
00170     else {
00171         if(rs->tothalo)
00172             fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
00173         else
00174             fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scenename, rs->totvert, rs->totface, rs->totlamp);
00175     }
00176 
00177     BLI_exec_cb(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
00178 
00179     fputc('\n', stdout);
00180     fflush(stdout);
00181 }
00182 
00183 void RE_FreeRenderResult(RenderResult *res)
00184 {
00185     render_result_free(res);
00186 }
00187 
00188 float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype)
00189 {
00190     RenderPass *rpass;
00191     
00192     for(rpass=rl->passes.first; rpass; rpass= rpass->next)
00193         if(rpass->passtype== passtype)
00194             return rpass->rect;
00195     return NULL;
00196 }
00197 
00198 RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
00199 {
00200     RenderLayer *rl;
00201     
00202     if(rr==NULL) return NULL;
00203     
00204     for(rl= rr->layers.first; rl; rl= rl->next)
00205         if(strncmp(rl->name, name, RE_MAXNAME)==0)
00206             return rl;
00207     return NULL;
00208 }
00209 
00210 RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty)
00211 {
00212     return render_result_new_from_exr(exrhandle, rectx, recty);
00213 }
00214 
00215 RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
00216 {
00217     RenderLayer *rl= BLI_findlink(&rr->layers, re->r.actlay);
00218     
00219     if(rl) 
00220         return rl;
00221     else 
00222         return rr->layers.first;
00223 }
00224 
00225 static int render_scene_needs_vector(Render *re)
00226 {
00227     SceneRenderLayer *srl;
00228     
00229     for(srl= re->scene->r.layers.first; srl; srl= srl->next)
00230         if(!(srl->layflag & SCE_LAY_DISABLE))
00231             if(srl->passflag & SCE_PASS_VECTOR)
00232                 return 1;
00233 
00234     return 0;
00235 }
00236 
00237 /* *************************************************** */
00238 
00239 Render *RE_GetRender(const char *name)
00240 {
00241     Render *re;
00242 
00243     /* search for existing renders */
00244     for(re= RenderGlobal.renderlist.first; re; re= re->next)
00245         if(strncmp(re->name, name, RE_MAXNAME)==0)
00246             break;
00247 
00248     return re;
00249 }
00250 
00251 /* if you want to know exactly what has been done */
00252 RenderResult *RE_AcquireResultRead(Render *re)
00253 {
00254     if(re) {
00255         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
00256         return re->result;
00257     }
00258 
00259     return NULL;
00260 }
00261 
00262 RenderResult *RE_AcquireResultWrite(Render *re)
00263 {
00264     if(re) {
00265         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
00266         return re->result;
00267     }
00268 
00269     return NULL;
00270 }
00271 
00272 void RE_SwapResult(Render *re, RenderResult **rr)
00273 {
00274     /* for keeping render buffers */
00275     if(re) {
00276         SWAP(RenderResult*, re->result, *rr);
00277     }
00278 }
00279 
00280 
00281 void RE_ReleaseResult(Render *re)
00282 {
00283     if(re)
00284         BLI_rw_mutex_unlock(&re->resultmutex);
00285 }
00286 
00287 /* displist.c util.... */
00288 Scene *RE_GetScene(Render *re)
00289 {
00290     if(re)
00291         return re->scene;
00292     return NULL;
00293 }
00294 
00295 /* fill provided result struct with what's currently active or done */
00296 void RE_AcquireResultImage(Render *re, RenderResult *rr)
00297 {
00298     memset(rr, 0, sizeof(RenderResult));
00299 
00300     if(re) {
00301         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ);
00302 
00303         if(re->result) {
00304             RenderLayer *rl;
00305             
00306             rr->rectx= re->result->rectx;
00307             rr->recty= re->result->recty;
00308             
00309             rr->rectf= re->result->rectf;
00310             rr->rectz= re->result->rectz;
00311             rr->rect32= re->result->rect32;
00312             
00313             /* active layer */
00314             rl= render_get_active_layer(re, re->result);
00315 
00316             if(rl) {
00317                 if(rr->rectf==NULL)
00318                     rr->rectf= rl->rectf;
00319                 if(rr->rectz==NULL)
00320                     rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z);   
00321             }
00322 
00323             rr->have_combined= (re->result->rectf != NULL);
00324             rr->layers= re->result->layers;
00325         }
00326     }
00327 }
00328 
00329 void RE_ReleaseResultImage(Render *re)
00330 {
00331     if(re)
00332         BLI_rw_mutex_unlock(&re->resultmutex);
00333 }
00334 
00335 /* caller is responsible for allocating rect in correct size! */
00336 void RE_ResultGet32(Render *re, unsigned int *rect)
00337 {
00338     RenderResult rres;
00339     
00340     RE_AcquireResultImage(re, &rres);
00341     render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty);
00342     RE_ReleaseResultImage(re);
00343 }
00344 
00345 RenderStats *RE_GetStats(Render *re)
00346 {
00347     return &re->i;
00348 }
00349 
00350 Render *RE_NewRender(const char *name)
00351 {
00352     Render *re;
00353 
00354     /* only one render per name exists */
00355     re= RE_GetRender(name);
00356     if(re==NULL) {
00357         
00358         /* new render data struct */
00359         re= MEM_callocN(sizeof(Render), "new render");
00360         BLI_addtail(&RenderGlobal.renderlist, re);
00361         BLI_strncpy(re->name, name, RE_MAXNAME);
00362         BLI_rw_mutex_init(&re->resultmutex);
00363     }
00364     
00365     RE_InitRenderCB(re);
00366 
00367     /* init some variables */
00368     re->ycor= 1.0f;
00369     
00370     return re;
00371 }
00372 
00373 /* called for new renders and when finishing rendering so
00374  * we calways have valid callbacks on a render */
00375 void RE_InitRenderCB(Render *re)
00376 {
00377     /* set default empty callbacks */
00378     re->display_init= result_nothing;
00379     re->display_clear= result_nothing;
00380     re->display_draw= result_rcti_nothing;
00381     re->progress= float_nothing;
00382     re->test_break= default_break;
00383     if(G.background)
00384         re->stats_draw= stats_background;
00385     else
00386         re->stats_draw= stats_nothing;
00387     /* clear callback handles */
00388     re->dih= re->dch= re->ddh= re->sdh= re->prh= re->tbh= NULL;
00389 }
00390 
00391 /* only call this while you know it will remove the link too */
00392 void RE_FreeRender(Render *re)
00393 {
00394     BLI_rw_mutex_end(&re->resultmutex);
00395     
00396     free_renderdata_tables(re);
00397     free_sample_tables(re);
00398     
00399     render_result_free(re->result);
00400     render_result_free(re->pushedresult);
00401     
00402     BLI_remlink(&RenderGlobal.renderlist, re);
00403     MEM_freeN(re);
00404 }
00405 
00406 /* exit blender */
00407 void RE_FreeAllRender(void)
00408 {
00409     while(RenderGlobal.renderlist.first) {
00410         RE_FreeRender(RenderGlobal.renderlist.first);
00411     }
00412 }
00413 
00414 /* ********* initialize state ******** */
00415 
00416 
00417 /* what doesn't change during entire render sequence */
00418 /* disprect is optional, if NULL it assumes full window render */
00419 void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *srl, int winx, int winy, rcti *disprect)
00420 {
00421     re->ok= TRUE;   /* maybe flag */
00422     
00423     re->i.starttime= PIL_check_seconds_timer();
00424     re->r= *rd;     /* hardcopy */
00425     
00426     re->winx= winx;
00427     re->winy= winy;
00428     if(disprect) {
00429         re->disprect= *disprect;
00430         re->rectx= disprect->xmax-disprect->xmin;
00431         re->recty= disprect->ymax-disprect->ymin;
00432     }
00433     else {
00434         re->disprect.xmin= re->disprect.ymin= 0;
00435         re->disprect.xmax= winx;
00436         re->disprect.ymax= winy;
00437         re->rectx= winx;
00438         re->recty= winy;
00439     }
00440     
00441     if(re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
00442                                           (re->rectx < 16 || re->recty < 16) )) {
00443         BKE_report(re->reports, RPT_ERROR, "Image too small");
00444         re->ok= 0;
00445         return;
00446     }
00447 
00448     if((re->r.mode & (R_OSA))==0)
00449         re->r.scemode &= ~R_FULL_SAMPLE;
00450 
00451 #ifdef WITH_OPENEXR
00452     if(re->r.scemode & R_FULL_SAMPLE)
00453         re->r.scemode |= R_EXR_TILE_FILE;   /* enable automatic */
00454 
00455     /* Until use_border is made compatible with save_buffers/full_sample, render without the later instead of not rendering at all.*/
00456     if(re->r.mode & R_BORDER) 
00457     {
00458         re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE);
00459     }
00460 
00461 #else
00462     /* can't do this without openexr support */
00463     re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE);
00464 #endif
00465     
00466     /* fullsample wants uniform osa levels */
00467     if(source && (re->r.scemode & R_FULL_SAMPLE)) {
00468         /* but, if source has no full sample we disable it */
00469         if((source->r.scemode & R_FULL_SAMPLE)==0)
00470             re->r.scemode &= ~R_FULL_SAMPLE;
00471         else
00472             re->r.osa= re->osa= source->osa;
00473     }
00474     else {
00475         /* check state variables, osa? */
00476         if(re->r.mode & (R_OSA)) {
00477             re->osa= re->r.osa;
00478             if(re->osa>16) re->osa= 16;
00479         }
00480         else re->osa= 0;
00481     }
00482     
00483     if (srl) {
00484         int index = BLI_findindex(&re->r.layers, srl);
00485         if (index != -1) {
00486             re->r.actlay = index;
00487             re->r.scemode |= R_SINGLE_LAYER;
00488         }
00489     }
00490         
00491     /* always call, checks for gamma, gamma tables and jitter too */
00492     make_sample_tables(re); 
00493     
00494     /* if preview render, we try to keep old result */
00495     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
00496 
00497     if(re->r.scemode & R_PREVIEWBUTS) {
00498         if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty);
00499         else {
00500             render_result_free(re->result);
00501             re->result= NULL;
00502         }
00503     }
00504     else {
00505         
00506         /* make empty render result, so display callbacks can initialize */
00507         render_result_free(re->result);
00508         re->result= MEM_callocN(sizeof(RenderResult), "new render result");
00509         re->result->rectx= re->rectx;
00510         re->result->recty= re->recty;
00511     }
00512 
00513     BLI_rw_mutex_unlock(&re->resultmutex);
00514     
00515     /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */
00516     re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx);
00517     
00518     re->mblur_offs = re->field_offs = 0.f;
00519     
00520     RE_init_threadcount(re);
00521 }
00522 
00523 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
00524 {
00525     /* re->ok flag? */
00526     
00527     re->viewplane= *viewplane;
00528     re->clipsta= clipsta;
00529     re->clipend= clipend;
00530     re->r.mode &= ~R_ORTHO;
00531 
00532     perspective_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend);
00533     
00534 }
00535 
00536 void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
00537 {
00538     /* re->ok flag? */
00539     
00540     re->viewplane= *viewplane;
00541     re->clipsta= clipsta;
00542     re->clipend= clipend;
00543     re->r.mode |= R_ORTHO;
00544 
00545     orthographic_m4( re->winmat,re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend);
00546 }
00547 
00548 void RE_SetView(Render *re, float mat[][4])
00549 {
00550     /* re->ok flag? */
00551     copy_m4_m4(re->viewmat, mat);
00552     invert_m4_m4(re->viewinv, re->viewmat);
00553 }
00554 
00555 /* image and movie output has to move to either imbuf or kernel */
00556 void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))
00557 {
00558     re->display_init= f;
00559     re->dih= handle;
00560 }
00561 void RE_display_clear_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))
00562 {
00563     re->display_clear= f;
00564     re->dch= handle;
00565 }
00566 void RE_display_draw_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr, volatile rcti *rect))
00567 {
00568     re->display_draw= f;
00569     re->ddh= handle;
00570 }
00571 void RE_stats_draw_cb(Render *re, void *handle, void (*f)(void *handle, RenderStats *rs))
00572 {
00573     re->stats_draw= f;
00574     re->sdh= handle;
00575 }
00576 void RE_progress_cb(Render *re, void *handle, void (*f)(void *handle, float))
00577 {
00578     re->progress= f;
00579     re->prh= handle;
00580 }
00581 
00582 void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i))
00583 {
00584     re->draw_lock= f;
00585     re->tbh= handle;
00586 }
00587 
00588 void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
00589 {
00590     re->test_break= f;
00591     re->tbh= handle;
00592 }
00593 
00594 
00595 /* ********* add object data (later) ******** */
00596 
00597 /* object is considered fully prepared on correct time etc */
00598 /* includes lights */
00599 #if 0
00600 void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob))
00601 {
00602     
00603 }
00604 #endif
00605 
00606 /* *************************************** */
00607 
00608 static int render_display_draw_enabled(Render *re)
00609 {
00610     /* don't show preprocess for previewrender sss */
00611     if(re->sss_points)
00612         return !(re->r.scemode & R_PREVIEWBUTS);
00613     else
00614         return 1;
00615 }
00616 
00617 /* the main thread call, renders an entire part */
00618 static void *do_part_thread(void *pa_v)
00619 {
00620     RenderPart *pa= pa_v;
00621     
00622     /* need to return nicely all parts on esc */
00623     if(R.test_break(R.tbh)==0) {
00624         
00625         if(!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
00626             pa->result= render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM);
00627         else
00628             pa->result= render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM);
00629 
00630         if(R.sss_points)
00631             zbufshade_sss_tile(pa);
00632         else if(R.osa)
00633             zbufshadeDA_tile(pa);
00634         else
00635             zbufshade_tile(pa);
00636         
00637         /* merge too on break! */
00638         if(R.result->exrhandle) {
00639             render_result_exr_file_merge(R.result, pa->result);
00640         }
00641         else if(render_display_draw_enabled(&R)) {
00642             /* on break, don't merge in result for preview renders, looks nicer */
00643             if(R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS));
00644             else render_result_merge(R.result, pa->result);
00645         }
00646     }
00647     
00648     pa->ready= 1;
00649     
00650     return NULL;
00651 }
00652 
00653 /* calculus for how much 1 pixel rendered should rotate the 3d geometry */
00654 /* is not that simple, needs to be corrected for errors of larger viewplane sizes */
00655 /* called in initrender.c, initparts() and convertblender.c, for speedvectors */
00656 float panorama_pixel_rot(Render *re)
00657 {
00658     float psize, phi, xfac;
00659     float borderfac= (float)(re->disprect.xmax - re->disprect.xmin) / (float)re->winx;
00660     
00661     /* size of 1 pixel mapped to viewplane coords */
00662     psize= (re->viewplane.xmax-re->viewplane.xmin)/(float)(re->winx);
00663     /* angle of a pixel */
00664     phi= atan(psize/re->clipsta);
00665     
00666     /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */
00667     xfac= borderfac*((re->viewplane.xmax-re->viewplane.xmin))/(float)re->xparts;
00668     xfac= atan(0.5f*xfac/re->clipsta); 
00669     /* and how much the same viewplane angle is wrapped */
00670     psize= 0.5f*phi*((float)re->partx);
00671     
00672     /* the ratio applied to final per-pixel angle */
00673     phi*= xfac/psize;
00674     
00675     return phi;
00676 }
00677 
00678 /* call when all parts stopped rendering, to find the next Y slice */
00679 /* if slice found, it rotates the dbase */
00680 static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
00681 {
00682     RenderPart *pa, *best= NULL;
00683     
00684     *minx= re->winx;
00685     
00686     /* most left part of the non-rendering parts */
00687     for(pa= re->parts.first; pa; pa= pa->next) {
00688         if(pa->ready==0 && pa->nr==0) {
00689             if(pa->disprect.xmin < *minx) {
00690                 best= pa;
00691                 *minx= pa->disprect.xmin;
00692             }
00693         }
00694     }
00695             
00696     if(best) {
00697         float phi= panorama_pixel_rot(re);
00698 
00699         R.panodxp= (re->winx - (best->disprect.xmin + best->disprect.xmax) )/2;
00700         R.panodxv= ((viewplane->xmax-viewplane->xmin)*R.panodxp)/(float)(re->winx);
00701 
00702         /* shift viewplane */
00703         R.viewplane.xmin = viewplane->xmin + R.panodxv;
00704         R.viewplane.xmax = viewplane->xmax + R.panodxv;
00705         RE_SetWindow(re, &R.viewplane, R.clipsta, R.clipend);
00706         copy_m4_m4(R.winmat, re->winmat);
00707         
00708         /* rotate database according to part coordinates */
00709         project_renderdata(re, projectverto, 1, -R.panodxp*phi, 1);
00710         R.panosi= sin(R.panodxp*phi);
00711         R.panoco= cos(R.panodxp*phi);
00712     }
00713     return best;
00714 }
00715 
00716 static RenderPart *find_next_part(Render *re, int minx)
00717 {
00718     RenderPart *pa, *best= NULL;
00719 
00720     /* long long int's needed because of overflow [#24414] */
00721     long long int centx=re->winx/2, centy=re->winy/2, tot=1;
00722     long long int mindist= (long long int)re->winx * (long long int)re->winy;
00723     
00724     /* find center of rendered parts, image center counts for 1 too */
00725     for(pa= re->parts.first; pa; pa= pa->next) {
00726         if(pa->ready) {
00727             centx+= (pa->disprect.xmin+pa->disprect.xmax)/2;
00728             centy+= (pa->disprect.ymin+pa->disprect.ymax)/2;
00729             tot++;
00730         }
00731     }
00732     centx/=tot;
00733     centy/=tot;
00734     
00735     /* closest of the non-rendering parts */
00736     for(pa= re->parts.first; pa; pa= pa->next) {
00737         if(pa->ready==0 && pa->nr==0) {
00738             long long int distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2;
00739             long long int disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2;
00740             distx= (long long int)sqrt(distx*distx + disty*disty);
00741             if(distx<mindist) {
00742                 if(re->r.mode & R_PANORAMA) {
00743                     if(pa->disprect.xmin==minx) {
00744                         best= pa;
00745                         mindist= distx;
00746                     }
00747                 }
00748                 else {
00749                     best= pa;
00750                     mindist= distx;
00751                 }
00752             }
00753         }
00754     }
00755     return best;
00756 }
00757 
00758 static void print_part_stats(Render *re, RenderPart *pa)
00759 {
00760     char str[64];
00761     
00762     BLI_snprintf(str, sizeof(str), "%s, Part %d-%d", re->scene->id.name+2, pa->nr, re->i.totpart);
00763     re->i.infostr= str;
00764     re->stats_draw(re->sdh, &re->i);
00765     re->i.infostr= NULL;
00766 }
00767 
00768 static void threaded_tile_processor(Render *re)
00769 {
00770     ListBase threads;
00771     RenderPart *pa, *nextpa;
00772     rctf viewplane= re->viewplane;
00773     int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0;
00774     
00775     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
00776 
00777     /* first step; free the entire render result, make new, and/or prepare exr buffer saving */
00778     if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
00779         render_result_free(re->result);
00780     
00781         if(re->sss_points && render_display_draw_enabled(re))
00782             re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
00783         else if(re->r.scemode & R_FULL_SAMPLE)
00784             re->result= render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
00785         else
00786             re->result= render_result_new(re, &re->disprect, 0,
00787                 (re->r.scemode & R_EXR_TILE_FILE)? RR_USE_EXR: RR_USE_MEM);
00788     }
00789 
00790     BLI_rw_mutex_unlock(&re->resultmutex);
00791     
00792     if(re->result==NULL)
00793         return;
00794     
00795     /* warning; no return here without closing exr file */
00796     
00797     initparts(re);
00798 
00799     if(re->result->exrhandle)
00800         render_result_exr_file_begin(re);
00801     
00802     BLI_init_threads(&threads, do_part_thread, re->r.threads);
00803     
00804     /* assuming no new data gets added to dbase... */
00805     R= *re;
00806     
00807     /* set threadsafe break */
00808     R.test_break= thread_break;
00809     
00810     /* timer loop demands to sleep when no parts are left, so we enter loop with a part */
00811     if(re->r.mode & R_PANORAMA)
00812         nextpa= find_next_pano_slice(re, &minx, &viewplane);
00813     else
00814         nextpa= find_next_part(re, 0);
00815     
00816     while(rendering) {
00817         
00818         if(re->test_break(re->tbh))
00819             PIL_sleep_ms(50);
00820         else if(nextpa && BLI_available_threads(&threads)) {
00821             drawtimer= 0;
00822             nextpa->nr= counter++;  /* for nicest part, and for stats */
00823             nextpa->thread= BLI_available_thread_index(&threads);   /* sample index */
00824             BLI_insert_thread(&threads, nextpa);
00825 
00826             nextpa= find_next_part(re, minx);
00827         }
00828         else if(re->r.mode & R_PANORAMA) {
00829             if(nextpa==NULL && BLI_available_threads(&threads)==re->r.threads)
00830                 nextpa= find_next_pano_slice(re, &minx, &viewplane);
00831             else {
00832                 PIL_sleep_ms(50);
00833                 drawtimer++;
00834             }
00835         }
00836         else {
00837             PIL_sleep_ms(50);
00838             drawtimer++;
00839         }
00840         
00841         /* check for ready ones to display, and if we need to continue */
00842         rendering= 0;
00843         hasdrawn= 0;
00844         for(pa= re->parts.first; pa; pa= pa->next) {
00845             if(pa->ready) {
00846                 
00847                 BLI_remove_thread(&threads, pa);
00848                 
00849                 if(pa->result) {
00850                     if(render_display_draw_enabled(re))
00851                         re->display_draw(re->ddh, pa->result, NULL);
00852                     print_part_stats(re, pa);
00853                     
00854                     render_result_free_list(&pa->fullresult, pa->result);
00855                     pa->result= NULL;
00856                     re->i.partsdone++;
00857                     re->progress(re->prh, re->i.partsdone / (float)re->i.totpart);
00858                     hasdrawn= 1;
00859                 }
00860             }
00861             else {
00862                 rendering= 1;
00863                 if(pa->nr && pa->result && drawtimer>20) {
00864                     if(render_display_draw_enabled(re))
00865                         re->display_draw(re->ddh, pa->result, &pa->result->renrect);
00866                     hasdrawn= 1;
00867                 }
00868             }
00869         }
00870         if(hasdrawn)
00871             drawtimer= 0;
00872 
00873         /* on break, wait for all slots to get freed */
00874         if( (g_break=re->test_break(re->tbh)) && BLI_available_threads(&threads)==re->r.threads)
00875             rendering= 0;
00876         
00877     }
00878     
00879     if(re->result->exrhandle) {
00880         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
00881         render_result_exr_file_end(re);
00882         BLI_rw_mutex_unlock(&re->resultmutex);
00883     }
00884     
00885     /* unset threadsafety */
00886     g_break= 0;
00887     
00888     BLI_end_threads(&threads);
00889     freeparts(re);
00890     re->viewplane= viewplane; /* restore viewplane, modified by pano render */
00891 }
00892 
00893 /* currently only called by preview renders and envmap */
00894 void RE_TileProcessor(Render *re)
00895 {
00896     threaded_tile_processor(re);
00897 }
00898 
00899 /* ************  This part uses API, for rendering Blender scenes ********** */
00900 
00901 static void do_render_3d(Render *re)
00902 {
00903     /* try external */
00904     if(RE_engine_render(re, 0))
00905         return;
00906 
00907     /* internal */
00908     
00909 //  re->cfra= cfra; /* <- unused! */
00910     re->scene->r.subframe = re->mblur_offs + re->field_offs;
00911     
00912     /* lock drawing in UI during data phase */
00913     if(re->draw_lock)
00914         re->draw_lock(re->dlh, 1);
00915     
00916     /* make render verts/faces/halos/lamps */
00917     if(render_scene_needs_vector(re))
00918         RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
00919     else
00920         RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
00921     
00922     /* clear UI drawing locks */
00923     if(re->draw_lock)
00924         re->draw_lock(re->dlh, 0);
00925     
00926     threaded_tile_processor(re);
00927     
00928     /* do left-over 3d post effects (flares) */
00929     if(re->flag & R_HALO)
00930         if(!re->test_break(re->tbh))
00931             add_halo_flare(re);
00932     
00933     /* free all render verts etc */
00934     RE_Database_Free(re);
00935     
00936     re->scene->r.subframe = 0.f;
00937 }
00938 
00939 /* called by blur loop, accumulate RGBA key alpha */
00940 static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, float blurfac)
00941 {
00942     float mfac= 1.0f - blurfac;
00943     int a, b, stride= 4*rr->rectx;
00944     int len= stride*sizeof(float);
00945     
00946     for(a=0; a<rr->recty; a++) {
00947         if(blurfac==1.0f) {
00948             memcpy(rectf, rectf1, len);
00949         }
00950         else {
00951             float *rf= rectf, *rf1= rectf1;
00952             
00953             for( b= rr->rectx; b>0; b--, rf+=4, rf1+=4) {
00954                 if(rf1[3]<0.01f)
00955                     rf[3]= mfac*rf[3];
00956                 else if(rf[3]<0.01f) {
00957                     rf[0]= rf1[0];
00958                     rf[1]= rf1[1];
00959                     rf[2]= rf1[2];
00960                     rf[3]= blurfac*rf1[3];
00961                 }
00962                 else {
00963                     rf[0]= mfac*rf[0] + blurfac*rf1[0];
00964                     rf[1]= mfac*rf[1] + blurfac*rf1[1];
00965                     rf[2]= mfac*rf[2] + blurfac*rf1[2];
00966                     rf[3]= mfac*rf[3] + blurfac*rf1[3];
00967                 }               
00968             }
00969         }
00970         rectf+= stride;
00971         rectf1+= stride;
00972     }
00973 }
00974 
00975 /* called by blur loop, accumulate renderlayers */
00976 static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels)
00977 {
00978     float mfac= 1.0f - blurfac;
00979     int a, b, stride= channels*rr->rectx;
00980     int len= stride*sizeof(float);
00981     
00982     for(a=0; a<rr->recty; a++) {
00983         if(blurfac==1.0f) {
00984             memcpy(rectf, rectf1, len);
00985         }
00986         else {
00987             float *rf= rectf, *rf1= rectf1;
00988             
00989             for( b= rr->rectx*channels; b>0; b--, rf++, rf1++) {
00990                 rf[0]= mfac*rf[0] + blurfac*rf1[0];
00991             }
00992         }
00993         rectf+= stride;
00994         rectf1+= stride;
00995     }
00996 }
00997 
00998 
00999 /* called by blur loop, accumulate renderlayers */
01000 static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac, int key_alpha)
01001 {
01002     RenderLayer *rl, *rl1;
01003     RenderPass *rpass, *rpass1;
01004     
01005     rl1= brr->layers.first;
01006     for(rl= rr->layers.first; rl && rl1; rl= rl->next, rl1= rl1->next) {
01007         
01008         /* combined */
01009         if(rl->rectf && rl1->rectf) {
01010             if(key_alpha)
01011                 addblur_rect_key(rr, rl->rectf, rl1->rectf, blurfac);
01012             else
01013                 addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
01014         }
01015         
01016         /* passes are allocated in sync */
01017         rpass1= rl1->passes.first;
01018         for(rpass= rl->passes.first; rpass && rpass1; rpass= rpass->next, rpass1= rpass1->next) {
01019             addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
01020         }
01021     }
01022 }
01023 
01024 /* main blur loop, can be called by fields too */
01025 static void do_render_blur_3d(Render *re)
01026 {
01027     RenderResult *rres;
01028     float blurfac;
01029     int blur= re->r.mblur_samples;
01030     
01031     /* create accumulation render result */
01032     rres= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
01033     
01034     /* do the blur steps */
01035     while(blur--) {
01036         re->mblur_offs = re->r.blurfac*((float)(re->r.mblur_samples-blur))/(float)re->r.mblur_samples;
01037         
01038         re->i.curblur= re->r.mblur_samples-blur;    /* stats */
01039         
01040         do_render_3d(re);
01041         
01042         blurfac= 1.0f/(float)(re->r.mblur_samples-blur);
01043         
01044         merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
01045         if(re->test_break(re->tbh)) break;
01046     }
01047     
01048     /* swap results */
01049     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01050     render_result_free(re->result);
01051     re->result= rres;
01052     BLI_rw_mutex_unlock(&re->resultmutex);
01053     
01054     re->mblur_offs = 0.0f;
01055     re->i.curblur= 0;   /* stats */
01056     
01057     /* weak... the display callback wants an active renderlayer pointer... */
01058     re->result->renlay= render_get_active_layer(re, re->result);
01059     re->display_draw(re->ddh, re->result, NULL);    
01060 }
01061 
01062 
01063 /* function assumes rectf1 and rectf2 to be half size of rectf */
01064 static void interleave_rect(RenderResult *rr, float *rectf, float *rectf1, float *rectf2, int channels)
01065 {
01066     int a, stride= channels*rr->rectx;
01067     int len= stride*sizeof(float);
01068     
01069     for(a=0; a<rr->recty; a+=2) {
01070         memcpy(rectf, rectf1, len);
01071         rectf+= stride;
01072         rectf1+= stride;
01073         memcpy(rectf, rectf2, len);
01074         rectf+= stride;
01075         rectf2+= stride;
01076     }
01077 }
01078 
01079 /* merge render results of 2 fields */
01080 static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, RenderResult *rr2)
01081 {
01082     RenderLayer *rl, *rl1, *rl2;
01083     RenderPass *rpass, *rpass1, *rpass2;
01084     
01085     rl1= rr1->layers.first;
01086     rl2= rr2->layers.first;
01087     for(rl= rr->layers.first; rl && rl1 && rl2; rl= rl->next, rl1= rl1->next, rl2= rl2->next) {
01088         
01089         /* combined */
01090         if(rl->rectf && rl1->rectf && rl2->rectf)
01091             interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4);
01092         
01093         /* passes are allocated in sync */
01094         rpass1= rl1->passes.first;
01095         rpass2= rl2->passes.first;
01096         for(rpass= rl->passes.first; rpass && rpass1 && rpass2; rpass= rpass->next, rpass1= rpass1->next, rpass2= rpass2->next) {
01097             interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels);
01098         }
01099     }
01100 }
01101 
01102 
01103 /* interleaves 2 frames */
01104 static void do_render_fields_3d(Render *re)
01105 {
01106     Object *camera= RE_GetCamera(re);
01107     RenderResult *rr1, *rr2= NULL;
01108     
01109     /* no render result was created, we can safely halve render y */
01110     re->winy /= 2;
01111     re->recty /= 2;
01112     re->disprect.ymin /= 2;
01113     re->disprect.ymax /= 2;
01114     
01115     re->i.curfield= 1;  /* stats */
01116     
01117     /* first field, we have to call camera routine for correct aspect and subpixel offset */
01118     RE_SetCamera(re, camera);
01119     if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0)
01120         do_render_blur_3d(re);
01121     else
01122         do_render_3d(re);
01123 
01124     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01125     rr1= re->result;
01126     re->result= NULL;
01127     BLI_rw_mutex_unlock(&re->resultmutex);
01128     
01129     /* second field */
01130     if(!re->test_break(re->tbh)) {
01131         
01132         re->i.curfield= 2;  /* stats */
01133         
01134         re->flag |= R_SEC_FIELD;
01135         if((re->r.mode & R_FIELDSTILL)==0) {
01136             re->field_offs = 0.5f;
01137         }
01138         RE_SetCamera(re, camera);
01139         if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0)
01140             do_render_blur_3d(re);
01141         else
01142             do_render_3d(re);
01143         re->flag &= ~R_SEC_FIELD;
01144         
01145         re->field_offs = 0.0f;
01146         
01147         rr2= re->result;
01148     }
01149     
01150     /* allocate original height new buffers */
01151     re->winy *= 2;
01152     re->recty *= 2;
01153     re->disprect.ymin *= 2;
01154     re->disprect.ymax *= 2;
01155 
01156     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01157     re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
01158 
01159     if(rr2) {
01160         if(re->r.mode & R_ODDFIELD)
01161             merge_renderresult_fields(re->result, rr2, rr1);
01162         else
01163             merge_renderresult_fields(re->result, rr1, rr2);
01164         
01165         render_result_free(rr2);
01166     }
01167 
01168     render_result_free(rr1);
01169     
01170     re->i.curfield= 0;  /* stats */
01171     
01172     /* weak... the display callback wants an active renderlayer pointer... */
01173     re->result->renlay= render_get_active_layer(re, re->result);
01174 
01175     BLI_rw_mutex_unlock(&re->resultmutex);
01176 
01177     re->display_draw(re->ddh, re->result, NULL);
01178 }
01179 
01180 /* main render routine, no compositing */
01181 static void do_render_fields_blur_3d(Render *re)
01182 {
01183     Object *camera= RE_GetCamera(re);
01184     /* also check for camera here */
01185     if(camera == NULL) {
01186         printf("ERROR: Cannot render, no camera\n");
01187         G.afbreek= 1;
01188         return;
01189     }
01190 
01191     /* now use renderdata and camera to set viewplane */
01192     RE_SetCamera(re, camera);
01193     
01194     if(re->r.mode & R_FIELDS)
01195         do_render_fields_3d(re);
01196     else if(re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE)==0)
01197         do_render_blur_3d(re);
01198     else
01199         do_render_3d(re);
01200     
01201     /* when border render, check if we have to insert it in black */
01202     if(re->result) {
01203         if(re->r.mode & R_BORDER) {
01204             if((re->r.mode & R_CROP)==0) {
01205                 RenderResult *rres;
01206                 
01207                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01208 
01209                 /* sub-rect for merge call later on */
01210                 re->result->tilerect= re->disprect;
01211                 
01212                 /* this copying sequence could become function? */
01213                 /* weak is: it chances disprect from border */
01214                 re->disprect.xmin= re->disprect.ymin= 0;
01215                 re->disprect.xmax= re->winx;
01216                 re->disprect.ymax= re->winy;
01217                 re->rectx= re->winx;
01218                 re->recty= re->winy;
01219                 
01220                 rres= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
01221                 
01222                 render_result_merge(rres, re->result);
01223                 render_result_free(re->result);
01224                 re->result= rres;
01225                 
01226                 /* weak... the display callback wants an active renderlayer pointer... */
01227                 re->result->renlay= render_get_active_layer(re, re->result);
01228                 
01229                 BLI_rw_mutex_unlock(&re->resultmutex);
01230         
01231                 re->display_init(re->dih, re->result);
01232                 re->display_draw(re->ddh, re->result, NULL);
01233             }
01234             else {
01235                 /* set offset (again) for use in compositor, disprect was manipulated. */
01236                 re->result->xof= 0;
01237                 re->result->yof= 0;
01238             }
01239         }
01240     }
01241 }
01242 
01243 
01244 /* within context of current Render *re, render another scene.
01245    it uses current render image size and disprect, but doesn't execute composite
01246 */
01247 static void render_scene(Render *re, Scene *sce, int cfra)
01248 {
01249     Render *resc= RE_NewRender(sce->id.name);
01250     int winx= re->winx, winy= re->winy;
01251     
01252     sce->r.cfra= cfra;
01253 
01254     scene_camera_switch_update(sce);
01255 
01256     /* exception: scene uses own size (unfinished code) */
01257     if(0) {
01258         winx= (sce->r.size*sce->r.xsch)/100;
01259         winy= (sce->r.size*sce->r.ysch)/100;
01260     }
01261     
01262     /* initial setup */
01263     RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect);
01264     
01265     /* still unsure entity this... */
01266     resc->main= re->main;
01267     resc->scene= sce;
01268     resc->lay= sce->lay;
01269     
01270     /* ensure scene has depsgraph, base flags etc OK */
01271     set_scene_bg(re->main, sce);
01272 
01273     /* copy callbacks */
01274     resc->display_draw= re->display_draw;
01275     resc->ddh= re->ddh;
01276     resc->test_break= re->test_break;
01277     resc->tbh= re->tbh;
01278     resc->stats_draw= re->stats_draw;
01279     resc->sdh= re->sdh;
01280     
01281     do_render_fields_blur_3d(resc);
01282 }
01283 
01284 /* helper call to detect if this scene needs a render, or if there's a any render layer to render */
01285 static int composite_needs_render(Scene *sce, int this_scene)
01286 {
01287     bNodeTree *ntree= sce->nodetree;
01288     bNode *node;
01289     
01290     if(ntree==NULL) return 1;
01291     if(sce->use_nodes==0) return 1;
01292     if((sce->r.scemode & R_DOCOMP)==0) return 1;
01293     
01294     for(node= ntree->nodes.first; node; node= node->next) {
01295         if(node->type==CMP_NODE_R_LAYERS)
01296             if(this_scene==0 || node->id==NULL || node->id==&sce->id)
01297                 return 1;
01298     }
01299     return 0;
01300 }
01301 
01302 static void tag_scenes_for_render(Render *re)
01303 {
01304     bNode *node;
01305     Scene *sce;
01306     
01307     for(sce= re->main->scene.first; sce; sce= sce->id.next)
01308         sce->id.flag &= ~LIB_DOIT;
01309     
01310     if(RE_GetCamera(re) && composite_needs_render(re->scene, 1))
01311         re->scene->id.flag |= LIB_DOIT;
01312     
01313     if(re->scene->nodetree==NULL) return;
01314     
01315     /* check for render-layers nodes using other scenes, we tag them LIB_DOIT */
01316     for(node= re->scene->nodetree->nodes.first; node; node= node->next) {
01317         if(node->type==CMP_NODE_R_LAYERS) {
01318             if(node->id) {
01319                 if(node->id != (ID *)re->scene)
01320                     node->id->flag |= LIB_DOIT;
01321             }
01322         }
01323     }
01324     
01325 }
01326 
01327 static void ntree_render_scenes(Render *re)
01328 {
01329     bNode *node;
01330     int cfra= re->scene->r.cfra;
01331     int restore_scene= 0;
01332     
01333     if(re->scene->nodetree==NULL) return;
01334     
01335     tag_scenes_for_render(re);
01336     
01337     /* now foreach render-result node tagged we do a full render */
01338     /* results are stored in a way compisitor will find it */
01339     for(node= re->scene->nodetree->nodes.first; node; node= node->next) {
01340         if(node->type==CMP_NODE_R_LAYERS) {
01341             if(node->id && node->id != (ID *)re->scene) {
01342                 if(node->id->flag & LIB_DOIT) {
01343                     Scene *scene = (Scene*)node->id;
01344 
01345                     render_scene(re, scene, cfra);
01346                     restore_scene= (scene != re->scene);
01347                     node->id->flag &= ~LIB_DOIT;
01348                     
01349                     nodeUpdate(re->scene->nodetree, node);
01350                 }
01351             }
01352         }
01353     }
01354 
01355     /* restore scene if we rendered another last */
01356     if(restore_scene)
01357         set_scene_bg(re->main, re->scene);
01358 }
01359 
01360 /* bad call... need to think over proper method still */
01361 static void render_composit_stats(void *UNUSED(arg), char *str)
01362 {
01363     R.i.infostr= str;
01364     R.stats_draw(R.sdh, &R.i);
01365     R.i.infostr= NULL;
01366 }
01367 
01368 
01369 /* reads all buffers, calls optional composite, merges in first result->rectf */
01370 static void do_merge_fullsample(Render *re, bNodeTree *ntree)
01371 {
01372     float *rectf, filt[3][3];
01373     int sample;
01374     
01375     /* interaction callbacks */
01376     if(ntree) {
01377         ntree->stats_draw= render_composit_stats;
01378         ntree->test_break= re->test_break;
01379         ntree->progress= re->progress;
01380         ntree->sdh= re->sdh;
01381         ntree->tbh= re->tbh;
01382         ntree->prh= re->prh;
01383     }
01384     
01385     /* filtmask needs it */
01386     R= *re;
01387     
01388     /* we accumulate in here */
01389     rectf= MEM_mapallocN(re->rectx*re->recty*sizeof(float)*4, "fullsample rgba");
01390     
01391     for(sample=0; sample<re->r.osa; sample++) {
01392         Render *re1;
01393         RenderResult rres;
01394         int x, y, mask;
01395         
01396         /* enable full sample print */
01397         R.i.curfsa= sample+1;
01398         
01399         /* set all involved renders on the samplebuffers (first was done by render itself, but needs tagged) */
01400         /* also function below assumes this */
01401             
01402         tag_scenes_for_render(re);
01403         for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
01404             if(re1->scene->id.flag & LIB_DOIT) {
01405                 if(re1->r.scemode & R_FULL_SAMPLE) {
01406                     if(sample) {
01407                         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01408                         render_result_exr_file_read(re1, sample);
01409                         BLI_rw_mutex_unlock(&re->resultmutex);
01410                     }
01411                     ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */
01412                 }
01413             }
01414         }
01415         
01416         /* composite */
01417         if(ntree) {
01418             ntreeCompositTagRender(re->scene);
01419             ntreeCompositTagAnimated(ntree);
01420             
01421             ntreeCompositExecTree(ntree, &re->r, G.background==0);
01422         }
01423         
01424         /* ensure we get either composited result or the active layer */
01425         RE_AcquireResultImage(re, &rres);
01426         
01427         /* accumulate with filter, and clip */
01428         mask= (1<<sample);
01429         mask_array(mask, filt);
01430 
01431         for(y=0; y<re->recty; y++) {
01432             float *rf= rectf + 4*y*re->rectx;
01433             float *col= rres.rectf + 4*y*re->rectx;
01434                 
01435             for(x=0; x<re->rectx; x++, rf+=4, col+=4) {
01436                 /* clamping to 1.0 is needed for correct AA */
01437                 if(col[0]<0.0f) col[0]=0.0f; else if(col[0] > 1.0f) col[0]= 1.0f;
01438                 if(col[1]<0.0f) col[1]=0.0f; else if(col[1] > 1.0f) col[1]= 1.0f;
01439                 if(col[2]<0.0f) col[2]=0.0f; else if(col[2] > 1.0f) col[2]= 1.0f;
01440                 
01441                 add_filt_fmask_coord(filt, col, rf, re->rectx, re->recty, x, y);
01442             }
01443         }
01444         
01445         RE_ReleaseResultImage(re);
01446 
01447         /* show stuff */
01448         if(sample!=re->osa-1) {
01449             /* weak... the display callback wants an active renderlayer pointer... */
01450             re->result->renlay= render_get_active_layer(re, re->result);
01451             re->display_draw(re->ddh, re->result, NULL);
01452         }
01453         
01454         if(re->test_break(re->tbh))
01455             break;
01456     }
01457     
01458     /* clear interaction callbacks */
01459     if(ntree) {
01460         ntree->stats_draw= NULL;
01461         ntree->test_break= NULL;
01462         ntree->progress= NULL;
01463         ntree->tbh= ntree->sdh= ntree->prh= NULL;
01464     }
01465     
01466     /* disable full sample print */
01467     R.i.curfsa= 0;
01468     
01469     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01470     if(re->result->rectf) 
01471         MEM_freeN(re->result->rectf);
01472     re->result->rectf= rectf;
01473     BLI_rw_mutex_unlock(&re->resultmutex);
01474 }
01475 
01476 /* called externally, via compositor */
01477 void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree)
01478 {
01479     Scene *scene;
01480     bNode *node;
01481 
01482     /* default start situation */
01483     G.afbreek= 0;
01484     
01485     re->main= bmain;
01486     re->scene= sce;
01487     
01488     /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */
01489     
01490     /* tag scenes unread */
01491     for(scene= re->main->scene.first; scene; scene= scene->id.next) 
01492         scene->id.flag |= LIB_DOIT;
01493     
01494     for(node= ntree->nodes.first; node; node= node->next) {
01495         if(node->type==CMP_NODE_R_LAYERS) {
01496             Scene *nodescene= (Scene *)node->id;
01497             
01498             if(nodescene==NULL) nodescene= sce;
01499             if(nodescene->id.flag & LIB_DOIT) {
01500                 nodescene->r.mode |= R_OSA; /* render struct needs tables */
01501                 RE_ReadRenderResult(sce, nodescene);
01502                 nodescene->id.flag &= ~LIB_DOIT;
01503             }
01504         }
01505     }
01506     
01507     /* own render result should be read/allocated */
01508     if(re->scene->id.flag & LIB_DOIT) {
01509         RE_ReadRenderResult(re->scene, re->scene);
01510         re->scene->id.flag &= ~LIB_DOIT;
01511     }
01512     
01513     /* and now we can draw (result is there) */
01514     re->display_init(re->dih, re->result);
01515     re->display_clear(re->dch, re->result);
01516     
01517     do_merge_fullsample(re, ntree);
01518 }
01519 
01520 /* returns fully composited render-result on given time step (in RenderData) */
01521 static void do_render_composite_fields_blur_3d(Render *re)
01522 {
01523     bNodeTree *ntree= re->scene->nodetree;
01524     int update_newframe=0;
01525     
01526     /* INIT seeding, compositor can use random texture */
01527     BLI_srandom(re->r.cfra);
01528     
01529     if(composite_needs_render(re->scene, 1)) {
01530         /* save memory... free all cached images */
01531         ntreeFreeCache(ntree);
01532         
01533         do_render_fields_blur_3d(re);
01534     } 
01535     else {
01536         /* ensure new result gets added, like for regular renders */
01537         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01538         
01539         render_result_free(re->result);
01540         re->result= render_result_new(re, &re->disprect, 0, RR_USE_MEM);
01541 
01542         BLI_rw_mutex_unlock(&re->resultmutex);
01543         
01544         /* scene render process already updates animsys */
01545         update_newframe = 1;
01546     }
01547     
01548     /* swap render result */
01549     if(re->r.scemode & R_SINGLE_LAYER) {
01550         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01551         render_result_single_layer_end(re);
01552         BLI_rw_mutex_unlock(&re->resultmutex);
01553     }
01554     
01555     if(!re->test_break(re->tbh)) {
01556         
01557         if(ntree) {
01558             ntreeCompositTagRender(re->scene);
01559             ntreeCompositTagAnimated(ntree);
01560         }
01561         
01562         if(ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
01563             /* checks if there are render-result nodes that need scene */
01564             if((re->r.scemode & R_SINGLE_LAYER)==0)
01565                 ntree_render_scenes(re);
01566             
01567             if(!re->test_break(re->tbh)) {
01568                 ntree->stats_draw= render_composit_stats;
01569                 ntree->test_break= re->test_break;
01570                 ntree->progress= re->progress;
01571                 ntree->sdh= re->sdh;
01572                 ntree->tbh= re->tbh;
01573                 ntree->prh= re->prh;
01574                 
01575                 /* in case it was never initialized */
01576                 R.sdh= re->sdh;
01577                 R.stats_draw= re->stats_draw;
01578                 
01579                 if (update_newframe)
01580                     scene_update_for_newframe(re->main, re->scene, re->lay);
01581                 
01582                 if(re->r.scemode & R_FULL_SAMPLE) 
01583                     do_merge_fullsample(re, ntree);
01584                 else {
01585                     ntreeCompositExecTree(ntree, &re->r, G.background==0);
01586                 }
01587                 
01588                 ntree->stats_draw= NULL;
01589                 ntree->test_break= NULL;
01590                 ntree->progress= NULL;
01591                 ntree->tbh= ntree->sdh= ntree->prh= NULL;
01592             }
01593         }
01594         else if(re->r.scemode & R_FULL_SAMPLE)
01595             do_merge_fullsample(re, NULL);
01596     }
01597 
01598     /* weak... the display callback wants an active renderlayer pointer... */
01599     re->result->renlay= render_get_active_layer(re, re->result);
01600     re->display_draw(re->ddh, re->result, NULL);
01601 }
01602 
01603 static void renderresult_stampinfo(Render *re)
01604 {
01605     RenderResult rres;
01606 
01607     /* this is the basic trick to get the displayed float or char rect from render result */
01608     RE_AcquireResultImage(re, &rres);
01609     BKE_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
01610     RE_ReleaseResultImage(re);
01611 }
01612 
01613 int RE_seq_render_active(Scene *scene, RenderData *rd)
01614 {
01615     Editing *ed;
01616     Sequence *seq;
01617 
01618     ed = scene->ed;
01619     
01620     if (!(rd->scemode & R_DOSEQ) || !ed || !ed->seqbase.first)
01621         return 0;
01622     
01623     for (seq= ed->seqbase.first; seq; seq= seq->next) {
01624         if (seq->type != SEQ_SOUND)
01625             return 1;
01626     }
01627     
01628     return 0;
01629 }
01630 
01631 static void do_render_seq(Render * re)
01632 {
01633     static int recurs_depth = 0;
01634     struct ImBuf *ibuf;
01635     RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
01636     int cfra = re->r.cfra;
01637     SeqRenderData context;
01638 
01639     re->i.cfra= cfra;
01640 
01641     if(recurs_depth==0) {
01642         /* otherwise sequencer animation isnt updated */
01643         BKE_animsys_evaluate_all_animation(re->main, re->scene, (float)cfra); // XXX, was BKE_curframe(re->scene)
01644     }
01645 
01646     recurs_depth++;
01647 
01648     if((re->r.mode & R_BORDER) && (re->r.mode & R_CROP)==0) {
01649         /* if border rendering is used and cropping is disabled, final buffer should
01650             be as large as the whole frame */
01651         context = seq_new_render_data(re->main, re->scene,
01652                           re->winx, re->winy,
01653                           100);
01654     } else {
01655         context = seq_new_render_data(re->main, re->scene,
01656                           re->result->rectx, re->result->recty,
01657                           100);
01658     }
01659 
01660     ibuf = give_ibuf_seq(context, cfra, 0);
01661 
01662     recurs_depth--;
01663 
01664     rr = re->result;
01665     
01666     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01667 
01668     if(ibuf) {
01669         /* copy ibuf into combined pixel rect */
01670         render_result_rect_from_ibuf(rr, &re->r, ibuf);
01671         
01672         if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
01673             Editing * ed = re->scene->ed;
01674             if (ed)
01675                 free_imbuf_seq(re->scene, &ed->seqbase, TRUE, TRUE);
01676         }
01677         IMB_freeImBuf(ibuf);
01678     }
01679     else {
01680         /* render result is delivered empty in most cases, nevertheless we handle all cases */
01681         render_result_rect_fill_zero(rr);
01682     }
01683 
01684     BLI_rw_mutex_unlock(&re->resultmutex);
01685 
01686     /* just in case this flag went missing at some point */
01687     re->r.scemode |= R_DOSEQ;
01688 
01689     /* set overall progress of sequence rendering */
01690     if(re->r.efra!=re->r.sfra)
01691         re->progress(re->prh, (float)(cfra-re->r.sfra) / (re->r.efra-re->r.sfra));
01692     else
01693         re->progress(re->prh, 1.0f);
01694 }
01695 
01696 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
01697 
01698 /* main loop: doing sequence + fields + blur + 3d render + compositing */
01699 static void do_render_all_options(Render *re)
01700 {
01701     scene_camera_switch_update(re->scene);
01702 
01703     re->i.starttime= PIL_check_seconds_timer();
01704 
01705     /* ensure no images are in memory from previous animated sequences */
01706     BKE_image_all_free_anim_ibufs(re->r.cfra);
01707 
01708     if(RE_engine_render(re, 1)) {
01709         /* in this case external render overrides all */
01710     }
01711     else if(RE_seq_render_active(re->scene, &re->r)) {
01712         /* note: do_render_seq() frees rect32 when sequencer returns float images */
01713         if(!re->test_break(re->tbh)) 
01714             do_render_seq(re);
01715         
01716         re->stats_draw(re->sdh, &re->i);
01717         re->display_draw(re->ddh, re->result, NULL);
01718     }
01719     else {
01720         do_render_composite_fields_blur_3d(re);
01721     }
01722     
01723     re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
01724     
01725     re->stats_draw(re->sdh, &re->i);
01726     
01727     /* stamp image info here */
01728     if((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) {
01729         renderresult_stampinfo(re);
01730         re->display_draw(re->ddh, re->result, NULL);
01731     }
01732 }
01733 
01734 static int check_valid_camera(Scene *scene, Object *camera_override)
01735 {
01736     int check_comp= 1;
01737 
01738     if (camera_override == NULL && scene->camera == NULL)
01739         scene->camera= scene_find_camera(scene);
01740 
01741     if(scene->r.scemode&R_DOSEQ) {
01742         if(scene->ed) {
01743             Sequence *seq= scene->ed->seqbase.first;
01744 
01745             check_comp= 0;
01746 
01747             while(seq) {
01748                 if(seq->type == SEQ_SCENE) {
01749                     if(!seq->scene_camera) {
01750                         if(!seq->scene->camera && !scene_find_camera(seq->scene)) {
01751                             if(seq->scene == scene) {
01752                                 /* for current scene camera could be unneeded due to compisite nodes */
01753                                 check_comp= 1;
01754                             } else {
01755                                 /* for other scenes camera is necessary */
01756                                 return 0;
01757                             }
01758                         }
01759                     }
01760                 }
01761 
01762                 seq= seq->next;
01763             }
01764         }
01765     }
01766 
01767     if(check_comp) { /* no sequencer or sequencer depends on compositor */
01768         if(scene->r.scemode&R_DOCOMP && scene->use_nodes) {
01769             bNode *node= scene->nodetree->nodes.first;
01770 
01771             while(node) {
01772                 if(node->type == CMP_NODE_R_LAYERS) {
01773                     Scene *sce= node->id ? (Scene*)node->id : scene;
01774 
01775                     if(!sce->camera && !scene_find_camera(sce)) {
01776                         /* all render layers nodes need camera */
01777                         return 0;
01778                     }
01779                 }
01780 
01781                 node= node->next;
01782             }
01783         } else {
01784             return (camera_override != NULL || scene->camera != NULL);
01785         }
01786     }
01787 
01788     return 1;
01789 }
01790 
01791 int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports)
01792 {
01793     SceneRenderLayer *srl;
01794     
01795     if(scene->r.mode & R_BORDER) {
01796         if(scene->r.border.xmax <= scene->r.border.xmin ||
01797            scene->r.border.ymax <= scene->r.border.ymin) {
01798             BKE_report(reports, RPT_ERROR, "No border area selected.");
01799             return 0;
01800         }
01801     }
01802     
01803     if(scene->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) {
01804         char str[FILE_MAX];
01805         
01806         render_result_exr_file_path(scene, 0, str);
01807         
01808         if (BLI_file_is_writable(str)==0) {
01809             BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path");
01810             return 0;
01811         }
01812         
01813         /* no fullsample and edge */
01814         if((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) {
01815             BKE_report(reports, RPT_ERROR, "Full Sample doesn't support Edge Enhance");
01816             return 0;
01817         }
01818         
01819     }
01820     else
01821         scene->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */
01822     
01823     if(scene->r.scemode & R_DOCOMP) {
01824         if(scene->use_nodes) {
01825             bNodeTree *ntree= scene->nodetree;
01826             bNode *node;
01827         
01828             if(ntree==NULL) {
01829                 BKE_report(reports, RPT_ERROR, "No Nodetree in Scene");
01830                 return 0;
01831             }
01832             
01833             for(node= ntree->nodes.first; node; node= node->next)
01834                 if(node->type==CMP_NODE_COMPOSITE)
01835                     break;
01836             
01837             if(node==NULL) {
01838                 BKE_report(reports, RPT_ERROR, "No Render Output Node in Scene");
01839                 return 0;
01840             }
01841             
01842             if(scene->r.scemode & R_FULL_SAMPLE) {
01843                 if(composite_needs_render(scene, 0)==0) {
01844                     BKE_report(reports, RPT_ERROR, "Full Sample AA not supported without 3d rendering");
01845                     return 0;
01846                 }
01847             }
01848         }
01849     }
01850     
01851      /* check valid camera, without camera render is OK (compo, seq) */
01852     if(!check_valid_camera(scene, camera_override)) {
01853         BKE_report(reports, RPT_ERROR, "No camera");
01854         return 0;
01855     }
01856     
01857     /* get panorama & ortho, only after camera is set */
01858     object_camera_mode(&scene->r, camera_override ? camera_override : scene->camera);
01859 
01860     /* forbidden combinations */
01861     if(scene->r.mode & R_PANORAMA) {
01862         if(scene->r.mode & R_ORTHO) {
01863             BKE_report(reports, RPT_ERROR, "No Ortho render possible for Panorama");
01864             return 0;
01865         }
01866     }
01867 
01868     /* layer flag tests */
01869     if(scene->r.scemode & R_SINGLE_LAYER) {
01870         srl= BLI_findlink(&scene->r.layers, scene->r.actlay);
01871         /* force layer to be enabled */
01872         srl->layflag &= ~SCE_LAY_DISABLE;
01873     }
01874     
01875     for(srl= scene->r.layers.first; srl; srl= srl->next)
01876         if(!(srl->layflag & SCE_LAY_DISABLE))
01877             break;
01878     if(srl==NULL) {
01879         BKE_report(reports, RPT_ERROR, "All RenderLayers are disabled");
01880         return 0;
01881     }
01882 
01883     return 1;
01884 }
01885 
01886 static void validate_render_settings(Render *re)
01887 {
01888     if(re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) {
01889         /* no osa + fullsample won't work... */
01890         if(re->r.osa==0)
01891             re->r.scemode &= ~R_FULL_SAMPLE;
01892     } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */
01893 
01894     if(RE_engine_is_external(re)) {
01895         /* not supported yet */
01896         re->r.scemode &= ~(R_EXR_TILE_FILE|R_FULL_SAMPLE);
01897     }
01898 }
01899 
01900 static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init))
01901 {
01902     PTCacheBaker baker;
01903 
01904     baker.main = re->main;
01905     baker.scene = scene;
01906     baker.pid = NULL;
01907     baker.bake = 0;
01908     baker.render = 1;
01909     baker.anim_init = 1;
01910     baker.quick_step = 1;
01911     baker.break_test = re->test_break;
01912     baker.break_data = re->tbh;
01913     baker.progressbar = NULL;
01914 
01915     BKE_ptcache_bake(&baker);
01916 }
01917 /* evaluating scene options for general Blender render */
01918 static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int anim, int anim_init)
01919 {
01920     int winx, winy;
01921     rcti disprect;
01922     
01923     /* r.xsch and r.ysch has the actual view window size
01924         r.border is the clipping rect */
01925     
01926     /* calculate actual render result and display size */
01927     winx= (scene->r.size*scene->r.xsch)/100;
01928     winy= (scene->r.size*scene->r.ysch)/100;
01929     
01930     /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */
01931     if(scene->r.mode & R_BORDER) {
01932         disprect.xmin= scene->r.border.xmin*winx;
01933         disprect.xmax= scene->r.border.xmax*winx;
01934         
01935         disprect.ymin= scene->r.border.ymin*winy;
01936         disprect.ymax= scene->r.border.ymax*winy;
01937     }
01938     else {
01939         disprect.xmin= disprect.ymin= 0;
01940         disprect.xmax= winx;
01941         disprect.ymax= winy;
01942     }
01943     
01944     re->main= bmain;
01945     re->scene= scene;
01946     re->camera_override= camera_override;
01947     re->lay= lay;
01948     
01949     /* not too nice, but it survives anim-border render */
01950     if(anim) {
01951         re->disprect= disprect;
01952         return 1;
01953     }
01954     
01955     /* check all scenes involved */
01956     tag_scenes_for_render(re);
01957 
01958     /*
01959      * Disabled completely for now,
01960      * can be later set as render profile option
01961      * and default for background render.
01962     */
01963     if(0) {
01964         /* make sure dynamics are up to date */
01965         update_physics_cache(re, scene, anim_init);
01966     }
01967     
01968     if(srl || scene->r.scemode & R_SINGLE_LAYER) {
01969         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
01970         render_result_single_layer_begin(re);
01971         BLI_rw_mutex_unlock(&re->resultmutex);
01972     }
01973     
01974     RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect);
01975     if(!re->ok)  /* if an error was printed, abort */
01976         return 0;
01977     
01978     /* initstate makes new result, have to send changed tags around */
01979     ntreeCompositTagRender(re->scene);
01980 
01981     validate_render_settings(re);
01982 
01983     re->display_init(re->dih, re->result);
01984     re->display_clear(re->dch, re->result);
01985     
01986     return 1;
01987 }
01988 
01989 void RE_SetReports(Render *re, ReportList *reports)
01990 {
01991     re->reports= reports;
01992 }
01993 
01994 /* general Blender frame render call */
01995 void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int frame, const short write_still)
01996 {
01997     /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
01998     G.rendering= 1;
01999     
02000     scene->r.cfra= frame;
02001     
02002     if(render_initialize_from_main(re, bmain, scene, srl, camera_override, lay, 0, 0)) {
02003         MEM_reset_peak_memory();
02004 
02005         BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
02006 
02007         do_render_all_options(re);
02008 
02009         if(write_still && !G.afbreek) {
02010             if(BKE_imtype_is_movie(scene->r.im_format.imtype)) {
02011                 /* operator checks this but incase its called from elsewhere */
02012                 printf("Error: cant write single images with a movie format!\n");
02013             }
02014             else {
02015                 char name[FILE_MAX];
02016                 BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, FALSE);
02017 
02018                 /* reports only used for Movie */
02019                 do_write_image_or_movie(re, bmain, scene, NULL, name);
02020             }
02021         }
02022 
02023         BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
02024     }
02025 
02026     /* UGLY WARNING */
02027     G.rendering= 0;
02028 }
02029 
02030 static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
02031 {
02032     char name[FILE_MAX];
02033     RenderResult rres;
02034     Object *camera= RE_GetCamera(re);
02035     int ok= 1;
02036     
02037     RE_AcquireResultImage(re, &rres);
02038 
02039     /* write movie or image */
02040     if(BKE_imtype_is_movie(scene->r.im_format.imtype)) {
02041         int dofree = 0;
02042         unsigned int *rect32 = (unsigned int *)rres.rect32;
02043         /* note; the way it gets 32 bits rects is weak... */
02044         if(rres.rect32 == NULL) {
02045             rect32 = MEM_mapallocN(sizeof(int)*rres.rectx*rres.recty, "temp 32 bits rect");
02046             RE_ResultGet32(re, rect32);
02047             dofree = 1;
02048         }
02049 
02050         ok= mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *)rect32,
02051                              rres.rectx, rres.recty, re->reports);
02052         if(dofree) {
02053             MEM_freeN(rect32);
02054         }
02055         printf("Append frame %d", scene->r.cfra);
02056     } 
02057     else {
02058         if(name_override)
02059             BLI_strncpy(name, name_override, sizeof(name));
02060         else
02061             BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
02062         
02063         if(re->r.im_format.imtype==R_IMF_IMTYPE_MULTILAYER) {
02064             if(re->result) {
02065                 RE_WriteRenderResult(re->reports, re->result, name, scene->r.im_format.compress);
02066                 printf("Saved: %s", name);
02067             }
02068         }
02069         else {
02070             ImBuf *ibuf= render_result_rect_to_ibuf(&rres, &scene->r);
02071 
02072             ok= BKE_write_ibuf_stamp(scene, camera, ibuf, name, &scene->r.im_format);
02073             
02074             if(ok==0) {
02075                 printf("Render error: cannot save %s\n", name);
02076             }
02077             else printf("Saved: %s", name);
02078             
02079             /* optional preview images for exr */
02080             if(ok && scene->r.im_format.imtype==R_IMF_IMTYPE_OPENEXR && (scene->r.im_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
02081                 ImageFormatData imf= scene->r.im_format;
02082                 imf.imtype= R_IMF_IMTYPE_JPEG90;
02083 
02084                 if(BLI_testextensie(name, ".exr")) 
02085                     name[strlen(name)-4]= 0;
02086                 BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
02087                 ibuf->planes= 24;
02088                 BKE_write_ibuf_stamp(scene, camera, ibuf, name, &imf);
02089                 printf("\nSaved: %s", name);
02090             }
02091             
02092                     /* imbuf knows which rects are not part of ibuf */
02093             IMB_freeImBuf(ibuf);
02094         }
02095     }
02096     
02097     RE_ReleaseResultImage(re);
02098 
02099     BLI_timestr(re->i.lastframetime, name);
02100     printf(" Time: %s\n", name);
02101     fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
02102 
02103     return ok;
02104 }
02105 
02106 /* saves images to disk */
02107 void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override, unsigned int lay, int sfra, int efra, int tfra)
02108 {
02109     bMovieHandle *mh= BKE_get_movie_handle(scene->r.im_format.imtype);
02110     int cfrao= scene->r.cfra;
02111     int nfra, totrendered= 0, totskipped= 0;
02112     
02113     /* do not fully call for each frame, it initializes & pops output window */
02114     if(!render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 0, 1))
02115         return;
02116     
02117     /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
02118     /* is also set by caller renderwin.c */
02119     G.rendering= 1;
02120 
02121     re->flag |= R_ANIMATION;
02122 
02123     if(BKE_imtype_is_movie(scene->r.im_format.imtype))
02124         if(!mh->start_movie(scene, &re->r, re->rectx, re->recty, re->reports))
02125             G.afbreek= 1;
02126 
02127     if (mh->get_next_frame) {
02128         while (!(G.afbreek == 1)) {
02129             int nf = mh->get_next_frame(&re->r, re->reports);
02130             if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) {
02131                 scene->r.cfra = re->r.cfra = nf;
02132 
02133                 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
02134 
02135                 do_render_all_options(re);
02136                 totrendered++;
02137 
02138                 if(re->test_break(re->tbh) == 0) {
02139                     if(!do_write_image_or_movie(re, bmain, scene, mh, NULL))
02140                         G.afbreek= 1;
02141                 }
02142 
02143                 if(G.afbreek == 0) {
02144                     BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
02145                 }
02146             }
02147             else {
02148                 if(re->test_break(re->tbh))
02149                     G.afbreek= 1;
02150             }
02151         }
02152     } else {
02153         for(nfra= sfra, scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) {
02154             char name[FILE_MAX];
02155             
02156             /* only border now, todo: camera lens. (ton) */
02157             render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 1, 0);
02158 
02159             if(nfra!=scene->r.cfra) {
02160                 /*
02161                  * Skip this frame, but update for physics and particles system.
02162                  * From convertblender.c:
02163                  * in localview, lamps are using normal layers, objects only local bits.
02164                  */
02165                 unsigned int updatelay;
02166 
02167                 if(re->lay & 0xFF000000)
02168                     updatelay= re->lay & 0xFF000000;
02169                 else
02170                     updatelay= re->lay;
02171 
02172                 scene_update_for_newframe(bmain, scene, updatelay);
02173                 continue;
02174             }
02175             else
02176                 nfra+= tfra;
02177 
02178             /* Touch/NoOverwrite options are only valid for image's */
02179             if(BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
02180                 if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
02181                     BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
02182 
02183                 if(scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
02184                     printf("skipping existing frame \"%s\"\n", name);
02185                     totskipped++;
02186                     continue;
02187                 }
02188                 if(scene->r.mode & R_TOUCH && !BLI_exists(name)) {
02189                     BLI_make_existing_file(name); /* makes the dir if its not there */
02190                     BLI_file_touch(name);
02191                 }
02192             }
02193 
02194             re->r.cfra= scene->r.cfra;     /* weak.... */
02195 
02196             /* run callbacs before rendering, before the scene is updated */
02197             BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
02198 
02199             
02200             do_render_all_options(re);
02201             totrendered++;
02202             
02203             if(re->test_break(re->tbh) == 0) {
02204                 if(!G.afbreek)
02205                     if(!do_write_image_or_movie(re, bmain, scene, mh, NULL))
02206                         G.afbreek= 1;
02207             }
02208             else
02209                 G.afbreek= 1;
02210         
02211             if(G.afbreek==1) {
02212                 /* remove touched file */
02213                 if(BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
02214                     if (scene->r.mode & R_TOUCH && BLI_exists(name) && BLI_file_size(name) == 0) {
02215                         BLI_delete(name, 0, 0);
02216                     }
02217                 }
02218                 
02219                 break;
02220             }
02221 
02222             if(G.afbreek==0) {
02223                 BLI_exec_cb(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
02224             }
02225         }
02226     }
02227     
02228     /* end movie */
02229     if(BKE_imtype_is_movie(scene->r.im_format.imtype))
02230         mh->end_movie();
02231     
02232     if(totskipped && totrendered == 0)
02233         BKE_report(re->reports, RPT_INFO, "No frames rendered, skipped to not overwrite");
02234 
02235     scene->r.cfra= cfrao;
02236 
02237     re->flag &= ~R_ANIMATION;
02238 
02239     /* UGLY WARNING */
02240     G.rendering= 0;
02241 }
02242 
02243 void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
02244 {
02245     Object *camera;
02246     int winx, winy;
02247 
02248     winx= (sce->r.size*sce->r.xsch)/100;
02249     winy= (sce->r.size*sce->r.ysch)/100;
02250 
02251     RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
02252 
02253     re->main = bmain;
02254     re->scene = sce;
02255     re->lay = sce->lay;
02256 
02257     camera = RE_GetCamera(re);
02258     RE_SetCamera(re, camera);
02259 
02260     do_render_3d(re);
02261 }
02262 
02263 /* note; repeated win/disprect calc... solve that nicer, also in compo */
02264 
02265 /* only the temp file! */
02266 int RE_ReadRenderResult(Scene *scene, Scene *scenode)
02267 {
02268     Render *re;
02269     int winx, winy, success;
02270     rcti disprect;
02271     
02272     /* calculate actual render result and display size */
02273     winx= (scene->r.size*scene->r.xsch)/100;
02274     winy= (scene->r.size*scene->r.ysch)/100;
02275     
02276     /* only in movie case we render smaller part */
02277     if(scene->r.mode & R_BORDER) {
02278         disprect.xmin= scene->r.border.xmin*winx;
02279         disprect.xmax= scene->r.border.xmax*winx;
02280         
02281         disprect.ymin= scene->r.border.ymin*winy;
02282         disprect.ymax= scene->r.border.ymax*winy;
02283     }
02284     else {
02285         disprect.xmin= disprect.ymin= 0;
02286         disprect.xmax= winx;
02287         disprect.ymax= winy;
02288     }
02289     
02290     if(scenode)
02291         scene= scenode;
02292     
02293     /* get render: it can be called from UI with draw callbacks */
02294     re= RE_GetRender(scene->id.name);
02295     if(re==NULL)
02296         re= RE_NewRender(scene->id.name);
02297     RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
02298     re->scene= scene;
02299     
02300     BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
02301     success= render_result_exr_file_read(re, 0);
02302     BLI_rw_mutex_unlock(&re->resultmutex);
02303 
02304     return success;
02305 }
02306 
02307 void RE_set_max_threads(int threads)
02308 {
02309     if (threads==0) {
02310         RenderGlobal.threads = BLI_system_thread_count();
02311     } else if(threads>=1 && threads<=BLENDER_MAX_THREADS) {
02312         RenderGlobal.threads= threads;
02313     } else {
02314         printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS);
02315     }
02316 }
02317 
02318 void RE_init_threadcount(Render *re) 
02319 {
02320     if(RenderGlobal.threads >= 1) { /* only set as an arg in background mode */
02321         re->r.threads= MIN2(RenderGlobal.threads, BLENDER_MAX_THREADS);
02322     } else if ((re->r.mode & R_FIXED_THREADS)==0 || RenderGlobal.threads == 0) { /* Automatic threads */
02323         re->r.threads = BLI_system_thread_count();
02324     }
02325 }
02326 
02327 /* loads in image into a result, size must match
02328  * x/y offsets are only used on a partial copy when dimensions dont match */
02329 void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
02330 {
02331     ImBuf *ibuf = IMB_loadiffname(filename, IB_rect);
02332 
02333     if(ibuf  && (ibuf->rect || ibuf->rect_float)) {
02334         if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
02335             if(ibuf->rect_float==NULL)
02336                 IMB_float_from_rect(ibuf);
02337 
02338             memcpy(layer->rectf, ibuf->rect_float, sizeof(float)*4*layer->rectx*layer->recty);
02339         } else {
02340             if ((ibuf->x - x >= layer->rectx) && (ibuf->y - y >= layer->recty)) {
02341                 ImBuf *ibuf_clip;
02342 
02343                 if(ibuf->rect_float==NULL)
02344                     IMB_float_from_rect(ibuf);
02345 
02346                 ibuf_clip = IMB_allocImBuf(layer->rectx, layer->recty, 32, IB_rectfloat);
02347                 if(ibuf_clip) {
02348                     IMB_rectcpy(ibuf_clip, ibuf, 0,0, x,y, layer->rectx, layer->recty);
02349 
02350                     memcpy(layer->rectf, ibuf_clip->rect_float, sizeof(float)*4*layer->rectx*layer->recty);
02351                     IMB_freeImBuf(ibuf_clip);
02352                 }
02353                 else {
02354                     BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'\n", filename);
02355                 }
02356             }
02357             else {
02358                 BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'\n", filename);
02359             }
02360         }
02361 
02362         IMB_freeImBuf(ibuf);
02363     }
02364     else {
02365         BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
02366     }
02367 }
02368 
02369 void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename)
02370 {
02371     if(!render_result_exr_file_read_path(result, filename)) {
02372         BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename);
02373         return;
02374     }
02375 }
02376 
02377 const float default_envmap_layout[] = { 0,0, 1,0, 2,0, 0,1, 1,1, 2,1 };
02378 
02379 int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, const char *relpath, const char imtype, float layout[12])
02380 {
02381     ImageFormatData imf;
02382     ImBuf *ibuf=NULL;
02383     int ok;
02384     int dx;
02385     int maxX=0,maxY=0,i=0;
02386     char filepath[FILE_MAX];
02387 
02388     if(env->cube[1]==NULL) {
02389         BKE_report(reports, RPT_ERROR, "There is no generated environment map available to save");
02390         return 0;
02391     }
02392 
02393     imf= scene->r.im_format;
02394     imf.imtype= imtype;
02395 
02396     dx= env->cube[1]->x;
02397 
02398     if (env->type == ENV_CUBE) {
02399         for (i=0; i < 12; i+=2) {
02400             maxX = MAX2(maxX,layout[i] + 1);
02401             maxY = MAX2(maxY,layout[i+1] + 1);
02402         }
02403 
02404         ibuf = IMB_allocImBuf(maxX*dx, maxY*dx, 24, IB_rectfloat);
02405 
02406         for (i=0; i < 12; i+=2)
02407             if (layout[i] > -1 && layout[i+1] > -1)
02408                 IMB_rectcpy(ibuf, env->cube[i/2], layout[i]*dx, layout[i+1]*dx, 0, 0, dx, dx);
02409     }
02410     else if (env->type == ENV_PLANE) {
02411         ibuf = IMB_allocImBuf(dx, dx, 24, IB_rectfloat);
02412         IMB_rectcpy(ibuf, env->cube[1], 0, 0, 0, 0, dx, dx);
02413     }
02414     else {
02415         BKE_report(reports, RPT_ERROR, "Invalid environment map type");
02416         return 0;
02417     }
02418 
02419     if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
02420         ibuf->profile = IB_PROFILE_LINEAR_RGB;
02421 
02422     /* to save, we first get absolute path */
02423     BLI_strncpy(filepath, relpath, sizeof(filepath));
02424     BLI_path_abs(filepath, G.main->name);
02425 
02426     ok= BKE_write_ibuf(ibuf, filepath, &imf);
02427 
02428     IMB_freeImBuf(ibuf);
02429 
02430     if(ok) {
02431         return TRUE;
02432     }
02433     else {
02434         BKE_report(reports, RPT_ERROR, "Error writing environment map.");
02435         return FALSE;
02436     }
02437 }
02438