Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/render/render_internal.c
| Context not available. | |||||
| #include "BLO_undofile.h" | #include "BLO_undofile.h" | ||||
| #include "GPU_extensions.h" | |||||
| #include "render_intern.h" | #include "render_intern.h" | ||||
| /* Render Callbacks */ | /* Render Callbacks */ | ||||
| Context not available. | |||||
| const bool is_animation = RNA_boolean_get(op->ptr, "animation"); | const bool is_animation = RNA_boolean_get(op->ptr, "animation"); | ||||
| const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); | const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); | ||||
| const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport"); | const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport"); | ||||
| /* Do not render inside a job when GPU Context is needed, but GPU has to run on the main | |||||
| * thread. */ | |||||
| const bool use_wm_job = !((re_type->flag & RE_USE_GPU_CONTEXT) && | |||||
| (GPU_main_thread_workaround())); | |||||
| View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL; | View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL; | ||||
| struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; | struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; | ||||
| const char *name; | const char *name; | ||||
| Context not available. | |||||
| name = "Render"; | name = "Render"; | ||||
| } | } | ||||
| wm_job = WM_jobs_get(CTX_wm_manager(C), | |||||
| CTX_wm_window(C), | |||||
| scene, | |||||
| name, | |||||
| WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, | |||||
| WM_JOB_TYPE_RENDER); | |||||
| WM_jobs_customdata_set(wm_job, rj, render_freejob); | |||||
| WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0); | |||||
| WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); | |||||
| if (RNA_struct_property_is_set(op->ptr, "layer")) { | |||||
| WM_jobs_delay_start(wm_job, 0.2); | |||||
| } | |||||
| /* get a render result image, and make sure it is empty */ | /* get a render result image, and make sure it is empty */ | ||||
| ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); | ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); | ||||
| BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE); | BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE); | ||||
| BKE_image_backup_render(rj->scene, ima, true); | BKE_image_backup_render(rj->scene, ima, true); | ||||
| rj->image = ima; | rj->image = ima; | ||||
| /* setup new render */ | |||||
| re = RE_NewSceneRender(scene); | re = RE_NewSceneRender(scene); | ||||
| RE_test_break_cb(re, rj, render_breakjob); | RE_test_break_cb(re, rj, render_breakjob); | ||||
| RE_draw_lock_cb(re, rj, render_drawlock); | RE_draw_lock_cb(re, rj, render_drawlock); | ||||
| Context not available. | |||||
| RE_current_scene_update_cb(re, rj, current_scene_update); | RE_current_scene_update_cb(re, rj, current_scene_update); | ||||
| RE_stats_draw_cb(re, rj, image_renderinfo_cb); | RE_stats_draw_cb(re, rj, image_renderinfo_cb); | ||||
| RE_progress_cb(re, rj, render_progress_update); | RE_progress_cb(re, rj, render_progress_update); | ||||
| RE_gl_context_create(re); | |||||
| rj->re = re; | rj->re = re; | ||||
| G.is_break = false; | |||||
| /* store actual owner of job, so modal operator could check for it, | /* setup new render */ | ||||
| * the reason of this is that active scene could change when rendering | if (use_wm_job) { | ||||
| * several layers from compositor [#31800] | wm_job = WM_jobs_get(CTX_wm_manager(C), | ||||
| */ | CTX_wm_window(C), | ||||
| op->customdata = scene; | scene, | ||||
| name, | |||||
| WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, | |||||
| WM_JOB_TYPE_RENDER); | |||||
| WM_jobs_customdata_set(wm_job, rj, render_freejob); | |||||
| WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0); | |||||
| WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); | |||||
| if (RNA_struct_property_is_set(op->ptr, "layer")) { | |||||
| WM_jobs_delay_start(wm_job, 0.2); | |||||
| } | |||||
| WM_jobs_start(CTX_wm_manager(C), wm_job); | RE_gl_context_create(re); | ||||
| WM_cursor_wait(0); | G.is_break = false; | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); | |||||
| /* store actual owner of job, so modal operator could check for it, | |||||
| * the reason of this is that active scene could change when rendering | |||||
| * several layers from compositor [#31800] | |||||
| */ | |||||
| op->customdata = scene; | |||||
| WM_jobs_start(CTX_wm_manager(C), wm_job); | |||||
| /* we set G.is_rendering here already instead of only in the job, this ensure | WM_cursor_wait(0); | ||||
| * main loop or other scene updates are disabled in time, since they may | WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); | ||||
| * have started before the job thread */ | |||||
| G.is_rendering = true; | |||||
| /* add modal handler for ESC */ | /* we set G.is_rendering here already instead of only in the job, this ensure | ||||
| WM_event_add_modal_handler(C, op); | * main loop or other scene updates are disabled in time, since they may | ||||
| * have started before the job thread */ | |||||
| G.is_rendering = true; | |||||
| return OPERATOR_RUNNING_MODAL; | /* add modal handler for ESC */ | ||||
| WM_event_add_modal_handler(C, op); | |||||
| return OPERATOR_RUNNING_MODAL; | |||||
| } | |||||
| else { | |||||
| short stop = 0; | |||||
| short do_update = 0; | |||||
| float progress = 0.0f; | |||||
| render_startjob(rj, &stop, &do_update, &progress); | |||||
| render_endjob(rj); | |||||
| render_freejob(rj); | |||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| } | } | ||||
| /* contextual render, using current scene, view3d? */ | /* contextual render, using current scene, view3d? */ | ||||
| Context not available. | |||||