Merged changes in the trunk up to revision 46045.
[blender-staging.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 "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 #ifdef WITH_GAMEENGINE
71
72 static RenderEngineType internal_game_type = {
73         NULL, NULL,
74         "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL|RE_GAME,
75         NULL, NULL, NULL, NULL,
76         {NULL, NULL, NULL}};
77
78 #endif
79
80 ListBase R_engines = {NULL, NULL};
81
82 void RE_engines_init(void)
83 {
84         BLI_addtail(&R_engines, &internal_render_type);
85 #ifdef WITH_GAMEENGINE
86         BLI_addtail(&R_engines, &internal_game_type);
87 #endif
88 }
89
90 void RE_engines_exit(void)
91 {
92         RenderEngineType *type, *next;
93
94         for (type=R_engines.first; type; type=next) {
95                 next= type->next;
96
97                 BLI_remlink(&R_engines, type);
98
99                 if (!(type->flag & RE_INTERNAL)) {
100                         if (type->ext.free)
101                                 type->ext.free(type->ext.data);
102
103                         MEM_freeN(type);
104                 }
105         }
106 }
107
108 RenderEngineType *RE_engines_find(const char *idname)
109 {
110         RenderEngineType *type;
111         
112         type= BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
113         if (!type)
114                 type= &internal_render_type;
115
116         return type;
117 }
118
119 int RE_engine_is_external(Render *re)
120 {
121         RenderEngineType *type= RE_engines_find(re->r.engine);
122         return (type && type->render);
123 }
124
125 /* Create, Free */
126
127 RenderEngine *RE_engine_create(RenderEngineType *type)
128 {
129         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
130         engine->type= type;
131
132         return engine;
133 }
134
135 void RE_engine_free(RenderEngine *engine)
136 {
137 #ifdef WITH_PYTHON
138         if (engine->py_instance) {
139                 BPY_DECREF(engine->py_instance);
140         }
141 #endif
142
143         if (engine->text)
144                 MEM_freeN(engine->text);
145
146         MEM_freeN(engine);
147 }
148
149 /* Render Results */
150
151 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
152 {
153         Render *re= engine->re;
154         RenderResult *result;
155         rcti disprect;
156
157         /* ensure the coordinates are within the right limits */
158         CLAMP(x, 0, re->result->rectx);
159         CLAMP(y, 0, re->result->recty);
160         CLAMP(w, 0, re->result->rectx);
161         CLAMP(h, 0, re->result->recty);
162
163         if (x + w > re->result->rectx)
164                 w= re->result->rectx - x;
165         if (y + h > re->result->recty)
166                 h= re->result->recty - y;
167
168         /* allocate a render result */
169         disprect.xmin = x;
170         disprect.xmax = x+w;
171         disprect.ymin = y;
172         disprect.ymax = y+h;
173
174         result= render_result_new(re, &disprect, 0, RR_USE_MEM);
175         BLI_addtail(&engine->fullresult, result);
176         
177         result->tilerect.xmin += re->disprect.xmin;
178         result->tilerect.xmax += re->disprect.xmin;
179         result->tilerect.ymin += re->disprect.ymin;
180         result->tilerect.ymax += re->disprect.ymin;
181
182         return result;
183 }
184
185 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
186 {
187         Render *re= engine->re;
188
189         if (result) {
190                 result->renlay= result->layers.first; // weak, draws first layer always
191                 re->display_draw(re->ddh, result, NULL);
192         }
193 }
194
195 void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
196 {
197         Render *re= engine->re;
198
199         if (!result)
200                 return;
201
202         /* merge. on break, don't merge in result for preview renders, looks nicer */
203         if (!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
204                 render_result_merge(re->result, result);
205
206         /* draw */
207         if (!re->test_break(re->tbh)) {
208                 result->renlay= result->layers.first; // weak, draws first layer always
209                 re->display_draw(re->ddh, result, NULL);
210         }
211
212         /* free */
213         render_result_free_list(&engine->fullresult, result);
214 }
215
216 /* Cancel */
217
218 int RE_engine_test_break(RenderEngine *engine)
219 {
220         Render *re= engine->re;
221
222         if (re)
223                 return re->test_break(re->tbh);
224         
225         return 0;
226 }
227
228 /* Statistics */
229
230 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
231 {
232         Render *re= engine->re;
233
234         /* stats draw callback */
235         if (re) {
236                 re->i.statstr= stats;
237                 re->i.infostr= info;
238                 re->stats_draw(re->sdh, &re->i);
239                 re->i.infostr= NULL;
240                 re->i.statstr= NULL;
241         }
242
243         /* set engine text */
244         if (engine->text) {
245                 MEM_freeN(engine->text);
246                 engine->text= NULL;
247         }
248
249         if (stats && stats[0] && info && info[0])
250                 engine->text= BLI_sprintfN("%s | %s", stats, info);
251         else if (info && info[0])
252                 engine->text= BLI_strdup(info);
253         else if (stats && stats[0])
254                 engine->text= BLI_strdup(stats);
255 }
256
257 void RE_engine_update_progress(RenderEngine *engine, float progress)
258 {
259         Render *re= engine->re;
260
261         if (re) {
262                 CLAMP(progress, 0.0f, 1.0f);
263                 re->progress(re->prh, progress);
264         }
265 }
266
267 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
268 {
269         BKE_report(engine->re->reports, type, msg);
270 }
271
272 /* Render */
273
274 int RE_engine_render(Render *re, int do_all)
275 {
276         RenderEngineType *type= RE_engines_find(re->r.engine);
277         RenderEngine *engine;
278
279         /* verify if we can render */
280         if (!type->render)
281                 return 0;
282         if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
283                 return 0;
284         if (do_all && !(type->flag & RE_USE_POSTPROCESS))
285                 return 0;
286         if (!do_all && (type->flag & RE_USE_POSTPROCESS))
287                 return 0;
288
289         /* create render result */
290         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
291         if (re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
292                 if (re->result)
293                         render_result_free(re->result);
294                 re->result= render_result_new(re, &re->disprect, 0, 0);
295         }
296         BLI_rw_mutex_unlock(&re->resultmutex);
297         
298         if (re->result==NULL)
299                 return 1;
300
301         /* set render info */
302         re->i.cfra= re->scene->r.cfra;
303         BLI_strncpy(re->i.scenename, re->scene->id.name+2, sizeof(re->i.scenename));
304         re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
305
306         /* render */
307         engine = RE_engine_create(type);
308         engine->re= re;
309
310         if (re->flag & R_ANIMATION)
311                 engine->flag |= RE_ENGINE_ANIMATION;
312         if (re->r.scemode & R_PREVIEWBUTS)
313                 engine->flag |= RE_ENGINE_PREVIEW;
314         engine->camera_override = re->camera_override;
315
316         if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
317                 scene_update_for_newframe(re->main, re->scene, re->lay);
318
319         if (type->update)
320                 type->update(engine, re->main, re->scene);
321         if (type->render)
322                 type->render(engine, re->scene);
323
324         render_result_free_list(&engine->fullresult, engine->fullresult.first);
325
326         RE_engine_free(engine);
327
328         if (BKE_reports_contain(re->reports, RPT_ERROR))
329                 G.afbreek = 1;
330         
331         return 1;
332 }
333