2.5: Render
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 21 Jul 2009 20:28:32 +0000 (20:28 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 21 Jul 2009 20:28:32 +0000 (20:28 +0000)
This adds a RenderEngine type to RNA, which can be subclassed
in python (c++ will follow once we support subclassing there).
It's very basic, but plugs into the pipeline nicely. Two example
scripts:

http://www.pasteall.org/6635/python
http://www.pasteall.org/6636/python

Issues:
* Render runs in a separate thread, and there is unrestricted
  access, so it's possible to crash blender with unsafe access.
* Save buffers and full sample are not supported yet.

release/ui/buttons_scene.py
source/blender/editors/screen/screen_ops.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_render.c
source/blender/makesrna/intern/rna_scene.c
source/blender/render/CMakeLists.txt
source/blender/render/SConscript
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/source/Makefile
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/intern/wm_init_exit.c

index 5f686469292a918982c919dc5e6a7e84b341bb84..45bf8b487887d410b208d2afa2e7fe2fd76d3c93 100644 (file)
@@ -18,6 +18,8 @@ class RENDER_PT_render(RenderButtonsPanel):
                row.item_booleanO("screen.render", "anim", True, text="Animation", icon='ICON_SEQUENCE')
 
                layout.itemR(rd, "display_mode", text="Display")
+               if rd.multiple_engines:
+                       layout.itemR(rd, "engine")
 
 class RENDER_PT_layers(RenderButtonsPanel):
        __label__ = "Layers"
index e13e27412b8dfb3dd5382a8c7f4d670dbef7d2be..4a42d1ed36920d68488a1a518a46bba8b181a12a 100644 (file)
@@ -2486,20 +2486,25 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
        else if(scene->r.scemode & R_SINGLE_LAYER)
                spos+= sprintf(spos, "Single Layer | ");
        
-       spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
-       if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
-       if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
-       spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory);
-       
-       if(rs->curfield)
-               spos+= sprintf(spos, "Field %d ", rs->curfield);
-       if(rs->curblur)
-               spos+= sprintf(spos, "Blur %d ", rs->curblur);
+       if(rs->statstr) {
+               spos+= sprintf(spos, "%s ", rs->statstr);
+       }
+       else {
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
+               if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
+               if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
+               spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory);
+               
+               if(rs->curfield)
+                       spos+= sprintf(spos, "Field %d ", rs->curfield);
+               if(rs->curblur)
+                       spos+= sprintf(spos, "Blur %d ", rs->curblur);
+       }
        
        BLI_timestr(rs->lastframetime, info_time_str);
        spos+= sprintf(spos, "Time:%s ", info_time_str);
        
-       if(rs->infostr)
+       if(rs->infostr && rs->infostr[0])
                spos+= sprintf(spos, "| %s ", rs->infostr);
        
        /* very weak... but 512 characters is quite safe */
index 8e517ad776068d3831d14989f812b398b26f1ae2..60176dd5e6ebf70c25b056811b8eeaa1cf8a31ab 100644 (file)
@@ -235,7 +235,7 @@ typedef struct RenderData {
         */
        int mode;
 
-       /* render engine, octree resolution */
+       /* render engine (deprecated), octree resolution */
        short renderer, ocres;
 
        /**
@@ -334,6 +334,8 @@ typedef struct RenderData {
        float pad2;                     //  XXX deprecated since 2.5
        struct Text *dometext;  //  XXX deprecated since 2.5
 
+       /* render engine */
+       char engine[32];
 } RenderData;
 
 /* control render convert and shading engine */
index 7eacb4079e57521871609f43d8211c3e57aad395..0ed4e9fb80fdd7ab9a742f39f0203b5c6be774ed 100644 (file)
@@ -34,7 +34,6 @@
 #include "WM_types.h"
 
 #include "RE_pipeline.h"
-#include "RE_render_ext.h"
 
 #ifdef RNA_RUNTIME
 
 
 #include "WM_api.h"
 
+/* RenderEngine */
+
+static void engine_render(RenderEngine *engine, struct Scene *scene)
+{
+       PointerRNA ptr;
+       ParameterList list;
+       FunctionRNA *func;
+
+       RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+       func= RNA_struct_find_function(&ptr, "render");
+
+       RNA_parameter_list_create(&list, &ptr, func);
+       RNA_parameter_set_lookup(&list, "scene", &scene);
+       engine->type->ext.call(&ptr, func, &list);
+
+       RNA_parameter_list_free(&list);
+}
+
+static void rna_RenderEngine_unregister(const bContext *C, StructRNA *type)
+{
+       RenderEngineType *et= RNA_struct_blender_type_get(type);
+
+       if(!et)
+               return;
+       
+       BLI_freelinkN(&R_engines, et);
+       RNA_struct_free(&BLENDER_RNA, type);
+}
+
+static StructRNA *rna_RenderEngine_register(const bContext *C, ReportList *reports, void *data, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+       RenderEngineType *et, dummyet = {0};
+       RenderEngine dummyengine= {0};
+       PointerRNA dummyptr;
+       int have_function[1];
+
+       /* setup dummy engine & engine type to store static properties in */
+       dummyengine.type= &dummyet;
+       RNA_pointer_create(NULL, &RNA_RenderEngine, &dummyengine, &dummyptr);
+
+       /* validate the python class */
+       if(validate(&dummyptr, data, have_function) != 0)
+               return NULL;
+       
+       /* check if we have registered this engine type before, and remove it */
+       for(et=R_engines.first; et; et=et->next) {
+               if(strcmp(et->idname, dummyet.idname) == 0) {
+                       if(et->ext.srna)
+                               rna_RenderEngine_unregister(C, et->ext.srna);
+                       break;
+               }
+       }
+       
+       /* create a new engine type */
+       et= MEM_callocN(sizeof(RenderEngineType), "python buttons engine");
+       memcpy(et, &dummyet, sizeof(dummyet));
+
+       et->ext.srna= RNA_def_struct(&BLENDER_RNA, et->idname, "RenderEngine"); 
+       et->ext.data= data;
+       et->ext.call= call;
+       et->ext.free= free;
+       RNA_struct_blender_type_set(et->ext.srna, et);
+
+       et->render= (have_function[0])? engine_render: NULL;
+
+       BLI_addtail(&R_engines, et);
+
+       return et->ext.srna;
+}
+
+static StructRNA* rna_RenderEngine_refine(PointerRNA *ptr)
+{
+       RenderEngine *engine= (RenderEngine*)ptr->data;
+       return (engine->type && engine->type->ext.srna)? engine->type->ext.srna: &RNA_RenderEngine;
+}
+
 static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
        RenderResult *rr= (RenderResult*)ptr->data;
@@ -96,6 +171,68 @@ static int rna_RenderPass_rect_length(PointerRNA *ptr)
 
 #else // RNA_RUNTIME
 
+static void rna_def_render_engine(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+       FunctionRNA *func;
+       
+       srna= RNA_def_struct(brna, "RenderEngine", NULL);
+       RNA_def_struct_sdna(srna, "RenderEngine");
+       RNA_def_struct_ui_text(srna, "Render Engine", "Render engine.");
+       RNA_def_struct_refine_func(srna, "rna_RenderEngine_refine");
+       RNA_def_struct_register_funcs(srna, "rna_RenderEngine_register", "rna_RenderEngine_unregister");
+
+       /* render */
+       func= RNA_def_function(srna, "render", NULL);
+       RNA_def_function_ui_description(func, "Render scene into an image.");
+       RNA_def_function_flag(func, FUNC_REGISTER);
+       RNA_def_pointer(func, "scene", "Scene", "", "");
+
+       func= RNA_def_function(srna, "begin_result", "RE_engine_begin_result");
+       prop= RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX);
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_int(func, "y", 0, 0, INT_MAX, "Y", "", 0, INT_MAX);
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_int(func, "w", 0, 0, INT_MAX, "Width", "", 0, INT_MAX);
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_int(func, "h", 0, 0, INT_MAX, "Height", "", 0, INT_MAX);
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_pointer(func, "result", "RenderResult", "Result", "");
+       RNA_def_function_return(func, prop);
+
+       func= RNA_def_function(srna, "update_result", "RE_engine_update_result");
+       prop= RNA_def_pointer(func, "result", "RenderResult", "Result", "");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+
+       func= RNA_def_function(srna, "end_result", "RE_engine_end_result");
+       prop= RNA_def_pointer(func, "result", "RenderResult", "Result", "");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+
+       func= RNA_def_function(srna, "test_break", "RE_engine_test_break");
+       prop= RNA_def_boolean(func, "do_break", 0, "Break", "");
+       RNA_def_function_return(func, prop);
+
+       func= RNA_def_function(srna, "update_stats", "RE_engine_update_stats");
+       prop= RNA_def_string(func, "stats", "", 0, "Stats", "");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_string(func, "info", "", 0, "Info", "");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+
+       /* registration */
+       RNA_define_verify_sdna(0);
+
+       prop= RNA_def_property(srna, "idname", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->idname");
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       prop= RNA_def_property(srna, "label", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "type->name");
+       RNA_def_property_flag(prop, PROP_REGISTER);
+
+       RNA_define_verify_sdna(1);
+}
+
 static void rna_def_render_result(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -205,6 +342,7 @@ static void rna_def_render_pass(BlenderRNA *brna)
 
 void RNA_def_render(BlenderRNA *brna)
 {
+       rna_def_render_engine(brna);
        rna_def_render_result(brna);
        rna_def_render_layer(brna);
        rna_def_render_pass(brna);
index f23a14d99fbb8d65a16aac4b05bcafc7ca6069ec..bd23fc9e1f6ac2bf0f478757a2912fa34b1f9c38 100644 (file)
@@ -60,6 +60,8 @@ EnumPropertyItem prop_mode_items[] ={
 
 #include "BLI_threads.h"
 
+#include "RE_pipeline.h"
+
 PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
 {
        ListBaseIterator *internal= iter->internal;
@@ -163,6 +165,48 @@ static void rna_SceneRenderData_active_layer_index_range(PointerRNA *ptr, int *m
        *max= MAX2(0, *max);
 }
 
+static void rna_SceneRenderData_engine_set(PointerRNA *ptr, int value)
+{
+       RenderData *rd= (RenderData*)ptr->data;
+       RenderEngineType *type= BLI_findlink(&R_engines, value);
+
+       if(type)
+               BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
+}
+
+static EnumPropertyItem *rna_SceneRenderData_engine_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       RenderEngineType *type;
+       EnumPropertyItem *item= NULL;
+       EnumPropertyItem tmp = {0, "", 0, "", ""};
+       int a=0, totitem= 0;
+
+       for(type=R_engines.first; type; type=type->next, a++) {
+               tmp.value= a;
+               tmp.identifier= type->idname;
+               tmp.name= type->name;
+               RNA_enum_item_add(&item, &totitem, &tmp);
+       }
+       
+       RNA_enum_item_end(&item, &totitem);
+       *free= 1;
+
+       return item;
+}
+
+static int rna_SceneRenderData_engine_get(PointerRNA *ptr)
+{
+       RenderData *rd= (RenderData*)ptr->data;
+       RenderEngineType *type;
+       int a= 0;
+
+       for(type=R_engines.first; type; type=type->next, a++)
+               if(strcmp(type->idname, rd->engine) == 0)
+                       return a;
+       
+       return 0;
+}
+
 static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
 {
        Scene *scene= (Scene*)ptr->id.data;
@@ -183,6 +227,11 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
        }
 }
 
+static int rna_SceneRenderData_multiple_engines_get(PointerRNA *ptr)
+{
+       return (BLI_countlist(&R_engines) > 1);
+}
+
 static void rna_SceneRenderLayer_layer_set(PointerRNA *ptr, const int *values)
 {
        SceneRenderLayer *rl= (SceneRenderLayer*)ptr->data;
@@ -997,6 +1046,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}};
 #endif
 
+       static EnumPropertyItem engine_items[] = {
+               {0, "BLENDER", 0, "Blender", ""},
+               {0, NULL, 0, NULL, NULL}};
+
        srna= RNA_def_struct(brna, "SceneRenderData", NULL);
        RNA_def_struct_sdna(srna, "RenderData");
        RNA_def_struct_nested(brna, srna, "Scene");
@@ -1520,6 +1573,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_int_funcs(prop, "rna_SceneRenderData_active_layer_index_get", "rna_SceneRenderData_active_layer_index_set", "rna_SceneRenderData_active_layer_index_range");
        RNA_def_property_ui_text(prop, "Active Layer Index", "Active index in render layer array.");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+
+       /* engine */
+       prop= RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, engine_items);
+       RNA_def_property_enum_funcs(prop, "rna_SceneRenderData_engine_get", "rna_SceneRenderData_engine_set", "rna_SceneRenderData_engine_itemf");
+       RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering.");
+
+       prop= RNA_def_property(srna, "multiple_engines", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_multiple_engines_get", NULL);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Multiple Engine", "More than one rendering engine is available.");
 }
 
 void RNA_def_scene(BlenderRNA *brna)
index 8ba7dc123e78383f6ad06c1a6dbacba3a5819e86..411bd61c3ff31f013b9fc686e2ea8dc9fa308c39 100644 (file)
@@ -30,6 +30,7 @@ SET(INC
   intern/include ../../../intern/guardedalloc ../blenlib ../makesdna
   extern/include ../blenkernel ../radiosity/extern/include ../imbuf
   ../quicktime ../include ../../kernel/gen_messaging ../blenloader
+  ../makesrna
 )
 
 IF(WITH_OPENEXR)
index 173f5db848258eaa9717127ce06eee8c1ef05b37..dbd9f65254b9dd62f5a9e8e763a2f1cdf920b99c 100644 (file)
@@ -4,7 +4,7 @@ Import ('env')
 cflags=''
 sources = env.Glob('intern/source/*.c')
 
-incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna'
+incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna ../makesrna'
 incs += ' extern/include ../blenkernel ../radiosity/extern/include ../imbuf'
 incs += ' ../include ../blenloader'
 
index e0e78739d3960e928024de8edb5f7d12587f7be6..643a381c54f4b20094da6bf02a35133f98a54a1c 100644 (file)
 #include "DNA_listBase.h"
 #include "DNA_vec_types.h"
 #include "BKE_utildefines.h"
+#include "RNA_types.h"
 
-struct Scene;
-struct RenderData;
+struct bNodeTree;
+struct Image;
 struct NodeBlurData;
 struct Object;
-struct bNodeTree;
+struct RenderData;
+struct RenderEngine;
+struct RenderEngineType;
+struct RenderResult;
+struct Scene;
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 /* this include is what is exposed of render to outside world */
@@ -130,7 +135,7 @@ typedef struct RenderStats {
        int totface, totvert, totstrand, tothalo, totlamp, totpart;
        short curfield, curblur, curpart, partsdone, convertdone;
        double starttime, lastframetime;
-       char *infostr, scenename[32];
+       char *infostr, *statstr, scenename[32];
        
 } RenderStats;
 
@@ -233,5 +238,38 @@ void RE_DataBase_GetView(struct Render *re, float mat[][4]);
 void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[][4]);
 struct Scene *RE_GetScene(struct Render *re);
 
+/* External Engine */
+
+
+extern ListBase R_engines;
+
+typedef struct RenderEngineType {
+       struct RenderEngineType *next, *prev;
+
+       /* type info */
+       char idname[32];
+       char name[32];
+
+       void (*render)(struct RenderEngine *engine, struct Scene *scene);
+
+       /* RNA integration */
+       ExtensionRNA ext;
+} RenderEngineType;
+
+typedef struct RenderEngine {
+       RenderEngineType *type;
+       struct Render *re;
+       ListBase fullresult;
+} RenderEngine;
+
+struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h);
+void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result);
+void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result);
+
+int RE_engine_test_break(RenderEngine *engine);
+void RE_engine_update_stats(RenderEngine *engine, char *stats, char *info);
+
+void RE_engines_free(void);
+
 #endif /* RE_PIPELINE_H */
 
index 22680b26338df10112bfecccc85f52308c1aa9c5..3c8d0f637a386471c88676a6ca858900d9cda076 100644 (file)
@@ -43,6 +43,7 @@ CPPFLAGS += -I../../../radiosity/extern/include
 CPPFLAGS += -I../../../blenlib
 CPPFLAGS += -I../../../imbuf
 CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../makesrna
 CPPFLAGS += -I../../../blenkernel
 CPPFLAGS += -I../../../quicktime
 CPPFLAGS += -I../../../../kernel/gen_messaging
index db78d0bbb6139fcdbaf633c47766ea0b06c32b74..801a9729277d91364465f22aeb64c32595a17034 100644 (file)
@@ -1664,8 +1664,23 @@ void RE_TileProcessor(Render *re, int firsttile, int threaded)
 
 /* ************  This part uses API, for rendering Blender scenes ********** */
 
+static void external_render_3d(Render *re, RenderEngineType *type);
+
 static void do_render_3d(Render *re)
 {
+       RenderEngineType *type;
+
+       /* try external */
+       for(type=R_engines.first; type; type=type->next)
+               if(strcmp(type->idname, re->r.engine) == 0)
+                       break;
+
+       if(type && type->render) {
+               external_render_3d(re, type);
+               return;
+       }
+
+       /* internal */
        
 //     re->cfra= cfra; /* <- unused! */
        
@@ -1681,7 +1696,6 @@ static void do_render_3d(Render *re)
        if(re->flag & R_HALO)
                if(!re->test_break(re->tbh))
                        add_halo_flare(re);
-
        
        /* free all render verts etc */
        RE_Database_Free(re);
@@ -2766,3 +2780,163 @@ void RE_init_threadcount(Render *re)
                re->r.threads = BLI_system_thread_count();
        }
 }
+
+/************************** External Engines ***************************/
+
+static RenderEngineType internal_engine_type = {
+       NULL, NULL, "BlenderRenderEngine", "Blender", NULL,
+       NULL, NULL, NULL, NULL};
+
+ListBase R_engines = {&internal_engine_type, &internal_engine_type};
+
+RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
+{
+       Render *re= engine->re;
+       RenderResult *result;
+       rcti disprect;
+
+       /* ensure the coordinates are within the right limits */
+       CLAMP(x, 0, re->result->rectx);
+       CLAMP(y, 0, re->result->recty);
+       CLAMP(w, 0, re->result->rectx);
+       CLAMP(h, 0, re->result->recty);
+
+       if(x + w > re->result->rectx)
+               w= re->result->rectx - x;
+       if(y + h > re->result->recty)
+               h= re->result->recty - y;
+
+       /* allocate a render result */
+       disprect.xmin= x;
+       disprect.xmax= x+w;
+       disprect.ymin= y;
+       disprect.ymax= y+h;
+
+       if(0) { // XXX (re->r.scemode & R_FULL_SAMPLE)) {
+               result= new_full_sample_buffers(re, &engine->fullresult, &disprect, 0);
+       }
+       else {
+               result= new_render_result(re, &disprect, 0, RR_USEMEM);
+               BLI_addtail(&engine->fullresult, result);
+       }
+
+       return result;
+}
+
+void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
+{
+       Render *re= engine->re;
+
+       if(result && render_display_draw_enabled(re)) {
+               result->renlay= result->layers.first; // weak
+               re->display_draw(re->ddh, result, NULL);
+       }
+}
+
+void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
+{
+       Render *re= engine->re;
+
+       if(!result)
+               return;
+
+       /* merge */
+       if(re->result->exrhandle) {
+               RenderResult *rr, *rrpart;
+               
+               // XXX crashes, exr expects very particular part sizes
+               for(rr= re->result, rrpart= result; rr && rrpart; rr= rr->next, rrpart= rrpart->next)
+                       save_render_result_tile(rr, rrpart);
+       }
+       else if(render_display_draw_enabled(re)) {
+               /* on break, don't merge in result for preview renders, looks nicer */
+               if(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS));
+               else merge_render_result(re->result, result);
+       }
+
+       /* draw */
+       if(!re->test_break(re->tbh) && render_display_draw_enabled(re)) {
+               result->renlay= result->layers.first; // weak
+               re->display_draw(re->ddh, result, NULL);
+       }
+
+       /* free */
+       free_render_result(&engine->fullresult, result);
+}
+
+int RE_engine_test_break(RenderEngine *engine)
+{
+       Render *re= engine->re;
+
+       return re->test_break(re->tbh);
+}
+
+void RE_engine_update_stats(RenderEngine *engine, char *stats, char *info)
+{
+       Render *re= engine->re;
+
+       re->i.statstr= stats;
+       re->i.infostr= info;
+       re->stats_draw(re->sdh, &re->i);
+       re->i.infostr= NULL;
+       re->i.statstr= NULL;
+}
+
+static void external_render_3d(Render *re, RenderEngineType *type)
+{
+       RenderEngine engine;
+
+       if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
+               RE_FreeRenderResult(re->result);
+       
+               if(0) // XXX re->r.scemode & R_FULL_SAMPLE)
+                       re->result= new_full_sample_buffers_exr(re);
+               else
+                       re->result= new_render_result(re, &re->disprect, 0, 0); // XXX re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE));
+       }
+       
+       if(re->result==NULL)
+               return;
+
+       /* external */
+       memset(&engine, 0, sizeof(engine));
+       engine.type= type;
+       engine.re= re;
+
+       type->render(&engine, re->scene);
+
+       free_render_result(&engine.fullresult, engine.fullresult.first);
+
+       if(re->result->exrhandle) {
+               RenderResult *rr;
+
+               save_empty_result_tiles(re);
+               
+               for(rr= re->result; rr; rr= rr->next) {
+                       IMB_exr_close(rr->exrhandle);
+                       rr->exrhandle= NULL;
+               }
+               
+               free_render_result(&re->fullresult, re->result);
+               re->result= NULL;
+               
+               read_render_result(re, 0);
+       }
+}
+
+void RE_engines_free()
+{
+       RenderEngineType *type, *next;
+
+       for(type=R_engines.first; type; type=next) {
+               next= type->next;
+
+               if(type != &internal_engine_type) {
+                       if(type->ext.free)
+                               type->ext.free(type->ext.data);
+
+                       MEM_freeN(type);
+               }
+       }
+}
+
index 5c34b19c1f41d79f1f570ce8a31e87d440bb57cc..3d8efc018c42a3a3b8827d44e0489ab341ba50fb 100644 (file)
@@ -239,6 +239,7 @@ void WM_exit(bContext *C)
        BLF_exit();
 
        RE_FreeAllRender();
+       RE_engines_free();
        
 //     free_txt_data();