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