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