Blender V5.0
render_internal.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstddef>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_listbase.h"
15#include "BLI_math_base.hh"
16#include "BLI_rect.h"
17#include "BLI_string_utf8.h"
18#include "BLI_string_utils.hh"
19#include "BLI_time.h"
20#include "BLI_timecode.h"
21#include "BLI_utildefines.h"
22
23#include "BLT_translation.hh"
24
25#include "DNA_object_types.h"
26#include "DNA_scene_types.h"
27#include "DNA_userdef_types.h"
28#include "DNA_view3d_types.h"
29
30#include "BKE_colortools.hh"
31#include "BKE_context.hh"
32#include "BKE_global.hh"
33#include "BKE_image.hh"
34#include "BKE_image_format.hh"
35#include "BKE_layer.hh"
36#include "BKE_lib_id.hh"
37#include "BKE_main.hh"
39#include "BKE_object.hh"
40#include "BKE_report.hh"
41#include "BKE_scene.hh"
42#include "BKE_screen.hh"
43
44#include "NOD_composite.hh"
45
46#include "DEG_depsgraph.hh"
47
48#include "WM_api.hh"
49#include "WM_types.hh"
50
51#include "ED_render.hh"
52#include "ED_screen.hh"
53#include "ED_util.hh"
54
55#include "BIF_glutil.hh"
56
57#include "RE_engine.h"
58#include "RE_pipeline.h"
59
61#include "IMB_imbuf_types.hh"
62
63#include "RNA_access.hh"
64#include "RNA_define.hh"
65
66#include "SEQ_relations.hh"
67
68#include "render_intern.hh"
69
70/* Render Callbacks */
71static bool render_break(void *rjv);
72
98
99/* called inside thread! */
101 const ImBuf *ibuf,
102 rcti *renrect,
103 rcti *r_ibuf_rect,
104 int *r_offset_x,
105 int *r_offset_y)
106{
107 int tile_y, tile_height, tile_x, tile_width;
108
109 /* When `renrect` argument is not nullptr, we only refresh scan-lines. */
110 if (renrect) {
111 /* `if (tile_height == recty)`, rendering of layer is ready,
112 * we should not draw, other things happen... */
113 if (rr->renlay == nullptr || renrect->ymax >= rr->recty) {
114 return false;
115 }
116
117 /* `tile_x` here is first sub-rectangle x coord, tile_width defines sub-rectangle width. */
118 tile_x = renrect->xmin;
119 tile_width = renrect->xmax - tile_x;
120 if (tile_width < 2) {
121 return false;
122 }
123
124 tile_y = renrect->ymin;
125 tile_height = renrect->ymax - tile_y;
126 if (tile_height < 2) {
127 return false;
128 }
129 renrect->ymin = renrect->ymax;
130 }
131 else {
132 tile_x = tile_y = 0;
133 tile_width = rr->rectx;
134 tile_height = rr->recty;
135 }
136
137 /* tile_x tile_y is in tile coords. transform to ibuf */
138 int offset_x = rr->tilerect.xmin;
139 if (offset_x >= ibuf->x) {
140 return false;
141 }
142 int offset_y = rr->tilerect.ymin;
143 if (offset_y >= ibuf->y) {
144 return false;
145 }
146
147 if (offset_x + tile_width > ibuf->x) {
148 tile_width = ibuf->x - offset_x;
149 }
150 if (offset_y + tile_height > ibuf->y) {
151 tile_height = ibuf->y - offset_y;
152 }
153
154 if (tile_width < 1 || tile_height < 1) {
155 return false;
156 }
157
158 r_ibuf_rect->xmax = tile_x + tile_width;
159 r_ibuf_rect->ymax = tile_y + tile_height;
160 r_ibuf_rect->xmin = tile_x;
161 r_ibuf_rect->ymin = tile_y;
162 *r_offset_x = offset_x;
163 *r_offset_y = offset_y;
164 return true;
165}
166
168 RenderResult *rr,
169 ImBuf *ibuf,
170 ImageUser *iuser,
171 const rcti *tile_rect,
172 int offset_x,
173 int offset_y,
174 const char *viewname)
175{
176 Scene *scene = rj->scene;
177 const float *rectf = nullptr;
178 int linear_stride, linear_offset_x, linear_offset_y;
179 const ColorManagedViewSettings *view_settings;
180 const ColorManagedDisplaySettings *display_settings;
181
183 /* The whole image buffer is to be color managed again anyway. */
184 return;
185 }
186
187 /* The thing here is, the logic below (which was default behavior
188 * of how rectf is acquiring since forever) gives float buffer for
189 * composite output only. This buffer can not be used for other
190 * passes obviously.
191 *
192 * We might try finding corresponding for pass buffer in render result
193 * (which is actually missing when rendering with Cycles, who only
194 * writes all the passes when the tile is finished) or use float
195 * buffer from image buffer as reference, which is easier to use and
196 * contains all the data we need anyway.
197 * - sergey -
198 */
199 /* TODO(sergey): Need to check has_combined here? */
200 if (iuser->pass == 0) {
201 const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
202 const RenderView *rv = RE_RenderViewGetById(rr, view_id);
203
204 if (rv->ibuf == nullptr) {
205 return;
206 }
207
208 /* find current float rect for display, first case is after composite... still weak */
209 if (rv->ibuf->float_buffer.data) {
210 rectf = rv->ibuf->float_buffer.data;
211 }
212 else {
213 if (rv->ibuf->byte_buffer.data) {
214 /* special case, currently only happens with sequencer rendering,
215 * which updates the whole frame, so we can only mark display buffer
216 * as invalid here (sergey)
217 */
219 return;
220 }
221 if (rr->renlay == nullptr) {
222 return;
223 }
224 rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname);
225 }
226 if (rectf == nullptr) {
227 return;
228 }
229
230 rectf += 4 * (rr->rectx * tile_rect->ymin + tile_rect->xmin);
231 linear_stride = rr->rectx;
232 linear_offset_x = offset_x;
233 linear_offset_y = offset_y;
234 }
235 else {
236 rectf = ibuf->float_buffer.data;
237 linear_stride = ibuf->x;
238 linear_offset_x = 0;
239 linear_offset_y = 0;
240 }
241
242 view_settings = &scene->view_settings;
243 display_settings = &scene->display_settings;
244
246 rectf,
247 nullptr,
248 linear_stride,
249 linear_offset_x,
250 linear_offset_y,
251 view_settings,
252 display_settings,
253 offset_x,
254 offset_y,
255 offset_x + BLI_rcti_size_x(tile_rect),
256 offset_y + BLI_rcti_size_y(tile_rect));
257}
258
259/* ****************************** render invoking ***************** */
260
261/* set callbacks, exported to sequence render too.
262 * Only call in foreground (UI) renders. */
263
265 wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer)
266{
267 /* single layer re-render */
268 if (RNA_struct_property_is_set(op->ptr, "scene")) {
269 Scene *scn;
270 char scene_name[MAX_ID_NAME - 2];
271
272 RNA_string_get(op->ptr, "scene", scene_name);
273 scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2);
274
275 if (scn) {
276 /* camera switch won't have updated */
277 scn->r.cfra = (*scene)->r.cfra;
279
280 *scene = scn;
281 }
282 }
283
284 if (RNA_struct_property_is_set(op->ptr, "layer")) {
285 ViewLayer *rl;
286 char rl_name[RE_MAXNAME];
287
288 RNA_string_get(op->ptr, "layer", rl_name);
289 rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name));
290
291 if (rl) {
292 *single_layer = rl;
293 }
294 }
295 else if (((*scene)->r.scemode & R_SINGLE_LAYER) && active_layer) {
296 *single_layer = active_layer;
297 }
298}
299
301{
302 return RNA_struct_property_is_set(render_operator->ptr, "frame_start") ||
303 RNA_struct_property_is_set(render_operator->ptr, "frame_end");
304}
305
306static void get_render_operator_frame_range(wmOperator *render_operator,
307 const Scene *scene,
308 int &frame_start,
309 int &frame_end)
310{
311 if (RNA_struct_property_is_set(render_operator->ptr, "frame_start")) {
312 frame_start = RNA_int_get(render_operator->ptr, "frame_start");
313 }
314 else {
315 frame_start = scene->r.sfra;
316 }
317
318 if (RNA_struct_property_is_set(render_operator->ptr, "frame_end")) {
319 frame_end = RNA_int_get(render_operator->ptr, "frame_end");
320 }
321 else {
322 frame_end = scene->r.efra;
323 }
324}
325
326/* executes blocking render */
328{
329 ViewLayer *single_layer = nullptr;
330 Render *re;
331 Image *ima;
332 View3D *v3d = CTX_wm_view3d(C);
333 Main *mainp = CTX_data_main(C);
334
335 const bool is_animation = RNA_boolean_get(op->ptr, "animation");
336 const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
337 const bool use_sequencer_scene = RNA_boolean_get(op->ptr, "use_sequencer_scene");
338
339 Scene *scene = use_sequencer_scene ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
340 ViewLayer *active_layer = use_sequencer_scene ? BKE_view_layer_default_render(scene) :
342 RenderEngineType *re_type = RE_engines_find(scene->r.engine);
343 Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : nullptr;
344
345 /* Cannot do render if there is not this function. */
346 if (re_type->render == nullptr) {
347 return OPERATOR_CANCELLED;
348 }
349
350 if (use_sequencer_scene && !RE_seq_render_active(scene, &scene->r)) {
351 BKE_report(op->reports, RPT_ERROR, "No sequencer scene with video strips to render");
352 return OPERATOR_CANCELLED;
353 }
354
355 if (!is_animation && render_operator_has_custom_frame_range(op)) {
356 BKE_report(op->reports, RPT_ERROR, "Frame start/end specified in a non-animation render");
357 return OPERATOR_CANCELLED;
358 }
359
360 int frame_start, frame_end;
361 get_render_operator_frame_range(op, scene, frame_start, frame_end);
362 if (is_animation && frame_start > frame_end) {
363 BKE_report(op->reports, RPT_ERROR, "Start frame is larger than end frame");
364 return OPERATOR_CANCELLED;
365 }
366
367 /* custom scene and single layer re-render */
368 screen_render_single_layer_set(op, mainp, active_layer, &scene, &single_layer);
369
370 if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
372 op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
373 return OPERATOR_CANCELLED;
374 }
375
376 re = RE_NewSceneRender(scene);
377
378 G.is_break = false;
379
380 RE_draw_lock_cb(re, nullptr, nullptr);
381 RE_test_break_cb(re, nullptr, render_break);
382
383 ima = BKE_image_ensure_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result");
384 BKE_image_signal(mainp, ima, nullptr, IMA_SIGNAL_FREE);
385 BKE_image_backup_render(scene, ima, true);
386
387 /* cleanup sequencer caches before starting user triggered render.
388 * otherwise, invalidated cache entries can make their way into
389 * the output rendering. We can't put that into RE_RenderFrame,
390 * since sequence rendering can call that recursively... (peter) */
392
393 RE_SetReports(re, op->reports);
394
395 if (is_animation) {
396 RE_RenderAnim(re,
397 mainp,
398 scene,
399 single_layer,
400 camera_override,
401 frame_start,
402 frame_end,
403 scene->r.frame_step);
404 }
405 else {
407 mainp,
408 scene,
409 single_layer,
410 camera_override,
411 scene->r.cfra,
412 scene->r.subframe,
413 is_write_still);
414 }
415
416 RE_SetReports(re, nullptr);
417
418 const bool cancelled = G.is_break;
419
420 if (cancelled) {
422 if (rr && rr->error) {
423 /* NOTE(@ideasman42): Report, otherwise the error is entirely hidden from script authors.
424 * This is only done for the #wmOperatorType::exec function because it's assumed users
425 * rendering interactively will view the render and see the error message there. */
427 }
429 }
430
431 /* No redraw needed, we leave state as we entered it. */
433
435
436 if (cancelled) {
437 return OPERATOR_CANCELLED;
438 }
439 return OPERATOR_FINISHED;
440}
441
442static void render_freejob(void *rjv)
443{
444 RenderJob *rj = static_cast<RenderJob *>(rjv);
445
447 MEM_delete(rj);
448}
449
451 const Scene *scene,
452 const bool v3d_override,
453 const char *error,
455{
456 const char *info_space = " ";
457 const char *info_sep = "| ";
458 struct {
459 char time_last[32];
460 char time_elapsed[32];
461 char frame[16];
462 char statistics[64];
463 } info_buffers;
464
465 const char *ret_array[32];
466 int i = 0;
467
468 const uintptr_t mem_in_use = MEM_get_memory_in_use();
469 const uintptr_t peak_memory = MEM_get_peak_memory();
470
471 const int megs_used_memory = ceilf(mem_in_use / (1024.0 * 1024.0));
472 const int megs_peak_memory = ceilf(peak_memory / (1024.0 * 1024.0));
473
474 /* local view */
475 if (rs->localview) {
476 ret_array[i++] = RPT_("3D Local View ");
477 ret_array[i++] = info_sep;
478 }
479 else if (v3d_override) {
480 ret_array[i++] = RPT_("3D View ");
481 ret_array[i++] = info_sep;
482 }
483
484 /* frame number */
485 SNPRINTF_UTF8(info_buffers.frame, "%d ", scene->r.cfra);
486 ret_array[i++] = RPT_("Frame:");
487 ret_array[i++] = info_buffers.frame;
488
489 /* Previous and elapsed time. */
490 const char *info_time = info_buffers.time_last;
492 info_buffers.time_last, sizeof(info_buffers.time_last), rs->lastframetime);
493
494 ret_array[i++] = info_sep;
495 if (rs->infostr && rs->infostr[0]) {
496 if (rs->lastframetime != 0.0) {
497 ret_array[i++] = "Last:";
498 ret_array[i++] = info_buffers.time_last;
499 ret_array[i++] = info_space;
500 }
501
502 info_time = info_buffers.time_elapsed;
503 BLI_timecode_string_from_time_simple(info_buffers.time_elapsed,
504 sizeof(info_buffers.time_elapsed),
506 }
507
508 ret_array[i++] = RPT_("Time:");
509 ret_array[i++] = info_time;
510 ret_array[i++] = info_space;
511
512 /* Statistics. */
513 {
514 const char *info_statistics = nullptr;
515 if (rs->statstr) {
516 if (rs->statstr[0]) {
517 info_statistics = rs->statstr;
518 }
519 }
520 else {
521 if (rs->mem_peak == 0.0f) {
522 SNPRINTF_UTF8(info_buffers.statistics,
523 RPT_("Mem:%dM, Peak: %dM"),
524 megs_used_memory,
525 megs_peak_memory);
526 }
527 else {
529 info_buffers.statistics, RPT_("Mem:%dM, Peak: %dM"), rs->mem_used, rs->mem_peak);
530 }
531 info_statistics = info_buffers.statistics;
532 }
533
534 if (info_statistics) {
535 ret_array[i++] = info_sep;
536 ret_array[i++] = info_statistics;
537 ret_array[i++] = info_space;
538 }
539 }
540
541 /* Extra info. */
542 {
543 const char *info_extra = nullptr;
544 if (rs->infostr && rs->infostr[0]) {
545 info_extra = rs->infostr;
546 }
547 else if (error && error[0]) {
548 info_extra = error;
549 }
550
551 if (info_extra) {
552 ret_array[i++] = info_sep;
553 ret_array[i++] = info_extra;
554 ret_array[i++] = info_space;
555 }
556 }
557
558 if (G.debug & G_DEBUG) {
560 printf("WARNING! renderwin text beyond limit\n");
561 }
562 }
563
564 BLI_assert(i < int(BOUNDED_ARRAY_TYPE_SIZE<decltype(ret_array)>()));
566}
567
568static void image_renderinfo_cb(void *rjv, RenderStats *rs)
569{
570 RenderJob *rj = static_cast<RenderJob *>(rjv);
571 RenderResult *rr;
572
573 rr = RE_AcquireResultRead(rj->re);
574
575 if (rr) {
576 /* `malloc` is OK here, `stats_draw` is not in tile threads. */
577 if (rr->text == nullptr) {
579 }
580
581 make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->error, rr->text);
582 }
583
584 RE_ReleaseResult(rj->re);
585
586 /* make jobs timer to send notifier */
587 *(rj->do_update) = true;
588}
589
590static void render_progress_update(void *rjv, float progress)
591{
592 RenderJob *rj = static_cast<RenderJob *>(rjv);
593
594 if (rj->progress && *rj->progress != progress) {
595 *rj->progress = progress;
596
597 /* make jobs timer to send notifier */
598 *(rj->do_update) = true;
599 }
600}
601
602/* Not totally reliable, but works fine in most of cases and
603 * in worst case would just make it so extra color management
604 * for the whole render result is applied (which was already
605 * happening already).
606 */
608{
609 ScrArea *first_area = nullptr, *matched_area = nullptr;
610
611 /* image window, compo node users */
612
613 /* Only ever 1 `wm`. */
614 for (wmWindowManager *wm = static_cast<wmWindowManager *>(rj->main->wm.first);
615 wm && matched_area == nullptr;
616 wm = static_cast<wmWindowManager *>(wm->id.next))
617 {
618 wmWindow *win;
619 for (win = static_cast<wmWindow *>(wm->windows.first); win && matched_area == nullptr;
620 win = win->next)
621 {
622 const bScreen *screen = WM_window_get_active_screen(win);
623
624 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
625 if (area->spacetype == SPACE_IMAGE) {
626 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
627 /* area->spacedata might be empty when toggling full-screen mode. */
628 if (sima != nullptr && sima->image == rj->image) {
629 if (first_area == nullptr) {
630 first_area = area;
631 }
632 if (area == rj->area) {
633 matched_area = area;
634 break;
635 }
636 }
637 }
638 }
639 }
640 }
641
642 if (matched_area == nullptr) {
643 matched_area = first_area;
644 }
645
646 if (matched_area) {
647 SpaceImage *sima = static_cast<SpaceImage *>(matched_area->spacedata.first);
648 RenderResult *main_rr = RE_AcquireResultRead(rj->re);
649
650 /* TODO(sergey): is there faster way to get the layer index? */
651 if (rr->renlay) {
652 int layer = BLI_findstringindex(
653 &main_rr->layers, (char *)rr->renlay->name, offsetof(RenderLayer, name));
654 sima->iuser.layer = layer;
655 rj->last_layer = layer;
656 }
657
658 iuser->pass = sima->iuser.pass;
659 iuser->layer = sima->iuser.layer;
660
661 RE_ReleaseResult(rj->re);
662 }
663}
664
665static void image_rect_update(void *rjv, RenderResult *rr, rcti *renrect)
666{
667 RenderJob *rj = static_cast<RenderJob *>(rjv);
668 Image *ima = rj->image;
669 ImBuf *ibuf;
670 void *lock;
671 const char *viewname = RE_GetActiveRenderView(rj->re);
672
673 /* only update if we are displaying the slot being rendered */
674 if (ima->render_slot != ima->last_render_slot) {
675 rj->image_outdated = true;
676 return;
677 }
678 if (rj->image_outdated) {
679 /* Free all render buffer caches when switching slots, with lock to ensure main
680 * thread is not drawing the buffer at the same time. */
681 rj->image_outdated = false;
682 ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
684 BKE_image_release_ibuf(ima, ibuf, lock);
685 *(rj->do_update) = true;
686 return;
687 }
688
689 if (rr == nullptr) {
690 return;
691 }
692
693 /* update part of render */
695 rcti tile_rect;
696 int offset_x;
697 int offset_y;
698 ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
699 if (ibuf) {
700 if (!image_buffer_calc_tile_rect(rr, ibuf, renrect, &tile_rect, &offset_x, &offset_y)) {
701 BKE_image_release_ibuf(ima, ibuf, lock);
702 return;
703 }
704
705 /* Don't waste time on CPU side color management if
706 * image will be displayed using GLSL.
707 *
708 * Need to update rect if Save Buffers enabled because in
709 * this case GLSL doesn't have original float buffer to
710 * operate with.
711 */
712 if (ibuf->channels == 1 || ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) {
713 image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, &tile_rect, offset_x, offset_y, viewname);
714 }
715 ImageTile *image_tile = BKE_image_get_tile(ima, 0);
717 image_tile,
718 ibuf,
719 offset_x,
720 offset_y,
721 BLI_rcti_size_x(&tile_rect),
722 BLI_rcti_size_y(&tile_rect));
723
724 /* make jobs timer to send notifier */
725 *(rj->do_update) = true;
726 }
727 BKE_image_release_ibuf(ima, ibuf, lock);
728}
729
730static void current_scene_update(void *rjv, Scene *scene)
731{
732 RenderJob *rj = static_cast<RenderJob *>(rjv);
733
734 if (rj->current_scene != scene) {
735 /* Image must be updated when rendered scene changes. */
737 }
738
739 rj->current_scene = scene;
740 rj->iuser.scene = scene;
741}
742
743static void render_startjob(void *rjv, wmJobWorkerStatus *worker_status)
744{
745 RenderJob *rj = static_cast<RenderJob *>(rjv);
746
747 rj->stop = &worker_status->stop;
748 rj->do_update = &worker_status->do_update;
749 rj->progress = &worker_status->progress;
750
751 RE_SetReports(rj->re, rj->reports);
752
753 if (rj->anim) {
754 RE_RenderAnim(rj->re,
755 rj->main,
756 rj->scene,
757 rj->single_layer,
758 rj->camera_override,
759 rj->frame_start,
760 rj->frame_end,
761 rj->scene->r.frame_step);
762 }
763 else {
764 RE_RenderFrame(rj->re,
765 rj->main,
766 rj->scene,
767 rj->single_layer,
768 rj->camera_override,
769 rj->scene->r.cfra,
770 rj->scene->r.subframe,
771 rj->write_still);
772 }
773
774 RE_SetReports(rj->re, nullptr);
775}
776
778{
779 /* image window, compo node users */
780
781 /* Only ever 1 `wm`. */
782 LISTBASE_FOREACH (wmWindowManager *, wm, &rj->main->wm) {
783 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
784 const bScreen *screen = WM_window_get_active_screen(win);
785
786 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
787 if (area == rj->area) {
788 if (area->spacetype == SPACE_IMAGE) {
789 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
790
791 /* Automatically show scene we just rendered. */
794
795 if (RE_HasSingleLayer(rj->re)) {
796 /* For single layer renders keep the active layer
797 * visible, or show the compositing result. */
799 if (RE_HasCombinedLayer(rr)) {
800 sima->iuser.layer = 0;
801 }
802 RE_ReleaseResult(rj->re);
803 }
804 else {
805 /* For multiple layer render, set back the layer
806 * that was set at the start of rendering. */
807 sima->iuser.layer = rj->orig_layer;
808 }
809 }
810 return;
811 }
812 }
813 }
814 }
815}
816
817static void render_endjob(void *rjv)
818{
819 RenderJob *rj = static_cast<RenderJob *>(rjv);
820
821 /* Clear display GPU context and callbacks since this may be used again
822 * by e.g. the sequencer (#24508). */
823 RE_display_free(rj->re);
824
825 if (rj->main != G_MAIN) {
826 BKE_main_free(rj->main);
827 }
828
829 /* Update depsgraph for returning to the original frame before animation render job. */
830 if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
831 /* Possible this fails when loading new file while rendering. */
832 if (G_MAIN->wm.first) {
833 /* Check view layer was not deleted during render. Technically another view layer
834 * may get allocated with the same pointer, but worst case it will cause an
835 * unnecessary update. */
836 if (BLI_findindex(&rj->scene->view_layers, rj->view_layer) != -1) {
837 Depsgraph *depsgraph = BKE_scene_get_depsgraph(rj->scene, rj->view_layer);
838 if (depsgraph) {
840 }
841 }
842 }
843 }
844
845 /* XXX above function sets all tags in nodes */
847
848 /* potentially set by caller */
850
851 if (rj->single_layer) {
855 }
856
857 if (rj->area) {
859 }
860
861 /* XXX render stability hack */
862 G.is_rendering = false;
864
865 /* Partial render result will always update display buffer
866 * for first render layer only. This is nice because you'll
867 * see render progress during rendering, but it ends up in
868 * wrong display buffer shown after rendering.
869 *
870 * The code below will mark display buffer as invalid after
871 * rendering in case multiple layers were rendered, which
872 * ensures display buffer matches render layer after
873 * rendering.
874 *
875 * Perhaps proper way would be to toggle active render
876 * layer in image editor and job, so we always display
877 * layer being currently rendered. But this is not so much
878 * trivial at this moment, especially because of external
879 * engine API, so lets use simple and robust way for now
880 * - sergey -
881 */
882 if (rj->scene->view_layers.first != rj->scene->view_layers.last || rj->image_outdated) {
883 void *lock;
884 Image *ima = rj->image;
885 ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
886
887 if (ibuf) {
889 }
890
891 BKE_image_release_ibuf(ima, ibuf, lock);
892 }
893
894 /* Finally unlock the user interface (if it was locked). */
895 if (rj->interface_locked) {
896 /* Interface was locked, so window manager couldn't have been changed
897 * and using one from Global will unlock exactly the same manager as
898 * was locked before running the job.
899 */
900 WM_locked_interface_set(static_cast<wmWindowManager *>(G_MAIN->wm.first), false);
902 }
903}
904
905/* called by render, check job 'stop' value or the global */
906static bool render_breakjob(void *rjv)
907{
908 RenderJob *rj = static_cast<RenderJob *>(rjv);
909
910 if (G.is_break) {
911 return true;
912 }
913 if (rj->stop && *(rj->stop)) {
914 return true;
915 }
916 return false;
917}
918
923static bool render_break(void * /*rjv*/)
924{
925 if (G.is_break) {
926 return true;
927 }
928 return false;
929}
930
931/* runs in thread, no cursor setting here works. careful with notifiers too (`malloc` conflicts) */
932/* maybe need a way to get job send notifier? */
933static void render_drawlock(void *rjv, bool lock)
934{
935 RenderJob *rj = static_cast<RenderJob *>(rjv);
936
937 /* If interface is locked, renderer callback shall do nothing. */
938 if (!rj->interface_locked) {
940 }
941}
942
945{
946 Scene *scene = (Scene *)op->customdata;
947
948 /* no running blender, remove handler and pass through */
949 if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
951 }
952
953 /* running render */
955}
956
958{
960 Scene *scene = (Scene *)op->customdata;
961
962 /* kill on cancel, because job is using op->reports */
964}
965
967{
969 return;
970 }
971
972 Object *object = base->object;
973
974 if (object->id.tag & ID_TAG_DOIT) {
975 return;
976 }
977
978 object->id.tag &= ~ID_TAG_DOIT;
979 if (RE_allow_render_generic_object(object)) {
981 }
982}
983
984static void clean_viewport_memory(Main *bmain, Scene *scene)
985{
986 Scene *sce_iter;
987 Base *base;
988
989 /* Tag all the available objects. */
991
992 /* Go over all the visible objects. */
993
994 /* Only ever 1 `wm`. */
995 LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
996 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
998 BKE_view_layer_synced_ensure(scene, view_layer);
999
1002 }
1003 }
1004 }
1005
1006 for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
1008 }
1009}
1010
1011/* using context, starts job */
1013{
1014 /* new render clears all callbacks */
1015 Main *bmain = CTX_data_main(C);
1016 ViewLayer *single_layer = nullptr;
1017 Render *re;
1018 wmJob *wm_job;
1019 RenderJob *rj;
1020 Image *ima;
1021 ScrArea *area;
1022
1023 const bool is_animation = RNA_boolean_get(op->ptr, "animation");
1024 const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
1025 const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
1026 const bool use_sequencer_scene = RNA_boolean_get(op->ptr, "use_sequencer_scene");
1027
1028 View3D *v3d = use_viewport ? CTX_wm_view3d(C) : nullptr;
1029 Scene *scene = use_sequencer_scene ? CTX_data_sequencer_scene(C) : CTX_data_scene(C);
1030 ViewLayer *active_layer = use_sequencer_scene ? BKE_view_layer_default_render(scene) :
1032 RenderEngineType *re_type = RE_engines_find(scene->r.engine);
1033 Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : nullptr;
1034
1035 /* Cannot do render if there is not this function. */
1036 if (re_type->render == nullptr) {
1037 return OPERATOR_CANCELLED;
1038 }
1039
1040 if (use_sequencer_scene && !RE_seq_render_active(scene, &scene->r)) {
1041 BKE_report(op->reports, RPT_ERROR, "No sequencer scene with video strips to render");
1042 return OPERATOR_CANCELLED;
1043 }
1044
1045 if (!is_animation && render_operator_has_custom_frame_range(op)) {
1046 BKE_report(op->reports, RPT_ERROR, "Frame start/end specified in a non-animation render");
1047 return OPERATOR_CANCELLED;
1048 }
1049
1050 int frame_start, frame_end;
1051 get_render_operator_frame_range(op, scene, frame_start, frame_end);
1052 if (is_animation && frame_start > frame_end) {
1053 BKE_report(op->reports, RPT_ERROR, "Start frame is larger than end frame");
1054 return OPERATOR_CANCELLED;
1055 }
1056
1057 /* custom scene and single layer re-render */
1058 screen_render_single_layer_set(op, bmain, active_layer, &scene, &single_layer);
1059
1060 /* only one render job at a time */
1062 return OPERATOR_CANCELLED;
1063 }
1064
1065 if (!RE_is_rendering_allowed(scene, single_layer, camera_override, op->reports)) {
1066 return OPERATOR_CANCELLED;
1067 }
1068
1069 if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
1070 BKE_report(
1071 op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
1072 return OPERATOR_CANCELLED;
1073 }
1074
1075 /* Reports are done inside check function, and it will return false if there are other strips to
1076 * render. */
1077 if ((scene->r.scemode & R_DOSEQ) &&
1079 {
1080 return OPERATOR_CANCELLED;
1081 }
1082
1083 /* stop all running jobs, except screen one. currently previews frustrate Render */
1085
1086 /* cancel animation playback */
1089 }
1090
1091 /* handle UI stuff */
1092 WM_cursor_wait(true);
1093
1094 /* flush sculpt and editmode changes */
1095 ED_editors_flush_edits_ex(bmain, true, false);
1096
1097 /* Cleanup VSE cache, since it is not guaranteed that stored images are invalid. */
1099
1100 /* store spare
1101 * get view3d layer, local layer, make this nice API call to render
1102 * store spare */
1103
1104 /* ensure at least 1 area shows result */
1105 area = render_view_open(C, event->xy[0], event->xy[1], op->reports);
1106
1107 /* job custom data */
1108 rj = MEM_new<RenderJob>("render job");
1109 rj->main = bmain;
1110 rj->scene = scene;
1111 rj->current_scene = rj->scene;
1112 rj->view_layer = active_layer;
1113 rj->single_layer = single_layer;
1114 rj->camera_override = camera_override;
1115 rj->anim = is_animation;
1116 rj->write_still = is_write_still && !is_animation;
1117 rj->iuser.scene = scene;
1118 rj->reports = op->reports;
1119 rj->orig_layer = 0;
1120 rj->last_layer = 0;
1121 rj->use_sequencer_scene = use_sequencer_scene;
1122 rj->area = area;
1123 rj->frame_start = frame_start;
1124 rj->frame_end = frame_end;
1125
1128
1129 if (area) {
1130 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
1131 rj->orig_layer = sima->iuser.layer;
1132 }
1133
1134 if (v3d) {
1135 if (camera_override && camera_override != scene->camera) {
1136 rj->v3d_override = true;
1137 }
1138 }
1139
1140 /* Lock the user interface depending on render settings. */
1141 if (scene->r.use_lock_interface) {
1143
1144 /* Set flag interface need to be unlocked.
1145 *
1146 * This is so because we don't have copy of render settings
1147 * accessible from render job and copy is needed in case
1148 * of non-locked rendering, so we wouldn't try to unlock
1149 * anything if option was initially unset but then was
1150 * enabled during rendering.
1151 */
1152 rj->interface_locked = true;
1153
1154 /* Clean memory used by viewport? */
1155 clean_viewport_memory(rj->main, scene);
1156 }
1157
1158 /* setup job */
1159 const char *name;
1160 if (RE_seq_render_active(scene, &scene->r)) {
1161 name = RPT_("Rendering sequence...");
1162 }
1163 else {
1164 name = RPT_("Rendering...");
1165 }
1166
1167 wm_job = WM_jobs_get(CTX_wm_manager(C),
1169 scene,
1170 name,
1174 WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
1175 WM_jobs_callbacks(wm_job, render_startjob, nullptr, nullptr, render_endjob);
1176
1177 if (RNA_struct_property_is_set(op->ptr, "layer")) {
1178 WM_jobs_delay_start(wm_job, 0.2);
1179 }
1180
1181 /* get a render result image, and make sure it is empty */
1182 ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
1183 BKE_image_signal(rj->main, ima, nullptr, IMA_SIGNAL_FREE);
1184 BKE_image_backup_render(rj->scene, ima, true);
1185 rj->image = ima;
1186
1187 /* setup new render */
1188 re = RE_NewSceneRender(scene);
1189 RE_display_init(re);
1197
1198 rj->re = re;
1199 G.is_break = false;
1200
1201 /* store actual owner of job, so modal operator could check for it,
1202 * the reason of this is that active scene could change when rendering
1203 * several layers from compositor #31800. */
1204 op->customdata = scene;
1205
1206 WM_jobs_start(CTX_wm_manager(C), wm_job);
1207
1208 WM_cursor_wait(false);
1210
1211 /* we set G.is_rendering here already instead of only in the job, this ensure
1212 * main loop or other scene updates are disabled in time, since they may
1213 * have started before the job thread */
1214 G.is_rendering = true;
1215
1216 /* add modal handler for ESC */
1218
1220}
1221
1222static std::string screen_render_get_description(bContext * /*C*/,
1223 wmOperatorType * /*ot*/,
1224 PointerRNA *ptr)
1225{
1226 const bool use_sequencer_scene = RNA_boolean_get(ptr, "use_sequencer_scene");
1227 if (use_sequencer_scene) {
1228 return TIP_("Render active sequencer scene");
1229 }
1230 return TIP_("Render active scene");
1231}
1232
1234{
1235 PropertyRNA *prop;
1236
1237 /* identifiers */
1238 ot->name = "Render";
1239 ot->idname = "RENDER_OT_render";
1240
1241 /* API callbacks. */
1242 ot->invoke = screen_render_invoke;
1243 ot->modal = screen_render_modal;
1244 ot->cancel = screen_render_cancel;
1245 ot->exec = screen_render_exec;
1246 ot->get_description = screen_render_get_description;
1247
1248 /* This isn't needed, causes failure in background mode. */
1249#if 0
1251#endif
1252
1253 prop = RNA_def_boolean(ot->srna,
1254 "animation",
1255 false,
1256 "Animation",
1257 "Render files from the animation range of this scene");
1260 ot->srna,
1261 "write_still",
1262 false,
1263 "Write Image",
1264 "Save the rendered image to the output path (used only when animation is disabled)");
1265 prop = RNA_def_boolean(ot->srna,
1266 "use_viewport",
1267 false,
1268 "Use 3D Viewport",
1269 "When inside a 3D viewport, use layers and camera of the viewport");
1271 prop = RNA_def_boolean(ot->srna,
1272 "use_sequencer_scene",
1273 false,
1274 "Use Sequencer Scene",
1275 "Render the sequencer scene instead of the active scene");
1277 prop = RNA_def_string(ot->srna,
1278 "layer",
1279 nullptr,
1280 RE_MAXNAME,
1281 "Render Layer",
1282 "Single render layer to re-render (used only when animation is disabled)");
1284 prop = RNA_def_string(ot->srna,
1285 "scene",
1286 nullptr,
1287 MAX_ID_NAME - 2,
1288 "Scene",
1289 "Scene to render, current scene if not specified");
1291 prop = RNA_def_int(
1292 ot->srna,
1293 "frame_start",
1294 0,
1295 INT_MIN,
1296 INT_MAX,
1297 "Start Frame",
1298 "Frame to start rendering animation at. If not specified, the scene start frame will be "
1299 "assumed. This should only be specified if doing an animation render",
1300 INT_MIN,
1301 INT_MAX);
1303 prop = RNA_def_int(
1304 ot->srna,
1305 "frame_end",
1306 0,
1307 INT_MIN,
1308 INT_MAX,
1309 "End Frame",
1310 "Frame to end rendering animation at. If not specified, the scene end frame will be "
1311 "assumed. This should only be specified if doing an animation render",
1312 INT_MIN,
1313 INT_MAX);
1315}
1316
1318{
1320 RenderJobBase *rj;
1321
1322 /* Try to find job tied to active scene first. */
1323 rj = static_cast<RenderJobBase *>(
1325
1326 /* If not found, attempt to find job tied to sequencer scene. */
1327 if (rj == nullptr) {
1328 return static_cast<RenderJobBase *>(
1330 }
1331
1332 return rj;
1333}
1334
1336{
1338 return rj ? rj->scene : nullptr;
1339}
1340
1342{
1344 return rj ? rj->current_scene : nullptr;
1345}
1346
1347/* Motion blur curve preset */
1348
1350{
1351 Scene *scene = CTX_data_scene(C);
1352 CurveMapping *mblur_shutter_curve = &scene->r.mblur_shutter_curve;
1353 CurveMap *cm = mblur_shutter_curve->cm;
1354 int preset = RNA_enum_get(op->ptr, "shape");
1355
1356 mblur_shutter_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1357 mblur_shutter_curve->preset = preset;
1359 &mblur_shutter_curve->clipr,
1360 mblur_shutter_curve->preset,
1362 BKE_curvemapping_changed(mblur_shutter_curve, false);
1363
1364 return OPERATOR_FINISHED;
1365}
1366
1368{
1369 PropertyRNA *prop;
1370 static const EnumPropertyItem prop_shape_items[] = {
1371 {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
1372 {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
1373 {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
1374 {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
1375 {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
1376 {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
1377 {0, nullptr, 0, nullptr, nullptr},
1378 };
1379
1380 ot->name = "Shutter Curve Preset";
1381 ot->description = "Set shutter curve";
1382 ot->idname = "RENDER_OT_shutter_curve_preset";
1383
1385
1386 prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
1388 BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
1389}
int ED_draw_imbuf_method(const ImBuf *ibuf)
Definition glutil.cc:619
void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, CurveMapSlopeType slope)
void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings, const ColorManagedDisplaySettings *settings)
void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings)
void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings, const ColorManagedViewSettings *settings)
void BKE_curvemapping_changed(CurveMapping *cumap, bool rem_doubles)
bScreen * CTX_wm_screen(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
@ G_DEBUG
#define G_MAIN
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
Image * BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_update_gputexture_delayed(Image *ima, ImageTile *image_tile, ImBuf *ibuf, int x, int y, int w, int h)
Definition image_gpu.cc:921
void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
#define IMA_SIGNAL_FREE
Definition BKE_image.hh:169
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
bool BKE_imtype_is_movie(char imtype)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1201
void BKE_main_free(Main *bmain)
Definition main.cc:192
void BKE_ntree_update(Main &bmain, std::optional< blender::Span< bNodeTree * > > modified_trees=std::nullopt, const NodeTreeUpdateExtraParams &params={})
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(Object *ob)
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define SETLOOPER_SET_ONLY(_sce_basis, _sce_iter, _base)
Definition BKE_scene.hh:52
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2265
int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
Definition scene.cc:3082
Depsgraph * BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_layer)
Definition scene.cc:3403
void BKE_spacedata_draw_locks(ARegionDrawLockFlags lock_flags)
Definition screen.cc:423
@ REGION_DRAW_LOCK_NONE
@ REGION_DRAW_LOCK_RENDER
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
int BLI_findstringindex(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:780
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
#define SNPRINTF_UTF8(dst, format,...)
size_t BLI_string_join_array(char *result, size_t result_maxncpy, const char *strings[], uint strings_num) ATTR_NONNULL()
void size_t BLI_string_len_array(const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxncpy, double time_seconds) ATTR_NONNULL()
Definition timecode.cc:170
#define SET_FLAG_FROM_TEST(value, test, flag)
#define RPT_(msgid)
#define BLT_I18NCONTEXT_ID_CURVE_LEGACY
#define TIP_(msgid)
void DEG_tag_on_visible_update(Main *bmain, bool do_time)
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ CUMA_EXTEND_EXTRAPOLATE
@ CURVE_PRESET_ROOT
@ CURVE_PRESET_SMOOTH
@ CURVE_PRESET_ROUND
@ CURVE_PRESET_LINE
@ CURVE_PRESET_SHARP
@ CURVE_PRESET_MAX
#define IMA_MAX_RENDER_TEXT_SIZE
@ IMA_TYPE_R_RESULT
@ IMA_SHOW_SEQUENCER_SCENE
@ BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT
Object is a sort of wrapper for general info.
#define RE_PASSNAME_COMBINED
#define V3D_CAMERA_LOCAL(v3d)
@ R_SINGLE_LAYER
@ R_DOSEQ
@ R_NO_FRAME_UPDATE
@ SPACE_IMAGE
@ IMAGE_DRAW_METHOD_GLSL
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode)
bool ED_operator_screenactive(bContext *C)
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
bool ED_editors_flush_edits_ex(Main *bmain, bool for_render, bool check_needs_flush)
Definition ed_util.cc:320
void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax)
@ IB_DISPLAY_BUFFER_INVALID
Read Guarded memory(de)allocation.
#define RE_MAXNAME
Definition RE_pipeline.h:37
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
@ WM_JOB_TYPE_RENDER
Definition WM_api.hh:1778
@ WM_JOB_EXCL_RENDER
Definition WM_api.hh:1765
@ WM_JOB_PROGRESS
Definition WM_api.hh:1766
@ WM_JOB_PRIORITY
Definition WM_api.hh:1760
#define NC_NODE
Definition WM_types.hh:394
#define ND_RENDER_RESULT
Definition WM_types.hh:446
#define NC_SCENE
Definition WM_types.hh:378
#define NA_EDITED
Definition WM_types.hh:584
volatile int lock
BPy_StructRNA * depsgraph
#define offsetof(t, d)
#define printf(...)
RenderEngineType * RE_engines_find(const char *idname)
size_t(* MEM_get_peak_memory)(void)
Definition mallocn.cc:73
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
size_t(* MEM_get_memory_in_use)(void)
Definition mallocn.cc:70
static size_t mem_in_use
#define G(x, y, z)
static void error(const char *str)
void cache_cleanup(Scene *scene)
bool relations_check_scene_recursion(Scene *scene, ReportList *reports)
void ntreeCompositClearTags(bNodeTree *ntree)
const char * name
return ret
#define ceilf
ScrArea * render_view_open(bContext *C, int mx, int my, ReportList *reports)
static void render_endjob(void *rjv)
static void current_scene_update(void *rjv, Scene *scene)
static void render_image_restore_scene_and_layer(RenderJob *rj)
static void image_rect_update(void *rjv, RenderResult *rr, rcti *renrect)
static RenderJobBase * render_job_get(const bContext *C)
static void image_renderinfo_cb(void *rjv, RenderStats *rs)
void RENDER_OT_render(wmOperatorType *ot)
static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, const rcti *tile_rect, int offset_x, int offset_y, const char *viewname)
static void make_renderinfo_string(const RenderStats *rs, const Scene *scene, const bool v3d_override, const char *error, char ret[IMA_MAX_RENDER_TEXT_SIZE])
Scene * ED_render_job_get_scene(const bContext *C)
static void screen_render_single_layer_set(wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer)
static void render_drawlock(void *rjv, bool lock)
static wmOperatorStatus screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void get_render_operator_frame_range(wmOperator *render_operator, const Scene *scene, int &frame_start, int &frame_end)
void RENDER_OT_shutter_curve_preset(wmOperatorType *ot)
static bool render_break(void *rjv)
static wmOperatorStatus render_shutter_curve_preset_exec(bContext *C, wmOperator *op)
static void clean_viewport_memory(Main *bmain, Scene *scene)
Scene * ED_render_job_get_current_scene(const bContext *C)
static bool render_breakjob(void *rjv)
static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, ImageUser *iuser)
static void render_progress_update(void *rjv, float progress)
static void clean_viewport_memory_base(Base *base)
static void screen_render_cancel(bContext *C, wmOperator *op)
static wmOperatorStatus screen_render_exec(bContext *C, wmOperator *op)
static wmOperatorStatus screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void render_freejob(void *rjv)
static bool image_buffer_calc_tile_rect(const RenderResult *rr, const ImBuf *ibuf, rcti *renrect, rcti *r_ibuf_rect, int *r_offset_x, int *r_offset_y)
static bool render_operator_has_custom_frame_range(wmOperator *render_operator)
static void render_startjob(void *rjv, wmJobWorkerStatus *worker_status)
static std::string screen_render_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
bool RE_HasCombinedLayer(const RenderResult *result)
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
int RNA_int_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
bool RE_HasSingleLayer(Render *re)
void RE_stats_draw_cb(Render *re, void *handle, void(*f)(void *handle, RenderStats *rs))
void RE_progress_cb(Render *re, void *handle, void(*f)(void *handle, float))
void RE_test_break_cb(Render *re, void *handle, bool(*f)(void *handle))
void RE_current_scene_update_cb(Render *re, void *handle, void(*f)(void *handle, Scene *scene))
void RE_RenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override, const int frame, const float subframe, const bool write_still)
void RE_display_free(Render *re)
Render * RE_NewSceneRender(const Scene *scene)
void RE_display_ensure_gpu_context(Render *re)
bool RE_seq_render_active(Scene *scene, RenderData *rd)
RenderResult * RE_AcquireResultRead(Render *re)
void RE_display_init(Render *re)
void RE_ReleaseResult(Render *re)
const char * RE_GetActiveRenderView(Render *re)
void RE_RenderAnim(Render *re, Main *bmain, Scene *scene, ViewLayer *single_layer, Object *camera_override, int sfra, int efra, int tfra)
bool RE_allow_render_generic_object(Object *ob)
void RE_display_update_cb(Render *re, void *handle, void(*f)(void *handle, RenderResult *rr, rcti *rect))
bool RE_is_rendering_allowed(Scene *scene, ViewLayer *single_layer, Object *camera_override, ReportList *reports)
void RE_draw_lock_cb(Render *re, void *handle, void(*f)(void *handle, bool lock))
void RE_SetReports(Render *re, ReportList *reports)
float * RE_RenderLayerGetPass(RenderLayer *rl, const char *name, const char *viewname)
short flag
struct Object * object
CurveMap cm[4]
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
struct Scene * scene
short last_render_slot
short render_slot
void * last
void * first
ListBase scenes
Definition BKE_main.hh:278
ListBase wm
Definition BKE_main.hh:307
ListBase objects
Definition BKE_main.hh:280
struct CurveMapping mblur_shutter_curve
char engine[32]
struct ImageFormatData im_format
char use_lock_interface
void(* render)(struct RenderEngine *engine, struct Depsgraph *depsgraph)
Definition RE_engine.h:79
Scene * current_scene
ImageUser iuser
bool use_sequencer_scene
ViewLayer * single_layer
ColorManagedViewSettings view_settings
ReportList * reports
ScrArea * area
bool interface_locked
ViewLayer * view_layer
ColorManagedDisplaySettings display_settings
Object * camera_override
float * progress
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
ListBase layers
RenderLayer * renlay
const char * statstr
double starttime
double lastframetime
const char * infostr
struct ImBuf * ibuf
Definition RE_pipeline.h:49
ColorManagedViewSettings view_settings
struct bNodeTree * compositing_node_group
struct RenderData r
ListBase view_layers
struct Object * camera
ColorManagedDisplaySettings display_settings
ListBase spacedata
struct ImageUser iuser
struct Image * image
ListBase areabase
int ymin
int ymax
int xmin
int xmax
wmEventType type
Definition WM_types.hh:757
int xy[2]
Definition WM_types.hh:761
struct ReportList * reports
struct PointerRNA * ptr
struct wmWindow * next
void * BKE_image_free_buffers
Definition stubs.c:35
void * BKE_image_get_tile
Definition stubs.c:36
i
Definition text_draw.cc:230
void WM_cursor_wait(bool val)
void WM_locked_interface_set(wmWindowManager *wm, bool lock)
void WM_locked_interface_set_with_flags(wmWindowManager *wm, short lock_flags)
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_ESCKEY
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
void WM_jobs_kill_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:623
void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
Definition wm_jobs.cc:383
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:211
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:388
void WM_jobs_kill_all_except(wmWindowManager *wm, const void *owner)
Definition wm_jobs.cc:614
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:247
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360
void * WM_jobs_customdata_from_type(wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:330
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
bScreen * WM_window_get_active_screen(const wmWindow *win)