Cycles OSL minor optimizations: recycle shading context, don't do memory
[blender.git] / intern / cycles / kernel / osl / osl_services.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include <string.h>
20
21 #include "mesh.h"
22 #include "object.h"
23 #include "scene.h"
24
25 #include "osl_closures.h"
26 #include "osl_globals.h"
27 #include "osl_services.h"
28 #include "osl_shader.h"
29
30 #include "util_foreach.h"
31 #include "util_string.h"
32
33 #include "kernel_compat_cpu.h"
34 #include "kernel_globals.h"
35 #include "kernel_montecarlo.h"
36 #include "kernel_projection.h"
37 #include "kernel_differential.h"
38 #include "kernel_object.h"
39 #include "kernel_bvh.h"
40 #include "kernel_attribute.h"
41 #include "kernel_projection.h"
42 #include "kernel_triangle.h"
43 #include "kernel_accumulate.h"
44 #include "kernel_shader.h"
45
46 CCL_NAMESPACE_BEGIN
47
48 /* RenderServices implementation */
49
50 #define COPY_MATRIX44(m1, m2) memcpy(m1, m2, sizeof(*m2))
51
52 /* static ustrings */
53 ustring OSLRenderServices::u_distance("distance");
54 ustring OSLRenderServices::u_index("index");
55 ustring OSLRenderServices::u_camera("camera");
56 ustring OSLRenderServices::u_screen("screen");
57 ustring OSLRenderServices::u_raster("raster");
58 ustring OSLRenderServices::u_ndc("NDC");
59 ustring OSLRenderServices::u_object_location("object:location");
60 ustring OSLRenderServices::u_object_index("object:index");
61 ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
62 ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
63 ustring OSLRenderServices::u_material_index("material:index");
64 ustring OSLRenderServices::u_object_random("object:random");
65 ustring OSLRenderServices::u_particle_index("particle:index");
66 ustring OSLRenderServices::u_particle_age("particle:age");
67 ustring OSLRenderServices::u_particle_lifetime("particle:lifetime");
68 ustring OSLRenderServices::u_particle_location("particle:location");
69 ustring OSLRenderServices::u_particle_rotation("particle:rotation");
70 ustring OSLRenderServices::u_particle_size("particle:size");
71 ustring OSLRenderServices::u_particle_velocity("particle:velocity");
72 ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity");
73 ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
74 ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
75 ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
76 ustring OSLRenderServices::u_geom_name("geom:name");
77 ustring OSLRenderServices::u_path_ray_length("path:ray_length");
78 ustring OSLRenderServices::u_trace("trace");
79 ustring OSLRenderServices::u_hit("hit");
80 ustring OSLRenderServices::u_hitdist("hitdist");
81 ustring OSLRenderServices::u_N("N");
82 ustring OSLRenderServices::u_Ng("Ng");
83 ustring OSLRenderServices::u_P("P");
84 ustring OSLRenderServices::u_I("I");
85 ustring OSLRenderServices::u_u("u");
86 ustring OSLRenderServices::u_v("v");
87 ustring OSLRenderServices::u_empty;
88
89 OSLRenderServices::OSLRenderServices()
90 {
91         kernel_globals = NULL;
92 }
93
94 OSLRenderServices::~OSLRenderServices()
95 {
96 }
97
98 void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_)
99 {
100         kernel_globals = kernel_globals_;
101 }
102
103 bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
104 {
105         /* this is only used for shader and object space, we don't really have
106          * a concept of shader space, so we just use object space for both. */
107         if (xform) {
108                 KernelGlobals *kg = kernel_globals;
109                 const ShaderData *sd = (const ShaderData *)xform;
110                 int object = sd->object;
111
112                 if (object != ~0) {
113 #ifdef __OBJECT_MOTION__
114                         Transform tfm;
115
116                         if(time == sd->time)
117                                 tfm = sd->ob_tfm;
118                         else
119                                 tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
120 #else
121                         Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
122 #endif
123                         tfm = transform_transpose(tfm);
124                         COPY_MATRIX44(&result, &tfm);
125
126                         return true;
127                 }
128         }
129
130         return false;
131 }
132
133 bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
134 {
135         /* this is only used for shader and object space, we don't really have
136          * a concept of shader space, so we just use object space for both. */
137         if (xform) {
138                 KernelGlobals *kg = kernel_globals;
139                 const ShaderData *sd = (const ShaderData *)xform;
140                 int object = sd->object;
141
142                 if (object != ~0) {
143 #ifdef __OBJECT_MOTION__
144                         Transform itfm;
145
146                         if(time == sd->time)
147                                 itfm = sd->ob_itfm;
148                         else
149                                 object_fetch_transform_motion_test(kg, object, time, &itfm);
150 #else
151                         Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
152 #endif
153                         itfm = transform_transpose(itfm);
154                         COPY_MATRIX44(&result, &itfm);
155
156                         return true;
157                 }
158         }
159
160         return false;
161 }
162
163 bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float time)
164 {
165         KernelGlobals *kg = kernel_globals;
166
167         if (from == u_ndc) {
168                 Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
169                 COPY_MATRIX44(&result, &tfm);
170                 return true;
171         }
172         else if (from == u_raster) {
173                 Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
174                 COPY_MATRIX44(&result, &tfm);
175                 return true;
176         }
177         else if (from == u_screen) {
178                 Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
179                 COPY_MATRIX44(&result, &tfm);
180                 return true;
181         }
182         else if (from == u_camera) {
183                 Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
184                 COPY_MATRIX44(&result, &tfm);
185                 return true;
186         }
187
188         return false;
189 }
190
191 bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time)
192 {
193         KernelGlobals *kg = kernel_globals;
194
195         if (to == u_ndc) {
196                 Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
197                 COPY_MATRIX44(&result, &tfm);
198                 return true;
199         }
200         else if (to == u_raster) {
201                 Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
202                 COPY_MATRIX44(&result, &tfm);
203                 return true;
204         }
205         else if (to == u_screen) {
206                 Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
207                 COPY_MATRIX44(&result, &tfm);
208                 return true;
209         }
210         else if (to == u_camera) {
211                 Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
212                 COPY_MATRIX44(&result, &tfm);
213                 return true;
214         }
215
216         return false;
217 }
218
219 bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform)
220 {
221         /* this is only used for shader and object space, we don't really have
222          * a concept of shader space, so we just use object space for both. */
223         if (xform) {
224                 const ShaderData *sd = (const ShaderData *)xform;
225                 int object = sd->object;
226
227                 if (object != ~0) {
228 #ifdef __OBJECT_MOTION__
229                         Transform tfm = sd->ob_tfm;
230 #else
231                         KernelGlobals *kg = kernel_globals;
232                         Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
233 #endif
234                         tfm = transform_transpose(tfm);
235                         COPY_MATRIX44(&result, &tfm);
236
237                         return true;
238                 }
239         }
240
241         return false;
242 }
243
244 bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform)
245 {
246         /* this is only used for shader and object space, we don't really have
247          * a concept of shader space, so we just use object space for both. */
248         if (xform) {
249                 const ShaderData *sd = (const ShaderData *)xform;
250                 int object = sd->object;
251
252                 if (object != ~0) {
253 #ifdef __OBJECT_MOTION__
254                         Transform tfm = sd->ob_itfm;
255 #else
256                         KernelGlobals *kg = kernel_globals;
257                         Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
258 #endif
259                         tfm = transform_transpose(tfm);
260                         COPY_MATRIX44(&result, &tfm);
261
262                         return true;
263                 }
264         }
265
266         return false;
267 }
268
269 bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from)
270 {
271         KernelGlobals *kg = kernel_globals;
272
273         if (from == u_ndc) {
274                 Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
275                 COPY_MATRIX44(&result, &tfm);
276                 return true;
277         }
278         else if (from == u_raster) {
279                 Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
280                 COPY_MATRIX44(&result, &tfm);
281                 return true;
282         }
283         else if (from == u_screen) {
284                 Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
285                 COPY_MATRIX44(&result, &tfm);
286                 return true;
287         }
288         else if (from == u_camera) {
289                 Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
290                 COPY_MATRIX44(&result, &tfm);
291                 return true;
292         }
293
294         return false;
295 }
296
297 bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to)
298 {
299         KernelGlobals *kg = kernel_globals;
300         
301         if (to == u_ndc) {
302                 Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
303                 COPY_MATRIX44(&result, &tfm);
304                 return true;
305         }
306         else if (to == u_raster) {
307                 Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
308                 COPY_MATRIX44(&result, &tfm);
309                 return true;
310         }
311         else if (to == u_screen) {
312                 Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
313                 COPY_MATRIX44(&result, &tfm);
314                 return true;
315         }
316         else if (to == u_camera) {
317                 Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
318                 COPY_MATRIX44(&result, &tfm);
319                 return true;
320         }
321         
322         return false;
323 }
324
325 bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, 
326                                             ustring object, TypeDesc type, ustring name,
327                                             int index, void *val)
328 {
329         return false;
330 }
331
332 static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
333 {
334         if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
335             type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
336         {
337                 float *fval = (float *)val;
338
339                 fval[0] = f[0].x;
340                 fval[1] = f[0].y;
341                 fval[2] = f[0].z;
342
343                 if (derivatives) {
344                         fval[3] = f[1].x;
345                         fval[4] = f[1].y;
346                         fval[5] = f[1].z;
347
348                         fval[6] = f[2].x;
349                         fval[7] = f[2].y;
350                         fval[8] = f[2].z;
351                 }
352
353                 return true;
354         }
355         else if(type == TypeDesc::TypeFloat) {
356                 float *fval = (float *)val;
357                 fval[0] = average(f[0]);
358
359                 if (derivatives) {
360                         fval[1] = average(f[1]);
361                         fval[2] = average(f[2]);
362                 }
363
364                 return true;
365         }
366
367         return false;
368 }
369
370 static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val)
371 {
372         float3 fv[3];
373
374         fv[0] = f;
375         fv[1] = make_float3(0.0f, 0.0f, 0.0f);
376         fv[2] = make_float3(0.0f, 0.0f, 0.0f);
377
378         return set_attribute_float3(fv, type, derivatives, val);
379 }
380
381 static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
382 {
383         if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
384             type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
385         {
386                 float *fval = (float *)val;
387                 fval[0] = f[0];
388                 fval[1] = f[1];
389                 fval[2] = f[2];
390
391                 if (derivatives) {
392                         fval[3] = f[1];
393                         fval[4] = f[1];
394                         fval[5] = f[1];
395
396                         fval[6] = f[2];
397                         fval[7] = f[2];
398                         fval[8] = f[2];
399                 }
400
401                 return true;
402         }
403         else if(type == TypeDesc::TypeFloat) {
404                 float *fval = (float *)val;
405                 fval[0] = f[0];
406
407                 if (derivatives) {
408                         fval[1] = f[1];
409                         fval[2] = f[2];
410                 }
411
412                 return true;
413         }
414
415         return false;
416 }
417
418 static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val)
419 {
420         float fv[3];
421
422         fv[0] = f;
423         fv[1] = 0.0f;
424         fv[2] = 0.0f;
425
426         return set_attribute_float(fv, type, derivatives, val);
427 }
428
429 static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
430 {
431         if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
432                 int *ival = (int *)val;
433                 ival[0] = i;
434
435                 if (derivatives) {
436                         ival[1] = 0;
437                         ival[2] = 0;
438                 }
439
440                 return true;
441         }
442
443         return false;
444 }
445
446 static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val)
447 {
448         if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
449                 ustring *sval = (ustring *)val;
450                 sval[0] = str;
451
452                 if (derivatives) {
453                         sval[1] = OSLRenderServices::u_empty;
454                         sval[2] = OSLRenderServices::u_empty;
455                 }
456
457                 return true;
458         }
459
460         return false;
461 }
462
463 static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val)
464 {
465         if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
466                 float *fval = (float *)val;
467
468                 fval[0] = P[0].x;
469                 fval[1] = P[0].y;
470                 fval[2] = P[0].z;
471
472                 fval[3] = P[1].x;
473                 fval[4] = P[1].y;
474                 fval[5] = P[1].z;
475
476                 fval[6] = P[2].x;
477                 fval[7] = P[2].y;
478                 fval[8] = P[2].z;
479
480                 if(type.arraylen > 3)
481                         memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3));
482                 if (derivatives)
483                         memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen);
484
485                 return true;
486         }
487
488         return false;
489 }
490
491 static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
492                                const TypeDesc& type, bool derivatives, void *val)
493 {
494         if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
495             attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
496         {
497                 float3 fval[3];
498                 fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
499                                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
500                 return set_attribute_float3(fval, type, derivatives, val);
501         }
502         else if (attr.type == TypeDesc::TypeFloat) {
503                 float fval[3];
504                 fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
505                                                    (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
506                 return set_attribute_float(fval, type, derivatives, val);
507         }
508         else {
509                 return false;
510         }
511 }
512
513 static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val)
514 {
515         size_t datasize = attr.value.datasize();
516
517         memcpy(val, attr.value.data(), datasize);
518         if (derivatives)
519                 memset((char *)val + datasize, 0, datasize * 2);
520 }
521
522 bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
523                                                       TypeDesc type, bool derivatives, void *val)
524 {
525         /* todo: turn this into hash table? */
526
527         /* Object Attributes */
528         if (name == u_object_location) {
529                 float3 f = object_location(kg, sd);
530                 return set_attribute_float3(f, type, derivatives, val);
531         }
532         else if (name == u_object_index) {
533                 float f = object_pass_id(kg, sd->object);
534                 return set_attribute_float(f, type, derivatives, val);
535         }
536         else if (name == u_geom_dupli_generated) {
537                 float3 f = object_dupli_generated(kg, sd->object);
538                 return set_attribute_float3(f, type, derivatives, val);
539         }
540         else if (name == u_geom_dupli_uv) {
541                 float3 f = object_dupli_uv(kg, sd->object);
542                 return set_attribute_float3(f, type, derivatives, val);
543         }
544         else if (name == u_material_index) {
545                 float f = shader_pass_id(kg, sd);
546                 return set_attribute_float(f, type, derivatives, val);
547         }
548         else if (name == u_object_random) {
549                 float f = object_random_number(kg, sd->object);
550                 return set_attribute_float(f, type, derivatives, val);
551         }
552
553         /* Particle Attributes */
554         else if (name == u_particle_index) {
555                 uint particle_id = object_particle_id(kg, sd->object);
556                 float f = particle_index(kg, particle_id);
557                 return set_attribute_float(f, type, derivatives, val);
558         }
559         else if (name == u_particle_age) {
560                 uint particle_id = object_particle_id(kg, sd->object);
561                 float f = particle_age(kg, particle_id);
562                 return set_attribute_float(f, type, derivatives, val);
563         }
564         else if (name == u_particle_lifetime) {
565                 uint particle_id = object_particle_id(kg, sd->object);
566                 float f= particle_lifetime(kg, particle_id);
567                 return set_attribute_float(f, type, derivatives, val);
568         }
569         else if (name == u_particle_location) {
570                 uint particle_id = object_particle_id(kg, sd->object);
571                 float3 f = particle_location(kg, particle_id);
572                 return set_attribute_float3(f, type, derivatives, val);
573         }
574 #if 0   /* unsupported */
575         else if (name == u_particle_rotation) {
576                 uint particle_id = object_particle_id(kg, sd->object);
577                 float4 f = particle_rotation(kg, particle_id);
578                 return set_attribute_float4(f, type, derivatives, val);
579         }
580 #endif
581         else if (name == u_particle_size) {
582                 uint particle_id = object_particle_id(kg, sd->object);
583                 float f = particle_size(kg, particle_id);
584                 return set_attribute_float(f, type, derivatives, val);
585         }
586         else if (name == u_particle_velocity) {
587                 uint particle_id = object_particle_id(kg, sd->object);
588                 float3 f = particle_velocity(kg, particle_id);
589                 return set_attribute_float3(f, type, derivatives, val);
590         }
591         else if (name == u_particle_angular_velocity) {
592                 uint particle_id = object_particle_id(kg, sd->object);
593                 float3 f = particle_angular_velocity(kg, particle_id);
594                 return set_attribute_float3(f, type, derivatives, val);
595         }
596         else if (name == u_geom_numpolyvertices) {
597                 return set_attribute_int(3, type, derivatives, val);
598         }
599         else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) {
600                 float3 P[3];
601                 triangle_vertices(kg, sd->prim, P);
602
603                 if(!(sd->flag & SD_TRANSFORM_APPLIED)) {
604                         object_position_transform(kg, sd, &P[0]);
605                         object_position_transform(kg, sd, &P[1]);
606                         object_position_transform(kg, sd, &P[2]);
607                 }
608
609                 return set_attribute_float3_3(P, type, derivatives, val);
610         }
611         else if(name == u_geom_name) {
612                 ustring object_name = kg->osl->object_names[sd->object];
613                 return set_attribute_string(object_name, type, derivatives, val);
614         }
615         else
616                 return false;
617 }
618
619 bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
620                                                  TypeDesc type, bool derivatives, void *val)
621 {
622         /* Ray Length */
623         if (name == u_path_ray_length) {
624                 float f = sd->ray_length;
625                 return set_attribute_float(f, type, derivatives, val);
626         }
627         
628         else
629                 return false;
630 }
631
632 bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
633                                       TypeDesc type, ustring name, void *val)
634 {
635         KernelGlobals *kg = kernel_globals;
636         ShaderData *sd = (ShaderData *)renderstate;
637         int object = sd->object;
638         int tri = sd->prim;
639
640         /* lookup of attribute on another object */
641         if (object_name != u_empty) {
642                 OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
643
644                 if (it == kg->osl->object_name_map.end())
645                         return false;
646
647                 object = it->second;
648                 tri = ~0;
649         }
650         else if (object == ~0) {
651                 return get_background_attribute(kg, sd, name, type, derivatives, val);
652         }
653
654         /* find attribute on object */
655         OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
656         OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
657
658         if (it != attribute_map.end()) {
659                 const OSLGlobals::Attribute& attr = it->second;
660
661                 if (attr.elem != ATTR_ELEMENT_VALUE) {
662                         /* triangle and vertex attributes */
663                         if (tri != ~0)
664                                 return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
665                 }
666                 else {
667                         /* object attribute */
668                         get_object_attribute(attr, derivatives, val);
669                         return true;
670                 }
671         }
672         else {
673                 /* not found in attribute, check standard object info */
674                 bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val);
675
676                 if (is_std_object_attribute)
677                         return true;
678
679                 return get_background_attribute(kg, sd, name, type, derivatives, val);
680         }
681
682         return false;
683 }
684
685 bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type, 
686                                      void *renderstate, void *val)
687 {
688         return false; /* disabled by lockgeom */
689 }
690
691 bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderstate)
692 {
693         return false; /* never called by OSL */
694 }
695
696 bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
697                                 OSL::ShaderGlobals *sg,
698                                 float s, float t, float dsdx, float dtdx,
699                                 float dsdy, float dtdy, float *result)
700 {
701         OSL::TextureSystem *ts = kernel_globals->osl->ts;
702         bool status = ts->texture(filename, options, s, t, dsdx, dtdx, dsdy, dtdy, result);
703
704         if(!status) {
705                 if(options.nchannels == 3 || options.nchannels == 4) {
706                         result[0] = 1.0f;
707                         result[1] = 0.0f;
708                         result[2] = 1.0f;
709
710                         if(options.nchannels == 4)
711                                 result[3] = 1.0f;
712                 }
713         }
714
715         return status;
716 }
717
718 bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options,
719                                   OSL::ShaderGlobals *sg, const OSL::Vec3 &P,
720                                   const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy,
721                                   const OSL::Vec3 &dPdz, float *result)
722 {
723         OSL::TextureSystem *ts = kernel_globals->osl->ts;
724         bool status = ts->texture3d(filename, options, P, dPdx, dPdy, dPdz, result);
725
726         if(!status) {
727                 if(options.nchannels == 3 || options.nchannels == 4) {
728                         result[0] = 1.0f;
729                         result[1] = 0.0f;
730                         result[2] = 1.0f;
731
732                         if(options.nchannels == 4)
733                                 result[3] = 1.0f;
734                 }
735
736         }
737
738         return status;
739 }
740
741 bool OSLRenderServices::environment(ustring filename, TextureOpt &options,
742                                     OSL::ShaderGlobals *sg, const OSL::Vec3 &R,
743                                     const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result)
744 {
745         OSL::TextureSystem *ts = kernel_globals->osl->ts;
746         bool status = ts->environment(filename, options, R, dRdx, dRdy, result);
747
748         if(!status) {
749                 if(options.nchannels == 3 || options.nchannels == 4) {
750                         result[0] = 1.0f;
751                         result[1] = 0.0f;
752                         result[2] = 1.0f;
753
754                         if(options.nchannels == 4)
755                                 result[3] = 1.0f;
756                 }
757         }
758
759         return status;
760 }
761
762 bool OSLRenderServices::get_texture_info(ustring filename, int subimage,
763                                          ustring dataname,
764                                          TypeDesc datatype, void *data)
765 {
766         OSL::TextureSystem *ts = kernel_globals->osl->ts;
767         return ts->get_texture_info(filename, subimage, dataname, datatype, data);
768 }
769
770 int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 &center,
771                                          float radius, int max_points, bool sort,
772                                          size_t *out_indices, float *out_distances, int derivs_offset)
773 {
774         return 0;
775 }
776
777 int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int count,
778                                       ustring attr_name, TypeDesc attr_type, void *out_data)
779 {
780         return 0;
781 }
782
783 bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
784         const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
785         const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
786         const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy)
787 {
788         /* todo: options.shader support, maybe options.traceset */
789         ShaderData *sd = (ShaderData *)(sg->renderstate);
790
791         /* setup ray */
792         Ray ray;
793
794         ray.P = TO_FLOAT3(P);
795         ray.D = TO_FLOAT3(R);
796         ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist;
797         ray.time = sd->time;
798
799         if(options.mindist == 0.0f) {
800                 /* avoid self-intersections */
801                 if(ray.P == sd->P) {
802                         bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
803                         ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
804                 }
805         }
806         else {
807                 /* offset for minimum distance */
808                 ray.P += options.mindist*ray.D;
809         }
810
811         /* ray differentials */
812         ray.dP.dx = TO_FLOAT3(dPdx);
813         ray.dP.dy = TO_FLOAT3(dPdy);
814         ray.dD.dx = TO_FLOAT3(dRdx);
815         ray.dD.dy = TO_FLOAT3(dRdy);
816
817         /* allocate trace data */
818         OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
819         tracedata->ray = ray;
820         tracedata->setup = false;
821         tracedata->init = true;
822
823         /* raytrace */
824         return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect);
825 }
826
827
828 bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name,
829         TypeDesc type, void *val, bool derivatives)
830 {
831         OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
832
833         if(source == u_trace && tracedata->init) {
834                 if(name == u_hit) {
835                         return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val);
836                 }
837                 else if(tracedata->isect.prim != ~0) {
838                         if(name == u_hitdist) {
839                                 float f[3] = {tracedata->isect.t, 0.0f, 0.0f};
840                                 return set_attribute_float(f, type, derivatives, val);
841                         }
842                         else {
843                                 KernelGlobals *kg = kernel_globals;
844                                 ShaderData *sd = &tracedata->sd;
845
846                                 if(!tracedata->setup) {
847                                         /* lazy shader data setup */
848                                         shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray);
849                                         tracedata->setup = true;
850                                 }
851
852                                 if(name == u_N) {
853                                         return set_attribute_float3(sd->N, type, derivatives, val);
854                                 }
855                                 else if(name == u_Ng) {
856                                         return set_attribute_float3(sd->Ng, type, derivatives, val);
857                                 }
858                                 else if(name == u_P) {
859                                         float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy};
860                                         return set_attribute_float3(f, type, derivatives, val);
861                                 }
862                                 else if(name == u_I) {
863                                         float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy};
864                                         return set_attribute_float3(f, type, derivatives, val);
865                                 }
866                                 else if(name == u_u) {
867                                         float f[3] = {sd->u, sd->du.dx, sd->du.dy};
868                                         return set_attribute_float(f, type, derivatives, val);
869                                 }
870                                 else if(name == u_v) {
871                                         float f[3] = {sd->v, sd->dv.dx, sd->dv.dy};
872                                         return set_attribute_float(f, type, derivatives, val);
873                                 }
874
875                                 return get_attribute(sd, derivatives, u_empty, type, name, val);
876                         }
877                 }
878         }
879
880         return false;
881 }
882
883 CCL_NAMESPACE_END