More GLSL code:
[mesa.git] / src / mesa / shader / shaderobjects_3dlabs.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file shaderobjects_3dlabs.c
27 * shader objects definitions for 3dlabs compiler
28 * \author Michal Krol
29 */
30
31 /* Set this to 1 when we are ready to use 3dlabs' front-end */
32 #define USE_3DLABS_FRONTEND 0
33
34 #include "glheader.h"
35 #include "shaderobjects.h"
36 #include "shaderobjects_3dlabs.h"
37 #include "context.h"
38 #include "macros.h"
39 #include "hash.h"
40
41 #if USE_3DLABS_FRONTEND
42 #include "slang_mesa.h"
43 #include "Public/ShaderLang.h"
44 #else
45 #include "slang_utility.h"
46 #include "slang_compile.h"
47 #include "slang_link.h"
48 #endif
49
50 struct gl2_unknown_obj
51 {
52 GLuint reference_count;
53 void (* _destructor) (struct gl2_unknown_intf **);
54 };
55
56 struct gl2_unknown_impl
57 {
58 struct gl2_unknown_intf *_vftbl;
59 struct gl2_unknown_obj _obj;
60 };
61
62 static void
63 _unknown_destructor (struct gl2_unknown_intf **intf)
64 {
65 }
66
67 static void
68 _unknown_AddRef (struct gl2_unknown_intf **intf)
69 {
70 struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;
71
72 impl->_obj.reference_count++;
73 }
74
75 static void
76 _unknown_Release (struct gl2_unknown_intf **intf)
77 {
78 struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;
79
80 impl->_obj.reference_count--;
81 if (impl->_obj.reference_count == 0)
82 {
83 impl->_obj._destructor (intf);
84 _mesa_free ((void *) intf);
85 }
86 }
87
88 static struct gl2_unknown_intf **
89 _unknown_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
90 {
91 if (uiid == UIID_UNKNOWN)
92 {
93 (**intf).AddRef (intf);
94 return intf;
95 }
96 return NULL;
97 }
98
99 static struct gl2_unknown_intf _unknown_vftbl = {
100 _unknown_AddRef,
101 _unknown_Release,
102 _unknown_QueryInterface
103 };
104
105 static void
106 _unknown_constructor (struct gl2_unknown_impl *impl)
107 {
108 impl->_vftbl = &_unknown_vftbl;
109 impl->_obj.reference_count = 1;
110 impl->_obj._destructor = _unknown_destructor;
111 }
112
113 struct gl2_unkinner_obj
114 {
115 struct gl2_unknown_intf **unkouter;
116 };
117
118 struct gl2_unkinner_impl
119 {
120 struct gl2_unknown_intf *_vftbl;
121 struct gl2_unkinner_obj _obj;
122 };
123
124 static void
125 _unkinner_destructor (struct gl2_unknown_intf **intf)
126 {
127 }
128
129 static void
130 _unkinner_AddRef (struct gl2_unknown_intf **intf)
131 {
132 struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
133
134 (**impl->_obj.unkouter).AddRef (impl->_obj.unkouter);
135 }
136
137 static void
138 _unkinner_Release (struct gl2_unknown_intf **intf)
139 {
140 struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
141
142 (**impl->_obj.unkouter).Release (impl->_obj.unkouter);
143 }
144
145 static struct gl2_unknown_intf **
146 _unkinner_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
147 {
148 struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
149
150 return (**impl->_obj.unkouter).QueryInterface (impl->_obj.unkouter, uiid);
151 }
152
153 static struct gl2_unknown_intf _unkinner_vftbl = {
154 _unkinner_AddRef,
155 _unkinner_Release,
156 _unkinner_QueryInterface
157 };
158
159 static void
160 _unkinner_constructor (struct gl2_unkinner_impl *impl, struct gl2_unknown_intf **outer)
161 {
162 impl->_vftbl = &_unkinner_vftbl;
163 impl->_obj.unkouter = outer;
164 }
165
166 struct gl2_generic_obj
167 {
168 struct gl2_unknown_obj _unknown;
169 GLhandleARB name;
170 GLboolean delete_status;
171 GLcharARB *info_log;
172 };
173
174 struct gl2_generic_impl
175 {
176 struct gl2_generic_intf *_vftbl;
177 struct gl2_generic_obj _obj;
178 };
179
180 static void
181 _generic_destructor (struct gl2_unknown_intf **intf)
182 {
183 GET_CURRENT_CONTEXT(ctx);
184 struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
185
186 _mesa_free ((void *) impl->_obj.info_log);
187
188 _glthread_LOCK_MUTEX (ctx->Shared->Mutex);
189 _mesa_HashRemove (ctx->Shared->GL2Objects, impl->_obj.name);
190 _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);
191
192 _unknown_destructor (intf);
193 }
194
195 static struct gl2_unknown_intf **
196 _generic_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
197 {
198 if (uiid == UIID_GENERIC)
199 {
200 (**intf).AddRef (intf);
201 return intf;
202 }
203 return _unknown_QueryInterface (intf, uiid);
204 }
205
206 static void
207 _generic_Delete (struct gl2_generic_intf **intf)
208 {
209 struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
210
211 if (impl->_obj.delete_status == GL_FALSE)
212 {
213 impl->_obj.delete_status = GL_TRUE;
214 (**intf)._unknown.Release ((struct gl2_unknown_intf **) intf);
215 }
216 }
217
218 static GLhandleARB
219 _generic_GetName (struct gl2_generic_intf **intf)
220 {
221 struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
222
223 return impl->_obj.name;
224 }
225
226 static GLboolean
227 _generic_GetDeleteStatus (struct gl2_generic_intf **intf)
228 {
229 struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
230
231 return impl->_obj.delete_status;
232 }
233
234 static const GLcharARB *
235 _generic_GetInfoLog (struct gl2_generic_intf **intf)
236 {
237 struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
238
239 return impl->_obj.info_log;
240 }
241
242 static struct gl2_generic_intf _generic_vftbl = {
243 {
244 _unknown_AddRef,
245 _unknown_Release,
246 _generic_QueryInterface
247 },
248 _generic_Delete,
249 NULL, /* abstract GetType */
250 _generic_GetName,
251 _generic_GetDeleteStatus,
252 _generic_GetInfoLog
253 };
254
255 static void
256 _generic_constructor (struct gl2_generic_impl *impl)
257 {
258 GET_CURRENT_CONTEXT(ctx);
259
260 _unknown_constructor ((struct gl2_unknown_impl *) impl);
261 impl->_vftbl = &_generic_vftbl;
262 impl->_obj._unknown._destructor = _generic_destructor;
263 impl->_obj.delete_status = GL_FALSE;
264 impl->_obj.info_log = NULL;
265
266 _glthread_LOCK_MUTEX (ctx->Shared->Mutex);
267 impl->_obj.name = _mesa_HashFindFreeKeyBlock (ctx->Shared->GL2Objects, 1);
268 _mesa_HashInsert (ctx->Shared->GL2Objects, impl->_obj.name, (void *) impl);
269 _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);
270 }
271
272 struct gl2_container_obj
273 {
274 struct gl2_generic_obj _generic;
275 struct gl2_generic_intf ***attached;
276 GLuint attached_count;
277 };
278
279 struct gl2_container_impl
280 {
281 struct gl2_container_intf *_vftbl;
282 struct gl2_container_obj _obj;
283 };
284
285 static void
286 _container_destructor (struct gl2_unknown_intf **intf)
287 {
288 struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
289 GLuint i;
290
291 for (i = 0; i < impl->_obj.attached_count; i++)
292 {
293 struct gl2_generic_intf **x = impl->_obj.attached[i];
294 (**x)._unknown.Release ((struct gl2_unknown_intf **) x);
295 }
296
297 _generic_destructor (intf);
298 }
299
300 static struct gl2_unknown_intf **
301 _container_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
302 {
303 if (uiid == UIID_CONTAINER)
304 {
305 (**intf).AddRef (intf);
306 return intf;
307 }
308 return _generic_QueryInterface (intf, uiid);
309 }
310
311 static GLboolean
312 _container_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
313 {
314 GET_CURRENT_CONTEXT(ctx);
315 struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
316 GLuint i;
317
318 for (i = 0; i < impl->_obj.attached_count; i++)
319 if (impl->_obj.attached[i] == att)
320 {
321 _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Attach");
322 return GL_FALSE;
323 }
324
325 impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,
326 impl->_obj.attached_count * sizeof (*impl->_obj.attached), (impl->_obj.attached_count + 1) *
327 sizeof (*impl->_obj.attached));
328 if (impl->_obj.attached == NULL)
329 return GL_FALSE;
330
331 impl->_obj.attached[impl->_obj.attached_count] = att;
332 impl->_obj.attached_count++;
333 (**att)._unknown.AddRef ((struct gl2_unknown_intf **) att);
334 return GL_TRUE;
335 }
336
337 static GLboolean
338 _container_Detach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
339 {
340 GET_CURRENT_CONTEXT(ctx);
341 struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
342 GLuint i, j;
343
344 for (i = 0; i < impl->_obj.attached_count; i++)
345 if (impl->_obj.attached[i] == att)
346 {
347 for (j = i; j < impl->_obj.attached_count - 1; j++)
348 impl->_obj.attached[j] = impl->_obj.attached[j + 1];
349 impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,
350 impl->_obj.attached_count * sizeof (*impl->_obj.attached),
351 (impl->_obj.attached_count - 1) * sizeof (*impl->_obj.attached));
352 impl->_obj.attached_count--;
353 (**att)._unknown.Release ((struct gl2_unknown_intf **) att);
354 return GL_TRUE;
355 }
356
357 _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Detach");
358 return GL_FALSE;
359 }
360
361 static GLsizei
362 _container_GetAttachedCount (struct gl2_container_intf **intf)
363 {
364 struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
365
366 return impl->_obj.attached_count;
367 }
368
369 static struct gl2_generic_intf **
370 _container_GetAttached (struct gl2_container_intf **intf, GLuint index)
371 {
372 struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
373
374 (**impl->_obj.attached[index])._unknown.AddRef (
375 (struct gl2_unknown_intf **)impl->_obj.attached[index]);
376 return impl->_obj.attached[index];
377 }
378
379 static struct gl2_container_intf _container_vftbl = {
380 {
381 {
382 _unknown_AddRef,
383 _unknown_Release,
384 _container_QueryInterface
385 },
386 _generic_Delete,
387 NULL, /* abstract GetType */
388 _generic_GetName,
389 _generic_GetDeleteStatus,
390 _generic_GetInfoLog
391 },
392 _container_Attach,
393 _container_Detach,
394 _container_GetAttachedCount,
395 _container_GetAttached
396 };
397
398 static void
399 _container_constructor (struct gl2_container_impl *impl)
400 {
401 _generic_constructor ((struct gl2_generic_impl *) impl);
402 impl->_vftbl = &_container_vftbl;
403 impl->_obj._generic._unknown._destructor = _container_destructor;
404 impl->_obj.attached = NULL;
405 impl->_obj.attached_count = 0;
406 }
407
408 struct gl2_3dlabs_shhandle_obj
409 {
410 struct gl2_unkinner_obj _unknown;
411 #if USE_3DLABS_FRONTEND
412 ShHandle handle;
413 #endif
414 };
415
416 struct gl2_3dlabs_shhandle_impl
417 {
418 struct gl2_3dlabs_shhandle_intf *_vftbl;
419 struct gl2_3dlabs_shhandle_obj _obj;
420 };
421
422 static void
423 _3dlabs_shhandle_destructor (struct gl2_unknown_intf **intf)
424 {
425 #if USE_3DLABS_FRONTEND
426 struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;
427 ShDestruct (impl->_obj.handle);
428 #endif
429 _unkinner_destructor (intf);
430 }
431
432 static GLvoid *
433 _3dlabs_shhandle_GetShHandle (struct gl2_3dlabs_shhandle_intf **intf)
434 {
435 #if USE_3DLABS_FRONTEND
436 struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;
437 return impl->_obj.handle;
438 #else
439 return NULL;
440 #endif
441 }
442
443 static struct gl2_3dlabs_shhandle_intf _3dlabs_shhandle_vftbl = {
444 {
445 _unkinner_AddRef,
446 _unkinner_Release,
447 _unkinner_QueryInterface
448 },
449 _3dlabs_shhandle_GetShHandle
450 };
451
452 static void
453 _3dlabs_shhandle_constructor (struct gl2_3dlabs_shhandle_impl *impl, struct gl2_unknown_intf **outer)
454 {
455 _unkinner_constructor ((struct gl2_unkinner_impl *) impl, outer);
456 impl->_vftbl = &_3dlabs_shhandle_vftbl;
457 #if USE_3DLABS_FRONTEND
458 impl->_obj.handle = NULL;
459 #endif
460 }
461
462 struct gl2_shader_obj
463 {
464 struct gl2_generic_obj _generic;
465 struct gl2_3dlabs_shhandle_impl _3dlabs_shhandle;
466 GLboolean compile_status;
467 GLcharARB *source;
468 GLint *offsets;
469 GLsizei offset_count;
470 slang_translation_unit unit;
471 };
472
473 struct gl2_shader_impl
474 {
475 struct gl2_shader_intf *_vftbl;
476 struct gl2_shader_obj _obj;
477 };
478
479 static void
480 _shader_destructor (struct gl2_unknown_intf **intf)
481 {
482 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
483
484 _mesa_free ((void *) impl->_obj.source);
485 _mesa_free ((void *) impl->_obj.offsets);
486 _3dlabs_shhandle_destructor ((struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl);
487 _generic_destructor (intf);
488 }
489
490 static struct gl2_unknown_intf **
491 _shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
492 {
493 #if USE_3DLABS_FRONTEND
494 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
495 #endif
496
497 if (uiid == UIID_SHADER)
498 {
499 (**intf).AddRef (intf);
500 return intf;
501 }
502 #if USE_3DLABS_FRONTEND
503 if (uiid == UIID_3DLABS_SHHANDLE)
504 {
505 (**intf).AddRef (intf);
506 return (struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl;
507 }
508 #endif
509 return _generic_QueryInterface (intf, uiid);
510 }
511
512 static GLenum
513 _shader_GetType (struct gl2_generic_intf **intf)
514 {
515 return GL_SHADER_OBJECT_ARB;
516 }
517
518 static GLboolean
519 _shader_GetCompileStatus (struct gl2_shader_intf **intf)
520 {
521 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
522
523 return impl->_obj.compile_status;
524 }
525
526 static GLvoid
527 _shader_SetSource (struct gl2_shader_intf **intf, GLcharARB *src, GLint *off, GLsizei cnt)
528 {
529 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
530
531 _mesa_free ((void *) impl->_obj.source);
532 impl->_obj.source = src;
533 _mesa_free ((void *) impl->_obj.offsets);
534 impl->_obj.offsets = off;
535 impl->_obj.offset_count = cnt;
536 }
537
538 static const GLcharARB *
539 _shader_GetSource (struct gl2_shader_intf **intf)
540 {
541 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
542
543 return impl->_obj.source;
544 }
545
546 static GLvoid
547 _shader_Compile (struct gl2_shader_intf **intf)
548 {
549 struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
550 #if USE_3DLABS_FRONTEND
551 char **strings;
552 TBuiltInResource res;
553 #else
554 slang_unit_type type;
555 slang_info_log info_log;
556 #endif
557
558 impl->_obj.compile_status = GL_FALSE;
559 _mesa_free ((void *) impl->_obj._generic.info_log);
560 impl->_obj._generic.info_log = NULL;
561
562 #if USE_3DLABS_FRONTEND
563 /* 3dlabs compiler expects us to feed it with null-terminated string array,
564 we've got only one big string with offsets, so we must split it; but when
565 there's only one string to deal with, we pass its address directly */
566
567 if (impl->_obj.offset_count <= 1)
568 strings = &impl->_obj.source;
569 else
570 {
571 GLsizei i, offset = 0;
572
573 strings = (char **) _mesa_malloc (impl->_obj.offset_count * sizeof (char *));
574 if (strings == NULL)
575 return;
576
577 for (i = 0; i < impl->_obj.offset_count; i++)
578 {
579 GLsizei size = impl->_obj.offsets[i] - offset;
580
581 strings[i] = (char *) _mesa_malloc ((size + 1) * sizeof (char));
582 if (strings[i] == NULL)
583 {
584 GLsizei j;
585
586 for (j = 0; j < i; j++)
587 _mesa_free (strings[j]);
588 _mesa_free (strings);
589 return;
590 }
591
592 _mesa_memcpy (strings[i], impl->_obj.source + offset, size * sizeof (char));
593 strings[i][size] = '\0';
594 offset = impl->_obj.offsets[i];
595 }
596 }
597
598 /* TODO set these fields to some REAL numbers */
599 res.maxLights = 8;
600 res.maxClipPlanes = 6;
601 res.maxTextureUnits = 2;
602 res.maxTextureCoords = 2;
603 res.maxVertexAttribs = 8;
604 res.maxVertexUniformComponents = 64;
605 res.maxVaryingFloats = 8;
606 res.maxVertexTextureImageUnits = 2;
607 res.maxCombinedTextureImageUnits = 2;
608 res.maxTextureImageUnits = 2;
609 res.maxFragmentUniformComponents = 64;
610 res.maxDrawBuffers = 1;
611
612 if (ShCompile (impl->_obj._3dlabs_shhandle._obj.handle, strings, impl->_obj.offset_count,
613 EShOptFull, &res, 0))
614 impl->_obj.compile_status = GL_TRUE;
615 if (impl->_obj.offset_count > 1)
616 {
617 GLsizei i;
618
619 for (i = 0; i < impl->_obj.offset_count; i++)
620 _mesa_free (strings[i]);
621 _mesa_free (strings);
622 }
623
624 impl->_obj._generic.info_log = _mesa_strdup (ShGetInfoLog (
625 impl->_obj._3dlabs_shhandle._obj.handle));
626 #else
627 if (impl->_vftbl->GetSubType (intf) == GL_FRAGMENT_SHADER)
628 type = slang_unit_fragment_shader;
629 else
630 type = slang_unit_vertex_shader;
631 slang_info_log_construct (&info_log);
632 if (_slang_compile (impl->_obj.source, &impl->_obj.unit, type, &info_log))
633 {
634 impl->_obj.compile_status = GL_TRUE;
635 }
636 if (info_log.text != NULL)
637 impl->_obj._generic.info_log = _mesa_strdup (info_log.text);
638 else
639 impl->_obj._generic.info_log = _mesa_strdup ("");
640 slang_info_log_destruct (&info_log);
641 #endif
642 }
643
644 static struct gl2_shader_intf _shader_vftbl = {
645 {
646 {
647 _unknown_AddRef,
648 _unknown_Release,
649 _shader_QueryInterface
650 },
651 _generic_Delete,
652 _shader_GetType,
653 _generic_GetName,
654 _generic_GetDeleteStatus,
655 _generic_GetInfoLog
656 },
657 NULL, /* abstract GetSubType */
658 _shader_GetCompileStatus,
659 _shader_SetSource,
660 _shader_GetSource,
661 _shader_Compile
662 };
663
664 static void
665 _shader_constructor (struct gl2_shader_impl *impl)
666 {
667 _generic_constructor ((struct gl2_generic_impl *) impl);
668 _3dlabs_shhandle_constructor (&impl->_obj._3dlabs_shhandle, (struct gl2_unknown_intf **)
669 &impl->_vftbl);
670 impl->_vftbl = &_shader_vftbl;
671 impl->_obj._generic._unknown._destructor = _shader_destructor;
672 impl->_obj.compile_status = GL_FALSE;
673 impl->_obj.source = NULL;
674 impl->_obj.offsets = NULL;
675 impl->_obj.offset_count = 0;
676 }
677
678 struct gl2_program_obj
679 {
680 struct gl2_container_obj _container;
681 GLboolean link_status;
682 GLboolean validate_status;
683 #if USE_3DLABS_FRONTEND
684 ShHandle linker;
685 ShHandle uniforms;
686 #endif
687 slang_program prog;
688 };
689
690 struct gl2_program_impl
691 {
692 struct gl2_program_intf *_vftbl;
693 struct gl2_program_obj _obj;
694 };
695
696 static void
697 _program_destructor (struct gl2_unknown_intf **intf)
698 {
699 struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
700 #if USE_3DLABS_FRONTEND
701 ShDestruct (impl->_obj.linker);
702 ShDestruct (impl->_obj.uniforms);
703 #endif
704 _container_destructor (intf);
705 slang_program_dtr (&impl->_obj.prog);
706 }
707
708 static struct gl2_unknown_intf **
709 _program_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
710 {
711 if (uiid == UIID_PROGRAM)
712 {
713 (**intf).AddRef (intf);
714 return intf;
715 }
716 return _container_QueryInterface (intf, uiid);
717 }
718
719 static GLenum
720 _program_GetType (struct gl2_generic_intf **intf)
721 {
722 return GL_PROGRAM_OBJECT_ARB;
723 }
724
725 static GLboolean
726 _program_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
727 {
728 GET_CURRENT_CONTEXT(ctx);
729 struct gl2_unknown_intf **sha;
730
731 sha = (**att)._unknown.QueryInterface ((struct gl2_unknown_intf **) att, UIID_SHADER);
732 if (sha == NULL)
733 {
734 _mesa_error (ctx, GL_INVALID_OPERATION, "_program_Attach");
735 return GL_FALSE;
736 }
737
738 (**sha).Release (sha);
739 return _container_Attach (intf, att);
740 }
741
742 static GLboolean
743 _program_GetLinkStatus (struct gl2_program_intf **intf)
744 {
745 struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
746
747 return impl->_obj.link_status;
748 }
749
750 static GLboolean
751 _program_GetValidateStatus (struct gl2_program_intf **intf)
752 {
753 struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
754
755 return impl->_obj.validate_status;
756 }
757
758 static GLvoid
759 _program_Link (struct gl2_program_intf **intf)
760 {
761 struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
762 #if USE_3DLABS_FRONTEND
763 ShHandle *handles;
764 #endif
765 GLuint i, count;
766 slang_translation_unit *units[2];
767
768 impl->_obj.link_status = GL_FALSE;
769 _mesa_free ((void *) impl->_obj._container._generic.info_log);
770 impl->_obj._container._generic.info_log = NULL;
771 slang_program_dtr (&impl->_obj.prog);
772 slang_program_ctr (&impl->_obj.prog);
773
774 #if USE_3DLABS_FRONTEND
775 handles = (ShHandle *) _mesa_malloc (impl->_obj._container.attached_count * sizeof (ShHandle));
776 if (handles == NULL)
777 return;
778
779 for (i = 0; i < impl->_obj._container.attached_count; i++)
780 {
781 struct gl2_generic_intf **gen = impl->_obj._container.attached[i];
782 struct gl2_3dlabs_shhandle_intf **sh;
783
784 sh = (struct gl2_3dlabs_shhandle_intf **) (**gen)._unknown.QueryInterface (
785 (struct gl2_unknown_intf **) gen, UIID_3DLABS_SHHANDLE);
786 if (sh != NULL)
787 {
788 handles[i] = (**sh).GetShHandle (sh);
789 (**sh)._unknown.Release ((struct gl2_unknown_intf **) sh);
790 }
791 else
792 {
793 _mesa_free (handles);
794 return;
795 }
796 }
797
798 if (ShLink (impl->_obj.linker, handles, impl->_obj._container.attached_count,
799 impl->_obj.uniforms, NULL, NULL))
800 impl->_obj.link_status = GL_TRUE;
801
802 impl->_obj._container._generic.info_log = _mesa_strdup (ShGetInfoLog (impl->_obj.linker));
803 #else
804 count = impl->_obj._container.attached_count;
805 if (count == 0 || count > 2)
806 return;
807 for (i = 0; i < count; i++)
808 {
809 struct gl2_generic_intf **obj;
810 struct gl2_unknown_intf **unk;
811 struct gl2_shader_impl *sha;
812
813 obj = impl->_obj._container.attached[i];
814 unk = (**obj)._unknown.QueryInterface ((struct gl2_unknown_intf **) obj, UIID_SHADER);
815 (**obj)._unknown.Release ((struct gl2_unknown_intf **) obj);
816 if (unk == NULL)
817 return;
818 sha = (struct gl2_shader_impl *) unk;
819 units[i] = &sha->_obj.unit;
820 (**unk).Release (unk);
821 }
822
823 impl->_obj.link_status = _slang_link (&impl->_obj.prog, units, count);
824 if (impl->_obj.link_status)
825 impl->_obj._container._generic.info_log = _mesa_strdup ("Link OK.\n");
826 else
827 impl->_obj._container._generic.info_log = _mesa_strdup ("Link failed.\n");
828 #endif
829 }
830
831 static GLvoid
832 _program_Validate (struct gl2_program_intf **intf)
833 {
834 struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
835
836 impl->_obj.validate_status = GL_FALSE;
837 _mesa_free ((void *) impl->_obj._container._generic.info_log);
838 impl->_obj._container._generic.info_log = NULL;
839
840 /* TODO validate */
841 }
842
843 static struct gl2_program_intf _program_vftbl = {
844 {
845 {
846 {
847 _unknown_AddRef,
848 _unknown_Release,
849 _program_QueryInterface
850 },
851 _generic_Delete,
852 _program_GetType,
853 _generic_GetName,
854 _generic_GetDeleteStatus,
855 _generic_GetInfoLog
856 },
857 _program_Attach,
858 _container_Detach,
859 _container_GetAttachedCount,
860 _container_GetAttached
861 },
862 _program_GetLinkStatus,
863 _program_GetValidateStatus,
864 _program_Link,
865 _program_Validate
866 };
867
868 static void
869 _program_constructor (struct gl2_program_impl *impl)
870 {
871 _container_constructor ((struct gl2_container_impl *) impl);
872 impl->_vftbl = &_program_vftbl;
873 impl->_obj._container._generic._unknown._destructor = _program_destructor;
874 impl->_obj.link_status = GL_FALSE;
875 impl->_obj.validate_status = GL_FALSE;
876 #if USE_3DLABS_FRONTEND
877 impl->_obj.linker = ShConstructLinker (EShExVertexFragment, 0);
878 impl->_obj.uniforms = ShConstructUniformMap ();
879 #endif
880 slang_program_ctr (&impl->_obj.prog);
881 }
882
883 struct gl2_fragment_shader_obj
884 {
885 struct gl2_shader_obj _shader;
886 };
887
888 struct gl2_fragment_shader_impl
889 {
890 struct gl2_fragment_shader_intf *_vftbl;
891 struct gl2_fragment_shader_obj _obj;
892 };
893
894 static void
895 _fragment_shader_destructor (struct gl2_unknown_intf **intf)
896 {
897 struct gl2_fragment_shader_impl *impl = (struct gl2_fragment_shader_impl *) intf;
898
899 (void) impl;
900 /* TODO free fragment shader data */
901
902 _shader_destructor (intf);
903 }
904
905 static struct gl2_unknown_intf **
906 _fragment_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
907 {
908 if (uiid == UIID_FRAGMENT_SHADER)
909 {
910 (**intf).AddRef (intf);
911 return intf;
912 }
913 return _shader_QueryInterface (intf, uiid);
914 }
915
916 static GLenum
917 _fragment_shader_GetSubType (struct gl2_shader_intf **intf)
918 {
919 return GL_FRAGMENT_SHADER_ARB;
920 }
921
922 static struct gl2_fragment_shader_intf _fragment_shader_vftbl = {
923 {
924 {
925 {
926 _unknown_AddRef,
927 _unknown_Release,
928 _fragment_shader_QueryInterface
929 },
930 _generic_Delete,
931 _shader_GetType,
932 _generic_GetName,
933 _generic_GetDeleteStatus,
934 _generic_GetInfoLog
935 },
936 _fragment_shader_GetSubType,
937 _shader_GetCompileStatus,
938 _shader_SetSource,
939 _shader_GetSource,
940 _shader_Compile
941 }
942 };
943
944 static void
945 _fragment_shader_constructor (struct gl2_fragment_shader_impl *impl)
946 {
947 _shader_constructor ((struct gl2_shader_impl *) impl);
948 impl->_vftbl = &_fragment_shader_vftbl;
949 impl->_obj._shader._generic._unknown._destructor = _fragment_shader_destructor;
950 #if USE_3DLABS_FRONTEND
951 impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangFragment, 0);
952 #endif
953 }
954
955 struct gl2_vertex_shader_obj
956 {
957 struct gl2_shader_obj _shader;
958 };
959
960 struct gl2_vertex_shader_impl
961 {
962 struct gl2_vertex_shader_intf *_vftbl;
963 struct gl2_vertex_shader_obj _obj;
964 };
965
966 static void
967 _vertex_shader_destructor (struct gl2_unknown_intf **intf)
968 {
969 struct gl2_vertex_shader_impl *impl = (struct gl2_vertex_shader_impl *) intf;
970
971 (void) impl;
972 /* TODO free vertex shader data */
973
974 _shader_destructor (intf);
975 }
976
977 static struct gl2_unknown_intf **
978 _vertex_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
979 {
980 if (uiid == UIID_VERTEX_SHADER)
981 {
982 (**intf).AddRef (intf);
983 return intf;
984 }
985 return _shader_QueryInterface (intf, uiid);
986 }
987
988 static GLenum
989 _vertex_shader_GetSubType (struct gl2_shader_intf **intf)
990 {
991 return GL_VERTEX_SHADER_ARB;
992 }
993
994 static struct gl2_vertex_shader_intf _vertex_shader_vftbl = {
995 {
996 {
997 {
998 _unknown_AddRef,
999 _unknown_Release,
1000 _vertex_shader_QueryInterface
1001 },
1002 _generic_Delete,
1003 _shader_GetType,
1004 _generic_GetName,
1005 _generic_GetDeleteStatus,
1006 _generic_GetInfoLog
1007 },
1008 _vertex_shader_GetSubType,
1009 _shader_GetCompileStatus,
1010 _shader_SetSource,
1011 _shader_GetSource,
1012 _shader_Compile
1013 }
1014 };
1015
1016 static void
1017 _vertex_shader_constructor (struct gl2_vertex_shader_impl *impl)
1018 {
1019 _shader_constructor ((struct gl2_shader_impl *) impl);
1020 impl->_vftbl = &_vertex_shader_vftbl;
1021 impl->_obj._shader._generic._unknown._destructor = _vertex_shader_destructor;
1022 #if USE_3DLABS_FRONTEND
1023 impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangVertex, 0);
1024 #endif
1025 }
1026
1027 GLhandleARB
1028 _mesa_3dlabs_create_shader_object (GLenum shaderType)
1029 {
1030 switch (shaderType)
1031 {
1032 case GL_FRAGMENT_SHADER_ARB:
1033 {
1034 struct gl2_fragment_shader_impl *x = (struct gl2_fragment_shader_impl *)
1035 _mesa_malloc (sizeof (struct gl2_fragment_shader_impl));
1036
1037 if (x != NULL)
1038 {
1039 _fragment_shader_constructor (x);
1040 return x->_obj._shader._generic.name;
1041 }
1042 }
1043 break;
1044 case GL_VERTEX_SHADER_ARB:
1045 {
1046 struct gl2_vertex_shader_impl *x = (struct gl2_vertex_shader_impl *)
1047 _mesa_malloc (sizeof (struct gl2_vertex_shader_impl));
1048
1049 if (x != NULL)
1050 {
1051 _vertex_shader_constructor (x);
1052 return x->_obj._shader._generic.name;
1053 }
1054 }
1055 break;
1056 }
1057
1058 return 0;
1059 }
1060
1061 GLhandleARB
1062 _mesa_3dlabs_create_program_object (void)
1063 {
1064 struct gl2_program_impl *x = (struct gl2_program_impl *)
1065 _mesa_malloc (sizeof (struct gl2_program_impl));
1066
1067 if (x != NULL)
1068 {
1069 _program_constructor (x);
1070 return x->_obj._container._generic.name;
1071 }
1072
1073 return 0;
1074 }
1075
1076 #include "slang_assemble.h"
1077 #include "slang_execute.h"
1078
1079 static GLubyte *get_address_of (struct gl2_vertex_shader_intf **vs, const char *name)
1080 {
1081 struct gl2_vertex_shader_impl *impl;
1082 slang_translation_unit *unit;
1083 slang_atom atom;
1084 slang_variable *var;
1085
1086 impl = (struct gl2_vertex_shader_impl *) vs;
1087 unit = &impl->_obj._shader.unit;
1088 atom = slang_atom_pool_atom (unit->atom_pool, name);
1089 var = _slang_locate_variable (&unit->globals, atom, 1);
1090 if (var == NULL || var->address == ~0)
1091 return NULL;
1092 return (GLubyte *) unit->machine->mem + var->address;
1093 }
1094
1095 static GLubyte *get_address_of_f (struct gl2_fragment_shader_intf **fs, const char *name)
1096 {
1097 struct gl2_fragment_shader_impl *impl;
1098 slang_translation_unit *unit;
1099 slang_atom atom;
1100 slang_variable *var;
1101
1102 impl = (struct gl2_fragment_shader_impl *) fs;
1103 unit = &impl->_obj._shader.unit;
1104 atom = slang_atom_pool_atom (unit->atom_pool, name);
1105 var = _slang_locate_variable (&unit->globals, atom, 1);
1106 if (var == NULL || var->address == ~0)
1107 return NULL;
1108 return (GLubyte *) unit->machine->mem + var->address;
1109 }
1110
1111 static int fetch_mem (struct gl2_vertex_shader_intf **vs, const char *name, GLvoid *val,
1112 GLuint size, GLuint index, int write)
1113 {
1114 GLubyte *data;
1115
1116 data = get_address_of (vs, name);
1117 if (data == NULL)
1118 return 0;
1119 if (write)
1120 _mesa_memcpy (data + index * size, val, size);
1121 else
1122 _mesa_memcpy (val, data + index * size, size);
1123 return 1;
1124 }
1125
1126 static int fetch_mem_f (struct gl2_fragment_shader_intf **fs, const char *name, GLvoid *val,
1127 GLuint size, GLuint index, int write)
1128 {
1129 GLubyte *data;
1130
1131 data = get_address_of_f (fs, name);
1132 if (data == NULL)
1133 return 0;
1134 if (write)
1135 _mesa_memcpy (data + index * size, val, size);
1136 else
1137 _mesa_memcpy (val, data + index * size, size);
1138 return 1;
1139 }
1140
1141 int _slang_fetch_float (struct gl2_vertex_shader_intf **vs, const char *name, GLfloat *val, int write)
1142 {
1143 return fetch_mem (vs, name, val, 4, 0, write);
1144 }
1145
1146 int _slang_fetch_vec3 (struct gl2_vertex_shader_intf **vs, const char *name, GLfloat *val, int write)
1147 {
1148 return fetch_mem (vs, name, val, 12, 0, write);
1149 }
1150
1151 int _slang_fetch_vec4 (struct gl2_vertex_shader_intf **vs, const char *name, GLfloat *val,
1152 GLuint index, int write)
1153 {
1154 return fetch_mem (vs, name, val, 16, index, write);
1155 }
1156
1157 int _slang_fetch_vec4_f (struct gl2_fragment_shader_intf **fs, const char *name, GLfloat *val,
1158 GLuint index, int write)
1159 {
1160 return fetch_mem_f (fs, name, val, 16, index, write);
1161 }
1162
1163 int _slang_fetch_mat3 (struct gl2_vertex_shader_intf **vs, const char *name, GLfloat *val,
1164 GLuint index, int write)
1165 {
1166 return fetch_mem (vs, name, val, 36, index, write);
1167 }
1168
1169 int _slang_fetch_mat4 (struct gl2_vertex_shader_intf **vs, const char *name, GLfloat *val,
1170 GLuint index, int write)
1171 {
1172 return fetch_mem (vs, name, val, 64, index, write);
1173 }
1174
1175 int _slang_fetch_discard (struct gl2_fragment_shader_intf **fs, GLboolean *val)
1176 {
1177 struct gl2_fragment_shader_impl *impl;
1178 slang_translation_unit *unit;
1179
1180 impl = (struct gl2_fragment_shader_impl *) fs;
1181 unit = &impl->_obj._shader.unit;
1182 *val = unit->machine->kill ? GL_TRUE : GL_FALSE;
1183 return 1;
1184 }
1185
1186 void exec_vertex_shader (struct gl2_vertex_shader_intf **vs)
1187 {
1188 struct gl2_vertex_shader_impl *impl;
1189 slang_translation_unit *unit;
1190 slang_atom atom;
1191 unsigned int i;
1192
1193 impl = (struct gl2_vertex_shader_impl *) vs;
1194 unit = &impl->_obj._shader.unit;
1195 atom = slang_atom_pool_atom (unit->atom_pool, "main");
1196 for (i = 0; i < unit->functions.num_functions; i++)
1197 if (atom == unit->functions.functions[i].header.a_name)
1198 break;
1199 if (i < unit->functions.num_functions)
1200 {
1201 slang_function *f;
1202 slang_assembly_file_restore_point point;
1203 slang_assemble_ctx A;
1204
1205 f = &unit->functions.functions[i];
1206 slang_assembly_file_restore_point_save (unit->assembly, &point);
1207
1208 slang_machine_init (unit->machine);
1209 unit->machine->ip = unit->assembly->count;
1210
1211 A.file = unit->assembly;
1212 A.mach = unit->machine;
1213 A.atoms = unit->atom_pool;
1214 A.space.funcs = &unit->functions;
1215 A.space.structs = &unit->structs;
1216 A.space.vars = &unit->globals;
1217 slang_assembly_file_push_label (unit->assembly, slang_asm_local_alloc, 20);
1218 slang_assembly_file_push_label (unit->assembly, slang_asm_enter, 20);
1219 _slang_assemble_function_call (&A, f, NULL, 0, GL_FALSE);
1220 slang_assembly_file_push (unit->assembly, slang_asm_exit);
1221
1222 _slang_execute2 (unit->assembly, unit->machine);
1223
1224 slang_assembly_file_restore_point_load (unit->assembly, &point);
1225 }
1226 }
1227
1228 void exec_fragment_shader (struct gl2_fragment_shader_intf **fs)
1229 {
1230 struct gl2_fragment_shader_impl *impl;
1231 slang_translation_unit *unit;
1232 slang_atom atom;
1233 unsigned int i;
1234
1235 impl = (struct gl2_fragment_shader_impl *) fs;
1236 unit = &impl->_obj._shader.unit;
1237 atom = slang_atom_pool_atom (unit->atom_pool, "main");
1238 for (i = 0; i < unit->functions.num_functions; i++)
1239 if (atom == unit->functions.functions[i].header.a_name)
1240 break;
1241 if (i < unit->functions.num_functions)
1242 {
1243 slang_function *f;
1244 slang_assembly_file_restore_point point;
1245 slang_assemble_ctx A;
1246
1247 f = &unit->functions.functions[i];
1248 slang_assembly_file_restore_point_save (unit->assembly, &point);
1249
1250 slang_machine_init (unit->machine);
1251 unit->machine->ip = unit->assembly->count;
1252
1253 A.file = unit->assembly;
1254 A.mach = unit->machine;
1255 A.atoms = unit->atom_pool;
1256 A.space.funcs = &unit->functions;
1257 A.space.structs = &unit->structs;
1258 A.space.vars = &unit->globals;
1259 slang_assembly_file_push_label (unit->assembly, slang_asm_local_alloc, 20);
1260 slang_assembly_file_push_label (unit->assembly, slang_asm_enter, 20);
1261 _slang_assemble_function_call (&A, f, NULL, 0, GL_FALSE);
1262 slang_assembly_file_push (unit->assembly, slang_asm_exit);
1263
1264 _slang_execute2 (unit->assembly, unit->machine);
1265
1266 slang_assembly_file_restore_point_load (unit->assembly, &point);
1267 }
1268 }
1269
1270 GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name)
1271 {
1272 struct gl2_program_impl *impl;
1273 slang_uniform_bindings *bind;
1274 GLuint i;
1275
1276 impl = (struct gl2_program_impl *) pro;
1277 bind = &impl->_obj.prog.uniforms;
1278 for (i = 0; i < bind->count; i++)
1279 if (_mesa_strcmp (bind->table[i].name, name) == 0)
1280 return i;
1281 return -1;
1282 }
1283
1284 GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count,
1285 const GLvoid *data, GLenum type)
1286 {
1287 struct gl2_program_impl *impl;
1288 slang_uniform_bindings *bind;
1289 slang_uniform_binding *b;
1290 GLuint i;
1291
1292 if (loc == -1)
1293 return GL_TRUE;
1294
1295 impl = (struct gl2_program_impl *) pro;
1296 bind = &impl->_obj.prog.uniforms;
1297 if (loc >= bind->count)
1298 return GL_FALSE;
1299
1300 b = &bind->table[loc];
1301 /* TODO: check sizes */
1302 /* TODO: check if not structure */
1303 if (b->quant->u.basic_type != type)
1304 return GL_FALSE;
1305
1306 for (i = 0; i < SLANG_UNIFORM_BINDING_MAX; i++)
1307 if (b->address[i] != ~0)
1308 {
1309 _mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data,
1310 count * b->quant->size);
1311 }
1312 return GL_TRUE;
1313 }
1314
1315 void
1316 _mesa_init_shaderobjects_3dlabs (GLcontext *ctx)
1317 {
1318 #if USE_3DLABS_FRONTEND
1319 _glslang_3dlabs_InitProcess ();
1320 _glslang_3dlabs_ShInitialize ();
1321 #endif
1322 }
1323