split BKE_utildefines.h, now it only has blender specific defines like GS() MAKE_ID...
[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         ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
598         
599         if(rj->srl) {
600                 NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id);
601                 WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene);
602         }
603         
604         /* XXX render stability hack */
605         G.rendering = 0;
606         WM_main_add_notifier(NC_WINDOW, NULL);
607 }
608
609 /* called by render, check job 'stop' value or the global */
610 static int render_breakjob(void *rjv)
611 {
612         RenderJob *rj= rjv;
613
614         if(G.afbreek)
615                 return 1;
616         if(rj->stop && *(rj->stop))
617                 return 1;
618         return 0;
619 }
620
621 /* catch esc */
622 static int screen_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
623 {
624         /* no running blender, remove handler and pass through */
625         if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
626                 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
627         }
628
629         /* running render */
630         switch (event->type) {
631                 case ESCKEY:
632                         return OPERATOR_RUNNING_MODAL;
633                         break;
634         }
635         return OPERATOR_PASS_THROUGH;
636 }
637
638 /* using context, starts job */
639 static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
640 {
641         /* new render clears all callbacks */
642         Main *mainp;
643         Scene *scene= CTX_data_scene(C);
644         SceneRenderLayer *srl=NULL;
645         bScreen *screen= CTX_wm_screen(C);
646         View3D *v3d= CTX_wm_view3d(C);
647         Render *re;
648         wmJob *steve;
649         RenderJob *rj;
650         Image *ima;
651         const short is_animation= RNA_boolean_get(op->ptr, "animation");
652         const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
653         
654         /* only one render job at a time */
655         if(WM_jobs_test(CTX_wm_manager(C), scene))
656                 return OPERATOR_CANCELLED;
657
658         if(!RE_is_rendering_allowed(scene, op->reports, render_error_reports)) {
659                 return OPERATOR_CANCELLED;
660         }
661
662         if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
663                 BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
664                 return OPERATOR_CANCELLED;
665         }       
666         
667         /* stop all running jobs, currently previews frustrate Render */
668         WM_jobs_stop_all(CTX_wm_manager(C));
669
670         /* get main */
671         if(G.rt == 101) {
672                 /* thread-safety experiment, copy main from the undo buffer */
673                 mainp= BKE_undo_get_main(&scene);
674         }
675         else
676                 mainp= CTX_data_main(C);
677
678         /* cancel animation playback */
679         if (screen->animtimer)
680                 ED_screen_animation_play(C, 0, 0);
681         
682         /* handle UI stuff */
683         WM_cursor_wait(1);
684
685         /* flush multires changes (for sculpt) */
686         multires_force_render_update(CTX_data_active_object(C));
687
688         /* cleanup sequencer caches before starting user triggered render.
689            otherwise, invalidated cache entries can make their way into
690            the output rendering. We can't put that into RE_BlenderFrame,
691            since sequence rendering can call that recursively... (peter) */
692         seq_stripelem_cache_cleanup();
693
694         /* get editmode results */
695         ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
696
697         // store spare
698         // get view3d layer, local layer, make this nice api call to render
699         // store spare
700
701         /* ensure at least 1 area shows result */
702         screen_set_image_output(C, event->x, event->y);
703
704         /* single layer re-render */
705         if(RNA_property_is_set(op->ptr, "layer")) {
706                 SceneRenderLayer *rl;
707                 Scene *scn;
708                 char scene_name[19], rl_name[RE_MAXNAME];
709
710                 RNA_string_get(op->ptr, "layer", rl_name);
711                 RNA_string_get(op->ptr, "scene", scene_name);
712
713                 scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
714                 rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
715
716                 if (scn && rl) {
717                         scene = scn;
718                         srl = rl;
719                 }
720         }
721
722         /* job custom data */
723         rj= MEM_callocN(sizeof(RenderJob), "render job");
724         rj->main= mainp;
725         rj->scene= scene;
726         rj->win= CTX_wm_window(C);
727         rj->srl = srl;
728         rj->lay = (v3d)? v3d->lay: scene->lay;
729         rj->anim= is_animation;
730         rj->write_still= is_write_still && !is_animation;
731         rj->iuser.scene= scene;
732         rj->iuser.ok= 1;
733         rj->reports= op->reports;
734
735         /* setup job */
736         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS);
737         WM_jobs_customdata(steve, rj, render_freejob);
738         WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
739         WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);
740
741         /* get a render result image, and make sure it is empty */
742         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
743         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
744         BKE_image_backup_render(rj->scene, ima);
745         rj->image= ima;
746
747         /* setup new render */
748         re= RE_NewRender(scene->id.name);
749         RE_test_break_cb(re, rj, render_breakjob);
750         RE_display_draw_cb(re, rj, image_rect_update);
751         RE_stats_draw_cb(re, rj, image_renderinfo_cb);
752         RE_progress_cb(re, rj, render_progress_update);
753
754         rj->re= re;
755         G.afbreek= 0;
756
757         RE_error_cb(re, op->reports, render_error_reports);
758
759         WM_jobs_start(CTX_wm_manager(C), steve);
760
761         WM_cursor_wait(0);
762         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
763
764         /* we set G.rendering here already instead of only in the job, this ensure
765            main loop or other scene updates are disabled in time, since they may
766            have started before the job thread */
767         G.rendering = 1;
768
769         /* add modal handler for ESC */
770         WM_event_add_modal_handler(C, op);
771
772         return OPERATOR_RUNNING_MODAL;
773 }
774
775
776 /* contextual render, using current scene, view3d? */
777 void RENDER_OT_render(wmOperatorType *ot)
778 {
779         /* identifiers */
780         ot->name= "Render";
781         ot->description= "Render active scene";
782         ot->idname= "RENDER_OT_render";
783
784         /* api callbacks */
785         ot->invoke= screen_render_invoke;
786         ot->modal= screen_render_modal;
787         ot->exec= screen_render_exec;
788
789         ot->poll= ED_operator_screenactive;
790
791         RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
792         RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
793         RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
794         RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
795 }
796
797 /* ****************************** opengl render *************************** */
798
799
800 /* *********************** cancel render viewer *************** */
801
802 static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
803 {
804         wmWindow *win= CTX_wm_window(C);
805         ScrArea *sa= CTX_wm_area(C);
806         SpaceImage *sima= sa->spacedata.first;
807
808         /* test if we have a temp screen in front */
809         if(CTX_wm_window(C)->screen->temp) {
810                 wm_window_lower(CTX_wm_window(C));
811                 return OPERATOR_FINISHED;
812         }
813         /* determine if render already shows */
814         else if(sima->flag & SI_PREVSPACE) {
815                 sima->flag &= ~SI_PREVSPACE;
816
817                 if(sima->flag & SI_FULLWINDOW) {
818                         sima->flag &= ~SI_FULLWINDOW;
819                         ED_screen_full_prevspace(C, sa);
820                 }
821                 else
822                         ED_area_prevspace(C, sa);
823
824                 return OPERATOR_FINISHED;
825         }
826         else if(sima->flag & SI_FULLWINDOW) {
827                 sima->flag &= ~SI_FULLWINDOW;
828                 ED_screen_full_toggle(C, win, sa);
829                 return OPERATOR_FINISHED;
830         }
831
832         return OPERATOR_PASS_THROUGH;
833 }
834
835 void RENDER_OT_view_cancel(struct wmOperatorType *ot)
836 {
837         /* identifiers */
838         ot->name= "Cancel Render View";
839         ot->description= "Cancel show render view";
840         ot->idname= "RENDER_OT_view_cancel";
841
842         /* api callbacks */
843         ot->exec= render_view_cancel_exec;
844         ot->poll= ED_operator_image_active;
845 }
846
847 /* *********************** show render viewer *************** */
848
849 static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(unused), wmEvent *event)
850 {
851         ScrArea *sa= find_area_showing_r_result(C);
852
853         /* test if we have a temp screen active */
854         if(CTX_wm_window(C)->screen->temp) {
855                 wm_window_lower(CTX_wm_window(C));
856         }
857         else { 
858                 /* is there another window? */
859                 wmWindow *win;
860                 
861                 for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) {
862                         if(win->screen->temp) {
863                                 wm_window_raise(win);
864                                 return OPERATOR_FINISHED;
865                         }
866                 }
867                 
868                 /* determine if render already shows */
869                 if(sa) {
870                         /* but don't close it when rendering */
871                         if(!G.rendering) {
872                                 SpaceImage *sima= sa->spacedata.first;
873
874                                 if(sima->flag & SI_PREVSPACE) {
875                                         sima->flag &= ~SI_PREVSPACE;
876
877                                         if(sima->flag & SI_FULLWINDOW) {
878                                                 sima->flag &= ~SI_FULLWINDOW;
879                                                 ED_screen_full_prevspace(C, sa);
880                                         }
881                                         else if(sima->next) {
882                                                 /* workaround for case of double prevspace, render window
883                                                    with a file browser on top of it (same as in ED_area_prevspace) */
884                                                 if(sima->next->spacetype == SPACE_FILE && sima->next->next)
885                                                         ED_area_newspace(C, sa, sima->next->next->spacetype);
886                                                 else
887                                                         ED_area_newspace(C, sa, sima->next->spacetype);
888                                                 ED_area_tag_redraw(sa);
889                                         }
890                                 }
891                         }
892                 }
893                 else {
894                         screen_set_image_output(C, event->x, event->y);
895                 }
896         }
897
898         return OPERATOR_FINISHED;
899 }
900
901 void RENDER_OT_view_show(struct wmOperatorType *ot)
902 {
903         /* identifiers */
904         ot->name= "Show/Hide Render View";
905         ot->description= "Toggle show render view";
906         ot->idname= "RENDER_OT_view_show";
907
908         /* api callbacks */
909         ot->invoke= render_view_show_invoke;
910         ot->poll= ED_operator_screenactive;
911 }