~ubuntu-branches/ubuntu/trusty/blender/trusty-proposed

« back to all changes in this revision

Viewing changes to source/blender/editors/render/render_internal.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2013-08-14 10:43:49 UTC
  • mfrom: (14.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20130814104349-t1d5mtwkphp12dyj
Tags: 2.68a-3
* Upload to unstable
* debian/: python3.3 Depends simplified
  - debian/control: python3.3 Depends dropped
    for blender-data package
  - 0001-blender_thumbnailer.patch refreshed
* debian/control: libavcodec b-dep versioning dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include "BLI_blenlib.h"
37
37
#include "BLI_math.h"
38
38
#include "BLI_threads.h"
39
 
#include "BLI_rand.h"
40
39
#include "BLI_utildefines.h"
41
40
 
 
41
#include "PIL_time.h"
 
42
 
 
43
#include "BLF_translation.h"
 
44
 
 
45
#include "DNA_object_types.h"
42
46
#include "DNA_scene_types.h"
 
47
#include "DNA_view3d_types.h"
 
48
#include "DNA_userdef_types.h"
43
49
 
44
50
#include "BKE_blender.h"
45
51
#include "BKE_context.h"
 
52
#include "BKE_depsgraph.h"
 
53
#include "BKE_freestyle.h"
46
54
#include "BKE_global.h"
47
55
#include "BKE_image.h"
48
56
#include "BKE_library.h"
49
57
#include "BKE_main.h"
50
58
#include "BKE_node.h"
51
59
#include "BKE_multires.h"
 
60
#include "BKE_paint.h"
52
61
#include "BKE_report.h"
53
62
#include "BKE_sequencer.h"
54
63
#include "BKE_screen.h"
57
66
#include "WM_api.h"
58
67
#include "WM_types.h"
59
68
 
 
69
#include "ED_object.h"
 
70
#include "ED_render.h"
60
71
#include "ED_screen.h"
61
 
#include "ED_object.h"
 
72
#include "ED_view3d.h"
62
73
 
63
74
#include "RE_pipeline.h"
 
75
#include "RE_engine.h"
 
76
 
64
77
#include "IMB_colormanagement.h"
65
78
#include "IMB_imbuf.h"
66
79
#include "IMB_imbuf_types.h"
67
80
 
 
81
#include "GPU_extensions.h"
 
82
 
 
83
#include "BIF_gl.h"
 
84
#include "BIF_glutil.h"
 
85
 
68
86
#include "RNA_access.h"
69
87
#include "RNA_define.h"
70
88
 
141
159
 
142
160
        if (ibuf->rect == NULL)
143
161
                imb_addrectImBuf(ibuf);
144
 
        
 
162
 
145
163
        rectf += 4 * (rr->rectx * ymin + xmin);
146
164
 
147
165
        IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
248
266
        SceneRenderLayer *srl;
249
267
        struct Object *camera_override;
250
268
        int lay;
 
269
        bool v3d_override;
251
270
        short anim, write_still;
252
271
        Image *image;
253
272
        ImageUser iuser;
265
284
}
266
285
 
267
286
/* str is IMA_MAX_RENDER_TEXT in size */
268
 
static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
 
287
static void make_renderinfo_string(RenderStats *rs, Scene *scene, bool v3d_override, char *str)
269
288
{
270
289
        char info_time_str[32]; // used to be extern to header_info.c
271
290
        uintptr_t mem_in_use, mmap_in_use, peak_memory;
280
299
        mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
281
300
        megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
282
301
 
283
 
        if (scene->lay & 0xFF000000)
284
 
                spos += sprintf(spos, "Localview | ");
285
 
        else if (scene->r.scemode & R_SINGLE_LAYER)
286
 
                spos += sprintf(spos, "Single Layer | ");
287
 
 
288
 
        spos += sprintf(spos, "Frame:%d ", (scene->r.cfra));
289
 
 
 
302
        /* local view */
 
303
        if (rs->localview)
 
304
                spos += sprintf(spos, "%s | ", IFACE_("3D Local View"));
 
305
        else if (v3d_override)
 
306
                spos += sprintf(spos, "%s | ", IFACE_("3D View"));
 
307
 
 
308
        /* frame number */
 
309
        spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
 
310
 
 
311
        /* previous and elapsed time */
 
312
        BLI_timestr(rs->lastframetime, info_time_str, sizeof(info_time_str));
 
313
 
 
314
        if (rs->infostr && rs->infostr[0]) {
 
315
                if (rs->lastframetime != 0.0)
 
316
                        spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str);
 
317
                else
 
318
                        spos += sprintf(spos, "| ");
 
319
 
 
320
                BLI_timestr(PIL_check_seconds_timer() - rs->starttime, info_time_str, sizeof(info_time_str));
 
321
        }
 
322
        else
 
323
                spos += sprintf(spos, "| ");
 
324
 
 
325
        spos += sprintf(spos, IFACE_("Time:%s "), info_time_str);
 
326
 
 
327
        /* statistics */
290
328
        if (rs->statstr) {
291
 
                spos += sprintf(spos, "| %s ", rs->statstr);
 
329
                if (rs->statstr[0]) {
 
330
                        spos += sprintf(spos, "| %s ", rs->statstr);
 
331
                }
292
332
        }
293
333
        else {
294
 
                if (rs->totvert) spos += sprintf(spos, "Ve:%d ", rs->totvert);
295
 
                if (rs->totface) spos += sprintf(spos, "Fa:%d ", rs->totface);
296
 
                if (rs->tothalo) spos += sprintf(spos, "Ha:%d ", rs->tothalo);
297
 
                if (rs->totstrand) spos += sprintf(spos, "St:%d ", rs->totstrand);
298
 
                if (rs->totlamp) spos += sprintf(spos, "La:%d ", rs->totlamp);
 
334
                if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp)
 
335
                        spos += sprintf(spos, "| ");
 
336
 
 
337
                if (rs->totvert) spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert);
 
338
                if (rs->totface) spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface);
 
339
                if (rs->tothalo) spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo);
 
340
                if (rs->totstrand) spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand);
 
341
                if (rs->totlamp) spos += sprintf(spos, IFACE_("La:%d "), rs->totlamp);
299
342
 
300
343
                if (rs->mem_peak == 0.0f)
301
 
                        spos += sprintf(spos, "Mem:%.2fM (%.2fM, peak %.2fM) ", megs_used_memory, mmap_used_memory, megs_peak_memory);
 
344
                        spos += sprintf(spos, IFACE_("| Mem:%.2fM (%.2fM, Peak %.2fM) "),
 
345
                                        megs_used_memory, mmap_used_memory, megs_peak_memory);
302
346
                else
303
 
                        spos += sprintf(spos, "Mem:%.2fM, Peak: %.2fM ", rs->mem_used, rs->mem_peak);
 
347
                        spos += sprintf(spos, IFACE_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
304
348
 
305
349
                if (rs->curfield)
306
 
                        spos += sprintf(spos, "Field %d ", rs->curfield);
 
350
                        spos += sprintf(spos, IFACE_("Field %d "), rs->curfield);
307
351
                if (rs->curblur)
308
 
                        spos += sprintf(spos, "Blur %d ", rs->curblur);
 
352
                        spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur);
309
353
        }
310
354
 
311
 
        BLI_timestr(rs->lastframetime, info_time_str);
312
 
        spos += sprintf(spos, "Time:%s ", info_time_str);
313
 
 
 
355
        /* full sample */
314
356
        if (rs->curfsa)
315
 
                spos += sprintf(spos, "| Full Sample %d ", rs->curfsa);
 
357
                spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
316
358
        
 
359
        /* extra info */
317
360
        if (rs->infostr && rs->infostr[0])
318
361
                spos += sprintf(spos, "| %s ", rs->infostr);
319
362
 
336
379
                if (rr->text == NULL)
337
380
                        rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext");
338
381
 
339
 
                make_renderinfo_string(rs, rj->scene, rr->text);
 
382
                make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->text);
340
383
        }
341
384
 
342
385
        RE_ReleaseResult(rj->re);
409
452
                free_main(rj->main);
410
453
 
411
454
        /* else the frame will not update for the original value */
412
 
        if (!(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
 
455
        if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
413
456
                /* possible this fails of loading new file while rendering */
414
457
                if (G.main->wm.first) {
415
458
                        ED_update_for_newframe(G.main, rj->scene, 1);
426
469
                nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
427
470
                WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
428
471
        }
429
 
        
 
472
 
430
473
        /* XXX render stability hack */
431
474
        G.is_rendering = FALSE;
432
 
        WM_main_add_notifier(NC_WINDOW, NULL);
 
475
        WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);
 
476
 
 
477
        /* Partial render result will always update display buffer
 
478
         * for first render layer only. This is nice because you'll
 
479
         * see render progress during rendering, but it ends up in
 
480
         * wrong display buffer shown after rendering.
 
481
         *
 
482
         * The code below will mark display buffer as invalid after
 
483
         * rendering in case multiple layers were rendered, which
 
484
         * ensures display buffer matches render layer after
 
485
         * rendering.
 
486
         *
 
487
         * Perhaps proper way would be to toggle active render
 
488
         * layer in image editor and job, so we always display
 
489
         * layer being currently rendered. But this is not so much
 
490
         * trivial at this moment, especially because of external
 
491
         * engine API, so lets use simple and robust way for now
 
492
         *                                          - sergey -
 
493
         */
 
494
        if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
 
495
                void *lock;
 
496
                Image *ima = rj->image;
 
497
                ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
 
498
 
 
499
                if (ibuf)
 
500
                        ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
 
501
 
 
502
                BKE_image_release_ibuf(ima, ibuf, lock);
 
503
        }
433
504
}
434
505
 
435
506
/* called by render, check job 'stop' value or the global */
462
533
}
463
534
 
464
535
/* catch esc */
465
 
static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
 
536
static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
466
537
{
467
538
        Scene *scene = (Scene *) op->customdata;
468
539
 
481
552
}
482
553
 
483
554
/* using context, starts job */
484
 
static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
555
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
485
556
{
486
557
        /* new render clears all callbacks */
487
558
        Main *mainp;
497
568
        const short is_write_still = RNA_boolean_get(op->ptr, "write_still");
498
569
        struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
499
570
        const char *name;
 
571
        Object *active_object = CTX_data_active_object(C);
500
572
        
501
573
        /* only one render job at a time */
502
574
        if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
530
602
        WM_cursor_wait(1);
531
603
 
532
604
        /* flush multires changes (for sculpt) */
533
 
        multires_force_render_update(CTX_data_active_object(C));
 
605
        multires_force_render_update(active_object);
 
606
 
 
607
        /* flush changes from dynamic topology sculpt */
 
608
        sculptsession_bm_to_me_for_render(active_object);
534
609
 
535
610
        /* cleanup sequencer caches before starting user triggered render.
536
611
         * otherwise, invalidated cache entries can make their way into
539
614
        BKE_sequencer_cache_cleanup();
540
615
 
541
616
        /* get editmode results */
542
 
        ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
 
617
        ED_object_editmode_load(CTX_data_edit_object(C));
543
618
 
544
619
        // store spare
545
620
        // get view3d layer, local layer, make this nice api call to render
571
646
        rj->reports = op->reports;
572
647
 
573
648
        if (v3d) {
574
 
                rj->lay = v3d->lay;
 
649
                if (rj->lay != v3d->lay) {
 
650
                        rj->lay = v3d->lay;
 
651
                        rj->v3d_override = true;
 
652
                }
 
653
                else if (camera_override && camera_override != scene->camera)
 
654
                        rj->v3d_override = true;
575
655
 
576
656
                if (v3d->localvd)
577
657
                        rj->lay |= v3d->localvd->lay;
650
730
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
651
731
}
652
732
 
 
733
 
 
734
/* ************** preview for 3d viewport ***************** */
 
735
 
 
736
#define PR_UPDATE_VIEW                          1
 
737
#define PR_UPDATE_RENDERSIZE            2
 
738
#define PR_UPDATE_MATERIAL                      4
 
739
#define PR_UPDATE_DATABASE                      8
 
740
 
 
741
typedef struct RenderPreview {
 
742
        /* from wmJob */
 
743
        void *owner;
 
744
        short *stop, *do_update;
 
745
        wmJob *job;
 
746
        
 
747
        Scene *scene;
 
748
        ScrArea *sa;
 
749
        ARegion *ar;
 
750
        View3D *v3d;
 
751
        RegionView3D *rv3d;
 
752
        Main *bmain;
 
753
        RenderEngine *engine;
 
754
        
 
755
        float viewmat[4][4];
 
756
} RenderPreview;
 
757
 
 
758
static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect)
 
759
{
 
760
        /* copied code from view3d_draw.c */
 
761
        rctf viewborder;
 
762
        int draw_border;
 
763
        
 
764
        if (rv3d->persp == RV3D_CAMOB)
 
765
                draw_border = (scene->r.mode & R_BORDER) != 0;
 
766
        else
 
767
                draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
 
768
 
 
769
        if (draw_border) {
 
770
                if (rv3d->persp == RV3D_CAMOB) {
 
771
                        ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
 
772
                        
 
773
                        disprect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
 
774
                        disprect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
 
775
                        disprect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
 
776
                        disprect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
 
777
                }
 
778
                else {
 
779
                        disprect->xmin = v3d->render_border.xmin * ar->winx;
 
780
                        disprect->xmax = v3d->render_border.xmax * ar->winx;
 
781
                        disprect->ymin = v3d->render_border.ymin * ar->winy;
 
782
                        disprect->ymax = v3d->render_border.ymax * ar->winy;
 
783
                }
 
784
                
 
785
                return 1;
 
786
        }
 
787
        
 
788
        BLI_rcti_init(disprect, 0, 0, 0, 0);
 
789
        return 0;
 
790
}
 
791
 
 
792
/* returns true if OK  */
 
793
static bool render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d, rctf *viewplane, RenderEngine *engine,
 
794
                                    float *r_clipsta, float *r_clipend, float *r_pixsize, bool *r_ortho)
 
795
{
 
796
        
 
797
        if (ar->winx < 4 || ar->winy < 4) return false;
 
798
        
 
799
        *r_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, viewplane, r_clipsta, r_clipend, r_pixsize);
 
800
        
 
801
        engine->resolution_x = ar->winx;
 
802
        engine->resolution_y = ar->winy;
 
803
 
 
804
        return true;
 
805
}
 
806
 
 
807
/* called by renderer, checks job value */
 
808
static int render_view3d_break(void *rpv)
 
809
{
 
810
        RenderPreview *rp = rpv;
 
811
        
 
812
        if (G.is_break)
 
813
                return 1;
 
814
        
 
815
        /* during render, rv3d->engine can get freed */
 
816
        if (rp->rv3d->render_engine == NULL)
 
817
                *rp->stop = 1;
 
818
        
 
819
        return *(rp->stop);
 
820
}
 
821
 
 
822
static void render_view3d_draw_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
 
823
{
 
824
        RenderPreview *rp = rpv;
 
825
        
 
826
        *(rp->do_update) = TRUE;
 
827
}
 
828
 
 
829
static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs)
 
830
{
 
831
        RenderPreview *rp = rjp;
 
832
 
 
833
        /* during render, rv3d->engine can get freed */
 
834
        if (rp->rv3d->render_engine == NULL) {
 
835
                *rp->stop = 1;
 
836
        }
 
837
        else {
 
838
                make_renderinfo_string(rs, rp->scene, false, rp->engine->text);
 
839
        
 
840
                /* make jobs timer to send notifier */
 
841
                *(rp->do_update) = TRUE;
 
842
        }
 
843
}
 
844
 
 
845
 
 
846
static void render_view3d_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
 
847
{
 
848
        RenderPreview *rp = customdata;
 
849
        Render *re;
 
850
        RenderStats *rstats;
 
851
        RenderData rdata;
 
852
        rctf viewplane;
 
853
        rcti cliprct;
 
854
        float clipsta, clipend, pixsize;
 
855
        bool orth, restore = 0;
 
856
        char name[32];
 
857
        int update_flag;
 
858
 
 
859
        update_flag = rp->engine->job_update_flag;
 
860
        rp->engine->job_update_flag = 0;
 
861
 
 
862
        //printf("ma %d res %d view %d db %d\n", update_flag & PR_UPDATE_MATERIAL, update_flag & PR_UPDATE_RENDERSIZE, update_flag & PR_UPDATE_VIEW, update_flag & PR_UPDATE_DATABASE);
 
863
 
 
864
        G.is_break = FALSE;
 
865
        
 
866
        if (false == render_view3d_get_rects(rp->ar, rp->v3d, rp->rv3d, &viewplane, rp->engine, &clipsta, &clipend, &pixsize, &orth))
 
867
                return;
 
868
        
 
869
        rp->stop = stop;
 
870
        rp->do_update = do_update;
 
871
 
 
872
        // printf("Enter previewrender\n");
 
873
        
 
874
        /* ok, are we rendering all over? */
 
875
        sprintf(name, "View3dPreview %p", (void *)rp->ar);
 
876
        re = rp->engine->re = RE_GetRender(name);
 
877
        
 
878
        /* set this always, rp is different for each job */
 
879
        RE_test_break_cb(re, rp, render_view3d_break);
 
880
        RE_display_draw_cb(re, rp, render_view3d_draw_update);
 
881
        RE_stats_draw_cb(re, rp, render_view3d_renderinfo_cb);
 
882
        
 
883
        rstats = RE_GetStats(re);
 
884
 
 
885
        if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE)) || rstats->convertdone == 0) {
 
886
                /* no osa, blur, seq, layers, etc for preview render */
 
887
                rdata = rp->scene->r;
 
888
                rdata.mode &= ~(R_OSA | R_MBLUR | R_BORDER | R_PANORAMA);
 
889
                rdata.scemode &= ~(R_DOSEQ | R_DOCOMP | R_FREE_IMAGE);
 
890
                rdata.scemode |= R_VIEWPORT_PREVIEW;
 
891
                
 
892
                /* we do use layers, but only active */
 
893
                rdata.scemode |= R_SINGLE_LAYER;
 
894
 
 
895
                /* initalize always */
 
896
                if (render_view3d_disprect(rp->scene, rp->ar, rp->v3d, rp->rv3d, &cliprct)) {
 
897
                        rdata.mode |= R_BORDER;
 
898
                        RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, &cliprct);
 
899
                }
 
900
                else
 
901
                        RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, NULL);
 
902
        }
 
903
 
 
904
        if (orth)
 
905
                RE_SetOrtho(re, &viewplane, clipsta, clipend);
 
906
        else
 
907
                RE_SetWindow(re, &viewplane, clipsta, clipend);
 
908
 
 
909
        RE_SetPixelSize(re, pixsize);
 
910
        
 
911
        if ((update_flag & PR_UPDATE_DATABASE) || rstats->convertdone == 0) {
 
912
                unsigned int lay = rp->scene->lay;
 
913
 
 
914
                /* allow localview render for objects with lights in normal layers */
 
915
                if (rp->v3d->lay & 0xFF000000)
 
916
                        lay |= rp->v3d->lay;
 
917
                else lay = rp->v3d->lay;
 
918
                
 
919
                RE_SetView(re, rp->viewmat);
 
920
 
 
921
                /* copying blender data while main thread is locked, to avoid crashes */
 
922
                WM_job_main_thread_lock_acquire(rp->job);
 
923
                RE_Database_Free(re);
 
924
                RE_Database_FromScene(re, rp->bmain, rp->scene, lay, 0);                // 0= dont use camera view
 
925
                WM_job_main_thread_lock_release(rp->job);
 
926
 
 
927
                /* do preprocessing like building raytree, shadows, volumes, SSS */
 
928
                RE_Database_Preprocess(re);
 
929
 
 
930
                /* conversion not completed, need to do it again */
 
931
                if (!rstats->convertdone)
 
932
                        rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
 
933
 
 
934
                // printf("dbase update\n");
 
935
        }
 
936
        else {
 
937
                // printf("dbase rotate\n");
 
938
                RE_DataBase_IncrementalView(re, rp->viewmat, 0);
 
939
                restore = 1;
 
940
        }
 
941
 
 
942
        RE_DataBase_ApplyWindow(re);
 
943
 
 
944
        /* OK, can we enter render code? */
 
945
        if (rstats->convertdone) {
 
946
                RE_TileProcessor(re);
 
947
                
 
948
                /* always rotate back */
 
949
                if (restore)
 
950
                        RE_DataBase_IncrementalView(re, rp->viewmat, 1);
 
951
        }
 
952
}
 
953
 
 
954
static void render_view3d_free(void *customdata)
 
955
{
 
956
        RenderPreview *rp = customdata;
 
957
        
 
958
        MEM_freeN(rp);
 
959
}
 
960
 
 
961
static bool render_view3d_flag_changed(RenderEngine *engine, const bContext *C)
 
962
{
 
963
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 
964
        View3D *v3d = CTX_wm_view3d(C);
 
965
        ARegion *ar = CTX_wm_region(C);
 
966
        Scene *scene = CTX_data_scene(C);
 
967
        Render *re;
 
968
        rctf viewplane;
 
969
        rcti disprect;
 
970
        float clipsta, clipend;
 
971
        bool orth;
 
972
        int job_update_flag = 0;
 
973
        char name[32];
 
974
        
 
975
        /* ensure render engine exists */
 
976
        re = engine->re;
 
977
 
 
978
        if (!re) {
 
979
                sprintf(name, "View3dPreview %p", (void *)ar);
 
980
                re = engine->re = RE_GetRender(name);
 
981
                if (!re)
 
982
                        re = engine->re = RE_NewRender(name);
 
983
 
 
984
                engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
 
985
        }
 
986
 
 
987
        /* check update_flag */
 
988
        if (engine->update_flag & RE_ENGINE_UPDATE_MA)
 
989
                job_update_flag |= PR_UPDATE_MATERIAL;
 
990
        
 
991
        if (engine->update_flag & RE_ENGINE_UPDATE_OTHER)
 
992
                job_update_flag |= PR_UPDATE_MATERIAL;
 
993
        
 
994
        if (engine->update_flag & RE_ENGINE_UPDATE_DATABASE) {
 
995
                job_update_flag |= PR_UPDATE_DATABASE;
 
996
 
 
997
                /* load editmesh */
 
998
                if (scene->obedit)
 
999
                        ED_object_editmode_load(scene->obedit);
 
1000
        }
 
1001
        
 
1002
        engine->update_flag = 0;
 
1003
        
 
1004
        /* check if viewport changed */
 
1005
        if (engine->last_winx != ar->winx || engine->last_winy != ar->winy) {
 
1006
                engine->last_winx = ar->winx;
 
1007
                engine->last_winy = ar->winy;
 
1008
                job_update_flag |= PR_UPDATE_RENDERSIZE;
 
1009
        }
 
1010
 
 
1011
        if (compare_m4m4(engine->last_viewmat, rv3d->viewmat, 0.00001f) == 0) {
 
1012
                copy_m4_m4(engine->last_viewmat, rv3d->viewmat);
 
1013
                job_update_flag |= PR_UPDATE_VIEW;
 
1014
        }
 
1015
        
 
1016
        render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, NULL, &orth);
 
1017
        
 
1018
        if (BLI_rctf_compare(&viewplane, &engine->last_viewplane, 0.00001f) == 0) {
 
1019
                engine->last_viewplane = viewplane;
 
1020
                job_update_flag |= PR_UPDATE_VIEW;
 
1021
        }
 
1022
        
 
1023
        render_view3d_disprect(scene, ar, v3d, rv3d, &disprect);
 
1024
        if (BLI_rcti_compare(&disprect, &engine->last_disprect) == 0) {
 
1025
                engine->last_disprect = disprect;
 
1026
                job_update_flag |= PR_UPDATE_RENDERSIZE;
 
1027
        }
 
1028
 
 
1029
        /* any changes? go ahead and rerender */
 
1030
        if (job_update_flag) {
 
1031
                engine->job_update_flag |= job_update_flag;
 
1032
                return true;
 
1033
        }
 
1034
 
 
1035
        return false;
 
1036
}
 
1037
 
 
1038
static void render_view3d_do(RenderEngine *engine, const bContext *C)
 
1039
{
 
1040
        wmJob *wm_job;
 
1041
        RenderPreview *rp;
 
1042
        Scene *scene = CTX_data_scene(C);
 
1043
        
 
1044
        if (CTX_wm_window(C) == NULL)
 
1045
                return;
 
1046
        if (!render_view3d_flag_changed(engine, C))
 
1047
                return;
 
1048
 
 
1049
        wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_region(C), "Render Preview",
 
1050
                             WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
 
1051
        rp = MEM_callocN(sizeof(RenderPreview), "render preview");
 
1052
        rp->job = wm_job;
 
1053
 
 
1054
        /* customdata for preview thread */
 
1055
        rp->scene = scene;
 
1056
        rp->engine = engine;
 
1057
        rp->sa = CTX_wm_area(C);
 
1058
        rp->ar = CTX_wm_region(C);
 
1059
        rp->v3d = rp->sa->spacedata.first;
 
1060
        rp->rv3d = CTX_wm_region_view3d(C);
 
1061
        rp->bmain = CTX_data_main(C);
 
1062
        copy_m4_m4(rp->viewmat, rp->rv3d->viewmat);
 
1063
        
 
1064
        /* clear info text */
 
1065
        engine->text[0] = '\0';
 
1066
        
 
1067
        /* setup job */
 
1068
        WM_jobs_customdata_set(wm_job, rp, render_view3d_free);
 
1069
        WM_jobs_timer(wm_job, 0.1, NC_SPACE | ND_SPACE_VIEW3D, NC_SPACE | ND_SPACE_VIEW3D);
 
1070
        WM_jobs_callbacks(wm_job, render_view3d_startjob, NULL, NULL, NULL);
 
1071
        
 
1072
        WM_jobs_start(CTX_wm_manager(C), wm_job);
 
1073
        
 
1074
        engine->flag &= ~RE_ENGINE_DO_UPDATE;
 
1075
}
 
1076
 
 
1077
/* callback for render engine , on changes */
 
1078
void render_view3d_update(RenderEngine *engine, const bContext *C)
 
1079
{       
 
1080
        /* this shouldn't be needed and causes too many database rebuilds, but we
 
1081
         * aren't actually tracking updates for all relevent datablocks so this is
 
1082
         * a catch-all for updates */
 
1083
        engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
 
1084
 
 
1085
        render_view3d_do(engine, C);
 
1086
}
 
1087
 
 
1088
void render_view3d_draw(RenderEngine *engine, const bContext *C)
 
1089
{
 
1090
        Render *re = engine->re;
 
1091
        RenderResult rres;
 
1092
        char name[32];
 
1093
        
 
1094
        render_view3d_do(engine, C);
 
1095
        
 
1096
        if (re == NULL) {
 
1097
                sprintf(name, "View3dPreview %p", (void *)CTX_wm_region(C));
 
1098
                re = RE_GetRender(name);
 
1099
        
 
1100
                if (re == NULL) return;
 
1101
        }
 
1102
        
 
1103
        RE_AcquireResultImage(re, &rres);
 
1104
        
 
1105
        if (rres.rectf) {
 
1106
                Scene *scene = CTX_data_scene(C);
 
1107
                bool force_fallback = false;
 
1108
                bool need_fallback = true;
 
1109
                float dither = scene->r.dither_intensity;
 
1110
 
 
1111
                /* Dithering is not supported on GLSL yet */
 
1112
                force_fallback |= dither != 0.0f;
 
1113
 
 
1114
                /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
 
1115
                force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
 
1116
 
 
1117
                /* Try using GLSL display transform. */
 
1118
                if (force_fallback == false) {
 
1119
                        if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) {
 
1120
                                glEnable(GL_BLEND);
 
1121
                                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 
1122
                                glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
 
1123
                                                 GL_LINEAR, rres.rectf);
 
1124
                                glDisable(GL_BLEND);
 
1125
 
 
1126
                                IMB_colormanagement_finish_glsl_draw();
 
1127
                                need_fallback = false;
 
1128
                        }
 
1129
                }
 
1130
 
 
1131
                /* If GLSL failed, use old-school CPU-based transform. */
 
1132
                if (need_fallback) {
 
1133
                        unsigned char *display_buffer = MEM_mallocN(4 * rres.rectx * rres.recty * sizeof(char),
 
1134
                                                                    "render_view3d_draw");
 
1135
 
 
1136
                        IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty,
 
1137
                                                                      4, dither, NULL, &scene->display_settings);
 
1138
 
 
1139
                        glEnable(GL_BLEND);
 
1140
                        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 
1141
                        glaDrawPixelsAuto(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE,
 
1142
                                          GL_LINEAR, display_buffer);
 
1143
                        glDisable(GL_BLEND);
 
1144
 
 
1145
                        MEM_freeN(display_buffer);
 
1146
                }
 
1147
        }
 
1148
 
 
1149
        RE_ReleaseResultImage(re);
 
1150
}
 
1151
 
 
1152
void ED_viewport_render_kill_jobs(const bContext *C, bool free_database)
 
1153
{
 
1154
        wmWindowManager *wm = CTX_wm_manager(C);
 
1155
        Main *bmain = CTX_data_main(C);
 
1156
        bScreen *sc;
 
1157
        ScrArea *sa;
 
1158
        ARegion *ar;
 
1159
 
 
1160
        if (!wm)
 
1161
                return;
 
1162
 
 
1163
        /* kill all actively running jobs */
 
1164
        WM_jobs_kill(wm, NULL, render_view3d_startjob);
 
1165
 
 
1166
        /* loop over 3D view render engines */
 
1167
        for (sc = bmain->screen.first; sc; sc = sc->id.next) {
 
1168
                for (sa = sc->areabase.first; sa; sa = sa->next) {
 
1169
                        if (sa->spacetype != SPACE_VIEW3D)
 
1170
                                continue;
 
1171
                        
 
1172
                        for (ar = sa->regionbase.first; ar; ar = ar->next) {
 
1173
                                RegionView3D *rv3d;
 
1174
                                
 
1175
                                if (ar->regiontype != RGN_TYPE_WINDOW)
 
1176
                                        continue;
 
1177
                                
 
1178
                                rv3d = ar->regiondata;
 
1179
 
 
1180
                                if (rv3d->render_engine) {
 
1181
                                        /* free render database now before we change data, because
 
1182
                                         * RE_Database_Free will also loop over blender data */
 
1183
                                        if (free_database) {
 
1184
                                                char name[32];
 
1185
                                                Render *re;
 
1186
 
 
1187
                                                sprintf(name, "View3dPreview %p", (void *)ar);
 
1188
                                                re = RE_GetRender(name);
 
1189
 
 
1190
                                                if (re)
 
1191
                                                        RE_Database_Free(re);
 
1192
 
 
1193
                                                /* tag render engine to update entire database */
 
1194
                                                rv3d->render_engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
 
1195
                                        }
 
1196
                                        else {
 
1197
                                                /* quick shader update */
 
1198
                                                rv3d->render_engine->update_flag |= RE_ENGINE_UPDATE_MA;
 
1199
                                        }
 
1200
                                }
 
1201
                        }
 
1202
                }
 
1203
        }
 
1204
}
 
1205