Bugfix #26188
[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, wmWindow **win);
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, &win); 
236                 if(sa==NULL)
237                         sa= find_area_image_empty(C);
238                 
239                 /* if area found in other window, we make that one show in front */
240                 if(win && win!=CTX_wm_window(C))
241                         wm_window_raise(win);
242
243                 if(sa==NULL) {
244                         /* find largest open non-image area */
245                         sa= biggest_non_image_area(C);
246                         if(sa) {
247                                 ED_area_newspace(C, sa, SPACE_IMAGE);
248                                 sima= sa->spacedata.first;
249
250                                 /* makes ESC go back to prev space */
251                                 sima->flag |= SI_PREVSPACE;
252                         }
253                         else {
254                                 /* use any area of decent size */
255                                 sa= biggest_area(C);
256                                 if(sa->spacetype!=SPACE_IMAGE) {
257                                         // XXX newspace(sa, SPACE_IMAGE);
258                                         sima= sa->spacedata.first;
259
260                                         /* makes ESC go back to prev space */
261                                         sima->flag |= SI_PREVSPACE;
262                                 }
263                         }
264                 }
265         }
266         sima= sa->spacedata.first;
267
268         /* get the correct image, and scale it */
269         sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
270
271
272         /* if we're rendering to full screen, set appropriate hints on image editor
273          * so it can restore properly on pressing esc */
274         if(sa->full) {
275                 sima->flag |= SI_FULLWINDOW;
276
277                 /* Tell the image editor to revert to previous space in space list on close
278                  * _only_ if it wasn't already an image editor when the render was invoked */
279                 if (area_was_image == 0)
280                         sima->flag |= SI_PREVSPACE;
281                 else {
282                         /* Leave it alone so the image editor will just go back from
283                          * full screen to the original tiled setup */
284                         ;
285                 }
286
287         }
288
289 }
290
291
292 /* ****************************** render invoking ***************** */
293
294 /* set callbacks, exported to sequence render too.
295  Only call in foreground (UI) renders. */
296
297 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
298 /* window as the last possible alternative.                                                                        */
299 static ScrArea *biggest_non_image_area(bContext *C)
300 {
301         bScreen *sc= CTX_wm_screen(C);
302         ScrArea *sa, *big= NULL;
303         int size, maxsize= 0, bwmaxsize= 0;
304         short foundwin= 0;
305
306         for(sa= sc->areabase.first; sa; sa= sa->next) {
307                 if(sa->winx > 30 && sa->winy > 30) {
308                         size= sa->winx*sa->winy;
309                         if(sa->spacetype == SPACE_BUTS) {
310                                 if(foundwin == 0 && size > bwmaxsize) {
311                                         bwmaxsize= size;
312                                         big= sa;
313                                 }
314                         }
315                         else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
316                                 maxsize= size;
317                                 big= sa;
318                                 foundwin= 1;
319                         }
320                 }
321         }
322
323         return big;
324 }
325
326 static ScrArea *biggest_area(bContext *C)
327 {
328         bScreen *sc= CTX_wm_screen(C);
329         ScrArea *sa, *big= NULL;
330         int size, maxsize= 0;
331
332         for(sa= sc->areabase.first; sa; sa= sa->next) {
333                 size= sa->winx*sa->winy;
334                 if(size > maxsize) {
335                         maxsize= size;
336                         big= sa;
337                 }
338         }
339         return big;
340 }
341
342
343 static ScrArea *find_area_showing_r_result(bContext *C, wmWindow **win)
344 {
345         wmWindowManager *wm= CTX_wm_manager(C);
346         ScrArea *sa = NULL;
347         SpaceImage *sima;
348
349         /* find an imagewindow showing render result */
350         for(*win=wm->windows.first; *win; *win= (*win)->next) {
351                 for(sa= (*win)->screen->areabase.first; sa; sa= sa->next) {
352                         if(sa->spacetype==SPACE_IMAGE) {
353                                 sima= sa->spacedata.first;
354                                 if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
355                                         break;
356                         }
357                 }
358                 if(sa)
359                         break;
360         }
361         
362         return sa;
363 }
364
365 static ScrArea *find_area_image_empty(bContext *C)
366 {
367         bScreen *sc= CTX_wm_screen(C);
368         ScrArea *sa;
369         SpaceImage *sima;
370
371         /* find an imagewindow showing render result */
372         for(sa=sc->areabase.first; sa; sa= sa->next) {
373                 if(sa->spacetype==SPACE_IMAGE) {
374                         sima= sa->spacedata.first;
375                         if(!sima->image)
376                                 break;
377                 }
378         }
379         return sa;
380 }
381
382 #if 0 // XXX not used
383 static ScrArea *find_empty_image_area(bContext *C)
384 {
385         bScreen *sc= CTX_wm_screen(C);
386         ScrArea *sa;
387         SpaceImage *sima;
388
389         /* find an imagewindow showing render result */
390         for(sa=sc->areabase.first; sa; sa= sa->next) {
391                 if(sa->spacetype==SPACE_IMAGE) {
392                         sima= sa->spacedata.first;
393                         if(!sima->image)
394                                 break;
395                 }
396         }
397         return sa;
398 }
399 #endif // XXX not used
400
401 static void render_error_reports(void *reports, const char *str)
402 {
403         BKE_report(reports, RPT_ERROR, str);
404 }
405
406 /* executes blocking render */
407 static int screen_render_exec(bContext *C, wmOperator *op)
408 {
409         Scene *scene= CTX_data_scene(C);
410         Render *re= RE_NewRender(scene->id.name);
411         Image *ima;
412         View3D *v3d= CTX_wm_view3d(C);
413         Main *mainp= CTX_data_main(C);
414         unsigned int lay= (v3d)? v3d->lay: scene->lay;
415         const short is_animation= RNA_boolean_get(op->ptr, "animation");
416         const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
417
418         if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
419                 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
420                 return OPERATOR_CANCELLED;
421         }
422
423         if(re==NULL) {
424                 re= RE_NewRender(scene->id.name);
425         }
426         
427         G.afbreek= 0;
428         RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
429         RE_error_cb(re, op->reports, render_error_reports);
430
431         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
432         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
433         BKE_image_backup_render(scene, ima);
434
435         /* cleanup sequencer caches before starting user triggered render.
436            otherwise, invalidated cache entries can make their way into
437            the output rendering. We can't put that into RE_BlenderFrame,
438            since sequence rendering can call that recursively... (peter) */
439         seq_stripelem_cache_cleanup();
440
441         if(is_animation)
442                 RE_BlenderAnim(re, mainp, scene, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports);
443         else
444                 RE_BlenderFrame(re, mainp, scene, NULL, lay, scene->r.cfra, is_write_still);
445
446         // no redraw needed, we leave state as we entered it
447         ED_update_for_newframe(mainp, scene, CTX_wm_screen(C), 1);
448
449         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
450
451         return OPERATOR_FINISHED;
452 }
453
454 typedef struct RenderJob {
455         Main *main;
456         Scene *scene;
457         Render *re;
458         wmWindow *win;
459         SceneRenderLayer *srl;
460         int lay;
461         short anim, write_still;
462         Image *image;
463         ImageUser iuser;
464         short *stop;
465         short *do_update;
466         float *progress;
467         ReportList *reports;
468 } RenderJob;
469
470 static void render_freejob(void *rjv)
471 {
472         RenderJob *rj= rjv;
473
474         MEM_freeN(rj);
475 }
476
477 /* str is IMA_MAX_RENDER_TEXT in size */
478 static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
479 {
480         char info_time_str[32]; // used to be extern to header_info.c
481         uintptr_t mem_in_use, mmap_in_use, peak_memory;
482         float megs_used_memory, mmap_used_memory, megs_peak_memory;
483         char *spos= str;
484
485         mem_in_use= MEM_get_memory_in_use();
486         mmap_in_use= MEM_get_mapped_memory_in_use();
487         peak_memory = MEM_get_peak_memory();
488
489         megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
490         mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
491         megs_peak_memory = (peak_memory)/(1024.0*1024.0);
492
493         if(scene->lay & 0xFF000000)
494                 spos+= sprintf(spos, "Localview | ");
495         else if(scene->r.scemode & R_SINGLE_LAYER)
496                 spos+= sprintf(spos, "Single Layer | ");
497
498         if(rs->statstr) {
499                 spos+= sprintf(spos, "%s ", rs->statstr);
500         }
501         else {
502                 spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
503                 if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
504                 if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
505                 spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory, megs_peak_memory);
506
507                 if(rs->curfield)
508                         spos+= sprintf(spos, "Field %d ", rs->curfield);
509                 if(rs->curblur)
510                         spos+= sprintf(spos, "Blur %d ", rs->curblur);
511         }
512
513         BLI_timestr(rs->lastframetime, info_time_str);
514         spos+= sprintf(spos, "Time:%s ", info_time_str);
515
516         if(rs->infostr && rs->infostr[0])
517                 spos+= sprintf(spos, "| %s ", rs->infostr);
518
519         /* very weak... but 512 characters is quite safe */
520         if(spos >= str+IMA_MAX_RENDER_TEXT)
521                 if (G.f & G_DEBUG)
522                         printf("WARNING! renderwin text beyond limit \n");
523
524 }
525
526 static void image_renderinfo_cb(void *rjv, RenderStats *rs)
527 {
528         RenderJob *rj= rjv;
529         RenderResult *rr;
530
531         rr= RE_AcquireResultRead(rj->re);
532
533         if(rr) {
534                 /* malloc OK here, stats_draw is not in tile threads */
535                 if(rr->text==NULL)
536                         rr->text= MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
537
538                 make_renderinfo_string(rs, rj->scene, rr->text);
539         }
540
541         RE_ReleaseResult(rj->re);
542
543         /* make jobs timer to send notifier */
544         *(rj->do_update)= 1;
545
546 }
547
548 static void render_progress_update(void *rjv, float progress)
549 {
550         RenderJob *rj= rjv;
551         
552         if (rj->progress)
553                 *rj->progress = progress;
554 }
555
556 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
557 {
558         RenderJob *rj= rjv;
559         Image *ima= rj->image;
560         ImBuf *ibuf;
561         void *lock;
562
563         /* only update if we are displaying the slot being rendered */
564         if(ima->render_slot != ima->last_render_slot)
565                 return;
566
567         ibuf= BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
568         if(ibuf) {
569                 image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
570
571                 /* make jobs timer to send notifier */
572                 *(rj->do_update)= 1;
573         }
574         BKE_image_release_ibuf(ima, lock);
575 }
576
577 static void render_startjob(void *rjv, short *stop, short *do_update, float *progress)
578 {
579         RenderJob *rj= rjv;
580
581         rj->stop= stop;
582         rj->do_update= do_update;
583         rj->progress= progress;
584
585         if(rj->anim)
586                 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);
587         else
588                 RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->lay, rj->scene->r.cfra, rj->write_still);
589 }
590
591 static void render_endjob(void *rjv)
592 {
593         RenderJob *rj= rjv;     
594
595         /* this render may be used again by the sequencer without the active 'Render' where the callbacks
596          * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
597         RE_InitRenderCB(rj->re);
598
599         if(rj->main != G.main)
600                 free_main(rj->main);
601
602         /* else the frame will not update for the original value */
603         if(!(rj->scene->r.scemode & R_NO_FRAME_UPDATE))
604                 ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
605         
606         /* XXX above function sets all tags in nodes */
607         ntreeClearTags(rj->scene->nodetree);
608         
609         /* potentially set by caller */
610         rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
611         
612         if(rj->srl) {
613                 NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id);
614                 WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene);
615         }
616         
617         /* XXX render stability hack */
618         G.rendering = 0;
619         WM_main_add_notifier(NC_WINDOW, NULL);
620 }
621
622 /* called by render, check job 'stop' value or the global */
623 static int render_breakjob(void *rjv)
624 {
625         RenderJob *rj= rjv;
626
627         if(G.afbreek)
628                 return 1;
629         if(rj->stop && *(rj->stop))
630                 return 1;
631         return 0;
632 }
633
634 /* catch esc */
635 static int screen_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
636 {
637         /* no running blender, remove handler and pass through */
638         if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
639                 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
640         }
641
642         /* running render */
643         switch (event->type) {
644                 case ESCKEY:
645                         return OPERATOR_RUNNING_MODAL;
646                         break;
647         }
648         return OPERATOR_PASS_THROUGH;
649 }
650
651 /* using context, starts job */
652 static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
653 {
654         /* new render clears all callbacks */
655         Main *mainp;
656         Scene *scene= CTX_data_scene(C);
657         SceneRenderLayer *srl=NULL;
658         bScreen *screen= CTX_wm_screen(C);
659         View3D *v3d= CTX_wm_view3d(C);
660         Render *re;
661         wmJob *steve;
662         RenderJob *rj;
663         Image *ima;
664         int jobflag;
665         const short is_animation= RNA_boolean_get(op->ptr, "animation");
666         const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
667         
668         /* only one render job at a time */
669         if(WM_jobs_test(CTX_wm_manager(C), scene))
670                 return OPERATOR_CANCELLED;
671
672         if(!RE_is_rendering_allowed(scene, op->reports, render_error_reports)) {
673                 return OPERATOR_CANCELLED;
674         }
675
676         if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
677                 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
678                 return OPERATOR_CANCELLED;
679         }       
680         
681         /* stop all running jobs, currently previews frustrate Render */
682         WM_jobs_stop_all(CTX_wm_manager(C));
683
684         /* get main */
685         if(G.rt == 101) {
686                 /* thread-safety experiment, copy main from the undo buffer */
687                 mainp= BKE_undo_get_main(&scene);
688         }
689         else
690                 mainp= CTX_data_main(C);
691
692         /* cancel animation playback */
693         if (screen->animtimer)
694                 ED_screen_animation_play(C, 0, 0);
695         
696         /* handle UI stuff */
697         WM_cursor_wait(1);
698
699         /* flush multires changes (for sculpt) */
700         multires_force_render_update(CTX_data_active_object(C));
701
702         /* cleanup sequencer caches before starting user triggered render.
703            otherwise, invalidated cache entries can make their way into
704            the output rendering. We can't put that into RE_BlenderFrame,
705            since sequence rendering can call that recursively... (peter) */
706         seq_stripelem_cache_cleanup();
707
708         /* get editmode results */
709         ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
710
711         // store spare
712         // get view3d layer, local layer, make this nice api call to render
713         // store spare
714
715         /* ensure at least 1 area shows result */
716         screen_set_image_output(C, event->x, event->y);
717
718         jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
719         
720         /* single layer re-render */
721         if(RNA_property_is_set(op->ptr, "layer")) {
722                 SceneRenderLayer *rl;
723                 Scene *scn;
724                 char scene_name[19], rl_name[RE_MAXNAME];
725
726                 RNA_string_get(op->ptr, "layer", rl_name);
727                 RNA_string_get(op->ptr, "scene", scene_name);
728
729                 scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
730                 rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
731                 
732                 if (scn && rl) {
733                         scene = scn;
734                         srl = rl;
735                 }
736                 jobflag |= WM_JOB_SUSPEND;
737         }
738
739         /* job custom data */
740         rj= MEM_callocN(sizeof(RenderJob), "render job");
741         rj->main= mainp;
742         rj->scene= scene;
743         rj->win= CTX_wm_window(C);
744         rj->srl = srl;
745         rj->lay = (v3d)? v3d->lay: scene->lay;
746         rj->anim= is_animation;
747         rj->write_still= is_write_still && !is_animation;
748         rj->iuser.scene= scene;
749         rj->iuser.ok= 1;
750         rj->reports= op->reports;
751
752         /* setup job */
753         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
754         WM_jobs_customdata(steve, rj, render_freejob);
755         WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
756         WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);
757
758         /* get a render result image, and make sure it is empty */
759         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
760         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
761         BKE_image_backup_render(rj->scene, ima);
762         rj->image= ima;
763
764         /* setup new render */
765         re= RE_NewRender(scene->id.name);
766         RE_test_break_cb(re, rj, render_breakjob);
767         RE_display_draw_cb(re, rj, image_rect_update);
768         RE_stats_draw_cb(re, rj, image_renderinfo_cb);
769         RE_progress_cb(re, rj, render_progress_update);
770
771         rj->re= re;
772         G.afbreek= 0;
773
774         RE_error_cb(re, op->reports, render_error_reports);
775
776         WM_jobs_start(CTX_wm_manager(C), steve);
777
778         WM_cursor_wait(0);
779         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
780
781         /* we set G.rendering here already instead of only in the job, this ensure
782            main loop or other scene updates are disabled in time, since they may
783            have started before the job thread */
784         G.rendering = 1;
785
786         /* add modal handler for ESC */
787         WM_event_add_modal_handler(C, op);
788
789         return OPERATOR_RUNNING_MODAL;
790 }
791
792
793 /* contextual render, using current scene, view3d? */
794 void RENDER_OT_render(wmOperatorType *ot)
795 {
796         /* identifiers */
797         ot->name= "Render";
798         ot->description= "Render active scene";
799         ot->idname= "RENDER_OT_render";
800
801         /* api callbacks */
802         ot->invoke= screen_render_invoke;
803         ot->modal= screen_render_modal;
804         ot->exec= screen_render_exec;
805
806         /*ot->poll= ED_operator_screenactive;*/ /* this isnt needed, causes failer in background mode */
807
808         RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
809         RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
810         RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
811         RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
812 }
813
814 /* ****************************** opengl render *************************** */
815
816
817 /* *********************** cancel render viewer *************** */
818
819 static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
820 {
821         wmWindow *win= CTX_wm_window(C);
822         ScrArea *sa= CTX_wm_area(C);
823         SpaceImage *sima= sa->spacedata.first;
824
825         /* test if we have a temp screen in front */
826         if(CTX_wm_window(C)->screen->temp) {
827                 wm_window_lower(CTX_wm_window(C));
828                 return OPERATOR_FINISHED;
829         }
830         /* determine if render already shows */
831         else if(sima->flag & SI_PREVSPACE) {
832                 sima->flag &= ~SI_PREVSPACE;
833
834                 if(sima->flag & SI_FULLWINDOW) {
835                         sima->flag &= ~SI_FULLWINDOW;
836                         ED_screen_full_prevspace(C, sa);
837                 }
838                 else
839                         ED_area_prevspace(C, sa);
840
841                 return OPERATOR_FINISHED;
842         }
843         else if(sima->flag & SI_FULLWINDOW) {
844                 sima->flag &= ~SI_FULLWINDOW;
845                 ED_screen_full_toggle(C, win, sa);
846                 return OPERATOR_FINISHED;
847         }
848
849         return OPERATOR_PASS_THROUGH;
850 }
851
852 void RENDER_OT_view_cancel(struct wmOperatorType *ot)
853 {
854         /* identifiers */
855         ot->name= "Cancel Render View";
856         ot->description= "Cancel show render view";
857         ot->idname= "RENDER_OT_view_cancel";
858
859         /* api callbacks */
860         ot->exec= render_view_cancel_exec;
861         ot->poll= ED_operator_image_active;
862 }
863
864 /* *********************** show render viewer *************** */
865
866 static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(unused), wmEvent *event)
867 {
868         wmWindow *wincur = CTX_wm_window(C);
869         
870         /* test if we have currently a temp screen active */
871         if(wincur->screen->temp) {
872                 wm_window_lower(wincur);
873         }
874         else { 
875                 wmWindow *win, *winshow;
876                 ScrArea *sa= find_area_showing_r_result(C, &winshow);
877                 
878                 /* is there another window showing result? */
879                 for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
880                         if(win->screen->temp || (win==winshow && winshow!=wincur)) {
881                                 wm_window_raise(win);
882                                 return OPERATOR_FINISHED;
883                         }
884                 }
885                 
886                 /* determine if render already shows */
887                 if(sa) {
888                         /* but don't close it when rendering */
889                         if(!G.rendering) {
890                                 SpaceImage *sima= sa->spacedata.first;
891
892                                 if(sima->flag & SI_PREVSPACE) {
893                                         sima->flag &= ~SI_PREVSPACE;
894
895                                         if(sima->flag & SI_FULLWINDOW) {
896                                                 sima->flag &= ~SI_FULLWINDOW;
897                                                 ED_screen_full_prevspace(C, sa);
898                                         }
899                                         else if(sima->next) {
900                                                 /* workaround for case of double prevspace, render window
901                                                    with a file browser on top of it (same as in ED_area_prevspace) */
902                                                 if(sima->next->spacetype == SPACE_FILE && sima->next->next)
903                                                         ED_area_newspace(C, sa, sima->next->next->spacetype);
904                                                 else
905                                                         ED_area_newspace(C, sa, sima->next->spacetype);
906                                                 ED_area_tag_redraw(sa);
907                                         }
908                                 }
909                         }
910                 }
911                 else {
912                         screen_set_image_output(C, event->x, event->y);
913                 }
914         }
915
916         return OPERATOR_FINISHED;
917 }
918
919 void RENDER_OT_view_show(struct wmOperatorType *ot)
920 {
921         /* identifiers */
922         ot->name= "Show/Hide Render View";
923         ot->description= "Toggle show render view";
924         ot->idname= "RENDER_OT_view_show";
925
926         /* api callbacks */
927         ot->invoke= render_view_show_invoke;
928         ot->poll= ED_operator_screenactive;
929 }