Orange; more render & compo stuff!
[blender-staging.git] / source / blender / render / intern / source / pipeline.c
1 /**  
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2006 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <math.h>
30 #include <limits.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 #include "DNA_group_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "BKE_global.h"
39 #include "BKE_image.h"
40 #include "BKE_node.h"
41 #include "BKE_scene.h"
42 #include "BKE_writeavi.h"       /* <------ should be replaced once with generic movie module */
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_arithb.h"
47 #include "BLI_blenlib.h"
48
49 #include "PIL_time.h"
50 #include "IMB_imbuf.h"
51 #include "IMB_imbuf_types.h"
52
53 #include "RE_pipeline.h"
54 #include "radio.h"
55
56 #include "BSE_sequence.h"  /* <----------------- bad!!! */
57
58 /* internal */
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "renderdatabase.h"
62 #include "rendercore.h"
63 #include "envmap.h"
64 #include "initrender.h"
65 #include "shadbuf.h"
66 #include "zbuf.h"
67
68 #include "SDL_thread.h"
69
70 /* render flow
71
72 1) Initialize state
73 - state data, tables
74 - movie/image file init
75 - everything that doesn't change during animation
76
77 2) Initialize data
78 - camera, world, matrices
79 - make render verts, faces, halos, strands
80 - everything can change per frame/field
81
82 3) Render Processor
83 - multiple layers
84 - tiles, rect, baking
85 - layers/tiles optionally to disk or directly in Render Result
86
87 4) Composit Render Result
88 - also read external files etc
89
90 5) Image Files
91 - save file or append in movie
92
93 */
94
95
96 /* ********* globals ******** */
97
98 /* here we store all renders */
99 static struct ListBase RenderList= {NULL, NULL};
100
101 /* hardcopy of current render, used while rendering for speed */
102 Render R;
103
104 /* ********* alloc and free ******** */
105
106
107 static SDL_mutex *malloc_lock= NULL;
108
109 void *RE_mallocN(int len, char *name)
110 {
111         void *mem;
112         if(malloc_lock) SDL_mutexP(malloc_lock);
113         mem= MEM_mallocN(len, name);
114         if(malloc_lock) SDL_mutexV(malloc_lock);
115         return mem;
116 }
117 void *RE_callocN(int len, char *name)
118 {
119         void *mem;
120         if(malloc_lock) SDL_mutexP(malloc_lock);
121         mem= MEM_callocN(len, name);
122         if(malloc_lock) SDL_mutexV(malloc_lock);
123         return mem;
124 }
125 void RE_freeN(void *poin)
126 {
127         if(malloc_lock) SDL_mutexP(malloc_lock);
128         MEM_freeN(poin);
129         if(malloc_lock) SDL_mutexV(malloc_lock);
130 }
131
132 /* ********************** */
133
134
135 /* default callbacks, set in each new render */
136 static void result_nothing(RenderResult *rr) {}
137 static void result_rcti_nothing(RenderResult *rr, rcti *rect) {}
138 static void stats_nothing(RenderStats *rs) {}
139 static void int_nothing(int val) {}
140 static int void_nothing(void) {return 0;}
141 static void print_error(const char *str) {printf("ERROR: %s\n", str);}
142
143 static void free_render_result(RenderResult *res)
144 {
145         if(res==NULL) return;
146
147         while(res->layers.first) {
148                 RenderLayer *rl= res->layers.first;
149                 if(rl->rectf) RE_freeN(rl->rectf);
150                 if(rl->rectz) RE_freeN(rl->rectz);
151                 BLI_remlink(&res->layers, rl);
152                 RE_freeN(rl);
153         }
154         
155         if(res->rect32)
156                 MEM_freeN(res->rect32);
157         if(res->rectz)
158                 MEM_freeN(res->rectz);
159         if(res->rectf)
160                 MEM_freeN(res->rectf);
161         
162         RE_freeN(res);
163 }
164
165 /* called by main render as well for parts */
166 /* will read info from Render *re to define layers */
167 /* called in threads */
168 /* winrct is coordinate rect of entire image, partrct the part within */
169 static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
170 {
171         RenderResult *rr;
172         RenderLayer *rl;
173         SceneRenderLayer *srl;
174         int rectx, recty;
175         
176         rectx= partrct->xmax - partrct->xmin;
177         recty= partrct->ymax - partrct->ymin;
178         
179         if(rectx<=0 || recty<=0)
180                 return NULL;
181         
182         rr= RE_callocN(sizeof(RenderResult), "new render result");
183         rr->rectx= rectx;
184         rr->recty= recty;
185         /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
186         rr->crop= crop;
187         
188         /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
189         rr->tilerect.xmin= partrct->xmin - re->disprect.xmin;
190         rr->tilerect.xmax= partrct->xmax - re->disprect.xmax;
191         rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
192         rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
193         
194         /* copy, so display callbacks can find out too */
195         rr->actlay= re->r.actlay;
196         
197         /* check renderdata for amount of layers */
198         for(srl= re->r.layers.first; srl; srl= srl->next) {
199                 rl= RE_callocN(sizeof(RenderLayer), "new render layer");
200                 BLI_addtail(&rr->layers, rl);
201                 
202                 strcpy(rl->name, srl->name);
203                 rl->lay= srl->lay;
204                 rl->layflag= srl->layflag;
205                 rl->passflag= srl->passflag;
206                 
207                 rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
208                 if(srl->passflag  & SCE_PASS_Z)
209                         rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
210                 
211         }
212         /* previewrender and envmap don't do layers, so we make a default one */
213         if(rr->layers.first==NULL) {
214                 rl= RE_callocN(sizeof(RenderLayer), "new render layer");
215                 BLI_addtail(&rr->layers, rl);
216                 
217                 rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
218                 rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
219         }
220         
221         return rr;
222 }
223
224
225 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
226 /* no test happens here if it fits... we also assume layers are in sync */
227 /* is used within threads */
228 static void merge_render_result(RenderResult *rr, RenderResult *rrpart)
229 {
230         RenderLayer *rl, *rlp;
231         float *rf, *rfp;
232         float *rz, *rzp;
233         int y, height, len, copylen;
234         
235         for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
236                 
237                 /* first combined and z pass */
238                 if(rl->rectf && rlp->rectf) {
239                         int ofs;
240                         
241                         rzp= rlp->rectz;
242                         rfp= rlp->rectf;
243                         
244                         copylen=len= rrpart->rectx;
245                         height= rrpart->recty;
246                         
247                         if(rrpart->crop) {      /* filters add pixel extra */
248                                 
249                                 if(rzp) rzp+= rrpart->crop + rrpart->crop*len;
250                                 if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len);
251                                 
252                                 copylen= len-2*rrpart->crop;
253                                 height -= 2*rrpart->crop;
254                                 
255                                 ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
256                                 rz= rl->rectz+ ofs;
257                                 rf= rl->rectf+ 4*ofs;
258                         }
259                         else {
260                                 ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
261                                 rz= rl->rectz+ ofs;
262                                 rf= rl->rectf+ 4*ofs;
263                         }
264
265                         for(y=0; y<height; y++) {
266                                 if(rzp) {
267                                         memcpy(rz, rzp, 4*copylen);
268                                         rz+= rr->rectx;
269                                         rzp+= len;
270                                 }
271                                 if(rfp) {
272                                         memcpy(rf, rfp, 16*copylen);
273                                         rf+= 4*rr->rectx;
274                                         rfp+= 4*len;
275                                 }
276                         }
277                 }
278         }
279 }
280
281
282 /* *************************************************** */
283
284 Render *RE_GetRender(const char *name)
285 {
286         Render *re;
287         
288         /* search for existing renders */
289         for(re= RenderList.first; re; re= re->next) {
290                 if(strncmp(re->name, name, RE_MAXNAME)==0) {
291                         break;
292                 }
293         }
294         return re;
295 }
296
297 /* if you want to know exactly what has been done */
298 RenderResult *RE_GetResult(Render *re)
299 {
300         if(re)
301                 return re->result;
302         return NULL;
303 }
304
305 /* fill provided result struct with what's currently active or done */
306 void RE_GetResultImage(Render *re, RenderResult *rr)
307 {
308         memset(rr, sizeof(RenderResult), 0);
309
310         if(re && re->result) {
311                 RenderLayer *rl;
312                 
313                 rr->rectx= re->result->rectx;
314                 rr->recty= re->result->recty;
315                 
316                 rr->rectf= re->result->rectf;
317                 rr->rectz= re->result->rectz;
318                 rr->rect32= re->result->rect32;
319                 
320                 /* active layer */
321                 rl= BLI_findlink(&re->result->layers, re->r.actlay);
322                 if(rl) {
323                         if(rr->rectf==NULL)
324                                 rr->rectf= rl->rectf;
325                         if(rr->rectz==NULL)
326                                 rr->rectz= rl->rectz;   
327                 }
328         }
329 }
330
331 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
332 /* caller is responsible for allocating rect in correct size! */
333 void RE_ResultGet32(Render *re, unsigned int *rect)
334 {
335         RenderResult rres;
336         
337         RE_GetResultImage(re, &rres);
338         if(rres.rect32) 
339                 memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
340         else if(rres.rectf) {
341                 float *fp= rres.rectf;
342                 int tot= rres.rectx*rres.recty;
343                 char *cp= (char *)rect;
344                 
345                 for(;tot>0; tot--, cp+=4, fp+=4) {
346                         cp[0] = FTOCHAR(fp[0]);
347                         cp[1] = FTOCHAR(fp[1]);
348                         cp[2] = FTOCHAR(fp[2]);
349                         cp[3] = FTOCHAR(fp[3]);
350                 }
351         }
352         else
353                 /* else fill with black */
354                 memset(rect, sizeof(int)*re->rectx*re->recty, 0);
355 }
356
357
358 RenderStats *RE_GetStats(Render *re)
359 {
360         return &re->i;
361 }
362
363 Render *RE_NewRender(const char *name)
364 {
365         Render *re;
366         
367         /* only one render per name exists */
368         re= RE_GetRender(name);
369         if(re) {
370                 BLI_remlink(&RenderList, re);
371                 RE_FreeRender(re);
372         }
373         
374         /* new render data struct */
375         re= RE_callocN(sizeof(Render), "new render");
376         BLI_addtail(&RenderList, re);
377         strncpy(re->name, name, RE_MAXNAME);
378         
379         /* set default empty callbacks */
380         re->display_init= result_nothing;
381         re->display_clear= result_nothing;
382         re->display_draw= result_rcti_nothing;
383         re->timecursor= int_nothing;
384         re->test_break= void_nothing;
385         re->test_return= void_nothing;
386         re->error= print_error; 
387         re->stats_draw= stats_nothing;
388         
389         /* init some variables */
390         re->ycor= 1.0f;
391         
392         return re;
393 }
394
395 /* only call this while you know it will remove the link too */
396 void RE_FreeRender(Render *re)
397 {
398         
399         free_renderdata_tables(re);
400         free_sample_tables(re);
401         
402         free_render_result(re->result);
403         
404         BLI_remlink(&RenderList, re);
405         RE_freeN(re);
406 }
407
408 /* exit blender */
409 void RE_FreeAllRender(void)
410 {
411         while(RenderList.first) {
412                 RE_FreeRender(RenderList.first);
413         }
414 }
415
416 /* ********* initialize state ******** */
417
418
419 /* what doesn't change during entire render sequence */
420 /* disprect is optional, if NULL it assumes full window render */
421 void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect)
422 {
423         re->ok= TRUE;   /* maybe flag */
424         
425         re->i.starttime= PIL_check_seconds_timer();
426         re->r= *rd;             /* hardcopy */
427         
428         re->winx= winx;
429         re->winy= winy;
430         if(disprect) {
431                 re->disprect= *disprect;
432                 re->rectx= disprect->xmax-disprect->xmin;
433                 re->recty= disprect->ymax-disprect->ymin;
434         }
435         else {
436                 re->disprect.xmin= re->disprect.xmax= 0;
437                 re->disprect.xmax= winx;
438                 re->disprect.ymax= winy;
439                 re->rectx= winx;
440                 re->recty= winy;
441         }
442         
443         if(re->rectx < 2 || re->recty < 2) {
444                 re->error("Image too small");
445                 re->ok= 0;
446         }
447         else {
448                 /* check state variables, osa? */
449                 if(re->r.mode & (R_OSA|R_MBLUR)) {
450                         re->osa= re->r.osa;
451                         if(re->osa>16) re->osa= 16;
452                 }
453                 else re->osa= 0;
454                 
455                 /* always call, checks for gamma, gamma tables and jitter too */
456                 make_sample_tables(re); 
457                 
458                 /* initialize render result */
459                 free_render_result(re->result);
460                 re->result= new_render_result(re, &re->disprect, 0);
461
462         }
463 }
464
465 void RE_SetDispRect (struct Render *re, rcti *disprect)
466 {
467         re->disprect= *disprect;
468         re->rectx= disprect->xmax-disprect->xmin;
469         re->recty= disprect->ymax-disprect->ymin;
470         
471         /* initialize render result */
472         free_render_result(re->result);
473         re->result= new_render_result(re, &re->disprect, 0);
474 }
475
476 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
477 {
478         /* re->ok flag? */
479         
480         re->viewplane= *viewplane;
481         re->clipsta= clipsta;
482         re->clipend= clipend;
483
484         i_window(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
485 }
486
487 void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
488 {
489         /* re->ok flag? */
490         
491         re->viewplane= *viewplane;
492         re->clipsta= clipsta;
493         re->clipend= clipend;
494         re->r.mode |= R_ORTHO;
495
496         i_ortho(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
497 }
498
499 void RE_SetView(Render *re, float mat[][4])
500 {
501         /* re->ok flag? */
502         Mat4CpyMat4(re->viewmat, mat);
503         Mat4Invert(re->viewinv, re->viewmat);
504 }
505
506 /* image and movie output has to move to either imbuf or kernel */
507
508 void RE_display_init_cb(Render *re, void (*f)(RenderResult *rr))
509 {
510         re->display_init= f;
511 }
512 void RE_display_clear_cb(Render *re, void (*f)(RenderResult *rr))
513 {
514         re->display_clear= f;
515 }
516 void RE_display_draw_cb(Render *re, void (*f)(RenderResult *rr, rcti *rect))
517 {
518         re->display_draw= f;
519 }
520
521 void RE_stats_draw_cb(Render *re, void (*f)(RenderStats *rs))
522 {
523         re->stats_draw= f;
524 }
525 void RE_timecursor_cb(Render *re, void (*f)(int))
526 {
527         re->timecursor= f;
528 }
529
530 void RE_test_break_cb(Render *re, int (*f)(void))
531 {
532         re->test_break= f;
533 }
534 void RE_test_return_cb(Render *re, int (*f)(void))
535 {
536         re->test_return= f;
537 }
538 void RE_error_cb(Render *re, void (*f)(const char *str))
539 {
540         re->error= f;
541 }
542
543
544 /* ********* add object data (later) ******** */
545
546 /* object is considered fully prepared on correct time etc */
547 /* includes lights */
548 void RE_AddObject(Render *re, Object *ob)
549 {
550         
551 }
552
553 /* ********** basic thread control API ************ */
554
555 #define RE_MAX_THREAD 4
556
557 typedef struct ThreadSlot {
558         RenderPart *part;
559         int avail;
560 } ThreadSlot;
561
562 static ThreadSlot threadslots[RE_MAX_THREAD];
563
564 static void init_threadslots(int tot)
565 {
566         int a;
567         
568         if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
569         else if(tot<1) tot= 1;
570         
571         for(a=0; a< RE_MAX_THREAD; a++) {
572                 threadslots[a].part= NULL;
573                 if(a<tot)
574                         threadslots[a].avail= 1;
575                 else
576                         threadslots[a].avail= 0;
577         }
578 }
579
580 static int available_threadslots(void)
581 {
582         int a, counter=0;
583         for(a=0; a< RE_MAX_THREAD; a++)
584                 if(threadslots[a].avail)
585                         counter++;
586         return counter;
587 }
588
589 static void insert_threadslot(RenderPart *pa)
590 {
591         int a;
592         for(a=0; a< RE_MAX_THREAD; a++) {
593                 if(threadslots[a].avail) {
594                         threadslots[a].avail= 0;
595                         threadslots[a].part= pa;
596                         pa->thread= a;
597                         break;
598                 }
599         }
600 }
601
602 static void remove_threadslot(RenderPart *pa)
603 {
604         int a;
605         for(a=0; a< RE_MAX_THREAD; a++) {
606                 if(threadslots[a].part==pa) {
607                         threadslots[a].avail= 1;
608                         threadslots[a].part= NULL;
609                 }
610         }
611 }
612
613 /* ********** basic thread control API ************ */
614
615 static int do_part_thread(void *pa_v)
616 {
617         RenderPart *pa= pa_v;
618         
619         /* need to return nicely all parts on esc */
620         if(R.test_break()==0) {
621                 
622                 pa->result= new_render_result(&R, &pa->disprect, pa->crop);
623                 
624                 if(R.osa)
625                         zbufshadeDA_tile(pa);
626                 else
627                         zbufshade_tile(pa);
628                         
629                 if(!R.test_break())
630                         merge_render_result(R.result, pa->result);
631         }
632         
633         pa->ready= 1;
634         remove_threadslot(pa);
635         
636         return 0;
637 }
638
639 /* returns with render result filled, not threaded */
640 static void render_tile_processor(Render *re)
641 {
642         RenderPart *pa;
643         
644         if(re->test_break())
645                 return;
646         
647         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
648         re->stats_draw(&re->i);
649         re->i.starttime= PIL_check_seconds_timer();
650  
651         if(re->result==NULL)
652                 return;
653         
654         initparts(re);
655         
656         /* assuming no new data gets added to dbase... */
657         R= *re;
658         
659         for(pa= re->parts.first; pa; pa= pa->next) {
660                 do_part_thread(pa);
661                 
662                 if(pa->result) {
663                         if(!re->test_break()) {
664                                 re->display_draw(pa->result, NULL);
665                                 re->i.partsdone++;
666                         }
667                         free_render_result(pa->result);
668                         pa->result= NULL;
669                 }               
670                 if(re->test_break())
671                         break;
672         }
673         
674         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
675         re->stats_draw(&re->i);
676
677         freeparts(re);
678 }
679
680 static RenderPart *find_nicest_part(Render *re)
681 {
682         RenderPart *pa, *best= NULL;
683         int centx=re->winx/2, centy=re->winy/2, tot=1;
684         int mindist, distx, disty;
685         
686         /* find center of rendered parts, image center counts for 1 too */
687         for(pa= re->parts.first; pa; pa= pa->next) {
688                 if(pa->ready) {
689                         centx+= (pa->disprect.xmin+pa->disprect.xmax)/2;
690                         centy+= (pa->disprect.ymin+pa->disprect.ymax)/2;
691                         tot++;
692                 }
693         }
694         centx/=tot;
695         centy/=tot;
696         
697         /* closest of the non-rendering parts */
698         mindist= re->winx*re->winy;
699         for(pa= re->parts.first; pa; pa= pa->next) {
700                 if(pa->ready==0 && pa->nr==0) {
701                         distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2;
702                         disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2;
703                         distx= (int)sqrt(distx*distx + disty*disty);
704                         if(distx<mindist) {
705                                 best= pa;
706                                 mindist= distx;
707                         }
708                 }
709         }
710         return best;
711 }
712
713 static void threaded_tile_processor(Render *re)
714 {
715         RenderPart *pa;
716         int maxthreads=2, rendering=1, counter= 1;
717         
718         if(re->result==NULL)
719                 return;
720         if(re->test_break())
721                 return;
722         
723         initparts(re);
724         init_threadslots(maxthreads);
725         
726         /* assuming no new data gets added to dbase... */
727         R= *re;
728         
729         malloc_lock = SDL_CreateMutex();
730         
731         while(rendering) {
732                 
733                 /* I noted that test_break() in a thread doesn't make ghost send ESC */
734                 if(available_threadslots() && !re->test_break()) {
735                         pa= find_nicest_part(re);
736                         if(pa) {
737                                 insert_threadslot(pa);
738                                 pa->nr= counter++;      /* only for stats */
739                                 SDL_CreateThread(do_part_thread, pa);
740                         }
741                 }
742                 else
743                         PIL_sleep_ms(50);
744                 
745                 /* check for ready ones to display, and if we need to continue */
746                 rendering= 0;
747                 for(pa= re->parts.first; pa; pa= pa->next) {
748                         if(pa->ready) {
749                                 if(pa->result) {
750                                         re->display_draw(pa->result, NULL);
751                                         free_render_result(pa->result);
752                                         pa->result= NULL;
753                                         re->i.partsdone++;
754                                 }
755                         }
756                         else rendering= 1;
757                 }
758                 
759                 /* on break, wait for all slots to get freed */
760                 if(re->test_break() && available_threadslots()==maxthreads)
761                         rendering= 0;
762                 
763         }
764         
765         if(malloc_lock) SDL_DestroyMutex(malloc_lock); malloc_lock= NULL;
766         
767         freeparts(re);
768 }
769
770 void RE_TileProcessor(Render *re)
771 {
772         if(re->r.mode & R_THREADS) 
773                 threaded_tile_processor(re);
774         else
775                 render_tile_processor(re);      
776 }
777
778
779 /* ************  This part uses API, for rendering Blender scenes ********** */
780
781 void render_one_frame(Render *re)
782 {
783         
784 //      re->cfra= cfra; /* <- unused! */
785         
786         /* make render verts/faces/halos/lamps */
787         RE_Database_FromScene(re, re->scene, 1);
788
789         RE_TileProcessor(re);
790         
791         /* free all render verts etc */
792         RE_Database_Free(re);
793 }
794
795 /* accumulates osa frames */
796 static void do_render_blurred(Render *re, float frame)
797 {
798         
799 }
800
801 /* interleaves 2 frames */
802 static void do_render_fields(Render *re)
803 {
804         
805 }
806
807 static void do_render_final(Render *re, Scene *scene)
808 {
809         /* we set start time here, for main Blender loops */
810         re->i.starttime= PIL_check_seconds_timer();
811
812         if(re->r.scemode & R_DOSEQ) {
813                 re->result->rect32= MEM_callocN(sizeof(int)*re->rectx*re->recty, "rectot");
814                 if(!re->test_break()) 
815                         do_render_seq(re->result);
816         }
817         else {
818                 /* first check if theres nodetree with render result */
819                 int do_render= ntreeCompositNeedsRender(scene->nodetree);
820                 /* but.. do we use nodes? */
821                 if(scene->use_nodes==NULL) do_render= 1;
822                 
823                 re->scene= scene;
824                 
825                 if(do_render) {
826                         /* now use renderdata and camera to set viewplane */
827                         RE_SetCamera(re, re->scene->camera);
828                         
829                         if(re->r.mode & R_FIELDS)
830                                 do_render_fields(re);
831                         else if(re->r.mode & R_MBLUR)
832                                 do_render_blurred(re, re->scene->r.cfra);
833                         else
834                                 render_one_frame(re);
835                 }
836                 if(re->r.scemode & R_DOCOMP)
837                         ntreeCompositExecTree(scene->nodetree, &re->r, 0);
838         }
839         
840
841         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
842         re->stats_draw(&re->i);
843         
844         re->display_draw(re->result, NULL);
845         
846 }
847
848
849 static int is_rendering_allowed(Render *re)
850 {
851         
852         /* forbidden combinations */
853         if(re->r.mode & R_PANORAMA) {
854                 if(re->r.mode & R_BORDER) {
855                         re->error("No border supported for Panorama");
856                         return 0;
857                 }
858                 if(re->r.yparts>1) {
859                         re->error("No Y-Parts supported for Panorama");
860                         return 0;
861                 }
862                 if(re->r.mode & R_ORTHO) {
863                         re->error("No Ortho render possible for Panorama");
864                         return 0;
865                 }
866         }
867         
868         if(re->r.mode & R_BORDER) {
869                 if(re->r.border.xmax <= re->r.border.xmin || 
870                    re->r.border.ymax <= re->r.border.ymin) {
871                         re->error("No border area selected.");
872                         return 0;
873                 }
874         }
875         
876         if(re->r.xparts*re->r.yparts>=2 && (re->r.mode & R_MOVIECROP) && (re->r.mode & R_BORDER)) {
877                 re->error("Combination of border, crop and parts not allowed");
878                 return 0;
879         }
880         
881         if(re->r.xparts*re->r.yparts>64) {
882                 re->error("No more than 64 parts supported");
883                 return 0;
884         }
885         
886         if(re->r.yparts>1 && (re->r.mode & R_PANORAMA)) {
887                 re->error("No Y-Parts supported for Panorama");
888                 return 0;
889         }
890         
891         /* check valid camera */
892         if(re->scene->camera==NULL)
893                 re->scene->camera= scene_find_camera(re->scene);
894         if(re->scene->camera==NULL) {
895                 re->error("No camera");
896                 return 0;
897         }
898         
899         
900         return 1;
901 }
902
903 /* evaluating scene options for general Blender render */
904 static int render_initialize_from_scene(Render *re, Scene *scene)
905 {
906         int winx, winy;
907         rcti disprect;
908         
909         /* r.xsch and r.ysch has the actual view window size
910                 r.border is the clipping rect */
911         
912         /* calculate actual render result and display size */
913         winx= (scene->r.size*scene->r.xsch)/100;
914         winy= (scene->r.size*scene->r.ysch)/100;
915         //      if(scene->r.mode & R_PANORAMA)
916         //              winx*= scene->r.xparts;
917         
918         /* only in movie case we render smaller part */
919         if(scene->r.mode & R_BORDER) {
920                 disprect.xmin= scene->r.border.xmin*winx;
921                 disprect.xmax= scene->r.border.xmax*winx;
922                 
923                 disprect.ymin= scene->r.border.ymin*winy;
924                 disprect.ymax= scene->r.border.ymax*winy;
925         }
926         else {
927                 disprect.xmin= disprect.ymin= 0;
928                 disprect.xmax= winx;
929                 disprect.ymax= winy;
930         }
931         
932         RE_InitState(re, &scene->r, winx, winy, &disprect);
933         
934         re->scene= scene;
935         if(!is_rendering_allowed(re))
936                 return 0;
937         
938         re->display_init(re->result);
939         re->display_clear(re->result);
940         
941         return 1;
942 }
943
944 /* general Blender frame render call */
945 /* should return 1 when all is OK, otherwise it throws up errors */
946 void RE_BlenderFrame(Render *re, Scene *scene, int frame)
947 {
948         /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
949         /* is also set by caller renderwin.c */
950         G.rendering= 1;
951         
952         if(render_initialize_from_scene(re, scene)) {
953                 do_render_final(re, scene);
954         }
955 }
956
957
958 /* saves images to disk */
959 void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
960 {
961         bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype);
962         int cfrao= scene->r.cfra;
963         char name[FILE_MAXDIR+FILE_MAXFILE];
964         
965         /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
966         /* is also set by caller renderwin.c */
967         G.rendering= 1;
968         
969         if(!render_initialize_from_scene(re, scene))
970            return;
971         
972         /* confusing... scene->r or re->r? make a decision once! */
973         if(BKE_imtype_is_movie(scene->r.imtype))
974                 mh->start_movie(&scene->r, re->rectx, re->recty);
975         
976         for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) {
977                 re->r.cfra= scene->r.cfra;      /* weak.... */
978                 
979                 do_render_final(re, scene);
980                 
981                 /* write image or movie */
982                 if(re->test_break()==0) {
983                         RenderResult rres;
984                         
985                         RE_GetResultImage(re, &rres);
986
987                         /* write movie or image */
988                         if(BKE_imtype_is_movie(scene->r.imtype)) {
989                                 /* note; the way it gets 32 bits rects is weak... */
990                                 int dofree=0;
991                                 if(rres.rect32==NULL) {
992                                         rres.rect32= MEM_mallocN(sizeof(int)*rres.rectx*rres.recty, "temp 32 bits rect");
993                                         dofree= 1;
994                                 }
995                                 RE_ResultGet32(re, rres.rect32);
996                                 mh->append_movie(scene->r.cfra, rres.rect32, rres.rectx, rres.recty);
997                                 if(dofree) MEM_freeN(rres.rect32);
998                                 printf("Append frame %d", scene->r.cfra);
999                         }
1000                         else {
1001                                 ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
1002                                 int ok;
1003                                 
1004                                 BKE_makepicstring(name, (scene->r.cfra));
1005                                 ibuf->rect= rres.rect32;                /* if not exists, BKE_write_ibuf makes one */
1006                                 ibuf->rect_float= rres.rectf;
1007                                 ibuf->zbuf_float= rres.rectz;
1008                                 ok= BKE_write_ibuf(ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
1009                                 IMB_freeImBuf(ibuf);    /* imbuf knows which rects are not part of ibuf */
1010
1011                                 if(ok==0) {
1012                                         printf("Render error: cannot save %s\n", name);
1013                                         break;
1014                                 }
1015                                 else printf("Saved: %s", name);
1016                         }
1017                         
1018                         BLI_timestr(re->i.lastframetime, name);
1019                         printf(" Time: %s\n", name);
1020                         fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
1021                 }
1022                 
1023                 if(G.afbreek==1) break;
1024         }
1025         
1026         /* end movie */
1027         if(BKE_imtype_is_movie(scene->r.imtype))
1028                 mh->end_movie();
1029
1030         scene->r.cfra= cfrao;
1031 }
1032
1033
1034