3 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
19 * The Original Code is Copyright (C) 2006 Blender Foundation.
20 * All rights reserved.
22 * The Original Code is: all of this file.
24 * Contributor(s): none yet.
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/render/intern/source/external_engine.c
37 #include "MEM_guardedalloc.h"
39 #include "BLF_translation.h"
41 #include "BLI_listbase.h"
42 #include "BLI_string.h"
43 #include "BLI_utildefines.h"
45 #include "BKE_global.h"
46 #include "BKE_report.h"
47 #include "BKE_scene.h"
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
53 #include "BPY_extern.h"
56 #include "RE_engine.h"
57 #include "RE_pipeline.h"
59 #include "render_types.h"
60 #include "render_result.h"
62 /* Render Engine Types */
64 static RenderEngineType internal_render_type = {
66 "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
67 NULL, NULL, NULL, NULL,
70 #ifdef WITH_GAMEENGINE
72 static RenderEngineType internal_game_type = {
74 "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL|RE_GAME,
75 NULL, NULL, NULL, NULL,
80 ListBase R_engines = {NULL, NULL};
82 void RE_engines_init(void)
84 BLI_addtail(&R_engines, &internal_render_type);
85 #ifdef WITH_GAMEENGINE
86 BLI_addtail(&R_engines, &internal_game_type);
90 void RE_engines_exit(void)
92 RenderEngineType *type, *next;
94 for (type=R_engines.first; type; type=next) {
97 BLI_remlink(&R_engines, type);
99 if (!(type->flag & RE_INTERNAL)) {
101 type->ext.free(type->ext.data);
108 RenderEngineType *RE_engines_find(const char *idname)
110 RenderEngineType *type;
112 type= BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
114 type= &internal_render_type;
119 int RE_engine_is_external(Render *re)
121 RenderEngineType *type= RE_engines_find(re->r.engine);
122 return (type && type->render);
127 RenderEngine *RE_engine_create(RenderEngineType *type)
129 RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
135 void RE_engine_free(RenderEngine *engine)
138 if (engine->py_instance) {
139 BPY_DECREF(engine->py_instance);
144 MEM_freeN(engine->text);
151 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
153 Render *re= engine->re;
154 RenderResult *result;
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);
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;
168 /* allocate a render result */
174 result= render_result_new(re, &disprect, 0, RR_USE_MEM);
175 BLI_addtail(&engine->fullresult, result);
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;
185 void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
187 Render *re= engine->re;
190 result->renlay= result->layers.first; // weak, draws first layer always
191 re->display_draw(re->ddh, result, NULL);
195 void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
197 Render *re= engine->re;
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);
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);
213 render_result_free_list(&engine->fullresult, result);
218 int RE_engine_test_break(RenderEngine *engine)
220 Render *re= engine->re;
223 return re->test_break(re->tbh);
230 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
232 Render *re= engine->re;
234 /* stats draw callback */
236 re->i.statstr= stats;
238 re->stats_draw(re->sdh, &re->i);
243 /* set engine text */
245 MEM_freeN(engine->text);
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);
257 void RE_engine_update_progress(RenderEngine *engine, float progress)
259 Render *re= engine->re;
262 CLAMP(progress, 0.0f, 1.0f);
263 re->progress(re->prh, progress);
267 void RE_engine_report(RenderEngine *engine, int type, const char *msg)
269 BKE_report(engine->re->reports, type, msg);
274 int RE_engine_render(Render *re, int do_all)
276 RenderEngineType *type= RE_engines_find(re->r.engine);
277 RenderEngine *engine;
279 /* verify if we can render */
282 if ((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
284 if (do_all && !(type->flag & RE_USE_POSTPROCESS))
286 if (!do_all && (type->flag & RE_USE_POSTPROCESS))
289 /* create render result */
290 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
291 if (re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
293 render_result_free(re->result);
294 re->result= render_result_new(re, &re->disprect, 0, 0);
296 BLI_rw_mutex_unlock(&re->resultmutex);
298 if (re->result==NULL)
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;
307 engine = RE_engine_create(type);
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;
316 if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
317 scene_update_for_newframe(re->main, re->scene, re->lay);
320 type->update(engine, re->main, re->scene);
322 type->render(engine, re->scene);
324 render_result_free_list(&engine->fullresult, engine->fullresult.first);
326 RE_engine_free(engine);
328 if (BKE_reports_contain(re->reports, RPT_ERROR))