a581f7bd198dc00681ba935300571a0f13b6010f
[blender-staging.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_begin_threaded_malloc();
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_end_threaded_malloc();
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 = PART_STATUS_READY;
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) {
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 /* Cancel */
307
308 int RE_engine_test_break(RenderEngine *engine)
309 {
310         Render *re = engine->re;
311
312         if (re)
313                 return re->test_break(re->tbh);
314         
315         return 0;
316 }
317
318 /* Statistics */
319
320 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
321 {
322         Render *re = engine->re;
323
324         /* stats draw callback */
325         if (re) {
326                 re->i.statstr = stats;
327                 re->i.infostr = info;
328                 re->stats_draw(re->sdh, &re->i);
329                 re->i.infostr = NULL;
330                 re->i.statstr = NULL;
331         }
332
333         /* set engine text */
334         engine->text[0] = '\0';
335
336         if (stats && stats[0] && info && info[0])
337                 BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
338         else if (info && info[0])
339                 BLI_strncpy(engine->text, info, sizeof(engine->text));
340         else if (stats && stats[0])
341                 BLI_strncpy(engine->text, stats, sizeof(engine->text));
342 }
343
344 void RE_engine_update_progress(RenderEngine *engine, float progress)
345 {
346         Render *re = engine->re;
347
348         if (re) {
349                 CLAMP(progress, 0.0f, 1.0f);
350                 re->progress(re->prh, progress);
351         }
352 }
353
354 void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
355 {
356         Render *re = engine->re;
357
358         if (re) {
359                 re->i.mem_used = mem_used;
360                 re->i.mem_peak = mem_peak;
361         }
362 }
363
364 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
365 {
366         Render *re = engine->re;
367
368         if (re)
369                 BKE_report(engine->re->reports, type, msg);
370         else if (engine->reports)
371                 BKE_report(engine->reports, type, msg);
372 }
373
374 void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
375 {
376         Render *re = engine->re;
377         if (re != NULL) {
378                 RenderResult *rr = RE_AcquireResultRead(re);
379                 if (rr) {
380                         if (rr->error != NULL) {
381                                 MEM_freeN(rr->error);
382                         }
383                         rr->error = BLI_strdup(msg);
384                 }
385                 RE_ReleaseResult(re);
386         }
387 }
388
389 const char *RE_engine_active_view_get(RenderEngine *engine)
390 {
391         Render *re = engine->re;
392         return RE_GetActiveRenderView(re);
393 }
394
395 void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
396 {
397         Render *re = engine->re;
398         RE_SetActiveRenderView(re, viewname);
399 }
400
401 float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, int use_spherical_stereo)
402 {
403         Render *re = engine->re;
404
405         /* when using spherical stereo, get camera shift without multiview, leaving stereo to be handled by the engine */
406         if (use_spherical_stereo)
407                 re = NULL;
408
409         return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
410 }
411
412 void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat)
413 {
414         Render *re = engine->re;
415
416         /* when using spherical stereo, get model matrix without multiview, leaving stereo to be handled by the engine */
417         if (use_spherical_stereo)
418                 re = NULL;
419
420         BKE_camera_multiview_model_matrix(re ? &re->r : NULL, camera, re->viewname, (float (*)[4])r_modelmat);
421 }
422
423 int RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
424 {
425         Render *re = engine->re;
426         return BKE_camera_multiview_spherical_stereo(re ? &re->r : NULL, camera) ? 1 : 0;
427 }
428
429 rcti* RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
430 {
431         static rcti tiles_static[BLENDER_MAX_THREADS];
432         const int allocation_step = BLENDER_MAX_THREADS;
433         RenderPart *pa;
434         int total_tiles = 0;
435         rcti *tiles = tiles_static;
436         int allocation_size = BLENDER_MAX_THREADS;
437
438         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_READ);
439
440         *r_needs_free = false;
441
442         if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
443                 *r_total_tiles = 0;
444                 BLI_rw_mutex_unlock(&re->partsmutex);
445                 return NULL;
446         }
447
448         for (pa = re->parts.first; pa; pa = pa->next) {
449                 if (pa->status == PART_STATUS_IN_PROGRESS) {
450                         if (total_tiles >= allocation_size) {
451                                 /* Just in case we're using crazy network rendering with more
452                                  * slaves as BLENDER_MAX_THREADS.
453                                  */
454                                 allocation_size += allocation_step;
455                                 if (tiles == tiles_static) {
456                                         /* Can not realloc yet, tiles are pointing to a
457                                          * stack memory.
458                                          */
459                                         tiles = MEM_mallocN(allocation_size * sizeof(rcti), "current engine tiles");
460                                 }
461                                 else {
462                                         tiles = MEM_reallocN(tiles, allocation_size * sizeof(rcti));
463                                 }
464                                 *r_needs_free = true;
465                         }
466                         tiles[total_tiles] = pa->disprect;
467
468                         if (pa->crop) {
469                                 tiles[total_tiles].xmin += pa->crop;
470                                 tiles[total_tiles].ymin += pa->crop;
471                                 tiles[total_tiles].xmax -= pa->crop;
472                                 tiles[total_tiles].ymax -= pa->crop;
473                         }
474
475                         total_tiles++;
476                 }
477         }
478         BLI_rw_mutex_unlock(&re->partsmutex);
479         *r_total_tiles = total_tiles;
480         return tiles;
481 }
482
483 RenderData *RE_engine_get_render_data(Render *re)
484 {
485         return &re->r;
486 }
487
488 /* Bake */
489 void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
490 {
491         re->scene = scene;
492         re->main = bmain;
493         render_copy_renderdata(&re->r, &scene->r);
494 }
495
496 bool RE_bake_has_engine(Render *re)
497 {
498         RenderEngineType *type = RE_engines_find(re->r.engine);
499         return (type->bake != NULL);
500 }
501
502 bool RE_bake_engine(
503         Render *re, Object *object,
504         const int object_id, const BakePixel pixel_array[],
505         const size_t num_pixels, const int depth,
506         const ScenePassType pass_type, const int pass_filter,
507         float result[])
508 {
509         RenderEngineType *type = RE_engines_find(re->r.engine);
510         RenderEngine *engine;
511         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
512
513         /* set render info */
514         re->i.cfra = re->scene->r.cfra;
515         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
516         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
517
518         /* render */
519         engine = re->engine;
520
521         if (!engine) {
522                 engine = RE_engine_create(type);
523                 re->engine = engine;
524         }
525
526         engine->flag |= RE_ENGINE_RENDERING;
527
528         /* TODO: actually link to a parent which shouldn't happen */
529         engine->re = re;
530
531         engine->resolution_x = re->winx;
532         engine->resolution_y = re->winy;
533
534         RE_parts_init(re, false);
535         engine->tile_x = re->r.tilex;
536         engine->tile_y = re->r.tiley;
537
538         /* update is only called so we create the engine.session */
539         if (type->update)
540                 type->update(engine, re->main, re->scene);
541
542         if (type->bake)
543                 type->bake(engine, re->scene, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result);
544
545         engine->tile_x = 0;
546         engine->tile_y = 0;
547         engine->flag &= ~RE_ENGINE_RENDERING;
548
549         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
550
551         /* re->engine becomes zero if user changed active render engine during render */
552         if (!persistent_data || !re->engine) {
553                 RE_engine_free(engine);
554                 re->engine = NULL;
555         }
556
557         RE_parts_free(re);
558         BLI_rw_mutex_unlock(&re->partsmutex);
559
560         if (BKE_reports_contain(re->reports, RPT_ERROR))
561                 G.is_break = true;
562
563         return true;
564 }
565
566 void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
567 {
568         Render *re = engine->re;
569         Scene *scene = re->scene;
570         double cfra = (double)frame + (double)subframe;
571
572         CLAMP(cfra, MINAFRAME, MAXFRAME);
573         BKE_scene_frame_set(scene, cfra);
574
575 #ifdef WITH_PYTHON
576         BPy_BEGIN_ALLOW_THREADS;
577 #endif
578
579         /* It's possible that here we're including layers which were never visible before. */
580         BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, scene, (1 << 20) - 1, true);
581
582 #ifdef WITH_PYTHON
583         BPy_END_ALLOW_THREADS;
584 #endif
585
586         BKE_scene_camera_switch_update(scene);
587 }
588
589 /* Render */
590
591 static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
592 {
593         PointerRNA ptr;
594         PropertyRNA *prop;
595
596         RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
597         prop = RNA_struct_find_property(&ptr, "layers_exclude");
598
599         return RNA_property_animated(&ptr, prop);
600 }
601
602 int RE_engine_render(Render *re, int do_all)
603 {
604         RenderEngineType *type = RE_engines_find(re->r.engine);
605         RenderEngine *engine;
606         bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
607
608         /* verify if we can render */
609         if (!type->render)
610                 return 0;
611         if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
612                 return 0;
613         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
614                 return 0;
615         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
616                 return 0;
617
618         /* Lock drawing in UI during data phase. */
619         if (re->draw_lock) {
620                 re->draw_lock(re->dlh, 1);
621         }
622
623         /* update animation here so any render layer animation is applied before
624          * creating the render result */
625         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
626                 unsigned int lay = re->lay;
627
628                 /* don't update layers excluded on all render layers */
629                 if (type->flag & RE_USE_EXCLUDE_LAYERS) {
630                         SceneRenderLayer *srl;
631                         unsigned int non_excluded_lay = 0;
632
633                         if (re->r.scemode & R_SINGLE_LAYER) {
634                                 srl = BLI_findlink(&re->r.layers, re->r.actlay);
635                                 if (srl) {
636                                         non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
637
638                                         /* in this case we must update all because animation for
639                                          * the scene has not been updated yet, and so may not be
640                                          * up to date until after BKE_scene_update_for_newframe */
641                                         if (render_layer_exclude_animated(re->scene, srl))
642                                                 non_excluded_lay |= ~0;
643                                 }
644                         }
645                         else {
646                                 for (srl = re->r.layers.first; srl; srl = srl->next) {
647                                         if (!(srl->layflag & SCE_LAY_DISABLE)) {
648                                                 non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
649
650                                                 if (render_layer_exclude_animated(re->scene, srl))
651                                                         non_excluded_lay |= ~0;
652                                         }
653                                 }
654                         }
655
656                         lay &= non_excluded_lay;
657                 }
658
659                 BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true);
660                 render_update_anim_renderdata(re, &re->scene->r);
661         }
662
663         /* create render result */
664         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
665         if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
666                 int savebuffers = RR_USE_MEM;
667
668                 if (re->result)
669                         render_result_free(re->result);
670
671                 if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
672                         savebuffers = RR_USE_EXR;
673                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS);
674         }
675         BLI_rw_mutex_unlock(&re->resultmutex);
676
677         if (re->result == NULL) {
678                 /* Clear UI drawing locks. */
679                 if (re->draw_lock) {
680                         re->draw_lock(re->dlh, 0);
681                 }
682                 /* Too small image is handled earlier, here it could only happen if
683                  * there was no sufficient memory to allocate all passes.
684                  */
685                 BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
686                 G.is_break = true;
687                 return 1;
688         }
689
690         /* set render info */
691         re->i.cfra = re->scene->r.cfra;
692         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
693         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
694
695         /* render */
696         engine = re->engine;
697
698         if (!engine) {
699                 engine = RE_engine_create(type);
700                 re->engine = engine;
701         }
702
703         engine->flag |= RE_ENGINE_RENDERING;
704
705         /* TODO: actually link to a parent which shouldn't happen */
706         engine->re = re;
707
708         if (re->flag & R_ANIMATION)
709                 engine->flag |= RE_ENGINE_ANIMATION;
710         if (re->r.scemode & R_BUTS_PREVIEW)
711                 engine->flag |= RE_ENGINE_PREVIEW;
712         engine->camera_override = re->camera_override;
713         engine->layer_override = re->layer_override;
714
715         engine->resolution_x = re->winx;
716         engine->resolution_y = re->winy;
717
718         RE_parts_init(re, false);
719         engine->tile_x = re->partx;
720         engine->tile_y = re->party;
721
722         if (re->result->do_exr_tile)
723                 render_result_exr_file_begin(re);
724
725         if (type->update)
726                 type->update(engine, re->main, re->scene);
727
728         /* Clear UI drawing locks. */
729         if (re->draw_lock) {
730                 re->draw_lock(re->dlh, 0);
731         }
732
733         if (type->render)
734                 type->render(engine, re->scene);
735
736         engine->tile_x = 0;
737         engine->tile_y = 0;
738         engine->flag &= ~RE_ENGINE_RENDERING;
739
740         render_result_free_list(&engine->fullresult, engine->fullresult.first);
741
742         BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
743
744         /* re->engine becomes zero if user changed active render engine during render */
745         if (!persistent_data || !re->engine) {
746                 RE_engine_free(engine);
747                 re->engine = NULL;
748         }
749
750         if (re->result->do_exr_tile) {
751                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
752                 render_result_save_empty_result_tiles(re);
753                 render_result_exr_file_end(re);
754                 BLI_rw_mutex_unlock(&re->resultmutex);
755         }
756
757         if (re->r.scemode & R_EXR_CACHE_FILE) {
758                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
759                 render_result_exr_file_cache_write(re);
760                 BLI_rw_mutex_unlock(&re->resultmutex);
761         }
762
763         RE_parts_free(re);
764         BLI_rw_mutex_unlock(&re->partsmutex);
765
766         if (BKE_reports_contain(re->reports, RPT_ERROR))
767                 G.is_break = true;
768         
769 #ifdef WITH_FREESTYLE
770         if (re->r.mode & R_EDGE_FRS)
771                 RE_RenderFreestyleExternal(re);
772 #endif
773
774         return 1;
775 }
776
777 void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
778                              const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
779 {
780         /* The channel information is currently not used, but is part of the API in case it's needed in the future. */
781
782         if (!(scene && srl && engine)) {
783                 return;
784         }
785
786         /* Register the pass in all scenes that have a render layer node for this layer.
787          * Since multiple scenes can be used in the compositor, the code must loop over all scenes
788          * and check whether their nodetree has a node that needs to be updated. */
789         Scene *sce;
790         for (sce = G.main->scene.first; sce; sce = sce->id.next) {
791                 if (sce->nodetree) {
792                         ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type);
793                 }
794         }
795 }