blob: de449fe098008fe0e2c931c4f8b3731f00948754 [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 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#define DEBUG_PARSING 0
26
27/**
28 * \file arbprogparse.c
29 * ARB_*_program parser core
30 * \author Karl Rasche
31 */
32
33#include "mtypes.h"
34#include "glheader.h"
35#include "context.h"
36#include "hash.h"
37#include "imports.h"
38#include "macros.h"
39#include "program.h"
40#include "nvvertprog.h"
41#include "nvfragprog.h"
42#include "arbprogparse.h"
43#include "grammar_mesa.h"
44
45/* TODO:
46 * Fragment Program Stuff:
47 * -----------------------------------------------------
48 *
49 * - things from Michal's email
50 * + overflow on atoi
51 * + not-overflowing floats (don't use parse_integer..)
52 * + can remove range checking in arbparse.c
53 *
54 * - check all limits of number of various variables
55 * + parameters
56 *
57 * - test! test! test!
58 *
59 * Vertex Program Stuff:
60 * -----------------------------------------------------
61 * - Optimize param array usage and count limits correctly, see spec,
62 * section 2.14.3.7
63 * + Record if an array is reference absolutly or relatively (or both)
64 * + For absolute arrays, store a bitmap of accesses
65 * + For single parameters, store an access flag
66 * + After parsing, make a parameter cleanup and merging pass, where
67 * relative arrays are layed out first, followed by abs arrays, and
68 * finally single state.
69 * + Remap offsets for param src and dst registers
70 * + Now we can properly count parameter usage
71 *
72 * - Multiple state binding errors in param arrays (see spec, just before
73 * section 2.14.3.3)
74 * - grep for XXX
75 *
76 * Mesa Stuff
77 * -----------------------------------------------------
78 * - User clipping planes vs. PositionInvariant
79 * - Is it sufficient to just multiply by the mvp to transform in the
80 * PositionInvariant case? Or do we need something more involved?
81 *
82 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
83 * - fetch state listed in program_parameters list
84 * + WTF should this go???
85 * + currently in nvvertexec.c and s_nvfragprog.c
86 *
87 * - allow for multiple address registers (and fetch address regs properly)
88 *
89 * Cosmetic Stuff
90 * -----------------------------------------------------
91 * - remove any leftover unused grammer.c stuff (dict_ ?)
92 * - fix grammer.c error handling so its not static
93 * - #ifdef around stuff pertaining to extentions
94 *
95 * Outstanding Questions:
96 * -----------------------------------------------------
97 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
98 * what gets hacked off because of this:
99 * + VERTEX_ATTRIB_MATRIXINDEX
100 * + VERTEX_ATTRIB_WEIGHT
101 * + MATRIX_MODELVIEW
102 * + MATRIX_PALETTE
103 *
104 * - When can we fetch env/local params from their own register files, and
105 * when to we have to fetch them into the main state register file?
106 * (think arrays)
107 *
108 * Grammar Changes:
109 * -----------------------------------------------------
110 */
111
112/* Changes since moving the file to shader directory
113
1142004-III-4 ------------------------------------------------------------
115- added #include "grammar_mesa.h"
116- removed grammar specific code part (it resides now in grammar.c)
117- added GL_ARB_fragment_program_shadow tokens
118- modified #include "arbparse_syn.h"
119- major changes inside _mesa_parse_arb_program()
120- check the program string for '\0' characters
121- copy the program string to a one-byte-longer location to have
122 it null-terminated
123- position invariance test (not writing to result.position) moved
124 to syntax part
125*/
126
127typedef GLubyte *production;
128
129/**
130 * This is the text describing the rules to parse the grammar
131 */
132static char arb_grammar_text[] =
133#include "arbprogram_syn.h"
134;
135
136/**
137 * These should match up with the values defined in arbprogram.syn
138 */
139
140/*
141 Changes:
142 - changed and merged V_* and F_* opcode values to OP_*.
143 - added GL_ARB_fragment_program_shadow specific tokens (michal)
144*/
145#define REVISION 0x07
146
147/* program type */
148#define FRAGMENT_PROGRAM 0x01
149#define VERTEX_PROGRAM 0x02
150
151/* program section */
152#define OPTION 0x01
153#define INSTRUCTION 0x02
154#define DECLARATION 0x03
155#define END 0x04
156
157/* GL_ARB_fragment_program option flags */
158#define ARB_PRECISION_HINT_FASTEST 0x01
159#define ARB_PRECISION_HINT_NICEST 0x02
160#define ARB_FOG_EXP 0x04
161#define ARB_FOG_EXP2 0x08
162#define ARB_FOG_LINEAR 0x10
163
164/* GL_ARB_vertex_program option flags */
165#define ARB_POSITION_INVARIANT 0x20
166
167/* GL_ARB_fragment_program_shadow option flags */
168#define ARB_FRAGMENT_PROGRAM_SHADOW 0x40
169
170/* GL_ARB_fragment_program instruction class */
171#define OP_ALU_INST 0x00
172#define OP_TEX_INST 0x01
173
174/* GL_ARB_vertex_program instruction class */
175/* OP_ALU_INST */
176
177/* GL_ARB_fragment_program instruction type */
178#define OP_ALU_VECTOR 0x00
179#define OP_ALU_SCALAR 0x01
180#define OP_ALU_BINSC 0x02
181#define OP_ALU_BIN 0x03
182#define OP_ALU_TRI 0x04
183#define OP_ALU_SWZ 0x05
184#define OP_TEX_SAMPLE 0x06
185#define OP_TEX_KIL 0x07
186
187/* GL_ARB_vertex_program instruction type */
188#define OP_ALU_ARL 0x08
189/* OP_ALU_VECTOR */
190/* OP_ALU_SCALAR */
191/* OP_ALU_BINSC */
192/* OP_ALU_BIN */
193/* OP_ALU_TRI */
194/* OP_ALU_SWZ */
195
196/* GL_ARB_fragment_program instruction code */
197#define OP_ABS 0x00
198#define OP_ABS_SAT 0x1B
199#define OP_FLR 0x09
200#define OP_FLR_SAT 0x26
201#define OP_FRC 0x0A
202#define OP_FRC_SAT 0x27
203#define OP_LIT 0x0C
204#define OP_LIT_SAT 0x2A
205#define OP_MOV 0x11
206#define OP_MOV_SAT 0x30
207#define OP_COS 0x1F
208#define OP_COS_SAT 0x20
209#define OP_EX2 0x07
210#define OP_EX2_SAT 0x25
211#define OP_LG2 0x0B
212#define OP_LG2_SAT 0x29
213#define OP_RCP 0x14
214#define OP_RCP_SAT 0x33
215#define OP_RSQ 0x15
216#define OP_RSQ_SAT 0x34
217#define OP_SIN 0x38
218#define OP_SIN_SAT 0x39
219#define OP_SCS 0x35
220#define OP_SCS_SAT 0x36
221#define OP_POW 0x13
222#define OP_POW_SAT 0x32
223#define OP_ADD 0x01
224#define OP_ADD_SAT 0x1C
225#define OP_DP3 0x03
226#define OP_DP3_SAT 0x21
227#define OP_DP4 0x04
228#define OP_DP4_SAT 0x22
229#define OP_DPH 0x05
230#define OP_DPH_SAT 0x23
231#define OP_DST 0x06
232#define OP_DST_SAT 0x24
233#define OP_MAX 0x0F
234#define OP_MAX_SAT 0x2E
235#define OP_MIN 0x10
236#define OP_MIN_SAT 0x2F
237#define OP_MUL 0x12
238#define OP_MUL_SAT 0x31
239#define OP_SGE 0x16
240#define OP_SGE_SAT 0x37
241#define OP_SLT 0x17
242#define OP_SLT_SAT 0x3A
243#define OP_SUB 0x18
244#define OP_SUB_SAT 0x3B
245#define OP_XPD 0x1A
246#define OP_XPD_SAT 0x43
247#define OP_CMP 0x1D
248#define OP_CMP_SAT 0x1E
249#define OP_LRP 0x2B
250#define OP_LRP_SAT 0x2C
251#define OP_MAD 0x0E
252#define OP_MAD_SAT 0x2D
253#define OP_SWZ 0x19
254#define OP_SWZ_SAT 0x3C
255#define OP_TEX 0x3D
256#define OP_TEX_SAT 0x3E
257#define OP_TXB 0x3F
258#define OP_TXB_SAT 0x40
259#define OP_TXP 0x41
260#define OP_TXP_SAT 0x42
261#define OP_KIL 0x28
262
263/* GL_ARB_vertex_program instruction code */
264#define OP_ARL 0x02
265/* OP_ABS */
266/* OP_FLR */
267/* OP_FRC */
268/* OP_LIT */
269/* OP_MOV */
270/* OP_EX2 */
271#define OP_EXP 0x08
272/* OP_LG2 */
273#define OP_LOG 0x0D
274/* OP_RCP */
275/* OP_RSQ */
276/* OP_POW */
277/* OP_ADD */
278/* OP_DP3 */
279/* OP_DP4 */
280/* OP_DPH */
281/* OP_DST */
282/* OP_MAX */
283/* OP_MIN */
284/* OP_MUL */
285/* OP_SGE */
286/* OP_SLT */
287/* OP_SUB */
288/* OP_XPD */
289/* OP_MAD */
290/* OP_SWZ */
291
292/* fragment attribute binding */
293#define FRAGMENT_ATTRIB_COLOR 0x01
294#define FRAGMENT_ATTRIB_TEXCOORD 0x02
295#define FRAGMENT_ATTRIB_FOGCOORD 0x03
296#define FRAGMENT_ATTRIB_POSITION 0x04
297
298/* vertex attribute binding */
299#define VERTEX_ATTRIB_POSITION 0x01
300#define VERTEX_ATTRIB_WEIGHT 0x02
301#define VERTEX_ATTRIB_NORMAL 0x03
302#define VERTEX_ATTRIB_COLOR 0x04
303#define VERTEX_ATTRIB_FOGCOORD 0x05
304#define VERTEX_ATTRIB_TEXCOORD 0x06
305#define VERTEX_ATTRIB_MATRIXINDEX 0x07
306#define VERTEX_ATTRIB_GENERIC 0x08
307
308/* fragment result binding */
309#define FRAGMENT_RESULT_COLOR 0x01
310#define FRAGMENT_RESULT_DEPTH 0x02
311
312/* vertex result binding */
313#define VERTEX_RESULT_POSITION 0x01
314#define VERTEX_RESULT_COLOR 0x02
315#define VERTEX_RESULT_FOGCOORD 0x03
316#define VERTEX_RESULT_POINTSIZE 0x04
317#define VERTEX_RESULT_TEXCOORD 0x05
318
319/* texture target */
320#define TEXTARGET_1D 0x01
321#define TEXTARGET_2D 0x02
322#define TEXTARGET_3D 0x03
323#define TEXTARGET_RECT 0x04
324#define TEXTARGET_CUBE 0x05
325/* GL_ARB_fragment_program_shadow */
326#define TEXTARGET_SHADOW1D 0x06
327#define TEXTARGET_SHADOW2D 0x07
328#define TEXTARGET_SHADOWRECT 0x08
329
330/* face type */
331#define FACE_FRONT 0x00
332#define FACE_BACK 0x01
333
334/* color type */
335#define COLOR_PRIMARY 0x00
336#define COLOR_SECONDARY 0x01
337
338/* component */
339#define COMPONENT_X 0x00
340#define COMPONENT_Y 0x01
341#define COMPONENT_Z 0x02
342#define COMPONENT_W 0x03
343#define COMPONENT_0 0x04
344#define COMPONENT_1 0x05
345
346/* array index type */
347#define ARRAY_INDEX_ABSOLUTE 0x00
348#define ARRAY_INDEX_RELATIVE 0x01
349
350/* matrix name */
351#define MATRIX_MODELVIEW 0x01
352#define MATRIX_PROJECTION 0x02
353#define MATRIX_MVP 0x03
354#define MATRIX_TEXTURE 0x04
355#define MATRIX_PALETTE 0x05
356#define MATRIX_PROGRAM 0x06
357
358/* matrix modifier */
359#define MATRIX_MODIFIER_IDENTITY 0x00
360#define MATRIX_MODIFIER_INVERSE 0x01
361#define MATRIX_MODIFIER_TRANSPOSE 0x02
362#define MATRIX_MODIFIER_INVTRANS 0x03
363
364/* constant type */
365#define CONSTANT_SCALAR 0x01
366#define CONSTANT_VECTOR 0x02
367
368/* program param type */
369#define PROGRAM_PARAM_ENV 0x01
370#define PROGRAM_PARAM_LOCAL 0x02
371
372/* register type */
373#define REGISTER_ATTRIB 0x01
374#define REGISTER_PARAM 0x02
375#define REGISTER_RESULT 0x03
376#define REGISTER_ESTABLISHED_NAME 0x04
377
378/* param binding */
379#define PARAM_NULL 0x00
380#define PARAM_ARRAY_ELEMENT 0x01
381#define PARAM_STATE_ELEMENT 0x02
382#define PARAM_PROGRAM_ELEMENT 0x03
383#define PARAM_PROGRAM_ELEMENTS 0x04
384#define PARAM_CONSTANT 0x05
385
386/* param state property */
387#define STATE_MATERIAL_PARSER 0x01
388#define STATE_LIGHT_PARSER 0x02
389#define STATE_LIGHT_MODEL 0x03
390#define STATE_LIGHT_PROD 0x04
391#define STATE_FOG 0x05
392#define STATE_MATRIX_ROWS 0x06
393/* GL_ARB_fragment_program */
394#define STATE_TEX_ENV 0x07
395#define STATE_DEPTH 0x08
396/* GL_ARB_vertex_program */
397#define STATE_TEX_GEN 0x09
398#define STATE_CLIP_PLANE 0x0A
399#define STATE_POINT 0x0B
400
401/* state material property */
402#define MATERIAL_AMBIENT 0x01
403#define MATERIAL_DIFFUSE 0x02
404#define MATERIAL_SPECULAR 0x03
405#define MATERIAL_EMISSION 0x04
406#define MATERIAL_SHININESS 0x05
407
408/* state light property */
409#define LIGHT_AMBIENT 0x01
410#define LIGHT_DIFFUSE 0x02
411#define LIGHT_SPECULAR 0x03
412#define LIGHT_POSITION 0x04
413#define LIGHT_ATTENUATION 0x05
414#define LIGHT_HALF 0x06
415#define LIGHT_SPOT_DIRECTION 0x07
416
417/* state light model property */
418#define LIGHT_MODEL_AMBIENT 0x01
419#define LIGHT_MODEL_SCENECOLOR 0x02
420
421/* state light product property */
422#define LIGHT_PROD_AMBIENT 0x01
423#define LIGHT_PROD_DIFFUSE 0x02
424#define LIGHT_PROD_SPECULAR 0x03
425
426/* state texture environment property */
427#define TEX_ENV_COLOR 0x01
428
429/* state texture generation coord property */
430#define TEX_GEN_EYE 0x01
431#define TEX_GEN_OBJECT 0x02
432
433/* state fog property */
434#define FOG_COLOR 0x01
435#define FOG_PARAMS 0x02
436
437/* state depth property */
438#define DEPTH_RANGE 0x01
439
440/* state point parameters property */
441#define POINT_SIZE 0x01
442#define POINT_ATTENUATION 0x02
443
444/* declaration */
445#define ATTRIB 0x01
446#define PARAM 0x02
447#define TEMP 0x03
448#define OUTPUT 0x04
449#define ALIAS 0x05
450/* GL_ARB_vertex_program */
451#define ADDRESS 0x06
452
453/*-----------------------------------------------------------------------
454 * From here on down is the semantic checking portion
455 *
456 */
457
458/**
459 * Variable Table Handling functions
460 */
461typedef enum
462{
463 vt_none,
464 vt_address,
465 vt_attrib,
466 vt_param,
467 vt_temp,
468 vt_output,
469 vt_alias
470} var_type;
471
472
473/*
474 * Setting an explicit field for each of the binding properties is a bit wasteful
475 * of space, but it should be much more clear when reading later on..
476 */
477struct var_cache
478{
479 GLubyte *name;
480 var_type type;
481 GLuint address_binding; /* The index of the address register we should
482 * be using */
483 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
484 GLuint attrib_binding_idx; /* The index into the attrib register file corresponding
485 * to the state in attrib_binding */
486 GLuint attrib_is_generic; /* If the attrib was specified through a generic
487 * vertex attrib */
488 GLuint temp_binding; /* The index of the temp register we are to use */
489 GLuint output_binding; /* For type vt_output, see nvfragprog.h for values */
490 GLuint output_binding_idx; /* This is the index into the result register file
491 * corresponding to the bound result state */
492 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
493 * that this is aliased to */
494 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
495 * PROGRAM_ENV_PARAM} */
496 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
497 * the tokens representing our bound state (or constants)
498 * start */
499 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
500 * we take up with our state tokens or constants. Note that
501 * this is _not_ the same as the number of param registers
502 * we eventually use */
503 struct var_cache *next;
504};
505
506static GLvoid
507var_cache_create (struct var_cache **va)
508{
509 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
510 if (*va) {
511 (**va).name = NULL;
512 (**va).type = vt_none;
513 (**va).attrib_binding = ~0;
514 (**va).attrib_is_generic = 0;
515 (**va).temp_binding = ~0;
516 (**va).output_binding = ~0;
517 (**va).output_binding_idx = ~0;
518 (**va).param_binding_type = ~0;
519 (**va).param_binding_begin = ~0;
520 (**va).param_binding_length = ~0;
521 (**va).alias_binding = NULL;
522 (**va).next = NULL;
523 }
524}
525
526static GLvoid
527var_cache_destroy (struct var_cache **va)
528{
529 if (*va) {
530 var_cache_destroy (&(**va).next);
531 _mesa_free (*va);
532 *va = NULL;
533 }
534}
535
536static GLvoid
537var_cache_append (struct var_cache **va, struct var_cache *nv)
538{
539 if (*va)
540 var_cache_append (&(**va).next, nv);
541 else
542 *va = nv;
543}
544
545static struct var_cache *
546var_cache_find (struct var_cache *va, GLubyte * name)
547{
548 struct var_cache *first = va;
549
550 while (va) {
551 if (!strcmp ( (const char*) name, (const char*) va->name)) {
552 if (va->type == vt_alias)
553 return var_cache_find (first, va->name);
554 return va;
555 }
556
557 va = va->next;
558 }
559
560 return NULL;
561}
562
563/**
564 * constructs an integer from 4 GLubytes in LE format
565 */
566static GLuint
567parse_position (GLubyte ** inst)
568{
569 GLuint value;
570
571 value = (GLuint) (*(*inst)++);
572 value += (GLuint) (*(*inst)++) * 0x100;
573 value += (GLuint) (*(*inst)++) * 0x10000;
574 value += (GLuint) (*(*inst)++) * 0x1000000;
575
576 return value;
577}
578
579/**
580 * This will, given a string, lookup the string as a variable name in the
581 * var cache. If the name is found, the var cache node corresponding to the
582 * var name is returned. If it is not found, a new entry is allocated
583 *
584 * \param I Points into the binary array where the string identifier begins
585 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
586 * \return The location on the var_cache corresponding the the string starting at I
587 */
588static struct var_cache *
589parse_string (GLubyte ** inst, struct var_cache **vc_head,
590 struct arb_program *Program, GLuint * found)
591{
592 GLubyte *i = *inst;
593 struct var_cache *va = NULL;
594
595 *inst += _mesa_strlen ((char *) i) + 1;
596
597 va = var_cache_find (*vc_head, i);
598
599 if (va) {
600 *found = 1;
601 return va;
602 }
603
604 *found = 0;
605 var_cache_create (&va);
606 va->name = i;
607
608 var_cache_append (vc_head, va);
609
610 return va;
611}
612
613static char *
614parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
615{
616 GLubyte *i = *inst;
617
618 *inst += _mesa_strlen ((char *) i) + 1;
619
620 return (char *) i;
621}
622
623/**
Brian Paul05908952004-06-08 15:20:23 +0000624 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000625 */
Brian Paul05908952004-06-08 15:20:23 +0000626static GLint
Jouk Jansen40322e12004-04-05 08:50:36 +0000627parse_sign (GLubyte ** inst)
628{
629 /*return *(*inst)++ != '+'; */
630
631 if (**inst == '-') {
632 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000633 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000634 }
635 else if (**inst == '+') {
636 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000637 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000638 }
639
Brian Paul05908952004-06-08 15:20:23 +0000640 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000641}
642
643/**
644 * parses and returns signed integer
645 */
646static GLint
647parse_integer (GLubyte ** inst, struct arb_program *Program)
648{
649 GLint sign;
650 GLint value;
651
652 /* check if *inst points to '+' or '-'
653 * if yes, grab the sign and increment *inst
654 */
655 sign = parse_sign (inst);
656
657 /* now check if *inst points to 0
658 * if yes, increment the *inst and return the default value
659 */
660 if (**inst == 0) {
661 (*inst)++;
662 return 0;
663 }
664
665 /* parse the integer as you normally would do it */
666 value = _mesa_atoi (parse_string_without_adding (inst, Program));
667
668 /* now, after terminating 0 there is a position
669 * to parse it - parse_position()
670 */
671 Program->Position = parse_position (inst);
672
Brian Paul05908952004-06-08 15:20:23 +0000673 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000674}
675
676/**
677 */
678static GLfloat
679parse_float (GLubyte ** inst, struct arb_program *Program)
680{
681 GLint tmp[5], denom;
682 GLuint leading_zeros =0;
683 GLfloat value = 0;
684
Jouk Jansen40322e12004-04-05 08:50:36 +0000685 tmp[1] = parse_integer (inst, Program); /* This is the integer portion of the number */
686
687 /* Now we grab the fractional portion of the number (the digits after
688 * the .). We can have leading 0's here, which parse_integer will ignore,
689 * so we'll check for those first
690 */
691 while ((**inst == '0') && ( *(*inst+1) != 0))
692 {
693 leading_zeros++;
694 (*inst)++;
695 }
696 tmp[2] = parse_integer (inst, Program); /* This is the fractional portion of the number */
697 tmp[3] = parse_sign (inst); /* This is the sign of the exponent */
698 tmp[4] = parse_integer (inst, Program); /* This is the exponent */
699
700 value = (GLfloat) tmp[1];
701 denom = 1;
702 while (denom < tmp[2])
703 denom *= 10;
704 denom *= (GLint) _mesa_pow( 10, leading_zeros );
705 value += (GLfloat) tmp[2] / (GLfloat) denom;
Brian Paul05908952004-06-08 15:20:23 +0000706
Jouk Jansen40322e12004-04-05 08:50:36 +0000707 value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
708
709 return value;
710}
711
712
713/**
714 */
715static GLfloat
716parse_signed_float (GLubyte ** inst, struct arb_program *Program)
717{
Brian Paul05908952004-06-08 15:20:23 +0000718 GLint sign = parse_sign (inst);
719 GLfloat value = parse_float (inst, Program);
720 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000721}
722
723/**
724 * This picks out a constant value from the parsed array. The constant vector is r
725 * returned in the *values array, which should be of length 4.
726 *
727 * \param values - The 4 component vector with the constant value in it
728 */
729static GLvoid
730parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
731 GLboolean use)
732{
733 GLuint components, i;
734
735
736 switch (*(*inst)++) {
737 case CONSTANT_SCALAR:
738 if (use == GL_TRUE) {
739 values[0] =
740 values[1] =
741 values[2] = values[3] = parse_float (inst, Program);
742 }
743 else {
744 values[0] =
745 values[1] =
746 values[2] = values[3] = parse_signed_float (inst, Program);
747 }
748
749 break;
750 case CONSTANT_VECTOR:
751 values[0] = values[1] = values[2] = 0;
752 values[3] = 1;
753 components = *(*inst)++;
754 for (i = 0; i < components; i++) {
755 values[i] = parse_signed_float (inst, Program);
756 }
757 break;
758 }
759}
760
761/**
762 * \param offset The offset from the address register that we should
763 * address
764 *
765 * \return 0 on sucess, 1 on error
766 */
767static GLuint
768parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
769 GLint *offset)
770{
771 *offset = parse_integer(inst, Program);
772 if ((*offset > 63) || (*offset < -64)) {
773 _mesa_set_program_error (ctx, Program->Position,
774 "Relative offset out of range");
775 _mesa_error (ctx, GL_INVALID_OPERATION, "Relative offset %d out of range",
776 *offset);
777 return 1;
778 }
779
780 return 0;
781}
782
783/**
784 * \param color 0 if color type is primary, 1 if color type is secondary
785 * \return 0 on sucess, 1 on error
786 */
787static GLuint
788parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
789 GLint * color)
790{
791 *color = *(*inst)++ != COLOR_PRIMARY;
792 return 0;
793}
794
795/**
796 * Get an integer corresponding to a generic vertex attribute.
797 *
798 * \return 0 on sucess, 1 on error
799 */
800static GLuint
801parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
802 struct arb_program *Program, GLuint *attrib)
803{
804 *attrib = parse_integer(inst, Program);
805
806 if ((*attrib < 0) || (*attrib > MAX_VERTEX_PROGRAM_ATTRIBS))
807 {
808 _mesa_set_program_error (ctx, Program->Position,
809 "Invalid generic vertex attribute index");
810 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
811
812 return 1;
813 }
814
815 return 0;
816}
817
818
819/**
820 * \param coord The texture unit index
821 * \return 0 on sucess, 1 on error
822 */
823static GLuint
824parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
825 struct arb_program *Program, GLuint * coord)
826{
827 *coord = parse_integer (inst, Program);
828
829 if ((*coord < 0) || (*coord >= ctx->Const.MaxTextureUnits)) {
830 _mesa_set_program_error (ctx, Program->Position,
831 "Invalid texture unit index");
832 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
833 return 1;
834 }
835
836 return 0;
837}
838
839/**
840 * \param coord The weight index
841 * \return 0 on sucess, 1 on error
842 */
843static GLuint
844parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
845 GLint * coord)
846{
847 *coord = parse_integer (inst, Program);
848
849 if ((*coord < 0) || (*coord >= 1)) {
850 _mesa_set_program_error (ctx, Program->Position,
851 "Invalid weight index");
852 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
853 return 1;
854 }
855
856 return 0;
857}
858
859/**
860 * \param coord The clip plane index
861 * \return 0 on sucess, 1 on error
862 */
863static GLuint
864parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
865 struct arb_program *Program, GLint * coord)
866{
867 *coord = parse_integer (inst, Program);
868
869 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
870 _mesa_set_program_error (ctx, Program->Position,
871 "Invalid clip plane index");
872 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
873 return 1;
874 }
875
876 return 0;
877}
878
879
880/**
881 * \return 0 on front face, 1 on back face
882 */
883static GLuint
884parse_face_type (GLubyte ** inst)
885{
886 switch (*(*inst)++) {
887 case FACE_FRONT:
888 return 0;
889
890 case FACE_BACK:
891 return 1;
892 }
893 return 0;
894}
895
896
897/**
898 * Given a matrix and a modifier token on the binary array, return tokens
899 * that _mesa_fetch_state() [program.c] can understand.
900 *
901 * \param matrix - the matrix we are talking about
902 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
903 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
904 * \return 0 on sucess, 1 on failure
905 */
906static GLuint
907parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
908 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
909{
910 GLubyte mat = *(*inst)++;
911
912 *matrix_idx = 0;
913
914 switch (mat) {
915 case MATRIX_MODELVIEW:
916 *matrix = STATE_MODELVIEW;
917 *matrix_idx = parse_integer (inst, Program);
918 if (*matrix_idx > 0) {
919 _mesa_set_program_error (ctx, Program->Position,
920 "ARB_vertex_blend not supported\n");
921 _mesa_error (ctx, GL_INVALID_OPERATION,
922 "ARB_vertex_blend not supported\n");
923 return 1;
924 }
925 break;
926
927 case MATRIX_PROJECTION:
928 *matrix = STATE_PROJECTION;
929 break;
930
931 case MATRIX_MVP:
932 *matrix = STATE_MVP;
933 break;
934
935 case MATRIX_TEXTURE:
936 *matrix = STATE_TEXTURE;
937 *matrix_idx = parse_integer (inst, Program);
938 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
939 _mesa_set_program_error (ctx, Program->Position,
940 "Invalid Texture Unit");
941 _mesa_error (ctx, GL_INVALID_OPERATION,
942 "Invalid Texture Unit: %d", *matrix_idx);
943 return 1;
944 }
945 break;
946
947 /* This is not currently supported (ARB_matrix_palette) */
948 case MATRIX_PALETTE:
949 *matrix_idx = parse_integer (inst, Program);
950 _mesa_set_program_error (ctx, Program->Position,
951 "ARB_matrix_palette not supported\n");
952 _mesa_error (ctx, GL_INVALID_OPERATION,
953 "ARB_matrix_palette not supported\n");
954 return 1;
955 break;
956
957 case MATRIX_PROGRAM:
958 *matrix = STATE_PROGRAM;
959 *matrix_idx = parse_integer (inst, Program);
960 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
961 _mesa_set_program_error (ctx, Program->Position,
962 "Invalid Program Matrix");
963 _mesa_error (ctx, GL_INVALID_OPERATION,
964 "Invalid Program Matrix: %d", *matrix_idx);
965 return 1;
966 }
967 break;
968 }
969
970 switch (*(*inst)++) {
971 case MATRIX_MODIFIER_IDENTITY:
972 *matrix_modifier = 0;
973 break;
974 case MATRIX_MODIFIER_INVERSE:
975 *matrix_modifier = STATE_MATRIX_INVERSE;
976 break;
977 case MATRIX_MODIFIER_TRANSPOSE:
978 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
979 break;
980 case MATRIX_MODIFIER_INVTRANS:
981 *matrix_modifier = STATE_MATRIX_INVTRANS;
982 break;
983 }
984
985 return 0;
986}
987
988
989/**
990 * This parses a state string (rather, the binary version of it) into
991 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
992 *
993 * \param inst - the start in the binary arry to start working from
994 * \param state_tokens - the storage for the 6-token state description
995 * \return - 0 on sucess, 1 on error
996 */
997static GLuint
998parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
999 struct arb_program *Program, GLint * state_tokens)
1000{
1001 switch (*(*inst)++) {
1002 case STATE_MATERIAL_PARSER:
1003 state_tokens[0] = STATE_MATERIAL;
1004 state_tokens[1] = parse_face_type (inst);
1005 switch (*(*inst)++) {
1006 case MATERIAL_AMBIENT:
1007 state_tokens[2] = STATE_AMBIENT;
1008 break;
1009 case MATERIAL_DIFFUSE:
1010 state_tokens[2] = STATE_DIFFUSE;
1011 break;
1012 case MATERIAL_SPECULAR:
1013 state_tokens[2] = STATE_SPECULAR;
1014 break;
1015 case MATERIAL_EMISSION:
1016 state_tokens[2] = STATE_EMISSION;
1017 break;
1018 case MATERIAL_SHININESS:
1019 state_tokens[2] = STATE_SHININESS;
1020 break;
1021 }
1022 break;
1023
1024 case STATE_LIGHT_PARSER:
1025 state_tokens[0] = STATE_LIGHT;
1026 state_tokens[1] = parse_integer (inst, Program);
1027
1028 /* Check the value of state_tokens[1] against the # of lights */
1029 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1030 _mesa_set_program_error (ctx, Program->Position,
1031 "Invalid Light Number");
1032 _mesa_error (ctx, GL_INVALID_OPERATION,
1033 "Invalid Light Number: %d", state_tokens[1]);
1034 return 1;
1035 }
1036
1037 switch (*(*inst)++) {
1038 case LIGHT_AMBIENT:
1039 state_tokens[2] = STATE_AMBIENT;
1040 break;
1041 case LIGHT_DIFFUSE:
1042 state_tokens[2] = STATE_DIFFUSE;
1043 break;
1044 case LIGHT_SPECULAR:
1045 state_tokens[2] = STATE_SPECULAR;
1046 break;
1047 case LIGHT_POSITION:
1048 state_tokens[2] = STATE_POSITION;
1049 break;
1050 case LIGHT_ATTENUATION:
1051 state_tokens[2] = STATE_ATTENUATION;
1052 break;
1053 case LIGHT_HALF:
1054 state_tokens[2] = STATE_HALF;
1055 break;
1056 case LIGHT_SPOT_DIRECTION:
1057 state_tokens[2] = STATE_SPOT_DIRECTION;
1058 break;
1059 }
1060 break;
1061
1062 case STATE_LIGHT_MODEL:
1063 switch (*(*inst)++) {
1064 case LIGHT_MODEL_AMBIENT:
1065 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1066 break;
1067 case LIGHT_MODEL_SCENECOLOR:
1068 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1069 state_tokens[1] = parse_face_type (inst);
1070 break;
1071 }
1072 break;
1073
1074 case STATE_LIGHT_PROD:
1075 state_tokens[0] = STATE_LIGHTPROD;
1076 state_tokens[1] = parse_integer (inst, Program);
1077
1078 /* Check the value of state_tokens[1] against the # of lights */
1079 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1080 _mesa_set_program_error (ctx, Program->Position,
1081 "Invalid Light Number");
1082 _mesa_error (ctx, GL_INVALID_OPERATION,
1083 "Invalid Light Number: %d", state_tokens[1]);
1084 return 1;
1085 }
1086
1087 state_tokens[2] = parse_face_type (inst);
1088 switch (*(*inst)++) {
1089 case LIGHT_PROD_AMBIENT:
1090 state_tokens[3] = STATE_AMBIENT;
1091 break;
1092 case LIGHT_PROD_DIFFUSE:
1093 state_tokens[3] = STATE_DIFFUSE;
1094 break;
1095 case LIGHT_PROD_SPECULAR:
1096 state_tokens[3] = STATE_SPECULAR;
1097 break;
1098 }
1099 break;
1100
1101
1102 case STATE_FOG:
1103 switch (*(*inst)++) {
1104 case FOG_COLOR:
1105 state_tokens[0] = STATE_FOG_COLOR;
1106 break;
1107 case FOG_PARAMS:
1108 state_tokens[0] = STATE_FOG_PARAMS;
1109 break;
1110 }
1111 break;
1112
1113 case STATE_TEX_ENV:
1114 state_tokens[1] = parse_integer (inst, Program);
1115 switch (*(*inst)++) {
1116 case TEX_ENV_COLOR:
1117 state_tokens[0] = STATE_TEXENV_COLOR;
1118 break;
1119 }
1120 break;
1121
1122 case STATE_TEX_GEN:
1123 {
1124 GLuint type, coord;
1125
1126 state_tokens[0] = STATE_TEXGEN;
1127 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1128
1129 if (parse_texcoord_num (ctx, inst, Program, &coord))
1130 return 1;
1131 state_tokens[1] = coord;
1132
1133 /* EYE or OBJECT */
1134 type = *(*inst++);
1135
1136 /* 0 - s, 1 - t, 2 - r, 3 - q */
1137 coord = *(*inst++);
1138
1139 if (type == TEX_GEN_EYE) {
1140 switch (coord) {
1141 case COMPONENT_X:
1142 state_tokens[2] = STATE_TEXGEN_EYE_S;
1143 break;
1144 case COMPONENT_Y:
1145 state_tokens[2] = STATE_TEXGEN_EYE_T;
1146 break;
1147 case COMPONENT_Z:
1148 state_tokens[2] = STATE_TEXGEN_EYE_R;
1149 break;
1150 case COMPONENT_W:
1151 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1152 break;
1153 }
1154 }
1155 else {
1156 switch (coord) {
1157 case COMPONENT_X:
1158 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1159 break;
1160 case COMPONENT_Y:
1161 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1162 break;
1163 case COMPONENT_Z:
1164 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1165 break;
1166 case COMPONENT_W:
1167 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1168 break;
1169 }
1170 }
1171 }
1172 break;
1173
1174 case STATE_DEPTH:
1175 switch (*(*inst)++) {
1176 case DEPTH_RANGE:
1177 state_tokens[0] = STATE_DEPTH_RANGE;
1178 break;
1179 }
1180 break;
1181
1182 case STATE_CLIP_PLANE:
1183 state_tokens[0] = STATE_CLIPPLANE;
1184 state_tokens[1] = parse_integer (inst, Program);
1185 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1186 return 1;
1187 break;
1188
1189 case STATE_POINT:
1190 switch (*(*inst++)) {
1191 case POINT_SIZE:
1192 state_tokens[0] = STATE_POINT_SIZE;
1193 break;
1194
1195 case POINT_ATTENUATION:
1196 state_tokens[0] = STATE_POINT_ATTENUATION;
1197 break;
1198 }
1199 break;
1200
1201 /* XXX: I think this is the correct format for a matrix row */
1202 case STATE_MATRIX_ROWS:
1203 state_tokens[0] = STATE_MATRIX;
1204 if (parse_matrix
1205 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1206 &state_tokens[5]))
1207 return 1;
1208
1209 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1210
1211 if ((**inst) != 0) { /* Either the last row, 0 */
1212 state_tokens[4] = parse_integer (inst, Program);
1213 if (state_tokens[4] < state_tokens[3]) {
1214 _mesa_set_program_error (ctx, Program->Position,
1215 "Second matrix index less than the first");
1216 _mesa_error (ctx, GL_INVALID_OPERATION,
1217 "Second matrix index (%d) less than the first (%d)",
1218 state_tokens[4], state_tokens[3]);
1219 return 1;
1220 }
1221 }
1222 else {
1223 state_tokens[4] = state_tokens[3];
1224 (*inst)++;
1225 }
1226 break;
1227 }
1228
1229 return 0;
1230}
1231
1232/**
1233 * This parses a state string (rather, the binary version of it) into
1234 * a 6-token similar for the state fetching code in program.c
1235 *
1236 * One might ask, why fetch these parameters into just like you fetch
1237 * state when they are already stored in other places?
1238 *
1239 * Because of array offsets -> We can stick env/local parameters in the
1240 * middle of a parameter array and then index someplace into the array
1241 * when we execute.
1242 *
1243 * One optimization might be to only do this for the cases where the
1244 * env/local parameters end up inside of an array, and leave the
1245 * single parameters (or arrays of pure env/local pareameters) in their
1246 * respective register files.
1247 *
1248 * For ENV parameters, the format is:
1249 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1250 * state_tokens[1] = STATE_ENV
1251 * state_tokens[2] = the parameter index
1252 *
1253 * for LOCAL parameters, the format is:
1254 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1255 * state_tokens[1] = STATE_LOCAL
1256 * state_tokens[2] = the parameter index
1257 *
1258 * \param inst - the start in the binary arry to start working from
1259 * \param state_tokens - the storage for the 6-token state description
1260 * \return - 0 on sucess, 1 on failure
1261 */
1262static GLuint
1263parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1264 struct arb_program *Program, GLint * state_tokens)
1265{
1266 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1267 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1268 else
1269 state_tokens[0] = STATE_VERTEX_PROGRAM;
1270
1271
1272 switch (*(*inst)++) {
1273 case PROGRAM_PARAM_ENV:
1274 state_tokens[1] = STATE_ENV;
1275 state_tokens[2] = parse_integer (inst, Program);
1276
1277 /* Check state_tokens[2] against the number of ENV parameters available */
1278 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1279 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
1280 ||
1281 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1282 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
1283 _mesa_set_program_error (ctx, Program->Position,
1284 "Invalid Program Env Parameter");
1285 _mesa_error (ctx, GL_INVALID_OPERATION,
1286 "Invalid Program Env Parameter: %d",
1287 state_tokens[2]);
1288 return 1;
1289 }
1290
1291 break;
1292
1293 case PROGRAM_PARAM_LOCAL:
1294 state_tokens[1] = STATE_LOCAL;
1295 state_tokens[2] = parse_integer (inst, Program);
1296
1297 /* Check state_tokens[2] against the number of LOCAL parameters available */
1298 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1299 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
1300 ||
1301 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1302 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
1303 _mesa_set_program_error (ctx, Program->Position,
1304 "Invalid Program Local Parameter");
1305 _mesa_error (ctx, GL_INVALID_OPERATION,
1306 "Invalid Program Local Parameter: %d",
1307 state_tokens[2]);
1308 return 1;
1309 }
1310 break;
1311 }
1312
1313 return 0;
1314}
1315
1316/**
1317 * For ARB_vertex_program, programs are not allowed to use both an explicit
1318 * vertex attribute and a generic vertex attribute corresponding to the same
1319 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1320 *
1321 * This will walk our var_cache and make sure that nobody does anything fishy.
1322 *
1323 * \return 0 on sucess, 1 on error
1324 */
1325static GLuint
1326generic_attrib_check(struct var_cache *vc_head)
1327{
1328 int a;
1329 struct var_cache *curr;
1330 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1331 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1332
1333 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1334 explicitAttrib[a] = GL_FALSE;
1335 genericAttrib[a] = GL_FALSE;
1336 }
1337
1338 curr = vc_head;
1339 while (curr) {
1340 if (curr->type == vt_attrib) {
1341 if (curr->attrib_is_generic)
1342 genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1343 else
1344 explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1345 }
1346
1347 curr = curr->next;
1348 }
1349
1350 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1351 if ((explicitAttrib[a]) && (genericAttrib[a]))
1352 return 1;
1353 }
1354
1355 return 0;
1356}
1357
1358/**
1359 * This will handle the binding side of an ATTRIB var declaration
1360 *
1361 * \param binding - the fragment input register state, defined in nvfragprog.h
1362 * \param binding_idx - the index in the attrib register file that binding is associated with
1363 * \return returns 0 on sucess, 1 on error
1364 *
1365 * See nvfragparse.c for attrib register file layout
1366 */
1367static GLuint
1368parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
1369 struct arb_program *Program, GLuint * binding,
1370 GLuint * binding_idx, GLuint *is_generic)
1371{
1372 GLuint texcoord;
1373 GLint coord;
1374 GLint err = 0;
1375
1376 *is_generic = 0;
1377 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1378 switch (*(*inst)++) {
1379 case FRAGMENT_ATTRIB_COLOR:
1380 err = parse_color_type (ctx, inst, Program, &coord);
1381 *binding = FRAG_ATTRIB_COL0 + coord;
1382 *binding_idx = 1 + coord;
1383 break;
1384
1385 case FRAGMENT_ATTRIB_TEXCOORD:
1386 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1387 *binding = FRAG_ATTRIB_TEX0 + texcoord;
1388 *binding_idx = 4 + texcoord;
1389 break;
1390
1391 case FRAGMENT_ATTRIB_FOGCOORD:
1392 *binding = FRAG_ATTRIB_FOGC;
1393 *binding_idx = 3;
1394 break;
1395
1396 case FRAGMENT_ATTRIB_POSITION:
1397 *binding = FRAG_ATTRIB_WPOS;
1398 *binding_idx = 0;
1399 break;
1400
1401 default:
1402 err = 1;
1403 break;
1404 }
1405 }
1406 else {
1407 switch (*(*inst)++) {
1408 case VERTEX_ATTRIB_POSITION:
1409 *binding = VERT_ATTRIB_POS;
1410 *binding_idx = 0;
1411 break;
1412
1413 case VERTEX_ATTRIB_WEIGHT:
1414 {
1415 GLint weight;
1416
1417 err = parse_weight_num (ctx, inst, Program, &weight);
1418 *binding = VERT_ATTRIB_WEIGHT;
1419 *binding_idx = 1;
1420 }
1421 _mesa_set_program_error (ctx, Program->Position,
1422 "ARB_vertex_blend not supported\n");
1423 _mesa_error (ctx, GL_INVALID_OPERATION,
1424 "ARB_vertex_blend not supported\n");
1425 return 1;
1426 break;
1427
1428 case VERTEX_ATTRIB_NORMAL:
1429 *binding = VERT_ATTRIB_NORMAL;
1430 *binding_idx = 2;
1431 break;
1432
1433 case VERTEX_ATTRIB_COLOR:
1434 {
1435 GLint color;
1436
1437 err = parse_color_type (ctx, inst, Program, &color);
1438 if (color) {
1439 *binding = VERT_ATTRIB_COLOR1;
1440 *binding_idx = 4;
1441 }
1442 else {
1443 *binding = VERT_ATTRIB_COLOR0;
1444 *binding_idx = 3;
1445 }
1446 }
1447 break;
1448
1449 case VERTEX_ATTRIB_FOGCOORD:
1450 *binding = VERT_ATTRIB_FOG;
1451 *binding_idx = 5;
1452 break;
1453
1454 case VERTEX_ATTRIB_TEXCOORD:
1455 {
1456 GLuint unit;
1457
1458 err = parse_texcoord_num (ctx, inst, Program, &unit);
1459 *binding = VERT_ATTRIB_TEX0 + unit;
1460 *binding_idx = 8 + unit;
1461 }
1462 break;
1463
1464 /* It looks like we don't support this at all, atm */
1465 case VERTEX_ATTRIB_MATRIXINDEX:
1466 parse_integer (inst, Program);
1467 _mesa_set_program_error (ctx, Program->Position,
1468 "ARB_palette_matrix not supported");
1469 _mesa_error (ctx, GL_INVALID_OPERATION,
1470 "ARB_palette_matrix not supported");
1471 return 1;
1472 break;
1473
1474 case VERTEX_ATTRIB_GENERIC:
1475 {
1476 GLuint attrib;
1477
1478 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1479 *is_generic = 1;
1480 switch (attrib) {
1481 case 0:
1482 *binding = VERT_ATTRIB_POS;
1483 break;
1484 case 1:
1485 *binding = VERT_ATTRIB_WEIGHT;
1486 break;
1487 case 2:
1488 *binding = VERT_ATTRIB_NORMAL;
1489 break;
1490 case 3:
1491 *binding = VERT_ATTRIB_COLOR0;
1492 break;
1493 case 4:
1494 *binding = VERT_ATTRIB_COLOR1;
1495 break;
1496 case 5:
1497 *binding = VERT_ATTRIB_FOG;
1498 break;
1499 case 6:
1500 break;
1501 case 7:
1502 break;
1503 default:
1504 *binding = VERT_ATTRIB_TEX0 + (attrib-8);
1505 break;
1506 }
1507 *binding_idx = attrib;
1508 }
1509 }
1510 break;
1511
1512 default:
1513 err = 1;
1514 break;
1515 }
1516 }
1517
1518 /* Can this even happen? */
1519 if (err) {
1520 _mesa_set_program_error (ctx, Program->Position,
1521 "Bad attribute binding");
1522 _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
1523 }
1524
1525 Program->InputsRead |= (1 << *binding_idx);
1526
1527 return err;
1528}
1529
1530/**
1531 * This translates between a binary token for an output variable type
1532 * and the mesa token for the same thing.
1533 *
1534 *
1535 * XXX: What is the 'name' for vertex program state? -> do we need it?
1536 * I don't think we do;
1537 *
1538 * See nvfragprog.h for definitions
1539 *
1540 * \param inst - The parsed tokens
1541 * \param binding - The name of the state we are binding too
1542 * \param binding_idx - The index into the result register file that this is bound too
1543 *
1544 * See nvfragparse.c for the register file layout for fragment programs
1545 * See nvvertparse.c for the register file layout for vertex programs
1546 */
1547static GLuint
1548parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
1549 GLuint * binding_idx, struct arb_program *Program)
1550{
1551 GLuint b;
1552
1553 switch (*(*inst)++) {
1554 case FRAGMENT_RESULT_COLOR:
1555 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
1556 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1557 *binding = FRAG_OUTPUT_COLR;
1558 *binding_idx = 0;
1559 }
1560 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1561 else {
1562 *binding_idx = 0;
1563 }
1564 break;
1565
1566 case FRAGMENT_RESULT_DEPTH:
1567 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
1568 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1569 *binding = FRAG_OUTPUT_DEPR;
1570 *binding_idx = 2;
1571 }
1572 /* for vtx programs, this is VERTEX_RESULT_COLOR */
1573 else {
1574 GLint color_type;
1575 GLuint face_type = parse_face_type(inst);
1576 GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
1577
1578 /* back face */
1579 if (face_type) {
1580 if (color_type_ret) return 1;
1581
1582 /* secondary color */
1583 if (color_type) {
1584 *binding_idx = 4;
1585 }
1586 /* primary color */
1587 else {
1588 *binding_idx = 3;
1589 }
1590 }
1591 /* front face */
1592 else {
1593 /* secondary color */
1594 if (color_type) {
1595 *binding_idx = 2;
1596 }
1597 /* primary color */
1598 else {
1599 *binding_idx = 1;
1600 }
1601 }
1602 }
1603 break;
1604
1605 case VERTEX_RESULT_FOGCOORD:
1606 *binding_idx = 5;
1607 break;
1608
1609 case VERTEX_RESULT_POINTSIZE:
1610 *binding_idx = 6;
1611 break;
1612
1613 case VERTEX_RESULT_TEXCOORD:
1614 if (parse_texcoord_num (ctx, inst, Program, &b))
1615 return 1;
1616 *binding_idx = 7 + b;
1617 break;
1618 }
1619
1620 Program->OutputsWritten |= (1 << *binding_idx);
1621
1622 return 0;
1623}
1624
1625/**
1626 * This handles the declaration of ATTRIB variables
1627 *
1628 * XXX: Still needs
1629 * parse_vert_attrib_binding(), or something like that
1630 *
1631 * \return 0 on sucess, 1 on error
1632 */
1633static GLint
1634parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1635 struct arb_program *Program)
1636{
1637 GLuint found;
1638 char *error_msg;
1639 struct var_cache *attrib_var;
1640
1641 attrib_var = parse_string (inst, vc_head, Program, &found);
1642 Program->Position = parse_position (inst);
1643 if (found) {
1644 error_msg = (char *)
1645 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1646 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1647 attrib_var->name);
1648
1649 _mesa_set_program_error (ctx, Program->Position, error_msg);
1650 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1651
1652 _mesa_free (error_msg);
1653 return 1;
1654 }
1655
1656 attrib_var->type = vt_attrib;
1657
1658 /* I think this is ok now - karl */
1659 /* XXX: */
1660 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
1661 {
1662 if (parse_attrib_binding
1663 (ctx, inst, Program, &attrib_var->attrib_binding,
1664 &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
1665 return 1;
1666 if (generic_attrib_check(*vc_head)) {
1667 _mesa_set_program_error (ctx, Program->Position,
1668 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1669 _mesa_error (ctx, GL_INVALID_OPERATION,
1670 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1671 return 1;
1672 }
1673
1674 }
1675
1676 Program->Base.NumAttributes++;
1677 return 0;
1678}
1679
1680/**
1681 * \param use -- TRUE if we're called when declaring implicit parameters,
1682 * FALSE if we're declaraing variables. This has to do with
1683 * if we get a signed or unsigned float for scalar constants
1684 */
1685static GLuint
1686parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1687 struct var_cache *param_var,
1688 struct arb_program *Program, GLboolean use)
1689{
1690 GLint idx;
1691 GLuint err;
1692 GLint state_tokens[6];
1693 GLfloat const_values[4];
1694
1695 err = 0;
1696
1697 switch (*(*inst)++) {
1698 case PARAM_STATE_ELEMENT:
1699
1700 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1701 return 1;
1702
1703 /* If we adding STATE_MATRIX that has multiple rows, we need to
1704 * unroll it and call _mesa_add_state_reference() for each row
1705 */
1706 if ((state_tokens[0] == STATE_MATRIX)
1707 && (state_tokens[3] != state_tokens[4])) {
1708 GLint row;
1709 GLint first_row = state_tokens[3];
1710 GLint last_row = state_tokens[4];
1711
1712 for (row = first_row; row <= last_row; row++) {
1713 state_tokens[3] = state_tokens[4] = row;
1714
1715 idx =
1716 _mesa_add_state_reference (Program->Parameters,
1717 state_tokens);
1718 if (param_var->param_binding_begin == ~0U)
1719 param_var->param_binding_begin = idx;
1720 param_var->param_binding_length++;
1721 Program->Base.NumParameters++;
1722 }
1723 }
1724 else {
1725 idx =
1726 _mesa_add_state_reference (Program->Parameters, state_tokens);
1727 if (param_var->param_binding_begin == ~0U)
1728 param_var->param_binding_begin = idx;
1729 param_var->param_binding_length++;
1730 Program->Base.NumParameters++;
1731 }
1732 break;
1733
1734 case PARAM_PROGRAM_ELEMENT:
1735
1736 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1737 return 1;
1738 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1739 if (param_var->param_binding_begin == ~0U)
1740 param_var->param_binding_begin = idx;
1741 param_var->param_binding_length++;
1742 Program->Base.NumParameters++;
1743
1744 /* Check if there is more: 0 -> we're done, else its an integer */
1745 if (**inst) {
1746 GLuint out_of_range, new_idx;
1747 GLuint start_idx = state_tokens[2] + 1;
1748 GLuint end_idx = parse_integer (inst, Program);
1749
1750 out_of_range = 0;
1751 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1752 if (((state_tokens[1] == STATE_ENV)
1753 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
1754 || ((state_tokens[1] == STATE_LOCAL)
1755 && (end_idx >=
1756 ctx->Const.MaxFragmentProgramLocalParams)))
1757 out_of_range = 1;
1758 }
1759 else {
1760 if (((state_tokens[1] == STATE_ENV)
1761 && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
1762 || ((state_tokens[1] == STATE_LOCAL)
1763 && (end_idx >=
1764 ctx->Const.MaxVertexProgramLocalParams)))
1765 out_of_range = 1;
1766 }
1767 if (out_of_range) {
1768 _mesa_set_program_error (ctx, Program->Position,
1769 "Invalid Program Parameter");
1770 _mesa_error (ctx, GL_INVALID_OPERATION,
1771 "Invalid Program Parameter: %d", end_idx);
1772 return 1;
1773 }
1774
1775 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1776 state_tokens[2] = new_idx;
1777 idx =
1778 _mesa_add_state_reference (Program->Parameters,
1779 state_tokens);
1780 param_var->param_binding_length++;
1781 Program->Base.NumParameters++;
1782 }
1783 }
1784 else
1785 {
1786 (*inst)++;
1787 }
1788 break;
1789
1790 case PARAM_CONSTANT:
1791 parse_constant (inst, const_values, Program, use);
1792 idx =
1793 _mesa_add_named_constant (Program->Parameters,
1794 (char *) param_var->name, const_values);
1795 if (param_var->param_binding_begin == ~0U)
1796 param_var->param_binding_begin = idx;
1797 param_var->param_binding_length++;
1798 Program->Base.NumParameters++;
1799 break;
1800
1801 default:
1802 _mesa_set_program_error (ctx, Program->Position,
1803 "Unexpected token in parse_param_elements()");
1804 _mesa_error (ctx, GL_INVALID_OPERATION,
1805 "Unexpected token in parse_param_elements()");
1806 return 1;
1807 }
1808
1809 /* Make sure we haven't blown past our parameter limits */
1810 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1811 (Program->Base.NumParameters >=
1812 ctx->Const.MaxVertexProgramLocalParams))
1813 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1814 && (Program->Base.NumParameters >=
1815 ctx->Const.MaxFragmentProgramLocalParams))) {
1816 _mesa_set_program_error (ctx, Program->Position,
1817 "Too many parameter variables");
1818 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1819 return 1;
1820 }
1821
1822 return err;
1823}
1824
1825/**
1826 * This picks out PARAM program parameter bindings.
1827 *
1828 * XXX: This needs to be stressed & tested
1829 *
1830 * \return 0 on sucess, 1 on error
1831 */
1832static GLuint
1833parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1834 struct arb_program *Program)
1835{
1836 GLuint found, specified_length, err;
1837 char *error_msg;
1838 struct var_cache *param_var;
1839
1840 err = 0;
1841 param_var = parse_string (inst, vc_head, Program, &found);
1842 Program->Position = parse_position (inst);
1843
1844 if (found) {
1845 error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
1846 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1847 param_var->name);
1848
1849 _mesa_set_program_error (ctx, Program->Position, error_msg);
1850 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1851
1852 _mesa_free (error_msg);
1853 return 1;
1854 }
1855
1856 specified_length = parse_integer (inst, Program);
1857
1858 if (specified_length < 0) {
1859 _mesa_set_program_error (ctx, Program->Position,
1860 "Negative parameter array length");
1861 _mesa_error (ctx, GL_INVALID_OPERATION,
1862 "Negative parameter array length: %d", specified_length);
1863 return 1;
1864 }
1865
1866 param_var->type = vt_param;
1867 param_var->param_binding_length = 0;
1868
1869 /* Right now, everything is shoved into the main state register file.
1870 *
1871 * In the future, it would be nice to leave things ENV/LOCAL params
1872 * in their respective register files, if possible
1873 */
1874 param_var->param_binding_type = PROGRAM_STATE_VAR;
1875
1876 /* Remember to:
1877 * * - add each guy to the parameter list
1878 * * - increment the param_var->param_binding_len
1879 * * - store the param_var->param_binding_begin for the first one
1880 * * - compare the actual len to the specified len at the end
1881 */
1882 while (**inst != PARAM_NULL) {
1883 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1884 return 1;
1885 }
1886
1887 /* Test array length here! */
1888 if (specified_length) {
1889 if (specified_length != param_var->param_binding_length) {
1890 _mesa_set_program_error (ctx, Program->Position,
1891 "Declared parameter array lenght does not match parameter list");
1892 _mesa_error (ctx, GL_INVALID_OPERATION,
1893 "Declared parameter array lenght does not match parameter list");
1894 }
1895 }
1896
1897 (*inst)++;
1898
1899 return 0;
1900}
1901
1902/**
1903 *
1904 */
1905static GLuint
1906parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1907 struct arb_program *Program, struct var_cache **new_var)
1908{
1909 struct var_cache *param_var;
1910
1911 /* First, insert a dummy entry into the var_cache */
1912 var_cache_create (&param_var);
1913 param_var->name = (GLubyte *) _mesa_strdup (" ");
1914 param_var->type = vt_param;
1915
1916 param_var->param_binding_length = 0;
1917 /* Don't fill in binding_begin; We use the default value of -1
1918 * to tell if its already initialized, elsewhere.
1919 *
1920 * param_var->param_binding_begin = 0;
1921 */
1922 param_var->param_binding_type = PROGRAM_STATE_VAR;
1923
1924 var_cache_append (vc_head, param_var);
1925
1926 /* Then fill it with juicy parameter goodness */
1927 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1928 return 1;
1929
1930 *new_var = param_var;
1931
1932 return 0;
1933}
1934
1935
1936/**
1937 * This handles the declaration of TEMP variables
1938 *
1939 * \return 0 on sucess, 1 on error
1940 */
1941static GLuint
1942parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1943 struct arb_program *Program)
1944{
1945 GLuint found;
1946 struct var_cache *temp_var;
1947 char *error_msg;
1948
1949 while (**inst != 0) {
1950 temp_var = parse_string (inst, vc_head, Program, &found);
1951 Program->Position = parse_position (inst);
1952 if (found) {
1953 error_msg = (char *)
1954 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1955 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1956 temp_var->name);
1957
1958 _mesa_set_program_error (ctx, Program->Position, error_msg);
1959 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1960
1961 _mesa_free (error_msg);
1962 return 1;
1963 }
1964
1965 temp_var->type = vt_temp;
1966
1967 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1968 (Program->Base.NumTemporaries >=
1969 ctx->Const.MaxFragmentProgramTemps))
1970 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1971 && (Program->Base.NumTemporaries >=
1972 ctx->Const.MaxVertexProgramTemps))) {
1973 _mesa_set_program_error (ctx, Program->Position,
1974 "Too many TEMP variables declared");
1975 _mesa_error (ctx, GL_INVALID_OPERATION,
1976 "Too many TEMP variables declared");
1977 return 1;
1978 }
1979
1980 temp_var->temp_binding = Program->Base.NumTemporaries;
1981 Program->Base.NumTemporaries++;
1982 }
1983 (*inst)++;
1984
1985 return 0;
1986}
1987
1988/**
1989 * This handles variables of the OUTPUT variety
1990 *
1991 * \return 0 on sucess, 1 on error
1992 */
1993static GLuint
1994parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1995 struct arb_program *Program)
1996{
1997 GLuint found;
1998 struct var_cache *output_var;
1999
2000 output_var = parse_string (inst, vc_head, Program, &found);
2001 Program->Position = parse_position (inst);
2002 if (found) {
2003 char *error_msg;
2004 error_msg = (char *)
2005 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
2006 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2007 output_var->name);
2008
2009 _mesa_set_program_error (ctx, Program->Position, error_msg);
2010 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2011
2012 _mesa_free (error_msg);
2013 return 1;
2014 }
2015
2016 output_var->type = vt_output;
2017 return parse_result_binding (ctx, inst, &output_var->output_binding,
2018 &output_var->output_binding_idx, Program);
2019}
2020
2021/**
2022 * This handles variables of the ALIAS kind
2023 *
2024 * \return 0 on sucess, 1 on error
2025 */
2026static GLuint
2027parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2028 struct arb_program *Program)
2029{
2030 GLuint found;
2031 struct var_cache *temp_var;
2032 char *error_msg;
2033
2034
2035 temp_var = parse_string (inst, vc_head, Program, &found);
2036 Program->Position = parse_position (inst);
2037
2038 if (found) {
2039 error_msg = (char *)
2040 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2041 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2042 temp_var->name);
2043
2044 _mesa_set_program_error (ctx, Program->Position, error_msg);
2045 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2046
2047 _mesa_free (error_msg);
2048 return 1;
2049 }
2050
2051 temp_var->type = vt_alias;
2052 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2053 Program->Position = parse_position (inst);
2054
2055 if (!found)
2056 {
2057 error_msg = (char *)
2058 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2059 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2060 temp_var->alias_binding->name);
2061
2062 _mesa_set_program_error (ctx, Program->Position, error_msg);
2063 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2064
2065 _mesa_free (error_msg);
2066 return 1;
2067 }
2068
2069 return 0;
2070}
2071
2072/**
2073 * This handles variables of the ADDRESS kind
2074 *
2075 * \return 0 on sucess, 1 on error
2076 */
2077static GLuint
2078parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2079 struct arb_program *Program)
2080{
2081 GLuint found;
2082 struct var_cache *temp_var;
2083 char *error_msg;
2084
2085 while (**inst != 0) {
2086 temp_var = parse_string (inst, vc_head, Program, &found);
2087 Program->Position = parse_position (inst);
2088 if (found) {
2089 error_msg = (char *)
2090 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2091 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2092 temp_var->name);
2093
2094 _mesa_set_program_error (ctx, Program->Position, error_msg);
2095 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2096
2097 _mesa_free (error_msg);
2098 return 1;
2099 }
2100
2101 temp_var->type = vt_address;
2102
2103 if (Program->Base.NumAddressRegs >=
2104 ctx->Const.MaxVertexProgramAddressRegs) {
2105 _mesa_set_program_error (ctx, Program->Position,
2106 "Too many ADDRESS variables declared");
2107 _mesa_error (ctx, GL_INVALID_OPERATION,
2108 "Too many ADDRESS variables declared");
2109 return 1;
2110 }
2111
2112 temp_var->address_binding = Program->Base.NumAddressRegs;
2113 Program->Base.NumAddressRegs++;
2114 }
2115 (*inst)++;
2116
2117 return 0;
2118}
2119
2120/**
2121 * Parse a program declaration
2122 *
2123 * \return 0 on sucess, 1 on error
2124 */
2125static GLint
2126parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2127 struct arb_program *Program)
2128{
2129 GLint err = 0;
2130
2131 switch (*(*inst)++) {
2132 case ADDRESS:
2133 err = parse_address (ctx, inst, vc_head, Program);
2134 break;
2135
2136 case ALIAS:
2137 err = parse_alias (ctx, inst, vc_head, Program);
2138 break;
2139
2140 case ATTRIB:
2141 err = parse_attrib (ctx, inst, vc_head, Program);
2142 break;
2143
2144 case OUTPUT:
2145 err = parse_output (ctx, inst, vc_head, Program);
2146 break;
2147
2148 case PARAM:
2149 err = parse_param (ctx, inst, vc_head, Program);
2150 break;
2151
2152 case TEMP:
2153 err = parse_temp (ctx, inst, vc_head, Program);
2154 break;
2155 }
2156
2157 return err;
2158}
2159
2160/**
2161 * Handle the parsing out of a masked destination register
2162 *
2163 * If we are a vertex program, make sure we don't write to
2164 * result.position of we have specified that the program is
2165 * position invariant
2166 *
2167 * \param File - The register file we write to
2168 * \param Index - The register index we write to
2169 * \param WriteMask - The mask controlling which components we write (1->write)
2170 *
2171 * \return 0 on sucess, 1 on error
2172 */
2173static GLuint
2174parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2175 struct var_cache **vc_head, struct arb_program *Program,
2176 GLint * File, GLint * Index, GLboolean * WriteMask)
2177{
2178 GLuint result;
2179 GLubyte mask;
2180 struct var_cache *dst;
2181
2182 /* We either have a result register specified, or a
2183 * variable that may or may not be writable
2184 */
2185 switch (*(*inst)++) {
2186 case REGISTER_RESULT:
2187 if (parse_result_binding
2188 (ctx, inst, &result, (GLuint *) Index, Program))
2189 return 1;
2190 *File = PROGRAM_OUTPUT;
2191 break;
2192
2193 case REGISTER_ESTABLISHED_NAME:
2194 dst = parse_string (inst, vc_head, Program, &result);
2195 Program->Position = parse_position (inst);
2196
2197 /* If the name has never been added to our symbol table, we're hosed */
2198 if (!result) {
2199 _mesa_set_program_error (ctx, Program->Position,
2200 "0: Undefined variable");
2201 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2202 dst->name);
2203 return 1;
2204 }
2205
2206 switch (dst->type) {
2207 case vt_output:
2208 *File = PROGRAM_OUTPUT;
2209 *Index = dst->output_binding_idx;
2210 break;
2211
2212 case vt_temp:
2213 *File = PROGRAM_TEMPORARY;
2214 *Index = dst->temp_binding;
2215 break;
2216
2217 /* If the var type is not vt_output or vt_temp, no go */
2218 default:
2219 _mesa_set_program_error (ctx, Program->Position,
2220 "Destination register is read only");
2221 _mesa_error (ctx, GL_INVALID_OPERATION,
2222 "Destination register is read only: %s",
2223 dst->name);
2224 return 1;
2225 }
2226 break;
2227
2228 default:
2229 _mesa_set_program_error (ctx, Program->Position,
2230 "Unexpected opcode in parse_masked_dst_reg()");
2231 _mesa_error (ctx, GL_INVALID_OPERATION,
2232 "Unexpected opcode in parse_masked_dst_reg()");
2233 return 1;
2234 }
2235
2236
2237 /* Position invariance test */
2238 /* This test is done now in syntax portion - when position invariance OPTION
2239 is specified, "result.position" rule is disabled so there is no way
2240 to write the position
2241 */
2242 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2243 (*Index == 0)) {
2244 _mesa_set_program_error (ctx, Program->Position,
2245 "Vertex program specified position invariance and wrote vertex position");
2246 _mesa_error (ctx, GL_INVALID_OPERATION,
2247 "Vertex program specified position invariance and wrote vertex position");
2248 }*/
2249
2250 /* And then the mask.
2251 * w,a -> bit 0
2252 * z,b -> bit 1
2253 * y,g -> bit 2
2254 * x,r -> bit 3
2255 */
2256 mask = *(*inst)++;
2257
2258 WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3;
2259 WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2;
2260 WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1;
2261 WriteMask[3] = (GLboolean) (mask & (1));
2262
2263 return 0;
2264}
2265
2266
2267/**
2268 * Handle the parsing of a address register
2269 *
2270 * \param Index - The register index we write to
2271 *
2272 * \return 0 on sucess, 1 on error
2273 */
2274static GLuint
2275parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2276 struct var_cache **vc_head,
2277 struct arb_program *Program, GLint * Index)
2278{
2279 struct var_cache *dst;
2280 GLuint result;
2281
2282 dst = parse_string (inst, vc_head, Program, &result);
2283 Program->Position = parse_position (inst);
2284
2285 /* If the name has never been added to our symbol table, we're hosed */
2286 if (!result) {
2287 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2288 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2289 dst->name);
2290 return 1;
2291 }
2292
2293 if (dst->type != vt_address) {
2294 _mesa_set_program_error (ctx, Program->Position,
2295 "Variable is not of type ADDRESS");
2296 _mesa_error (ctx, GL_INVALID_OPERATION,
2297 "Variable: %s is not of type ADDRESS", dst->name);
2298 return 1;
2299 }
2300
2301 return 0;
2302}
2303
2304/**
2305 * Handle the parsing out of a masked address register
2306 *
2307 * \param Index - The register index we write to
2308 * \param WriteMask - The mask controlling which components we write (1->write)
2309 *
2310 * \return 0 on sucess, 1 on error
2311 */
2312static GLuint
2313parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2314 struct var_cache **vc_head,
2315 struct arb_program *Program, GLint * Index,
2316 GLboolean * WriteMask)
2317{
2318 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2319 return 1;
2320
2321 /* This should be 0x8 */
2322 (*inst)++;
2323
2324 /* Writemask of .x is implied */
2325 WriteMask[0] = 1;
2326 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2327
2328 return 0;
2329}
2330
2331
2332/**
2333 * Parse out a swizzle mask.
2334 *
2335 * The values in the input stream are:
2336 * COMPONENT_X -> x/r
2337 * COMPONENT_Y -> y/g
2338 * COMPONENT_Z-> z/b
2339 * COMPONENT_W-> w/a
2340 *
2341 * The values in the output mask are:
2342 * 0 -> x/r
2343 * 1 -> y/g
2344 * 2 -> z/b
2345 * 3 -> w/a
2346 *
2347 * The len parameter allows us to grab 4 components for a vector
2348 * swizzle, or just 1 component for a scalar src register selection
2349 */
2350static GLuint
2351parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)
2352{
2353 GLint a;
2354
2355 for (a = 0; a < 4; a++)
2356 mask[a] = a;
2357
2358 for (a = 0; a < len; a++) {
2359 switch (*(*inst)++) {
2360 case COMPONENT_X:
2361 mask[a] = 0;
2362 break;
2363
2364 case COMPONENT_Y:
2365 mask[a] = 1;
2366 break;
2367
2368 case COMPONENT_Z:
2369 mask[a] = 2;
2370 break;
2371
2372 case COMPONENT_W:
2373 mask[a] = 3;
2374 break;
2375 }
2376 }
2377
2378 return 0;
2379}
2380
2381/**
2382 */
2383static GLuint
2384parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)
2385{
2386 GLint a;
2387 GLubyte swz;
2388
2389 *Negate = GL_FALSE;
2390 for (a = 0; a < 4; a++) {
Brian Paul05908952004-06-08 15:20:23 +00002391 if (parse_sign (inst) == -1)
Jouk Jansen40322e12004-04-05 08:50:36 +00002392 *Negate = GL_TRUE;
2393
2394 swz = *(*inst)++;
2395
2396 switch (swz) {
2397 case COMPONENT_0:
2398 mask[a] = SWIZZLE_ZERO;
2399 break;
2400 case COMPONENT_1:
2401 mask[a] = SWIZZLE_ONE;
2402 break;
2403 case COMPONENT_X:
2404 mask[a] = SWIZZLE_X;
2405 break;
2406 case COMPONENT_Y:
2407 mask[a] = SWIZZLE_Y;
2408 break;
2409 case COMPONENT_Z:
2410 mask[a] = SWIZZLE_Z;
2411 break;
2412 case COMPONENT_W:
2413 mask[a] = SWIZZLE_W;
2414 break;
2415
2416 }
2417#if 0
2418 if (swz == 0)
2419 mask[a] = SWIZZLE_ZERO;
2420 else if (swz == 1)
2421 mask[a] = SWIZZLE_ONE;
2422 else
2423 mask[a] = swz - 2;
2424#endif
2425
2426 }
2427
2428 return 0;
2429}
2430
2431
2432static GLuint
2433parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2434 struct arb_program *Program, GLint * File, GLint * Index,
2435 GLboolean *IsRelOffset )
2436{
2437 struct var_cache *src;
2438 GLuint binding_state, binding_idx, is_generic, found, offset;
2439
2440 /* And the binding for the src */
2441 switch (*(*inst)++) {
2442 case REGISTER_ATTRIB:
2443 if (parse_attrib_binding
2444 (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
2445 return 1;
2446 *File = PROGRAM_INPUT;
2447 *Index = binding_idx;
2448
2449 /* We need to insert a dummy variable into the var_cache so we can
2450 * catch generic vertex attrib aliasing errors
2451 */
2452 var_cache_create(&src);
2453 src->type = vt_attrib;
2454 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
2455 src->attrib_binding = binding_state;
2456 src->attrib_binding_idx = binding_idx;
2457 src->attrib_is_generic = is_generic;
2458 var_cache_append(vc_head, src);
2459 if (generic_attrib_check(*vc_head)) {
2460 _mesa_set_program_error (ctx, Program->Position,
2461 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2462 _mesa_error (ctx, GL_INVALID_OPERATION,
2463 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2464 return 1;
2465 }
2466 break;
2467
2468 case REGISTER_PARAM:
2469 switch (**inst) {
2470 case PARAM_ARRAY_ELEMENT:
2471 (*inst)++;
2472 src = parse_string (inst, vc_head, Program, &found);
2473 Program->Position = parse_position (inst);
2474
2475 if (!found) {
2476 _mesa_set_program_error (ctx, Program->Position,
2477 "2: Undefined variable");
2478 _mesa_error (ctx, GL_INVALID_OPERATION,
2479 "2: Undefined variable: %s", src->name);
2480 return 1;
2481 }
2482
2483 *File = src->param_binding_type;
2484
2485 switch (*(*inst)++) {
2486 case ARRAY_INDEX_ABSOLUTE:
2487 offset = parse_integer (inst, Program);
2488
2489 if ((offset < 0)
2490 || (offset >= src->param_binding_length)) {
2491 _mesa_set_program_error (ctx, Program->Position,
2492 "Index out of range");
2493 _mesa_error (ctx, GL_INVALID_OPERATION,
2494 "Index %d out of range for %s", offset,
2495 src->name);
2496 return 1;
2497 }
2498
2499 *Index = src->param_binding_begin + offset;
2500 break;
2501
2502 case ARRAY_INDEX_RELATIVE:
2503 {
2504 GLint addr_reg_idx, rel_off;
2505
2506 /* First, grab the address regiseter */
2507 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2508 return 1;
2509
2510 /* And the .x */
2511 ((*inst)++);
2512 ((*inst)++);
2513 ((*inst)++);
2514 ((*inst)++);
2515
2516 /* Then the relative offset */
2517 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2518
2519 /* And store it properly */
2520 *Index = src->param_binding_begin + rel_off;
2521 *IsRelOffset = 1;
2522 }
2523 break;
2524 }
2525 break;
2526
2527 default:
2528
2529 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2530 return 1;
2531
2532 *File = src->param_binding_type;
2533 *Index = src->param_binding_begin;
2534 break;
2535 }
2536 break;
2537
2538 case REGISTER_ESTABLISHED_NAME:
2539
2540 src = parse_string (inst, vc_head, Program, &found);
2541 Program->Position = parse_position (inst);
2542
2543 /* If the name has never been added to our symbol table, we're hosed */
2544 if (!found) {
2545 _mesa_set_program_error (ctx, Program->Position,
2546 "3: Undefined variable");
2547 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2548 src->name);
2549 return 1;
2550 }
2551
2552 switch (src->type) {
2553 case vt_attrib:
2554 *File = PROGRAM_INPUT;
2555 *Index = src->attrib_binding_idx;
2556 break;
2557
2558 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2559 case vt_param:
2560 *File = src->param_binding_type;
2561 *Index = src->param_binding_begin;
2562 break;
2563
2564 case vt_temp:
2565 *File = PROGRAM_TEMPORARY;
2566 *Index = src->temp_binding;
2567 break;
2568
2569 /* If the var type is vt_output no go */
2570 default:
2571 _mesa_set_program_error (ctx, Program->Position,
2572 "destination register is read only");
2573 _mesa_error (ctx, GL_INVALID_OPERATION,
2574 "destination register is read only: %s",
2575 src->name);
2576 return 1;
2577 }
2578 break;
2579
2580 default:
2581 _mesa_set_program_error (ctx, Program->Position,
2582 "Unknown token in parse_src_reg");
2583 _mesa_error (ctx, GL_INVALID_OPERATION,
2584 "Unknown token in parse_src_reg");
2585 return 1;
2586 }
2587
2588 return 0;
2589}
2590
2591/**
2592 */
2593static GLuint
2594parse_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
2595 struct var_cache **vc_head, struct arb_program *Program,
2596 GLint * File, GLint * Index, GLboolean * Negate,
2597 GLubyte * Swizzle, GLboolean *IsRelOffset)
2598{
2599 /* Grab the sign */
Brian Paul05908952004-06-08 15:20:23 +00002600 *Negate = (parse_sign (inst) == -1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002601
2602 /* And the src reg */
2603 if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))
2604 return 1;
2605
2606 /* finally, the swizzle */
2607 parse_swizzle_mask (inst, Swizzle, 4);
2608
2609 return 0;
2610}
2611
2612/**
2613 */
2614static GLuint
2615parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
2616 struct var_cache **vc_head, struct arb_program *Program,
2617 GLint * File, GLint * Index, GLboolean * Negate,
2618 GLubyte * Swizzle, GLboolean *IsRelOffset)
2619{
2620 /* Grab the sign */
Brian Paul05908952004-06-08 15:20:23 +00002621 *Negate = (parse_sign (inst) == -1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002622
2623 /* And the src reg */
2624 if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))
2625 return 1;
2626
2627 /* Now, get the component and shove it into all the swizzle slots */
2628 parse_swizzle_mask (inst, Swizzle, 1);
2629
2630 return 0;
2631}
2632
2633/**
2634 * This is a big mother that handles getting opcodes into the instruction
2635 * and handling the src & dst registers for fragment program instructions
2636 */
2637static GLuint
2638parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2639 struct var_cache **vc_head, struct arb_program *Program,
2640 struct fp_instruction *fp)
2641{
2642 GLint a, b;
2643 GLubyte swz[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
2644 GLuint texcoord;
2645 GLubyte instClass, type, code;
2646 GLboolean rel;
2647
2648 /* No condition codes in ARB_fp */
2649 fp->UpdateCondRegister = 0;
2650
2651 /* Record the position in the program string for debugging */
2652 fp->StringPos = Program->Position;
2653
2654 /* OP_ALU_INST or OP_TEX_INST */
2655 instClass = *(*inst)++;
2656
2657 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2658 * OP_TEX_{SAMPLE, KIL}
2659 */
2660 type = *(*inst)++;
2661
2662 /* The actual opcode name */
2663 code = *(*inst)++;
2664
2665 /* Increment the correct count */
2666 switch (instClass) {
2667 case OP_ALU_INST:
2668 Program->NumAluInstructions++;
2669 break;
2670 case OP_TEX_INST:
2671 Program->NumTexInstructions++;
2672 break;
2673 }
2674
2675 fp->Saturate = 0;
2676 fp->Precision = FLOAT32;
2677
2678 fp->DstReg.CondMask = COND_TR;
2679
2680 switch (type) {
2681 case OP_ALU_VECTOR:
2682 switch (code) {
2683 case OP_ABS_SAT:
2684 fp->Saturate = 1;
2685 case OP_ABS:
2686 fp->Opcode = FP_OPCODE_ABS;
2687 break;
2688
2689 case OP_FLR_SAT:
2690 fp->Saturate = 1;
2691 case OP_FLR:
2692 fp->Opcode = FP_OPCODE_FLR;
2693 break;
2694
2695 case OP_FRC_SAT:
2696 fp->Saturate = 1;
2697 case OP_FRC:
2698 fp->Opcode = FP_OPCODE_FRC;
2699 break;
2700
2701 case OP_LIT_SAT:
2702 fp->Saturate = 1;
2703 case OP_LIT:
2704 fp->Opcode = FP_OPCODE_LIT;
2705 break;
2706
2707 case OP_MOV_SAT:
2708 fp->Saturate = 1;
2709 case OP_MOV:
2710 fp->Opcode = FP_OPCODE_MOV;
2711 break;
2712 }
2713
2714 if (parse_masked_dst_reg
2715 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2716 &fp->DstReg.Index, fp->DstReg.WriteMask))
2717 return 1;
2718
2719 fp->SrcReg[0].Abs = GL_FALSE;
2720 fp->SrcReg[0].NegateAbs = GL_FALSE;
2721 if (parse_vector_src_reg
2722 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
2723 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
2724 swz, &rel))
2725 return 1;
2726 for (b=0; b<4; b++)
2727 fp->SrcReg[0].Swizzle[b] = swz[b];
2728 break;
2729
2730 case OP_ALU_SCALAR:
2731 switch (code) {
2732 case OP_COS_SAT:
2733 fp->Saturate = 1;
2734 case OP_COS:
2735 fp->Opcode = FP_OPCODE_COS;
2736 break;
2737
2738 case OP_EX2_SAT:
2739 fp->Saturate = 1;
2740 case OP_EX2:
2741 fp->Opcode = FP_OPCODE_EX2;
2742 break;
2743
2744 case OP_LG2_SAT:
2745 fp->Saturate = 1;
2746 case OP_LG2:
2747 fp->Opcode = FP_OPCODE_LG2;
2748 break;
2749
2750 case OP_RCP_SAT:
2751 fp->Saturate = 1;
2752 case OP_RCP:
2753 fp->Opcode = FP_OPCODE_RCP;
2754 break;
2755
2756 case OP_RSQ_SAT:
2757 fp->Saturate = 1;
2758 case OP_RSQ:
2759 fp->Opcode = FP_OPCODE_RSQ;
2760 break;
2761
2762 case OP_SIN_SAT:
2763 fp->Saturate = 1;
2764 case OP_SIN:
2765 fp->Opcode = FP_OPCODE_SIN;
2766 break;
2767
2768 case OP_SCS_SAT:
2769 fp->Saturate = 1;
2770 case OP_SCS:
2771
2772 fp->Opcode = FP_OPCODE_SCS;
2773 break;
2774 }
2775
2776 if (parse_masked_dst_reg
2777 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2778 &fp->DstReg.Index, fp->DstReg.WriteMask))
2779 return 1;
2780 fp->SrcReg[0].Abs = GL_FALSE;
2781 fp->SrcReg[0].NegateAbs = GL_FALSE;
2782 if (parse_scalar_src_reg
2783 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
2784 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
2785 swz, &rel))
2786 return 1;
2787 for (b=0; b<4; b++)
2788 fp->SrcReg[0].Swizzle[b] = swz[b];
2789 break;
2790
2791 case OP_ALU_BINSC:
2792 switch (code) {
2793 case OP_POW_SAT:
2794 fp->Saturate = 1;
2795 case OP_POW:
2796 fp->Opcode = FP_OPCODE_POW;
2797 break;
2798 }
2799
2800 if (parse_masked_dst_reg
2801 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2802 &fp->DstReg.Index, fp->DstReg.WriteMask))
2803 return 1;
2804 for (a = 0; a < 2; a++) {
2805 fp->SrcReg[a].Abs = GL_FALSE;
2806 fp->SrcReg[a].NegateAbs = GL_FALSE;
2807 if (parse_scalar_src_reg
2808 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
2809 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
2810 swz, &rel))
2811 return 1;
2812 for (b=0; b<4; b++)
2813 fp->SrcReg[a].Swizzle[b] = swz[b];
2814 }
2815 break;
2816
2817
2818 case OP_ALU_BIN:
2819 switch (code) {
2820 case OP_ADD_SAT:
2821 fp->Saturate = 1;
2822 case OP_ADD:
2823 fp->Opcode = FP_OPCODE_ADD;
2824 break;
2825
2826 case OP_DP3_SAT:
2827 fp->Saturate = 1;
2828 case OP_DP3:
2829 fp->Opcode = FP_OPCODE_DP3;
2830 break;
2831
2832 case OP_DP4_SAT:
2833 fp->Saturate = 1;
2834 case OP_DP4:
2835 fp->Opcode = FP_OPCODE_DP4;
2836 break;
2837
2838 case OP_DPH_SAT:
2839 fp->Saturate = 1;
2840 case OP_DPH:
2841 fp->Opcode = FP_OPCODE_DPH;
2842 break;
2843
2844 case OP_DST_SAT:
2845 fp->Saturate = 1;
2846 case OP_DST:
2847 fp->Opcode = FP_OPCODE_DST;
2848 break;
2849
2850 case OP_MAX_SAT:
2851 fp->Saturate = 1;
2852 case OP_MAX:
2853 fp->Opcode = FP_OPCODE_MAX;
2854 break;
2855
2856 case OP_MIN_SAT:
2857 fp->Saturate = 1;
2858 case OP_MIN:
2859 fp->Opcode = FP_OPCODE_MIN;
2860 break;
2861
2862 case OP_MUL_SAT:
2863 fp->Saturate = 1;
2864 case OP_MUL:
2865 fp->Opcode = FP_OPCODE_MUL;
2866 break;
2867
2868 case OP_SGE_SAT:
2869 fp->Saturate = 1;
2870 case OP_SGE:
2871 fp->Opcode = FP_OPCODE_SGE;
2872 break;
2873
2874 case OP_SLT_SAT:
2875 fp->Saturate = 1;
2876 case OP_SLT:
2877 fp->Opcode = FP_OPCODE_SLT;
2878 break;
2879
2880 case OP_SUB_SAT:
2881 fp->Saturate = 1;
2882 case OP_SUB:
2883 fp->Opcode = FP_OPCODE_SUB;
2884 break;
2885
2886 case OP_XPD_SAT:
2887 fp->Saturate = 1;
2888 case OP_XPD:
2889 fp->Opcode = FP_OPCODE_XPD;
2890 break;
2891 }
2892
2893 if (parse_masked_dst_reg
2894 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2895 &fp->DstReg.Index, fp->DstReg.WriteMask))
2896 return 1;
2897 for (a = 0; a < 2; a++) {
2898 fp->SrcReg[a].Abs = GL_FALSE;
2899 fp->SrcReg[a].NegateAbs = GL_FALSE;
2900 if (parse_vector_src_reg
2901 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
2902 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
2903 swz, &rel))
2904 return 1;
2905 for (b=0; b<4; b++)
2906 fp->SrcReg[a].Swizzle[b] = swz[b];
2907 }
2908 break;
2909
2910 case OP_ALU_TRI:
2911 switch (code) {
2912 case OP_CMP_SAT:
2913 fp->Saturate = 1;
2914 case OP_CMP:
2915 fp->Opcode = FP_OPCODE_CMP;
2916 break;
2917
2918 case OP_LRP_SAT:
2919 fp->Saturate = 1;
2920 case OP_LRP:
2921 fp->Opcode = FP_OPCODE_LRP;
2922 break;
2923
2924 case OP_MAD_SAT:
2925 fp->Saturate = 1;
2926 case OP_MAD:
2927 fp->Opcode = FP_OPCODE_MAD;
2928 break;
2929 }
2930
2931 if (parse_masked_dst_reg
2932 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2933 &fp->DstReg.Index, fp->DstReg.WriteMask))
2934 return 1;
2935 for (a = 0; a < 3; a++) {
2936 fp->SrcReg[a].Abs = GL_FALSE;
2937 fp->SrcReg[a].NegateAbs = GL_FALSE;
2938 if (parse_vector_src_reg
2939 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
2940 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
2941 swz, &rel))
2942 return 1;
2943 for (b=0; b<4; b++)
2944 fp->SrcReg[a].Swizzle[b] = swz[b];
2945 }
2946 break;
2947
2948 case OP_ALU_SWZ:
2949 switch (code) {
2950 case OP_SWZ_SAT:
2951 fp->Saturate = 1;
2952 case OP_SWZ:
2953 fp->Opcode = FP_OPCODE_SWZ;
2954 break;
2955 }
2956 if (parse_masked_dst_reg
2957 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2958 &fp->DstReg.Index, fp->DstReg.WriteMask))
2959 return 1;
2960
2961 if (parse_src_reg
2962 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
2963 &fp->SrcReg[0].Index, &rel))
2964 return 1;
2965 parse_extended_swizzle_mask (inst, swz,
2966 &fp->SrcReg[0].NegateBase);
2967 for (b=0; b<4; b++)
2968 fp->SrcReg[0].Swizzle[b] = swz[b];
2969 break;
2970
2971 case OP_TEX_SAMPLE:
2972 switch (code) {
2973 case OP_TEX_SAT:
2974 fp->Saturate = 1;
2975 case OP_TEX:
2976 fp->Opcode = FP_OPCODE_TEX;
2977 break;
2978
2979 case OP_TXP_SAT:
2980 fp->Saturate = 1;
2981 case OP_TXP:
2982 fp->Opcode = FP_OPCODE_TXP;
2983 break;
2984
2985 case OP_TXB_SAT:
2986
2987 fp->Saturate = 1;
2988 case OP_TXB:
2989 fp->Opcode = FP_OPCODE_TXB;
2990 break;
2991 }
2992
2993 if (parse_masked_dst_reg
2994 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
2995 &fp->DstReg.Index, fp->DstReg.WriteMask))
2996 return 1;
2997 fp->SrcReg[0].Abs = GL_FALSE;
2998 fp->SrcReg[0].NegateAbs = GL_FALSE;
2999 if (parse_vector_src_reg
3000 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
3001 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
3002 swz, &rel))
3003 return 1;
3004 for (b=0; b<4; b++)
3005 fp->SrcReg[0].Swizzle[b] = swz[b];
3006
3007 /* texImageUnit */
3008 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
3009 return 1;
3010 fp->TexSrcUnit = texcoord;
3011
3012 /* texTarget */
3013 switch (*(*inst)++) {
3014 case TEXTARGET_1D:
3015 fp->TexSrcBit = TEXTURE_1D_BIT;
3016 break;
3017 case TEXTARGET_2D:
3018 fp->TexSrcBit = TEXTURE_2D_BIT;
3019 break;
3020 case TEXTARGET_3D:
3021 fp->TexSrcBit = TEXTURE_3D_BIT;
3022 break;
3023 case TEXTARGET_RECT:
3024 fp->TexSrcBit = TEXTURE_RECT_BIT;
3025 break;
3026 case TEXTARGET_CUBE:
3027 fp->TexSrcBit = TEXTURE_CUBE_BIT;
3028 break;
3029 case TEXTARGET_SHADOW1D:
3030 case TEXTARGET_SHADOW2D:
3031 case TEXTARGET_SHADOWRECT:
3032 /* TODO ARB_fragment_program_shadow code */
3033 break;
3034 }
3035 Program->TexturesUsed[texcoord] |= fp->TexSrcBit;
3036 break;
3037
3038 case OP_TEX_KIL:
3039 fp->Opcode = FP_OPCODE_KIL;
3040 fp->SrcReg[0].Abs = GL_FALSE;
3041 fp->SrcReg[0].NegateAbs = GL_FALSE;
3042 if (parse_vector_src_reg
3043 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
3044 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
3045 swz, &rel))
3046 return 1;
3047 for (b=0; b<4; b++)
3048 fp->SrcReg[0].Swizzle[b] = swz[b];
3049 break;
3050 }
3051
3052 return 0;
3053}
3054
3055/**
3056 * This is a big mother that handles getting opcodes into the instruction
3057 * and handling the src & dst registers for vertex program instructions
3058 */
3059static GLuint
3060parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3061 struct var_cache **vc_head, struct arb_program *Program,
3062 struct vp_instruction *vp)
3063{
3064 GLint a;
3065 GLubyte type, code;
3066
3067 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3068 type = *(*inst)++;
3069
3070 /* The actual opcode name */
3071 code = *(*inst)++;
3072
3073 /* Record the position in the program string for debugging */
3074 vp->StringPos = Program->Position;
3075
3076 vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
3077
3078 for (a = 0; a < 4; a++) {
3079 vp->SrcReg[0].Swizzle[a] = a;
3080 vp->SrcReg[1].Swizzle[a] = a;
3081 vp->SrcReg[2].Swizzle[a] = a;
3082 vp->DstReg.WriteMask[a] = 1;
3083 }
3084
3085 switch (type) {
3086 /* XXX: */
3087 case OP_ALU_ARL:
3088 vp->Opcode = VP_OPCODE_ARL;
3089
3090 /* Remember to set SrcReg.RelAddr; */
3091
3092 /* Get the masked address register [dst] */
3093 if (parse_masked_address_reg
3094 (ctx, inst, vc_head, Program, &vp->DstReg.Index,
3095 vp->DstReg.WriteMask))
3096 return 1;
3097 vp->DstReg.File = PROGRAM_ADDRESS;
3098
3099 /* Get a scalar src register */
3100 if (parse_scalar_src_reg
3101 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
3102 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
3103 vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
3104 return 1;
3105
3106 break;
3107
3108 case OP_ALU_VECTOR:
3109 switch (code) {
3110 case OP_ABS:
3111 vp->Opcode = VP_OPCODE_ABS;
3112 break;
3113 case OP_FLR:
3114 vp->Opcode = VP_OPCODE_FLR;
3115 break;
3116 case OP_FRC:
3117 vp->Opcode = VP_OPCODE_FRC;
3118 break;
3119 case OP_LIT:
3120 vp->Opcode = VP_OPCODE_LIT;
3121 break;
3122 case OP_MOV:
3123 vp->Opcode = VP_OPCODE_MOV;
3124 break;
3125 }
3126 if (parse_masked_dst_reg
3127 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3128 &vp->DstReg.Index, vp->DstReg.WriteMask))
3129 return 1;
3130 if (parse_vector_src_reg
3131 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
3132 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
3133 vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
3134 return 1;
3135 break;
3136
3137 case OP_ALU_SCALAR:
3138 switch (code) {
3139 case OP_EX2:
3140 vp->Opcode = VP_OPCODE_EX2;
3141 break;
3142 case OP_EXP:
3143 vp->Opcode = VP_OPCODE_EXP;
3144 break;
3145 case OP_LG2:
3146 vp->Opcode = VP_OPCODE_LG2;
3147 break;
3148 case OP_LOG:
3149 vp->Opcode = VP_OPCODE_LOG;
3150 break;
3151 case OP_RCP:
3152 vp->Opcode = VP_OPCODE_RCP;
3153 break;
3154 case OP_RSQ:
3155 vp->Opcode = VP_OPCODE_RSQ;
3156 break;
3157 }
3158 if (parse_masked_dst_reg
3159 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3160 &vp->DstReg.Index, vp->DstReg.WriteMask))
3161 return 1;
3162 if (parse_scalar_src_reg
3163 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
3164 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
3165 vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
3166 return 1;
3167 break;
3168
3169 case OP_ALU_BINSC:
3170 switch (code) {
3171 case OP_POW:
3172 vp->Opcode = VP_OPCODE_POW;
3173 break;
3174 }
3175 if (parse_masked_dst_reg
3176 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3177 &vp->DstReg.Index, vp->DstReg.WriteMask))
3178 return 1;
3179 for (a = 0; a < 2; a++) {
3180 if (parse_scalar_src_reg
3181 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
3182 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
3183 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
3184 return 1;
3185 }
3186 break;
3187
3188 case OP_ALU_BIN:
3189 switch (code) {
3190 case OP_ADD:
3191 vp->Opcode = VP_OPCODE_ADD;
3192 break;
3193 case OP_DP3:
3194 vp->Opcode = VP_OPCODE_DP3;
3195 break;
3196 case OP_DP4:
3197 vp->Opcode = VP_OPCODE_DP4;
3198 break;
3199 case OP_DPH:
3200 vp->Opcode = VP_OPCODE_DPH;
3201 break;
3202 case OP_DST:
3203 vp->Opcode = VP_OPCODE_DST;
3204 break;
3205 case OP_MAX:
3206 vp->Opcode = VP_OPCODE_MAX;
3207 break;
3208 case OP_MIN:
3209 vp->Opcode = VP_OPCODE_MIN;
3210 break;
3211 case OP_MUL:
3212 vp->Opcode = VP_OPCODE_MUL;
3213 break;
3214 case OP_SGE:
3215 vp->Opcode = VP_OPCODE_SGE;
3216 break;
3217 case OP_SLT:
3218 vp->Opcode = VP_OPCODE_SLT;
3219 break;
3220 case OP_SUB:
3221 vp->Opcode = VP_OPCODE_SUB;
3222 break;
3223 case OP_XPD:
3224 vp->Opcode = VP_OPCODE_XPD;
3225 break;
3226 }
3227 if (parse_masked_dst_reg
3228 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3229 &vp->DstReg.Index, vp->DstReg.WriteMask))
3230 return 1;
3231 for (a = 0; a < 2; a++) {
3232 if (parse_vector_src_reg
3233 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
3234 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
3235 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
3236 return 1;
3237 }
3238 break;
3239
3240 case OP_ALU_TRI:
3241 switch (code) {
3242 case OP_MAD:
3243 vp->Opcode = VP_OPCODE_MAD;
3244 break;
3245 }
3246
3247 if (parse_masked_dst_reg
3248 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3249 &vp->DstReg.Index, vp->DstReg.WriteMask))
3250 return 1;
3251 for (a = 0; a < 3; a++) {
3252 if (parse_vector_src_reg
3253 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
3254 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
3255 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
3256 return 1;
3257 }
3258 break;
3259
3260 case OP_ALU_SWZ:
3261 switch (code) {
3262 case OP_SWZ:
3263 vp->Opcode = VP_OPCODE_SWZ;
3264 break;
3265 }
3266 if (parse_masked_dst_reg
3267 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
3268 &vp->DstReg.Index, vp->DstReg.WriteMask))
3269 return 1;
3270
3271 if (parse_src_reg
3272 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
3273 &vp->SrcReg[0].Index, &vp->SrcReg[0].RelAddr))
3274 return 1;
3275 parse_extended_swizzle_mask (inst, vp->SrcReg[0].Swizzle,
3276 &vp->SrcReg[0].Negate);
3277 break;
3278 }
3279 return 0;
3280}
3281
3282#if DEBUG_PARSING
3283
3284static GLvoid
3285print_state_token (GLint token)
3286{
3287 switch (token) {
3288 case STATE_MATERIAL:
3289 fprintf (stderr, "STATE_MATERIAL ");
3290 break;
3291 case STATE_LIGHT:
3292 fprintf (stderr, "STATE_LIGHT ");
3293 break;
3294
3295 case STATE_LIGHTMODEL_AMBIENT:
3296 fprintf (stderr, "STATE_AMBIENT ");
3297 break;
3298
3299 case STATE_LIGHTMODEL_SCENECOLOR:
3300 fprintf (stderr, "STATE_SCENECOLOR ");
3301 break;
3302
3303 case STATE_LIGHTPROD:
3304 fprintf (stderr, "STATE_LIGHTPROD ");
3305 break;
3306
3307 case STATE_TEXGEN:
3308 fprintf (stderr, "STATE_TEXGEN ");
3309 break;
3310
3311 case STATE_FOG_COLOR:
3312 fprintf (stderr, "STATE_FOG_COLOR ");
3313 break;
3314
3315 case STATE_FOG_PARAMS:
3316 fprintf (stderr, "STATE_FOG_PARAMS ");
3317 break;
3318
3319 case STATE_CLIPPLANE:
3320 fprintf (stderr, "STATE_CLIPPLANE ");
3321 break;
3322
3323 case STATE_POINT_SIZE:
3324 fprintf (stderr, "STATE_POINT_SIZE ");
3325 break;
3326
3327 case STATE_POINT_ATTENUATION:
3328 fprintf (stderr, "STATE_ATTENUATION ");
3329 break;
3330
3331 case STATE_MATRIX:
3332 fprintf (stderr, "STATE_MATRIX ");
3333 break;
3334
3335 case STATE_MODELVIEW:
3336 fprintf (stderr, "STATE_MODELVIEW ");
3337 break;
3338
3339 case STATE_PROJECTION:
3340 fprintf (stderr, "STATE_PROJECTION ");
3341 break;
3342
3343 case STATE_MVP:
3344 fprintf (stderr, "STATE_MVP ");
3345 break;
3346
3347 case STATE_TEXTURE:
3348 fprintf (stderr, "STATE_TEXTURE ");
3349 break;
3350
3351 case STATE_PROGRAM:
3352 fprintf (stderr, "STATE_PROGRAM ");
3353 break;
3354
3355 case STATE_MATRIX_INVERSE:
3356 fprintf (stderr, "STATE_INVERSE ");
3357 break;
3358
3359 case STATE_MATRIX_TRANSPOSE:
3360 fprintf (stderr, "STATE_TRANSPOSE ");
3361 break;
3362
3363 case STATE_MATRIX_INVTRANS:
3364 fprintf (stderr, "STATE_INVTRANS ");
3365 break;
3366
3367 case STATE_AMBIENT:
3368 fprintf (stderr, "STATE_AMBIENT ");
3369 break;
3370
3371 case STATE_DIFFUSE:
3372 fprintf (stderr, "STATE_DIFFUSE ");
3373 break;
3374
3375 case STATE_SPECULAR:
3376 fprintf (stderr, "STATE_SPECULAR ");
3377 break;
3378
3379 case STATE_EMISSION:
3380 fprintf (stderr, "STATE_EMISSION ");
3381 break;
3382
3383 case STATE_SHININESS:
3384 fprintf (stderr, "STATE_SHININESS ");
3385 break;
3386
3387 case STATE_HALF:
3388 fprintf (stderr, "STATE_HALF ");
3389 break;
3390
3391 case STATE_POSITION:
3392 fprintf (stderr, "STATE_POSITION ");
3393 break;
3394
3395 case STATE_ATTENUATION:
3396 fprintf (stderr, "STATE_ATTENUATION ");
3397 break;
3398
3399 case STATE_SPOT_DIRECTION:
3400 fprintf (stderr, "STATE_DIRECTION ");
3401 break;
3402
3403 case STATE_TEXGEN_EYE_S:
3404 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3405 break;
3406
3407 case STATE_TEXGEN_EYE_T:
3408 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3409 break;
3410
3411 case STATE_TEXGEN_EYE_R:
3412 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3413 break;
3414
3415 case STATE_TEXGEN_EYE_Q:
3416 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3417 break;
3418
3419 case STATE_TEXGEN_OBJECT_S:
3420 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3421 break;
3422
3423 case STATE_TEXGEN_OBJECT_T:
3424 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3425 break;
3426
3427 case STATE_TEXGEN_OBJECT_R:
3428 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3429 break;
3430
3431 case STATE_TEXGEN_OBJECT_Q:
3432 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3433 break;
3434
3435 case STATE_TEXENV_COLOR:
3436 fprintf (stderr, "STATE_TEXENV_COLOR ");
3437 break;
3438
3439 case STATE_DEPTH_RANGE:
3440 fprintf (stderr, "STATE_DEPTH_RANGE ");
3441 break;
3442
3443 case STATE_VERTEX_PROGRAM:
3444 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3445 break;
3446
3447 case STATE_FRAGMENT_PROGRAM:
3448 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3449 break;
3450
3451 case STATE_ENV:
3452 fprintf (stderr, "STATE_ENV ");
3453 break;
3454
3455 case STATE_LOCAL:
3456 fprintf (stderr, "STATE_LOCAL ");
3457 break;
3458
3459 }
3460 fprintf (stderr, "[%d] ", token);
3461}
3462
3463
3464static GLvoid
3465debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3466 struct arb_program *Program)
3467{
3468 struct var_cache *vc;
3469 GLint a, b;
3470
3471 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3472
3473 /* First of all, print out the contents of the var_cache */
3474 vc = vc_head;
3475 while (vc) {
3476 fprintf (stderr, "[%x]\n", vc);
3477 switch (vc->type) {
3478 case vt_none:
3479 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3480 break;
3481 case vt_attrib:
3482 fprintf (stderr, "ATTRIB %s\n", vc->name);
3483 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3484 break;
3485 case vt_param:
3486 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3487 vc->param_binding_begin, vc->param_binding_length);
3488 b = vc->param_binding_begin;
3489 for (a = 0; a < vc->param_binding_length; a++) {
3490 fprintf (stderr, "%s\n",
3491 Program->Parameters->Parameters[a + b].Name);
3492 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3493 print_state_token (Program->Parameters->Parameters[a + b].
3494 StateIndexes[0]);
3495 print_state_token (Program->Parameters->Parameters[a + b].
3496 StateIndexes[1]);
3497 print_state_token (Program->Parameters->Parameters[a + b].
3498 StateIndexes[2]);
3499 print_state_token (Program->Parameters->Parameters[a + b].
3500 StateIndexes[3]);
3501 print_state_token (Program->Parameters->Parameters[a + b].
3502 StateIndexes[4]);
3503 print_state_token (Program->Parameters->Parameters[a + b].
3504 StateIndexes[5]);
3505 }
3506 else
3507 fprintf (stderr, "%f %f %f %f\n",
3508 Program->Parameters->Parameters[a + b].Values[0],
3509 Program->Parameters->Parameters[a + b].Values[1],
3510 Program->Parameters->Parameters[a + b].Values[2],
3511 Program->Parameters->Parameters[a + b].Values[3]);
3512 }
3513 break;
3514 case vt_temp:
3515 fprintf (stderr, "TEMP %s\n", vc->name);
3516 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3517 break;
3518 case vt_output:
3519 fprintf (stderr, "OUTPUT %s\n", vc->name);
3520 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3521 break;
3522 case vt_alias:
3523 fprintf (stderr, "ALIAS %s\n", vc->name);
3524 fprintf (stderr, " binding: 0x%x (%s)\n",
3525 vc->alias_binding, vc->alias_binding->name);
3526 break;
3527 }
3528 vc = vc->next;
3529 }
3530}
3531
3532#endif
3533
3534
3535/**
3536 * The main loop for parsing a fragment or vertex program
3537 *
3538 * \return 0 on sucess, 1 on error
3539 */
3540static GLint
3541parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3542 struct arb_program *Program)
3543{
3544 GLint err = 0;
3545
3546 Program->MajorVersion = (GLuint) * inst++;
3547 Program->MinorVersion = (GLuint) * inst++;
3548
3549 while (*inst != END) {
3550 switch (*inst++) {
3551
3552 case OPTION:
3553 switch (*inst++) {
3554 case ARB_PRECISION_HINT_FASTEST:
3555 Program->PrecisionOption = GL_FASTEST;
3556 break;
3557
3558 case ARB_PRECISION_HINT_NICEST:
3559 Program->PrecisionOption = GL_NICEST;
3560 break;
3561
3562 case ARB_FOG_EXP:
3563 Program->FogOption = GL_EXP;
3564 break;
3565
3566 case ARB_FOG_EXP2:
3567 Program->FogOption = GL_EXP2;
3568 break;
3569
3570 case ARB_FOG_LINEAR:
3571 Program->FogOption = GL_LINEAR;
3572 break;
3573
3574 case ARB_POSITION_INVARIANT:
3575 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
3576 Program->HintPositionInvariant = 1;
3577 break;
3578
3579 case ARB_FRAGMENT_PROGRAM_SHADOW:
3580 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3581 /* TODO ARB_fragment_program_shadow code */
3582 }
3583 break;
3584 }
3585 break;
3586
3587 case INSTRUCTION:
3588 Program->Position = parse_position (&inst);
3589
3590 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3591
3592 /* Check the instruction count
3593 * XXX: Does END count as an instruction?
3594 */
3595 if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
3596 _mesa_set_program_error (ctx, Program->Position,
3597 "Max instruction count exceeded!");
3598 _mesa_error (ctx, GL_INVALID_OPERATION,
3599 "Max instruction count exceeded!");
3600 }
3601
3602 /* Realloc Program->FPInstructions */
3603 Program->FPInstructions =
3604 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3605 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3606 (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));
3607
3608 /* parse the current instruction */
3609 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
3610 &Program->FPInstructions[Program->Base.NumInstructions]);
3611
3612 }
3613 else {
3614 /* Check the instruction count
3615 * XXX: Does END count as an instruction?
3616 */
3617 if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
3618 _mesa_set_program_error (ctx, Program->Position,
3619 "Max instruction count exceeded!");
3620 _mesa_error (ctx, GL_INVALID_OPERATION,
3621 "Max instruction count exceeded!");
3622 }
3623
3624 /* Realloc Program->VPInstructions */
3625 Program->VPInstructions =
3626 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3627 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3628 (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));
3629
3630 /* parse the current instruction */
3631 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
3632 &Program->VPInstructions[Program->Base.NumInstructions]);
3633 }
3634
3635 /* increment Program->Base.NumInstructions */
3636 Program->Base.NumInstructions++;
3637 break;
3638
3639 case DECLARATION:
3640 err = parse_declaration (ctx, &inst, vc_head, Program);
3641 break;
3642
3643 default:
3644 break;
3645 }
3646
3647 if (err)
3648 break;
3649 }
3650
3651 /* Finally, tag on an OPCODE_END instruction */
3652 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3653 Program->FPInstructions =
3654 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3655 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3656 (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
3657
3658 Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
3659 /* YYY Wrong Position in program, whatever, at least not random -> crash
3660 Program->Position = parse_position (&inst);
3661 */
3662 Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
3663 }
3664 else {
3665 Program->VPInstructions =
3666 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3667 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3668 (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
3669
3670 Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
3671 /* YYY Wrong Position in program, whatever, at least not random -> crash
3672 Program->Position = parse_position (&inst);
3673 */
3674 Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
3675 }
3676
3677 /* increment Program->Base.NumInstructions */
3678 Program->Base.NumInstructions++;
3679
3680 return err;
3681}
3682
3683/* XXX temporary */
3684static char core_grammar_text[] =
3685#include "grammar_syn.h"
3686;
3687
3688static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3689{
3690 char error_msg[300];
3691 GLint error_pos;
3692
3693 if (grammar_set_reg8 (id, name, value))
3694 return 0;
3695
3696 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3697 _mesa_set_program_error (ctx, error_pos, error_msg);
3698 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3699 return 1;
3700}
3701
3702static int extension_is_supported (const GLubyte *ext)
3703{
3704 const GLubyte *extensions = glGetString (GL_EXTENSIONS);
3705 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
3706 const GLint ext_len = _mesa_strlen ((const char *) ext);
3707
3708 while (extensions < end)
3709 {
3710 const GLubyte *name_end = (const GLubyte *) strchr ((const char *) extensions, ' ');
3711 if (name_end == NULL)
3712 name_end = end;
3713 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3714 (const char *) extensions, ext_len) == 0)
3715 return 1;
3716 extensions = name_end + 1;
3717 }
3718
3719 return 0;
3720}
3721
3722static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3723{
3724 if (extension_is_supported (extname))
3725 if (set_reg8 (ctx, id, name, 0x01))
3726 return 1;
3727 return 0;
3728}
3729
3730/**
3731 * This kicks everything off.
3732 *
3733 * \param ctx - The GL Context
3734 * \param str - The program string
3735 * \param len - The program string length
3736 * \param Program - The arb_program struct to return all the parsed info in
3737 * \return 0 on sucess, 1 on error
3738 */
3739GLuint
3740_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3741 struct arb_program * program)
3742{
3743 GLint a, err, error_pos;
3744 char error_msg[300];
3745 GLuint parsed_len;
3746 struct var_cache *vc_head;
3747 grammar arbprogram_syn_id;
3748 GLubyte *parsed, *inst;
3749 GLubyte *strz = NULL;
3750 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3751
3752#if DEBUG_PARSING
3753 fprintf (stderr, "Loading grammar text!\n");
3754#endif
3755
3756 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3757 if (!arbprogram_syn_is_ok) {
3758 grammar grammar_syn_id;
3759 GLint err;
3760 GLuint parsed_len;
3761 byte *parsed;
3762
3763 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3764 if (grammar_syn_id == 0) {
3765 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3766 _mesa_set_program_error (ctx, error_pos, error_msg);
3767 _mesa_error (ctx, GL_INVALID_OPERATION,
3768 "Error loading grammar rule set");
3769 return 1;
3770 }
3771
3772 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3773
3774 /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can
3775 reset the last error
3776 */
3777
3778 if (err == 0) {
3779 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3780 _mesa_set_program_error (ctx, error_pos, error_msg);
3781 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3782
3783 grammar_destroy (grammar_syn_id);
3784 return 1;
3785 }
3786
3787 grammar_destroy (grammar_syn_id);
3788
3789 arbprogram_syn_is_ok = 1;
3790 }
3791
3792 /* create the grammar object */
3793 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3794 if (arbprogram_syn_id == 0) {
3795 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3796 _mesa_set_program_error (ctx, error_pos, error_msg);
3797 _mesa_error (ctx, GL_INVALID_OPERATION,
3798 "Error loading grammer rule set");
3799 return 1;
3800 }
3801
3802 /* Set program_target register value */
3803 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3804 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3805 grammar_destroy (arbprogram_syn_id);
3806 return 1;
3807 }
3808
3809 /* Enable all active extensions */
3810 if (enable_ext (ctx, arbprogram_syn_id,
3811 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3812 enable_ext (ctx, arbprogram_syn_id,
3813 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3814 enable_ext (ctx, arbprogram_syn_id,
3815 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
3816 enable_ext (ctx, arbprogram_syn_id,
3817 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
3818 enable_ext (ctx, arbprogram_syn_id,
3819 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
3820 enable_ext (ctx, arbprogram_syn_id,
3821 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
3822 enable_ext (ctx, arbprogram_syn_id,
3823 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
3824 enable_ext (ctx, arbprogram_syn_id,
3825 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
3826 enable_ext (ctx, arbprogram_syn_id,
3827 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
3828 enable_ext (ctx, arbprogram_syn_id,
3829 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow")) {
3830 grammar_destroy (arbprogram_syn_id);
3831 return 1;
3832 }
3833
3834 /* check for NULL character occurences */
3835 {
3836 int i;
3837 for (i = 0; i < len; i++)
3838 if (str[i] == '\0') {
3839 _mesa_set_program_error (ctx, i, "invalid character");
3840 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
3841
3842 grammar_destroy (arbprogram_syn_id);
3843 return 1;
3844 }
3845 }
3846
3847 /* copy the program string to a null-terminated string */
3848 /* XXX should I check for NULL from malloc()? */
Brian Paulbdd15b52004-05-04 15:11:06 +00003849 strz = (GLubyte *) _mesa_malloc (len + 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003850 _mesa_memcpy (strz, str, len);
3851 strz[len] = '\0';
3852
3853#if DEBUG_PARSING
3854 printf ("Checking Grammar!\n");
3855#endif
3856 err = grammar_check (arbprogram_syn_id, strz, &parsed, &parsed_len);
3857
3858 /* Syntax parse error */
3859 if (err == 0) {
3860 _mesa_free (strz);
3861 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3862 _mesa_set_program_error (ctx, error_pos, error_msg);
3863 _mesa_error (ctx, GL_INVALID_OPERATION, "Parse Error");
3864
3865 grammar_destroy (arbprogram_syn_id);
3866 return 1;
3867 }
3868
3869#if DEBUG_PARSING
3870 printf ("Destroying grammer dict [parse retval: %d]\n", err);
3871#endif
3872 grammar_destroy (arbprogram_syn_id);
3873
3874 /* Initialize the arb_program struct */
3875 program->Base.String = strz;
3876 program->Base.NumInstructions =
3877 program->Base.NumTemporaries =
3878 program->Base.NumParameters =
3879 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
3880 program->Parameters = _mesa_new_parameter_list ();
3881 program->InputsRead = 0;
3882 program->OutputsWritten = 0;
3883 program->Position = 0;
3884 program->MajorVersion = program->MinorVersion = 0;
3885 program->PrecisionOption = GL_DONT_CARE;
3886 program->FogOption = GL_NONE;
3887 program->HintPositionInvariant = GL_FALSE;
3888 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
3889 program->TexturesUsed[a] = 0;
3890 program->NumAluInstructions =
3891 program->NumTexInstructions =
3892 program->NumTexIndirections = 0;
3893
3894 program->FPInstructions = NULL;
3895 program->VPInstructions = NULL;
3896
3897 vc_head = NULL;
3898 err = 0;
3899
3900 /* Start examining the tokens in the array */
3901 inst = parsed;
3902
3903 /* Check the grammer rev */
3904 if (*inst++ != REVISION) {
3905 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
3906 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar verison mismatch");
3907 err = 1;
3908 }
3909 else {
3910 switch (*inst++) {
3911 case FRAGMENT_PROGRAM:
3912 program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
3913 break;
3914
3915 case VERTEX_PROGRAM:
3916 program->Base.Target = GL_VERTEX_PROGRAM_ARB;
3917 break;
3918 }
3919
3920 err = parse_arb_program (ctx, inst, &vc_head, program);
3921#if DEBUG_PARSING
3922 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
3923#endif
3924 }
3925
3926 /*debug_variables(ctx, vc_head, program); */
3927
3928 /* We're done with the parsed binary array */
3929 var_cache_destroy (&vc_head);
3930
3931 _mesa_free (parsed);
3932#if DEBUG_PARSING
3933 printf ("_mesa_parse_arb_program() done\n");
3934#endif
3935 return err;
3936}