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