Cycles: merge of changes from tomato branch.
[blender-staging.git] / source / blender / render / intern / source / external_engine.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/render/intern/source/external_engine.c
29  *  \ingroup render
30  */
31
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLF_translation.h"
39
40 #include "BLI_listbase.h"
41 #include "BLI_string.h"
42 #include "BLI_utildefines.h"
43
44 #include "BKE_global.h"
45 #include "BKE_report.h"
46 #include "BKE_scene.h"
47
48 #include "IMB_imbuf.h"
49 #include "IMB_imbuf_types.h"
50
51 #ifdef WITH_PYTHON
52 #include "BPY_extern.h"
53 #endif
54
55 #include "RE_engine.h"
56 #include "RE_pipeline.h"
57
58 #include "initrender.h"
59 #include "render_types.h"
60 #include "render_result.h"
61
62 /* Render Engine Types */
63
64 static RenderEngineType internal_render_type = {
65         NULL, NULL,
66         "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
67         NULL, NULL, NULL, NULL,
68         {NULL, NULL, NULL}
69 };
70
71 #ifdef WITH_GAMEENGINE
72
73 static RenderEngineType internal_game_type = {
74         NULL, NULL,
75         "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
76         NULL, NULL, NULL, NULL,
77         {NULL, NULL, NULL}
78 };
79
80 #endif
81
82 ListBase R_engines = {NULL, NULL};
83
84 void RE_engines_init(void)
85 {
86         BLI_addtail(&R_engines, &internal_render_type);
87 #ifdef WITH_GAMEENGINE
88         BLI_addtail(&R_engines, &internal_game_type);
89 #endif
90 }
91
92 void RE_engines_exit(void)
93 {
94         RenderEngineType *type, *next;
95
96         for (type = R_engines.first; type; type = next) {
97                 next = type->next;
98
99                 BLI_remlink(&R_engines, type);
100
101                 if (!(type->flag & RE_INTERNAL)) {
102                         if (type->ext.free)
103                                 type->ext.free(type->ext.data);
104
105                         MEM_freeN(type);
106                 }
107         }
108 }
109
110 RenderEngineType *RE_engines_find(const char *idname)
111 {
112         RenderEngineType *type;
113         
114         type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
115         if (!type)
116                 type = &internal_render_type;
117
118         return type;
119 }
120
121 int RE_engine_is_external(Render *re)
122 {
123         RenderEngineType *type = RE_engines_find(re->r.engine);
124         return (type && type->render);
125 }
126
127 /* Create, Free */
128
129 RenderEngine *RE_engine_create(RenderEngineType *type)
130 {
131         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
132         engine->type = type;
133
134         return engine;
135 }
136
137 void RE_engine_free(RenderEngine *engine)
138 {
139 #ifdef WITH_PYTHON
140         if (engine->py_instance) {
141                 BPY_DECREF(engine->py_instance);
142         }
143 #endif
144
145         if (engine->text)
146                 MEM_freeN(engine->text);
147
148         MEM_freeN(engine);
149 }
150
151 /* Render Results */
152
153 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
154 {
155         Render *re = engine->re;
156         RenderResult *result;
157         rcti disprect;
158
159         /* ensure the coordinates are within the right limits */
160         CLAMP(x, 0, re->result->rectx);
161         CLAMP(y, 0, re->result->recty);
162         CLAMP(w, 0, re->result->rectx);
163         CLAMP(h, 0, re->result->recty);
164
165         if (x + w > re->result->rectx)
166                 w = re->result->rectx - x;
167         if (y + h > re->result->recty)
168                 h = re->result->recty - y;
169
170         /* allocate a render result */
171         disprect.xmin = x;
172         disprect.xmax = x + w;
173         disprect.ymin = y;
174         disprect.ymax = y + h;
175
176         result = render_result_new(re, &disprect, 0, RR_USE_MEM, layername);
177
178         /* todo: make this thread safe */
179
180         /* can be NULL if we CLAMP the width or height to 0 */
181         if (result) {
182                 BLI_addtail(&engine->fullresult, result);
183
184                 result->tilerect.xmin += re->disprect.xmin;
185                 result->tilerect.xmax += re->disprect.xmin;
186                 result->tilerect.ymin += re->disprect.ymin;
187                 result->tilerect.ymax += re->disprect.ymin;
188         }
189
190         return result;
191 }
192
193 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
194 {
195         Render *re = engine->re;
196
197         if (result) {
198                 result->renlay = result->layers.first; /* weak, draws first layer always */
199                 re->display_draw(re->ddh, result, NULL);
200         }
201 }
202
203 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
204 {
205         Render *re = engine->re;
206         RenderPart *pa;
207
208         if (!result)
209                 return;
210
211         /* merge. on break, don't merge in result for preview renders, looks nicer */
212         if (!cancel) {
213                 /* for exr tile render, detect tiles that are done */
214                 for (pa = re->parts.first; pa; pa = pa->next) {
215                         if (result->tilerect.xmin == pa->disprect.xmin &&
216                            result->tilerect.ymin == pa->disprect.ymin &&
217                            result->tilerect.xmax == pa->disprect.xmax &&
218                            result->tilerect.ymax == pa->disprect.ymax) {
219                                 pa->ready = 1;
220                         }
221                 }
222
223                 if (re->result->do_exr_tile)
224                         render_result_exr_file_merge(re->result, result);
225                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
226                         render_result_merge(re->result, result);
227
228                 /* draw */
229                 if (!re->test_break(re->tbh)) {
230                         result->renlay = result->layers.first; /* weak, draws first layer always */
231                         re->display_draw(re->ddh, result, NULL);
232                 }
233         }
234
235         /* free */
236         BLI_remlink(&engine->fullresult, result);
237         render_result_free(result);
238 }
239
240 /* Cancel */
241
242 int RE_engine_test_break(RenderEngine *engine)
243 {
244         Render *re = engine->re;
245
246         if (re)
247                 return re->test_break(re->tbh);
248         
249         return 0;
250 }
251
252 /* Statistics */
253
254 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
255 {
256         Render *re = engine->re;
257
258         /* stats draw callback */
259         if (re) {
260                 re->i.statstr = stats;
261                 re->i.infostr = info;
262                 re->stats_draw(re->sdh, &re->i);
263                 re->i.infostr = NULL;
264                 re->i.statstr = NULL;
265         }
266
267         /* set engine text */
268         if (engine->text) {
269                 MEM_freeN(engine->text);
270                 engine->text = NULL;
271         }
272
273         if (stats && stats[0] && info && info[0])
274                 engine->text = BLI_sprintfN("%s | %s", stats, info);
275         else if (info && info[0])
276                 engine->text = BLI_strdup(info);
277         else if (stats && stats[0])
278                 engine->text = BLI_strdup(stats);
279 }
280
281 void RE_engine_update_progress(RenderEngine *engine, float progress)
282 {
283         Render *re = engine->re;
284
285         if (re) {
286                 CLAMP(progress, 0.0f, 1.0f);
287                 re->progress(re->prh, progress);
288         }
289 }
290
291 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
292 {
293         BKE_report(engine->re->reports, type, msg);
294 }
295
296 /* Render */
297
298 int RE_engine_render(Render *re, int do_all)
299 {
300         RenderEngineType *type = RE_engines_find(re->r.engine);
301         RenderEngine *engine;
302
303         /* verify if we can render */
304         if (!type->render)
305                 return 0;
306         if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
307                 return 0;
308         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
309                 return 0;
310         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
311                 return 0;
312
313         /* create render result */
314         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
315         if (re->result == NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
316                 int savebuffers;
317
318                 if (re->result)
319                         render_result_free(re->result);
320
321                 savebuffers = (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM;
322                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
323         }
324         BLI_rw_mutex_unlock(&re->resultmutex);
325
326         if (re->result == NULL)
327                 return 1;
328
329         /* set render info */
330         re->i.cfra = re->scene->r.cfra;
331         BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
332         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
333
334         /* render */
335         engine = RE_engine_create(type);
336         engine->re = re;
337
338         if (re->flag & R_ANIMATION)
339                 engine->flag |= RE_ENGINE_ANIMATION;
340         if (re->r.scemode & R_PREVIEWBUTS)
341                 engine->flag |= RE_ENGINE_PREVIEW;
342         engine->camera_override = re->camera_override;
343
344         engine->resolution_x = re->winx;
345         engine->resolution_y = re->winy;
346
347         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0)
348                 BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
349
350         initparts(re, FALSE);
351         engine->tile_x = re->partx;
352         engine->tile_y = re->party;
353
354         if (re->result->do_exr_tile)
355                 render_result_exr_file_begin(re);
356
357         if (type->update)
358                 type->update(engine, re->main, re->scene);
359         
360         if (type->render)
361                 type->render(engine, re->scene);
362
363         if (re->result->do_exr_tile) {
364                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
365                 render_result_exr_file_end(re);
366                 BLI_rw_mutex_unlock(&re->resultmutex);
367         }
368
369         engine->tile_x = 0;
370         engine->tile_y = 0;
371         freeparts(re);
372
373         render_result_free_list(&engine->fullresult, engine->fullresult.first);
374
375         RE_engine_free(engine);
376
377         if (BKE_reports_contain(re->reports, RPT_ERROR))
378                 G.is_break = TRUE;
379         
380         return 1;
381 }
382