UI: only reset eyedropper on cancel when set
[blender.git] / source / blender / render / intern / source / external_engine.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/render/intern/source/external_engine.c
29  *  \ingroup render
30  */
31
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLT_translation.h"
39
40 #include "BLI_listbase.h"
41 #include "BLI_string.h"
42 #include "BLI_utildefines.h"
43
44 #include "DNA_object_types.h"
45
46 #include "BKE_camera.h"
47 #include "BKE_global.h"
48 #include "BKE_colortools.h"
49 #include "BKE_layer.h"
50 #include "BKE_node.h"
51 #include "BKE_report.h"
52 #include "BKE_scene.h"
53
54 #include "DEG_depsgraph.h"
55 #include "DEG_depsgraph_debug.h"
56 #include "DEG_depsgraph_query.h"
57
58 #include "RNA_access.h"
59
60 #ifdef WITH_PYTHON
61 #include "BPY_extern.h"
62 #endif
63
64 #include "RE_engine.h"
65 #include "RE_pipeline.h"
66 #include "RE_bake.h"
67
68 #include "DRW_engine.h"
69
70 #include "initrender.h"
71 #include "renderpipeline.h"
72 #include "render_types.h"
73 #include "render_result.h"
74
75 /* Render Engine Types */
76
77 ListBase R_engines = {NULL, NULL};
78
79 void RE_engines_init(void)
80 {
81         DRW_engines_register();
82 }
83
84 void RE_engines_exit(void)
85 {
86         RenderEngineType *type, *next;
87
88         DRW_engines_free();
89
90         for (type = R_engines.first; type; type = next) {
91                 next = type->next;
92
93                 BLI_remlink(&R_engines, type);
94
95                 if (!(type->flag & RE_INTERNAL)) {
96                         if (type->ext.free)
97                                 type->ext.free(type->ext.data);
98
99                         MEM_freeN(type);
100                 }
101         }
102 }
103
104 void RE_engines_register(RenderEngineType *render_type)
105 {
106         if (render_type->draw_engine) {
107                 DRW_engine_register(render_type->draw_engine);
108         }
109         BLI_addtail(&R_engines, render_type);
110 }
111
112 RenderEngineType *RE_engines_find(const char *idname)
113 {
114         RenderEngineType *type;
115
116         type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
117         if (!type)
118                 type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname));
119
120         return type;
121 }
122
123 bool RE_engine_is_external(Render *re)
124 {
125         return (re->engine && re->engine->type && re->engine->type->render);
126 }
127
128 bool RE_engine_is_opengl(RenderEngineType *render_type)
129 {
130         /* TODO refine? Can we have ogl render engine without ogl render pipeline? */
131         return (render_type->draw_engine != NULL) &&
132                DRW_engine_render_support(render_type->draw_engine);
133 }
134
135 /* Create, Free */
136
137 RenderEngine *RE_engine_create(RenderEngineType *type)
138 {
139         return RE_engine_create_ex(type, false);
140 }
141
142 RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
143 {
144         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
145         engine->type = type;
146
147         if (use_for_viewport) {
148                 engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
149
150                 BLI_threaded_malloc_begin();
151         }
152
153         return engine;
154 }
155
156 void RE_engine_free(RenderEngine *engine)
157 {
158 #ifdef WITH_PYTHON
159         if (engine->py_instance) {
160                 BPY_DECREF_RNA_INVALIDATE(engine->py_instance);
161         }
162 #endif
163
164         if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
165                 BLI_threaded_malloc_end();
166         }
167
168         MEM_freeN(engine);
169 }
170
171 /* Render Results */
172
173 static RenderPart *get_part_from_result(Render *re, RenderResult *result)
174 {
175         RenderPart *pa;
176
177         for (pa = re->parts.first; pa; pa = pa->next) {
178                 if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
179                     result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
180                     result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
181                     result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
182                 {
183                         return pa;
184                 }
185         }
186
187         return NULL;
188 }
189
190 RenderResult *RE_engine_begin_result(
191         RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
192 {
193         Render *re = engine->re;
194         RenderResult *result;
195         rcti disprect;
196
197         /* ensure the coordinates are within the right limits */
198         CLAMP(x, 0, re->result->rectx);
199         CLAMP(y, 0, re->result->recty);
200         CLAMP(w, 0, re->result->rectx);
201         CLAMP(h, 0, re->result->recty);
202
203         if (x + w > re->result->rectx)
204                 w = re->result->rectx - x;
205         if (y + h > re->result->recty)
206                 h = re->result->recty - y;
207
208         /* allocate a render result */
209         disprect.xmin = x;
210         disprect.xmax = x + w;
211         disprect.ymin = y;
212         disprect.ymax = y + h;
213
214         result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername, viewname);
215
216         /* todo: make this thread safe */
217
218         /* can be NULL if we CLAMP the width or height to 0 */
219         if (result) {
220                 render_result_clone_passes(re, result, viewname);
221
222                 RenderPart *pa;
223
224                 /* Copy EXR tile settings, so pipeline knows whether this is a result
225                  * for Save Buffers enabled rendering.
226                  */
227                 result->do_exr_tile = re->result->do_exr_tile;
228
229                 BLI_addtail(&engine->fullresult, result);
230
231                 result->tilerect.xmin += re->disprect.xmin;
232                 result->tilerect.xmax += re->disprect.xmin;
233                 result->tilerect.ymin += re->disprect.ymin;
234                 result->tilerect.ymax += re->disprect.ymin;
235
236                 pa = get_part_from_result(re, result);
237
238                 if (pa)
239                         pa->status = PART_STATUS_IN_PROGRESS;
240         }
241
242         return result;
243 }
244
245 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
246 {
247         Render *re = engine->re;
248
249         if (result) {
250                 result->renlay = result->layers.first; /* weak, draws first layer always */
251                 re->display_update(re->duh, result, NULL);
252         }
253 }
254
255 void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
256 {
257         Render *re = engine->re;
258
259         if (!re || !re->result) {
260                 return;
261         }
262
263         render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
264 }
265
266 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
267 {
268         Render *re = engine->re;
269
270         if (!result) {
271                 return;
272         }
273
274         /* merge. on break, don't merge in result for preview renders, looks nicer */
275         if (!highlight) {
276                 /* for exr tile render, detect tiles that are done */
277                 RenderPart *pa = get_part_from_result(re, result);
278
279                 if (pa) {
280                         pa->status = (!cancel && merge_results)? PART_STATUS_MERGED: PART_STATUS_RENDERED;
281                 }
282                 else if (re->result->do_exr_tile) {
283                         /* if written result does not match any tile and we are using save
284                          * buffers, we are going to get openexr save errors */
285                         fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n");
286                 }
287         }
288
289         if (!cancel || merge_results) {
290                 if (re->result->do_exr_tile) {
291                         if (!cancel && merge_results) {
292                                 render_result_exr_file_merge(re->result, result, re->viewname);
293                         }
294                 }
295                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
296                         render_result_merge(re->result, result);
297
298                 /* draw */
299                 if (!re->test_break(re->tbh)) {
300                         result->renlay = result->layers.first; /* weak, draws first layer always */
301                         re->display_update(re->duh, result, NULL);
302                 }
303         }
304
305         /* free */
306         BLI_remlink(&engine->fullresult, result);
307         render_result_free(result);
308 }
309
310 RenderResult *RE_engine_get_result(RenderEngine *engine)
311 {
312         return engine->re->result;
313 }
314
315 /* Cancel */
316
317 bool RE_engine_test_break(RenderEngine *engine)
318 {
319         Render *re = engine->re;
320
321         if (re)
322                 return re->test_break(re->tbh);
323
324         return 0;
325 }
326
327 /* Statistics */
328
329 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
330 {
331         Render *re = engine->re;
332
333         /* stats draw callback */
334         if (re) {
335                 re->i.statstr = stats;
336                 re->i.infostr = info;
337                 re->stats_draw(re->sdh, &re->i);
338                 re->i.infostr = NULL;
339                 re->i.statstr = NULL;
340         }
341
342         /* set engine text */
343         engine->text[0] = '\0';
344
345         if (stats && stats[0] && info && info[0])
346                 BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
347         else if (info && info[0])
348                 BLI_strncpy(engine->text, info, sizeof(engine->text));
349         else if (stats && stats[0])
350                 BLI_strncpy(engine->text, stats, sizeof(engine->text));
351 }
352
353 void RE_engine_update_progress(RenderEngine *engine, float progress)
354 {
355         Render *re = engine->re;
356
357         if (re) {
358                 CLAMP(progress, 0.0f, 1.0f);
359                 re->progress(re->prh, progress);
360         }
361 }
362
363 void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
364 {
365         Render *re = engine->re;
366
367         if (re) {
368                 re->i.mem_used = mem_used;
369                 re->i.mem_peak = mem_peak;
370         }
371 }
372
373 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
374 {
375         Render *re = engine->re;
376
377         if (re)
378                 BKE_report(engine->re->reports, type, msg);
379         else if (engine->reports)
380                 BKE_report(engine->reports, type, msg);
381 }
382
383 void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
384 {
385         Render *re = engine->re;
386         if (re != NULL) {
387                 RenderResult *rr = RE_AcquireResultRead(re);
388                 if (rr) {
389                         if (rr->error != NULL) {
390                                 MEM_freeN(rr->error);
391                         }
392                         rr->error = BLI_strdup(msg);
393                 }
394                 RE_ReleaseResult(re);
395         }
396 }
397
398 const char *RE_engine_active_view_get(RenderEngine *engine)
399 {
400         Render *re = engine->re;
401         return RE_GetActiveRenderView(re);
402 }
403
404 void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
405 {
406         Render *re = engine->re;
407         RE_SetActiveRenderView(re, viewname);
408 }
409
410 float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, bool use_spherical_stereo)
411 {
412         Render *re = engine->re;
413
414         /* when using spherical stereo, get camera shift without multiview, leaving stereo to be handled by the engine */
415         if (use_spherical_stereo)
416                 re = NULL;
417
418         return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
419 }
420
421 void RE_engine_get_camera_model_matrix(
422         RenderEngine *engine, Object *camera, bool use_spherical_stereo, float *r_modelmat)
423 {
424         Render *re = engine->re;
425
426         /* when using spherical stereo, get model matrix without multiview, leaving stereo to be handled by the engine */
427         if (use_spherical_stereo)
428                 re = NULL;
429
430         BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
431 }
432
433 bool RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
434 {
435         Render *re = engine->re;
436         return BKE_camera_multiview_spherical_stereo(re ? &re->r : NULL, camera) ? 1 : 0;
437 }
438
439 rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
440 {
441         static rcti tiles_static[BLENDER_MAX_THREADS];
442         const int allocation_step = BLENDER_MAX_THREADS;
443         RenderPart *pa;
444         int total_tiles = 0;
445         rcti *tiles = tiles_static;
446         int allocation_size = BLENDER_MAX_THREADS;
447
448         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
449
450         *r_needs_free = false;
451
452         if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
453                 *r_total_tiles = 0;
454                 BLI_rw_mutex_unlock(&re->partsmutex);
455                 return NULL;
456         }
457
458         for (pa = re->parts.first; pa; pa = pa->next) {
459                 if (pa->status == PART_STATUS_IN_PROGRESS) {
460                         if (total_tiles >= allocation_size) {
461                                 /* Just in case we're using crazy network rendering with more
462                                  * workers than BLENDER_MAX_THREADS.
463                                  */
464                                 allocation_size += allocation_step;
465                                 if (tiles == tiles_static) {
466                                         /* Can not realloc yet, tiles are pointing to a
467                                          * stack memory.
468                                          */
469                                         tiles = MEM_mallocN(allocation_size * sizeof(rcti), "current engine tiles");
470                                 }
471                                 else {
472                                         tiles = MEM_reallocN(tiles, allocation_size * sizeof(rcti));
473                                 }
474                                 *r_needs_free = true;
475                         }
476                         tiles[total_tiles] = pa->disprect;
477
478                         total_tiles++;
479                 }
480         }
481         BLI_rw_mutex_unlock(&re->partsmutex);
482         *r_total_tiles = total_tiles;
483         return tiles;
484 }
485
486 RenderData *RE_engine_get_render_data(Render *re)
487 {
488         return &re->r;
489 }
490
491 /* Depsgraph */
492 static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
493 {
494         Main *bmain = engine->re->main;
495         Scene *scene = engine->re->scene;
496
497         engine->depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
498         DEG_debug_name_set(engine->depsgraph, "RENDER");
499
500         BKE_scene_graph_update_for_newframe(engine->depsgraph, bmain);
501 }
502
503 static void engine_depsgraph_free(RenderEngine *engine)
504 {
505         DEG_graph_free(engine->depsgraph);
506
507         engine->depsgraph = NULL;
508 }
509
510 void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
511 {
512         if(!engine->depsgraph) {
513                 return;
514         }
515
516 #ifdef WITH_PYTHON
517         BPy_BEGIN_ALLOW_THREADS;
518 #endif
519
520         Render *re = engine->re;
521         double cfra = (double)frame + (double)subframe;
522
523         CLAMP(cfra, MINAFRAME, MAXFRAME);
524         BKE_scene_frame_set(re->scene, cfra);
525         BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main);
526
527         BKE_scene_camera_switch_update(re->scene);
528
529 #ifdef WITH_PYTHON
530         BPy_END_ALLOW_THREADS;
531 #endif
532 }
533
534 /* Bake */
535 void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
536 {
537         re->scene = scene;
538         re->main = bmain;
539         render_copy_renderdata(&re->r, &scene->r);
540 }
541
542 bool RE_bake_has_engine(Render *re)
543 {
544         RenderEngineType *type = RE_engines_find(re->r.engine);
545         return (type->bake != NULL);
546 }
547
548 bool RE_bake_engine(
549         Render *re, Depsgraph *depsgraph, Object *object,
550         const int object_id, const BakePixel pixel_array[],
551         const size_t num_pixels, const int depth,
552         const eScenePassType pass_type, const int pass_filter,
553         float result[])
554 {
555         RenderEngineType *type = RE_engines_find(re->r.engine);
556         RenderEngine *engine;
557         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
558
559         /* set render info */
560         re->i.cfra = re->scene->r.cfra;
561         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
562         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
563
564         /* render */
565         engine = re->engine;
566
567         if (!engine) {
568                 engine = RE_engine_create(type);
569                 re->engine = engine;
570         }
571
572         engine->flag |= RE_ENGINE_RENDERING;
573
574         /* TODO: actually link to a parent which shouldn't happen */
575         engine->re = re;
576
577         engine->resolution_x = re->winx;
578         engine->resolution_y = re->winy;
579
580         RE_parts_init(re);
581         engine->tile_x = re->r.tilex;
582         engine->tile_y = re->r.tiley;
583
584         if (type->bake) {
585                 engine->depsgraph = depsgraph;
586
587                 /* update is only called so we create the engine.session */
588                 if (type->update)
589                         type->update(engine, re->main, engine->depsgraph);
590
591                 type->bake(engine,
592                            engine->depsgraph,
593                            object,
594                            pass_type,
595                            pass_filter,
596                            object_id,
597                            pixel_array,
598                            num_pixels,
599                            depth,
600                            result);
601
602                 engine->depsgraph = NULL;
603         }
604
605         engine->tile_x = 0;
606         engine->tile_y = 0;
607         engine->flag &= ~RE_ENGINE_RENDERING;
608
609         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
610
611         /* re->engine becomes zero if user changed active render engine during render */
612         if (!persistent_data || !re->engine) {
613                 RE_engine_free(engine);
614                 re->engine = NULL;
615         }
616
617         RE_parts_free(re);
618         BLI_rw_mutex_unlock(&re->partsmutex);
619
620         if (BKE_reports_contain(re->reports, RPT_ERROR))
621                 G.is_break = true;
622
623         return true;
624 }
625
626 /* Render */
627
628 int RE_engine_render(Render *re, int do_all)
629 {
630         RenderEngineType *type = RE_engines_find(re->r.engine);
631         RenderEngine *engine;
632         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
633
634         /* verify if we can render */
635         if (!type->render)
636                 return 0;
637         if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
638                 return 0;
639         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
640                 return 0;
641         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
642                 return 0;
643
644         /* Lock drawing in UI during data phase. */
645         if (re->draw_lock) {
646                 re->draw_lock(re->dlh, 1);
647         }
648
649         /* update animation here so any render layer animation is applied before
650          * creating the render result */
651         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
652                 render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
653         }
654
655         /* create render result */
656         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
657         if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
658                 int savebuffers = RR_USE_MEM;
659
660                 if (re->result)
661                         render_result_free(re->result);
662
663                 if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
664                         savebuffers = RR_USE_EXR;
665                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
666         }
667         BLI_rw_mutex_unlock(&re->resultmutex);
668
669         if (re->result == NULL) {
670                 /* Clear UI drawing locks. */
671                 if (re->draw_lock) {
672                         re->draw_lock(re->dlh, 0);
673                 }
674                 /* Too small image is handled earlier, here it could only happen if
675                  * there was no sufficient memory to allocate all passes.
676                  */
677                 BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
678                 G.is_break = true;
679                 return 1;
680         }
681
682         /* set render info */
683         re->i.cfra = re->scene->r.cfra;
684         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
685         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
686
687         /* render */
688         engine = re->engine;
689
690         if (!engine) {
691                 engine = RE_engine_create(type);
692                 re->engine = engine;
693         }
694
695         engine->flag |= RE_ENGINE_RENDERING;
696
697         /* TODO: actually link to a parent which shouldn't happen */
698         engine->re = re;
699
700         if (re->flag & R_ANIMATION)
701                 engine->flag |= RE_ENGINE_ANIMATION;
702         if (re->r.scemode & R_BUTS_PREVIEW)
703                 engine->flag |= RE_ENGINE_PREVIEW;
704         engine->camera_override = re->camera_override;
705
706         engine->resolution_x = re->winx;
707         engine->resolution_y = re->winy;
708
709         RE_parts_init(re);
710         engine->tile_x = re->partx;
711         engine->tile_y = re->party;
712
713         if (re->result->do_exr_tile)
714                 render_result_exr_file_begin(re);
715
716         /* Clear UI drawing locks. */
717         if (re->draw_lock) {
718                 re->draw_lock(re->dlh, 0);
719         }
720
721         if (type->render) {
722                 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re, view_layer_iter)
723                 {
724                         if (re->draw_lock) {
725                                 re->draw_lock(re->dlh, 1);
726                         }
727
728                         ViewLayer *view_layer = BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name));
729                         engine_depsgraph_init(engine, view_layer);
730
731                         if (type->update) {
732                                 type->update(engine, re->main, engine->depsgraph);
733                         }
734
735                         if (re->draw_lock) {
736                                 re->draw_lock(re->dlh, 0);
737                         }
738
739                         type->render(engine, engine->depsgraph);
740
741                         /* Grease pencil render over previous render result.
742                          *
743                          * NOTE: External engine might have been requested to free its
744                          * dependency graph, which is only allowed if there is no grease
745                          * pencil (pipeline is taking care of that).
746                          */
747                         if (!RE_engine_test_break(engine) && engine->depsgraph != NULL) {
748                                 DRW_render_gpencil(engine, engine->depsgraph);
749                         }
750
751                         engine_depsgraph_free(engine);
752
753                         if (RE_engine_test_break(engine)) {
754                                 break;
755                         }
756                 }
757                 FOREACH_VIEW_LAYER_TO_RENDER_END;
758         }
759
760         engine->tile_x = 0;
761         engine->tile_y = 0;
762         engine->flag &= ~RE_ENGINE_RENDERING;
763
764         render_result_free_list(&engine->fullresult, engine->fullresult.first);
765
766         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
767
768         /* re->engine becomes zero if user changed active render engine during render */
769         if (!persistent_data || !re->engine) {
770                 RE_engine_free(engine);
771                 re->engine = NULL;
772         }
773
774         if (re->result->do_exr_tile) {
775                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
776                 render_result_save_empty_result_tiles(re);
777                 render_result_exr_file_end(re);
778                 BLI_rw_mutex_unlock(&re->resultmutex);
779         }
780
781         if (re->r.scemode & R_EXR_CACHE_FILE) {
782                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
783                 render_result_exr_file_cache_write(re);
784                 BLI_rw_mutex_unlock(&re->resultmutex);
785         }
786
787         RE_parts_free(re);
788         BLI_rw_mutex_unlock(&re->partsmutex);
789
790         if (BKE_reports_contain(re->reports, RPT_ERROR))
791                 G.is_break = true;
792
793 #ifdef WITH_FREESTYLE
794         if (re->r.mode & R_EDGE_FRS)
795                 RE_RenderFreestyleExternal(re);
796 #endif
797
798         return 1;
799 }
800
801 void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
802                              const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
803 {
804         /* The channel information is currently not used, but is part of the API in case it's needed in the future. */
805
806         if (!(scene && view_layer && engine)) {
807                 return;
808         }
809
810         /* Register the pass in all scenes that have a render layer node for this layer.
811          * Since multiple scenes can be used in the compositor, the code must loop over all scenes
812          * and check whether their nodetree has a node that needs to be updated. */
813         /* NOTE: using G_MAIN seems valid here,
814          * unless we want to register that for every other temp Main we could generate??? */
815         ntreeCompositRegisterPass(scene->nodetree, scene, view_layer, name, type);
816
817         for (Scene *sce = G_MAIN->scene.first; sce; sce = sce->id.next) {
818                 if (sce->nodetree && sce != scene) {
819                         ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type);
820                 }
821         }
822 }
823
824 void RE_engine_free_blender_memory(RenderEngine *engine)
825 {
826         /* Weak way to save memory, but not crash grease pencil.
827          *
828          * TODO(sergey): Find better solution for this.
829          * TODO(sergey): Try to find solution which does not involve looping over
830          * all the objects.
831          */
832         if (DRW_render_check_grease_pencil(engine->depsgraph)) {
833                 return;
834         }
835         DEG_graph_free(engine->depsgraph);
836         engine->depsgraph = NULL;
837 }