svn merge ^/trunk/blender -r41226:41227 .
[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/pipeline/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,
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,
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         MEM_freeN(engine);
129 }
130
131 /* Render Results */
132
133 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
134 {
135         Render *re= engine->re;
136         RenderResult *result;
137         rcti disprect;
138
139         /* ensure the coordinates are within the right limits */
140         CLAMP(x, 0, re->result->rectx);
141         CLAMP(y, 0, re->result->recty);
142         CLAMP(w, 0, re->result->rectx);
143         CLAMP(h, 0, re->result->recty);
144
145         if(x + w > re->result->rectx)
146                 w= re->result->rectx - x;
147         if(y + h > re->result->recty)
148                 h= re->result->recty - y;
149
150         /* allocate a render result */
151         disprect.xmin= x;
152         disprect.xmax= x+w;
153         disprect.ymin= y;
154         disprect.ymax= y+h;
155
156         result= new_render_result(re, &disprect, 0, RR_USEMEM);
157         BLI_addtail(&engine->fullresult, result);
158
159         return result;
160 }
161
162 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
163 {
164         Render *re= engine->re;
165
166         if(result) {
167                 result->renlay= result->layers.first; // weak, draws first layer always
168                 re->display_draw(re->ddh, result, NULL);
169         }
170 }
171
172 void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
173 {
174         Render *re= engine->re;
175
176         if(!result)
177                 return;
178
179         /* merge. on break, don't merge in result for preview renders, looks nicer */
180         if(!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
181                 merge_render_result(re->result, result);
182
183         /* draw */
184         if(!re->test_break(re->tbh)) {
185                 result->renlay= result->layers.first; // weak, draws first layer always
186                 re->display_draw(re->ddh, result, NULL);
187         }
188
189         /* free */
190         free_render_result(&engine->fullresult, result);
191 }
192
193 /* Cancel */
194
195 int RE_engine_test_break(RenderEngine *engine)
196 {
197         Render *re= engine->re;
198
199         if(re)
200                 return re->test_break(re->tbh);
201         
202         return 0;
203 }
204
205 /* Statistics */
206
207 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
208 {
209         Render *re= engine->re;
210
211         /* stats draw callback */
212         if(re) {
213                 re->i.statstr= stats;
214                 re->i.infostr= info;
215                 re->stats_draw(re->sdh, &re->i);
216                 re->i.infostr= NULL;
217                 re->i.statstr= NULL;
218         }
219 }
220
221 void RE_engine_update_progress(RenderEngine *engine, float progress)
222 {
223         Render *re= engine->re;
224
225         if(re) {
226                 CLAMP(progress, 0.0f, 1.0f);
227                 re->progress(re->prh, progress);
228         }
229 }
230
231 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
232 {
233         BKE_report(engine->re->reports, type, msg);
234 }
235
236 /* Render */
237
238 int RE_engine_render(Render *re, int do_all)
239 {
240         RenderEngineType *type= RE_engines_find(re->r.engine);
241         RenderEngine *engine;
242
243         /* verify if we can render */
244         if(!type->render)
245                 return 0;
246         if((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
247                 return 0;
248         if(do_all && !(type->flag & RE_USE_POSTPROCESS))
249                 return 0;
250         if(!do_all && (type->flag & RE_USE_POSTPROCESS))
251                 return 0;
252
253         /* create render result */
254         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
255         if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
256                 RE_FreeRenderResult(re->result);
257                 re->result= new_render_result(re, &re->disprect, 0, 0);
258         }
259         BLI_rw_mutex_unlock(&re->resultmutex);
260         
261         if(re->result==NULL)
262                 return 1;
263
264         /* render */
265         engine = RE_engine_create(type);
266         engine->re= re;
267
268         if((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
269                 scene_update_for_newframe(re->main, re->scene, re->lay);
270
271         type->render(engine, re->scene);
272
273
274         free_render_result(&engine->fullresult, engine->fullresult.first);
275
276         RE_engine_free(engine);
277
278         return 1;
279 }
280