Bugfix #25301
authorTon Roosendaal <ton@blender.org>
Sun, 19 Dec 2010 20:12:12 +0000 (20:12 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 19 Dec 2010 20:12:12 +0000 (20:12 +0000)
Preview render for node shaders broke, caused by localizing
materials last week, to prevent thread crashes. Fixed now.
Also added a temp fix to draw color-management corrected
node previews default. Will follow scene setting tomorrow.

Also: SSS in nodes doesn't render yet. Was issue in 2.4 too...

source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/node.c
source/blender/editors/render/render_preview.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/sss.c

index 53bb95c..16c99cd 100644 (file)
@@ -49,6 +49,7 @@ void resize_object_material(struct Object *ob, const short totcol);
 void init_material(struct Material *ma);
 struct Material *add_material(const char *name);
 struct Material *copy_material(struct Material *ma);
+struct Material *localize_material(struct Material *ma);
 struct Material *give_node_material(struct Material *ma); /* returns node material or self */
 void make_local_material(struct Material *ma);
 
index 30df188..cac41e4 100644 (file)
@@ -44,6 +44,7 @@
 #include "DNA_scene_types.h"
 
 #include "BLI_math.h"          
+#include "BLI_listbase.h"              
 
 #include "BKE_animsys.h"
 #include "BKE_displist.h"
@@ -196,6 +197,7 @@ Material *add_material(const char *name)
        return ma;      
 }
 
+/* XXX keep synced with next function */
 Material *copy_material(Material *ma)
 {
        Material *man;
@@ -227,6 +229,38 @@ Material *copy_material(Material *ma)
        return man;
 }
 
+/* XXX (see above) material copy without adding to main dbase */
+Material *localize_material(Material *ma)
+{
+       Material *man;
+       int a;
+       
+       man= copy_libblock(ma);
+       BLI_remlink(&G.main->mat, man);
+
+       for(a=0; a<MAX_MTEX; a++) {
+               if(ma->mtex[a]) {
+                       man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
+                       memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
+                       /* free_material decrements! */
+                       id_us_plus((ID *)man->mtex[a]->tex);
+               }
+       }
+       
+       if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
+       if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
+       
+       if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
+       
+       if(ma->nodetree) {
+               man->nodetree= ntreeLocalize(ma->nodetree);
+       }
+       
+       man->gpumaterial.first= man->gpumaterial.last= NULL;
+       
+       return man;
+}
+
 void make_local_material(Material *ma)
 {
        Main *bmain= G.main;
index 4b158f4..663a2d8 100644 (file)
@@ -1186,12 +1186,12 @@ static void node_init_preview(bNode *node, int xsize, int ysize)
        }
        
        if(node->preview->rect==NULL) {
-               node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
+               node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(char)*4, "node preview rect");
                node->preview->xsize= xsize;
                node->preview->ysize= ysize;
        }
        else
-               memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(float)*4);
+               memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(char)*4);
 }
 
 void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
@@ -1241,12 +1241,18 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y)
                if(x>=0 && y>=0) {
                        if(x<preview->xsize && y<preview->ysize) {
                                unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x);
-                               //if(tar[0]==0.0f) {
-                               tar[0]= FTOCHAR(col[0]);
-                               tar[1]= FTOCHAR(col[1]);
-                               tar[2]= FTOCHAR(col[2]);
+                               
+                               if(TRUE) {
+                                       tar[0]= FTOCHAR(linearrgb_to_srgb(col[0]));
+                                       tar[1]= FTOCHAR(linearrgb_to_srgb(col[1]));
+                                       tar[2]= FTOCHAR(linearrgb_to_srgb(col[2]));
+                               }
+                               else {
+                                       tar[0]= FTOCHAR(col[0]);
+                                       tar[1]= FTOCHAR(col[1]);
+                                       tar[2]= FTOCHAR(col[2]);
+                               }
                                tar[3]= FTOCHAR(col[3]);
-                               //}
                        }
                        //else printf("prv out bound x y %d %d\n", x, y);
                }
@@ -1699,33 +1705,36 @@ static void ntreeSetOutput(bNodeTree *ntree)
 {
        bNode *node;
 
-       /* find the active outputs, might become tree type dependant handler */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                       bNode *tnode;
-                       int output= 0;
-                       
-                       /* we need a check for which output node should be tagged like this, below an exception */
-                       if(node->type==CMP_NODE_OUTPUT_FILE)
-                          continue;
-                          
-                       /* there is more types having output class, each one is checked */
-                       for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
-                               if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                                       /* same type, exception for viewer */
-                                       if(tnode->type==node->type ||
-                                          (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
-                                           ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
-                                               if(tnode->flag & NODE_DO_OUTPUT) {
-                                                       output++;
-                                                       if(output>1)
-                                                               tnode->flag &= ~NODE_DO_OUTPUT;
+       if(ntree->type==NTREE_COMPOSIT) {
+               
+               /* find the active outputs, might become tree type dependant handler */
+               for(node= ntree->nodes.first; node; node= node->next) {
+                       if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                               bNode *tnode;
+                               int output= 0;
+                               
+                               /* we need a check for which output node should be tagged like this, below an exception */
+                               if(node->type==CMP_NODE_OUTPUT_FILE)
+                                  continue;
+                                  
+                               /* there is more types having output class, each one is checked */
+                               for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
+                                       if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                                               /* same type, exception for viewer */
+                                               if(tnode->type==node->type ||
+                                                  (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
+                                                       ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
+                                                       if(tnode->flag & NODE_DO_OUTPUT) {
+                                                               output++;
+                                                               if(output>1)
+                                                                       tnode->flag &= ~NODE_DO_OUTPUT;
+                                                       }
                                                }
                                        }
                                }
+                               if(output==0)
+                                       node->flag |= NODE_DO_OUTPUT;
                        }
-                       if(output==0)
-                               node->flag |= NODE_DO_OUTPUT;
                }
        }
        
@@ -2586,8 +2595,6 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
        /* ensures only a single output node is enabled */
        ntreeSetOutput(ntree);
 
-       /* move over the compbufs */
-       /* right after ntreeCopyTree() oldsock pointers are valid */
        for(node= ntree->nodes.first; node; node= node->next) {
                
                /* store new_node pointer to original */
@@ -2595,22 +2602,27 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
                /* ensure new user input gets handled ok */
                node->need_exec= 0;
                
-               if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
-                       if(node->id) {
-                               if(node->flag & NODE_DO_OUTPUT)
-                                       node->new_node->id= (ID *)copy_image((Image *)node->id);
-                               else
-                                       node->new_node->id= NULL;
-                       }
-               }
-               
-               for(sock= node->outputs.first; sock; sock= sock->next) {
+               if(ntree->type==NTREE_COMPOSIT) {
+                       /* move over the compbufs */
+                       /* right after ntreeCopyTree() oldsock pointers are valid */
                        
-                       sock->new_sock->ns.data= sock->ns.data;
-                       compbuf_set_node(sock->new_sock->ns.data, node->new_node);
+                       if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+                               if(node->id) {
+                                       if(node->flag & NODE_DO_OUTPUT)
+                                               node->new_node->id= (ID *)copy_image((Image *)node->id);
+                                       else
+                                               node->new_node->id= NULL;
+                               }
+                       }
                        
-                       sock->ns.data= NULL;
-                       sock->new_sock->new_sock= sock;
+                       for(sock= node->outputs.first; sock; sock= sock->next) {
+                               
+                               sock->new_sock->ns.data= sock->ns.data;
+                               compbuf_set_node(sock->new_sock->ns.data, node->new_node);
+                               
+                               sock->ns.data= NULL;
+                               sock->new_sock->new_sock= sock;
+                       }
                }
        }
        
@@ -2638,19 +2650,38 @@ static int outsocket_exists(bNode *node, bNodeSocket *testsock)
 
 /* sync local composite with real tree */
 /* local composite is supposed to be running, be careful moving previews! */
+/* is called by jobs manager, outside threads, so it doesnt happen during draw */
 void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
 {
        bNode *lnode;
        
-       /* move over the compbufs and previews */
-       for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
-               if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
+       if(ntree->type==NTREE_COMPOSIT) {
+               /* move over the compbufs and previews */
+               for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
+                       if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
+                               if(node_exists(ntree, lnode->new_node)) {
+                                       
+                                       if(lnode->preview && lnode->preview->rect) {
+                                               node_free_preview(lnode->new_node);
+                                               lnode->new_node->preview= lnode->preview;
+                                               lnode->preview= NULL;
+                                       }
+                               }
+                       }
+               }
+       }
+       else if(ntree->type==NTREE_SHADER) {
+               /* copy over contents of previews */
+               for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
                        if(node_exists(ntree, lnode->new_node)) {
+                               bNode *node= lnode->new_node;
                                
-                               if(lnode->preview && lnode->preview->rect) {
-                                       node_free_preview(lnode->new_node);
-                                       lnode->new_node->preview= lnode->preview;
-                                       lnode->preview= NULL;
+                               if(node->preview && node->preview->rect) {
+                                       if(lnode->preview && lnode->preview->rect) {
+                                               int xsize= node->preview->xsize;
+                                               int ysize= node->preview->ysize;
+                                               memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4);
+                                       }
                                }
                        }
                }
index 61fb930..f492d9a 100644 (file)
@@ -343,13 +343,12 @@ 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= NULL;
+                       Material *mat= NULL, *origmat= (Material *)id;
                        
                        if(id) {
                                /* work on a copy */
-                               mat= copy_material((Material *)id);
+                               mat= localize_material(origmat);
                                sp->matcopy= mat;
-                               BLI_remlink(&G.main->mat, mat);
                                BLI_addtail(&pr_main->mat, mat);
                                
                                init_render_material(mat, 0, NULL);             /* call that retrieves mode_l */
@@ -403,18 +402,16 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
                                }
                                else {
                                        sce->lay= 1<<mat->pr_type;
-                                       if(mat->nodetree && sp->pr_method==PR_NODE_RENDER)
+                                       if(mat->nodetree && sp->pr_method==PR_NODE_RENDER) {
+                                               /* two previews, they get copied by wmJob */
                                                ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
+                                               ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
+                                       }
                                }
                        }
                        else {
                                sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
                                
-                               /* get rid of copied material */
-                               BLI_remlink(&pr_main->mat, sp->matcopy);
-                               free_material(sp->matcopy);
-                               MEM_freeN(sp->matcopy);
-                               sp->matcopy= NULL;
                        }
                        
                        for(base= sce->base.first; base; base= base->next) {
@@ -918,10 +915,14 @@ static int shader_preview_break(void *spv)
 }
 
 /* outside thread, called before redraw notifiers, it moves finished preview over */
-static void shader_preview_updatejob(void *UNUSED(spv))
+static void shader_preview_updatejob(void *spv)
 {
-//     ShaderPreview *sp= spv;
+       ShaderPreview *sp= spv;
+       Material *mat= (Material *)sp->id;
        
+       if(sp->matcopy && mat->nodetree)
+               ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree);
+
 }
 
 static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first)
@@ -1027,6 +1028,16 @@ static void shader_preview_free(void *customdata)
 {
        ShaderPreview *sp= customdata;
        
+       if(sp->matcopy) {
+               /* node previews */
+               shader_preview_updatejob(sp);
+               
+               /* get rid of copied material */
+               BLI_remlink(&pr_main->mat, sp->matcopy);
+               free_material(sp->matcopy);
+               MEM_freeN(sp->matcopy);
+       }
+       
        MEM_freeN(sp);
 }
 
index 4dedcbd..5df593e 100644 (file)
@@ -2050,7 +2050,7 @@ static void load_backbuffer(Render *re)
                char name[256];
                
                strcpy(name, re->r.backbuf);
-               BLI_path_abs(name, G.main->name);
+               BLI_path_abs(name, re->main->name);
                BLI_path_frame(name, re->r.cfra, 0);
                
                if(re->backbuf) {
index 1e8709d..993e0ae 100644 (file)
@@ -56,6 +56,7 @@
 #include "DNA_material_types.h"
 
 #include "BKE_colortools.h"
+#include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_node.h"
@@ -995,6 +996,7 @@ void make_sss_tree(Render *re)
        for(mat= re->main->mat.first; mat; mat= mat->id.next)
                if(mat->id.us && (mat->flag & MA_IS_USED) && (mat->sss_flag & MA_DIFF_SSS))
                        sss_create_tree_mat(re, mat);
+       
 }
 
 void free_sss(Render *re)