827a1f8f1134ae5afa8e4715a36b4ba87666edc9
[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 "BLF_translation.h"
40
41 #include "BLI_listbase.h"
42 #include "BLI_string.h"
43 #include "BLI_utildefines.h"
44
45 #include "BKE_global.h"
46 #include "BKE_report.h"
47 #include "BKE_scene.h"
48
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51
52 #include "RNA_access.h"
53
54 #ifdef WITH_PYTHON
55 #include "BPY_extern.h"
56 #endif
57
58 #include "RE_engine.h"
59 #include "RE_pipeline.h"
60
61 #include "initrender.h"
62 #include "render_types.h"
63 #include "render_result.h"
64
65 /* Render Engine Types */
66
67 static RenderEngineType internal_render_type = {
68         NULL, NULL,
69         "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
70         NULL, NULL, NULL, NULL, NULL,
71         {NULL, NULL, NULL}
72 };
73
74 #ifdef WITH_GAMEENGINE
75
76 static RenderEngineType internal_game_type = {
77         NULL, NULL,
78         "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
79         NULL, NULL, NULL, NULL, NULL,
80         {NULL, NULL, NULL}
81 };
82
83 #endif
84
85 ListBase R_engines = {NULL, NULL};
86
87 void RE_engines_init(void)
88 {
89         BLI_addtail(&R_engines, &internal_render_type);
90 #ifdef WITH_GAMEENGINE
91         BLI_addtail(&R_engines, &internal_game_type);
92 #endif
93 }
94
95 void RE_engines_exit(void)
96 {
97         RenderEngineType *type, *next;
98
99         for (type = R_engines.first; type; type = next) {
100                 next = type->next;
101
102                 BLI_remlink(&R_engines, type);
103
104                 if (!(type->flag & RE_INTERNAL)) {
105                         if (type->ext.free)
106                                 type->ext.free(type->ext.data);
107
108                         MEM_freeN(type);
109                 }
110         }
111 }
112
113 RenderEngineType *RE_engines_find(const char *idname)
114 {
115         RenderEngineType *type;
116         
117         type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
118         if (!type)
119                 type = &internal_render_type;
120         
121         return type;
122 }
123
124 int RE_engine_is_external(Render *re)
125 {
126         RenderEngineType *type = RE_engines_find(re->r.engine);
127         return (type && type->render);
128 }
129
130 /* Create, Free */
131
132 RenderEngine *RE_engine_create(RenderEngineType *type)
133 {
134         return RE_engine_create_ex(type, FALSE);
135 }
136
137 RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
138 {
139         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
140         engine->type = type;
141
142         if (use_for_viewport) {
143                 engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
144
145                 BLI_begin_threaded_malloc();
146         }
147
148         return engine;
149 }
150
151 void RE_engine_free(RenderEngine *engine)
152 {
153 #ifdef WITH_PYTHON
154         if (engine->py_instance) {
155                 BPY_DECREF_RNA_INVALIDATE(engine->py_instance);
156         }
157 #endif
158
159         if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
160                 BLI_end_threaded_malloc();
161         }
162
163         MEM_freeN(engine);
164 }
165
166 /* Render Results */
167
168 static RenderPart *get_part_from_result(Render *re, RenderResult *result)
169 {
170         RenderPart *pa;
171
172         for (pa = re->parts.first; pa; pa = pa->next) {
173                 if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
174                     result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
175                     result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
176                     result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
177                 {
178                         return pa;
179                 }
180         }
181
182         return NULL;
183 }
184
185 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
186 {
187         Render *re = engine->re;
188         RenderResult *result;
189         rcti disprect;
190
191         /* ensure the coordinates are within the right limits */
192         CLAMP(x, 0, re->result->rectx);
193         CLAMP(y, 0, re->result->recty);
194         CLAMP(w, 0, re->result->rectx);
195         CLAMP(h, 0, re->result->recty);
196
197         if (x + w > re->result->rectx)
198                 w = re->result->rectx - x;
199         if (y + h > re->result->recty)
200                 h = re->result->recty - y;
201
202         /* allocate a render result */
203         disprect.xmin = x;
204         disprect.xmax = x + w;
205         disprect.ymin = y;
206         disprect.ymax = y + h;
207
208         result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername);
209
210         /* todo: make this thread safe */
211
212         /* can be NULL if we CLAMP the width or height to 0 */
213         if (result) {
214                 RenderPart *pa;
215
216                 BLI_addtail(&engine->fullresult, result);
217
218                 result->tilerect.xmin += re->disprect.xmin;
219                 result->tilerect.xmax += re->disprect.xmin;
220                 result->tilerect.ymin += re->disprect.ymin;
221                 result->tilerect.ymax += re->disprect.ymin;
222
223                 pa = get_part_from_result(re, result);
224
225                 if (pa)
226                         pa->status = PART_STATUS_IN_PROGRESS;
227         }
228
229         return result;
230 }
231
232 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
233 {
234         Render *re = engine->re;
235
236         if (result) {
237                 result->renlay = result->layers.first; /* weak, draws first layer always */
238                 re->display_draw(re->ddh, result, NULL);
239         }
240 }
241
242 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
243 {
244         Render *re = engine->re;
245
246         if (!result) {
247                 return;
248         }
249
250         /* merge. on break, don't merge in result for preview renders, looks nicer */
251         if (!cancel) {
252                 /* for exr tile render, detect tiles that are done */
253                 RenderPart *pa = get_part_from_result(re, result);
254
255                 if (pa) {
256                         pa->status = PART_STATUS_READY;
257                 }
258                 else if (re->result->do_exr_tile) {
259                         /* if written result does not match any tile and we are using save
260                          * buffers, we are going to get openexr save errors */
261                         fprintf(stderr, "RenderEngine.end_result: dimensions do not match any OpenEXR tile.\n");
262                 }
263
264                 if (re->result->do_exr_tile)
265                         render_result_exr_file_merge(re->result, result);
266                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
267                         render_result_merge(re->result, result);
268
269                 /* draw */
270                 if (!re->test_break(re->tbh)) {
271                         result->renlay = result->layers.first; /* weak, draws first layer always */
272                         re->display_draw(re->ddh, result, NULL);
273                 }
274         }
275
276         /* free */
277         BLI_remlink(&engine->fullresult, result);
278         render_result_free(result);
279 }
280
281 /* Cancel */
282
283 int RE_engine_test_break(RenderEngine *engine)
284 {
285         Render *re = engine->re;
286
287         if (re)
288                 return re->test_break(re->tbh);
289         
290         return 0;
291 }
292
293 /* Statistics */
294
295 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
296 {
297         Render *re = engine->re;
298
299         /* stats draw callback */
300         if (re) {
301                 re->i.statstr = stats;
302                 re->i.infostr = info;
303                 re->stats_draw(re->sdh, &re->i);
304                 re->i.infostr = NULL;
305                 re->i.statstr = NULL;
306         }
307
308         /* set engine text */
309         engine->text[0] = '\0';
310
311         if (stats && stats[0] && info && info[0])
312                 BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
313         else if (info && info[0])
314                 BLI_strncpy(engine->text, info, sizeof(engine->text));
315         else if (stats && stats[0])
316                 BLI_strncpy(engine->text, stats, sizeof(engine->text));
317 }
318
319 void RE_engine_update_progress(RenderEngine *engine, float progress)
320 {
321         Render *re = engine->re;
322
323         if (re) {
324                 CLAMP(progress, 0.0f, 1.0f);
325                 re->progress(re->prh, progress);
326         }
327 }
328
329 void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
330 {
331         Render *re = engine->re;
332
333         if (re) {
334                 re->i.mem_used = mem_used;
335                 re->i.mem_peak = mem_peak;
336         }
337 }
338
339 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
340 {
341         Render *re = engine->re;
342
343         if (re)
344                 BKE_report(engine->re->reports, type, msg);
345         else if (engine->reports)
346                 BKE_report(engine->reports, type, msg);
347 }
348
349 void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
350 {
351         RenderPart *pa;
352         int total_tiles = 0;
353         rcti *tiles = NULL;
354         int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
355
356         if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
357                 *total_tiles_r = 0;
358                 *tiles_r = NULL;
359                 return;
360         }
361
362         for (pa = re->parts.first; pa; pa = pa->next) {
363                 if (pa->status == PART_STATUS_IN_PROGRESS) {
364                         if (total_tiles >= allocation_size) {
365                                 if (tiles == NULL)
366                                         tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
367                                 else
368                                         tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));
369
370                                 allocation_size += allocation_step;
371                         }
372
373                         tiles[total_tiles] = pa->disprect;
374
375                         if (pa->crop) {
376                                 tiles[total_tiles].xmin += pa->crop;
377                                 tiles[total_tiles].ymin += pa->crop;
378                                 tiles[total_tiles].xmax -= pa->crop;
379                                 tiles[total_tiles].ymax -= pa->crop;
380                         }
381
382                         total_tiles++;
383                 }
384         }
385
386         *total_tiles_r = total_tiles;
387         *tiles_r = tiles;
388 }
389
390 RenderData *RE_engine_get_render_data(Render *re)
391 {
392         return &re->r;
393 }
394
395 /* Render */
396
397 static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
398 {
399         PointerRNA ptr;
400         PropertyRNA *prop;
401
402         RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
403         prop = RNA_struct_find_property(&ptr, "layers_exclude");
404
405         return RNA_property_animated(&ptr, prop);
406 }
407
408 int RE_engine_render(Render *re, int do_all)
409 {
410         RenderEngineType *type = RE_engines_find(re->r.engine);
411         RenderEngine *engine;
412         int persistent_data = re->r.mode & R_PERSISTENT_DATA;
413
414         /* verify if we can render */
415         if (!type->render)
416                 return 0;
417         if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
418                 return 0;
419         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
420                 return 0;
421         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
422                 return 0;
423
424         /* update animation here so any render layer animation is applied before
425          * creating the render result */
426         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
427                 unsigned int lay = re->lay;
428
429                 /* don't update layers excluded on all render layers */
430                 if (type->flag & RE_USE_EXCLUDE_LAYERS) {
431                         SceneRenderLayer *srl;
432                         unsigned int non_excluded_lay = 0;
433
434                         if (re->r.scemode & R_SINGLE_LAYER) {
435                                 srl = BLI_findlink(&re->r.layers, re->r.actlay);
436                                 if (srl) {
437                                         non_excluded_lay |= ~srl->lay_exclude;
438
439                                         /* in this case we must update all because animation for
440                                          * the scene has not been updated yet, and so may not be
441                                          * up to date until after BKE_scene_update_for_newframe */
442                                         if (render_layer_exclude_animated(re->scene, srl))
443                                                 non_excluded_lay |= ~0;
444                                 }
445                         }
446                         else {
447                                 for (srl = re->r.layers.first; srl; srl = srl->next) {
448                                         if (!(srl->layflag & SCE_LAY_DISABLE)) {
449                                                 non_excluded_lay |= ~srl->lay_exclude;
450
451                                                 if (render_layer_exclude_animated(re->scene, srl))
452                                                         non_excluded_lay |= ~0;
453                                         }
454                                 }
455                         }
456
457                         lay &= non_excluded_lay;
458                 }
459
460                 BKE_scene_update_for_newframe(re->main, re->scene, lay);
461         }
462
463         /* create render result */
464         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
465         if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
466                 int savebuffers = RR_USE_MEM;
467
468                 if (re->result)
469                         render_result_free(re->result);
470
471                 if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
472                         savebuffers = RR_USE_EXR;
473                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
474         }
475         BLI_rw_mutex_unlock(&re->resultmutex);
476
477         if (re->result == NULL)
478                 return 1;
479
480         /* set render info */
481         re->i.cfra = re->scene->r.cfra;
482         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
483         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
484
485         /* render */
486         engine = re->engine;
487
488         if (!engine) {
489                 engine = RE_engine_create(type);
490                 re->engine = engine;
491         }
492
493         engine->flag |= RE_ENGINE_RENDERING;
494
495         /* TODO: actually link to a parent which shouldn't happen */
496         engine->re = re;
497
498         if (re->flag & R_ANIMATION)
499                 engine->flag |= RE_ENGINE_ANIMATION;
500         if (re->r.scemode & R_BUTS_PREVIEW)
501                 engine->flag |= RE_ENGINE_PREVIEW;
502         engine->camera_override = re->camera_override;
503
504         engine->resolution_x = re->winx;
505         engine->resolution_y = re->winy;
506
507         RE_parts_init(re, FALSE);
508         engine->tile_x = re->partx;
509         engine->tile_y = re->party;
510
511         if (re->result->do_exr_tile)
512                 render_result_exr_file_begin(re);
513
514         if (type->update)
515                 type->update(engine, re->main, re->scene);
516         
517         if (type->render)
518                 type->render(engine, re->scene);
519
520         engine->tile_x = 0;
521         engine->tile_y = 0;
522         engine->flag &= ~RE_ENGINE_RENDERING;
523
524         render_result_free_list(&engine->fullresult, engine->fullresult.first);
525
526         /* re->engine becomes zero if user changed active render engine during render */
527         if (!persistent_data || !re->engine) {
528                 RE_engine_free(engine);
529                 re->engine = NULL;
530         }
531
532         if (re->result->do_exr_tile) {
533                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
534                 render_result_exr_file_end(re);
535                 BLI_rw_mutex_unlock(&re->resultmutex);
536         }
537
538         RE_parts_free(re);
539
540         if (BKE_reports_contain(re->reports, RPT_ERROR))
541                 G.is_break = TRUE;
542         
543         return 1;
544 }
545