Fix for a crash when freeing copied scenes.
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Tue, 29 Jan 2013 03:12:49 +0000 (03:12 +0000)
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>
Tue, 29 Jan 2013 03:12:49 +0000 (03:12 +0000)
The problem was caused by the fact that BKE_scene_copy() was simply doing "memcpy"
to duplicate render layers including lineset settings without taking care of pointers
in the linesets.  For this reason, freeing the original scene and copied one resulted
in freeing allocated memory buffers twice.

Now BKE_scene_copy() properly duplicates linesets as part of render layers.

Also some code clean-up was made in the modified files.

Problem report by IRIE Shinsuke (with a patch to fix the crash).  Many thanks!

source/blender/blenkernel/intern/scene.c
source/blender/freestyle/FRS_freestyle.h
source/blender/freestyle/FRS_freestyle_config.h
source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
source/blender/render/intern/source/render_result.c

index 285646191f755217b49279f6827086e4bfa5733a..ba43f238e7605203b8eb58a2b12f5e05e7c233eb 100644 (file)
@@ -210,6 +210,22 @@ Scene *BKE_scene_copy(Scene *sce, int type)
                /* remove animation used by sequencer */
                if (type != SCE_COPY_FULL)
                        remove_sequencer_fcurves(scen);
+
+#ifdef WITH_FREESTYLE
+               {
+                       SceneRenderLayer *srl, *new_srl;
+
+                       new_srl = scen->r.layers.first;
+                       for (srl = sce->r.layers.first; srl; srl = srl->next) {
+                               if (type == SCE_COPY_FULL) {
+                                       FRS_copy_freestyle_config(&new_srl->freestyleConfig, &srl->freestyleConfig);
+                               } else {
+                                       FRS_init_freestyle_config(&srl->freestyleConfig);
+                               }
+                               new_srl = new_srl->next;
+                       }
+               }
+#endif
        }
 
        /* tool settings */
@@ -340,7 +356,7 @@ void BKE_scene_free(Scene *sce)
                SceneRenderLayer *srl;
 
                for (srl = sce->r.layers.first; srl; srl = srl->next) {
-                       FRS_free_freestyle_config(srl);
+                       FRS_free_freestyle_config(&srl->freestyleConfig);
                }
        }
 #endif
@@ -1267,7 +1283,7 @@ SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
        srl->layflag = 0x7FFF;   /* solid ztra halo edge strand */
        srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
 #ifdef WITH_FREESTYLE
-       FRS_add_freestyle_config(srl);
+       FRS_init_freestyle_config(&srl->freestyleConfig);
 #endif
 
        return srl;
index ece51d2004827dc5b0684b68849ae1f18d18bc6b..3eaa1f3fbedb162de1918290f0cc9976dad28fb1 100644 (file)
@@ -61,12 +61,15 @@ void FRS_finish_stroke_rendering(struct Render* re);
 void FRS_composite_result(struct Render* re, struct SceneRenderLayer* srl, struct Render* freestyle_render);
 void FRS_exit(void);
 
-/* Panel configuration */
+/* FreestyleConfig.modules */
+FreestyleModuleConfig *FRS_alloc_module(void);
 void FRS_add_module(FreestyleConfig *config);
 void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
 void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
 void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
 
+/* FreestyleConfig.linesets */
+FreestyleLineSet *FRS_alloc_lineset(void);
 FreestyleLineSet *FRS_add_lineset(FreestyleConfig *config);
 void FRS_copy_active_lineset(FreestyleConfig *config);
 void FRS_paste_active_lineset(FreestyleConfig *config);
index 0aceffcee1dfecc7ebb5e7e851692caad374468c..3a1d1482ec09d2c1ca55eab702641856a346cd88 100644 (file)
@@ -38,8 +38,10 @@ extern "C" {
 
 #include "DNA_scene_types.h"
 
-void FRS_add_freestyle_config(SceneRenderLayer* srl);
-void FRS_free_freestyle_config(SceneRenderLayer* srl);
+void FRS_init_freestyle_config(FreestyleConfig *config);
+void FRS_free_freestyle_config(FreestyleConfig *config);
+
+void FRS_copy_freestyle_config(FreestyleConfig *new_config, FreestyleConfig *config);
 
 #ifdef __cplusplus
 }
index 97a84a284e07b3ada2eb68f394fd3a931a489021..543c47b21535e55b3f819c88400585b0c5e1ba09 100644 (file)
@@ -95,6 +95,10 @@ Scene *freestyle_scene;
 
 string default_module_path;
 
+// function declarations
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset);
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module);
+
 //=======================================================
 //   Initialization 
 //=======================================================
@@ -641,10 +645,8 @@ void FRS_finish_stroke_rendering(Render *re) {
 //   Freestyle Panel Configuration
 //=======================================================
 
-void FRS_add_freestyle_config(SceneRenderLayer *srl)
+void FRS_init_freestyle_config(FreestyleConfig *config)
 {
-       FreestyleConfig *config = &srl->freestyleConfig;
-
        config->mode = FREESTYLE_CONTROL_SCRIPT_MODE;
 
        config->modules.first = config->modules.last = NULL;
@@ -656,11 +658,11 @@ void FRS_add_freestyle_config(SceneRenderLayer *srl)
        config->linesets.first = config->linesets.last = NULL;
 }
 
-void FRS_free_freestyle_config(SceneRenderLayer *srl)
+void FRS_free_freestyle_config(FreestyleConfig *config)
 {
        FreestyleLineSet *lineset;
 
-       for (lineset = (FreestyleLineSet*)srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+       for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) {
                if (lineset->group) {
                        lineset->group->id.us--;
                        lineset->group = NULL;
@@ -668,8 +670,58 @@ void FRS_free_freestyle_config(SceneRenderLayer *srl)
                lineset->linestyle->id.us--;
                lineset->linestyle = NULL;
        }
-       BLI_freelistN(&srl->freestyleConfig.linesets);
-       BLI_freelistN(&srl->freestyleConfig.modules);
+       BLI_freelistN(&config->linesets);
+       BLI_freelistN(&config->modules);
+}
+
+void FRS_copy_freestyle_config(FreestyleConfig *new_config, FreestyleConfig *config)
+{
+       FreestyleLineSet *lineset, *new_lineset;
+       FreestyleModuleConfig *module, *new_module;
+
+       new_config->mode = config->mode;
+       new_config->raycasting_algorithm = config->raycasting_algorithm; /* deprecated */
+       new_config->flags = config->flags;
+       new_config->sphere_radius = config->sphere_radius;
+       new_config->dkr_epsilon = config->dkr_epsilon;
+       new_config->crease_angle = config->crease_angle;
+
+       new_config->linesets.first = new_config->linesets.last = NULL;
+       for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) {
+               new_lineset = FRS_alloc_lineset();
+               copy_lineset(new_lineset, lineset);
+               BLI_addtail(&new_config->linesets, (void*)new_lineset);
+       }
+
+       new_config->modules.first = new_config->modules.last = NULL;
+       for (module = (FreestyleModuleConfig*)config->modules.first; module; module = module->next) {
+               new_module = FRS_alloc_module();
+               copy_module(new_module, module);
+               BLI_addtail(&new_config->modules, (void*)new_module);
+       }
+}
+
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset)
+{
+       new_lineset->linestyle = lineset->linestyle;
+       new_lineset->linestyle->id.us++;
+       new_lineset->flags = lineset->flags;
+       new_lineset->selection = lineset->selection;
+       new_lineset->qi = lineset->qi;
+       new_lineset->qi_start = lineset->qi_start;
+       new_lineset->qi_end = lineset->qi_end;
+       new_lineset->edge_types = lineset->edge_types;
+       new_lineset->exclude_edge_types = lineset->exclude_edge_types;
+       new_lineset->group = lineset->group;
+       if (new_lineset->group) {
+               new_lineset->group->id.us++;
+       }
+       strcpy(new_lineset->name, lineset->name);
+}
+
+FreestyleModuleConfig *FRS_alloc_module()
+{
+       return (FreestyleModuleConfig*)MEM_callocN(sizeof(FreestyleModuleConfig), "style module configuration");
 }
 
 void FRS_add_module(FreestyleConfig *config)
@@ -682,6 +734,12 @@ void FRS_add_module(FreestyleConfig *config)
        module_conf->is_displayed = 1;
 }
 
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module)
+{
+       strcpy(new_module->module_path, module->module_path);
+       new_module->is_displayed = module->is_displayed;
+}
+
 void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
 {
        BLI_freelinkN(&config->modules, module_conf);
@@ -705,11 +763,16 @@ static void unique_lineset_name(FreestyleConfig *config, FreestyleLineSet *lines
                       sizeof(lineset->name));
 }
 
+FreestyleLineSet *FRS_alloc_lineset()
+{
+       return (FreestyleLineSet*)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set");
+}
+
 FreestyleLineSet *FRS_add_lineset(FreestyleConfig *config)
 {
        int lineset_index = BLI_countlist(&config->linesets);
 
-       FreestyleLineSet *lineset = (FreestyleLineSet*)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set");
+       FreestyleLineSet *lineset = FRS_alloc_lineset();
        BLI_addtail(&config->linesets, (void*)lineset);
        FRS_set_active_lineset_index(config, lineset_index);
 
index 62919297e73e7c778e9ee8c5969e6c5bb17f30b9..11c6356f9c5332e7bc6e900847e48ca7eb25651a 100644 (file)
@@ -569,7 +569,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
                rl->layflag = 0x7FFF;    /* solid ztra halo strand */
                rl->passflag = SCE_PASS_COMBINED;
 #ifdef WITH_FREESTYLE
-               FRS_add_freestyle_config( srl );
+               FRS_init_freestyle_config(&srl->freestyleConfig);
 #endif
                
                re->r.actlay = 0;