Bugfix #20812 (and probably others)
[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
406         if(re==NULL) {
407                 re= RE_NewRender(scene->id.name);
408         }
409         
410         G.afbreek= 0;
411         RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
412         RE_error_cb(re, op->reports, render_error_reports);
413
414         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
415         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
416         BKE_image_backup_render(scene, ima);
417
418         /* cleanup sequencer caches before starting user triggered render.
419            otherwise, invalidated cache entries can make their way into
420            the output rendering. We can't put that into RE_BlenderFrame,
421            since sequence rendering can call that recursively... (peter) */
422         seq_stripelem_cache_cleanup();
423
424         if(RNA_boolean_get(op->ptr, "animation"))
425                 RE_BlenderAnim(re, mainp, scene, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports);
426         else
427                 RE_BlenderFrame(re, mainp, scene, NULL, lay, scene->r.cfra);
428
429         // no redraw needed, we leave state as we entered it
430         ED_update_for_newframe(mainp, scene, CTX_wm_screen(C), 1);
431
432         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
433
434         return OPERATOR_FINISHED;
435 }
436
437 typedef struct RenderJob {
438         Main *main;
439         Scene *scene;
440         Render *re;
441         wmWindow *win;
442         SceneRenderLayer *srl;
443         int lay;
444         int anim;
445         Image *image;
446         ImageUser iuser;
447         short *stop;
448         short *do_update;
449         float *progress;
450         ReportList *reports;
451 } RenderJob;
452
453 static void render_freejob(void *rjv)
454 {
455         RenderJob *rj= rjv;
456
457         MEM_freeN(rj);
458 }
459
460 /* str is IMA_MAX_RENDER_TEXT in size */
461 static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
462 {
463         char info_time_str[32]; // used to be extern to header_info.c
464         uintptr_t mem_in_use, mmap_in_use, peak_memory;
465         float megs_used_memory, mmap_used_memory, megs_peak_memory;
466         char *spos= str;
467
468         mem_in_use= MEM_get_memory_in_use();
469         mmap_in_use= MEM_get_mapped_memory_in_use();
470         peak_memory = MEM_get_peak_memory();
471
472         megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
473         mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
474         megs_peak_memory = (peak_memory)/(1024.0*1024.0);
475
476         if(scene->lay & 0xFF000000)
477                 spos+= sprintf(spos, "Localview | ");
478         else if(scene->r.scemode & R_SINGLE_LAYER)
479                 spos+= sprintf(spos, "Single Layer | ");
480
481         if(rs->statstr) {
482                 spos+= sprintf(spos, "%s ", rs->statstr);
483         }
484         else {
485                 spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
486                 if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
487                 if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
488                 spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory, megs_peak_memory);
489
490                 if(rs->curfield)
491                         spos+= sprintf(spos, "Field %d ", rs->curfield);
492                 if(rs->curblur)
493                         spos+= sprintf(spos, "Blur %d ", rs->curblur);
494         }
495
496         BLI_timestr(rs->lastframetime, info_time_str);
497         spos+= sprintf(spos, "Time:%s ", info_time_str);
498
499         if(rs->infostr && rs->infostr[0])
500                 spos+= sprintf(spos, "| %s ", rs->infostr);
501
502         /* very weak... but 512 characters is quite safe */
503         if(spos >= str+IMA_MAX_RENDER_TEXT)
504                 if (G.f & G_DEBUG)
505                         printf("WARNING! renderwin text beyond limit \n");
506
507 }
508
509 static void image_renderinfo_cb(void *rjv, RenderStats *rs)
510 {
511         RenderJob *rj= rjv;
512         RenderResult *rr;
513
514         rr= RE_AcquireResultRead(rj->re);
515
516         if(rr) {
517                 /* malloc OK here, stats_draw is not in tile threads */
518                 if(rr->text==NULL)
519                         rr->text= MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
520
521                 make_renderinfo_string(rs, rj->scene, rr->text);
522         }
523
524         RE_ReleaseResult(rj->re);
525
526         /* make jobs timer to send notifier */
527         *(rj->do_update)= 1;
528
529 }
530
531 static void render_progress_update(void *rjv, float progress)
532 {
533         RenderJob *rj= rjv;
534         
535         if (rj->progress)
536                 *rj->progress = progress;
537 }
538
539 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
540 {
541         RenderJob *rj= rjv;
542         Image *ima= rj->image;
543         ImBuf *ibuf;
544         void *lock;
545
546         /* only update if we are displaying the slot being rendered */
547         if(ima->render_slot != ima->last_render_slot)
548                 return;
549
550         ibuf= BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
551         if(ibuf) {
552                 image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
553
554                 /* make jobs timer to send notifier */
555                 *(rj->do_update)= 1;
556         }
557         BKE_image_release_ibuf(ima, lock);
558 }
559
560 static void render_startjob(void *rjv, short *stop, short *do_update, float *progress)
561 {
562         RenderJob *rj= rjv;
563
564         rj->stop= stop;
565         rj->do_update= do_update;
566         rj->progress= progress;
567
568         if(rj->anim)
569                 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);
570         else
571                 RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->lay, rj->scene->r.cfra);
572 }
573
574 static void render_endjob(void *rjv)
575 {
576         RenderJob *rj= rjv;     
577
578         /* this render may be used again by the sequencer without the active 'Render' where the callbacks
579          * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
580         RE_InitRenderCB(rj->re);
581
582         if(rj->main != G.main)
583                 free_main(rj->main);
584
585         /* else the frame will not update for the original value */
586         ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
587         
588         /* XXX render stability hack */
589         G.rendering = 0;
590         WM_main_add_notifier(NC_WINDOW, NULL);
591 }
592
593 /* called by render, check job 'stop' value or the global */
594 static int render_breakjob(void *rjv)
595 {
596         RenderJob *rj= rjv;
597
598         if(G.afbreek)
599                 return 1;
600         if(rj->stop && *(rj->stop))
601                 return 1;
602         return 0;
603 }
604
605 /* catch esc */
606 static int screen_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
607 {
608         /* no running blender, remove handler and pass through */
609         if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
610                 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
611         }
612
613         /* running render */
614         switch (event->type) {
615                 case ESCKEY:
616                         return OPERATOR_RUNNING_MODAL;
617                         break;
618         }
619         return OPERATOR_PASS_THROUGH;
620 }
621
622 /* using context, starts job */
623 static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
624 {
625         /* new render clears all callbacks */
626         Main *mainp;
627         Scene *scene= CTX_data_scene(C);
628         SceneRenderLayer *srl=NULL;
629         bScreen *screen= CTX_wm_screen(C);
630         View3D *v3d= CTX_wm_view3d(C);
631         Render *re;
632         wmJob *steve;
633         RenderJob *rj;
634         Image *ima;
635
636         /* only one render job at a time */
637         if(WM_jobs_test(CTX_wm_manager(C), scene))
638                 return OPERATOR_CANCELLED;
639
640         if(!RE_is_rendering_allowed(scene, op->reports, render_error_reports)) {
641                 return OPERATOR_CANCELLED;
642         }
643
644         /* stop all running jobs, currently previews frustrate Render */
645         WM_jobs_stop_all(CTX_wm_manager(C));
646
647         /* get main */
648         if(G.rt == 101) {
649                 /* thread-safety experiment, copy main from the undo buffer */
650                 mainp= BKE_undo_get_main(&scene);
651         }
652         else
653                 mainp= CTX_data_main(C);
654
655         /* cancel animation playback */
656         if (screen->animtimer)
657                 ED_screen_animation_play(C, 0, 0);
658         
659         /* handle UI stuff */
660         WM_cursor_wait(1);
661
662         /* flush multires changes (for sculpt) */
663         multires_force_render_update(CTX_data_active_object(C));
664
665         /* cleanup sequencer caches before starting user triggered render.
666            otherwise, invalidated cache entries can make their way into
667            the output rendering. We can't put that into RE_BlenderFrame,
668            since sequence rendering can call that recursively... (peter) */
669         seq_stripelem_cache_cleanup();
670
671         /* get editmode results */
672         ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
673
674         // store spare
675         // get view3d layer, local layer, make this nice api call to render
676         // store spare
677
678         /* ensure at least 1 area shows result */
679         screen_set_image_output(C, event->x, event->y);
680
681         /* single layer re-render */
682         if(RNA_property_is_set(op->ptr, "layer")) {
683                 SceneRenderLayer *rl;
684                 Scene *scn;
685                 char scene_name[19], rl_name[RE_MAXNAME];
686
687                 RNA_string_get(op->ptr, "layer", rl_name);
688                 RNA_string_get(op->ptr, "scene", scene_name);
689
690                 scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
691                 rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
692
693                 if (scn && rl) {
694                         scene = scn;
695                         srl = rl;
696                 }
697         }
698
699         /* job custom data */
700         rj= MEM_callocN(sizeof(RenderJob), "render job");
701         rj->main= mainp;
702         rj->scene= scene;
703         rj->win= CTX_wm_window(C);
704         rj->srl = srl;
705         rj->lay = (v3d)? v3d->lay: scene->lay;
706         rj->anim= RNA_boolean_get(op->ptr, "animation");
707         rj->iuser.scene= scene;
708         rj->iuser.ok= 1;
709         rj->reports= op->reports;
710
711         /* setup job */
712         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS);
713         WM_jobs_customdata(steve, rj, render_freejob);
714         WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
715         WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);
716
717         /* get a render result image, and make sure it is empty */
718         ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
719         BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
720         BKE_image_backup_render(rj->scene, ima);
721         rj->image= ima;
722
723         /* setup new render */
724         re= RE_NewRender(scene->id.name);
725         RE_test_break_cb(re, rj, render_breakjob);
726         RE_display_draw_cb(re, rj, image_rect_update);
727         RE_stats_draw_cb(re, rj, image_renderinfo_cb);
728         RE_progress_cb(re, rj, render_progress_update);
729
730         rj->re= re;
731         G.afbreek= 0;
732
733         RE_error_cb(re, op->reports, render_error_reports);
734
735         WM_jobs_start(CTX_wm_manager(C), steve);
736
737         WM_cursor_wait(0);
738         WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
739
740         /* we set G.rendering here already instead of only in the job, this ensure
741            main loop or other scene updates are disabled in time, since they may
742            have started before the job thread */
743         G.rendering = 1;
744
745         /* add modal handler for ESC */
746         WM_event_add_modal_handler(C, op);
747
748         return OPERATOR_RUNNING_MODAL;
749 }
750
751
752 /* contextual render, using current scene, view3d? */
753 void RENDER_OT_render(wmOperatorType *ot)
754 {
755         /* identifiers */
756         ot->name= "Render";
757         ot->description= "Render active scene";
758         ot->idname= "RENDER_OT_render";
759
760         /* api callbacks */
761         ot->invoke= screen_render_invoke;
762         ot->modal= screen_render_modal;
763         ot->exec= screen_render_exec;
764
765         ot->poll= ED_operator_screenactive;
766
767         RNA_def_boolean(ot->srna, "animation", 0, "Animation", "");
768         RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
769         RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
770 }
771
772 /* ****************************** opengl render *************************** */
773
774
775 /* *********************** cancel render viewer *************** */
776
777 static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
778 {
779         wmWindow *win= CTX_wm_window(C);
780         ScrArea *sa= CTX_wm_area(C);
781         SpaceImage *sima= sa->spacedata.first;
782
783         /* test if we have a temp screen in front */
784         if(CTX_wm_window(C)->screen->temp) {
785                 wm_window_lower(CTX_wm_window(C));
786                 return OPERATOR_FINISHED;
787         }
788         /* determine if render already shows */
789         else if(sima->flag & SI_PREVSPACE) {
790                 sima->flag &= ~SI_PREVSPACE;
791
792                 if(sima->flag & SI_FULLWINDOW) {
793                         sima->flag &= ~SI_FULLWINDOW;
794                         ED_screen_full_prevspace(C, sa);
795                 }
796                 else
797                         ED_area_prevspace(C, sa);
798
799                 return OPERATOR_FINISHED;
800         }
801         else if(sima->flag & SI_FULLWINDOW) {
802                 sima->flag &= ~SI_FULLWINDOW;
803                 ED_screen_full_toggle(C, win, sa);
804                 return OPERATOR_FINISHED;
805         }
806
807         return OPERATOR_PASS_THROUGH;
808 }
809
810 void RENDER_OT_view_cancel(struct wmOperatorType *ot)
811 {
812         /* identifiers */
813         ot->name= "Cancel Render View";
814         ot->description= "Cancel show render view";
815         ot->idname= "RENDER_OT_view_cancel";
816
817         /* api callbacks */
818         ot->exec= render_view_cancel_exec;
819         ot->poll= ED_operator_image_active;
820 }
821
822 /* *********************** show render viewer *************** */
823
824 static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(unused), wmEvent *event)
825 {
826         ScrArea *sa= find_area_showing_r_result(C);
827
828         /* test if we have a temp screen in front */
829         if(CTX_wm_window(C)->screen->temp) {
830                 wm_window_lower(CTX_wm_window(C));
831         }
832         /* determine if render already shows */
833         else if(sa) {
834                 SpaceImage *sima= sa->spacedata.first;
835
836                 if(sima->flag & SI_PREVSPACE) {
837                         sima->flag &= ~SI_PREVSPACE;
838
839                         if(sima->flag & SI_FULLWINDOW) {
840                                 sima->flag &= ~SI_FULLWINDOW;
841                                 ED_screen_full_prevspace(C, sa);
842                         }
843                         else if(sima->next) {
844                                 /* workaround for case of double prevspace, render window
845                                    with a file browser on top of it (same as in ED_area_prevspace) */
846                                 if(sima->next->spacetype == SPACE_FILE && sima->next->next)
847                                         ED_area_newspace(C, sa, sima->next->next->spacetype);
848                                 else
849                                         ED_area_newspace(C, sa, sima->next->spacetype);
850                                 ED_area_tag_redraw(sa);
851                         }
852                 }
853         }
854         else {
855                 screen_set_image_output(C, event->x, event->y);
856         }
857
858         return OPERATOR_FINISHED;
859 }
860
861 void RENDER_OT_view_show(struct wmOperatorType *ot)
862 {
863         /* identifiers */
864         ot->name= "Show/Hide Render View";
865         ot->description= "Toggle show render view";
866         ot->idname= "RENDER_OT_view_show";
867
868         /* api callbacks */
869         ot->invoke= render_view_show_invoke;
870         ot->poll= ED_operator_screenactive;
871 }