blob: 6648ed7b7191d08071fe54c850574568e42e2f89 [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Brianb7978af2007-01-09 19:17:17 -07003 * Version: 6.5.3
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
Brianb7978af2007-01-09 19:17:17 -07005 * Copyright (C) 1999-2007 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
Brianc223c6b2007-07-04 13:15:20 -060033#include "main/glheader.h"
34#include "main/imports.h"
35#include "shader/grammar/grammar_mesa.h"
Jouk Jansen40322e12004-04-05 08:50:36 +000036#include "arbprogparse.h"
Brian Paul32df89e2005-10-29 18:26:43 +000037#include "program.h"
Brian Paulc0ef1662008-03-25 11:32:31 -060038#include "programopt.h"
Brianc0551f02006-12-14 15:02:37 -070039#include "prog_parameter.h"
40#include "prog_statevars.h"
Brian Paul8c41a142005-11-19 15:36:28 +000041#include "context.h"
Brian Paul6211a142006-08-24 23:37:13 +000042#include "macros.h"
Brian Paul8c41a142005-11-19 15:36:28 +000043#include "mtypes.h"
Brianc0551f02006-12-14 15:02:37 -070044#include "prog_instruction.h"
Brian Paul8c41a142005-11-19 15:36:28 +000045
46
Brian Paul6211a142006-08-24 23:37:13 +000047/* For ARB programs, use the NV instruction limits */
48#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
49 MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
Brian Paul8c41a142005-11-19 15:36:28 +000050
51
52/**
53 * This is basically a union of the vertex_program and fragment_program
54 * structs that we can use to parse the program into
55 *
56 * XXX we can probably get rid of this entirely someday.
57 */
58struct arb_program
59{
Brian Paul122629f2006-07-20 16:49:57 +000060 struct gl_program Base;
Brian Paul8c41a142005-11-19 15:36:28 +000061
62 GLuint Position; /* Just used for error reporting while parsing */
63 GLuint MajorVersion;
64 GLuint MinorVersion;
65
66 /* ARB_vertex_progmra options */
67 GLboolean HintPositionInvariant;
68
69 /* ARB_fragment_progmra options */
70 GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
71 GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
72
73 /* ARB_fragment_program specifics */
74 GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];
Ian Romanick7b559a92007-06-07 13:58:50 -070075 GLbitfield ShadowSamplers;
Brian Paul8c41a142005-11-19 15:36:28 +000076 GLuint NumAluInstructions;
77 GLuint NumTexInstructions;
78 GLuint NumTexIndirections;
79
80 GLboolean UsesKill;
81};
82
Ian Romanick9bdfee32005-07-18 12:31:24 +000083
Brian Paula6c423d2004-08-25 15:59:48 +000084
Jouk Jansen40322e12004-04-05 08:50:36 +000085/* TODO:
86 * Fragment Program Stuff:
87 * -----------------------------------------------------
88 *
89 * - things from Michal's email
90 * + overflow on atoi
91 * + not-overflowing floats (don't use parse_integer..)
92 * + can remove range checking in arbparse.c
93 *
94 * - check all limits of number of various variables
95 * + parameters
96 *
97 * - test! test! test!
98 *
99 * Vertex Program Stuff:
100 * -----------------------------------------------------
101 * - Optimize param array usage and count limits correctly, see spec,
102 * section 2.14.3.7
103 * + Record if an array is reference absolutly or relatively (or both)
104 * + For absolute arrays, store a bitmap of accesses
105 * + For single parameters, store an access flag
106 * + After parsing, make a parameter cleanup and merging pass, where
107 * relative arrays are layed out first, followed by abs arrays, and
108 * finally single state.
109 * + Remap offsets for param src and dst registers
110 * + Now we can properly count parameter usage
111 *
112 * - Multiple state binding errors in param arrays (see spec, just before
113 * section 2.14.3.3)
114 * - grep for XXX
115 *
116 * Mesa Stuff
117 * -----------------------------------------------------
118 * - User clipping planes vs. PositionInvariant
119 * - Is it sufficient to just multiply by the mvp to transform in the
120 * PositionInvariant case? Or do we need something more involved?
121 *
122 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
123 * - fetch state listed in program_parameters list
124 * + WTF should this go???
125 * + currently in nvvertexec.c and s_nvfragprog.c
126 *
127 * - allow for multiple address registers (and fetch address regs properly)
128 *
129 * Cosmetic Stuff
130 * -----------------------------------------------------
131 * - remove any leftover unused grammer.c stuff (dict_ ?)
132 * - fix grammer.c error handling so its not static
133 * - #ifdef around stuff pertaining to extentions
134 *
135 * Outstanding Questions:
136 * -----------------------------------------------------
137 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
138 * what gets hacked off because of this:
139 * + VERTEX_ATTRIB_MATRIXINDEX
140 * + VERTEX_ATTRIB_WEIGHT
141 * + MATRIX_MODELVIEW
142 * + MATRIX_PALETTE
143 *
144 * - When can we fetch env/local params from their own register files, and
145 * when to we have to fetch them into the main state register file?
146 * (think arrays)
147 *
148 * Grammar Changes:
149 * -----------------------------------------------------
150 */
151
152/* Changes since moving the file to shader directory
153
1542004-III-4 ------------------------------------------------------------
155- added #include "grammar_mesa.h"
156- removed grammar specific code part (it resides now in grammar.c)
157- added GL_ARB_fragment_program_shadow tokens
158- modified #include "arbparse_syn.h"
159- major changes inside _mesa_parse_arb_program()
160- check the program string for '\0' characters
161- copy the program string to a one-byte-longer location to have
162 it null-terminated
163- position invariance test (not writing to result.position) moved
164 to syntax part
165*/
166
167typedef GLubyte *production;
168
Brian Paul11a54c32006-11-15 19:54:25 +0000169
Jouk Jansen40322e12004-04-05 08:50:36 +0000170/**
171 * This is the text describing the rules to parse the grammar
172 */
Brian Paul11a54c32006-11-15 19:54:25 +0000173LONGSTRING static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000174#include "arbprogram_syn.h"
175;
176
177/**
178 * These should match up with the values defined in arbprogram.syn
179 */
180
181/*
182 Changes:
183 - changed and merged V_* and F_* opcode values to OP_*.
184 - added GL_ARB_fragment_program_shadow specific tokens (michal)
185*/
Ian Romanickbb372f12007-05-16 15:34:22 -0700186#define REVISION 0x0a
Jouk Jansen40322e12004-04-05 08:50:36 +0000187
188/* program type */
189#define FRAGMENT_PROGRAM 0x01
190#define VERTEX_PROGRAM 0x02
191
192/* program section */
193#define OPTION 0x01
194#define INSTRUCTION 0x02
195#define DECLARATION 0x03
196#define END 0x04
197
Michal Krolb80bc052004-10-21 14:09:54 +0000198/* GL_ARB_fragment_program option */
199#define ARB_PRECISION_HINT_FASTEST 0x00
200#define ARB_PRECISION_HINT_NICEST 0x01
201#define ARB_FOG_EXP 0x02
202#define ARB_FOG_EXP2 0x03
203#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000204
Michal Krolb80bc052004-10-21 14:09:54 +0000205/* GL_ARB_vertex_program option */
206#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000207
Michal Krolb80bc052004-10-21 14:09:54 +0000208/* GL_ARB_fragment_program_shadow option */
209#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000210
Michal Krolb80bc052004-10-21 14:09:54 +0000211/* GL_ARB_draw_buffers option */
212#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000213
Ian Romanickbb372f12007-05-16 15:34:22 -0700214/* GL_MESA_texture_array option */
215#define MESA_TEXTURE_ARRAY 0x08
216
Jouk Jansen40322e12004-04-05 08:50:36 +0000217/* GL_ARB_fragment_program instruction class */
218#define OP_ALU_INST 0x00
219#define OP_TEX_INST 0x01
220
221/* GL_ARB_vertex_program instruction class */
222/* OP_ALU_INST */
223
224/* GL_ARB_fragment_program instruction type */
225#define OP_ALU_VECTOR 0x00
226#define OP_ALU_SCALAR 0x01
227#define OP_ALU_BINSC 0x02
228#define OP_ALU_BIN 0x03
229#define OP_ALU_TRI 0x04
230#define OP_ALU_SWZ 0x05
231#define OP_TEX_SAMPLE 0x06
232#define OP_TEX_KIL 0x07
233
234/* GL_ARB_vertex_program instruction type */
235#define OP_ALU_ARL 0x08
236/* OP_ALU_VECTOR */
237/* OP_ALU_SCALAR */
238/* OP_ALU_BINSC */
239/* OP_ALU_BIN */
240/* OP_ALU_TRI */
241/* OP_ALU_SWZ */
242
243/* GL_ARB_fragment_program instruction code */
244#define OP_ABS 0x00
245#define OP_ABS_SAT 0x1B
246#define OP_FLR 0x09
247#define OP_FLR_SAT 0x26
248#define OP_FRC 0x0A
249#define OP_FRC_SAT 0x27
250#define OP_LIT 0x0C
251#define OP_LIT_SAT 0x2A
252#define OP_MOV 0x11
253#define OP_MOV_SAT 0x30
254#define OP_COS 0x1F
255#define OP_COS_SAT 0x20
256#define OP_EX2 0x07
257#define OP_EX2_SAT 0x25
258#define OP_LG2 0x0B
259#define OP_LG2_SAT 0x29
260#define OP_RCP 0x14
261#define OP_RCP_SAT 0x33
262#define OP_RSQ 0x15
263#define OP_RSQ_SAT 0x34
264#define OP_SIN 0x38
265#define OP_SIN_SAT 0x39
266#define OP_SCS 0x35
267#define OP_SCS_SAT 0x36
268#define OP_POW 0x13
269#define OP_POW_SAT 0x32
270#define OP_ADD 0x01
271#define OP_ADD_SAT 0x1C
272#define OP_DP3 0x03
273#define OP_DP3_SAT 0x21
274#define OP_DP4 0x04
275#define OP_DP4_SAT 0x22
276#define OP_DPH 0x05
277#define OP_DPH_SAT 0x23
278#define OP_DST 0x06
279#define OP_DST_SAT 0x24
280#define OP_MAX 0x0F
281#define OP_MAX_SAT 0x2E
282#define OP_MIN 0x10
283#define OP_MIN_SAT 0x2F
284#define OP_MUL 0x12
285#define OP_MUL_SAT 0x31
286#define OP_SGE 0x16
287#define OP_SGE_SAT 0x37
288#define OP_SLT 0x17
289#define OP_SLT_SAT 0x3A
290#define OP_SUB 0x18
291#define OP_SUB_SAT 0x3B
292#define OP_XPD 0x1A
293#define OP_XPD_SAT 0x43
294#define OP_CMP 0x1D
295#define OP_CMP_SAT 0x1E
296#define OP_LRP 0x2B
297#define OP_LRP_SAT 0x2C
298#define OP_MAD 0x0E
299#define OP_MAD_SAT 0x2D
300#define OP_SWZ 0x19
301#define OP_SWZ_SAT 0x3C
302#define OP_TEX 0x3D
303#define OP_TEX_SAT 0x3E
304#define OP_TXB 0x3F
305#define OP_TXB_SAT 0x40
306#define OP_TXP 0x41
307#define OP_TXP_SAT 0x42
308#define OP_KIL 0x28
309
310/* GL_ARB_vertex_program instruction code */
311#define OP_ARL 0x02
312/* OP_ABS */
313/* OP_FLR */
314/* OP_FRC */
315/* OP_LIT */
316/* OP_MOV */
317/* OP_EX2 */
318#define OP_EXP 0x08
319/* OP_LG2 */
320#define OP_LOG 0x0D
321/* OP_RCP */
322/* OP_RSQ */
323/* OP_POW */
324/* OP_ADD */
325/* OP_DP3 */
326/* OP_DP4 */
327/* OP_DPH */
328/* OP_DST */
329/* OP_MAX */
330/* OP_MIN */
331/* OP_MUL */
332/* OP_SGE */
333/* OP_SLT */
334/* OP_SUB */
335/* OP_XPD */
336/* OP_MAD */
337/* OP_SWZ */
338
339/* fragment attribute binding */
340#define FRAGMENT_ATTRIB_COLOR 0x01
341#define FRAGMENT_ATTRIB_TEXCOORD 0x02
342#define FRAGMENT_ATTRIB_FOGCOORD 0x03
343#define FRAGMENT_ATTRIB_POSITION 0x04
344
345/* vertex attribute binding */
346#define VERTEX_ATTRIB_POSITION 0x01
347#define VERTEX_ATTRIB_WEIGHT 0x02
348#define VERTEX_ATTRIB_NORMAL 0x03
349#define VERTEX_ATTRIB_COLOR 0x04
350#define VERTEX_ATTRIB_FOGCOORD 0x05
351#define VERTEX_ATTRIB_TEXCOORD 0x06
352#define VERTEX_ATTRIB_MATRIXINDEX 0x07
353#define VERTEX_ATTRIB_GENERIC 0x08
354
355/* fragment result binding */
356#define FRAGMENT_RESULT_COLOR 0x01
357#define FRAGMENT_RESULT_DEPTH 0x02
358
359/* vertex result binding */
360#define VERTEX_RESULT_POSITION 0x01
361#define VERTEX_RESULT_COLOR 0x02
362#define VERTEX_RESULT_FOGCOORD 0x03
363#define VERTEX_RESULT_POINTSIZE 0x04
364#define VERTEX_RESULT_TEXCOORD 0x05
365
366/* texture target */
367#define TEXTARGET_1D 0x01
368#define TEXTARGET_2D 0x02
369#define TEXTARGET_3D 0x03
370#define TEXTARGET_RECT 0x04
371#define TEXTARGET_CUBE 0x05
372/* GL_ARB_fragment_program_shadow */
373#define TEXTARGET_SHADOW1D 0x06
374#define TEXTARGET_SHADOW2D 0x07
375#define TEXTARGET_SHADOWRECT 0x08
Ian Romanickbb372f12007-05-16 15:34:22 -0700376/* GL_MESA_texture_array */
377#define TEXTARGET_1D_ARRAY 0x09
378#define TEXTARGET_2D_ARRAY 0x0a
Ian Romanick69358e72007-06-05 09:24:27 -0700379#define TEXTARGET_SHADOW1D_ARRAY 0x0b
380#define TEXTARGET_SHADOW2D_ARRAY 0x0c
Jouk Jansen40322e12004-04-05 08:50:36 +0000381
382/* face type */
383#define FACE_FRONT 0x00
384#define FACE_BACK 0x01
385
386/* color type */
387#define COLOR_PRIMARY 0x00
388#define COLOR_SECONDARY 0x01
389
390/* component */
391#define COMPONENT_X 0x00
392#define COMPONENT_Y 0x01
393#define COMPONENT_Z 0x02
394#define COMPONENT_W 0x03
395#define COMPONENT_0 0x04
396#define COMPONENT_1 0x05
397
398/* array index type */
399#define ARRAY_INDEX_ABSOLUTE 0x00
400#define ARRAY_INDEX_RELATIVE 0x01
401
402/* matrix name */
403#define MATRIX_MODELVIEW 0x01
404#define MATRIX_PROJECTION 0x02
405#define MATRIX_MVP 0x03
406#define MATRIX_TEXTURE 0x04
407#define MATRIX_PALETTE 0x05
408#define MATRIX_PROGRAM 0x06
409
410/* matrix modifier */
411#define MATRIX_MODIFIER_IDENTITY 0x00
412#define MATRIX_MODIFIER_INVERSE 0x01
413#define MATRIX_MODIFIER_TRANSPOSE 0x02
414#define MATRIX_MODIFIER_INVTRANS 0x03
415
416/* constant type */
417#define CONSTANT_SCALAR 0x01
418#define CONSTANT_VECTOR 0x02
419
420/* program param type */
421#define PROGRAM_PARAM_ENV 0x01
422#define PROGRAM_PARAM_LOCAL 0x02
423
424/* register type */
425#define REGISTER_ATTRIB 0x01
426#define REGISTER_PARAM 0x02
427#define REGISTER_RESULT 0x03
428#define REGISTER_ESTABLISHED_NAME 0x04
429
430/* param binding */
431#define PARAM_NULL 0x00
432#define PARAM_ARRAY_ELEMENT 0x01
433#define PARAM_STATE_ELEMENT 0x02
434#define PARAM_PROGRAM_ELEMENT 0x03
435#define PARAM_PROGRAM_ELEMENTS 0x04
436#define PARAM_CONSTANT 0x05
437
438/* param state property */
439#define STATE_MATERIAL_PARSER 0x01
440#define STATE_LIGHT_PARSER 0x02
441#define STATE_LIGHT_MODEL 0x03
442#define STATE_LIGHT_PROD 0x04
443#define STATE_FOG 0x05
444#define STATE_MATRIX_ROWS 0x06
445/* GL_ARB_fragment_program */
446#define STATE_TEX_ENV 0x07
447#define STATE_DEPTH 0x08
448/* GL_ARB_vertex_program */
449#define STATE_TEX_GEN 0x09
450#define STATE_CLIP_PLANE 0x0A
451#define STATE_POINT 0x0B
452
453/* state material property */
454#define MATERIAL_AMBIENT 0x01
455#define MATERIAL_DIFFUSE 0x02
456#define MATERIAL_SPECULAR 0x03
457#define MATERIAL_EMISSION 0x04
458#define MATERIAL_SHININESS 0x05
459
460/* state light property */
461#define LIGHT_AMBIENT 0x01
462#define LIGHT_DIFFUSE 0x02
463#define LIGHT_SPECULAR 0x03
464#define LIGHT_POSITION 0x04
465#define LIGHT_ATTENUATION 0x05
466#define LIGHT_HALF 0x06
467#define LIGHT_SPOT_DIRECTION 0x07
468
469/* state light model property */
470#define LIGHT_MODEL_AMBIENT 0x01
471#define LIGHT_MODEL_SCENECOLOR 0x02
472
473/* state light product property */
474#define LIGHT_PROD_AMBIENT 0x01
475#define LIGHT_PROD_DIFFUSE 0x02
476#define LIGHT_PROD_SPECULAR 0x03
477
478/* state texture environment property */
479#define TEX_ENV_COLOR 0x01
480
481/* state texture generation coord property */
482#define TEX_GEN_EYE 0x01
483#define TEX_GEN_OBJECT 0x02
484
485/* state fog property */
486#define FOG_COLOR 0x01
487#define FOG_PARAMS 0x02
488
489/* state depth property */
490#define DEPTH_RANGE 0x01
491
492/* state point parameters property */
493#define POINT_SIZE 0x01
494#define POINT_ATTENUATION 0x02
495
496/* declaration */
497#define ATTRIB 0x01
498#define PARAM 0x02
499#define TEMP 0x03
500#define OUTPUT 0x04
501#define ALIAS 0x05
502/* GL_ARB_vertex_program */
503#define ADDRESS 0x06
504
505/*-----------------------------------------------------------------------
506 * From here on down is the semantic checking portion
507 *
508 */
509
510/**
511 * Variable Table Handling functions
512 */
513typedef enum
514{
515 vt_none,
516 vt_address,
517 vt_attrib,
518 vt_param,
519 vt_temp,
520 vt_output,
521 vt_alias
522} var_type;
523
524
Brian Paul7aebaf32005-10-30 21:23:23 +0000525/**
526 * Setting an explicit field for each of the binding properties is a bit
527 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000528 */
529struct var_cache
530{
Brian Paul6a769d92006-04-28 15:42:15 +0000531 const GLubyte *name; /* don't free() - no need */
Jouk Jansen40322e12004-04-05 08:50:36 +0000532 var_type type;
533 GLuint address_binding; /* The index of the address register we should
534 * be using */
535 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
Jouk Jansen40322e12004-04-05 08:50:36 +0000536 GLuint attrib_is_generic; /* If the attrib was specified through a generic
537 * vertex attrib */
538 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000539 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000540 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
541 * that this is aliased to */
542 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
543 * PROGRAM_ENV_PARAM} */
544 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
545 * the tokens representing our bound state (or constants)
546 * start */
547 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
548 * we take up with our state tokens or constants. Note that
549 * this is _not_ the same as the number of param registers
550 * we eventually use */
551 struct var_cache *next;
552};
553
554static GLvoid
555var_cache_create (struct var_cache **va)
556{
557 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
558 if (*va) {
559 (**va).name = NULL;
560 (**va).type = vt_none;
561 (**va).attrib_binding = ~0;
562 (**va).attrib_is_generic = 0;
563 (**va).temp_binding = ~0;
564 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000565 (**va).param_binding_type = ~0;
566 (**va).param_binding_begin = ~0;
567 (**va).param_binding_length = ~0;
568 (**va).alias_binding = NULL;
569 (**va).next = NULL;
570 }
571}
572
573static GLvoid
574var_cache_destroy (struct var_cache **va)
575{
576 if (*va) {
577 var_cache_destroy (&(**va).next);
578 _mesa_free (*va);
579 *va = NULL;
580 }
581}
582
583static GLvoid
584var_cache_append (struct var_cache **va, struct var_cache *nv)
585{
586 if (*va)
587 var_cache_append (&(**va).next, nv);
588 else
589 *va = nv;
590}
591
592static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000593var_cache_find (struct var_cache *va, const GLubyte * name)
Jouk Jansen40322e12004-04-05 08:50:36 +0000594{
Brian Paul0a360cf2005-01-17 01:21:03 +0000595 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000596
597 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000598 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000599 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000600 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000601 return va;
602 }
603
604 va = va->next;
605 }
606
607 return NULL;
608}
609
Brian Paula088f162006-09-05 23:08:51 +0000610
611
612/**
613 * Called when an error is detected while parsing/compiling a program.
614 * Sets the ctx->Program.ErrorString field to descript and records a
615 * GL_INVALID_OPERATION error.
616 * \param position position of error in program string
617 * \param descrip verbose error description
618 */
619static void
620program_error(GLcontext *ctx, GLint position, const char *descrip)
621{
622 if (descrip) {
623 const char *prefix = "glProgramString(", *suffix = ")";
624 char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
625 _mesa_strlen(prefix) +
626 _mesa_strlen(suffix) + 1);
627 if (str) {
628 _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
629 _mesa_error(ctx, GL_INVALID_OPERATION, str);
630 _mesa_free(str);
631 }
632 }
633 _mesa_set_program_error(ctx, position, descrip);
634}
635
636
637
Jouk Jansen40322e12004-04-05 08:50:36 +0000638/**
639 * constructs an integer from 4 GLubytes in LE format
640 */
641static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000642parse_position (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000643{
644 GLuint value;
645
646 value = (GLuint) (*(*inst)++);
647 value += (GLuint) (*(*inst)++) * 0x100;
648 value += (GLuint) (*(*inst)++) * 0x10000;
649 value += (GLuint) (*(*inst)++) * 0x1000000;
650
651 return value;
652}
653
654/**
655 * This will, given a string, lookup the string as a variable name in the
656 * var cache. If the name is found, the var cache node corresponding to the
657 * var name is returned. If it is not found, a new entry is allocated
658 *
659 * \param I Points into the binary array where the string identifier begins
660 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
661 * \return The location on the var_cache corresponding the the string starting at I
662 */
663static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000664parse_string (const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +0000665 struct arb_program *Program, GLuint * found)
666{
Brian Paula088f162006-09-05 23:08:51 +0000667 const GLubyte *i = *inst;
Jouk Jansen40322e12004-04-05 08:50:36 +0000668 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000669 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000670
671 *inst += _mesa_strlen ((char *) i) + 1;
672
673 va = var_cache_find (*vc_head, i);
674
675 if (va) {
676 *found = 1;
677 return va;
678 }
679
680 *found = 0;
681 var_cache_create (&va);
Brian Paul6a769d92006-04-28 15:42:15 +0000682 va->name = (const GLubyte *) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000683
684 var_cache_append (vc_head, va);
685
686 return va;
687}
688
689static char *
Brian Paula088f162006-09-05 23:08:51 +0000690parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000691{
Brian Paula088f162006-09-05 23:08:51 +0000692 const GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000693 (void) Program;
694
Jouk Jansen40322e12004-04-05 08:50:36 +0000695 *inst += _mesa_strlen ((char *) i) + 1;
696
697 return (char *) i;
698}
699
700/**
Brian Paul05908952004-06-08 15:20:23 +0000701 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000702 */
Brian Paul05908952004-06-08 15:20:23 +0000703static GLint
Brian Paula088f162006-09-05 23:08:51 +0000704parse_sign (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000705{
706 /*return *(*inst)++ != '+'; */
707
708 if (**inst == '-') {
709 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000710 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000711 }
712 else if (**inst == '+') {
713 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000714 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000715 }
716
Brian Paul05908952004-06-08 15:20:23 +0000717 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000718}
719
720/**
721 * parses and returns signed integer
722 */
723static GLint
Brian Paula088f162006-09-05 23:08:51 +0000724parse_integer (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000725{
726 GLint sign;
727 GLint value;
728
729 /* check if *inst points to '+' or '-'
730 * if yes, grab the sign and increment *inst
731 */
732 sign = parse_sign (inst);
733
734 /* now check if *inst points to 0
735 * if yes, increment the *inst and return the default value
736 */
737 if (**inst == 0) {
738 (*inst)++;
739 return 0;
740 }
741
742 /* parse the integer as you normally would do it */
743 value = _mesa_atoi (parse_string_without_adding (inst, Program));
744
745 /* now, after terminating 0 there is a position
746 * to parse it - parse_position()
747 */
748 Program->Position = parse_position (inst);
749
Brian Paul05908952004-06-08 15:20:23 +0000750 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000751}
752
753/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000754 Accumulate this string of digits, and return them as
755 a large integer represented in floating point (for range).
756 If scale is not NULL, also accumulates a power-of-ten
757 integer scale factor that represents the number of digits
758 in the string.
759*/
760static GLdouble
Brian Paula088f162006-09-05 23:08:51 +0000761parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
Brian Paul1ff8f502005-02-16 15:08:29 +0000762{
763 GLdouble value = 0.0;
764 GLdouble oscale = 1.0;
765
766 if (**inst == 0) { /* this string of digits is empty-- do nothing */
767 (*inst)++;
768 }
769 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000770 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000771 GLubyte digit = *((*inst)++);
772 value = value * 10.0 + (GLint) (digit - '0');
773 oscale *= 10.0;
774 }
775 assert(**inst == 0); /* integer string should end with 0 */
776 (*inst)++; /* skip over terminating 0 */
777 Program->Position = parse_position(inst); /* skip position (from integer) */
778 }
779 if (scale)
780 *scale = oscale;
781 return value;
782}
783
784/**
785 Parse an unsigned floating-point number from this stream of tokenized
786 characters. Example floating-point formats supported:
787 12.34
788 12
789 0.34
790 .34
791 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000792 */
793static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000794parse_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000795{
Brian Paul1ff8f502005-02-16 15:08:29 +0000796 GLint exponent;
797 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000798
Brian Paul1ff8f502005-02-16 15:08:29 +0000799 whole = parse_float_string(inst, Program, 0);
800 fraction = parse_float_string(inst, Program, &fracScale);
801
802 /* Parse signed exponent */
803 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000804
Brian Paul1ff8f502005-02-16 15:08:29 +0000805 /* Assemble parts of floating-point number: */
806 return (GLfloat) ((whole + fraction / fracScale) *
807 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000808}
809
810
811/**
812 */
813static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000814parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000815{
Brian Paul05908952004-06-08 15:20:23 +0000816 GLint sign = parse_sign (inst);
817 GLfloat value = parse_float (inst, Program);
818 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000819}
820
821/**
822 * This picks out a constant value from the parsed array. The constant vector is r
823 * returned in the *values array, which should be of length 4.
824 *
825 * \param values - The 4 component vector with the constant value in it
826 */
827static GLvoid
Brian Paula088f162006-09-05 23:08:51 +0000828parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000829 GLboolean use)
830{
831 GLuint components, i;
832
833
834 switch (*(*inst)++) {
835 case CONSTANT_SCALAR:
836 if (use == GL_TRUE) {
837 values[0] =
838 values[1] =
839 values[2] = values[3] = parse_float (inst, Program);
840 }
841 else {
842 values[0] =
843 values[1] =
844 values[2] = values[3] = parse_signed_float (inst, Program);
845 }
846
847 break;
848 case CONSTANT_VECTOR:
849 values[0] = values[1] = values[2] = 0;
850 values[3] = 1;
851 components = *(*inst)++;
852 for (i = 0; i < components; i++) {
853 values[i] = parse_signed_float (inst, Program);
854 }
855 break;
856 }
857}
858
859/**
860 * \param offset The offset from the address register that we should
861 * address
862 *
863 * \return 0 on sucess, 1 on error
864 */
865static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000866parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
867 struct arb_program *Program, GLint *offset)
Jouk Jansen40322e12004-04-05 08:50:36 +0000868{
Brian Paul6a769d92006-04-28 15:42:15 +0000869 (void) ctx;
Jouk Jansen40322e12004-04-05 08:50:36 +0000870 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000871 return 0;
872}
873
874/**
875 * \param color 0 if color type is primary, 1 if color type is secondary
876 * \return 0 on sucess, 1 on error
877 */
878static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000879parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000880 GLint * color)
881{
Brian Paula6c423d2004-08-25 15:59:48 +0000882 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000883 *color = *(*inst)++ != COLOR_PRIMARY;
884 return 0;
885}
886
887/**
888 * Get an integer corresponding to a generic vertex attribute.
889 *
890 * \return 0 on sucess, 1 on error
891 */
892static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000893parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000894 struct arb_program *Program, GLuint *attrib)
895{
Brian Paulbd997cd2004-07-20 21:12:56 +0000896 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000897
Michal Krolbb38cad2006-04-11 11:41:11 +0000898 if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000899 {
Brian Paula088f162006-09-05 23:08:51 +0000900 program_error(ctx, Program->Position,
901 "Invalid generic vertex attribute index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000902 return 1;
903 }
904
Brian Paulbd997cd2004-07-20 21:12:56 +0000905 *attrib = (GLuint) i;
906
Jouk Jansen40322e12004-04-05 08:50:36 +0000907 return 0;
908}
909
910
911/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000912 * \param color The index of the color buffer to write into
913 * \return 0 on sucess, 1 on error
914 */
915static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000916parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
Brian Paulbe76b7f2004-10-04 14:40:05 +0000917 struct arb_program *Program, GLuint * color)
918{
919 GLint i = parse_integer (inst, Program);
920
921 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
Brian Paula088f162006-09-05 23:08:51 +0000922 program_error(ctx, Program->Position, "Invalid draw buffer index");
Brian Paulbe76b7f2004-10-04 14:40:05 +0000923 return 1;
924 }
925
926 *color = (GLuint) i;
927 return 0;
928}
929
930
931/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000932 * \param coord The texture unit index
933 * \return 0 on sucess, 1 on error
934 */
935static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000936parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000937 struct arb_program *Program, GLuint * coord)
938{
Brian Paulbd997cd2004-07-20 21:12:56 +0000939 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000940
Brian Paula6c423d2004-08-25 15:59:48 +0000941 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Brian Paula088f162006-09-05 23:08:51 +0000942 program_error(ctx, Program->Position, "Invalid texture unit index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000943 return 1;
944 }
945
Brian Paulbd997cd2004-07-20 21:12:56 +0000946 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000947 return 0;
948}
949
950/**
951 * \param coord The weight index
952 * \return 0 on sucess, 1 on error
953 */
954static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000955parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000956 GLint * coord)
957{
958 *coord = parse_integer (inst, Program);
959
960 if ((*coord < 0) || (*coord >= 1)) {
Brian Paula088f162006-09-05 23:08:51 +0000961 program_error(ctx, Program->Position, "Invalid weight index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000962 return 1;
963 }
964
965 return 0;
966}
967
968/**
969 * \param coord The clip plane index
970 * \return 0 on sucess, 1 on error
971 */
972static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000973parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000974 struct arb_program *Program, GLint * coord)
975{
976 *coord = parse_integer (inst, Program);
977
978 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
Brian Paula088f162006-09-05 23:08:51 +0000979 program_error(ctx, Program->Position, "Invalid clip plane index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000980 return 1;
981 }
982
983 return 0;
984}
985
986
987/**
988 * \return 0 on front face, 1 on back face
989 */
990static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000991parse_face_type (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000992{
993 switch (*(*inst)++) {
994 case FACE_FRONT:
995 return 0;
996
997 case FACE_BACK:
998 return 1;
999 }
1000 return 0;
1001}
1002
1003
1004/**
1005 * Given a matrix and a modifier token on the binary array, return tokens
1006 * that _mesa_fetch_state() [program.c] can understand.
1007 *
1008 * \param matrix - the matrix we are talking about
1009 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
1010 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
1011 * \return 0 on sucess, 1 on failure
1012 */
1013static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001014parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +00001015 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
1016{
1017 GLubyte mat = *(*inst)++;
1018
1019 *matrix_idx = 0;
1020
1021 switch (mat) {
1022 case MATRIX_MODELVIEW:
Brian65319522007-02-21 11:08:21 -07001023 *matrix = STATE_MODELVIEW_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001024 *matrix_idx = parse_integer (inst, Program);
1025 if (*matrix_idx > 0) {
Brian Paula088f162006-09-05 23:08:51 +00001026 program_error(ctx, Program->Position,
1027 "ARB_vertex_blend not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001028 return 1;
1029 }
1030 break;
1031
1032 case MATRIX_PROJECTION:
Brian65319522007-02-21 11:08:21 -07001033 *matrix = STATE_PROJECTION_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001034 break;
1035
1036 case MATRIX_MVP:
Brian65319522007-02-21 11:08:21 -07001037 *matrix = STATE_MVP_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001038 break;
1039
1040 case MATRIX_TEXTURE:
Brian65319522007-02-21 11:08:21 -07001041 *matrix = STATE_TEXTURE_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001042 *matrix_idx = parse_integer (inst, Program);
1043 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
Brian Paula088f162006-09-05 23:08:51 +00001044 program_error(ctx, Program->Position, "Invalid Texture Unit");
1045 /* bad *matrix_id */
Jouk Jansen40322e12004-04-05 08:50:36 +00001046 return 1;
1047 }
1048 break;
1049
1050 /* This is not currently supported (ARB_matrix_palette) */
1051 case MATRIX_PALETTE:
1052 *matrix_idx = parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001053 program_error(ctx, Program->Position,
1054 "ARB_matrix_palette not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001055 return 1;
1056 break;
1057
1058 case MATRIX_PROGRAM:
Brian65319522007-02-21 11:08:21 -07001059 *matrix = STATE_PROGRAM_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001060 *matrix_idx = parse_integer (inst, Program);
1061 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
Brian Paula088f162006-09-05 23:08:51 +00001062 program_error(ctx, Program->Position, "Invalid Program Matrix");
1063 /* bad *matrix_idx */
Jouk Jansen40322e12004-04-05 08:50:36 +00001064 return 1;
1065 }
1066 break;
1067 }
1068
1069 switch (*(*inst)++) {
1070 case MATRIX_MODIFIER_IDENTITY:
1071 *matrix_modifier = 0;
1072 break;
1073 case MATRIX_MODIFIER_INVERSE:
1074 *matrix_modifier = STATE_MATRIX_INVERSE;
1075 break;
1076 case MATRIX_MODIFIER_TRANSPOSE:
1077 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1078 break;
1079 case MATRIX_MODIFIER_INVTRANS:
1080 *matrix_modifier = STATE_MATRIX_INVTRANS;
1081 break;
1082 }
1083
1084 return 0;
1085}
1086
1087
1088/**
1089 * This parses a state string (rather, the binary version of it) into
1090 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1091 *
1092 * \param inst - the start in the binary arry to start working from
1093 * \param state_tokens - the storage for the 6-token state description
1094 * \return - 0 on sucess, 1 on error
1095 */
1096static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001097parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001098 struct arb_program *Program,
1099 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001100{
1101 switch (*(*inst)++) {
1102 case STATE_MATERIAL_PARSER:
1103 state_tokens[0] = STATE_MATERIAL;
1104 state_tokens[1] = parse_face_type (inst);
1105 switch (*(*inst)++) {
1106 case MATERIAL_AMBIENT:
1107 state_tokens[2] = STATE_AMBIENT;
1108 break;
1109 case MATERIAL_DIFFUSE:
1110 state_tokens[2] = STATE_DIFFUSE;
1111 break;
1112 case MATERIAL_SPECULAR:
1113 state_tokens[2] = STATE_SPECULAR;
1114 break;
1115 case MATERIAL_EMISSION:
1116 state_tokens[2] = STATE_EMISSION;
1117 break;
1118 case MATERIAL_SHININESS:
1119 state_tokens[2] = STATE_SHININESS;
1120 break;
1121 }
1122 break;
1123
1124 case STATE_LIGHT_PARSER:
1125 state_tokens[0] = STATE_LIGHT;
1126 state_tokens[1] = parse_integer (inst, Program);
1127
1128 /* Check the value of state_tokens[1] against the # of lights */
1129 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001130 program_error(ctx, Program->Position, "Invalid Light Number");
1131 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001132 return 1;
1133 }
1134
1135 switch (*(*inst)++) {
1136 case LIGHT_AMBIENT:
1137 state_tokens[2] = STATE_AMBIENT;
1138 break;
1139 case LIGHT_DIFFUSE:
1140 state_tokens[2] = STATE_DIFFUSE;
1141 break;
1142 case LIGHT_SPECULAR:
1143 state_tokens[2] = STATE_SPECULAR;
1144 break;
1145 case LIGHT_POSITION:
1146 state_tokens[2] = STATE_POSITION;
1147 break;
1148 case LIGHT_ATTENUATION:
1149 state_tokens[2] = STATE_ATTENUATION;
1150 break;
1151 case LIGHT_HALF:
Brianf958aab2007-02-21 15:23:11 -07001152 state_tokens[2] = STATE_HALF_VECTOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001153 break;
1154 case LIGHT_SPOT_DIRECTION:
1155 state_tokens[2] = STATE_SPOT_DIRECTION;
1156 break;
1157 }
1158 break;
1159
1160 case STATE_LIGHT_MODEL:
1161 switch (*(*inst)++) {
1162 case LIGHT_MODEL_AMBIENT:
1163 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1164 break;
1165 case LIGHT_MODEL_SCENECOLOR:
1166 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1167 state_tokens[1] = parse_face_type (inst);
1168 break;
1169 }
1170 break;
1171
1172 case STATE_LIGHT_PROD:
1173 state_tokens[0] = STATE_LIGHTPROD;
1174 state_tokens[1] = parse_integer (inst, Program);
1175
1176 /* Check the value of state_tokens[1] against the # of lights */
1177 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001178 program_error(ctx, Program->Position, "Invalid Light Number");
1179 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001180 return 1;
1181 }
1182
1183 state_tokens[2] = parse_face_type (inst);
1184 switch (*(*inst)++) {
1185 case LIGHT_PROD_AMBIENT:
1186 state_tokens[3] = STATE_AMBIENT;
1187 break;
1188 case LIGHT_PROD_DIFFUSE:
1189 state_tokens[3] = STATE_DIFFUSE;
1190 break;
1191 case LIGHT_PROD_SPECULAR:
1192 state_tokens[3] = STATE_SPECULAR;
1193 break;
1194 }
1195 break;
1196
1197
1198 case STATE_FOG:
1199 switch (*(*inst)++) {
1200 case FOG_COLOR:
Brianf1390a32007-02-23 17:11:01 -07001201 state_tokens[0] = STATE_FOG_COLOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001202 break;
1203 case FOG_PARAMS:
Brianf1390a32007-02-23 17:11:01 -07001204 state_tokens[0] = STATE_FOG_PARAMS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001205 break;
1206 }
1207 break;
1208
1209 case STATE_TEX_ENV:
1210 state_tokens[1] = parse_integer (inst, Program);
1211 switch (*(*inst)++) {
1212 case TEX_ENV_COLOR:
1213 state_tokens[0] = STATE_TEXENV_COLOR;
1214 break;
1215 }
1216 break;
1217
1218 case STATE_TEX_GEN:
1219 {
1220 GLuint type, coord;
1221
1222 state_tokens[0] = STATE_TEXGEN;
1223 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1224
1225 if (parse_texcoord_num (ctx, inst, Program, &coord))
1226 return 1;
1227 state_tokens[1] = coord;
1228
1229 /* EYE or OBJECT */
1230 type = *(*inst++);
1231
1232 /* 0 - s, 1 - t, 2 - r, 3 - q */
1233 coord = *(*inst++);
1234
1235 if (type == TEX_GEN_EYE) {
1236 switch (coord) {
1237 case COMPONENT_X:
1238 state_tokens[2] = STATE_TEXGEN_EYE_S;
1239 break;
1240 case COMPONENT_Y:
1241 state_tokens[2] = STATE_TEXGEN_EYE_T;
1242 break;
1243 case COMPONENT_Z:
1244 state_tokens[2] = STATE_TEXGEN_EYE_R;
1245 break;
1246 case COMPONENT_W:
1247 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1248 break;
1249 }
1250 }
1251 else {
1252 switch (coord) {
1253 case COMPONENT_X:
1254 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1255 break;
1256 case COMPONENT_Y:
1257 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1258 break;
1259 case COMPONENT_Z:
1260 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1261 break;
1262 case COMPONENT_W:
1263 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1264 break;
1265 }
1266 }
1267 }
1268 break;
1269
1270 case STATE_DEPTH:
1271 switch (*(*inst)++) {
1272 case DEPTH_RANGE:
1273 state_tokens[0] = STATE_DEPTH_RANGE;
1274 break;
1275 }
1276 break;
1277
1278 case STATE_CLIP_PLANE:
1279 state_tokens[0] = STATE_CLIPPLANE;
1280 state_tokens[1] = parse_integer (inst, Program);
Brianaa9d22a2007-02-23 11:21:03 -07001281 if (parse_clipplane_num (ctx, inst, Program,
1282 (GLint *) &state_tokens[1]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001283 return 1;
1284 break;
1285
1286 case STATE_POINT:
1287 switch (*(*inst++)) {
1288 case POINT_SIZE:
Brian776bc9c2007-02-22 09:29:46 -07001289 state_tokens[0] = STATE_POINT_SIZE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001290 break;
1291
1292 case POINT_ATTENUATION:
Brian776bc9c2007-02-22 09:29:46 -07001293 state_tokens[0] = STATE_POINT_ATTENUATION;
Jouk Jansen40322e12004-04-05 08:50:36 +00001294 break;
1295 }
1296 break;
1297
1298 /* XXX: I think this is the correct format for a matrix row */
1299 case STATE_MATRIX_ROWS:
Brianaa9d22a2007-02-23 11:21:03 -07001300 if (parse_matrix(ctx, inst, Program,
1301 (GLint *) &state_tokens[0],
1302 (GLint *) &state_tokens[1],
1303 (GLint *) &state_tokens[4]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001304 return 1;
1305
Brian65319522007-02-21 11:08:21 -07001306 state_tokens[2] = parse_integer (inst, Program); /* The first row to grab */
Jouk Jansen40322e12004-04-05 08:50:36 +00001307
1308 if ((**inst) != 0) { /* Either the last row, 0 */
Brian65319522007-02-21 11:08:21 -07001309 state_tokens[3] = parse_integer (inst, Program);
1310 if (state_tokens[3] < state_tokens[2]) {
Brian Paula088f162006-09-05 23:08:51 +00001311 program_error(ctx, Program->Position,
1312 "Second matrix index less than the first");
1313 /* state_tokens[4] vs. state_tokens[3] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001314 return 1;
1315 }
1316 }
1317 else {
Brian65319522007-02-21 11:08:21 -07001318 state_tokens[3] = state_tokens[2];
Jouk Jansen40322e12004-04-05 08:50:36 +00001319 (*inst)++;
1320 }
1321 break;
1322 }
1323
1324 return 0;
1325}
1326
1327/**
1328 * This parses a state string (rather, the binary version of it) into
1329 * a 6-token similar for the state fetching code in program.c
1330 *
1331 * One might ask, why fetch these parameters into just like you fetch
1332 * state when they are already stored in other places?
1333 *
1334 * Because of array offsets -> We can stick env/local parameters in the
1335 * middle of a parameter array and then index someplace into the array
1336 * when we execute.
1337 *
1338 * One optimization might be to only do this for the cases where the
1339 * env/local parameters end up inside of an array, and leave the
1340 * single parameters (or arrays of pure env/local pareameters) in their
1341 * respective register files.
1342 *
1343 * For ENV parameters, the format is:
1344 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1345 * state_tokens[1] = STATE_ENV
1346 * state_tokens[2] = the parameter index
1347 *
1348 * for LOCAL parameters, the format is:
1349 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1350 * state_tokens[1] = STATE_LOCAL
1351 * state_tokens[2] = the parameter index
1352 *
1353 * \param inst - the start in the binary arry to start working from
1354 * \param state_tokens - the storage for the 6-token state description
1355 * \return - 0 on sucess, 1 on failure
1356 */
1357static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001358parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001359 struct arb_program *Program,
1360 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001361{
1362 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1363 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1364 else
1365 state_tokens[0] = STATE_VERTEX_PROGRAM;
1366
1367
1368 switch (*(*inst)++) {
1369 case PROGRAM_PARAM_ENV:
1370 state_tokens[1] = STATE_ENV;
1371 state_tokens[2] = parse_integer (inst, Program);
1372
1373 /* Check state_tokens[2] against the number of ENV parameters available */
1374 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001375 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001376 ||
1377 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001378 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001379 program_error(ctx, Program->Position,
1380 "Invalid Program Env Parameter");
1381 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001382 return 1;
1383 }
1384
1385 break;
1386
1387 case PROGRAM_PARAM_LOCAL:
1388 state_tokens[1] = STATE_LOCAL;
1389 state_tokens[2] = parse_integer (inst, Program);
1390
1391 /* Check state_tokens[2] against the number of LOCAL parameters available */
1392 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001393 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001394 ||
1395 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001396 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001397 program_error(ctx, Program->Position,
1398 "Invalid Program Local Parameter");
1399 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001400 return 1;
1401 }
1402 break;
1403 }
1404
1405 return 0;
1406}
1407
1408/**
1409 * For ARB_vertex_program, programs are not allowed to use both an explicit
1410 * vertex attribute and a generic vertex attribute corresponding to the same
1411 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1412 *
1413 * This will walk our var_cache and make sure that nobody does anything fishy.
1414 *
1415 * \return 0 on sucess, 1 on error
1416 */
1417static GLuint
1418generic_attrib_check(struct var_cache *vc_head)
1419{
1420 int a;
1421 struct var_cache *curr;
1422 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1423 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1424
1425 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1426 explicitAttrib[a] = GL_FALSE;
1427 genericAttrib[a] = GL_FALSE;
1428 }
1429
1430 curr = vc_head;
1431 while (curr) {
1432 if (curr->type == vt_attrib) {
1433 if (curr->attrib_is_generic)
Brian Paul18e7c5c2005-10-30 21:46:00 +00001434 genericAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001435 else
Brian Paul18e7c5c2005-10-30 21:46:00 +00001436 explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001437 }
1438
1439 curr = curr->next;
1440 }
1441
1442 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1443 if ((explicitAttrib[a]) && (genericAttrib[a]))
1444 return 1;
1445 }
1446
1447 return 0;
1448}
1449
1450/**
1451 * This will handle the binding side of an ATTRIB var declaration
1452 *
Brian Paul18e7c5c2005-10-30 21:46:00 +00001453 * \param inputReg returns the input register index, one of the
1454 * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
Brian Paula088f162006-09-05 23:08:51 +00001455 * \return returns 0 on success, 1 on error
Jouk Jansen40322e12004-04-05 08:50:36 +00001456 */
1457static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001458parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
Brian Paul18e7c5c2005-10-30 21:46:00 +00001459 struct arb_program *Program,
1460 GLuint *inputReg, GLuint *is_generic)
Jouk Jansen40322e12004-04-05 08:50:36 +00001461{
Jouk Jansen40322e12004-04-05 08:50:36 +00001462 GLint err = 0;
1463
1464 *is_generic = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001465
Jouk Jansen40322e12004-04-05 08:50:36 +00001466 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1467 switch (*(*inst)++) {
1468 case FRAGMENT_ATTRIB_COLOR:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001469 {
1470 GLint coord;
1471 err = parse_color_type (ctx, inst, Program, &coord);
1472 *inputReg = FRAG_ATTRIB_COL0 + coord;
1473 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001474 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001475 case FRAGMENT_ATTRIB_TEXCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001476 {
Brian8fa6f732007-02-01 09:24:41 -07001477 GLuint texcoord = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001478 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1479 *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
1480 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001481 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001482 case FRAGMENT_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001483 *inputReg = FRAG_ATTRIB_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001484 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001485 case FRAGMENT_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001486 *inputReg = FRAG_ATTRIB_WPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001487 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001488 default:
1489 err = 1;
1490 break;
1491 }
1492 }
1493 else {
1494 switch (*(*inst)++) {
1495 case VERTEX_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001496 *inputReg = VERT_ATTRIB_POS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001497 break;
1498
1499 case VERTEX_ATTRIB_WEIGHT:
1500 {
1501 GLint weight;
Jouk Jansen40322e12004-04-05 08:50:36 +00001502 err = parse_weight_num (ctx, inst, Program, &weight);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001503 *inputReg = VERT_ATTRIB_WEIGHT;
Brian Paul3a557502006-09-05 23:15:29 +00001504#if 1
1505 /* hack for Warcraft (see bug 8060) */
1506 _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
Brian Pauld9aebd82006-09-06 05:03:47 +00001507 break;
Brian Paul3a557502006-09-05 23:15:29 +00001508#else
Brian Paula088f162006-09-05 23:08:51 +00001509 program_error(ctx, Program->Position,
1510 "ARB_vertex_blend not supported");
Brian Pauld9aebd82006-09-06 05:03:47 +00001511 return 1;
Brian Paul3a557502006-09-05 23:15:29 +00001512#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00001513 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001514
1515 case VERTEX_ATTRIB_NORMAL:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001516 *inputReg = VERT_ATTRIB_NORMAL;
Jouk Jansen40322e12004-04-05 08:50:36 +00001517 break;
1518
1519 case VERTEX_ATTRIB_COLOR:
1520 {
1521 GLint color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001522 err = parse_color_type (ctx, inst, Program, &color);
1523 if (color) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001524 *inputReg = VERT_ATTRIB_COLOR1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001525 }
1526 else {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001527 *inputReg = VERT_ATTRIB_COLOR0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001528 }
1529 }
1530 break;
1531
1532 case VERTEX_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001533 *inputReg = VERT_ATTRIB_FOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00001534 break;
1535
1536 case VERTEX_ATTRIB_TEXCOORD:
1537 {
Brian8fa6f732007-02-01 09:24:41 -07001538 GLuint unit = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001539 err = parse_texcoord_num (ctx, inst, Program, &unit);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001540 *inputReg = VERT_ATTRIB_TEX0 + unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001541 }
1542 break;
1543
Jouk Jansen40322e12004-04-05 08:50:36 +00001544 case VERTEX_ATTRIB_MATRIXINDEX:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001545 /* Not supported at this time */
1546 {
1547 const char *msg = "ARB_palette_matrix not supported";
1548 parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001549 program_error(ctx, Program->Position, msg);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001550 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001551 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001552
1553 case VERTEX_ATTRIB_GENERIC:
1554 {
1555 GLuint attrib;
Tilman Sauerbeck6c334752006-06-28 16:26:20 +00001556 err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
Brian Paula088f162006-09-05 23:08:51 +00001557 if (!err) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001558 *is_generic = 1;
Brian Paul095c6692006-04-25 00:21:32 +00001559 /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
1560 * attributes do not alias the conventional vertex
1561 * attributes.
1562 */
1563 if (attrib > 0)
1564 *inputReg = attrib + VERT_ATTRIB_GENERIC0;
Brian Paul919f6a02006-05-29 14:37:56 +00001565 else
1566 *inputReg = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001567 }
1568 }
1569 break;
1570
1571 default:
1572 err = 1;
1573 break;
1574 }
1575 }
1576
Jouk Jansen40322e12004-04-05 08:50:36 +00001577 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00001578 program_error(ctx, Program->Position, "Bad attribute binding");
Jouk Jansen40322e12004-04-05 08:50:36 +00001579 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001580
1581 return err;
1582}
1583
Brian Paul7aebaf32005-10-30 21:23:23 +00001584
Jouk Jansen40322e12004-04-05 08:50:36 +00001585/**
1586 * This translates between a binary token for an output variable type
1587 * and the mesa token for the same thing.
1588 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001589 * \param inst The parsed tokens
1590 * \param outputReg Returned index/number of the output register,
Brian Paul90ebb582005-11-02 18:06:12 +00001591 * one of the VERT_RESULT_* or FRAG_RESULT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001592 */
1593static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001594parse_result_binding(GLcontext *ctx, const GLubyte **inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00001595 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001596{
Brian Paul7aebaf32005-10-30 21:23:23 +00001597 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001598
Brian Paul7aebaf32005-10-30 21:23:23 +00001599 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001600 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001601 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001602 GLuint out_color;
1603
Brian Paulbe76b7f2004-10-04 14:40:05 +00001604 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001605 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001606 */
1607 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001608 ASSERT(out_color < MAX_DRAW_BUFFERS);
Brian Paul90ebb582005-11-02 18:06:12 +00001609 *outputReg = FRAG_RESULT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001610 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001611 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001612 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1613 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001614 }
1615 break;
1616
1617 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001618 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001619 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
Brian Paul90ebb582005-11-02 18:06:12 +00001620 *outputReg = FRAG_RESULT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001621 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001622 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001623 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001624 GLint color_type;
1625 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001626 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1627 if (err)
1628 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001629
Jouk Jansen40322e12004-04-05 08:50:36 +00001630 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001631 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001632 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001633 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001634 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001635 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001636 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001637 }
1638 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001639 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001640 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001641 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001642 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001643 }
1644 /* primary color */
1645 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001646 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001647 }
1648 }
1649 }
1650 break;
1651
1652 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001653 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001654 break;
1655
1656 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001657 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001658 break;
1659
1660 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001661 {
1662 GLuint unit;
1663 if (parse_texcoord_num (ctx, inst, Program, &unit))
1664 return 1;
1665 *outputReg = VERT_RESULT_TEX0 + unit;
1666 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001667 break;
1668 }
1669
Brian Paulde997602005-11-12 17:53:14 +00001670 Program->Base.OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001671
1672 return 0;
1673}
1674
Brian Paul7aebaf32005-10-30 21:23:23 +00001675
Jouk Jansen40322e12004-04-05 08:50:36 +00001676/**
1677 * This handles the declaration of ATTRIB variables
1678 *
1679 * XXX: Still needs
1680 * parse_vert_attrib_binding(), or something like that
1681 *
1682 * \return 0 on sucess, 1 on error
1683 */
1684static GLint
Brian Paula088f162006-09-05 23:08:51 +00001685parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001686 struct arb_program *Program)
1687{
1688 GLuint found;
1689 char *error_msg;
1690 struct var_cache *attrib_var;
1691
1692 attrib_var = parse_string (inst, vc_head, Program, &found);
1693 Program->Position = parse_position (inst);
1694 if (found) {
1695 error_msg = (char *)
1696 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07001697 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00001698 attrib_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001699 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001700 _mesa_free (error_msg);
1701 return 1;
1702 }
1703
1704 attrib_var->type = vt_attrib;
1705
Brian Paul7aebaf32005-10-30 21:23:23 +00001706 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
Brian Paul7aebaf32005-10-30 21:23:23 +00001707 &attrib_var->attrib_is_generic))
1708 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001709
Brian Paul7aebaf32005-10-30 21:23:23 +00001710 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00001711 program_error(ctx, Program->Position,
1712 "Cannot use both a generic vertex attribute "
1713 "and a specific attribute of the same type");
Brian Paul7aebaf32005-10-30 21:23:23 +00001714 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001715 }
1716
1717 Program->Base.NumAttributes++;
1718 return 0;
1719}
1720
1721/**
1722 * \param use -- TRUE if we're called when declaring implicit parameters,
1723 * FALSE if we're declaraing variables. This has to do with
1724 * if we get a signed or unsigned float for scalar constants
1725 */
1726static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001727parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00001728 struct var_cache *param_var,
1729 struct arb_program *Program, GLboolean use)
1730{
1731 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001732 GLuint err = 0;
Brianaa9d22a2007-02-23 11:21:03 -07001733 gl_state_index state_tokens[STATE_LENGTH];
Jouk Jansen40322e12004-04-05 08:50:36 +00001734 GLfloat const_values[4];
1735
Jouk Jansen40322e12004-04-05 08:50:36 +00001736 switch (*(*inst)++) {
1737 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001738 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1739 return 1;
1740
1741 /* If we adding STATE_MATRIX that has multiple rows, we need to
1742 * unroll it and call _mesa_add_state_reference() for each row
1743 */
Brian65319522007-02-21 11:08:21 -07001744 if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
1745 state_tokens[0] == STATE_PROJECTION_MATRIX ||
1746 state_tokens[0] == STATE_MVP_MATRIX ||
1747 state_tokens[0] == STATE_TEXTURE_MATRIX ||
1748 state_tokens[0] == STATE_PROGRAM_MATRIX)
1749 && (state_tokens[2] != state_tokens[3])) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001750 GLint row;
Brian65319522007-02-21 11:08:21 -07001751 const GLint first_row = state_tokens[2];
1752 const GLint last_row = state_tokens[3];
Jouk Jansen40322e12004-04-05 08:50:36 +00001753
1754 for (row = first_row; row <= last_row; row++) {
Brian65319522007-02-21 11:08:21 -07001755 state_tokens[2] = state_tokens[3] = row;
Jouk Jansen40322e12004-04-05 08:50:36 +00001756
Brian Paulde997602005-11-12 17:53:14 +00001757 idx = _mesa_add_state_reference(Program->Base.Parameters,
1758 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001759 if (param_var->param_binding_begin == ~0U)
1760 param_var->param_binding_begin = idx;
1761 param_var->param_binding_length++;
1762 Program->Base.NumParameters++;
1763 }
1764 }
1765 else {
Brian Paulde997602005-11-12 17:53:14 +00001766 idx = _mesa_add_state_reference(Program->Base.Parameters,
1767 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001768 if (param_var->param_binding_begin == ~0U)
1769 param_var->param_binding_begin = idx;
1770 param_var->param_binding_length++;
1771 Program->Base.NumParameters++;
1772 }
1773 break;
1774
1775 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001776 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1777 return 1;
Brian Paulde997602005-11-12 17:53:14 +00001778 idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001779 if (param_var->param_binding_begin == ~0U)
1780 param_var->param_binding_begin = idx;
1781 param_var->param_binding_length++;
1782 Program->Base.NumParameters++;
1783
1784 /* Check if there is more: 0 -> we're done, else its an integer */
1785 if (**inst) {
1786 GLuint out_of_range, new_idx;
1787 GLuint start_idx = state_tokens[2] + 1;
1788 GLuint end_idx = parse_integer (inst, Program);
1789
1790 out_of_range = 0;
1791 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1792 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001793 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001794 || ((state_tokens[1] == STATE_LOCAL)
1795 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001796 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001797 out_of_range = 1;
1798 }
1799 else {
1800 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001801 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001802 || ((state_tokens[1] == STATE_LOCAL)
1803 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001804 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001805 out_of_range = 1;
1806 }
1807 if (out_of_range) {
Brian Paula088f162006-09-05 23:08:51 +00001808 program_error(ctx, Program->Position,
1809 "Invalid Program Parameter"); /*end_idx*/
Jouk Jansen40322e12004-04-05 08:50:36 +00001810 return 1;
1811 }
1812
1813 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1814 state_tokens[2] = new_idx;
Brian Paulde997602005-11-12 17:53:14 +00001815 idx = _mesa_add_state_reference(Program->Base.Parameters,
1816 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001817 param_var->param_binding_length++;
1818 Program->Base.NumParameters++;
1819 }
1820 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001821 else {
1822 (*inst)++;
1823 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001824 break;
1825
1826 case PARAM_CONSTANT:
Brian7cbfe8c2008-01-18 12:45:55 -07001827 /* parsing something like {1.0, 2.0, 3.0, 4.0} */
Jouk Jansen40322e12004-04-05 08:50:36 +00001828 parse_constant (inst, const_values, Program, use);
Brian Paulde997602005-11-12 17:53:14 +00001829 idx = _mesa_add_named_constant(Program->Base.Parameters,
1830 (char *) param_var->name,
Brian Paul0c6723a2006-11-15 23:38:02 +00001831 const_values, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00001832 if (param_var->param_binding_begin == ~0U)
1833 param_var->param_binding_begin = idx;
Brian7cbfe8c2008-01-18 12:45:55 -07001834 param_var->param_binding_type = PROGRAM_CONSTANT;
Jouk Jansen40322e12004-04-05 08:50:36 +00001835 param_var->param_binding_length++;
1836 Program->Base.NumParameters++;
1837 break;
1838
1839 default:
Brian Paula088f162006-09-05 23:08:51 +00001840 program_error(ctx, Program->Position,
1841 "Unexpected token (in parse_param_elements())");
Jouk Jansen40322e12004-04-05 08:50:36 +00001842 return 1;
1843 }
1844
1845 /* Make sure we haven't blown past our parameter limits */
1846 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1847 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001848 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001849 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1850 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001851 ctx->Const.FragmentProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001852 program_error(ctx, Program->Position, "Too many parameter variables");
Jouk Jansen40322e12004-04-05 08:50:36 +00001853 return 1;
1854 }
1855
1856 return err;
1857}
1858
Brian Paul7aebaf32005-10-30 21:23:23 +00001859
Jouk Jansen40322e12004-04-05 08:50:36 +00001860/**
1861 * This picks out PARAM program parameter bindings.
1862 *
1863 * XXX: This needs to be stressed & tested
1864 *
1865 * \return 0 on sucess, 1 on error
1866 */
1867static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001868parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001869 struct arb_program *Program)
1870{
Brian Paulbd997cd2004-07-20 21:12:56 +00001871 GLuint found, err;
1872 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001873 struct var_cache *param_var;
1874
1875 err = 0;
1876 param_var = parse_string (inst, vc_head, Program, &found);
1877 Program->Position = parse_position (inst);
1878
1879 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001880 char *error_msg = (char *)
1881 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07001882 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00001883 param_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001884 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001885 _mesa_free (error_msg);
1886 return 1;
1887 }
1888
1889 specified_length = parse_integer (inst, Program);
1890
1891 if (specified_length < 0) {
Brian Paula088f162006-09-05 23:08:51 +00001892 program_error(ctx, Program->Position, "Negative parameter array length");
Jouk Jansen40322e12004-04-05 08:50:36 +00001893 return 1;
1894 }
1895
1896 param_var->type = vt_param;
1897 param_var->param_binding_length = 0;
1898
1899 /* Right now, everything is shoved into the main state register file.
1900 *
1901 * In the future, it would be nice to leave things ENV/LOCAL params
1902 * in their respective register files, if possible
1903 */
1904 param_var->param_binding_type = PROGRAM_STATE_VAR;
1905
1906 /* Remember to:
1907 * * - add each guy to the parameter list
1908 * * - increment the param_var->param_binding_len
1909 * * - store the param_var->param_binding_begin for the first one
1910 * * - compare the actual len to the specified len at the end
1911 */
1912 while (**inst != PARAM_NULL) {
1913 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1914 return 1;
1915 }
1916
1917 /* Test array length here! */
1918 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001919 if (specified_length != (int)param_var->param_binding_length) {
Brian Paula088f162006-09-05 23:08:51 +00001920 program_error(ctx, Program->Position,
1921 "Declared parameter array length does not match parameter list");
Jouk Jansen40322e12004-04-05 08:50:36 +00001922 }
1923 }
1924
1925 (*inst)++;
1926
1927 return 0;
1928}
1929
1930/**
1931 *
1932 */
1933static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001934parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001935 struct arb_program *Program, struct var_cache **new_var)
1936{
1937 struct var_cache *param_var;
1938
1939 /* First, insert a dummy entry into the var_cache */
1940 var_cache_create (&param_var);
Brian Paul6a769d92006-04-28 15:42:15 +00001941 param_var->name = (const GLubyte *) " ";
Jouk Jansen40322e12004-04-05 08:50:36 +00001942 param_var->type = vt_param;
1943
1944 param_var->param_binding_length = 0;
1945 /* Don't fill in binding_begin; We use the default value of -1
1946 * to tell if its already initialized, elsewhere.
1947 *
1948 * param_var->param_binding_begin = 0;
1949 */
1950 param_var->param_binding_type = PROGRAM_STATE_VAR;
1951
1952 var_cache_append (vc_head, param_var);
1953
1954 /* Then fill it with juicy parameter goodness */
1955 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1956 return 1;
1957
1958 *new_var = param_var;
1959
1960 return 0;
1961}
1962
1963
1964/**
1965 * This handles the declaration of TEMP variables
1966 *
1967 * \return 0 on sucess, 1 on error
1968 */
1969static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001970parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001971 struct arb_program *Program)
1972{
1973 GLuint found;
1974 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001975
1976 while (**inst != 0) {
1977 temp_var = parse_string (inst, vc_head, Program, &found);
1978 Program->Position = parse_position (inst);
1979 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001980 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001981 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07001982 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00001983 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00001984 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001985 _mesa_free (error_msg);
1986 return 1;
1987 }
1988
1989 temp_var->type = vt_temp;
1990
1991 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1992 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001993 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00001994 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
1995 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00001996 ctx->Const.VertexProgram.MaxTemps))) {
Brian Paula088f162006-09-05 23:08:51 +00001997 program_error(ctx, Program->Position,
1998 "Too many TEMP variables declared");
Jouk Jansen40322e12004-04-05 08:50:36 +00001999 return 1;
2000 }
2001
2002 temp_var->temp_binding = Program->Base.NumTemporaries;
2003 Program->Base.NumTemporaries++;
2004 }
2005 (*inst)++;
2006
2007 return 0;
2008}
2009
2010/**
2011 * This handles variables of the OUTPUT variety
2012 *
2013 * \return 0 on sucess, 1 on error
2014 */
2015static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002016parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002017 struct arb_program *Program)
2018{
2019 GLuint found;
2020 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00002021 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002022
2023 output_var = parse_string (inst, vc_head, Program, &found);
2024 Program->Position = parse_position (inst);
2025 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002026 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002027 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07002028 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00002029 output_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002030 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002031 _mesa_free (error_msg);
2032 return 1;
2033 }
2034
2035 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002036
2037 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2038 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002039}
2040
2041/**
2042 * This handles variables of the ALIAS kind
2043 *
2044 * \return 0 on sucess, 1 on error
2045 */
2046static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002047parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002048 struct arb_program *Program)
2049{
2050 GLuint found;
2051 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002052
2053 temp_var = parse_string (inst, vc_head, Program, &found);
2054 Program->Position = parse_position (inst);
2055
2056 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002057 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002058 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07002059 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00002060 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002061 program_error(ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002062 _mesa_free (error_msg);
2063 return 1;
2064 }
2065
2066 temp_var->type = vt_alias;
2067 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2068 Program->Position = parse_position (inst);
2069
2070 if (!found)
2071 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002072 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002073 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2074 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2075 temp_var->alias_binding->name);
Brian Paula088f162006-09-05 23:08:51 +00002076 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002077 _mesa_free (error_msg);
2078 return 1;
2079 }
2080
2081 return 0;
2082}
2083
2084/**
2085 * This handles variables of the ADDRESS kind
2086 *
2087 * \return 0 on sucess, 1 on error
2088 */
2089static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002090parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002091 struct arb_program *Program)
2092{
2093 GLuint found;
2094 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002095
2096 while (**inst != 0) {
2097 temp_var = parse_string (inst, vc_head, Program, &found);
2098 Program->Position = parse_position (inst);
2099 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002100 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002101 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
Brian06b019d2008-01-18 12:47:20 -07002102 _mesa_sprintf (error_msg, "Duplicate Variable Declaration: %s",
Jouk Jansen40322e12004-04-05 08:50:36 +00002103 temp_var->name);
Brian Paula088f162006-09-05 23:08:51 +00002104 program_error (ctx, Program->Position, error_msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002105 _mesa_free (error_msg);
2106 return 1;
2107 }
2108
2109 temp_var->type = vt_address;
2110
2111 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002112 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002113 const char *msg = "Too many ADDRESS variables declared";
Brian Paula088f162006-09-05 23:08:51 +00002114 program_error(ctx, Program->Position, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002115 return 1;
2116 }
2117
2118 temp_var->address_binding = Program->Base.NumAddressRegs;
2119 Program->Base.NumAddressRegs++;
2120 }
2121 (*inst)++;
2122
2123 return 0;
2124}
2125
2126/**
2127 * Parse a program declaration
2128 *
2129 * \return 0 on sucess, 1 on error
2130 */
2131static GLint
Brian Paula088f162006-09-05 23:08:51 +00002132parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002133 struct arb_program *Program)
2134{
2135 GLint err = 0;
2136
2137 switch (*(*inst)++) {
2138 case ADDRESS:
2139 err = parse_address (ctx, inst, vc_head, Program);
2140 break;
2141
2142 case ALIAS:
2143 err = parse_alias (ctx, inst, vc_head, Program);
2144 break;
2145
2146 case ATTRIB:
2147 err = parse_attrib (ctx, inst, vc_head, Program);
2148 break;
2149
2150 case OUTPUT:
2151 err = parse_output (ctx, inst, vc_head, Program);
2152 break;
2153
2154 case PARAM:
2155 err = parse_param (ctx, inst, vc_head, Program);
2156 break;
2157
2158 case TEMP:
2159 err = parse_temp (ctx, inst, vc_head, Program);
2160 break;
2161 }
2162
2163 return err;
2164}
2165
2166/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002167 * Handle the parsing out of a masked destination register, either for a
2168 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002169 *
2170 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002171 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002172 * position invariant
2173 *
2174 * \param File - The register file we write to
2175 * \param Index - The register index we write to
2176 * \param WriteMask - The mask controlling which components we write (1->write)
2177 *
2178 * \return 0 on sucess, 1 on error
2179 */
2180static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002181parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002182 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002183 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002184{
Brian Paul7aebaf32005-10-30 21:23:23 +00002185 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002186 struct var_cache *dst;
2187
2188 /* We either have a result register specified, or a
2189 * variable that may or may not be writable
2190 */
2191 switch (*(*inst)++) {
2192 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002193 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002194 return 1;
2195 *File = PROGRAM_OUTPUT;
2196 break;
2197
2198 case REGISTER_ESTABLISHED_NAME:
2199 dst = parse_string (inst, vc_head, Program, &result);
2200 Program->Position = parse_position (inst);
2201
2202 /* If the name has never been added to our symbol table, we're hosed */
2203 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002204 program_error(ctx, Program->Position, "0: Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002205 return 1;
2206 }
2207
2208 switch (dst->type) {
2209 case vt_output:
2210 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002211 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002212 break;
2213
2214 case vt_temp:
2215 *File = PROGRAM_TEMPORARY;
2216 *Index = dst->temp_binding;
2217 break;
2218
2219 /* If the var type is not vt_output or vt_temp, no go */
2220 default:
Brian Paula088f162006-09-05 23:08:51 +00002221 program_error(ctx, Program->Position,
2222 "Destination register is read only");
Jouk Jansen40322e12004-04-05 08:50:36 +00002223 return 1;
2224 }
2225 break;
2226
2227 default:
Brian Paula088f162006-09-05 23:08:51 +00002228 program_error(ctx, Program->Position,
2229 "Unexpected opcode in parse_masked_dst_reg()");
Jouk Jansen40322e12004-04-05 08:50:36 +00002230 return 1;
2231 }
2232
2233
2234 /* Position invariance test */
2235 /* This test is done now in syntax portion - when position invariance OPTION
2236 is specified, "result.position" rule is disabled so there is no way
2237 to write the position
2238 */
2239 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2240 (*Index == 0)) {
Brian Paula088f162006-09-05 23:08:51 +00002241 program_error(ctx, Program->Position,
Jouk Jansen40322e12004-04-05 08:50:36 +00002242 "Vertex program specified position invariance and wrote vertex position");
2243 }*/
2244
2245 /* And then the mask.
2246 * w,a -> bit 0
2247 * z,b -> bit 1
2248 * y,g -> bit 2
2249 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002250 *
2251 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002252 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002253 tmp = (GLint) *(*inst)++;
2254 *WriteMask = (((tmp>>3) & 0x1) |
2255 ((tmp>>1) & 0x2) |
2256 ((tmp<<1) & 0x4) |
2257 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002258
2259 return 0;
2260}
2261
2262
2263/**
2264 * Handle the parsing of a address register
2265 *
2266 * \param Index - The register index we write to
2267 *
2268 * \return 0 on sucess, 1 on error
2269 */
2270static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002271parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002272 struct var_cache **vc_head,
2273 struct arb_program *Program, GLint * Index)
2274{
2275 struct var_cache *dst;
2276 GLuint result;
Aapo Tahkola6fc864b2006-03-22 21:29:15 +00002277
2278 *Index = 0; /* XXX */
Jouk Jansen40322e12004-04-05 08:50:36 +00002279
2280 dst = parse_string (inst, vc_head, Program, &result);
2281 Program->Position = parse_position (inst);
2282
2283 /* If the name has never been added to our symbol table, we're hosed */
2284 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002285 program_error(ctx, Program->Position, "Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002286 return 1;
2287 }
2288
2289 if (dst->type != vt_address) {
Brian Paula088f162006-09-05 23:08:51 +00002290 program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
Jouk Jansen40322e12004-04-05 08:50:36 +00002291 return 1;
2292 }
2293
2294 return 0;
2295}
2296
Brian Paul8e8fa632005-07-01 02:03:33 +00002297#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002298/**
2299 * Handle the parsing out of a masked address register
2300 *
2301 * \param Index - The register index we write to
2302 * \param WriteMask - The mask controlling which components we write (1->write)
2303 *
2304 * \return 0 on sucess, 1 on error
2305 */
2306static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002307parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002308 struct var_cache **vc_head,
2309 struct arb_program *Program, GLint * Index,
2310 GLboolean * WriteMask)
2311{
2312 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2313 return 1;
2314
2315 /* This should be 0x8 */
2316 (*inst)++;
2317
2318 /* Writemask of .x is implied */
2319 WriteMask[0] = 1;
2320 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2321
2322 return 0;
2323}
Brian Paul8e8fa632005-07-01 02:03:33 +00002324#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002325
2326/**
2327 * Parse out a swizzle mask.
2328 *
Brian Paul32df89e2005-10-29 18:26:43 +00002329 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002330 *
2331 * The len parameter allows us to grab 4 components for a vector
2332 * swizzle, or just 1 component for a scalar src register selection
2333 */
Brian Paul32df89e2005-10-29 18:26:43 +00002334static void
Brian Paula088f162006-09-05 23:08:51 +00002335parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002336{
Brian Paul32df89e2005-10-29 18:26:43 +00002337 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002338
Brian Paul32df89e2005-10-29 18:26:43 +00002339 for (i = 0; i < 4; i++)
2340 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002341
Brian Paul32df89e2005-10-29 18:26:43 +00002342 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002343 switch (*(*inst)++) {
2344 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002345 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002346 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002347 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002348 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002349 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002350 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002351 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002352 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002353 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002354 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002355 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002356 default:
2357 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2358 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002359 }
2360 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002361}
2362
Jouk Jansen40322e12004-04-05 08:50:36 +00002363
Brian Paul32df89e2005-10-29 18:26:43 +00002364/**
2365 * Parse an extended swizzle mask which is a sequence of
2366 * four x/y/z/w/0/1 tokens.
2367 * \return swizzle four swizzle values
2368 * \return negateMask four element bitfield
2369 */
2370static void
Brian Paula088f162006-09-05 23:08:51 +00002371parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
Brian Paul32df89e2005-10-29 18:26:43 +00002372 GLubyte *negateMask)
2373{
2374 GLint i;
2375
2376 *negateMask = 0x0;
2377 for (i = 0; i < 4; i++) {
2378 GLubyte swz;
2379 if (parse_sign(inst) == -1)
2380 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002381
2382 swz = *(*inst)++;
2383
2384 switch (swz) {
2385 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002386 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002387 break;
2388 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002389 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002390 break;
2391 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002392 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002393 break;
2394 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002395 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002396 break;
2397 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002398 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002399 break;
2400 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002401 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002402 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002403 default:
2404 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2405 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002406 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002407 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002408}
2409
2410
2411static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002412parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
2413 struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002414 struct arb_program *Program,
2415 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002416 GLboolean *IsRelOffset )
2417{
2418 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002419 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002420 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002421
Keith Whitwell7c26b612005-04-21 14:46:57 +00002422 *IsRelOffset = 0;
2423
Jouk Jansen40322e12004-04-05 08:50:36 +00002424 /* And the binding for the src */
2425 switch (*(*inst)++) {
2426 case REGISTER_ATTRIB:
2427 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002428 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002429 return 1;
2430 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002431 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002432
2433 /* We need to insert a dummy variable into the var_cache so we can
2434 * catch generic vertex attrib aliasing errors
2435 */
2436 var_cache_create(&src);
2437 src->type = vt_attrib;
Brian Paul6a769d92006-04-28 15:42:15 +00002438 src->name = (const GLubyte *) "Dummy Attrib Variable";
Brian Paul18e7c5c2005-10-30 21:46:00 +00002439 src->attrib_binding = binding;
2440 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002441 var_cache_append(vc_head, src);
2442 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00002443 program_error(ctx, Program->Position,
2444 "Cannot use both a generic vertex attribute "
2445 "and a specific attribute of the same type");
Jouk Jansen40322e12004-04-05 08:50:36 +00002446 return 1;
2447 }
2448 break;
2449
2450 case REGISTER_PARAM:
2451 switch (**inst) {
2452 case PARAM_ARRAY_ELEMENT:
2453 (*inst)++;
2454 src = parse_string (inst, vc_head, Program, &found);
2455 Program->Position = parse_position (inst);
2456
2457 if (!found) {
Brian Paula088f162006-09-05 23:08:51 +00002458 program_error(ctx, Program->Position,
2459 "2: Undefined variable"); /* src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002460 return 1;
2461 }
2462
Brian Paul95801792005-12-06 15:41:43 +00002463 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002464
2465 switch (*(*inst)++) {
2466 case ARRAY_INDEX_ABSOLUTE:
2467 offset = parse_integer (inst, Program);
2468
2469 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002470 || (offset >= (int)src->param_binding_length)) {
Brian Paula088f162006-09-05 23:08:51 +00002471 program_error(ctx, Program->Position,
2472 "Index out of range");
2473 /* offset, src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002474 return 1;
2475 }
2476
2477 *Index = src->param_binding_begin + offset;
2478 break;
2479
2480 case ARRAY_INDEX_RELATIVE:
2481 {
2482 GLint addr_reg_idx, rel_off;
2483
2484 /* First, grab the address regiseter */
2485 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2486 return 1;
2487
2488 /* And the .x */
2489 ((*inst)++);
2490 ((*inst)++);
2491 ((*inst)++);
2492 ((*inst)++);
2493
2494 /* Then the relative offset */
2495 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2496
2497 /* And store it properly */
2498 *Index = src->param_binding_begin + rel_off;
2499 *IsRelOffset = 1;
2500 }
2501 break;
2502 }
2503 break;
2504
2505 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002506 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2507 return 1;
2508
Brian Paul95801792005-12-06 15:41:43 +00002509 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002510 *Index = src->param_binding_begin;
2511 break;
2512 }
2513 break;
2514
2515 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002516 src = parse_string (inst, vc_head, Program, &found);
2517 Program->Position = parse_position (inst);
2518
2519 /* If the name has never been added to our symbol table, we're hosed */
2520 if (!found) {
Brian Paula088f162006-09-05 23:08:51 +00002521 program_error(ctx, Program->Position,
2522 "3: Undefined variable"); /* src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002523 return 1;
2524 }
2525
2526 switch (src->type) {
2527 case vt_attrib:
2528 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002529 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002530 break;
2531
2532 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2533 case vt_param:
Brian Paul95801792005-12-06 15:41:43 +00002534 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002535 *Index = src->param_binding_begin;
2536 break;
2537
2538 case vt_temp:
2539 *File = PROGRAM_TEMPORARY;
2540 *Index = src->temp_binding;
2541 break;
2542
2543 /* If the var type is vt_output no go */
2544 default:
Brian Paula088f162006-09-05 23:08:51 +00002545 program_error(ctx, Program->Position,
2546 "destination register is read only");
2547 /* bad src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002548 return 1;
2549 }
2550 break;
2551
2552 default:
Brian Paula088f162006-09-05 23:08:51 +00002553 program_error(ctx, Program->Position,
2554 "Unknown token in parse_src_reg");
Jouk Jansen40322e12004-04-05 08:50:36 +00002555 return 1;
2556 }
2557
Markus Amslerf3c49062008-03-17 08:35:37 -06002558 /* Add attributes to InputsRead only if they are used the program.
2559 * This avoids the handling of unused ATTRIB declarations in the drivers. */
2560 if (*File == PROGRAM_INPUT)
2561 Program->Base.InputsRead |= (1 << *Index);
2562
Jouk Jansen40322e12004-04-05 08:50:36 +00002563 return 0;
2564}
2565
2566/**
Brian Paul18e7c5c2005-10-30 21:46:00 +00002567 * Parse fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002568 */
2569static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002570parse_fp_vector_src_reg(GLcontext * ctx, const GLubyte ** inst,
Brian Paul32df89e2005-10-29 18:26:43 +00002571 struct var_cache **vc_head,
2572 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00002573 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002574{
Brian Paul7aebaf32005-10-30 21:23:23 +00002575 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002576 GLint index;
2577 GLboolean negate;
2578 GLubyte swizzle[4];
2579 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002580
Jouk Jansen40322e12004-04-05 08:50:36 +00002581 /* Grab the sign */
Brian Paulbedb93e2008-03-25 11:22:57 -06002582 negate = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002583
2584 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002585 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002586 return 1;
2587
2588 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002589 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002590
Brian Paul32df89e2005-10-29 18:26:43 +00002591 reg->File = file;
2592 reg->Index = index;
Brian Paul32df89e2005-10-29 18:26:43 +00002593 reg->NegateBase = negate;
2594 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002595 return 0;
2596}
2597
Jouk Jansen40322e12004-04-05 08:50:36 +00002598
Brian Paulb7fc1c32006-08-30 23:38:03 +00002599/**
2600 * Parse fragment program destination register.
2601 * \return 1 if error, 0 if no error.
2602 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002603static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002604parse_fp_dst_reg(GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00002605 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002606 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002607{
Brian Paul7aebaf32005-10-30 21:23:23 +00002608 GLint mask;
2609 GLuint idx;
2610 enum register_file file;
2611
Keith Whitwell7c26b612005-04-21 14:46:57 +00002612 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002613 return 1;
2614
Keith Whitwell7c26b612005-04-21 14:46:57 +00002615 reg->File = file;
2616 reg->Index = idx;
2617 reg->WriteMask = mask;
2618 return 0;
2619}
2620
2621
Brian Paul7aebaf32005-10-30 21:23:23 +00002622/**
2623 * Parse fragment program scalar src register.
Brian Paulb7fc1c32006-08-30 23:38:03 +00002624 * \return 1 if error, 0 if no error.
Brian Paul7aebaf32005-10-30 21:23:23 +00002625 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002626static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002627parse_fp_scalar_src_reg (GLcontext * ctx, const GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002628 struct var_cache **vc_head,
2629 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002630 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002631{
Brian Paul7aebaf32005-10-30 21:23:23 +00002632 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002633 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002634 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002635 GLubyte Swizzle[4];
2636 GLboolean IsRelOffset;
2637
2638 /* Grab the sign */
Brian Paulbedb93e2008-03-25 11:22:57 -06002639 Negate = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002640
2641 /* And the src reg */
2642 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2643 return 1;
2644
2645 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002646 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002647
Keith Whitwell7c26b612005-04-21 14:46:57 +00002648 reg->File = File;
2649 reg->Index = Index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002650 reg->NegateBase = Negate;
2651 reg->Swizzle = (Swizzle[0] << 0);
2652
Jouk Jansen40322e12004-04-05 08:50:36 +00002653 return 0;
2654}
2655
Keith Whitwell7c26b612005-04-21 14:46:57 +00002656
Jouk Jansen40322e12004-04-05 08:50:36 +00002657/**
2658 * This is a big mother that handles getting opcodes into the instruction
2659 * and handling the src & dst registers for fragment program instructions
Brian Paulb7fc1c32006-08-30 23:38:03 +00002660 * \return 1 if error, 0 if no error
Jouk Jansen40322e12004-04-05 08:50:36 +00002661 */
2662static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002663parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002664 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002665 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002666{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002667 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002668 GLuint texcoord;
2669 GLubyte instClass, type, code;
2670 GLboolean rel;
Ian Romanick7b559a92007-06-07 13:58:50 -07002671 GLuint shadow_tex = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002672
Brian Pauld6272e02006-10-29 18:03:16 +00002673 _mesa_init_instructions(fp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002674
2675 /* Record the position in the program string for debugging */
2676 fp->StringPos = Program->Position;
2677
2678 /* OP_ALU_INST or OP_TEX_INST */
2679 instClass = *(*inst)++;
2680
2681 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2682 * OP_TEX_{SAMPLE, KIL}
2683 */
2684 type = *(*inst)++;
2685
2686 /* The actual opcode name */
2687 code = *(*inst)++;
2688
2689 /* Increment the correct count */
2690 switch (instClass) {
2691 case OP_ALU_INST:
2692 Program->NumAluInstructions++;
2693 break;
2694 case OP_TEX_INST:
2695 Program->NumTexInstructions++;
2696 break;
2697 }
2698
Jouk Jansen40322e12004-04-05 08:50:36 +00002699 switch (type) {
2700 case OP_ALU_VECTOR:
2701 switch (code) {
2702 case OP_ABS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002703 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002704 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002705 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002706 break;
2707
2708 case OP_FLR_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002709 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002710 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002711 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002712 break;
2713
2714 case OP_FRC_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002715 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002716 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002717 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002718 break;
2719
2720 case OP_LIT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002721 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002722 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002723 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002724 break;
2725
2726 case OP_MOV_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002727 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002728 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002729 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002730 break;
2731 }
2732
Keith Whitwell7c26b612005-04-21 14:46:57 +00002733 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002734 return 1;
2735
Keith Whitwell7c26b612005-04-21 14:46:57 +00002736 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002737 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002738 break;
2739
2740 case OP_ALU_SCALAR:
2741 switch (code) {
2742 case OP_COS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002743 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002744 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002745 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002746 break;
2747
2748 case OP_EX2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002749 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002750 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002751 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002752 break;
2753
2754 case OP_LG2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002755 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002756 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002757 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002758 break;
2759
2760 case OP_RCP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002761 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002762 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002763 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002764 break;
2765
2766 case OP_RSQ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002767 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002768 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002769 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002770 break;
2771
2772 case OP_SIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002773 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002774 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002775 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002776 break;
2777
2778 case OP_SCS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002779 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002780 case OP_SCS:
2781
Brian Paul7e807512005-11-05 17:10:45 +00002782 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002783 break;
2784 }
2785
Keith Whitwell7c26b612005-04-21 14:46:57 +00002786 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002787 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002788
2789 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002790 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002791 break;
2792
2793 case OP_ALU_BINSC:
2794 switch (code) {
2795 case OP_POW_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002796 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002797 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002798 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002799 break;
2800 }
2801
Keith Whitwell7c26b612005-04-21 14:46:57 +00002802 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002803 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002804
Jouk Jansen40322e12004-04-05 08:50:36 +00002805 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002806 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002807 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002808 }
2809 break;
2810
2811
2812 case OP_ALU_BIN:
2813 switch (code) {
2814 case OP_ADD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002815 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002816 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002817 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002818 break;
2819
2820 case OP_DP3_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002821 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002822 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002823 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002824 break;
2825
2826 case OP_DP4_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002827 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002828 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002829 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002830 break;
2831
2832 case OP_DPH_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002833 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002834 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002835 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002836 break;
2837
2838 case OP_DST_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002839 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002840 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002841 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002842 break;
2843
2844 case OP_MAX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002845 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002846 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002847 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002848 break;
2849
2850 case OP_MIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002851 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002852 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002853 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002854 break;
2855
2856 case OP_MUL_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002857 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002858 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002859 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002860 break;
2861
2862 case OP_SGE_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002863 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002864 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002865 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002866 break;
2867
2868 case OP_SLT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002869 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002870 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002871 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002872 break;
2873
2874 case OP_SUB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002875 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002876 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002877 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002878 break;
2879
2880 case OP_XPD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002881 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002882 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002883 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002884 break;
2885 }
2886
Keith Whitwell7c26b612005-04-21 14:46:57 +00002887 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002888 return 1;
2889 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002890 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2891 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002892 }
2893 break;
2894
2895 case OP_ALU_TRI:
2896 switch (code) {
2897 case OP_CMP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002898 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002899 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002900 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002901 break;
2902
2903 case OP_LRP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002904 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002905 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002906 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002907 break;
2908
2909 case OP_MAD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002910 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002911 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002912 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002913 break;
2914 }
2915
Keith Whitwell7c26b612005-04-21 14:46:57 +00002916 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002917 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002918
Jouk Jansen40322e12004-04-05 08:50:36 +00002919 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002920 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2921 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002922 }
2923 break;
2924
2925 case OP_ALU_SWZ:
2926 switch (code) {
2927 case OP_SWZ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002928 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002929 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002930 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002931 break;
2932 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002933 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002934 return 1;
2935
Keith Whitwell7c26b612005-04-21 14:46:57 +00002936 {
Brian Paul32df89e2005-10-29 18:26:43 +00002937 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002938 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002939 enum register_file file;
2940 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002941
Brian Paul32df89e2005-10-29 18:26:43 +00002942 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002943 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002944 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2945 fp->SrcReg[0].File = file;
2946 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002947 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002948 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
2949 swizzle[1],
2950 swizzle[2],
2951 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00002952 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002953 break;
2954
2955 case OP_TEX_SAMPLE:
2956 switch (code) {
2957 case OP_TEX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002958 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002959 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00002960 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002961 break;
2962
2963 case OP_TXP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002964 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002965 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00002966 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002967 break;
2968
2969 case OP_TXB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002970 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002971 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00002972 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002973 break;
2974 }
2975
Keith Whitwell7c26b612005-04-21 14:46:57 +00002976 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002977 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002978
2979 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002980 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002981
2982 /* texImageUnit */
2983 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
2984 return 1;
2985 fp->TexSrcUnit = texcoord;
2986
2987 /* texTarget */
2988 switch (*(*inst)++) {
Ian Romanick7b559a92007-06-07 13:58:50 -07002989 case TEXTARGET_SHADOW1D:
2990 shadow_tex = 1 << texcoord;
2991 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00002992 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00002993 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002994 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07002995 case TEXTARGET_SHADOW2D:
2996 shadow_tex = 1 << texcoord;
2997 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00002998 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00002999 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003000 break;
3001 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00003002 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003003 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07003004 case TEXTARGET_SHADOWRECT:
3005 shadow_tex = 1 << texcoord;
3006 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00003007 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00003008 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003009 break;
3010 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00003011 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003012 break;
Ian Romanick69358e72007-06-05 09:24:27 -07003013 case TEXTARGET_SHADOW1D_ARRAY:
Ian Romanick7b559a92007-06-07 13:58:50 -07003014 shadow_tex = 1 << texcoord;
3015 /* FALLTHROUGH */
Ian Romanickbb372f12007-05-16 15:34:22 -07003016 case TEXTARGET_1D_ARRAY:
3017 fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
3018 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07003019 case TEXTARGET_SHADOW2D_ARRAY:
3020 shadow_tex = 1 << texcoord;
3021 /* FALLTHROUGH */
Ian Romanickbb372f12007-05-16 15:34:22 -07003022 case TEXTARGET_2D_ARRAY:
3023 fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
3024 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003025 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003026
3027 /* Don't test the first time a particular sampler is seen. Each time
3028 * after that, make sure the shadow state is the same.
3029 */
3030 if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
3031 && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
3032 program_error(ctx, Program->Position,
3033 "texture image unit used for shadow sampling and non-shadow sampling");
3034 return 1;
3035 }
3036
Brian Paulb7fc1c32006-08-30 23:38:03 +00003037 Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
3038 /* Check that both "2D" and "CUBE" (for example) aren't both used */
3039 if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
Brian Paula088f162006-09-05 23:08:51 +00003040 program_error(ctx, Program->Position,
3041 "multiple targets used on one texture image unit");
Brian Paulb7fc1c32006-08-30 23:38:03 +00003042 return 1;
3043 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003044
3045
3046 Program->ShadowSamplers |= shadow_tex;
Jouk Jansen40322e12004-04-05 08:50:36 +00003047 break;
3048
3049 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003050 Program->UsesKill = 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003051 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003052 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003053 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003054 break;
Brian Paulb7fc1c32006-08-30 23:38:03 +00003055 default:
3056 _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
3057 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003058 }
3059
3060 return 0;
3061}
3062
Keith Whitwell7c26b612005-04-21 14:46:57 +00003063static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003064parse_vp_dst_reg(GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003065 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003066 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003067{
Brian Paul7aebaf32005-10-30 21:23:23 +00003068 GLint mask;
3069 GLuint idx;
3070 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003071
3072 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3073 return 1;
3074
3075 reg->File = file;
3076 reg->Index = idx;
3077 reg->WriteMask = mask;
3078 return 0;
3079}
3080
3081/**
3082 * Handle the parsing out of a masked address register
3083 *
3084 * \param Index - The register index we write to
3085 * \param WriteMask - The mask controlling which components we write (1->write)
3086 *
3087 * \return 0 on sucess, 1 on error
3088 */
3089static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003090parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003091 struct var_cache **vc_head,
3092 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003093 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003094{
3095 GLint idx;
3096
3097 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3098 return 1;
3099
3100 /* This should be 0x8 */
3101 (*inst)++;
3102
3103 reg->File = PROGRAM_ADDRESS;
3104 reg->Index = idx;
3105
3106 /* Writemask of .x is implied */
3107 reg->WriteMask = 0x1;
3108 return 0;
3109}
3110
3111/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003112 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003113 */
3114static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003115parse_vp_vector_src_reg(GLcontext * ctx, const GLubyte ** inst,
Brian Paul32df89e2005-10-29 18:26:43 +00003116 struct var_cache **vc_head,
3117 struct arb_program *program,
Brian Paul7e807512005-11-05 17:10:45 +00003118 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003119{
Brian Paul7aebaf32005-10-30 21:23:23 +00003120 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003121 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003122 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003123 GLubyte swizzle[4];
3124 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003125
3126 /* Grab the sign */
Brian Paulbedb93e2008-03-25 11:22:57 -06003127 negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003128
3129 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003130 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003131 return 1;
3132
3133 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003134 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003135
Brian Paul32df89e2005-10-29 18:26:43 +00003136 reg->File = file;
3137 reg->Index = index;
3138 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3139 swizzle[2], swizzle[3]);
Brian Paul7e807512005-11-05 17:10:45 +00003140 reg->NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003141 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003142 return 0;
3143}
3144
3145
3146static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003147parse_vp_scalar_src_reg (GLcontext * ctx, const GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003148 struct var_cache **vc_head,
3149 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003150 struct prog_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003151{
Brian Paul7aebaf32005-10-30 21:23:23 +00003152 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003153 GLint Index;
Brian Paulbedb93e2008-03-25 11:22:57 -06003154 GLubyte negateMask;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003155 GLubyte Swizzle[4];
3156 GLboolean IsRelOffset;
3157
3158 /* Grab the sign */
Brian Paulbedb93e2008-03-25 11:22:57 -06003159 negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003160
3161 /* And the src reg */
3162 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3163 return 1;
3164
3165 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003166 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003167
3168 reg->File = File;
3169 reg->Index = Index;
3170 reg->Swizzle = (Swizzle[0] << 0);
Brian Paulbedb93e2008-03-25 11:22:57 -06003171 reg->NegateBase = negateMask;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003172 reg->RelAddr = IsRelOffset;
3173 return 0;
3174}
3175
3176
Jouk Jansen40322e12004-04-05 08:50:36 +00003177/**
3178 * This is a big mother that handles getting opcodes into the instruction
3179 * and handling the src & dst registers for vertex program instructions
3180 */
3181static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003182parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00003183 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003184 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003185{
3186 GLint a;
3187 GLubyte type, code;
3188
3189 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3190 type = *(*inst)++;
3191
3192 /* The actual opcode name */
3193 code = *(*inst)++;
3194
Brian Pauld6272e02006-10-29 18:03:16 +00003195 _mesa_init_instructions(vp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003196 /* Record the position in the program string for debugging */
3197 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003198
3199 switch (type) {
3200 /* XXX: */
3201 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003202 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003203
3204 /* Remember to set SrcReg.RelAddr; */
3205
3206 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003207 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003208 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003209
Jouk Jansen40322e12004-04-05 08:50:36 +00003210 vp->DstReg.File = PROGRAM_ADDRESS;
3211
3212 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003213 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003214 return 1;
3215
3216 break;
3217
3218 case OP_ALU_VECTOR:
3219 switch (code) {
3220 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003221 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003222 break;
3223 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003224 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003225 break;
3226 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003227 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003228 break;
3229 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003230 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003231 break;
3232 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003233 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003234 break;
3235 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003236
3237 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003238 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003239
3240 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003241 return 1;
3242 break;
3243
3244 case OP_ALU_SCALAR:
3245 switch (code) {
3246 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003247 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003248 break;
3249 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003250 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003251 break;
3252 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003253 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003254 break;
3255 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003256 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003257 break;
3258 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003259 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003260 break;
3261 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003262 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003263 break;
3264 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003265 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003266 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003267
3268 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003269 return 1;
3270 break;
3271
3272 case OP_ALU_BINSC:
3273 switch (code) {
3274 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003275 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003276 break;
3277 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003278 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003279 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003280
Jouk Jansen40322e12004-04-05 08:50:36 +00003281 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003282 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003283 return 1;
3284 }
3285 break;
3286
3287 case OP_ALU_BIN:
3288 switch (code) {
3289 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003290 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003291 break;
3292 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003293 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003294 break;
3295 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003296 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003297 break;
3298 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003299 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003300 break;
3301 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003302 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003303 break;
3304 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003305 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003306 break;
3307 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003308 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003309 break;
3310 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003311 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003312 break;
3313 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003314 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003315 break;
3316 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003317 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003318 break;
3319 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003320 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003321 break;
3322 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003323 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003324 break;
3325 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003326 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003327 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003328
Jouk Jansen40322e12004-04-05 08:50:36 +00003329 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003330 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003331 return 1;
3332 }
3333 break;
3334
3335 case OP_ALU_TRI:
3336 switch (code) {
3337 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003338 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003339 break;
3340 }
3341
Keith Whitwell7c26b612005-04-21 14:46:57 +00003342 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003343 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003344
Jouk Jansen40322e12004-04-05 08:50:36 +00003345 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003346 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003347 return 1;
3348 }
3349 break;
3350
3351 case OP_ALU_SWZ:
3352 switch (code) {
3353 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003354 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003355 break;
3356 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003357 {
Brian Paul32df89e2005-10-29 18:26:43 +00003358 GLubyte swizzle[4];
3359 GLubyte negateMask;
3360 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003361 enum register_file file;
3362 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003363
Keith Whitwell7c26b612005-04-21 14:46:57 +00003364 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3365 return 1;
3366
Brian Paul32df89e2005-10-29 18:26:43 +00003367 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003368 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003369 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3370 vp->SrcReg[0].File = file;
3371 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003372 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003373 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3374 swizzle[1],
3375 swizzle[2],
3376 swizzle[3]);
3377 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003378 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003379 break;
3380 }
3381 return 0;
3382}
3383
3384#if DEBUG_PARSING
3385
3386static GLvoid
Jouk Jansen40322e12004-04-05 08:50:36 +00003387debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3388 struct arb_program *Program)
3389{
3390 struct var_cache *vc;
3391 GLint a, b;
3392
Brianb618ac82007-02-22 09:39:25 -07003393 fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
Jouk Jansen40322e12004-04-05 08:50:36 +00003394
3395 /* First of all, print out the contents of the var_cache */
3396 vc = vc_head;
3397 while (vc) {
Brianb618ac82007-02-22 09:39:25 -07003398 fprintf (stderr, "[%p]\n", (void*) vc);
Jouk Jansen40322e12004-04-05 08:50:36 +00003399 switch (vc->type) {
3400 case vt_none:
3401 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3402 break;
3403 case vt_attrib:
3404 fprintf (stderr, "ATTRIB %s\n", vc->name);
3405 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3406 break;
3407 case vt_param:
3408 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3409 vc->param_binding_begin, vc->param_binding_length);
3410 b = vc->param_binding_begin;
3411 for (a = 0; a < vc->param_binding_length; a++) {
3412 fprintf (stderr, "%s\n",
Brianb618ac82007-02-22 09:39:25 -07003413 Program->Base.Parameters->Parameters[a + b].Name);
3414 if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
3415 const char *s;
3416 s = _mesa_program_state_string(Program->Base.Parameters->Parameters
3417 [a + b].StateIndexes);
3418 fprintf(stderr, "%s\n", s);
3419 _mesa_free((char *) s);
Jouk Jansen40322e12004-04-05 08:50:36 +00003420 }
3421 else
3422 fprintf (stderr, "%f %f %f %f\n",
Brianb618ac82007-02-22 09:39:25 -07003423 Program->Base.Parameters->ParameterValues[a + b][0],
3424 Program->Base.Parameters->ParameterValues[a + b][1],
3425 Program->Base.Parameters->ParameterValues[a + b][2],
3426 Program->Base.Parameters->ParameterValues[a + b][3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003427 }
3428 break;
3429 case vt_temp:
3430 fprintf (stderr, "TEMP %s\n", vc->name);
3431 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3432 break;
3433 case vt_output:
3434 fprintf (stderr, "OUTPUT %s\n", vc->name);
3435 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3436 break;
3437 case vt_alias:
3438 fprintf (stderr, "ALIAS %s\n", vc->name);
Brianb618ac82007-02-22 09:39:25 -07003439 fprintf (stderr, " binding: 0x%p (%s)\n",
3440 (void*) vc->alias_binding, vc->alias_binding->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00003441 break;
Brianb618ac82007-02-22 09:39:25 -07003442 default:
3443 /* nothing */
3444 ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003445 }
3446 vc = vc->next;
3447 }
3448}
3449
Brian Paul72030e02005-11-03 03:30:34 +00003450#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003451
3452
3453/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003454 * The main loop for parsing a fragment or vertex program
3455 *
Brian Paul72030e02005-11-03 03:30:34 +00003456 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003457 */
Brian Paul72030e02005-11-03 03:30:34 +00003458static GLint
Brian Paula088f162006-09-05 23:08:51 +00003459parse_instructions(GLcontext * ctx, const GLubyte * inst,
3460 struct var_cache **vc_head, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003461{
Brian Paul72030e02005-11-03 03:30:34 +00003462 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3463 ? ctx->Const.FragmentProgram.MaxInstructions
3464 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003465 GLint err = 0;
3466
Brian Paul72030e02005-11-03 03:30:34 +00003467 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3468
Jouk Jansen40322e12004-04-05 08:50:36 +00003469 Program->MajorVersion = (GLuint) * inst++;
3470 Program->MinorVersion = (GLuint) * inst++;
3471
3472 while (*inst != END) {
3473 switch (*inst++) {
3474
3475 case OPTION:
3476 switch (*inst++) {
3477 case ARB_PRECISION_HINT_FASTEST:
3478 Program->PrecisionOption = GL_FASTEST;
3479 break;
3480
3481 case ARB_PRECISION_HINT_NICEST:
3482 Program->PrecisionOption = GL_NICEST;
3483 break;
3484
3485 case ARB_FOG_EXP:
3486 Program->FogOption = GL_EXP;
3487 break;
3488
3489 case ARB_FOG_EXP2:
3490 Program->FogOption = GL_EXP2;
3491 break;
3492
3493 case ARB_FOG_LINEAR:
3494 Program->FogOption = GL_LINEAR;
3495 break;
3496
3497 case ARB_POSITION_INVARIANT:
3498 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003499 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003500 break;
3501
3502 case ARB_FRAGMENT_PROGRAM_SHADOW:
3503 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3504 /* TODO ARB_fragment_program_shadow code */
3505 }
3506 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003507
3508 case ARB_DRAW_BUFFERS:
3509 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3510 /* do nothing for now */
3511 }
3512 break;
Ian Romanickbb372f12007-05-16 15:34:22 -07003513
3514 case MESA_TEXTURE_ARRAY:
3515 /* do nothing for now */
3516 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003517 }
3518 break;
3519
3520 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003521 /* check length */
3522 if (Program->Base.NumInstructions + 1 >= maxInst) {
Brian Paula088f162006-09-05 23:08:51 +00003523 program_error(ctx, Program->Position,
3524 "Max instruction count exceeded");
Brian Paul72030e02005-11-03 03:30:34 +00003525 return 1;
3526 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003527 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003528 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003529 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003530 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003531 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003532 }
3533 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003534 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003535 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003536 }
3537
Brian Paul72030e02005-11-03 03:30:34 +00003538 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003539 Program->Base.NumInstructions++;
3540 break;
3541
3542 case DECLARATION:
3543 err = parse_declaration (ctx, &inst, vc_head, Program);
3544 break;
3545
3546 default:
3547 break;
3548 }
3549
3550 if (err)
3551 break;
3552 }
3553
3554 /* Finally, tag on an OPCODE_END instruction */
Brian Paul8c41a142005-11-19 15:36:28 +00003555 {
Brian Paul7aebaf32005-10-30 21:23:23 +00003556 const GLuint numInst = Program->Base.NumInstructions;
Brian Pauld6272e02006-10-29 18:03:16 +00003557 _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
Brian Paul8c41a142005-11-19 15:36:28 +00003558 Program->Base.Instructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003559 /* YYY Wrong Position in program, whatever, at least not random -> crash
3560 Program->Position = parse_position (&inst);
3561 */
Brian Paul8c41a142005-11-19 15:36:28 +00003562 Program->Base.Instructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003563 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003564 Program->Base.NumInstructions++;
3565
Brian Paul05051032005-11-01 04:36:33 +00003566 /*
3567 * Initialize native counts to logical counts. The device driver may
3568 * change them if program is translated into a hardware program.
3569 */
3570 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3571 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3572 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3573 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3574 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +00003575
Jouk Jansen40322e12004-04-05 08:50:36 +00003576 return err;
3577}
3578
Brian Paul7aebaf32005-10-30 21:23:23 +00003579
Jouk Jansen40322e12004-04-05 08:50:36 +00003580/* XXX temporary */
Brian5cc12922006-12-14 14:27:05 -07003581LONGSTRING static char core_grammar_text[] =
Brianc223c6b2007-07-04 13:15:20 -06003582#include "shader/grammar/grammar_syn.h"
Jouk Jansen40322e12004-04-05 08:50:36 +00003583;
3584
Brian Paul7aebaf32005-10-30 21:23:23 +00003585
Brian Paul8c41a142005-11-19 15:36:28 +00003586/**
3587 * Set a grammar parameter.
3588 * \param name the grammar parameter
3589 * \param value the new parameter value
3590 * \return 0 if OK, 1 if error
3591 */
3592static int
3593set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
Jouk Jansen40322e12004-04-05 08:50:36 +00003594{
3595 char error_msg[300];
3596 GLint error_pos;
3597
Brian Paul8c41a142005-11-19 15:36:28 +00003598 if (grammar_set_reg8 (id, (const byte *) name, value))
Jouk Jansen40322e12004-04-05 08:50:36 +00003599 return 0;
3600
3601 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3602 _mesa_set_program_error (ctx, error_pos, error_msg);
3603 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3604 return 1;
3605}
3606
Brian Paul8c41a142005-11-19 15:36:28 +00003607
3608/**
3609 * Enable support for the given language option in the parser.
3610 * \return 1 if OK, 0 if error
3611 */
3612static int
3613enable_ext(GLcontext *ctx, grammar id, const char *name)
Jouk Jansen40322e12004-04-05 08:50:36 +00003614{
Brian Paul8c41a142005-11-19 15:36:28 +00003615 return !set_reg8(ctx, id, name, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003616}
3617
Brian Paul8c41a142005-11-19 15:36:28 +00003618
3619/**
3620 * Enable parser extensions based on which OpenGL extensions are supported
3621 * by this rendering context.
3622 *
3623 * \return GL_TRUE if OK, GL_FALSE if error.
3624 */
3625static GLboolean
3626enable_parser_extensions(GLcontext *ctx, grammar id)
Jouk Jansen40322e12004-04-05 08:50:36 +00003627{
Brian Paul8c41a142005-11-19 15:36:28 +00003628#if 0
3629 /* These are not supported at this time */
3630 if ((ctx->Extensions.ARB_vertex_blend ||
3631 ctx->Extensions.EXT_vertex_weighting)
Brian Paul43cc1dc2006-09-05 23:11:09 +00003632 && !enable_ext(ctx, id, "vertex_blend"))
Brian Paul8c41a142005-11-19 15:36:28 +00003633 return GL_FALSE;
3634 if (ctx->Extensions.ARB_matrix_palette
3635 && !enable_ext(ctx, id, "matrix_palette"))
3636 return GL_FALSE;
Ian Romanick7b559a92007-06-07 13:58:50 -07003637#endif
Brian Paul8c41a142005-11-19 15:36:28 +00003638 if (ctx->Extensions.ARB_fragment_program_shadow
3639 && !enable_ext(ctx, id, "fragment_program_shadow"))
3640 return GL_FALSE;
Brian Paul8c41a142005-11-19 15:36:28 +00003641 if (ctx->Extensions.EXT_point_parameters
3642 && !enable_ext(ctx, id, "point_parameters"))
3643 return GL_FALSE;
3644 if (ctx->Extensions.EXT_secondary_color
3645 && !enable_ext(ctx, id, "secondary_color"))
3646 return GL_FALSE;
3647 if (ctx->Extensions.EXT_fog_coord
3648 && !enable_ext(ctx, id, "fog_coord"))
3649 return GL_FALSE;
3650 if (ctx->Extensions.NV_texture_rectangle
3651 && !enable_ext(ctx, id, "texture_rectangle"))
3652 return GL_FALSE;
3653 if (ctx->Extensions.ARB_draw_buffers
3654 && !enable_ext(ctx, id, "draw_buffers"))
3655 return GL_FALSE;
Ian Romanickbb372f12007-05-16 15:34:22 -07003656 if (ctx->Extensions.MESA_texture_array
3657 && !enable_ext(ctx, id, "texture_array"))
3658 return GL_FALSE;
Brian Paul3a557502006-09-05 23:15:29 +00003659#if 1
3660 /* hack for Warcraft (see bug 8060) */
3661 enable_ext(ctx, id, "vertex_blend");
3662#endif
3663
Brian Paul8c41a142005-11-19 15:36:28 +00003664 return GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003665}
3666
Brian Paul8c41a142005-11-19 15:36:28 +00003667
Jouk Jansen40322e12004-04-05 08:50:36 +00003668/**
3669 * This kicks everything off.
3670 *
3671 * \param ctx - The GL Context
3672 * \param str - The program string
3673 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003674 * \param program - The arb_program struct to return all the parsed info in
3675 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003676 */
Brian Paul8c41a142005-11-19 15:36:28 +00003677static GLboolean
3678_mesa_parse_arb_program(GLcontext *ctx, GLenum target,
3679 const GLubyte *str, GLsizei len,
3680 struct arb_program *program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003681{
3682 GLint a, err, error_pos;
3683 char error_msg[300];
3684 GLuint parsed_len;
3685 struct var_cache *vc_head;
3686 grammar arbprogram_syn_id;
3687 GLubyte *parsed, *inst;
3688 GLubyte *strz = NULL;
3689 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3690
Brian Paul8c41a142005-11-19 15:36:28 +00003691 /* set the program target before parsing */
3692 program->Base.Target = target;
3693
Brian Paul7f76b8f2004-09-10 01:05:39 +00003694 /* Reset error state */
3695 _mesa_set_program_error(ctx, -1, NULL);
3696
Brian Paul8c41a142005-11-19 15:36:28 +00003697 /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
Jouk Jansen40322e12004-04-05 08:50:36 +00003698 if (!arbprogram_syn_is_ok) {
Brian Paul8c41a142005-11-19 15:36:28 +00003699 /* One-time initialization of parsing system */
Jouk Jansen40322e12004-04-05 08:50:36 +00003700 grammar grammar_syn_id;
Jouk Jansen40322e12004-04-05 08:50:36 +00003701 GLuint parsed_len;
Jouk Jansen40322e12004-04-05 08:50:36 +00003702
3703 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3704 if (grammar_syn_id == 0) {
3705 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
Brian Paul8c41a142005-11-19 15:36:28 +00003706 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003707 _mesa_set_program_error (ctx, error_pos, error_msg);
3708 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003709 "glProgramStringARB(Error loading grammar rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003710 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003711 }
3712
Brian Paul8c41a142005-11-19 15:36:28 +00003713 err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
3714 &parsed, &parsed_len);
Jouk Jansen40322e12004-04-05 08:50:36 +00003715
Brian Paul49a80ca2006-04-28 15:40:11 +00003716 /* 'parsed' is unused here */
3717 _mesa_free (parsed);
3718 parsed = NULL;
3719
Brian Paul45703642005-10-29 15:52:31 +00003720 /* NOTE: we can't destroy grammar_syn_id right here because
3721 * grammar_destroy() can reset the last error
3722 */
Brian Paul8c41a142005-11-19 15:36:28 +00003723 if (err) {
3724 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003725 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3726 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul8c41a142005-11-19 15:36:28 +00003727 _mesa_error (ctx, GL_INVALID_OPERATION,
3728 "glProgramString(Error loading grammar rule set");
Jouk Jansen40322e12004-04-05 08:50:36 +00003729 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003730 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003731 }
3732
3733 grammar_destroy (grammar_syn_id);
3734
3735 arbprogram_syn_is_ok = 1;
3736 }
3737
3738 /* create the grammar object */
3739 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3740 if (arbprogram_syn_id == 0) {
Brian Paul8c41a142005-11-19 15:36:28 +00003741 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003742 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3743 _mesa_set_program_error (ctx, error_pos, error_msg);
3744 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003745 "glProgramString(Error loading grammer rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003746 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003747 }
3748
3749 /* Set program_target register value */
Brian Paul55194df2005-11-19 23:29:18 +00003750 if (set_reg8 (ctx, arbprogram_syn_id, "program_target",
Jouk Jansen40322e12004-04-05 08:50:36 +00003751 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3752 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003753 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003754 }
3755
Brian Paul8c41a142005-11-19 15:36:28 +00003756 if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
3757 grammar_destroy(arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003758 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003759 }
3760
3761 /* check for NULL character occurences */
3762 {
Brian Paul8c41a142005-11-19 15:36:28 +00003763 GLint i;
3764 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003765 if (str[i] == '\0') {
Brian Paula088f162006-09-05 23:08:51 +00003766 program_error(ctx, i, "illegal character");
Jouk Jansen40322e12004-04-05 08:50:36 +00003767 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003768 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003769 }
Brian Paul8c41a142005-11-19 15:36:28 +00003770 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003771 }
3772
3773 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003774 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003775 if (!strz) {
Brian Paul8c41a142005-11-19 15:36:28 +00003776 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
3777 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003778 return GL_FALSE;
3779 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003780 _mesa_memcpy (strz, str, len);
3781 strz[len] = '\0';
3782
Michal Krolb80bc052004-10-21 14:09:54 +00003783 /* do a fast check on program string - initial production buffer is 4K */
Brian Paul8c41a142005-11-19 15:36:28 +00003784 err = !grammar_fast_check(arbprogram_syn_id, strz,
3785 &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003786
3787 /* Syntax parse error */
Brian Paul8c41a142005-11-19 15:36:28 +00003788 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00003789 grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
3790 program_error(ctx, error_pos, error_msg);
Brian Paul5fe90292004-07-20 21:15:13 +00003791
Brian Paulb3aefd12005-09-19 20:12:32 +00003792#if DEBUG_PARSING
Brian Paula088f162006-09-05 23:08:51 +00003793 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003794 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003795 int line, col;
3796 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003797 fprintf(stderr, "program: %s\n", (char *) strz);
3798 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
Brian Paula088f162006-09-05 23:08:51 +00003799 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos,
3800 &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003801 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
3802 } while (0)
3803#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003804
Brian Paula088f162006-09-05 23:08:51 +00003805 _mesa_free(strz);
3806 _mesa_free(parsed);
3807
Jouk Jansen40322e12004-04-05 08:50:36 +00003808 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003809 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003810 }
3811
Jouk Jansen40322e12004-04-05 08:50:36 +00003812 grammar_destroy (arbprogram_syn_id);
3813
Brian Paul8c41a142005-11-19 15:36:28 +00003814 /*
3815 * Program string is syntactically correct at this point
3816 * Parse the tokenized version of the program now, generating
3817 * vertex/fragment program instructions.
3818 */
3819
Jouk Jansen40322e12004-04-05 08:50:36 +00003820 /* Initialize the arb_program struct */
3821 program->Base.String = strz;
Brian Paul383c39e2006-08-25 15:14:25 +00003822 program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003823 program->Base.NumInstructions =
3824 program->Base.NumTemporaries =
3825 program->Base.NumParameters =
3826 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
Brian Paulde997602005-11-12 17:53:14 +00003827 program->Base.Parameters = _mesa_new_parameter_list ();
3828 program->Base.InputsRead = 0x0;
3829 program->Base.OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003830 program->Position = 0;
3831 program->MajorVersion = program->MinorVersion = 0;
3832 program->PrecisionOption = GL_DONT_CARE;
3833 program->FogOption = GL_NONE;
3834 program->HintPositionInvariant = GL_FALSE;
3835 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003836 program->TexturesUsed[a] = 0x0;
Ian Romanick7b559a92007-06-07 13:58:50 -07003837 program->ShadowSamplers = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003838 program->NumAluInstructions =
3839 program->NumTexInstructions =
3840 program->NumTexIndirections = 0;
Keith Whitwellc3626a92005-11-01 17:25:49 +00003841 program->UsesKill = 0;
3842
Jouk Jansen40322e12004-04-05 08:50:36 +00003843 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003844 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003845
3846 /* Start examining the tokens in the array */
3847 inst = parsed;
3848
3849 /* Check the grammer rev */
3850 if (*inst++ != REVISION) {
Brian Paula088f162006-09-05 23:08:51 +00003851 program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003852 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003853 }
3854 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003855 /* ignore program target */
3856 inst++;
Brian Paul8c41a142005-11-19 15:36:28 +00003857 err = parse_instructions(ctx, inst, &vc_head, program);
Jouk Jansen40322e12004-04-05 08:50:36 +00003858 }
3859
3860 /*debug_variables(ctx, vc_head, program); */
3861
3862 /* We're done with the parsed binary array */
3863 var_cache_destroy (&vc_head);
3864
3865 _mesa_free (parsed);
Brian Paul45703642005-10-29 15:52:31 +00003866
Brian Paul8c41a142005-11-19 15:36:28 +00003867 /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
3868 * to size [ap.Base.NumInstructions].
3869 */
Brian Paula7543902006-08-24 21:58:32 +00003870 program->Base.Instructions
3871 = _mesa_realloc_instructions(program->Base.Instructions,
3872 MAX_INSTRUCTIONS,
3873 program->Base.NumInstructions);
3874
Brian Paul45703642005-10-29 15:52:31 +00003875 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00003876}
Brian Paul8c41a142005-11-19 15:36:28 +00003877
3878
3879
3880void
3881_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
3882 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003883 struct gl_fragment_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003884{
3885 struct arb_program ap;
3886 GLuint i;
3887
3888 ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
Brian Paul95801792005-12-06 15:41:43 +00003889 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Brian Paul8c41a142005-11-19 15:36:28 +00003890 /* Error in the program. Just return. */
3891 return;
3892 }
3893
3894 /* Copy the relevant contents of the arb_program struct into the
3895 * fragment_program struct.
3896 */
3897 program->Base.String = ap.Base.String;
3898 program->Base.NumInstructions = ap.Base.NumInstructions;
3899 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3900 program->Base.NumParameters = ap.Base.NumParameters;
3901 program->Base.NumAttributes = ap.Base.NumAttributes;
3902 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003903 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3904 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3905 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3906 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3907 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian21f99792007-01-09 11:00:21 -07003908 program->Base.NumAluInstructions = ap.Base.NumAluInstructions;
3909 program->Base.NumTexInstructions = ap.Base.NumTexInstructions;
3910 program->Base.NumTexIndirections = ap.Base.NumTexIndirections;
3911 program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
3912 program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
3913 program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
Brian Paul8c41a142005-11-19 15:36:28 +00003914 program->Base.InputsRead = ap.Base.InputsRead;
3915 program->Base.OutputsWritten = ap.Base.OutputsWritten;
Briand1284d32008-03-12 15:33:41 -06003916 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
Brianc9db2232007-01-04 17:22:19 -07003917 program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
Briand1284d32008-03-12 15:33:41 -06003918 if (ap.TexturesUsed[i])
3919 program->Base.SamplersUsed |= (1 << i);
3920 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003921 program->Base.ShadowSamplers = ap.ShadowSamplers;
Brian Paul8c41a142005-11-19 15:36:28 +00003922 program->FogOption = ap.FogOption;
Keith Whitwell7ecdfb22007-03-04 21:47:05 +00003923 program->UsesKill = ap.UsesKill;
Brian Paul8c41a142005-11-19 15:36:28 +00003924
3925 if (program->Base.Instructions)
3926 _mesa_free(program->Base.Instructions);
3927 program->Base.Instructions = ap.Base.Instructions;
3928
3929 if (program->Base.Parameters)
3930 _mesa_free_parameter_list(program->Base.Parameters);
3931 program->Base.Parameters = ap.Base.Parameters;
3932
Brian Paulc0ef1662008-03-25 11:32:31 -06003933 /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
3934 * or similar. We used to leave this up to drivers, but it appears
3935 * there's no hardware that wants to do fog in a discrete stage separate
3936 * from the fragment shader.
3937 */
3938 if (program->FogOption != GL_NONE) {
3939 _mesa_append_fog_code(ctx, program);
3940 program->FogOption = GL_NONE;
3941 }
3942
Brian Paul8c41a142005-11-19 15:36:28 +00003943#if DEBUG_FP
Brian Paul11a54c32006-11-15 19:54:25 +00003944 _mesa_printf("____________Fragment program %u ________\n", program->Base.ID);
3945 _mesa_print_program(&program->Base);
Brian Paul8c41a142005-11-19 15:36:28 +00003946#endif
3947}
3948
3949
3950
3951/**
3952 * Parse the vertex program string. If success, update the given
3953 * vertex_program object with the new program. Else, leave the vertex_program
3954 * object unchanged.
3955 */
3956void
3957_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
3958 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003959 struct gl_vertex_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003960{
3961 struct arb_program ap;
3962
3963 ASSERT(target == GL_VERTEX_PROGRAM_ARB);
3964
Brian Paul95801792005-12-06 15:41:43 +00003965 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Brian Paul8c41a142005-11-19 15:36:28 +00003966 /* Error in the program. Just return. */
3967 return;
3968 }
3969
3970 /* Copy the relevant contents of the arb_program struct into the
3971 * vertex_program struct.
3972 */
3973 program->Base.String = ap.Base.String;
3974 program->Base.NumInstructions = ap.Base.NumInstructions;
3975 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3976 program->Base.NumParameters = ap.Base.NumParameters;
3977 program->Base.NumAttributes = ap.Base.NumAttributes;
3978 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003979 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3980 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3981 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3982 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3983 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian Paul8c41a142005-11-19 15:36:28 +00003984 program->Base.InputsRead = ap.Base.InputsRead;
3985 program->Base.OutputsWritten = ap.Base.OutputsWritten;
3986 program->IsPositionInvariant = ap.HintPositionInvariant;
3987
3988 if (program->Base.Instructions)
3989 _mesa_free(program->Base.Instructions);
3990 program->Base.Instructions = ap.Base.Instructions;
3991
3992 if (program->Base.Parameters)
3993 _mesa_free_parameter_list(program->Base.Parameters);
3994 program->Base.Parameters = ap.Base.Parameters;
3995
3996#if DEBUG_VP
Roland Scheidegger54dac2c2007-02-09 00:36:40 +01003997 _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
Brian Paul8c41a142005-11-19 15:36:28 +00003998 _mesa_print_program(&program->Base);
3999#endif
4000}