doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / editors / render / render_internal.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <math.h>
28 #include <string.h>
29 #include <stddef.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35 #include "BLI_threads.h"
36 #include "BLI_rand.h"
37 #include "BLI_utildefines.h"
38
39 #include "DNA_scene_types.h"
40
41 #include "BKE_blender.h"
42 #include "BKE_context.h"
43 #include "BKE_global.h"
44 #include "BKE_image.h"
45 #include "BKE_library.h"
46 #include "BKE_main.h"
47 #include "BKE_node.h"
48 #include "BKE_multires.h"
49 #include "BKE_report.h"
50 #include "BKE_sequencer.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "ED_screen.h"
56 #include "ED_object.h"
57
58 #include "RE_pipeline.h"
59 #include "IMB_imbuf.h"
60 #include "IMB_imbuf_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 #include "wm_window.h"
66
67 #include "render_intern.h"
68
69 static ScrArea *biggest_area(bContext *C);
70 static ScrArea *biggest_non_image_area(bContext *C);
71 static ScrArea *find_area_showing_r_result(bContext *C);
72 static ScrArea *find_area_image_empty(bContext *C);
73
74 /* called inside thread! */
75 void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
76 {
77         float x1, y1, *rectf= NULL;
78         int ymin, ymax, xmin, xmax;
79         int rymin, rxmin;
80         char *rectc;
81
82         /* if renrect argument, we only refresh scanlines */
83         if(renrect) {
84                 /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
85                 if(rr->renlay==NULL || renrect->ymax>=rr->recty)
86                         return;
87
88                 /* xmin here is first subrect x coord, xmax defines subrect width */
89                 xmin = renrect->xmin + rr->crop;
90                 xmax = renrect->xmax - xmin + rr->crop;
91                 if (xmax<2) return;
92
93                 ymin= renrect->ymin + rr->crop;
94                 ymax= renrect->ymax - ymin + rr->crop;
95                 if(ymax<2)
96                         return;
97                 renrect->ymin= renrect->ymax;
98
99         }
100         else {
101                 xmin = ymin = rr->crop;
102                 xmax = rr->rectx - 2*rr->crop;
103                 ymax = rr->recty - 2*rr->crop;
104         }
105
106         /* xmin ymin is in tile coords. transform to ibuf */
107         rxmin= rr->tilerect.xmin + xmin;
108         if(rxmin >= ibuf->x) return;
109         rymin= rr->tilerect.ymin + ymin;
110         if(rymin >= ibuf->y) return;
111
112         if(rxmin + xmax > ibuf->x)
113                 xmax= ibuf->x - rxmin;
114         if(rymin + ymax > ibuf->y)
115                 ymax= ibuf->y - rymin;
116
117         if(xmax < 1 || ymax < 1) return;
118
119         /* find current float rect for display, first case is after composit... still weak */
120         if(rr->rectf)
121                 rectf= rr->rectf;
122         else {
123                 if(rr->rect32)
124                         return;
125                 else {
126                         if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
127                         rectf= rr->renlay->rectf;
128                 }
129         }
130         if(rectf==NULL) return;
131
132         if(ibuf->rect==NULL)
133                 imb_addrectImBuf(ibuf);
134         
135         rectf+= 4*(rr->rectx*ymin + xmin);
136         rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
137         
138         /* XXX make nice consistent functions for this */
139         if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
140                 for(y1= 0; y1<ymax; y1++) {
141                         float *rf= rectf;
142                         float srgb[3];
143                         char *rc= rectc;
144                         const float dither = ibuf->dither / 255.0;
145
146                         /* XXX temp. because crop offset */
147                         if( rectc >= (char *)(ibuf->rect)) {
148                                 for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
149                                         const float d = (BLI_frand()-0.5)*dither;
150                                         srgb[0]= d + linearrgb_to_srgb(rf[0]);
151                                         srgb[1]= d + linearrgb_to_srgb(rf[1]);
152                                         srgb[2]= d + linearrgb_to_srgb(rf[2]);
153
154                                         rc[0]= FTOCHAR(srgb[0]);
155                                         rc[1]= FTOCHAR(srgb[1]);
156                                         rc[2]= FTOCHAR(srgb[2]);
157                                         rc[3]= FTOCHAR(rf[3]);
158                                 }
159                         }
160                         rectf += 4*rr->rectx;
161                         rectc += 4*ibuf->x;
162                 }
163         } else {
164                 for(y1= 0; y1<ymax; y1++) {
165                         float *rf= rectf;
166                         char *rc= rectc;
167                         float rgb[3];
168                         const float dither = ibuf->dither / 255.0;
169
170                         /* XXX temp. because crop offset */
171                         if( rectc >= (char *)(ibuf->rect)) {
172                                 for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
173                                         const float d = (BLI_frand()-0.5)*dither;
174                                         
175                                         rgb[0] = d + rf[0];
176                                         rgb[1] = d + rf[1];
177                                         rgb[2] = d + rf[2];
178                                         
179                                         rc[0]= FTOCHAR(rgb[0]);
180                                         rc[1]= FTOCHAR(rgb[1]);
181                                         rc[2]= FTOCHAR(rgb[2]);
182                                         rc[3]= FTOCHAR(rf[3]);
183                                 }
184                         }
185                         rectf += 4*rr->rectx;
186                         rectc += 4*ibuf->x;
187                 }
188         }       
189 }
190
191 /* new window uses x,y to set position */
192 void screen_set_image_output(bContext *C, int mx, int my)
193 {
194         wmWindow *win= CTX_wm_window(C);
195         Scene *scene= CTX_data_scene(C);
196         ScrArea *sa= NULL;
197         SpaceImage *sima;
198         int area_was_image=0;
199
200         if(scene->r.displaymode==R_OUTPUT_NONE)
201                 return;
202         
203         if(scene->r.displaymode==R_OUTPUT_WINDOW) {
204                 rcti rect;
205                 int sizex, sizey;
206
207                 sizex= 10 + (scene->r.xsch*scene->r.size)/100;
208                 sizey= 40 + (scene->r.ysch*scene->r.size)/100;
209
210                 /* arbitrary... miniature image window views don't make much sense */
211                 if(sizex < 320) sizex= 320;
212                 if(sizey < 256) sizey= 256;
213
214                 /* XXX some magic to calculate postition */
215                 rect.xmin= mx + win->posx - sizex/2;
216                 rect.ymin= my + win->posy - sizey/2;
217                 rect.xmax= rect.xmin + sizex;
218                 rect.ymax= rect.ymin + sizey;
219
220                 /* changes context! */
221                 WM_window_open_temp(C, &rect, WM_WINDOW_RENDER);
222
223                 sa= CTX_wm_area(C);
224         }
225         else if(scene->r.displaymode==R_OUTPUT_SCREEN) {
226                 if (CTX_wm_area(C) && CTX_wm_area(C)->spacetype == SPACE_IMAGE)
227                         area_was_image = 1;
228
229                 /* this function returns with changed context */
230                 ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE);
231                 sa= CTX_wm_area(C);
232         }
233
234         if(!sa) {
235                 sa= find_area_showing_r_result(C);
236                 if(sa==NULL)
237                         sa= find_area_image_empty(C);
238
239                 if(sa==NULL) {
240                         /* find largest open non-image area */
241                         sa= biggest_non_image_area(C);
242                         if(sa) {
243                                 ED_area_newspace(C, sa, SPACE_IMAGE);
244                                 sima= sa->spacedata.first;
245
246                                 /* makes ESC go back to prev space */
247                                 sima->flag |= SI_PREVSPACE;
248                         }
249                         else {
250                                 /* use any area of decent size */
251                                 sa= biggest_area(C);
252                                 if(sa->spacetype!=SPACE_IMAGE) {
253                                         // XXX newspace(sa, SPACE_IMAGE);
254                                         sima= sa->spacedata.first;
255
256                                         /* makes ESC go back to prev space */
257                                         sima->flag |= SI_PREVSPACE;
258                                 }
259                         }
260                 }
261         }
262         sima= sa->spacedata.first;
263
264         /* get the correct image, and scale it */
265         sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
266
267
268         /* if we're rendering to full screen, set appropriate hints on image editor
269          * so it can restore properly on pressing esc */
270         if(sa->full) {
271                 sima->flag |= SI_FULLWINDOW;
272
273                 /* Tell the image editor to revert to previous space in space list on close
274                  * _only_ if it wasn't already an image editor when the render was invoked */
275                 if (area_was_image == 0)
276                         sima->flag |= SI_PREVSPACE;
277                 else {
278                         /* Leave it alone so the image editor will just go back from
279                          * full screen to the original tiled setup */
280                         ;
281                 }
282
283         }
284
285 }
286
287
288 /* ****************************** render invoking ***************** */
289
290 /* set callbacks, exported to sequence render too.
291  Only call in foreground (UI) renders. */
292
293 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
294 /* window as the last possible alternative.                                                                        */
295 static ScrArea *biggest_non_image_area(bContext *C)
296 {
297         bScreen *sc= CTX_wm_screen(C);
298         ScrArea *sa, *big= NULL;
299         int size, maxsize= 0, bwmaxsize= 0;
300         short foundwin= 0;
301
302         for(sa= sc->areabase.first; sa; sa= sa->next) {
303                 if(sa->winx > 30 && sa->winy > 30) {
304                         size= sa->winx*sa->winy;
305                         if(sa->spacetype == SPACE_BUTS) {
306                                 if(foundwin == 0 && size > bwmaxsize) {
307                                         bwmaxsize= size;
308                                         big= sa;
309                                 }
310                         }
311                         else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
312                                 maxsize= size;
313                                 big= sa;
314                                 foundwin= 1;
315                         }
316                 }
317         }
318
319         return big;
320 }
321
322 static ScrArea *biggest_area(bContext *C)
323 {
324         bScreen *sc= CTX_wm_screen(C);
325         ScrArea *sa, *big= NULL;
326         int size, maxsize= 0;
327
328         for(sa= sc->areabase.first; sa; sa= sa->next) {
329                 size= sa->winx*sa->winy;
330                 if(size > maxsize) {
331                         maxsize= size;
332                         big= sa;
333                 }
334         }
335         return big;
336 }
337
338
339 static ScrArea *find_area_showing_r_result(bContext *C)
340 {
341         wmWindowManager *wm= CTX_wm_manager(C);
342         wmWindow *win;
343         ScrArea *sa = NULL;
344         SpaceImage *sima;
345
346         /* find an imagewindow showing render result */
347         for(win=wm->windows.first; win; win=win->next) {
348                 for(sa=win->screen->areabase.first; sa; sa= sa->next) {
349                         if(sa->spacetype==SPACE_IMAGE) {
350                                 sima= sa->spacedata.first;
351                                 if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
352                                         break;
353                         }
354                 }
355                 if(sa)
356                         break;
357         }
358
359         return sa;
360 }
361
362 static ScrArea *find_area_image_empty(bContext *C)
363 {
364         bScreen *sc= CTX_wm_screen(C);
365         ScrArea *sa;
366         SpaceImage *sima;
367
368         /* find an imagewindow showing render result */
369         for(sa=sc->areabase.first; sa; sa= sa->next) {
370                 if(sa->spacetype==SPACE_IMAGE) {
371                         sima= sa->spacedata.first;
372                         if(!sima->image)
373                                 break;
374                 }
375         }
376         return sa;
377 }
378
379 #if 0 // XXX not used
380 static ScrArea *find_empty_image_area(bContext *C)
381 {
382         bScreen *sc= CTX_wm_screen(C);
383         ScrArea *sa;
384         SpaceImage *sima;
385
386         /* find an imagewindow showing render result */
387         for(sa=sc->areabase.first; sa; sa= sa->next) {
388                 if(sa->spacetype==SPACE_IMAGE) {
389                         sima= sa->spacedata.first;
390                         if(!sima->image)
391                                 break;
392                 }
393         }
394         return sa;
395 }
396 #endif // XXX not used
397
398 static void render_error_reports(void *reports, const char *str)
399 {
400         BKE_report(reports, RPT_ERROR, str);
401 }
402
403 /* executes blocking render */
404 static int screen_render_exec(bContext *C, wmOperator *op)
405 {
406         Scene *scene= CTX_data_scene(C);
407         Render *re= RE_NewRender(scene->id.name);
408         Image *ima;
409         View3D *v3d= CTX_wm_view3d(C);
410         Main *mainp= CTX_data_main(C);
411         unsigned int lay= (v3d)? v3d->lay: scene->lay;
412         const short is_animation= RNA_boolean_get(op->ptr, "animation");
413         const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
414
415         if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
416                 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
417                 return OPERATOR_CANCELLED;
418         }
419
420         if(re==NULL) {
421                 re= RE_NewRender(scene->id.name);
422         }
423         
424         G.afbreek= 0;
425         RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
426         RE_error_cb(re, op->reports, render_error_reports);
427
428         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
429         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
430         BKE_image_backup_render(scene, ima);
431
432         /* cleanup sequencer caches before starting user triggered render.
433            otherwise, invalidated cache entries can make their way into
434            the output rendering. We can't put that into RE_BlenderFrame,
435            since sequence rendering can call that recursively... (peter) */
436         seq_stripelem_cache_cleanup();
437
438         if(is_animation)
439                 RE_BlenderAnim(re, mainp, scene, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports);
440         else
441                 RE_BlenderFrame(re, mainp, scene, NULL, lay, scene->r.cfra, is_write_still);
442
443         // no redraw needed, we leave state as we entered it
444         ED_update_for_newframe(mainp, scene, CTX_wm_screen(C), 1);
445
446         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
447
448         return OPERATOR_FINISHED;
449 }
450
451 typedef struct RenderJob {
452         Main *main;
453         Scene *scene;
454         Render *re;
455         wmWindow *win;
456         SceneRenderLayer *srl;
457         int lay;
458         short anim, write_still;
459         Image *image;
460         ImageUser iuser;
461         short *stop;
462         short *do_update;
463         float *progress;
464         ReportList *reports;
465 } RenderJob;
466
467 static void render_freejob(void *rjv)
468 {
469         RenderJob *rj= rjv;
470
471         MEM_freeN(rj);
472 }
473
474 /* str is IMA_MAX_RENDER_TEXT in size */
475 static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
476 {
477         char info_time_str[32]; // used to be extern to header_info.c
478         uintptr_t mem_in_use, mmap_in_use, peak_memory;
479         float megs_used_memory, mmap_used_memory, megs_peak_memory;
480         char *spos= str;
481
482         mem_in_use= MEM_get_memory_in_use();
483         mmap_in_use= MEM_get_mapped_memory_in_use();
484         peak_memory = MEM_get_peak_memory();
485
486         megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
487         mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
488         megs_peak_memory = (peak_memory)/(1024.0*1024.0);
489
490         if(scene->lay & 0xFF000000)
491                 spos+= sprintf(spos, "Localview | ");
492         else if(scene->r.scemode & R_SINGLE_LAYER)
493                 spos+= sprintf(spos, "Single Layer | ");
494
495         if(rs->statstr) {
496                 spos+= sprintf(spos, "%s ", rs->statstr);
497         }
498         else {
499                 spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
500                 if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
501                 if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
502                 spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory, megs_peak_memory);
503
504                 if(rs->curfield)
505                         spos+= sprintf(spos, "Field %d ", rs->curfield);
506                 if(rs->curblur)
507                         spos+= sprintf(spos, "Blur %d ", rs->curblur);
508         }
509
510         BLI_timestr(rs->lastframetime, info_time_str);
511         spos+= sprintf(spos, "Time:%s ", info_time_str);
512
513         if(rs->infostr && rs->infostr[0])
514                 spos+= sprintf(spos, "| %s ", rs->infostr);
515
516         /* very weak... but 512 characters is quite safe */
517         if(spos >= str+IMA_MAX_RENDER_TEXT)
518                 if (G.f & G_DEBUG)
519                         printf("WARNING! renderwin text beyond limit \n");
520
521 }
522
523 static void image_renderinfo_cb(void *rjv, RenderStats *rs)
524 {
525         RenderJob *rj= rjv;
526         RenderResult *rr;
527
528         rr= RE_AcquireResultRead(rj->re);
529
530         if(rr) {
531                 /* malloc OK here, stats_draw is not in tile threads */
532                 if(rr->text==NULL)
533                         rr->text= MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
534
535                 make_renderinfo_string(rs, rj->scene, rr->text);
536         }
537
538         RE_ReleaseResult(rj->re);
539
540         /* make jobs timer to send notifier */
541         *(rj->do_update)= 1;
542
543 }
544
545 static void render_progress_update(void *rjv, float progress)
546 {
547         RenderJob *rj= rjv;
548         
549         if (rj->progress)
550                 *rj->progress = progress;
551 }
552
553 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
554 {
555         RenderJob *rj= rjv;
556         Image *ima= rj->image;
557         ImBuf *ibuf;
558         void *lock;
559
560         /* only update if we are displaying the slot being rendered */
561         if(ima->render_slot != ima->last_render_slot)
562                 return;
563
564         ibuf= BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
565         if(ibuf) {
566                 image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
567
568                 /* make jobs timer to send notifier */
569                 *(rj->do_update)= 1;
570         }
571         BKE_image_release_ibuf(ima, lock);
572 }
573
574 static void render_startjob(void *rjv, short *stop, short *do_update, float *progress)
575 {
576         RenderJob *rj= rjv;
577
578         rj->stop= stop;
579         rj->do_update= do_update;
580         rj->progress= progress;
581
582         if(rj->anim)
583                 RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->lay, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports);
584         else
585                 RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->lay, rj->scene->r.cfra, rj->write_still);
586 }
587
588 static void render_endjob(void *rjv)
589 {
590         RenderJob *rj= rjv;     
591
592         /* this render may be used again by the sequencer without the active 'Render' where the callbacks
593          * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
594         RE_InitRenderCB(rj->re);
595
596         if(rj->main != G.main)
597                 free_main(rj->main);
598
599         /* else the frame will not update for the original value */
600         if(!(rj->scene->r.scemode & R_NO_FRAME_UPDATE))
601                 ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
602         
603         /* XXX above function sets all tags in nodes */
604         ntreeClearTags(rj->scene->nodetree);
605         
606         /* potentially set by caller */
607         rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
608         
609         if(rj->srl) {
610                 NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id);
611                 WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene);
612         }
613         
614         /* XXX render stability hack */
615         G.rendering = 0;
616         WM_main_add_notifier(NC_WINDOW, NULL);
617 }
618
619 /* called by render, check job 'stop' value or the global */
620 static int render_breakjob(void *rjv)
621 {
622         RenderJob *rj= rjv;
623
624         if(G.afbreek)
625                 return 1;
626         if(rj->stop && *(rj->stop))
627                 return 1;
628         return 0;
629 }
630
631 /* catch esc */
632 static int screen_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
633 {
634         /* no running blender, remove handler and pass through */
635         if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
636                 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
637         }
638
639         /* running render */
640         switch (event->type) {
641                 case ESCKEY:
642                         return OPERATOR_RUNNING_MODAL;
643                         break;
644         }
645         return OPERATOR_PASS_THROUGH;
646 }
647
648 /* using context, starts job */
649 static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
650 {
651         /* new render clears all callbacks */
652         Main *mainp;
653         Scene *scene= CTX_data_scene(C);
654         SceneRenderLayer *srl=NULL;
655         bScreen *screen= CTX_wm_screen(C);
656         View3D *v3d= CTX_wm_view3d(C);
657         Render *re;
658         wmJob *steve;
659         RenderJob *rj;
660         Image *ima;
661         int jobflag;
662         const short is_animation= RNA_boolean_get(op->ptr, "animation");
663         const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
664         
665         /* only one render job at a time */
666         if(WM_jobs_test(CTX_wm_manager(C), scene))
667                 return OPERATOR_CANCELLED;
668
669         if(!RE_is_rendering_allowed(scene, op->reports, render_error_reports)) {
670                 return OPERATOR_CANCELLED;
671         }
672
673         if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
674                 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
675                 return OPERATOR_CANCELLED;
676         }       
677         
678         /* stop all running jobs, currently previews frustrate Render */
679         WM_jobs_stop_all(CTX_wm_manager(C));
680
681         /* get main */
682         if(G.rt == 101) {
683                 /* thread-safety experiment, copy main from the undo buffer */
684                 mainp= BKE_undo_get_main(&scene);
685         }
686         else
687                 mainp= CTX_data_main(C);
688
689         /* cancel animation playback */
690         if (screen->animtimer)
691                 ED_screen_animation_play(C, 0, 0);
692         
693         /* handle UI stuff */
694         WM_cursor_wait(1);
695
696         /* flush multires changes (for sculpt) */
697         multires_force_render_update(CTX_data_active_object(C));
698
699         /* cleanup sequencer caches before starting user triggered render.
700            otherwise, invalidated cache entries can make their way into
701            the output rendering. We can't put that into RE_BlenderFrame,
702            since sequence rendering can call that recursively... (peter) */
703         seq_stripelem_cache_cleanup();
704
705         /* get editmode results */
706         ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
707
708         // store spare
709         // get view3d layer, local layer, make this nice api call to render
710         // store spare
711
712         /* ensure at least 1 area shows result */
713         screen_set_image_output(C, event->x, event->y);
714
715         jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
716         
717         /* single layer re-render */
718         if(RNA_property_is_set(op->ptr, "layer")) {
719                 SceneRenderLayer *rl;
720                 Scene *scn;
721                 char scene_name[19], rl_name[RE_MAXNAME];
722
723                 RNA_string_get(op->ptr, "layer", rl_name);
724                 RNA_string_get(op->ptr, "scene", scene_name);
725
726                 scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
727                 rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
728                 
729                 if (scn && rl) {
730                         scene = scn;
731                         srl = rl;
732                 }
733                 jobflag |= WM_JOB_SUSPEND;
734         }
735
736         /* job custom data */
737         rj= MEM_callocN(sizeof(RenderJob), "render job");
738         rj->main= mainp;
739         rj->scene= scene;
740         rj->win= CTX_wm_window(C);
741         rj->srl = srl;
742         rj->lay = (v3d)? v3d->lay: scene->lay;
743         rj->anim= is_animation;
744         rj->write_still= is_write_still && !is_animation;
745         rj->iuser.scene= scene;
746         rj->iuser.ok= 1;
747         rj->reports= op->reports;
748
749         /* setup job */
750         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
751         WM_jobs_customdata(steve, rj, render_freejob);
752         WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
753         WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);
754
755         /* get a render result image, and make sure it is empty */
756         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
757         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
758         BKE_image_backup_render(rj->scene, ima);
759         rj->image= ima;
760
761         /* setup new render */
762         re= RE_NewRender(scene->id.name);
763         RE_test_break_cb(re, rj, render_breakjob);
764         RE_display_draw_cb(re, rj, image_rect_update);
765         RE_stats_draw_cb(re, rj, image_renderinfo_cb);
766         RE_progress_cb(re, rj, render_progress_update);
767
768         rj->re= re;
769         G.afbreek= 0;
770
771         RE_error_cb(re, op->reports, render_error_reports);
772
773         WM_jobs_start(CTX_wm_manager(C), steve);
774
775         WM_cursor_wait(0);
776         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
777
778         /* we set G.rendering here already instead of only in the job, this ensure
779            main loop or other scene updates are disabled in time, since they may
780            have started before the job thread */
781         G.rendering = 1;
782
783         /* add modal handler for ESC */
784         WM_event_add_modal_handler(C, op);
785
786         return OPERATOR_RUNNING_MODAL;
787 }
788
789
790 /* contextual render, using current scene, view3d? */
791 void RENDER_OT_render(wmOperatorType *ot)
792 {
793         /* identifiers */
794         ot->name= "Render";
795         ot->description= "Render active scene";
796         ot->idname= "RENDER_OT_render";
797
798         /* api callbacks */
799         ot->invoke= screen_render_invoke;
800         ot->modal= screen_render_modal;
801         ot->exec= screen_render_exec;
802
803         /*ot->poll= ED_operator_screenactive;*/ /* this isnt needed, causes failer in background mode */
804
805         RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
806         RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
807         RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
808         RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
809 }
810
811 /* ****************************** opengl render *************************** */
812
813
814 /* *********************** cancel render viewer *************** */
815
816 static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
817 {
818         wmWindow *win= CTX_wm_window(C);
819         ScrArea *sa= CTX_wm_area(C);
820         SpaceImage *sima= sa->spacedata.first;
821
822         /* test if we have a temp screen in front */
823         if(CTX_wm_window(C)->screen->temp) {
824                 wm_window_lower(CTX_wm_window(C));
825                 return OPERATOR_FINISHED;
826         }
827         /* determine if render already shows */
828         else if(sima->flag & SI_PREVSPACE) {
829                 sima->flag &= ~SI_PREVSPACE;
830
831                 if(sima->flag & SI_FULLWINDOW) {
832                         sima->flag &= ~SI_FULLWINDOW;
833                         ED_screen_full_prevspace(C, sa);
834                 }
835                 else
836                         ED_area_prevspace(C, sa);
837
838                 return OPERATOR_FINISHED;
839         }
840         else if(sima->flag & SI_FULLWINDOW) {
841                 sima->flag &= ~SI_FULLWINDOW;
842                 ED_screen_full_toggle(C, win, sa);
843                 return OPERATOR_FINISHED;
844         }
845
846         return OPERATOR_PASS_THROUGH;
847 }
848
849 void RENDER_OT_view_cancel(struct wmOperatorType *ot)
850 {
851         /* identifiers */
852         ot->name= "Cancel Render View";
853         ot->description= "Cancel show render view";
854         ot->idname= "RENDER_OT_view_cancel";
855
856         /* api callbacks */
857         ot->exec= render_view_cancel_exec;
858         ot->poll= ED_operator_image_active;
859 }
860
861 /* *********************** show render viewer *************** */
862
863 static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(unused), wmEvent *event)
864 {
865         ScrArea *sa= find_area_showing_r_result(C);
866
867         /* test if we have a temp screen active */
868         if(CTX_wm_window(C)->screen->temp) {
869                 wm_window_lower(CTX_wm_window(C));
870         }
871         else { 
872                 /* is there another window? */
873                 wmWindow *win;
874                 
875                 for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
876                         if(win->screen->temp) {
877                                 wm_window_raise(win);
878                                 return OPERATOR_FINISHED;
879                         }
880                 }
881                 
882                 /* determine if render already shows */
883                 if(sa) {
884                         /* but don't close it when rendering */
885                         if(!G.rendering) {
886                                 SpaceImage *sima= sa->spacedata.first;
887
888                                 if(sima->flag & SI_PREVSPACE) {
889                                         sima->flag &= ~SI_PREVSPACE;
890
891                                         if(sima->flag & SI_FULLWINDOW) {
892                                                 sima->flag &= ~SI_FULLWINDOW;
893                                                 ED_screen_full_prevspace(C, sa);
894                                         }
895                                         else if(sima->next) {
896                                                 /* workaround for case of double prevspace, render window
897                                                    with a file browser on top of it (same as in ED_area_prevspace) */
898                                                 if(sima->next->spacetype == SPACE_FILE && sima->next->next)
899                                                         ED_area_newspace(C, sa, sima->next->next->spacetype);
900                                                 else
901                                                         ED_area_newspace(C, sa, sima->next->spacetype);
902                                                 ED_area_tag_redraw(sa);
903                                         }
904                                 }
905                         }
906                 }
907                 else {
908                         screen_set_image_output(C, event->x, event->y);
909                 }
910         }
911
912         return OPERATOR_FINISHED;
913 }
914
915 void RENDER_OT_view_show(struct wmOperatorType *ot)
916 {
917         /* identifiers */
918         ot->name= "Show/Hide Render View";
919         ot->description= "Toggle show render view";
920         ot->idname= "RENDER_OT_view_show";
921
922         /* api callbacks */
923         ot->invoke= render_view_show_invoke;
924         ot->poll= ED_operator_screenactive;
925 }