Blender V2.61 - r43446

node_shader_common.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
00024  * Juho Vepsäläinen
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "DNA_node_types.h"
00035 
00036 #include "BKE_node.h"
00037 
00038 #include "node_shader_util.h"
00039 #include "node_common.h"
00040 #include "node_exec.h"
00041 
00042 static void copy_stack(bNodeStack *to, bNodeStack *from)
00043 {
00044     if (to != from) {
00045         copy_v4_v4(to->vec, from->vec);
00046         to->data = from->data;
00047         to->datatype = from->datatype;
00048         
00049         /* tag as copy to prevent freeing */
00050         to->is_copy = 1;
00051     }
00052 }
00053 
00054 static void move_stack(bNodeStack *to, bNodeStack *from)
00055 {
00056     if (to != from) {
00057         copy_v4_v4(to->vec, from->vec);
00058         to->data = from->data;
00059         to->datatype = from->datatype;
00060         to->is_copy = from->is_copy;
00061         
00062         zero_v4(from->vec);
00063         from->data = NULL;
00064         from->datatype = 0;
00065         from->is_copy = 0;
00066     }
00067 }
00068 
00069 /**** GROUP ****/
00070 
00071 static void *group_initexec(bNode *node)
00072 {
00073     bNodeTree *ngroup= (bNodeTree*)node->id;
00074     bNodeTreeExec *exec;
00075     
00076     /* initialize the internal node tree execution */
00077     exec = ntreeShaderBeginExecTree(ngroup, 0);
00078     
00079     return exec;
00080 }
00081 
00082 static void group_freeexec(bNode *UNUSED(node), void *nodedata)
00083 {
00084     bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
00085     
00086     ntreeShaderEndExecTree(gexec, 0);
00087 }
00088 
00089 /* Copy inputs to the internal stack.
00090  */
00091 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
00092 {
00093     bNodeSocket *sock;
00094     bNodeStack *ns;
00095     int a;
00096     for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
00097         if (sock->groupsock) {
00098             ns = node_get_socket_stack(gstack, sock->groupsock);
00099             copy_stack(ns, in[a]);
00100         }
00101     }
00102 }
00103 
00104 /* Copy internal results to the external outputs.
00105  */
00106 static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
00107 {
00108     bNodeSocket *sock;
00109     bNodeStack *ns;
00110     int a;
00111     for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
00112         if (sock->groupsock) {
00113             ns = node_get_socket_stack(gstack, sock->groupsock);
00114             move_stack(out[a], ns);
00115         }
00116     }
00117 }
00118 
00119 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00120 {
00121     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00122     bNodeThreadStack *nts;
00123     
00124     /* XXX same behavior as trunk: all nodes inside group are executed.
00125      * it's stupid, but just makes it work. compo redesign will do this better.
00126      */
00127     {
00128         bNode *inode;
00129         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00130             inode->need_exec = 1;
00131     }
00132     
00133     nts = ntreeGetThreadStack(exec, thread);
00134     
00135     group_copy_inputs(node, in, nts->stack);
00136     ntreeExecThreadNodes(exec, nts, data, thread);
00137     group_move_outputs(node, out, nts->stack);
00138     
00139     ntreeReleaseThreadStack(nts);
00140 }
00141 
00142 static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack)
00143 {
00144     bNodeSocket *sock;
00145     bNodeStack *ns;
00146     int a;
00147     for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
00148         if (sock->groupsock) {
00149             ns = node_get_socket_stack(gstack, sock->groupsock);
00150             /* convert the external gpu stack back to internal node stack data */
00151             node_data_from_gpu_stack(ns, &in[a]);
00152         }
00153     }
00154 }
00155 
00156 /* Copy internal results to the external outputs.
00157  */
00158 static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack)
00159 {
00160     bNodeSocket *sock;
00161     bNodeStack *ns;
00162     int a;
00163     for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
00164         if (sock->groupsock) {
00165             ns = node_get_socket_stack(gstack, sock->groupsock);
00166             /* convert the node stack data result back to gpu stack */
00167             node_gpu_stack_from_data(&out[a], sock->type, ns);
00168         }
00169     }
00170 }
00171 
00172 static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out)
00173 {
00174     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00175     
00176     group_gpu_copy_inputs(node, in, exec->stack);
00177     ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT));
00178     group_gpu_move_outputs(node, out, exec->stack);
00179     
00180     return 1;
00181 }
00182 
00183 void register_node_type_sh_group(bNodeTreeType *ttype)
00184 {
00185     static bNodeType ntype;
00186 
00187     node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
00188     node_type_socket_templates(&ntype, NULL, NULL);
00189     node_type_size(&ntype, 120, 60, 200);
00190     node_type_label(&ntype, node_group_label);
00191     node_type_init(&ntype, node_group_init);
00192     node_type_valid(&ntype, node_group_valid);
00193     node_type_template(&ntype, node_group_template);
00194     node_type_update(&ntype, NULL, node_group_verify);
00195     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00196     node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
00197     node_type_gpu_ext(&ntype, gpu_group_execute);
00198     
00199     nodeRegisterType(ttype, &ntype);
00200 }
00201 
00202 
00203 /**** FOR LOOP ****/
00204 
00205 #if 0 /* XXX loop nodes don't work nicely with current trees */
00206 static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00207 {
00208     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00209     bNodeThreadStack *nts;
00210     int iterations= (int)in[0]->vec[0];
00211     bNodeSocket *sock;
00212     bNodeStack *ns;
00213     int iteration;
00214     
00215     /* XXX same behavior as trunk: all nodes inside group are executed.
00216      * it's stupid, but just makes it work. compo redesign will do this better.
00217      */
00218     {
00219         bNode *inode;
00220         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00221             inode->need_exec = 1;
00222     }
00223     
00224     nts = ntreeGetThreadStack(exec, thread);
00225     
00226     /* "Iteration" socket */
00227     sock = exec->nodetree->inputs.first;
00228     ns = node_get_socket_stack(nts->stack, sock);
00229     
00230 //  group_copy_inputs(node, in, nts->stack);
00231     for (iteration=0; iteration < iterations; ++iteration) {
00232         /* first input contains current iteration counter */
00233         ns->vec[0] = (float)iteration;
00234         ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f;
00235         
00236 //      if (iteration > 0)
00237 //          loop_init_iteration(exec->nodetree, nts->stack);
00238 //      ntreeExecThreadNodes(exec, nts, data, thread);
00239     }
00240 //  loop_copy_outputs(node, in, out, exec->stack);
00241     
00242     ntreeReleaseThreadStack(nts);
00243 }
00244 
00245 void register_node_type_sh_forloop(bNodeTreeType *ttype)
00246 {
00247     static bNodeType ntype;
00248 
00249     node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS);
00250     node_type_socket_templates(&ntype, NULL, NULL);
00251     node_type_size(&ntype, 120, 60, 200);
00252     node_type_label(&ntype, node_group_label);
00253     node_type_init(&ntype, node_forloop_init);
00254     node_type_valid(&ntype, node_group_valid);
00255     node_type_template(&ntype, node_forloop_template);
00256     node_type_update(&ntype, NULL, node_group_verify);
00257     node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree);
00258     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00259     node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute);
00260     
00261     nodeRegisterType(ttype, &ntype);
00262 }
00263 #endif
00264 
00265 /**** WHILE LOOP ****/
00266 
00267 #if 0 /* XXX loop nodes don't work nicely with current trees */
00268 static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00269 {
00270     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00271     bNodeThreadStack *nts;
00272     int condition= (in[0]->vec[0] > 0.0f);
00273     bNodeSocket *sock;
00274     bNodeStack *ns;
00275     int iteration;
00276     
00277     /* XXX same behavior as trunk: all nodes inside group are executed.
00278      * it's stupid, but just makes it work. compo redesign will do this better.
00279      */
00280     {
00281         bNode *inode;
00282         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00283             inode->need_exec = 1;
00284     }
00285     
00286     nts = ntreeGetThreadStack(exec, thread);
00287     
00288     /* "Condition" socket */
00289     sock = exec->nodetree->outputs.first;
00290     ns = node_get_socket_stack(nts->stack, sock);
00291     
00292     iteration = 0;
00293 //  group_copy_inputs(node, in, nts->stack);
00294     while (condition && iteration < node->custom1) {
00295 //      if (iteration > 0)
00296 //          loop_init_iteration(exec->nodetree, nts->stack);
00297 //      ntreeExecThreadNodes(exec, nts, data, thread);
00298         
00299         condition = (ns->vec[0] > 0.0f);
00300         ++iteration;
00301     }
00302 //  loop_copy_outputs(node, in, out, exec->stack);
00303     
00304     ntreeReleaseThreadStack(nts);
00305 }
00306 
00307 void register_node_type_sh_whileloop(bNodeTreeType *ttype)
00308 {
00309     static bNodeType ntype;
00310 
00311     node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS);
00312     node_type_socket_templates(&ntype, NULL, NULL);
00313     node_type_size(&ntype, 120, 60, 200);
00314     node_type_label(&ntype, node_group_label);
00315     node_type_init(&ntype, node_whileloop_init);
00316     node_type_valid(&ntype, node_group_valid);
00317     node_type_template(&ntype, node_whileloop_template);
00318     node_type_update(&ntype, NULL, node_group_verify);
00319     node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree);
00320     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00321     node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute);
00322     
00323     nodeRegisterType(ttype, &ntype);
00324 }
00325 #endif