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