Orange: new pipeline separated calculus for window matrix from converting
[blender.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->rectf)
158                 MEM_freeN(res->rectf);
159         
160         RE_freeN(res);
161 }
162
163 /* called by main render as well for parts */
164 /* will read info from Render *re to define layers */
165 /* called in threads */
166 /* winrct is coordinate rect of entire image, partrct the part within */
167 static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
168 {
169         RenderResult *rr;
170         RenderLayer *rl;
171         int rectx, recty;
172         
173         rectx= partrct->xmax - partrct->xmin;
174         recty= partrct->ymax - partrct->ymin;
175         
176         if(rectx<=0 || recty<=0)
177                 return NULL;
178         
179         rr= RE_callocN(sizeof(RenderResult), "new render result");
180         rr->rectx= rectx;
181         rr->recty= recty;
182         /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
183         rr->crop= crop;
184         
185         /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
186         rr->tilerect.xmin= partrct->xmin - re->disprect.xmin;
187         rr->tilerect.xmax= partrct->xmax - re->disprect.xmax;
188         rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
189         rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
190         
191         /* check renderdata for amount of layers */
192         /* for now just one */
193         rl= RE_callocN(sizeof(RenderLayer), "new render layer");
194         BLI_addtail(&rr->layers, rl);
195         
196         rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
197         rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
198         
199         return rr;
200 }
201
202
203 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
204 /* no test happens here if it fits... */
205 /* is used within threads */
206 static void merge_render_result(RenderResult *rr, RenderResult *rrpart)
207 {
208         RenderLayer *rl= rr->layers.first;
209         RenderLayer *rlp= rrpart->layers.first;
210         float *rf, *rfp;
211         int *rz=NULL, *rzp;
212         int y, height, len, copylen;
213         
214         if(rlp->rectf==NULL) return;
215         if(rl->rectf==NULL) return;
216         
217         rzp= NULL; //rlp->rectz;
218         rfp= rlp->rectf;
219         
220         copylen=len= rrpart->rectx;
221         height= rrpart->recty;
222         
223         if(rrpart->crop) {      /* filters add pixel extra */
224                 
225                 if(rzp) rzp+= rrpart->crop + rrpart->crop*len;
226                 if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len);
227                 
228                 copylen= len-2*rrpart->crop;
229                 height -= 2*rrpart->crop;
230                 
231                 //              rz= re->rectz+ (pa->miny + rrpart->crop)*rr->rectx+ (pa->minx+rrpart->crop);
232                 rf= rl->rectf+ ( (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop) )*4;
233         }
234         else {
235                 //              rz= re->rectz +  (pa->disprect.ymin*rr->rectx + pa->disprect.xmin);
236                 rf= rl->rectf+ (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin)*4;
237         }
238
239         for(y=0; y<height; y++) {
240                 if(rzp) {
241                         memcpy(rz, rzp, 4*copylen);
242                         rz+= rr->rectx;
243                         rzp+= len;
244                 }
245                 if(rfp) {
246                         memcpy(rf, rfp, 16*copylen);
247                         rf+= 4*rr->rectx;
248                         rfp+= 4*len;
249                 }
250         }
251 }
252
253
254 /* *************************************************** */
255
256 Render *RE_GetRender(const char *name)
257 {
258         Render *re;
259         
260         /* search for existing renders */
261         for(re= RenderList.first; re; re= re->next) {
262                 if(strncmp(re->name, name, RE_MAXNAME)==0) {
263                         break;
264                 }
265         }
266         return re;
267 }
268
269 /* if you want to know exactly what has been done */
270 RenderResult *RE_GetResult(Render *re)
271 {
272         if(re)
273                 return re->result;
274         return NULL;
275 }
276
277 /* fill provided result struct with what's currently active or done */
278 void RE_GetResultImage(Render *re, RenderResult *rr)
279 {
280         memset(rr, sizeof(RenderResult), 0);
281         
282         if(re && re->result) {
283                 RenderLayer *rl;
284                 
285                 rr->rectx= re->result->rectx;
286                 rr->recty= re->result->recty;
287                 rr->rectf= re->result->rectf;
288                 rr->rectz= re->result->rectz;
289                 rr->rect32= re->result->rect32;
290                 
291                 /* will become 'active' call */
292                 rl= re->result->layers.first;
293                 if(rr->rectf==NULL)
294                         rr->rectf= rl->rectf;
295                 if(rr->rectz==NULL)
296                         rr->rectz= rl->rectz;   
297         }
298 }
299
300 #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
301 /* caller is responsible for allocating rect in correct size! */
302 void RE_ResultGet32(Render *re, unsigned int *rect)
303 {
304         RenderResult rres;
305         
306         RE_GetResultImage(re, &rres);
307         if(rres.rect32) 
308                 memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
309         else if(rres.rectf) {
310                 float *fp= rres.rectf;
311                 int tot= rres.rectx*rres.recty;
312                 char *cp= (char *)rect;
313                 
314                 for(;tot>0; tot--, cp+=4, fp+=4) {
315                         cp[0] = FTOCHAR(fp[0]);
316                         cp[1] = FTOCHAR(fp[1]);
317                         cp[2] = FTOCHAR(fp[2]);
318                         cp[3] = FTOCHAR(fp[3]);
319                 }
320         }
321         else
322                 /* else fill with black */
323                 memset(rect, sizeof(int)*re->rectx*re->recty, 0);
324 }
325
326
327 RenderStats *RE_GetStats(Render *re)
328 {
329         return &re->i;
330 }
331
332 Render *RE_NewRender(const char *name)
333 {
334         Render *re;
335         
336         /* only one render per name exists */
337         re= RE_GetRender(name);
338         if(re) {
339                 BLI_remlink(&RenderList, re);
340                 RE_FreeRender(re);
341         }
342         
343         /* new render data struct */
344         re= RE_callocN(sizeof(Render), "new render");
345         BLI_addtail(&RenderList, re);
346         strncpy(re->name, name, RE_MAXNAME);
347         
348         /* set default empty callbacks */
349         re->display_init= result_nothing;
350         re->display_clear= result_nothing;
351         re->display_draw= result_rcti_nothing;
352         re->timecursor= int_nothing;
353         re->test_break= void_nothing;
354         re->test_return= void_nothing;
355         re->error= print_error; 
356         re->stats_draw= stats_nothing;
357         
358         /* init some variables */
359         re->ycor= 1.0f;
360         
361         return re;
362 }
363
364 /* only call this while you know it will remove the link too */
365 void RE_FreeRender(Render *re)
366 {
367         
368         free_renderdata_tables(re);
369         free_sample_tables(re);
370         
371         free_render_result(re->result);
372         
373         BLI_remlink(&RenderList, re);
374         RE_freeN(re);
375 }
376
377 /* exit blender */
378 void RE_FreeAllRender(void)
379 {
380         while(RenderList.first) {
381                 RE_FreeRender(RenderList.first);
382         }
383 }
384
385 /* ********* initialize state ******** */
386
387
388 /* what doesn't change during entire render sequence */
389 /* disprect is optional, if NULL it assumes full window render */
390 void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect)
391 {
392         re->ok= TRUE;   /* maybe flag */
393         
394         re->i.starttime= PIL_check_seconds_timer();
395         re->r= *rd;             /* hardcopy */
396         
397         re->winx= winx;
398         re->winy= winy;
399         if(disprect) {
400                 re->disprect= *disprect;
401                 re->rectx= disprect->xmax-disprect->xmin;
402                 re->recty= disprect->ymax-disprect->ymin;
403         }
404         else {
405                 re->disprect.xmin= re->disprect.xmax= 0;
406                 re->disprect.xmax= winx;
407                 re->disprect.ymax= winy;
408                 re->rectx= winx;
409                 re->recty= winy;
410         }
411         
412         if(re->rectx < 2 || re->recty < 2) {
413                 re->error("Image too small");
414                 re->ok= 0;
415         }
416         else {
417                 /* check state variables, osa? */
418                 if(re->r.mode & (R_OSA|R_MBLUR)) {
419                         re->osa= re->r.osa;
420                         if(re->osa>16) re->osa= 16;
421                 }
422                 else re->osa= 0;
423                 
424                 /* always call, checks for gamma, gamma tables and jitter too */
425                 make_sample_tables(re); 
426                 
427                 /* initialize render result */
428                 free_render_result(re->result);
429                 re->result= new_render_result(re, &re->disprect, 0);
430
431         }
432 }
433
434 void RE_SetDispRect (struct Render *re, rcti *disprect)
435 {
436         re->disprect= *disprect;
437         re->rectx= disprect->xmax-disprect->xmin;
438         re->recty= disprect->ymax-disprect->ymin;
439         
440         /* initialize render result */
441         free_render_result(re->result);
442         re->result= new_render_result(re, &re->disprect, 0);
443 }
444
445 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
446 {
447         /* re->ok flag? */
448         
449         re->viewplane= *viewplane;
450         re->clipsta= clipsta;
451         re->clipend= clipend;
452
453         i_window(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
454 }
455
456 void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
457 {
458         /* re->ok flag? */
459         
460         re->viewplane= *viewplane;
461         re->clipsta= clipsta;
462         re->clipend= clipend;
463         re->r.mode |= R_ORTHO;
464
465         i_ortho(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
466 }
467
468 void RE_SetView(Render *re, float mat[][4])
469 {
470         /* re->ok flag? */
471         Mat4CpyMat4(re->viewmat, mat);
472         Mat4Invert(re->viewinv, re->viewmat);
473 }
474
475 /* image and movie output has to move to either imbuf or kernel */
476
477 void RE_display_init_cb(Render *re, void (*f)(RenderResult *rr))
478 {
479         re->display_init= f;
480 }
481 void RE_display_clear_cb(Render *re, void (*f)(RenderResult *rr))
482 {
483         re->display_clear= f;
484 }
485 void RE_display_draw_cb(Render *re, void (*f)(RenderResult *rr, rcti *rect))
486 {
487         re->display_draw= f;
488 }
489
490 void RE_stats_draw_cb(Render *re, void (*f)(RenderStats *rs))
491 {
492         re->stats_draw= f;
493 }
494 void RE_timecursor_cb(Render *re, void (*f)(int))
495 {
496         re->timecursor= f;
497 }
498
499 void RE_test_break_cb(Render *re, int (*f)(void))
500 {
501         re->test_break= f;
502 }
503 void RE_test_return_cb(Render *re, int (*f)(void))
504 {
505         re->test_return= f;
506 }
507 void RE_error_cb(Render *re, void (*f)(const char *str))
508 {
509         re->error= f;
510 }
511
512
513 /* ********* add object data (later) ******** */
514
515 /* object is considered fully prepared on correct time etc */
516 /* includes lights */
517 void RE_AddObject(Render *re, Object *ob)
518 {
519         
520 }
521
522 /* ********** basic thread control API ************ */
523
524 #define RE_MAX_THREAD 4
525
526 typedef struct ThreadSlot {
527         RenderPart *part;
528         int avail;
529 } ThreadSlot;
530
531 static ThreadSlot threadslots[RE_MAX_THREAD];
532
533 static void init_threadslots(int tot)
534 {
535         int a;
536         
537         if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
538         else if(tot<1) tot= 1;
539         
540         for(a=0; a< RE_MAX_THREAD; a++) {
541                 threadslots[a].part= NULL;
542                 if(a<tot)
543                         threadslots[a].avail= 1;
544                 else
545                         threadslots[a].avail= 0;
546         }
547 }
548
549 static int available_threadslots(void)
550 {
551         int a, counter=0;
552         for(a=0; a< RE_MAX_THREAD; a++)
553                 if(threadslots[a].avail)
554                         counter++;
555         return counter;
556 }
557
558 static void insert_threadslot(RenderPart *pa)
559 {
560         int a;
561         for(a=0; a< RE_MAX_THREAD; a++) {
562                 if(threadslots[a].avail) {
563                         threadslots[a].avail= 0;
564                         threadslots[a].part= pa;
565                         pa->thread= a;
566                         break;
567                 }
568         }
569 }
570
571 static void remove_threadslot(RenderPart *pa)
572 {
573         int a;
574         for(a=0; a< RE_MAX_THREAD; a++) {
575                 if(threadslots[a].part==pa) {
576                         threadslots[a].avail= 1;
577                         threadslots[a].part= NULL;
578                 }
579         }
580 }
581
582 /* ********** basic thread control API ************ */
583
584 static int do_part_thread(void *pa_v)
585 {
586         RenderPart *pa= pa_v;
587         
588         /* need to return nicely all parts on esc */
589         if(R.test_break()==0) {
590                 
591                 pa->result= new_render_result(&R, &pa->disprect, pa->crop);
592                 
593                 if(R.osa)
594                         zbufshadeDA_tile(pa);
595                 else
596                         zbufshade_tile(pa);
597                         
598                 if(!R.test_break())
599                         merge_render_result(R.result, pa->result);
600         }
601         
602         pa->ready= 1;
603         remove_threadslot(pa);
604         
605         return 0;
606 }
607
608 /* returns with render result filled, not threaded */
609 static void render_tile_processor(Render *re)
610 {
611         RenderPart *pa;
612         
613         if(re->test_break())
614                 return;
615         
616         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
617         re->stats_draw(&re->i);
618         re->i.starttime= PIL_check_seconds_timer();
619  
620         if(re->result==NULL)
621                 return;
622         
623         initparts(re);
624         
625         /* assuming no new data gets added to dbase... */
626         R= *re;
627         
628         for(pa= re->parts.first; pa; pa= pa->next) {
629                 do_part_thread(pa);
630                 
631                 if(pa->result) {
632                         if(!re->test_break()) {
633                                 re->display_draw(pa->result, NULL);
634                                 re->i.partsdone++;
635                         }
636                         free_render_result(pa->result);
637                         pa->result= NULL;
638                 }               
639                 if(re->test_break())
640                         break;
641         }
642         
643         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
644         re->stats_draw(&re->i);
645
646         freeparts(re);
647 }
648
649 static RenderPart *find_nicest_part(Render *re)
650 {
651         RenderPart *pa, *best= NULL;
652         int centx=re->winx/2, centy=re->winy/2, tot=1;
653         int mindist, distx, disty;
654         
655         /* find center of rendered parts, image center counts for 1 too */
656         for(pa= re->parts.first; pa; pa= pa->next) {
657                 if(pa->ready) {
658                         centx+= (pa->disprect.xmin+pa->disprect.xmax)/2;
659                         centy+= (pa->disprect.ymin+pa->disprect.ymax)/2;
660                         tot++;
661                 }
662         }
663         centx/=tot;
664         centy/=tot;
665         
666         /* closest of the non-rendering parts */
667         mindist= re->winx*re->winy;
668         for(pa= re->parts.first; pa; pa= pa->next) {
669                 if(pa->ready==0 && pa->nr==0) {
670                         distx= centx - (pa->disprect.xmin+pa->disprect.xmax)/2;
671                         disty= centy - (pa->disprect.ymin+pa->disprect.ymax)/2;
672                         distx= (int)sqrt(distx*distx + disty*disty);
673                         if(distx<mindist) {
674                                 best= pa;
675                                 mindist= distx;
676                         }
677                 }
678         }
679         return best;
680 }
681
682 static void threaded_tile_processor(Render *re)
683 {
684         RenderPart *pa;
685         int maxthreads=2, rendering=1, counter= 1;
686         
687         if(re->result==NULL)
688                 return;
689         if(re->test_break())
690                 return;
691         
692         initparts(re);
693         init_threadslots(maxthreads);
694         
695         /* assuming no new data gets added to dbase... */
696         R= *re;
697         
698         malloc_lock = SDL_CreateMutex();
699         
700         while(rendering) {
701                 
702                 /* I noted that test_break() in a thread doesn't make ghost send ESC */
703                 if(available_threadslots() && !re->test_break()) {
704                         pa= find_nicest_part(re);
705                         if(pa) {
706                                 insert_threadslot(pa);
707                                 pa->nr= counter++;      /* only for stats */
708                                 SDL_CreateThread(do_part_thread, pa);
709                         }
710                 }
711                 else
712                         PIL_sleep_ms(50);
713                 
714                 /* check for ready ones to display, and if we need to continue */
715                 rendering= 0;
716                 for(pa= re->parts.first; pa; pa= pa->next) {
717                         if(pa->ready) {
718                                 if(pa->result) {
719                                         re->display_draw(pa->result, NULL);
720                                         free_render_result(pa->result);
721                                         pa->result= NULL;
722                                         re->i.partsdone++;
723                                 }
724                         }
725                         else rendering= 1;
726                 }
727                 
728                 /* on break, wait for all slots to get freed */
729                 if(re->test_break() && available_threadslots()==maxthreads)
730                         rendering= 0;
731                 
732         }
733         
734         if(malloc_lock) SDL_DestroyMutex(malloc_lock); malloc_lock= NULL;
735         
736         freeparts(re);
737 }
738
739 void RE_TileProcessor(Render *re)
740 {
741         if(re->r.mode & R_THREADS) 
742                 threaded_tile_processor(re);
743         else
744                 render_tile_processor(re);      
745 }
746
747
748 /* ************  This part uses API, for rendering Blender scenes ********** */
749
750 void render_one_frame(Render *re)
751 {
752         
753 //      re->cfra= cfra; /* <- unused! */
754         
755         /* make render verts/faces/halos/lamps */
756         RE_Database_FromScene(re, re->scene, 1);
757
758         RE_TileProcessor(re);
759         
760         /* free all render verts etc */
761         RE_Database_Free(re);
762 }
763
764 /* accumulates osa frames */
765 static void do_render_blurred(Render *re, float frame)
766 {
767         
768 }
769
770 /* interleaves 2 frames */
771 static void do_render_fields(Render *re)
772 {
773         
774 }
775
776 static void do_render_final(Render *re, Scene *scene)
777 {
778         if(re->r.scemode & R_DOSEQ) {
779                 re->result->rect32= MEM_callocN(sizeof(int)*re->rectx*re->recty, "rectot");
780                 if(!re->test_break()) 
781                         do_render_seq(re->result);
782         }
783         else {
784                 /* first check if theres nodetree with render result */
785                 int do_render= ntreeCompositNeedsRender(scene->nodetree);
786                 /* but.. do we use nodes? */
787                 if(scene->use_nodes==NULL) do_render= 1;
788                 
789                 re->scene= scene;
790                 
791                 if(do_render) {
792                         /* now use renderdata and camera to set viewplane */
793                         RE_SetCamera(re, re->scene->camera);
794                         
795                         if(re->r.mode & R_FIELDS)
796                                 do_render_fields(re);
797                         else if(re->r.mode & R_MBLUR)
798                                 do_render_blurred(re, re->scene->r.cfra);
799                         else
800                                 render_one_frame(re);
801                 }
802                 if(re->r.scemode & R_DOCOMP)
803                         ntreeCompositExecTree(scene->nodetree, &re->r, 0);
804         }
805         
806
807         re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
808         re->stats_draw(&re->i);
809         
810         re->display_draw(re->result, NULL);
811         
812 }
813
814
815 static int is_rendering_allowed(Render *re)
816 {
817         
818         /* forbidden combinations */
819         if(re->r.mode & R_PANORAMA) {
820                 if(re->r.mode & R_BORDER) {
821                         re->error("No border supported for Panorama");
822                         return 0;
823                 }
824                 if(re->r.yparts>1) {
825                         re->error("No Y-Parts supported for Panorama");
826                         return 0;
827                 }
828                 if(re->r.mode & R_ORTHO) {
829                         re->error("No Ortho render possible for Panorama");
830                         return 0;
831                 }
832         }
833         
834         if(re->r.mode & R_BORDER) {
835                 if(re->r.border.xmax <= re->r.border.xmin || 
836                    re->r.border.ymax <= re->r.border.ymin) {
837                         re->error("No border area selected.");
838                         return 0;
839                 }
840         }
841         
842         if(re->r.xparts*re->r.yparts>=2 && (re->r.mode & R_MOVIECROP) && (re->r.mode & R_BORDER)) {
843                 re->error("Combination of border, crop and parts not allowed");
844                 return 0;
845         }
846         
847         if(re->r.xparts*re->r.yparts>64) {
848                 re->error("No more than 64 parts supported");
849                 return 0;
850         }
851         
852         if(re->r.yparts>1 && (re->r.mode & R_PANORAMA)) {
853                 re->error("No Y-Parts supported for Panorama");
854                 return 0;
855         }
856         
857         /* check valid camera */
858         if(re->scene->camera==NULL)
859                 re->scene->camera= scene_find_camera(re->scene);
860         if(re->scene->camera==NULL) {
861                 re->error("No camera");
862                 return 0;
863         }
864         
865         
866         return 1;
867 }
868
869 /* evaluating scene options for general Blender render */
870 static int render_initialize_from_scene(Render *re, Scene *scene)
871 {
872         int winx, winy;
873         rcti disprect;
874         
875         /* r.xsch and r.ysch has the actual view window size
876                 r.border is the clipping rect */
877         
878         /* calculate actual render result and display size */
879         winx= (scene->r.size*scene->r.xsch)/100;
880         winy= (scene->r.size*scene->r.ysch)/100;
881         //      if(scene->r.mode & R_PANORAMA)
882         //              winx*= scene->r.xparts;
883         
884         /* only in movie case we render smaller part */
885         if(scene->r.mode & R_BORDER) {
886                 disprect.xmin= scene->r.border.xmin*winx;
887                 disprect.xmax= scene->r.border.xmax*winx;
888                 
889                 disprect.ymin= scene->r.border.ymin*winy;
890                 disprect.ymax= scene->r.border.ymax*winy;
891         }
892         else {
893                 disprect.xmin= disprect.ymin= 0;
894                 disprect.xmax= winx;
895                 disprect.ymax= winy;
896         }
897         
898         RE_InitState(re, &scene->r, winx, winy, &disprect);
899         
900         re->scene= scene;
901         if(!is_rendering_allowed(re))
902                 return 0;
903         
904         re->display_init(re->result);
905         re->display_clear(re->result);
906         
907         return 1;
908 }
909
910 /* general Blender frame render call */
911 /* should return 1 when all is OK, otherwise it throws up errors */
912 void RE_BlenderFrame(Render *re, Scene *scene, int frame)
913 {
914         /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
915         /* is also set by caller renderwin.c */
916         G.rendering= 1;
917         
918         if(render_initialize_from_scene(re, scene)) {
919                 do_render_final(re, scene);
920         }
921 }
922
923
924 /* saves images to disk */
925 void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
926 {
927         bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype);
928         int cfrao= scene->r.cfra;
929         char name[FILE_MAXDIR+FILE_MAXFILE];
930         
931         /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
932         /* is also set by caller renderwin.c */
933         G.rendering= 1;
934         
935         if(!render_initialize_from_scene(re, scene))
936            return;
937         
938         /* confusing... scene->r or re->r? make a decision once! */
939         if(BKE_imtype_is_movie(scene->r.imtype))
940                 mh->start_movie(&scene->r, re->rectx, re->recty);
941         
942         for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) {
943                 re->r.cfra= scene->r.cfra;      /* weak.... */
944                 
945                 do_render_final(re, scene);
946                 
947                 /* write image or movie */
948                 if(re->test_break()==0) {
949                         RenderResult rres;
950                         
951                         RE_GetResultImage(re, &rres);
952
953                         /* write movie or image */
954                         if(BKE_imtype_is_movie(scene->r.imtype)) {
955                                 if(rres.rect32==NULL) {
956                                         rres.rect32= MEM_mallocN(sizeof(int)*rres.rectx*rres.recty, "temp 32 bits rect");
957                                 }
958                                 RE_ResultGet32(re, rres.rect32);
959                                 mh->append_movie(scene->r.cfra, rres.rect32, rres.rectx, rres.recty);
960                                 printf("Append frame %d", scene->r.cfra);
961                         }
962                         else {
963                                 ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
964                                 int ok;
965                                 
966                                 BKE_makepicstring(name, (scene->r.cfra));
967                                 ibuf->rect= rres.rect32;                /* if not exists, BKE_write_ibuf makes one */
968                                 ibuf->rect_float= rres.rectf;
969                                 ibuf->zbuf_float= rres.rectz;
970                                 ok= BKE_write_ibuf(ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
971                                 IMB_freeImBuf(ibuf);    /* imbuf knows which rects are not part of ibuf */
972
973                                 if(ok==0) {
974                                         printf("Render error: cannot save %s\n", name);
975                                         break;
976                                 }
977                                 else printf("Saved: %s", name);
978                         }
979                         
980                         BLI_timestr(re->i.lastframetime, name);
981                         printf(" Time: %s\n", name);
982                         fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
983                 }
984                 
985                 if(G.afbreek==1) break;
986         }
987         
988         /* end movie */
989         if(BKE_imtype_is_movie(scene->r.imtype))
990                 mh->end_movie();
991
992         scene->r.cfra= cfrao;
993 }
994
995
996