~ubuntu-branches/ubuntu/trusty/blender/trusty-proposed

« back to all changes in this revision

Viewing changes to source/blender/nodes/shader/node_shader_tree.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2013-08-14 10:43:49 UTC
  • mfrom: (14.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20130814104349-t1d5mtwkphp12dyj
Tags: 2.68a-3
* Upload to unstable
* debian/: python3.3 Depends simplified
  - debian/control: python3.3 Depends dropped
    for blender-data package
  - 0001-blender_thumbnailer.patch refreshed
* debian/control: libavcodec b-dep versioning dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include "DNA_material_types.h"
37
37
#include "DNA_node_types.h"
38
38
#include "DNA_scene_types.h"
 
39
#include "DNA_space_types.h"
39
40
#include "DNA_world_types.h"
40
41
 
41
42
#include "BLI_listbase.h"
45
46
 
46
47
#include "BLF_translation.h"
47
48
 
 
49
#include "BKE_context.h"
48
50
#include "BKE_global.h"
49
51
#include "BKE_main.h"
50
52
#include "BKE_node.h"
51
53
#include "BKE_scene.h"
52
54
 
 
55
#include "RNA_access.h"
 
56
 
53
57
#include "GPU_material.h"
54
58
 
55
59
#include "RE_shader_ext.h"
59
63
#include "node_util.h"
60
64
#include "node_shader_util.h"
61
65
 
62
 
static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
63
 
{
64
 
        Material *ma;
65
 
        Lamp *la;
66
 
        World *wo;
67
 
 
68
 
        for (ma = main->mat.first; ma; ma = ma->id.next)
69
 
                if (ma->nodetree)
70
 
                        func(calldata, &ma->id, ma->nodetree);
71
 
 
72
 
        for (la = main->lamp.first; la; la = la->id.next)
73
 
                if (la->nodetree)
74
 
                        func(calldata, &la->id, la->nodetree);
75
 
 
76
 
        for (wo = main->world.first; wo; wo = wo->id.next)
77
 
                if (wo->nodetree)
78
 
                        func(calldata, &wo->id, wo->nodetree);
 
66
static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
 
67
{
 
68
        Scene *scene = CTX_data_scene(C);
 
69
        /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
 
70
        return (scene->r.engine[0] == '\0' ||
 
71
                STREQ(scene->r.engine, "BLENDER_RENDER") ||
 
72
                STREQ(scene->r.engine, "BLENDER_GAME") ||
 
73
                STREQ(scene->r.engine, "CYCLES"));
 
74
}
 
75
 
 
76
static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
 
77
{
 
78
        SpaceNode *snode = CTX_wm_space_node(C);
 
79
        Scene *scene = CTX_data_scene(C);
 
80
        Object *ob = OBACT;
 
81
        
 
82
        if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
 
83
                if (ob) {
 
84
                        *r_from = &ob->id;
 
85
                        if (ob->type == OB_LAMP) {
 
86
                                *r_id = ob->data;
 
87
                                *r_ntree = ((Lamp *)ob->data)->nodetree;
 
88
                        }
 
89
                        else {
 
90
                                Material *ma = give_current_material(ob, ob->actcol);
 
91
                                if (ma) {
 
92
                                        *r_id = &ma->id;
 
93
                                        *r_ntree = ma->nodetree;
 
94
                                }
 
95
                        }
 
96
                }
 
97
        }
 
98
        else { /* SNODE_SHADER_WORLD */
 
99
                if (scene->world) {
 
100
                        *r_from = NULL;
 
101
                        *r_id = &scene->world->id;
 
102
                        *r_ntree = scene->world->nodetree;
 
103
                }
 
104
        }
79
105
}
80
106
 
81
107
static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
93
119
        func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
94
120
        func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
95
121
        func(calldata, NODE_CLASS_GROUP, N_("Group"));
 
122
        func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
96
123
        func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
97
124
}
98
125
 
113
140
 
114
141
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
115
142
{
116
 
        bNode *lnode;
117
 
        
118
 
        /* copy over contents of previews */
119
 
        for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
120
 
                if (ntreeNodeExists(ntree, lnode->new_node)) {
121
 
                        bNode *node = lnode->new_node;
122
 
                        
123
 
                        if (node->preview && node->preview->rect) {
124
 
                                if (lnode->preview && lnode->preview->rect) {
125
 
                                        int xsize = node->preview->xsize;
126
 
                                        int ysize = node->preview->ysize;
127
 
                                        memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
128
 
                                }
129
 
                        }
130
 
                }
131
 
        }
 
143
        BKE_node_preview_sync_tree(ntree, localtree);
 
144
}
 
145
 
 
146
static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
 
147
{
 
148
        BKE_node_preview_merge_tree(ntree, localtree, true);
132
149
}
133
150
 
134
151
static void update(bNodeTree *ntree)
136
153
        ntreeSetOutput(ntree);
137
154
        
138
155
        ntree_update_reroute_nodes(ntree);
139
 
}
140
 
 
141
 
bNodeTreeType ntreeType_Shader = {
142
 
        /* type */                              NTREE_SHADER,
143
 
        /* id_name */                   "NTShader Nodetree",
144
 
        
145
 
        /* node_types */                { NULL, NULL },
146
 
        
147
 
        /* free_cache */                NULL,
148
 
        /* free_node_cache */   NULL,
149
 
        /* foreach_nodetree */  foreach_nodetree,
150
 
        /* foreach_nodeclass */ foreach_nodeclass,
151
 
        /* localize */                  localize,
152
 
        /* local_sync */                local_sync,
153
 
        /* local_merge */               NULL,
154
 
        /* update */                    update,
155
 
        /* update_node */               NULL,
156
 
        /* validate_link */             NULL,
157
 
        /* update_internal_links */     node_update_internal_links_default
158
 
};
 
156
        
 
157
        if (ntree->update & NTREE_UPDATE_NODES) {
 
158
                /* clean up preview cache, in case nodes have been removed */
 
159
                BKE_node_preview_remove_unused(ntree);
 
160
        }
 
161
}
 
162
 
 
163
bNodeTreeType *ntreeType_Shader;
 
164
 
 
165
void register_node_tree_type_sh(void)
 
166
{
 
167
        bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
 
168
        
 
169
        tt->type = NTREE_SHADER;
 
170
        strcpy(tt->idname, "ShaderNodeTree");
 
171
        strcpy(tt->ui_name, "Shader");
 
172
        tt->ui_icon = 0;    /* defined in drawnode.c */
 
173
        strcpy(tt->ui_description, "Shader nodes");
 
174
        
 
175
        tt->foreach_nodeclass = foreach_nodeclass;
 
176
        tt->localize = localize;
 
177
        tt->local_sync = local_sync;
 
178
        tt->local_merge = local_merge;
 
179
        tt->update = update;
 
180
        tt->poll = shader_tree_poll;
 
181
        tt->get_from_context = shader_get_from_context;
 
182
        
 
183
        tt->ext.srna = &RNA_ShaderNodeTree;
 
184
        
 
185
        ntreeTypeAdd(tt);
 
186
}
159
187
 
160
188
/* GPU material from shader nodes */
161
189
 
163
191
{
164
192
        bNodeTreeExec *exec;
165
193
 
166
 
        exec = ntreeShaderBeginExecTree(ntree, 1);
 
194
        exec = ntreeShaderBeginExecTree(ntree);
167
195
 
168
196
        ntreeExecGPUNodes(exec, mat, 1);
169
197
 
170
 
        ntreeShaderEndExecTree(exec, 1);
 
198
        ntreeShaderEndExecTree(exec);
171
199
}
172
200
 
173
201
/* **************** call to switch lamploop for material node ************ */
180
208
}
181
209
 
182
210
 
183
 
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
184
 
 * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
185
 
 */
186
 
bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
 
211
bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
187
212
{
188
213
        bNodeTreeExec *exec;
189
214
        bNode *node;
190
215
        
191
 
        if (use_tree_data) {
192
 
                /* XXX hack: prevent exec data from being generated twice.
193
 
                 * this should be handled by the renderer!
194
 
                 */
195
 
                if (ntree->execdata)
196
 
                        return ntree->execdata;
197
 
        }
198
 
        
199
216
        /* ensures only a single output node is enabled */
200
217
        ntreeSetOutput(ntree);
201
218
        
202
219
        /* common base initialization */
203
 
        exec = ntree_exec_begin(ntree);
 
220
        exec = ntree_exec_begin(context, ntree, parent_key);
204
221
        
205
222
        /* allocate the thread stack listbase array */
206
223
        exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
208
225
        for (node = exec->nodetree->nodes.first; node; node = node->next)
209
226
                node->need_exec = 1;
210
227
        
211
 
        if (use_tree_data) {
212
 
                /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
213
 
                 * which only store the ntree pointer. Should be fixed at some point!
214
 
                 */
215
 
                ntree->execdata = exec;
 
228
        return exec;
 
229
}
 
230
 
 
231
bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
 
232
{
 
233
        bNodeExecContext context;
 
234
        bNodeTreeExec *exec;
 
235
        
 
236
        /* XXX hack: prevent exec data from being generated twice.
 
237
         * this should be handled by the renderer!
 
238
         */
 
239
        if (ntree->execdata)
 
240
                return ntree->execdata;
 
241
        
 
242
        context.previews = ntree->previews;
 
243
        
 
244
        exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
 
245
        
 
246
        /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
 
247
         * which only store the ntree pointer. Should be fixed at some point!
 
248
         */
 
249
        ntree->execdata = exec;
 
250
        
 
251
        return exec;
 
252
}
 
253
 
 
254
void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
 
255
{
 
256
        bNodeThreadStack *nts;
 
257
        int a;
 
258
        
 
259
        if (exec->threadstack) {
 
260
                for (a = 0; a < BLENDER_MAX_THREADS; a++) {
 
261
                        for (nts = exec->threadstack[a].first; nts; nts = nts->next)
 
262
                                if (nts->stack) MEM_freeN(nts->stack);
 
263
                        BLI_freelistN(&exec->threadstack[a]);
 
264
                }
 
265
                
 
266
                MEM_freeN(exec->threadstack);
 
267
                exec->threadstack = NULL;
216
268
        }
217
269
        
218
 
        return exec;
 
270
        ntree_exec_end(exec);
219
271
}
220
272
 
221
 
/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
222
 
 * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
223
 
 */
224
 
void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
 
273
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
225
274
{
226
275
        if (exec) {
 
276
                /* exec may get freed, so assign ntree */
227
277
                bNodeTree *ntree = exec->nodetree;
228
 
                bNodeThreadStack *nts;
229
 
                int a;
230
 
                
231
 
                if (exec->threadstack) {
232
 
                        for (a = 0; a < BLENDER_MAX_THREADS; a++) {
233
 
                                for (nts = exec->threadstack[a].first; nts; nts = nts->next)
234
 
                                        if (nts->stack) MEM_freeN(nts->stack);
235
 
                                BLI_freelistN(&exec->threadstack[a]);
236
 
                        }
237
 
                        
238
 
                        MEM_freeN(exec->threadstack);
239
 
                        exec->threadstack = NULL;
240
 
                }
241
 
                
242
 
                ntree_exec_end(exec);
243
 
                
244
 
                if (use_tree_data) {
245
 
                        /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
246
 
                        ntree->execdata = NULL;
247
 
                }
 
278
                ntreeShaderEndExecTree_internal(exec);
 
279
                
 
280
                /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
 
281
                ntree->execdata = NULL;
248
282
        }
249
283
}
250
284
 
272
306
        if (!exec) {
273
307
                BLI_lock_thread(LOCK_NODES);
274
308
                if (!ntree->execdata)
275
 
                        ntree->execdata = ntreeShaderBeginExecTree(ntree, 1);
 
309
                        ntree->execdata = ntreeShaderBeginExecTree(ntree);
276
310
                BLI_unlock_thread(LOCK_NODES);
277
311
 
278
312
                exec = ntree->execdata;