280
299
mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
281
300
megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
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 | ");
288
spos += sprintf(spos, "Frame:%d ", (scene->r.cfra));
304
spos += sprintf(spos, "%s | ", IFACE_("3D Local View"));
305
else if (v3d_override)
306
spos += sprintf(spos, "%s | ", IFACE_("3D View"));
309
spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
311
/* previous and elapsed time */
312
BLI_timestr(rs->lastframetime, info_time_str, sizeof(info_time_str));
314
if (rs->infostr && rs->infostr[0]) {
315
if (rs->lastframetime != 0.0)
316
spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str);
318
spos += sprintf(spos, "| ");
320
BLI_timestr(PIL_check_seconds_timer() - rs->starttime, info_time_str, sizeof(info_time_str));
323
spos += sprintf(spos, "| ");
325
spos += sprintf(spos, IFACE_("Time:%s "), info_time_str);
290
328
if (rs->statstr) {
291
spos += sprintf(spos, "| %s ", rs->statstr);
329
if (rs->statstr[0]) {
330
spos += sprintf(spos, "| %s ", rs->statstr);
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, "| ");
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);
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);
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);
305
349
if (rs->curfield)
306
spos += sprintf(spos, "Field %d ", rs->curfield);
350
spos += sprintf(spos, IFACE_("Field %d "), rs->curfield);
308
spos += sprintf(spos, "Blur %d ", rs->curblur);
352
spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur);
311
BLI_timestr(rs->lastframetime, info_time_str);
312
spos += sprintf(spos, "Time:%s ", info_time_str);
315
spos += sprintf(spos, "| Full Sample %d ", rs->curfsa);
357
spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
317
360
if (rs->infostr && rs->infostr[0])
318
361
spos += sprintf(spos, "| %s ", rs->infostr);
650
730
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
734
/* ************** preview for 3d viewport ***************** */
736
#define PR_UPDATE_VIEW 1
737
#define PR_UPDATE_RENDERSIZE 2
738
#define PR_UPDATE_MATERIAL 4
739
#define PR_UPDATE_DATABASE 8
741
typedef struct RenderPreview {
744
short *stop, *do_update;
753
RenderEngine *engine;
758
static int render_view3d_disprect(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, rcti *disprect)
760
/* copied code from view3d_draw.c */
764
if (rv3d->persp == RV3D_CAMOB)
765
draw_border = (scene->r.mode & R_BORDER) != 0;
767
draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
770
if (rv3d->persp == RV3D_CAMOB) {
771
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
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);
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;
788
BLI_rcti_init(disprect, 0, 0, 0, 0);
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)
797
if (ar->winx < 4 || ar->winy < 4) return false;
799
*r_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, viewplane, r_clipsta, r_clipend, r_pixsize);
801
engine->resolution_x = ar->winx;
802
engine->resolution_y = ar->winy;
807
/* called by renderer, checks job value */
808
static int render_view3d_break(void *rpv)
810
RenderPreview *rp = rpv;
815
/* during render, rv3d->engine can get freed */
816
if (rp->rv3d->render_engine == NULL)
822
static void render_view3d_draw_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
824
RenderPreview *rp = rpv;
826
*(rp->do_update) = TRUE;
829
static void render_view3d_renderinfo_cb(void *rjp, RenderStats *rs)
831
RenderPreview *rp = rjp;
833
/* during render, rv3d->engine can get freed */
834
if (rp->rv3d->render_engine == NULL) {
838
make_renderinfo_string(rs, rp->scene, false, rp->engine->text);
840
/* make jobs timer to send notifier */
841
*(rp->do_update) = TRUE;
846
static void render_view3d_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress))
848
RenderPreview *rp = customdata;
854
float clipsta, clipend, pixsize;
855
bool orth, restore = 0;
859
update_flag = rp->engine->job_update_flag;
860
rp->engine->job_update_flag = 0;
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);
866
if (false == render_view3d_get_rects(rp->ar, rp->v3d, rp->rv3d, &viewplane, rp->engine, &clipsta, &clipend, &pixsize, &orth))
870
rp->do_update = do_update;
872
// printf("Enter previewrender\n");
874
/* ok, are we rendering all over? */
875
sprintf(name, "View3dPreview %p", (void *)rp->ar);
876
re = rp->engine->re = RE_GetRender(name);
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);
883
rstats = RE_GetStats(re);
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;
892
/* we do use layers, but only active */
893
rdata.scemode |= R_SINGLE_LAYER;
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);
901
RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, NULL);
905
RE_SetOrtho(re, &viewplane, clipsta, clipend);
907
RE_SetWindow(re, &viewplane, clipsta, clipend);
909
RE_SetPixelSize(re, pixsize);
911
if ((update_flag & PR_UPDATE_DATABASE) || rstats->convertdone == 0) {
912
unsigned int lay = rp->scene->lay;
914
/* allow localview render for objects with lights in normal layers */
915
if (rp->v3d->lay & 0xFF000000)
917
else lay = rp->v3d->lay;
919
RE_SetView(re, rp->viewmat);
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);
927
/* do preprocessing like building raytree, shadows, volumes, SSS */
928
RE_Database_Preprocess(re);
930
/* conversion not completed, need to do it again */
931
if (!rstats->convertdone)
932
rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
934
// printf("dbase update\n");
937
// printf("dbase rotate\n");
938
RE_DataBase_IncrementalView(re, rp->viewmat, 0);
942
RE_DataBase_ApplyWindow(re);
944
/* OK, can we enter render code? */
945
if (rstats->convertdone) {
946
RE_TileProcessor(re);
948
/* always rotate back */
950
RE_DataBase_IncrementalView(re, rp->viewmat, 1);
954
static void render_view3d_free(void *customdata)
956
RenderPreview *rp = customdata;
961
static bool render_view3d_flag_changed(RenderEngine *engine, const bContext *C)
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);
970
float clipsta, clipend;
972
int job_update_flag = 0;
975
/* ensure render engine exists */
979
sprintf(name, "View3dPreview %p", (void *)ar);
980
re = engine->re = RE_GetRender(name);
982
re = engine->re = RE_NewRender(name);
984
engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
987
/* check update_flag */
988
if (engine->update_flag & RE_ENGINE_UPDATE_MA)
989
job_update_flag |= PR_UPDATE_MATERIAL;
991
if (engine->update_flag & RE_ENGINE_UPDATE_OTHER)
992
job_update_flag |= PR_UPDATE_MATERIAL;
994
if (engine->update_flag & RE_ENGINE_UPDATE_DATABASE) {
995
job_update_flag |= PR_UPDATE_DATABASE;
999
ED_object_editmode_load(scene->obedit);
1002
engine->update_flag = 0;
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;
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;
1016
render_view3d_get_rects(ar, v3d, rv3d, &viewplane, engine, &clipsta, &clipend, NULL, &orth);
1018
if (BLI_rctf_compare(&viewplane, &engine->last_viewplane, 0.00001f) == 0) {
1019
engine->last_viewplane = viewplane;
1020
job_update_flag |= PR_UPDATE_VIEW;
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;
1029
/* any changes? go ahead and rerender */
1030
if (job_update_flag) {
1031
engine->job_update_flag |= job_update_flag;
1038
static void render_view3d_do(RenderEngine *engine, const bContext *C)
1042
Scene *scene = CTX_data_scene(C);
1044
if (CTX_wm_window(C) == NULL)
1046
if (!render_view3d_flag_changed(engine, C))
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");
1054
/* customdata for preview thread */
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);
1064
/* clear info text */
1065
engine->text[0] = '\0';
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);
1072
WM_jobs_start(CTX_wm_manager(C), wm_job);
1074
engine->flag &= ~RE_ENGINE_DO_UPDATE;
1077
/* callback for render engine , on changes */
1078
void render_view3d_update(RenderEngine *engine, const bContext *C)
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;
1085
render_view3d_do(engine, C);
1088
void render_view3d_draw(RenderEngine *engine, const bContext *C)
1090
Render *re = engine->re;
1094
render_view3d_do(engine, C);
1097
sprintf(name, "View3dPreview %p", (void *)CTX_wm_region(C));
1098
re = RE_GetRender(name);
1100
if (re == NULL) return;
1103
RE_AcquireResultImage(re, &rres);
1106
Scene *scene = CTX_data_scene(C);
1107
bool force_fallback = false;
1108
bool need_fallback = true;
1109
float dither = scene->r.dither_intensity;
1111
/* Dithering is not supported on GLSL yet */
1112
force_fallback |= dither != 0.0f;
1114
/* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */
1115
force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL);
1117
/* Try using GLSL display transform. */
1118
if (force_fallback == false) {
1119
if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) {
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);
1126
IMB_colormanagement_finish_glsl_draw();
1127
need_fallback = false;
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");
1136
IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty,
1137
4, dither, NULL, &scene->display_settings);
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);
1145
MEM_freeN(display_buffer);
1149
RE_ReleaseResultImage(re);
1152
void ED_viewport_render_kill_jobs(const bContext *C, bool free_database)
1154
wmWindowManager *wm = CTX_wm_manager(C);
1155
Main *bmain = CTX_data_main(C);
1163
/* kill all actively running jobs */
1164
WM_jobs_kill(wm, NULL, render_view3d_startjob);
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)
1172
for (ar = sa->regionbase.first; ar; ar = ar->next) {
1175
if (ar->regiontype != RGN_TYPE_WINDOW)
1178
rv3d = ar->regiondata;
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) {
1187
sprintf(name, "View3dPreview %p", (void *)ar);
1188
re = RE_GetRender(name);
1191
RE_Database_Free(re);
1193
/* tag render engine to update entire database */
1194
rv3d->render_engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
1197
/* quick shader update */
1198
rv3d->render_engine->update_flag |= RE_ENGINE_UPDATE_MA;