Render API: add update_progress() function to update progress bar progress from
[blender.git] / source / blender / render / intern / source / external_engine.c
1 /*  
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/render/intern/pipeline/engine.c
31  *  \ingroup render
32  */
33
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_listbase.h"
41 #include "BLI_string.h"
42 #include "BLI_utildefines.h"
43
44 #include "BKE_report.h"
45 #include "BKE_scene.h"
46
47 #include "IMB_imbuf.h"
48 #include "IMB_imbuf_types.h"
49
50 #ifdef WITH_PYTHON
51 #include "BPY_extern.h"
52 #endif
53
54 #include "RE_engine.h"
55 #include "RE_pipeline.h"
56
57 #include "render_types.h"
58 #include "renderpipeline.h"
59
60 /* Render Engine Types */
61
62 static RenderEngineType internal_render_type = {
63         NULL, NULL,
64         "BLENDER_RENDER", "Blender Render", RE_INTERNAL,
65         NULL,
66         {NULL, NULL, NULL}};
67
68 #ifdef WITH_GAMEENGINE
69
70 static RenderEngineType internal_game_type = {
71         NULL, NULL,
72         "BLENDER_GAME", "Blender Game", RE_INTERNAL|RE_GAME,
73         NULL,
74         {NULL, NULL, NULL}};
75
76 #endif
77
78 ListBase R_engines = {NULL, NULL};
79
80 void RE_engines_init(void)
81 {
82         BLI_addtail(&R_engines, &internal_render_type);
83 #ifdef WITH_GAMEENGINE
84         BLI_addtail(&R_engines, &internal_game_type);
85 #endif
86 }
87
88 void RE_engines_exit(void)
89 {
90         RenderEngineType *type, *next;
91
92         for(type=R_engines.first; type; type=next) {
93                 next= type->next;
94
95                 BLI_remlink(&R_engines, type);
96
97                 if(!(type->flag & RE_INTERNAL)) {
98                         if(type->ext.free)
99                                 type->ext.free(type->ext.data);
100
101                         MEM_freeN(type);
102                 }
103         }
104 }
105
106 RenderEngineType *RE_engines_find(const char *idname)
107 {
108         RenderEngineType *type;
109         
110         type= BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
111         if(!type)
112                 type= &internal_render_type;
113
114         return type;
115 }
116
117 /* Create, Free */
118
119 RenderEngine *RE_engine_create(RenderEngineType *type)
120 {
121         RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
122         engine->type= type;
123
124         return engine;
125 }
126
127 void RE_engine_free(RenderEngine *engine)
128 {
129         MEM_freeN(engine);
130 }
131
132 /* Render Results */
133
134 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
135 {
136         Render *re= engine->re;
137         RenderResult *result;
138         rcti disprect;
139
140         /* ensure the coordinates are within the right limits */
141         CLAMP(x, 0, re->result->rectx);
142         CLAMP(y, 0, re->result->recty);
143         CLAMP(w, 0, re->result->rectx);
144         CLAMP(h, 0, re->result->recty);
145
146         if(x + w > re->result->rectx)
147                 w= re->result->rectx - x;
148         if(y + h > re->result->recty)
149                 h= re->result->recty - y;
150
151         /* allocate a render result */
152         disprect.xmin= x;
153         disprect.xmax= x+w;
154         disprect.ymin= y;
155         disprect.ymax= y+h;
156
157         result= new_render_result(re, &disprect, 0, RR_USEMEM);
158         BLI_addtail(&engine->fullresult, result);
159
160         return result;
161 }
162
163 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
164 {
165         Render *re= engine->re;
166
167         if(result) {
168                 result->renlay= result->layers.first; // weak, draws first layer always
169                 re->display_draw(re->ddh, result, NULL);
170         }
171 }
172
173 void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
174 {
175         Render *re= engine->re;
176
177         if(!result)
178                 return;
179
180         /* merge. on break, don't merge in result for preview renders, looks nicer */
181         if(!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
182                 merge_render_result(re->result, result);
183
184         /* draw */
185         if(!re->test_break(re->tbh)) {
186                 result->renlay= result->layers.first; // weak, draws first layer always
187                 re->display_draw(re->ddh, result, NULL);
188         }
189
190         /* free */
191         free_render_result(&engine->fullresult, result);
192 }
193
194 /* Cancel */
195
196 int RE_engine_test_break(RenderEngine *engine)
197 {
198         Render *re= engine->re;
199
200         if(re)
201                 return re->test_break(re->tbh);
202         
203         return 0;
204 }
205
206 /* Statistics */
207
208 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
209 {
210         Render *re= engine->re;
211
212         /* stats draw callback */
213         if(re) {
214                 re->i.statstr= stats;
215                 re->i.infostr= info;
216                 re->stats_draw(re->sdh, &re->i);
217                 re->i.infostr= NULL;
218                 re->i.statstr= NULL;
219         }
220 }
221
222 void RE_engine_update_progress(RenderEngine *engine, float progress)
223 {
224         Render *re= engine->re;
225
226         if(re) {
227                 CLAMP(progress, 0.0f, 1.0f);
228                 re->progress(re->prh, progress);
229         }
230 }
231
232 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
233 {
234         BKE_report(engine->re->reports, type, msg);
235 }
236
237 /* Render */
238
239 int RE_engine_render(Render *re, int do_all)
240 {
241         RenderEngineType *type= RE_engines_find(re->r.engine);
242         RenderEngine *engine;
243
244         /* verify if we can render */
245         if(!type->render)
246                 return 0;
247         if((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
248                 return 0;
249         if(do_all && !(type->flag & RE_USE_POSTPROCESS))
250                 return 0;
251         if(!do_all && (type->flag & RE_USE_POSTPROCESS))
252                 return 0;
253
254         /* create render result */
255         BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
256         if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
257                 RE_FreeRenderResult(re->result);
258                 re->result= new_render_result(re, &re->disprect, 0, 0);
259         }
260         BLI_rw_mutex_unlock(&re->resultmutex);
261         
262         if(re->result==NULL)
263                 return 1;
264
265         /* render */
266         engine = RE_engine_create(type);
267         engine->re= re;
268
269         if((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
270                 scene_update_for_newframe(re->main, re->scene, re->lay);
271
272         type->render(engine, re->scene);
273
274
275         free_render_result(&engine->fullresult, engine->fullresult.first);
276
277         RE_engine_free(engine);
278
279         return 1;
280 }
281