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