Changes to partial update during rendering
[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_update(re->duh, result, NULL);
239         }
240 }
241
242 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int merge_results)
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
265         if (!cancel || merge_results) {
266                 if (re->result->do_exr_tile)
267                         render_result_exr_file_merge(re->result, result);
268                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_BUTS_PREVIEW)))
269                         render_result_merge(re->result, result);
270
271                 /* draw */
272                 if (!re->test_break(re->tbh)) {
273                         result->renlay = result->layers.first; /* weak, draws first layer always */
274                         re->display_update(re->duh, result, NULL);
275                 }
276         }
277
278         /* free */
279         BLI_remlink(&engine->fullresult, result);
280         render_result_free(result);
281 }
282
283 /* Cancel */
284
285 int RE_engine_test_break(RenderEngine *engine)
286 {
287         Render *re = engine->re;
288
289         if (re)
290                 return re->test_break(re->tbh);
291         
292         return 0;
293 }
294
295 /* Statistics */
296
297 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
298 {
299         Render *re = engine->re;
300
301         /* stats draw callback */
302         if (re) {
303                 re->i.statstr = stats;
304                 re->i.infostr = info;
305                 re->stats_draw(re->sdh, &re->i);
306                 re->i.infostr = NULL;
307                 re->i.statstr = NULL;
308         }
309
310         /* set engine text */
311         engine->text[0] = '\0';
312
313         if (stats && stats[0] && info && info[0])
314                 BLI_snprintf(engine->text, sizeof(engine->text), "%s | %s", stats, info);
315         else if (info && info[0])
316                 BLI_strncpy(engine->text, info, sizeof(engine->text));
317         else if (stats && stats[0])
318                 BLI_strncpy(engine->text, stats, sizeof(engine->text));
319 }
320
321 void RE_engine_update_progress(RenderEngine *engine, float progress)
322 {
323         Render *re = engine->re;
324
325         if (re) {
326                 CLAMP(progress, 0.0f, 1.0f);
327                 re->progress(re->prh, progress);
328         }
329 }
330
331 void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
332 {
333         Render *re = engine->re;
334
335         if (re) {
336                 re->i.mem_used = mem_used;
337                 re->i.mem_peak = mem_peak;
338         }
339 }
340
341 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
342 {
343         Render *re = engine->re;
344
345         if (re)
346                 BKE_report(engine->re->reports, type, msg);
347         else if (engine->reports)
348                 BKE_report(engine->reports, type, msg);
349 }
350
351 void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r)
352 {
353         RenderPart *pa;
354         int total_tiles = 0;
355         rcti *tiles = NULL;
356         int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
357
358         if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
359                 *total_tiles_r = 0;
360                 *tiles_r = NULL;
361                 return;
362         }
363
364         for (pa = re->parts.first; pa; pa = pa->next) {
365                 if (pa->status == PART_STATUS_IN_PROGRESS) {
366                         if (total_tiles >= allocation_size) {
367                                 if (tiles == NULL)
368                                         tiles = MEM_mallocN(allocation_step * sizeof(rcti), "current engine tiles");
369                                 else
370                                         tiles = MEM_reallocN(tiles, (total_tiles + allocation_step) * sizeof(rcti));
371
372                                 allocation_size += allocation_step;
373                         }
374
375                         tiles[total_tiles] = pa->disprect;
376
377                         if (pa->crop) {
378                                 tiles[total_tiles].xmin += pa->crop;
379                                 tiles[total_tiles].ymin += pa->crop;
380                                 tiles[total_tiles].xmax -= pa->crop;
381                                 tiles[total_tiles].ymax -= pa->crop;
382                         }
383
384                         total_tiles++;
385                 }
386         }
387
388         *total_tiles_r = total_tiles;
389         *tiles_r = tiles;
390 }
391
392 RenderData *RE_engine_get_render_data(Render *re)
393 {
394         return &re->r;
395 }
396
397 /* Render */
398
399 static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
400 {
401         PointerRNA ptr;
402         PropertyRNA *prop;
403
404         RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
405         prop = RNA_struct_find_property(&ptr, "layers_exclude");
406
407         return RNA_property_animated(&ptr, prop);
408 }
409
410 int RE_engine_render(Render *re, int do_all)
411 {
412         RenderEngineType *type = RE_engines_find(re->r.engine);
413         RenderEngine *engine;
414         int persistent_data = re->r.mode & R_PERSISTENT_DATA;
415
416         /* verify if we can render */
417         if (!type->render)
418                 return 0;
419         if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
420                 return 0;
421         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
422                 return 0;
423         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
424                 return 0;
425
426         /* update animation here so any render layer animation is applied before
427          * creating the render result */
428         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
429                 unsigned int lay = re->lay;
430
431                 /* don't update layers excluded on all render layers */
432                 if (type->flag & RE_USE_EXCLUDE_LAYERS) {
433                         SceneRenderLayer *srl;
434                         unsigned int non_excluded_lay = 0;
435
436                         if (re->r.scemode & R_SINGLE_LAYER) {
437                                 srl = BLI_findlink(&re->r.layers, re->r.actlay);
438                                 if (srl) {
439                                         non_excluded_lay |= ~srl->lay_exclude;
440
441                                         /* in this case we must update all because animation for
442                                          * the scene has not been updated yet, and so may not be
443                                          * up to date until after BKE_scene_update_for_newframe */
444                                         if (render_layer_exclude_animated(re->scene, srl))
445                                                 non_excluded_lay |= ~0;
446                                 }
447                         }
448                         else {
449                                 for (srl = re->r.layers.first; srl; srl = srl->next) {
450                                         if (!(srl->layflag & SCE_LAY_DISABLE)) {
451                                                 non_excluded_lay |= ~srl->lay_exclude;
452
453                                                 if (render_layer_exclude_animated(re->scene, srl))
454                                                         non_excluded_lay |= ~0;
455                                         }
456                                 }
457                         }
458
459                         lay &= non_excluded_lay;
460                 }
461
462                 BKE_scene_update_for_newframe(re->main, re->scene, lay);
463         }
464
465         /* create render result */
466         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
467         if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) {
468                 int savebuffers = RR_USE_MEM;
469
470                 if (re->result)
471                         render_result_free(re->result);
472
473                 if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE))
474                         savebuffers = RR_USE_EXR;
475                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
476         }
477         BLI_rw_mutex_unlock(&re->resultmutex);
478
479         if (re->result == NULL)
480                 return 1;
481
482         /* set render info */
483         re->i.cfra = re->scene->r.cfra;
484         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
485         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
486
487         /* render */
488         engine = re->engine;
489
490         if (!engine) {
491                 engine = RE_engine_create(type);
492                 re->engine = engine;
493         }
494
495         engine->flag |= RE_ENGINE_RENDERING;
496
497         /* TODO: actually link to a parent which shouldn't happen */
498         engine->re = re;
499
500         if (re->flag & R_ANIMATION)
501                 engine->flag |= RE_ENGINE_ANIMATION;
502         if (re->r.scemode & R_BUTS_PREVIEW)
503                 engine->flag |= RE_ENGINE_PREVIEW;
504         engine->camera_override = re->camera_override;
505
506         engine->resolution_x = re->winx;
507         engine->resolution_y = re->winy;
508
509         RE_parts_init(re, FALSE);
510         engine->tile_x = re->partx;
511         engine->tile_y = re->party;
512
513         if (re->result->do_exr_tile)
514                 render_result_exr_file_begin(re);
515
516         if (type->update)
517                 type->update(engine, re->main, re->scene);
518         
519         if (type->render)
520                 type->render(engine, re->scene);
521
522         engine->tile_x = 0;
523         engine->tile_y = 0;
524         engine->flag &= ~RE_ENGINE_RENDERING;
525
526         render_result_free_list(&engine->fullresult, engine->fullresult.first);
527
528         /* re->engine becomes zero if user changed active render engine during render */
529         if (!persistent_data || !re->engine) {
530                 RE_engine_free(engine);
531                 re->engine = NULL;
532         }
533
534         if (re->result->do_exr_tile) {
535                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
536                 render_result_exr_file_end(re);
537                 BLI_rw_mutex_unlock(&re->resultmutex);
538         }
539
540         RE_parts_free(re);
541
542         if (BKE_reports_contain(re->reports, RPT_ERROR))
543                 G.is_break = TRUE;
544         
545         return 1;
546 }
547