Bugfix #20565
authorTon Roosendaal <ton@blender.org>
Fri, 3 Dec 2010 14:26:03 +0000 (14:26 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 3 Dec 2010 14:26:03 +0000 (14:26 +0000)
Material Node shaders: displaying GLSL + rendering previews crashed.
Reason was non-safe threaded access to material nodes. Now, on a preview
render, a full copy of Material is being made.

source/blender/editors/render/render_preview.c

index 5697154998ba4fa1ad306e3c46464f06b8b67f18..af210f495537a5570acef085b29a74c910b21202 100644 (file)
@@ -148,6 +148,9 @@ typedef struct ShaderPreview {
        ID *parent;
        MTex *slot;
        
+       /* node materials need full copy during preview render, glsl uses it too */
+       Material *matcopy;
+       
        int sizex, sizey;
        unsigned int *pr_rect;
        int pr_method;
@@ -329,9 +332,9 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                
                sce->r.color_mgt_flag = scene->r.color_mgt_flag;
                /* exception: don't color manage texture previews or icons */
-               if((sp && sp->pr_method==PR_ICON_RENDER) || id_type == ID_TE)
+               if((id && sp->pr_method==PR_ICON_RENDER) || id_type == ID_TE)
                        sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT;
-               if((sp && sp->pr_method==PR_ICON_RENDER) && id_type != ID_WO)
+               if((id && sp->pr_method==PR_ICON_RENDER) && id_type != ID_WO)
                        sce->r.alphamode= R_ALPHAPREMUL;
                else
                        sce->r.alphamode= R_ADDSKY;
@@ -340,9 +343,14 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                strcpy(sce->r.engine, scene->r.engine);
                
                if(id_type==ID_MA) {
-                       Material *mat= (Material *)id;
+                       Material *mat= NULL;
                        
                        if(id) {
+                               /* work on a copy */
+                               mat= copy_material((Material *)id);
+                               sp->matcopy= mat;
+                               BLI_remlink(&G.main->mat, mat);
+                               
                                init_render_material(mat, 0, NULL);             /* call that retrieves mode_l */
                                end_render_material(mat);
                                
@@ -384,7 +392,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                }
 
                                
-                               if(sp && sp->pr_method==PR_ICON_RENDER) {
+                               if(sp->pr_method==PR_ICON_RENDER) {
                                        if (mat->material_type == MA_TYPE_HALO) {
                                                sce->lay= 1<<MA_FLAT;
                                        } 
@@ -400,6 +408,10 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                        }
                        else {
                                sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
+                               
+                               free_material(sp->matcopy);
+                               MEM_freeN(sp->matcopy);
+                               sp->matcopy= NULL;
                        }
                        
                        for(base= sce->base.first; base; base= base->next) {
@@ -428,7 +440,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                        if(mat && mat->mtex[0]) {
                                                mat->mtex[0]->tex= tex;
                                                
-                                               if(sp && sp->slot)
+                                               if(tex && sp->slot)
                                                        mat->mtex[0]->which_output = sp->slot->which_output;
                                                
                                                /* show alpha in this case */
@@ -444,7 +456,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                }
                        }
 
-                       if(tex && tex->nodetree && sp && sp->pr_method==PR_NODE_RENDER)
+                       if(tex && tex->nodetree && sp->pr_method==PR_NODE_RENDER)
                                ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
                }
                else if(id_type==ID_LA) {
@@ -987,7 +999,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
        }
 
        /* unassign the pointers, reset vars */
-       preview_prepare_scene(sp->scene, NULL, GS(id->name), NULL);
+       preview_prepare_scene(sp->scene, NULL, GS(id->name), sp);
 }
 
 /* runs inside thread for material and icons */