Blender V2.61 - r43446
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2006 Blender Foundation. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00033 #include <stddef.h> 00034 #include <stdlib.h> 00035 #include <string.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "BLI_listbase.h" 00040 #include "BLI_string.h" 00041 #include "BLI_utildefines.h" 00042 00043 #include "BKE_report.h" 00044 #include "BKE_scene.h" 00045 00046 #include "IMB_imbuf.h" 00047 #include "IMB_imbuf_types.h" 00048 00049 #ifdef WITH_PYTHON 00050 #include "BPY_extern.h" 00051 #endif 00052 00053 #include "RE_engine.h" 00054 #include "RE_pipeline.h" 00055 00056 #include "render_types.h" 00057 #include "render_result.h" 00058 00059 /* Render Engine Types */ 00060 00061 static RenderEngineType internal_render_type = { 00062 NULL, NULL, 00063 "BLENDER_RENDER", "Blender Render", RE_INTERNAL, 00064 NULL, NULL, NULL, NULL, 00065 {NULL, NULL, NULL}}; 00066 00067 #ifdef WITH_GAMEENGINE 00068 00069 static RenderEngineType internal_game_type = { 00070 NULL, NULL, 00071 "BLENDER_GAME", "Blender Game", RE_INTERNAL|RE_GAME, 00072 NULL, NULL, NULL, NULL, 00073 {NULL, NULL, NULL}}; 00074 00075 #endif 00076 00077 ListBase R_engines = {NULL, NULL}; 00078 00079 void RE_engines_init(void) 00080 { 00081 BLI_addtail(&R_engines, &internal_render_type); 00082 #ifdef WITH_GAMEENGINE 00083 BLI_addtail(&R_engines, &internal_game_type); 00084 #endif 00085 } 00086 00087 void RE_engines_exit(void) 00088 { 00089 RenderEngineType *type, *next; 00090 00091 for(type=R_engines.first; type; type=next) { 00092 next= type->next; 00093 00094 BLI_remlink(&R_engines, type); 00095 00096 if(!(type->flag & RE_INTERNAL)) { 00097 if(type->ext.free) 00098 type->ext.free(type->ext.data); 00099 00100 MEM_freeN(type); 00101 } 00102 } 00103 } 00104 00105 RenderEngineType *RE_engines_find(const char *idname) 00106 { 00107 RenderEngineType *type; 00108 00109 type= BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname)); 00110 if(!type) 00111 type= &internal_render_type; 00112 00113 return type; 00114 } 00115 00116 int RE_engine_is_external(Render *re) 00117 { 00118 RenderEngineType *type= RE_engines_find(re->r.engine); 00119 return (type && type->render); 00120 } 00121 00122 /* Create, Free */ 00123 00124 RenderEngine *RE_engine_create(RenderEngineType *type) 00125 { 00126 RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine"); 00127 engine->type= type; 00128 00129 return engine; 00130 } 00131 00132 void RE_engine_free(RenderEngine *engine) 00133 { 00134 #ifdef WITH_PYTHON 00135 if(engine->py_instance) { 00136 BPY_DECREF(engine->py_instance); 00137 } 00138 #endif 00139 00140 if(engine->text) 00141 MEM_freeN(engine->text); 00142 00143 MEM_freeN(engine); 00144 } 00145 00146 /* Render Results */ 00147 00148 RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h) 00149 { 00150 Render *re= engine->re; 00151 RenderResult *result; 00152 rcti disprect; 00153 00154 /* ensure the coordinates are within the right limits */ 00155 CLAMP(x, 0, re->result->rectx); 00156 CLAMP(y, 0, re->result->recty); 00157 CLAMP(w, 0, re->result->rectx); 00158 CLAMP(h, 0, re->result->recty); 00159 00160 if(x + w > re->result->rectx) 00161 w= re->result->rectx - x; 00162 if(y + h > re->result->recty) 00163 h= re->result->recty - y; 00164 00165 /* allocate a render result */ 00166 disprect.xmin= x; 00167 disprect.xmax= x+w; 00168 disprect.ymin= y; 00169 disprect.ymax= y+h; 00170 00171 result= render_result_new(re, &disprect, 0, RR_USE_MEM); 00172 BLI_addtail(&engine->fullresult, result); 00173 00174 result->tilerect.xmin += re->disprect.xmin; 00175 result->tilerect.xmax += re->disprect.xmin; 00176 result->tilerect.ymin += re->disprect.ymin; 00177 result->tilerect.ymax += re->disprect.ymin; 00178 00179 return result; 00180 } 00181 00182 void RE_engine_update_result(RenderEngine *engine, RenderResult *result) 00183 { 00184 Render *re= engine->re; 00185 00186 if(result) { 00187 result->renlay= result->layers.first; // weak, draws first layer always 00188 re->display_draw(re->ddh, result, NULL); 00189 } 00190 } 00191 00192 void RE_engine_end_result(RenderEngine *engine, RenderResult *result) 00193 { 00194 Render *re= engine->re; 00195 00196 if(!result) 00197 return; 00198 00199 /* merge. on break, don't merge in result for preview renders, looks nicer */ 00200 if(!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS))) 00201 render_result_merge(re->result, result); 00202 00203 /* draw */ 00204 if(!re->test_break(re->tbh)) { 00205 result->renlay= result->layers.first; // weak, draws first layer always 00206 re->display_draw(re->ddh, result, NULL); 00207 } 00208 00209 /* free */ 00210 render_result_free_list(&engine->fullresult, result); 00211 } 00212 00213 /* Cancel */ 00214 00215 int RE_engine_test_break(RenderEngine *engine) 00216 { 00217 Render *re= engine->re; 00218 00219 if(re) 00220 return re->test_break(re->tbh); 00221 00222 return 0; 00223 } 00224 00225 /* Statistics */ 00226 00227 void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) 00228 { 00229 Render *re= engine->re; 00230 00231 /* stats draw callback */ 00232 if(re) { 00233 re->i.statstr= stats; 00234 re->i.infostr= info; 00235 re->stats_draw(re->sdh, &re->i); 00236 re->i.infostr= NULL; 00237 re->i.statstr= NULL; 00238 } 00239 00240 /* set engine text */ 00241 if(engine->text) { 00242 MEM_freeN(engine->text); 00243 engine->text= NULL; 00244 } 00245 00246 if(stats && stats[0] && info && info[0]) 00247 engine->text= BLI_sprintfN("%s | %s", stats, info); 00248 else if(info && info[0]) 00249 engine->text= BLI_strdup(info); 00250 else if(stats && stats[0]) 00251 engine->text= BLI_strdup(stats); 00252 } 00253 00254 void RE_engine_update_progress(RenderEngine *engine, float progress) 00255 { 00256 Render *re= engine->re; 00257 00258 if(re) { 00259 CLAMP(progress, 0.0f, 1.0f); 00260 re->progress(re->prh, progress); 00261 } 00262 } 00263 00264 void RE_engine_report(RenderEngine *engine, int type, const char *msg) 00265 { 00266 BKE_report(engine->re->reports, type, msg); 00267 } 00268 00269 /* Render */ 00270 00271 int RE_engine_render(Render *re, int do_all) 00272 { 00273 RenderEngineType *type= RE_engines_find(re->r.engine); 00274 RenderEngine *engine; 00275 00276 /* verify if we can render */ 00277 if(!type->render) 00278 return 0; 00279 if((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW)) 00280 return 0; 00281 if(do_all && !(type->flag & RE_USE_POSTPROCESS)) 00282 return 0; 00283 if(!do_all && (type->flag & RE_USE_POSTPROCESS)) 00284 return 0; 00285 00286 /* create render result */ 00287 BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); 00288 if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { 00289 if(re->result) 00290 render_result_free(re->result); 00291 re->result= render_result_new(re, &re->disprect, 0, 0); 00292 } 00293 BLI_rw_mutex_unlock(&re->resultmutex); 00294 00295 if(re->result==NULL) 00296 return 1; 00297 00298 /* set render info */ 00299 re->i.cfra= re->scene->r.cfra; 00300 BLI_strncpy(re->i.scenename, re->scene->id.name+2, sizeof(re->i.scenename)); 00301 re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0; 00302 00303 /* render */ 00304 engine = RE_engine_create(type); 00305 engine->re= re; 00306 00307 if(re->flag & R_ANIMATION) 00308 engine->flag |= RE_ENGINE_ANIMATION; 00309 if(re->r.scemode & R_PREVIEWBUTS) 00310 engine->flag |= RE_ENGINE_PREVIEW; 00311 00312 if((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0) 00313 scene_update_for_newframe(re->main, re->scene, re->lay); 00314 00315 if(type->update) 00316 type->update(engine, re->main, re->scene); 00317 if(type->render) 00318 type->render(engine, re->scene); 00319 00320 render_result_free_list(&engine->fullresult, engine->fullresult.first); 00321 00322 RE_engine_free(engine); 00323 00324 return 1; 00325 } 00326