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