3 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
19 * The Original Code is Copyright (C) 2006 Blender Foundation.
20 * All rights reserved.
22 * The Original Code is: all of this file.
24 * Contributor(s): none yet.
26 * ***** END GPL LICENSE BLOCK *****
34 #include "DNA_group_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
38 #include "BKE_global.h"
39 #include "BKE_image.h"
41 #include "BKE_scene.h"
42 #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
44 #include "MEM_guardedalloc.h"
46 #include "BLI_arithb.h"
47 #include "BLI_blenlib.h"
50 #include "IMB_imbuf.h"
51 #include "IMB_imbuf_types.h"
53 #include "RE_pipeline.h"
56 #include "BSE_sequence.h" /* <----------------- bad!!! */
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "renderdatabase.h"
62 #include "rendercore.h"
64 #include "initrender.h"
68 #include "SDL_thread.h"
74 - movie/image file init
75 - everything that doesn't change during animation
78 - camera, world, matrices
79 - make render verts, faces, halos, strands
80 - everything can change per frame/field
85 - layers/tiles optionally to disk or directly in Render Result
87 4) Composit Render Result
88 - also read external files etc
91 - save file or append in movie
96 /* ********* globals ******** */
98 /* here we store all renders */
99 static struct ListBase RenderList= {NULL, NULL};
101 /* hardcopy of current render, used while rendering for speed */
104 /* ********* alloc and free ******** */
107 static SDL_mutex *malloc_lock= NULL;
109 void *RE_mallocN(int len, char *name)
112 if(malloc_lock) SDL_mutexP(malloc_lock);
113 mem= MEM_mallocN(len, name);
114 if(malloc_lock) SDL_mutexV(malloc_lock);
117 void *RE_callocN(int len, char *name)
120 if(malloc_lock) SDL_mutexP(malloc_lock);
121 mem= MEM_callocN(len, name);
122 if(malloc_lock) SDL_mutexV(malloc_lock);
125 void RE_freeN(void *poin)
127 if(malloc_lock) SDL_mutexP(malloc_lock);
129 if(malloc_lock) SDL_mutexV(malloc_lock);
132 /* ********************** */
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);}
143 static void free_render_result(RenderResult *res)
145 if(res==NULL) return;
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);
156 MEM_freeN(res->rect32);
158 MEM_freeN(res->rectz);
160 MEM_freeN(res->rectf);
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)
173 SceneRenderLayer *srl;
176 rectx= partrct->xmax - partrct->xmin;
177 recty= partrct->ymax - partrct->ymin;
179 if(rectx<=0 || recty<=0)
182 rr= RE_callocN(sizeof(RenderResult), "new render result");
185 /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
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;
194 /* copy, so display callbacks can find out too */
195 rr->actlay= re->r.actlay;
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);
202 strcpy(rl->name, srl->name);
204 rl->layflag= srl->layflag;
205 rl->passflag= srl->passflag;
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");
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);
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");
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)
230 RenderLayer *rl, *rlp;
233 int y, height, len, copylen;
235 for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
237 /* first combined and z pass */
238 if(rl->rectf && rlp->rectf) {
244 copylen=len= rrpart->rectx;
245 height= rrpart->recty;
247 if(rrpart->crop) { /* filters add pixel extra */
249 if(rzp) rzp+= rrpart->crop + rrpart->crop*len;
250 if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len);
252 copylen= len-2*rrpart->crop;
253 height -= 2*rrpart->crop;
255 ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
257 rf= rl->rectf+ 4*ofs;
260 ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
262 rf= rl->rectf+ 4*ofs;
265 for(y=0; y<height; y++) {
267 memcpy(rz, rzp, 4*copylen);
272 memcpy(rf, rfp, 16*copylen);
282 /* *************************************************** */
284 Render *RE_GetRender(const char *name)
288 /* search for existing renders */
289 for(re= RenderList.first; re; re= re->next) {
290 if(strncmp(re->name, name, RE_MAXNAME)==0) {
297 /* if you want to know exactly what has been done */
298 RenderResult *RE_GetResult(Render *re)
305 /* fill provided result struct with what's currently active or done */
306 void RE_GetResultImage(Render *re, RenderResult *rr)
308 memset(rr, sizeof(RenderResult), 0);
310 if(re && re->result) {
313 rr->rectx= re->result->rectx;
314 rr->recty= re->result->recty;
316 rr->rectf= re->result->rectf;
317 rr->rectz= re->result->rectz;
318 rr->rect32= re->result->rect32;
321 rl= BLI_findlink(&re->result->layers, re->r.actlay);
324 rr->rectf= rl->rectf;
326 rr->rectz= rl->rectz;
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)
337 RE_GetResultImage(re, &rres);
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;
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]);
353 /* else fill with black */
354 memset(rect, sizeof(int)*re->rectx*re->recty, 0);
358 RenderStats *RE_GetStats(Render *re)
363 Render *RE_NewRender(const char *name)
367 /* only one render per name exists */
368 re= RE_GetRender(name);
370 BLI_remlink(&RenderList, re);
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);
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;
389 /* init some variables */
395 /* only call this while you know it will remove the link too */
396 void RE_FreeRender(Render *re)
399 free_renderdata_tables(re);
400 free_sample_tables(re);
402 free_render_result(re->result);
404 BLI_remlink(&RenderList, re);
409 void RE_FreeAllRender(void)
411 while(RenderList.first) {
412 RE_FreeRender(RenderList.first);
416 /* ********* initialize state ******** */
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)
423 re->ok= TRUE; /* maybe flag */
425 re->i.starttime= PIL_check_seconds_timer();
426 re->r= *rd; /* hardcopy */
431 re->disprect= *disprect;
432 re->rectx= disprect->xmax-disprect->xmin;
433 re->recty= disprect->ymax-disprect->ymin;
436 re->disprect.xmin= re->disprect.xmax= 0;
437 re->disprect.xmax= winx;
438 re->disprect.ymax= winy;
443 if(re->rectx < 2 || re->recty < 2) {
444 re->error("Image too small");
448 /* check state variables, osa? */
449 if(re->r.mode & (R_OSA|R_MBLUR)) {
451 if(re->osa>16) re->osa= 16;
455 /* always call, checks for gamma, gamma tables and jitter too */
456 make_sample_tables(re);
458 /* initialize render result */
459 free_render_result(re->result);
460 re->result= new_render_result(re, &re->disprect, 0);
465 void RE_SetDispRect (struct Render *re, rcti *disprect)
467 re->disprect= *disprect;
468 re->rectx= disprect->xmax-disprect->xmin;
469 re->recty= disprect->ymax-disprect->ymin;
471 /* initialize render result */
472 free_render_result(re->result);
473 re->result= new_render_result(re, &re->disprect, 0);
476 void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
480 re->viewplane= *viewplane;
481 re->clipsta= clipsta;
482 re->clipend= clipend;
484 i_window(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
487 void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend)
491 re->viewplane= *viewplane;
492 re->clipsta= clipsta;
493 re->clipend= clipend;
494 re->r.mode |= R_ORTHO;
496 i_ortho(re->viewplane.xmin, re->viewplane.xmax, re->viewplane.ymin, re->viewplane.ymax, re->clipsta, re->clipend, re->winmat);
499 void RE_SetView(Render *re, float mat[][4])
502 Mat4CpyMat4(re->viewmat, mat);
503 Mat4Invert(re->viewinv, re->viewmat);
506 /* image and movie output has to move to either imbuf or kernel */
508 void RE_display_init_cb(Render *re, void (*f)(RenderResult *rr))
512 void RE_display_clear_cb(Render *re, void (*f)(RenderResult *rr))
514 re->display_clear= f;
516 void RE_display_draw_cb(Render *re, void (*f)(RenderResult *rr, rcti *rect))
521 void RE_stats_draw_cb(Render *re, void (*f)(RenderStats *rs))
525 void RE_timecursor_cb(Render *re, void (*f)(int))
530 void RE_test_break_cb(Render *re, int (*f)(void))
534 void RE_test_return_cb(Render *re, int (*f)(void))
538 void RE_error_cb(Render *re, void (*f)(const char *str))
544 /* ********* add object data (later) ******** */
546 /* object is considered fully prepared on correct time etc */
547 /* includes lights */
548 void RE_AddObject(Render *re, Object *ob)
553 /* ********** basic thread control API ************ */
555 #define RE_MAX_THREAD 4
557 typedef struct ThreadSlot {
562 static ThreadSlot threadslots[RE_MAX_THREAD];
564 static void init_threadslots(int tot)
568 if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
569 else if(tot<1) tot= 1;
571 for(a=0; a< RE_MAX_THREAD; a++) {
572 threadslots[a].part= NULL;
574 threadslots[a].avail= 1;
576 threadslots[a].avail= 0;
580 static int available_threadslots(void)
583 for(a=0; a< RE_MAX_THREAD; a++)
584 if(threadslots[a].avail)
589 static void insert_threadslot(RenderPart *pa)
592 for(a=0; a< RE_MAX_THREAD; a++) {
593 if(threadslots[a].avail) {
594 threadslots[a].avail= 0;
595 threadslots[a].part= pa;
602 static void remove_threadslot(RenderPart *pa)
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;
613 /* ********** basic thread control API ************ */
615 static int do_part_thread(void *pa_v)
617 RenderPart *pa= pa_v;
619 /* need to return nicely all parts on esc */
620 if(R.test_break()==0) {
622 pa->result= new_render_result(&R, &pa->disprect, pa->crop);
625 zbufshadeDA_tile(pa);
630 merge_render_result(R.result, pa->result);
634 remove_threadslot(pa);
639 /* returns with render result filled, not threaded */
640 static void render_tile_processor(Render *re)
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();
656 /* assuming no new data gets added to dbase... */
659 for(pa= re->parts.first; pa; pa= pa->next) {
663 if(!re->test_break()) {
664 re->display_draw(pa->result, NULL);
667 free_render_result(pa->result);
674 re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
675 re->stats_draw(&re->i);
680 static RenderPart *find_nicest_part(Render *re)
682 RenderPart *pa, *best= NULL;
683 int centx=re->winx/2, centy=re->winy/2, tot=1;
684 int mindist, distx, disty;
686 /* find center of rendered parts, image center counts for 1 too */
687 for(pa= re->parts.first; pa; pa= pa->next) {
689 centx+= (pa->disprect.xmin+pa->disprect.xmax)/2;
690 centy+= (pa->disprect.ymin+pa->disprect.ymax)/2;
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);
713 static void threaded_tile_processor(Render *re)
716 int maxthreads=2, rendering=1, counter= 1;
724 init_threadslots(maxthreads);
726 /* assuming no new data gets added to dbase... */
729 malloc_lock = SDL_CreateMutex();
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);
737 insert_threadslot(pa);
738 pa->nr= counter++; /* only for stats */
739 SDL_CreateThread(do_part_thread, pa);
745 /* check for ready ones to display, and if we need to continue */
747 for(pa= re->parts.first; pa; pa= pa->next) {
750 re->display_draw(pa->result, NULL);
751 free_render_result(pa->result);
759 /* on break, wait for all slots to get freed */
760 if(re->test_break() && available_threadslots()==maxthreads)
765 if(malloc_lock) SDL_DestroyMutex(malloc_lock); malloc_lock= NULL;
770 void RE_TileProcessor(Render *re)
772 if(re->r.mode & R_THREADS)
773 threaded_tile_processor(re);
775 render_tile_processor(re);
779 /* ************ This part uses API, for rendering Blender scenes ********** */
781 void render_one_frame(Render *re)
784 // re->cfra= cfra; /* <- unused! */
786 /* make render verts/faces/halos/lamps */
787 RE_Database_FromScene(re, re->scene, 1);
789 RE_TileProcessor(re);
791 /* free all render verts etc */
792 RE_Database_Free(re);
795 /* accumulates osa frames */
796 static void do_render_blurred(Render *re, float frame)
801 /* interleaves 2 frames */
802 static void do_render_fields(Render *re)
807 static void do_render_final(Render *re, Scene *scene)
809 /* we set start time here, for main Blender loops */
810 re->i.starttime= PIL_check_seconds_timer();
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);
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;
826 /* now use renderdata and camera to set viewplane */
827 RE_SetCamera(re, re->scene->camera);
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);
834 render_one_frame(re);
836 if(re->r.scemode & R_DOCOMP)
837 ntreeCompositExecTree(scene->nodetree, &re->r, 0);
841 re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
842 re->stats_draw(&re->i);
844 re->display_draw(re->result, NULL);
849 static int is_rendering_allowed(Render *re)
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");
859 re->error("No Y-Parts supported for Panorama");
862 if(re->r.mode & R_ORTHO) {
863 re->error("No Ortho render possible for Panorama");
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.");
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");
881 if(re->r.xparts*re->r.yparts>64) {
882 re->error("No more than 64 parts supported");
886 if(re->r.yparts>1 && (re->r.mode & R_PANORAMA)) {
887 re->error("No Y-Parts supported for Panorama");
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");
903 /* evaluating scene options for general Blender render */
904 static int render_initialize_from_scene(Render *re, Scene *scene)
909 /* r.xsch and r.ysch has the actual view window size
910 r.border is the clipping rect */
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;
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;
923 disprect.ymin= scene->r.border.ymin*winy;
924 disprect.ymax= scene->r.border.ymax*winy;
927 disprect.xmin= disprect.ymin= 0;
932 RE_InitState(re, &scene->r, winx, winy, &disprect);
935 if(!is_rendering_allowed(re))
938 re->display_init(re->result);
939 re->display_clear(re->result);
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)
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 */
952 if(render_initialize_from_scene(re, scene)) {
953 do_render_final(re, scene);
958 /* saves images to disk */
959 void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
961 bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype);
962 int cfrao= scene->r.cfra;
963 char name[FILE_MAXDIR+FILE_MAXFILE];
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 */
969 if(!render_initialize_from_scene(re, scene))
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);
976 for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) {
977 re->r.cfra= scene->r.cfra; /* weak.... */
979 do_render_final(re, scene);
981 /* write image or movie */
982 if(re->test_break()==0) {
985 RE_GetResultImage(re, &rres);
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... */
991 if(rres.rect32==NULL) {
992 rres.rect32= MEM_mallocN(sizeof(int)*rres.rectx*rres.recty, "temp 32 bits rect");
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);
1001 ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
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 */
1012 printf("Render error: cannot save %s\n", name);
1015 else printf("Saved: %s", name);
1018 BLI_timestr(re->i.lastframetime, name);
1019 printf(" Time: %s\n", name);
1020 fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
1023 if(G.afbreek==1) break;
1027 if(BKE_imtype_is_movie(scene->r.imtype))
1030 scene->r.cfra= cfrao;