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