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