Blender V2.61 - r43446

external_engine.c

Go to the documentation of this file.
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