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