Tomato keying screen: small fixes and improvements
[blender.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         BLI_addtail(&engine->fullresult, result);
180         
181         result->tilerect.xmin += re->disprect.xmin;
182         result->tilerect.xmax += re->disprect.xmin;
183         result->tilerect.ymin += re->disprect.ymin;
184         result->tilerect.ymax += re->disprect.ymin;
185
186         return result;
187 }
188
189 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
190 {
191         Render *re = engine->re;
192
193         if (result) {
194                 result->renlay = result->layers.first; // weak, draws first layer always
195                 re->display_draw(re->ddh, result, NULL);
196         }
197 }
198
199 void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
200 {
201         Render *re = engine->re;
202         RenderPart *pa;
203
204         if (!result)
205                 return;
206
207         /* merge. on break, don't merge in result for preview renders, looks nicer */
208         if (!cancel) {
209                 /* for exr tile render, detect tiles that are done */
210                 for (pa = re->parts.first; pa; pa = pa->next) {
211                         if (result->tilerect.xmin == pa->disprect.xmin &&
212                            result->tilerect.ymin == pa->disprect.ymin &&
213                            result->tilerect.xmax == pa->disprect.xmax &&
214                            result->tilerect.ymax == pa->disprect.ymax) {
215                                 pa->ready = 1;
216                         }
217                 }
218
219                 if (re->result->do_exr_tile)
220                         render_result_exr_file_merge(re->result, result);
221                 else if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
222                         render_result_merge(re->result, result);
223
224                 /* draw */
225                 if (!re->test_break(re->tbh)) {
226                         result->renlay = result->layers.first; // weak, draws first layer always
227                         re->display_draw(re->ddh, result, NULL);
228                 }
229         }
230
231         /* free */
232         render_result_free_list(&engine->fullresult, result);
233 }
234
235 /* Cancel */
236
237 int RE_engine_test_break(RenderEngine *engine)
238 {
239         Render *re = engine->re;
240
241         if (re)
242                 return re->test_break(re->tbh);
243         
244         return 0;
245 }
246
247 /* Statistics */
248
249 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
250 {
251         Render *re = engine->re;
252
253         /* stats draw callback */
254         if (re) {
255                 re->i.statstr = stats;
256                 re->i.infostr = info;
257                 re->stats_draw(re->sdh, &re->i);
258                 re->i.infostr = NULL;
259                 re->i.statstr = NULL;
260         }
261
262         /* set engine text */
263         if (engine->text) {
264                 MEM_freeN(engine->text);
265                 engine->text = NULL;
266         }
267
268         if (stats && stats[0] && info && info[0])
269                 engine->text = BLI_sprintfN("%s | %s", stats, info);
270         else if (info && info[0])
271                 engine->text = BLI_strdup(info);
272         else if (stats && stats[0])
273                 engine->text = BLI_strdup(stats);
274 }
275
276 void RE_engine_update_progress(RenderEngine *engine, float progress)
277 {
278         Render *re = engine->re;
279
280         if (re) {
281                 CLAMP(progress, 0.0f, 1.0f);
282                 re->progress(re->prh, progress);
283         }
284 }
285
286 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
287 {
288         BKE_report(engine->re->reports, type, msg);
289 }
290
291 /* Render */
292
293 int RE_engine_render(Render *re, int do_all)
294 {
295         RenderEngineType *type = RE_engines_find(re->r.engine);
296         RenderEngine *engine;
297
298         /* verify if we can render */
299         if (!type->render)
300                 return 0;
301         if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
302                 return 0;
303         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
304                 return 0;
305         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
306                 return 0;
307
308         /* create render result */
309         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
310         if (re->result == NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
311                 int savebuffers;
312
313                 if (re->result)
314                         render_result_free(re->result);
315
316                 savebuffers = (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM;
317                 re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS);
318         }
319         BLI_rw_mutex_unlock(&re->resultmutex);
320
321         if (re->result == NULL)
322                 return 1;
323
324         /* set render info */
325         re->i.cfra = re->scene->r.cfra;
326         BLI_strncpy(re->i.scenename, re->scene->id.name + 2, sizeof(re->i.scenename));
327         re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
328
329         /* render */
330         engine = RE_engine_create(type);
331         engine->re = re;
332
333         if (re->flag & R_ANIMATION)
334                 engine->flag |= RE_ENGINE_ANIMATION;
335         if (re->r.scemode & R_PREVIEWBUTS)
336                 engine->flag |= RE_ENGINE_PREVIEW;
337         engine->camera_override = re->camera_override;
338
339         if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0)
340                 BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
341
342         initparts(re, FALSE);
343         engine->tile_x = re->partx;
344         engine->tile_y = re->party;
345
346         if (re->result->do_exr_tile)
347                 render_result_exr_file_begin(re);
348
349         if (type->update)
350                 type->update(engine, re->main, re->scene);
351         
352         if (type->render)
353                 type->render(engine, re->scene);
354
355         if (re->result->do_exr_tile) {
356                 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
357                 render_result_exr_file_end(re);
358                 BLI_rw_mutex_unlock(&re->resultmutex);
359         }
360
361         engine->tile_x = 0;
362         engine->tile_y = 0;
363         freeparts(re);
364
365         render_result_free_list(&engine->fullresult, engine->fullresult.first);
366
367         RE_engine_free(engine);
368
369         if (BKE_reports_contain(re->reports, RPT_ERROR))
370                 G.afbreek = 1;
371         
372         return 1;
373 }
374