blob: 5e81477592a9b162014338c6f626880778993224 [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Brian50a20d42008-03-27 15:51:07 -06003 * Version: 7.1
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
Brianbdf279b2008-03-27 16:19:46 -06005 * Copyright (C) 1999-2008 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
Brian Paul0576e832008-09-19 13:04:52 +020033/**
34Notes on program parameters, etc.
35
36The instructions we emit will use six kinds of source registers:
37
38 PROGRAM_INPUT - input registers
39 PROGRAM_TEMPORARY - temp registers
40 PROGRAM_ADDRESS - address/indirect register
41 PROGRAM_SAMPLER - texture sampler
42 PROGRAM_CONSTANT - indexes into program->Parameters, a known constant/literal
43 PROGRAM_STATE_VAR - indexes into program->Parameters, and may actually be:
44 + a state variable, like "state.fog.color", or
45 + a pointer to a "program.local[k]" parameter, or
46 + a pointer to a "program.env[k]" parameter
47
48Basically, all the program.local[] and program.env[] values will get mapped
49into the unified gl_program->Parameters array. This solves the problem of
50having three separate program parameter arrays.
51*/
52
53
Brianc223c6b2007-07-04 13:15:20 -060054#include "main/glheader.h"
55#include "main/imports.h"
56#include "shader/grammar/grammar_mesa.h"
Jouk Jansen40322e12004-04-05 08:50:36 +000057#include "arbprogparse.h"
Brian Paul32df89e2005-10-29 18:26:43 +000058#include "program.h"
Brian Paulc0ef1662008-03-25 11:32:31 -060059#include "programopt.h"
Brianc0551f02006-12-14 15:02:37 -070060#include "prog_parameter.h"
61#include "prog_statevars.h"
José Fonseca101d1a62008-07-23 21:06:01 +090062#include "main/context.h"
63#include "main/macros.h"
64#include "main/mtypes.h"
Brianc0551f02006-12-14 15:02:37 -070065#include "prog_instruction.h"
Brian Paul8c41a142005-11-19 15:36:28 +000066
67
Brian Paul6211a142006-08-24 23:37:13 +000068/* For ARB programs, use the NV instruction limits */
69#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
70 MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
Brian Paul8c41a142005-11-19 15:36:28 +000071
72
73/**
74 * This is basically a union of the vertex_program and fragment_program
75 * structs that we can use to parse the program into
76 *
77 * XXX we can probably get rid of this entirely someday.
78 */
79struct arb_program
80{
Brian Paul122629f2006-07-20 16:49:57 +000081 struct gl_program Base;
Brian Paul8c41a142005-11-19 15:36:28 +000082
83 GLuint Position; /* Just used for error reporting while parsing */
84 GLuint MajorVersion;
85 GLuint MinorVersion;
86
87 /* ARB_vertex_progmra options */
88 GLboolean HintPositionInvariant;
89
90 /* ARB_fragment_progmra options */
91 GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
92 GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
93
94 /* ARB_fragment_program specifics */
95 GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];
Ian Romanick7b559a92007-06-07 13:58:50 -070096 GLbitfield ShadowSamplers;
Brian Paul8c41a142005-11-19 15:36:28 +000097 GLuint NumAluInstructions;
98 GLuint NumTexInstructions;
99 GLuint NumTexIndirections;
100
101 GLboolean UsesKill;
102};
103
Ian Romanick9bdfee32005-07-18 12:31:24 +0000104
Brian Paula6c423d2004-08-25 15:59:48 +0000105
Jouk Jansen40322e12004-04-05 08:50:36 +0000106/* TODO:
107 * Fragment Program Stuff:
108 * -----------------------------------------------------
109 *
110 * - things from Michal's email
111 * + overflow on atoi
112 * + not-overflowing floats (don't use parse_integer..)
113 * + can remove range checking in arbparse.c
114 *
115 * - check all limits of number of various variables
116 * + parameters
117 *
118 * - test! test! test!
119 *
120 * Vertex Program Stuff:
121 * -----------------------------------------------------
122 * - Optimize param array usage and count limits correctly, see spec,
123 * section 2.14.3.7
124 * + Record if an array is reference absolutly or relatively (or both)
125 * + For absolute arrays, store a bitmap of accesses
126 * + For single parameters, store an access flag
127 * + After parsing, make a parameter cleanup and merging pass, where
128 * relative arrays are layed out first, followed by abs arrays, and
129 * finally single state.
130 * + Remap offsets for param src and dst registers
131 * + Now we can properly count parameter usage
132 *
133 * - Multiple state binding errors in param arrays (see spec, just before
134 * section 2.14.3.3)
135 * - grep for XXX
136 *
137 * Mesa Stuff
138 * -----------------------------------------------------
139 * - User clipping planes vs. PositionInvariant
140 * - Is it sufficient to just multiply by the mvp to transform in the
141 * PositionInvariant case? Or do we need something more involved?
142 *
143 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
144 * - fetch state listed in program_parameters list
145 * + WTF should this go???
146 * + currently in nvvertexec.c and s_nvfragprog.c
147 *
148 * - allow for multiple address registers (and fetch address regs properly)
149 *
150 * Cosmetic Stuff
151 * -----------------------------------------------------
152 * - remove any leftover unused grammer.c stuff (dict_ ?)
153 * - fix grammer.c error handling so its not static
154 * - #ifdef around stuff pertaining to extentions
155 *
156 * Outstanding Questions:
157 * -----------------------------------------------------
158 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
159 * what gets hacked off because of this:
160 * + VERTEX_ATTRIB_MATRIXINDEX
161 * + VERTEX_ATTRIB_WEIGHT
162 * + MATRIX_MODELVIEW
163 * + MATRIX_PALETTE
164 *
165 * - When can we fetch env/local params from their own register files, and
166 * when to we have to fetch them into the main state register file?
167 * (think arrays)
168 *
169 * Grammar Changes:
170 * -----------------------------------------------------
171 */
172
173/* Changes since moving the file to shader directory
174
1752004-III-4 ------------------------------------------------------------
176- added #include "grammar_mesa.h"
177- removed grammar specific code part (it resides now in grammar.c)
178- added GL_ARB_fragment_program_shadow tokens
179- modified #include "arbparse_syn.h"
180- major changes inside _mesa_parse_arb_program()
181- check the program string for '\0' characters
182- copy the program string to a one-byte-longer location to have
183 it null-terminated
184- position invariance test (not writing to result.position) moved
185 to syntax part
186*/
187
188typedef GLubyte *production;
189
Brian Paul11a54c32006-11-15 19:54:25 +0000190
Jouk Jansen40322e12004-04-05 08:50:36 +0000191/**
192 * This is the text describing the rules to parse the grammar
193 */
Brian Paul11a54c32006-11-15 19:54:25 +0000194LONGSTRING static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000195#include "arbprogram_syn.h"
196;
197
198/**
199 * These should match up with the values defined in arbprogram.syn
200 */
201
202/*
203 Changes:
204 - changed and merged V_* and F_* opcode values to OP_*.
205 - added GL_ARB_fragment_program_shadow specific tokens (michal)
206*/
Ian Romanickbb372f12007-05-16 15:34:22 -0700207#define REVISION 0x0a
Jouk Jansen40322e12004-04-05 08:50:36 +0000208
209/* program type */
210#define FRAGMENT_PROGRAM 0x01
211#define VERTEX_PROGRAM 0x02
212
213/* program section */
214#define OPTION 0x01
215#define INSTRUCTION 0x02
216#define DECLARATION 0x03
217#define END 0x04
218
Michal Krolb80bc052004-10-21 14:09:54 +0000219/* GL_ARB_fragment_program option */
220#define ARB_PRECISION_HINT_FASTEST 0x00
221#define ARB_PRECISION_HINT_NICEST 0x01
222#define ARB_FOG_EXP 0x02
223#define ARB_FOG_EXP2 0x03
224#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000225
Michal Krolb80bc052004-10-21 14:09:54 +0000226/* GL_ARB_vertex_program option */
227#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000228
Michal Krolb80bc052004-10-21 14:09:54 +0000229/* GL_ARB_fragment_program_shadow option */
230#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000231
Michal Krolb80bc052004-10-21 14:09:54 +0000232/* GL_ARB_draw_buffers option */
233#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000234
Ian Romanickbb372f12007-05-16 15:34:22 -0700235/* GL_MESA_texture_array option */
236#define MESA_TEXTURE_ARRAY 0x08
237
Jouk Jansen40322e12004-04-05 08:50:36 +0000238/* GL_ARB_fragment_program instruction class */
239#define OP_ALU_INST 0x00
240#define OP_TEX_INST 0x01
241
242/* GL_ARB_vertex_program instruction class */
243/* OP_ALU_INST */
244
245/* GL_ARB_fragment_program instruction type */
246#define OP_ALU_VECTOR 0x00
247#define OP_ALU_SCALAR 0x01
248#define OP_ALU_BINSC 0x02
249#define OP_ALU_BIN 0x03
250#define OP_ALU_TRI 0x04
251#define OP_ALU_SWZ 0x05
252#define OP_TEX_SAMPLE 0x06
253#define OP_TEX_KIL 0x07
254
255/* GL_ARB_vertex_program instruction type */
256#define OP_ALU_ARL 0x08
257/* OP_ALU_VECTOR */
258/* OP_ALU_SCALAR */
259/* OP_ALU_BINSC */
260/* OP_ALU_BIN */
261/* OP_ALU_TRI */
262/* OP_ALU_SWZ */
263
264/* GL_ARB_fragment_program instruction code */
265#define OP_ABS 0x00
266#define OP_ABS_SAT 0x1B
267#define OP_FLR 0x09
268#define OP_FLR_SAT 0x26
269#define OP_FRC 0x0A
270#define OP_FRC_SAT 0x27
271#define OP_LIT 0x0C
272#define OP_LIT_SAT 0x2A
273#define OP_MOV 0x11
274#define OP_MOV_SAT 0x30
275#define OP_COS 0x1F
276#define OP_COS_SAT 0x20
277#define OP_EX2 0x07
278#define OP_EX2_SAT 0x25
279#define OP_LG2 0x0B
280#define OP_LG2_SAT 0x29
281#define OP_RCP 0x14
282#define OP_RCP_SAT 0x33
283#define OP_RSQ 0x15
284#define OP_RSQ_SAT 0x34
285#define OP_SIN 0x38
286#define OP_SIN_SAT 0x39
287#define OP_SCS 0x35
288#define OP_SCS_SAT 0x36
289#define OP_POW 0x13
290#define OP_POW_SAT 0x32
291#define OP_ADD 0x01
292#define OP_ADD_SAT 0x1C
293#define OP_DP3 0x03
294#define OP_DP3_SAT 0x21
295#define OP_DP4 0x04
296#define OP_DP4_SAT 0x22
297#define OP_DPH 0x05
298#define OP_DPH_SAT 0x23
299#define OP_DST 0x06
300#define OP_DST_SAT 0x24
301#define OP_MAX 0x0F
302#define OP_MAX_SAT 0x2E
303#define OP_MIN 0x10
304#define OP_MIN_SAT 0x2F
305#define OP_MUL 0x12
306#define OP_MUL_SAT 0x31
307#define OP_SGE 0x16
308#define OP_SGE_SAT 0x37
309#define OP_SLT 0x17
310#define OP_SLT_SAT 0x3A
311#define OP_SUB 0x18
312#define OP_SUB_SAT 0x3B
313#define OP_XPD 0x1A
314#define OP_XPD_SAT 0x43
315#define OP_CMP 0x1D
316#define OP_CMP_SAT 0x1E
317#define OP_LRP 0x2B
318#define OP_LRP_SAT 0x2C
319#define OP_MAD 0x0E
320#define OP_MAD_SAT 0x2D
321#define OP_SWZ 0x19
322#define OP_SWZ_SAT 0x3C
323#define OP_TEX 0x3D
324#define OP_TEX_SAT 0x3E
325#define OP_TXB 0x3F
326#define OP_TXB_SAT 0x40
327#define OP_TXP 0x41
328#define OP_TXP_SAT 0x42
329#define OP_KIL 0x28
330
331/* GL_ARB_vertex_program instruction code */
332#define OP_ARL 0x02
333/* OP_ABS */
334/* OP_FLR */
335/* OP_FRC */
336/* OP_LIT */
337/* OP_MOV */
338/* OP_EX2 */
339#define OP_EXP 0x08
340/* OP_LG2 */
341#define OP_LOG 0x0D
342/* OP_RCP */
343/* OP_RSQ */
344/* OP_POW */
345/* OP_ADD */
346/* OP_DP3 */
347/* OP_DP4 */
348/* OP_DPH */
349/* OP_DST */
350/* OP_MAX */
351/* OP_MIN */
352/* OP_MUL */
353/* OP_SGE */
354/* OP_SLT */
355/* OP_SUB */
356/* OP_XPD */
357/* OP_MAD */
358/* OP_SWZ */
359
360/* fragment attribute binding */
361#define FRAGMENT_ATTRIB_COLOR 0x01
362#define FRAGMENT_ATTRIB_TEXCOORD 0x02
363#define FRAGMENT_ATTRIB_FOGCOORD 0x03
364#define FRAGMENT_ATTRIB_POSITION 0x04
365
366/* vertex attribute binding */
367#define VERTEX_ATTRIB_POSITION 0x01
368#define VERTEX_ATTRIB_WEIGHT 0x02
369#define VERTEX_ATTRIB_NORMAL 0x03
370#define VERTEX_ATTRIB_COLOR 0x04
371#define VERTEX_ATTRIB_FOGCOORD 0x05
372#define VERTEX_ATTRIB_TEXCOORD 0x06
373#define VERTEX_ATTRIB_MATRIXINDEX 0x07
374#define VERTEX_ATTRIB_GENERIC 0x08
375
376/* fragment result binding */
377#define FRAGMENT_RESULT_COLOR 0x01
378#define FRAGMENT_RESULT_DEPTH 0x02
379
380/* vertex result binding */
381#define VERTEX_RESULT_POSITION 0x01
382#define VERTEX_RESULT_COLOR 0x02
383#define VERTEX_RESULT_FOGCOORD 0x03
384#define VERTEX_RESULT_POINTSIZE 0x04
385#define VERTEX_RESULT_TEXCOORD 0x05
386
387/* texture target */
388#define TEXTARGET_1D 0x01
389#define TEXTARGET_2D 0x02
390#define TEXTARGET_3D 0x03
391#define TEXTARGET_RECT 0x04
392#define TEXTARGET_CUBE 0x05
393/* GL_ARB_fragment_program_shadow */
394#define TEXTARGET_SHADOW1D 0x06
395#define TEXTARGET_SHADOW2D 0x07
396#define TEXTARGET_SHADOWRECT 0x08
Ian Romanickbb372f12007-05-16 15:34:22 -0700397/* GL_MESA_texture_array */
398#define TEXTARGET_1D_ARRAY 0x09
399#define TEXTARGET_2D_ARRAY 0x0a
Ian Romanick69358e72007-06-05 09:24:27 -0700400#define TEXTARGET_SHADOW1D_ARRAY 0x0b
401#define TEXTARGET_SHADOW2D_ARRAY 0x0c
Jouk Jansen40322e12004-04-05 08:50:36 +0000402
403/* face type */
404#define FACE_FRONT 0x00
405#define FACE_BACK 0x01
406
407/* color type */
408#define COLOR_PRIMARY 0x00
409#define COLOR_SECONDARY 0x01
410
411/* component */
412#define COMPONENT_X 0x00
413#define COMPONENT_Y 0x01
414#define COMPONENT_Z 0x02
415#define COMPONENT_W 0x03
416#define COMPONENT_0 0x04
417#define COMPONENT_1 0x05
418
419/* array index type */
420#define ARRAY_INDEX_ABSOLUTE 0x00
421#define ARRAY_INDEX_RELATIVE 0x01
422
423/* matrix name */
424#define MATRIX_MODELVIEW 0x01
425#define MATRIX_PROJECTION 0x02
426#define MATRIX_MVP 0x03
427#define MATRIX_TEXTURE 0x04
428#define MATRIX_PALETTE 0x05
429#define MATRIX_PROGRAM 0x06
430
431/* matrix modifier */
432#define MATRIX_MODIFIER_IDENTITY 0x00
433#define MATRIX_MODIFIER_INVERSE 0x01
434#define MATRIX_MODIFIER_TRANSPOSE 0x02
435#define MATRIX_MODIFIER_INVTRANS 0x03
436
437/* constant type */
438#define CONSTANT_SCALAR 0x01
439#define CONSTANT_VECTOR 0x02
440
441/* program param type */
442#define PROGRAM_PARAM_ENV 0x01
443#define PROGRAM_PARAM_LOCAL 0x02
444
445/* register type */
446#define REGISTER_ATTRIB 0x01
447#define REGISTER_PARAM 0x02
448#define REGISTER_RESULT 0x03
449#define REGISTER_ESTABLISHED_NAME 0x04
450
451/* param binding */
452#define PARAM_NULL 0x00
453#define PARAM_ARRAY_ELEMENT 0x01
454#define PARAM_STATE_ELEMENT 0x02
455#define PARAM_PROGRAM_ELEMENT 0x03
456#define PARAM_PROGRAM_ELEMENTS 0x04
457#define PARAM_CONSTANT 0x05
458
459/* param state property */
460#define STATE_MATERIAL_PARSER 0x01
461#define STATE_LIGHT_PARSER 0x02
462#define STATE_LIGHT_MODEL 0x03
463#define STATE_LIGHT_PROD 0x04
464#define STATE_FOG 0x05
465#define STATE_MATRIX_ROWS 0x06
466/* GL_ARB_fragment_program */
467#define STATE_TEX_ENV 0x07
468#define STATE_DEPTH 0x08
469/* GL_ARB_vertex_program */
470#define STATE_TEX_GEN 0x09
471#define STATE_CLIP_PLANE 0x0A
472#define STATE_POINT 0x0B
473
474/* state material property */
475#define MATERIAL_AMBIENT 0x01
476#define MATERIAL_DIFFUSE 0x02
477#define MATERIAL_SPECULAR 0x03
478#define MATERIAL_EMISSION 0x04
479#define MATERIAL_SHININESS 0x05
480
481/* state light property */
482#define LIGHT_AMBIENT 0x01
483#define LIGHT_DIFFUSE 0x02
484#define LIGHT_SPECULAR 0x03
485#define LIGHT_POSITION 0x04
486#define LIGHT_ATTENUATION 0x05
487#define LIGHT_HALF 0x06
488#define LIGHT_SPOT_DIRECTION 0x07
489
490/* state light model property */
491#define LIGHT_MODEL_AMBIENT 0x01
492#define LIGHT_MODEL_SCENECOLOR 0x02
493
494/* state light product property */
495#define LIGHT_PROD_AMBIENT 0x01
496#define LIGHT_PROD_DIFFUSE 0x02
497#define LIGHT_PROD_SPECULAR 0x03
498
499/* state texture environment property */
500#define TEX_ENV_COLOR 0x01
501
502/* state texture generation coord property */
503#define TEX_GEN_EYE 0x01
504#define TEX_GEN_OBJECT 0x02
505
506/* state fog property */
507#define FOG_COLOR 0x01
508#define FOG_PARAMS 0x02
509
510/* state depth property */
511#define DEPTH_RANGE 0x01
512
513/* state point parameters property */
514#define POINT_SIZE 0x01
515#define POINT_ATTENUATION 0x02
516
517/* declaration */
518#define ATTRIB 0x01
519#define PARAM 0x02
520#define TEMP 0x03
521#define OUTPUT 0x04
522#define ALIAS 0x05
523/* GL_ARB_vertex_program */
524#define ADDRESS 0x06
525
526/*-----------------------------------------------------------------------
527 * From here on down is the semantic checking portion
528 *
529 */
530
531/**
532 * Variable Table Handling functions
533 */
534typedef enum
535{
536 vt_none,
537 vt_address,
538 vt_attrib,
539 vt_param,
540 vt_temp,
541 vt_output,
542 vt_alias
543} var_type;
544
545
Brian Paul7aebaf32005-10-30 21:23:23 +0000546/**
547 * Setting an explicit field for each of the binding properties is a bit
548 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000549 */
550struct var_cache
551{
Brian Paul6a769d92006-04-28 15:42:15 +0000552 const GLubyte *name; /* don't free() - no need */
Jouk Jansen40322e12004-04-05 08:50:36 +0000553 var_type type;
554 GLuint address_binding; /* The index of the address register we should
555 * be using */
556 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
Jouk Jansen40322e12004-04-05 08:50:36 +0000557 GLuint attrib_is_generic; /* If the attrib was specified through a generic
558 * vertex attrib */
559 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000560 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000561 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
562 * that this is aliased to */
563 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
564 * PROGRAM_ENV_PARAM} */
565 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
566 * the tokens representing our bound state (or constants)
567 * start */
568 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
569 * we take up with our state tokens or constants. Note that
570 * this is _not_ the same as the number of param registers
571 * we eventually use */
572 struct var_cache *next;
573};
574
575static GLvoid
576var_cache_create (struct var_cache **va)
577{
578 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
579 if (*va) {
580 (**va).name = NULL;
581 (**va).type = vt_none;
582 (**va).attrib_binding = ~0;
583 (**va).attrib_is_generic = 0;
584 (**va).temp_binding = ~0;
585 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000586 (**va).param_binding_type = ~0;
587 (**va).param_binding_begin = ~0;
588 (**va).param_binding_length = ~0;
589 (**va).alias_binding = NULL;
590 (**va).next = NULL;
591 }
592}
593
594static GLvoid
595var_cache_destroy (struct var_cache **va)
596{
597 if (*va) {
598 var_cache_destroy (&(**va).next);
599 _mesa_free (*va);
600 *va = NULL;
601 }
602}
603
604static GLvoid
605var_cache_append (struct var_cache **va, struct var_cache *nv)
606{
607 if (*va)
608 var_cache_append (&(**va).next, nv);
609 else
610 *va = nv;
611}
612
613static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000614var_cache_find (struct var_cache *va, const GLubyte * name)
Jouk Jansen40322e12004-04-05 08:50:36 +0000615{
Brian Paul0a360cf2005-01-17 01:21:03 +0000616 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000617
618 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000619 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000620 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000621 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000622 return va;
623 }
624
625 va = va->next;
626 }
627
628 return NULL;
629}
630
Brian Paula088f162006-09-05 23:08:51 +0000631
632
633/**
634 * Called when an error is detected while parsing/compiling a program.
635 * Sets the ctx->Program.ErrorString field to descript and records a
636 * GL_INVALID_OPERATION error.
637 * \param position position of error in program string
638 * \param descrip verbose error description
639 */
640static void
641program_error(GLcontext *ctx, GLint position, const char *descrip)
642{
643 if (descrip) {
644 const char *prefix = "glProgramString(", *suffix = ")";
645 char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
646 _mesa_strlen(prefix) +
647 _mesa_strlen(suffix) + 1);
648 if (str) {
649 _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
650 _mesa_error(ctx, GL_INVALID_OPERATION, str);
651 _mesa_free(str);
652 }
653 }
654 _mesa_set_program_error(ctx, position, descrip);
655}
656
657
Brian50a20d42008-03-27 15:51:07 -0600658/**
659 * As above, but with an extra string parameter for more info.
660 */
661static void
662program_error2(GLcontext *ctx, GLint position, const char *descrip,
663 const char *var)
664{
665 if (descrip) {
666 const char *prefix = "glProgramString(", *suffix = ")";
667 char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
668 _mesa_strlen(": ") +
669 _mesa_strlen(var) +
670 _mesa_strlen(prefix) +
671 _mesa_strlen(suffix) + 1);
672 if (str) {
673 _mesa_sprintf(str, "%s%s: %s%s", prefix, descrip, var, suffix);
674 _mesa_error(ctx, GL_INVALID_OPERATION, str);
675 _mesa_free(str);
676 }
677 }
678 {
679 char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
680 _mesa_strlen(": ") +
681 _mesa_strlen(var) + 1);
682 if (str) {
683 _mesa_sprintf(str, "%s: %s", descrip, var);
684 }
685 _mesa_set_program_error(ctx, position, str);
686 if (str) {
687 _mesa_free(str);
688 }
689 }
690}
691
692
Brian Paula088f162006-09-05 23:08:51 +0000693
Jouk Jansen40322e12004-04-05 08:50:36 +0000694/**
695 * constructs an integer from 4 GLubytes in LE format
696 */
697static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000698parse_position (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000699{
700 GLuint value;
701
702 value = (GLuint) (*(*inst)++);
703 value += (GLuint) (*(*inst)++) * 0x100;
704 value += (GLuint) (*(*inst)++) * 0x10000;
705 value += (GLuint) (*(*inst)++) * 0x1000000;
706
707 return value;
708}
709
710/**
711 * This will, given a string, lookup the string as a variable name in the
712 * var cache. If the name is found, the var cache node corresponding to the
713 * var name is returned. If it is not found, a new entry is allocated
714 *
715 * \param I Points into the binary array where the string identifier begins
716 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
717 * \return The location on the var_cache corresponding the the string starting at I
718 */
719static struct var_cache *
Brian Paula088f162006-09-05 23:08:51 +0000720parse_string (const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +0000721 struct arb_program *Program, GLuint * found)
722{
Brian Paula088f162006-09-05 23:08:51 +0000723 const GLubyte *i = *inst;
Jouk Jansen40322e12004-04-05 08:50:36 +0000724 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000725 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000726
727 *inst += _mesa_strlen ((char *) i) + 1;
728
729 va = var_cache_find (*vc_head, i);
730
731 if (va) {
732 *found = 1;
733 return va;
734 }
735
736 *found = 0;
737 var_cache_create (&va);
Brian Paul6a769d92006-04-28 15:42:15 +0000738 va->name = (const GLubyte *) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000739
740 var_cache_append (vc_head, va);
741
742 return va;
743}
744
745static char *
Brian Paula088f162006-09-05 23:08:51 +0000746parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000747{
Brian Paula088f162006-09-05 23:08:51 +0000748 const GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000749 (void) Program;
750
Jouk Jansen40322e12004-04-05 08:50:36 +0000751 *inst += _mesa_strlen ((char *) i) + 1;
752
753 return (char *) i;
754}
755
756/**
Brian Paul05908952004-06-08 15:20:23 +0000757 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000758 */
Brian Paul05908952004-06-08 15:20:23 +0000759static GLint
Brian Paula088f162006-09-05 23:08:51 +0000760parse_sign (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +0000761{
762 /*return *(*inst)++ != '+'; */
763
764 if (**inst == '-') {
765 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000766 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000767 }
768 else if (**inst == '+') {
769 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000770 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000771 }
772
Brian Paul05908952004-06-08 15:20:23 +0000773 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000774}
775
776/**
777 * parses and returns signed integer
778 */
779static GLint
Brian Paula088f162006-09-05 23:08:51 +0000780parse_integer (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000781{
782 GLint sign;
783 GLint value;
784
785 /* check if *inst points to '+' or '-'
786 * if yes, grab the sign and increment *inst
787 */
788 sign = parse_sign (inst);
789
790 /* now check if *inst points to 0
791 * if yes, increment the *inst and return the default value
792 */
793 if (**inst == 0) {
794 (*inst)++;
795 return 0;
796 }
797
798 /* parse the integer as you normally would do it */
799 value = _mesa_atoi (parse_string_without_adding (inst, Program));
800
801 /* now, after terminating 0 there is a position
802 * to parse it - parse_position()
803 */
804 Program->Position = parse_position (inst);
805
Brian Paul05908952004-06-08 15:20:23 +0000806 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000807}
808
809/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000810 Accumulate this string of digits, and return them as
811 a large integer represented in floating point (for range).
812 If scale is not NULL, also accumulates a power-of-ten
813 integer scale factor that represents the number of digits
814 in the string.
815*/
816static GLdouble
Brian Paula088f162006-09-05 23:08:51 +0000817parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
Brian Paul1ff8f502005-02-16 15:08:29 +0000818{
819 GLdouble value = 0.0;
820 GLdouble oscale = 1.0;
821
822 if (**inst == 0) { /* this string of digits is empty-- do nothing */
823 (*inst)++;
824 }
825 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000826 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000827 GLubyte digit = *((*inst)++);
828 value = value * 10.0 + (GLint) (digit - '0');
829 oscale *= 10.0;
830 }
831 assert(**inst == 0); /* integer string should end with 0 */
832 (*inst)++; /* skip over terminating 0 */
833 Program->Position = parse_position(inst); /* skip position (from integer) */
834 }
835 if (scale)
836 *scale = oscale;
837 return value;
838}
839
840/**
841 Parse an unsigned floating-point number from this stream of tokenized
842 characters. Example floating-point formats supported:
843 12.34
844 12
845 0.34
846 .34
847 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000848 */
849static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000850parse_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000851{
Brian Paul1ff8f502005-02-16 15:08:29 +0000852 GLint exponent;
853 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000854
Brian Paul1ff8f502005-02-16 15:08:29 +0000855 whole = parse_float_string(inst, Program, 0);
856 fraction = parse_float_string(inst, Program, &fracScale);
857
858 /* Parse signed exponent */
859 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000860
Brian Paul1ff8f502005-02-16 15:08:29 +0000861 /* Assemble parts of floating-point number: */
862 return (GLfloat) ((whole + fraction / fracScale) *
863 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000864}
865
866
867/**
868 */
869static GLfloat
Brian Paula088f162006-09-05 23:08:51 +0000870parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +0000871{
Brian Paul05908952004-06-08 15:20:23 +0000872 GLint sign = parse_sign (inst);
873 GLfloat value = parse_float (inst, Program);
874 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000875}
876
877/**
878 * This picks out a constant value from the parsed array. The constant vector is r
879 * returned in the *values array, which should be of length 4.
880 *
881 * \param values - The 4 component vector with the constant value in it
882 */
883static GLvoid
Brian Paula088f162006-09-05 23:08:51 +0000884parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000885 GLboolean use)
886{
887 GLuint components, i;
888
889
890 switch (*(*inst)++) {
891 case CONSTANT_SCALAR:
892 if (use == GL_TRUE) {
893 values[0] =
894 values[1] =
895 values[2] = values[3] = parse_float (inst, Program);
896 }
897 else {
898 values[0] =
899 values[1] =
900 values[2] = values[3] = parse_signed_float (inst, Program);
901 }
902
903 break;
904 case CONSTANT_VECTOR:
905 values[0] = values[1] = values[2] = 0;
906 values[3] = 1;
907 components = *(*inst)++;
908 for (i = 0; i < components; i++) {
909 values[i] = parse_signed_float (inst, Program);
910 }
911 break;
912 }
913}
914
915/**
916 * \param offset The offset from the address register that we should
917 * address
918 *
919 * \return 0 on sucess, 1 on error
920 */
921static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000922parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
923 struct arb_program *Program, GLint *offset)
Jouk Jansen40322e12004-04-05 08:50:36 +0000924{
Brian Paul6a769d92006-04-28 15:42:15 +0000925 (void) ctx;
Jouk Jansen40322e12004-04-05 08:50:36 +0000926 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000927 return 0;
928}
929
930/**
931 * \param color 0 if color type is primary, 1 if color type is secondary
932 * \return 0 on sucess, 1 on error
933 */
934static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000935parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +0000936 GLint * color)
937{
Brian Paula6c423d2004-08-25 15:59:48 +0000938 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000939 *color = *(*inst)++ != COLOR_PRIMARY;
940 return 0;
941}
942
943/**
944 * Get an integer corresponding to a generic vertex attribute.
945 *
946 * \return 0 on sucess, 1 on error
947 */
948static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000949parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000950 struct arb_program *Program, GLuint *attrib)
951{
Brian Paulbd997cd2004-07-20 21:12:56 +0000952 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000953
Michal Krolbb38cad2006-04-11 11:41:11 +0000954 if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000955 {
Brian Paula088f162006-09-05 23:08:51 +0000956 program_error(ctx, Program->Position,
957 "Invalid generic vertex attribute index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000958 return 1;
959 }
960
Brian Paulbd997cd2004-07-20 21:12:56 +0000961 *attrib = (GLuint) i;
962
Jouk Jansen40322e12004-04-05 08:50:36 +0000963 return 0;
964}
965
966
967/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000968 * \param color The index of the color buffer to write into
969 * \return 0 on sucess, 1 on error
970 */
971static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000972parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
Brian Paulbe76b7f2004-10-04 14:40:05 +0000973 struct arb_program *Program, GLuint * color)
974{
975 GLint i = parse_integer (inst, Program);
976
977 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
Brian Paula088f162006-09-05 23:08:51 +0000978 program_error(ctx, Program->Position, "Invalid draw buffer index");
Brian Paulbe76b7f2004-10-04 14:40:05 +0000979 return 1;
980 }
981
982 *color = (GLuint) i;
983 return 0;
984}
985
986
987/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000988 * \param coord The texture unit index
989 * \return 0 on sucess, 1 on error
990 */
991static GLuint
Brian Paula088f162006-09-05 23:08:51 +0000992parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +0000993 struct arb_program *Program, GLuint * coord)
994{
Brian Paulbd997cd2004-07-20 21:12:56 +0000995 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000996
Brian Paula6c423d2004-08-25 15:59:48 +0000997 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Brian Paula088f162006-09-05 23:08:51 +0000998 program_error(ctx, Program->Position, "Invalid texture unit index");
Jouk Jansen40322e12004-04-05 08:50:36 +0000999 return 1;
1000 }
1001
Brian Paulbd997cd2004-07-20 21:12:56 +00001002 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +00001003 return 0;
1004}
1005
1006/**
1007 * \param coord The weight index
1008 * \return 0 on sucess, 1 on error
1009 */
1010static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001011parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +00001012 GLint * coord)
1013{
1014 *coord = parse_integer (inst, Program);
1015
1016 if ((*coord < 0) || (*coord >= 1)) {
Brian Paula088f162006-09-05 23:08:51 +00001017 program_error(ctx, Program->Position, "Invalid weight index");
Jouk Jansen40322e12004-04-05 08:50:36 +00001018 return 1;
1019 }
1020
1021 return 0;
1022}
1023
1024/**
1025 * \param coord The clip plane index
1026 * \return 0 on sucess, 1 on error
1027 */
1028static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001029parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00001030 struct arb_program *Program, GLint * coord)
1031{
1032 *coord = parse_integer (inst, Program);
1033
1034 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
Brian Paula088f162006-09-05 23:08:51 +00001035 program_error(ctx, Program->Position, "Invalid clip plane index");
Jouk Jansen40322e12004-04-05 08:50:36 +00001036 return 1;
1037 }
1038
1039 return 0;
1040}
1041
1042
1043/**
1044 * \return 0 on front face, 1 on back face
1045 */
1046static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001047parse_face_type (const GLubyte ** inst)
Jouk Jansen40322e12004-04-05 08:50:36 +00001048{
1049 switch (*(*inst)++) {
1050 case FACE_FRONT:
1051 return 0;
1052
1053 case FACE_BACK:
1054 return 1;
1055 }
1056 return 0;
1057}
1058
1059
1060/**
1061 * Given a matrix and a modifier token on the binary array, return tokens
1062 * that _mesa_fetch_state() [program.c] can understand.
1063 *
1064 * \param matrix - the matrix we are talking about
1065 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
1066 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
1067 * \return 0 on sucess, 1 on failure
1068 */
1069static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001070parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
Jouk Jansen40322e12004-04-05 08:50:36 +00001071 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
1072{
1073 GLubyte mat = *(*inst)++;
1074
1075 *matrix_idx = 0;
1076
1077 switch (mat) {
1078 case MATRIX_MODELVIEW:
Brian65319522007-02-21 11:08:21 -07001079 *matrix = STATE_MODELVIEW_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001080 *matrix_idx = parse_integer (inst, Program);
1081 if (*matrix_idx > 0) {
Brian Paula088f162006-09-05 23:08:51 +00001082 program_error(ctx, Program->Position,
1083 "ARB_vertex_blend not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001084 return 1;
1085 }
1086 break;
1087
1088 case MATRIX_PROJECTION:
Brian65319522007-02-21 11:08:21 -07001089 *matrix = STATE_PROJECTION_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001090 break;
1091
1092 case MATRIX_MVP:
Brian65319522007-02-21 11:08:21 -07001093 *matrix = STATE_MVP_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001094 break;
1095
1096 case MATRIX_TEXTURE:
Brian65319522007-02-21 11:08:21 -07001097 *matrix = STATE_TEXTURE_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001098 *matrix_idx = parse_integer (inst, Program);
1099 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
Brian Paula088f162006-09-05 23:08:51 +00001100 program_error(ctx, Program->Position, "Invalid Texture Unit");
1101 /* bad *matrix_id */
Jouk Jansen40322e12004-04-05 08:50:36 +00001102 return 1;
1103 }
1104 break;
1105
1106 /* This is not currently supported (ARB_matrix_palette) */
1107 case MATRIX_PALETTE:
1108 *matrix_idx = parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001109 program_error(ctx, Program->Position,
1110 "ARB_matrix_palette not supported");
Jouk Jansen40322e12004-04-05 08:50:36 +00001111 return 1;
1112 break;
1113
1114 case MATRIX_PROGRAM:
Brian65319522007-02-21 11:08:21 -07001115 *matrix = STATE_PROGRAM_MATRIX;
Jouk Jansen40322e12004-04-05 08:50:36 +00001116 *matrix_idx = parse_integer (inst, Program);
1117 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
Brian Paula088f162006-09-05 23:08:51 +00001118 program_error(ctx, Program->Position, "Invalid Program Matrix");
1119 /* bad *matrix_idx */
Jouk Jansen40322e12004-04-05 08:50:36 +00001120 return 1;
1121 }
1122 break;
1123 }
1124
1125 switch (*(*inst)++) {
1126 case MATRIX_MODIFIER_IDENTITY:
1127 *matrix_modifier = 0;
1128 break;
1129 case MATRIX_MODIFIER_INVERSE:
1130 *matrix_modifier = STATE_MATRIX_INVERSE;
1131 break;
1132 case MATRIX_MODIFIER_TRANSPOSE:
1133 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1134 break;
1135 case MATRIX_MODIFIER_INVTRANS:
1136 *matrix_modifier = STATE_MATRIX_INVTRANS;
1137 break;
1138 }
1139
1140 return 0;
1141}
1142
1143
1144/**
1145 * This parses a state string (rather, the binary version of it) into
1146 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1147 *
1148 * \param inst - the start in the binary arry to start working from
1149 * \param state_tokens - the storage for the 6-token state description
1150 * \return - 0 on sucess, 1 on error
1151 */
1152static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001153parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001154 struct arb_program *Program,
1155 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001156{
Brian Paul57f2d072008-07-09 08:47:23 -06001157 GLubyte token = *(*inst)++;
1158
1159 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001160 case STATE_MATERIAL_PARSER:
1161 state_tokens[0] = STATE_MATERIAL;
1162 state_tokens[1] = parse_face_type (inst);
1163 switch (*(*inst)++) {
1164 case MATERIAL_AMBIENT:
1165 state_tokens[2] = STATE_AMBIENT;
1166 break;
1167 case MATERIAL_DIFFUSE:
1168 state_tokens[2] = STATE_DIFFUSE;
1169 break;
1170 case MATERIAL_SPECULAR:
1171 state_tokens[2] = STATE_SPECULAR;
1172 break;
1173 case MATERIAL_EMISSION:
1174 state_tokens[2] = STATE_EMISSION;
1175 break;
1176 case MATERIAL_SHININESS:
1177 state_tokens[2] = STATE_SHININESS;
1178 break;
1179 }
1180 break;
1181
1182 case STATE_LIGHT_PARSER:
1183 state_tokens[0] = STATE_LIGHT;
1184 state_tokens[1] = parse_integer (inst, Program);
1185
1186 /* Check the value of state_tokens[1] against the # of lights */
1187 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001188 program_error(ctx, Program->Position, "Invalid Light Number");
1189 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001190 return 1;
1191 }
1192
1193 switch (*(*inst)++) {
1194 case LIGHT_AMBIENT:
1195 state_tokens[2] = STATE_AMBIENT;
1196 break;
1197 case LIGHT_DIFFUSE:
1198 state_tokens[2] = STATE_DIFFUSE;
1199 break;
1200 case LIGHT_SPECULAR:
1201 state_tokens[2] = STATE_SPECULAR;
1202 break;
1203 case LIGHT_POSITION:
1204 state_tokens[2] = STATE_POSITION;
1205 break;
1206 case LIGHT_ATTENUATION:
1207 state_tokens[2] = STATE_ATTENUATION;
1208 break;
1209 case LIGHT_HALF:
Brianf958aab2007-02-21 15:23:11 -07001210 state_tokens[2] = STATE_HALF_VECTOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001211 break;
1212 case LIGHT_SPOT_DIRECTION:
1213 state_tokens[2] = STATE_SPOT_DIRECTION;
1214 break;
1215 }
1216 break;
1217
1218 case STATE_LIGHT_MODEL:
1219 switch (*(*inst)++) {
1220 case LIGHT_MODEL_AMBIENT:
1221 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1222 break;
1223 case LIGHT_MODEL_SCENECOLOR:
1224 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1225 state_tokens[1] = parse_face_type (inst);
1226 break;
1227 }
1228 break;
1229
1230 case STATE_LIGHT_PROD:
1231 state_tokens[0] = STATE_LIGHTPROD;
1232 state_tokens[1] = parse_integer (inst, Program);
1233
1234 /* Check the value of state_tokens[1] against the # of lights */
1235 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
Brian Paula088f162006-09-05 23:08:51 +00001236 program_error(ctx, Program->Position, "Invalid Light Number");
1237 /* bad state_tokens[1] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001238 return 1;
1239 }
1240
1241 state_tokens[2] = parse_face_type (inst);
1242 switch (*(*inst)++) {
1243 case LIGHT_PROD_AMBIENT:
1244 state_tokens[3] = STATE_AMBIENT;
1245 break;
1246 case LIGHT_PROD_DIFFUSE:
1247 state_tokens[3] = STATE_DIFFUSE;
1248 break;
1249 case LIGHT_PROD_SPECULAR:
1250 state_tokens[3] = STATE_SPECULAR;
1251 break;
1252 }
1253 break;
1254
1255
1256 case STATE_FOG:
1257 switch (*(*inst)++) {
1258 case FOG_COLOR:
Brianf1390a32007-02-23 17:11:01 -07001259 state_tokens[0] = STATE_FOG_COLOR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001260 break;
1261 case FOG_PARAMS:
Brianf1390a32007-02-23 17:11:01 -07001262 state_tokens[0] = STATE_FOG_PARAMS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001263 break;
1264 }
1265 break;
1266
1267 case STATE_TEX_ENV:
1268 state_tokens[1] = parse_integer (inst, Program);
1269 switch (*(*inst)++) {
1270 case TEX_ENV_COLOR:
1271 state_tokens[0] = STATE_TEXENV_COLOR;
1272 break;
1273 }
1274 break;
1275
1276 case STATE_TEX_GEN:
1277 {
1278 GLuint type, coord;
1279
1280 state_tokens[0] = STATE_TEXGEN;
1281 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1282
1283 if (parse_texcoord_num (ctx, inst, Program, &coord))
1284 return 1;
1285 state_tokens[1] = coord;
1286
1287 /* EYE or OBJECT */
Brian7b91d872008-03-27 15:48:54 -06001288 type = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001289
1290 /* 0 - s, 1 - t, 2 - r, 3 - q */
Brian7b91d872008-03-27 15:48:54 -06001291 coord = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001292
1293 if (type == TEX_GEN_EYE) {
1294 switch (coord) {
1295 case COMPONENT_X:
1296 state_tokens[2] = STATE_TEXGEN_EYE_S;
1297 break;
1298 case COMPONENT_Y:
1299 state_tokens[2] = STATE_TEXGEN_EYE_T;
1300 break;
1301 case COMPONENT_Z:
1302 state_tokens[2] = STATE_TEXGEN_EYE_R;
1303 break;
1304 case COMPONENT_W:
1305 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1306 break;
Brian7b91d872008-03-27 15:48:54 -06001307 default:
1308 _mesa_problem(ctx, "bad texgen component in "
1309 "parse_state_single_item()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001310 }
1311 }
1312 else {
1313 switch (coord) {
1314 case COMPONENT_X:
1315 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1316 break;
1317 case COMPONENT_Y:
1318 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1319 break;
1320 case COMPONENT_Z:
1321 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1322 break;
1323 case COMPONENT_W:
1324 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1325 break;
Brian7b91d872008-03-27 15:48:54 -06001326 default:
1327 _mesa_problem(ctx, "bad texgen component in "
1328 "parse_state_single_item()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001329 }
1330 }
1331 }
1332 break;
1333
1334 case STATE_DEPTH:
1335 switch (*(*inst)++) {
1336 case DEPTH_RANGE:
1337 state_tokens[0] = STATE_DEPTH_RANGE;
1338 break;
1339 }
1340 break;
1341
1342 case STATE_CLIP_PLANE:
1343 state_tokens[0] = STATE_CLIPPLANE;
Brianaa9d22a2007-02-23 11:21:03 -07001344 if (parse_clipplane_num (ctx, inst, Program,
1345 (GLint *) &state_tokens[1]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001346 return 1;
1347 break;
1348
1349 case STATE_POINT:
Brian7b91d872008-03-27 15:48:54 -06001350 switch (*(*inst)++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001351 case POINT_SIZE:
Brian776bc9c2007-02-22 09:29:46 -07001352 state_tokens[0] = STATE_POINT_SIZE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001353 break;
1354
1355 case POINT_ATTENUATION:
Brian776bc9c2007-02-22 09:29:46 -07001356 state_tokens[0] = STATE_POINT_ATTENUATION;
Jouk Jansen40322e12004-04-05 08:50:36 +00001357 break;
1358 }
1359 break;
1360
1361 /* XXX: I think this is the correct format for a matrix row */
1362 case STATE_MATRIX_ROWS:
Brianaa9d22a2007-02-23 11:21:03 -07001363 if (parse_matrix(ctx, inst, Program,
1364 (GLint *) &state_tokens[0],
1365 (GLint *) &state_tokens[1],
1366 (GLint *) &state_tokens[4]))
Jouk Jansen40322e12004-04-05 08:50:36 +00001367 return 1;
1368
Brian65319522007-02-21 11:08:21 -07001369 state_tokens[2] = parse_integer (inst, Program); /* The first row to grab */
Jouk Jansen40322e12004-04-05 08:50:36 +00001370
1371 if ((**inst) != 0) { /* Either the last row, 0 */
Brian65319522007-02-21 11:08:21 -07001372 state_tokens[3] = parse_integer (inst, Program);
1373 if (state_tokens[3] < state_tokens[2]) {
Brian Paula088f162006-09-05 23:08:51 +00001374 program_error(ctx, Program->Position,
1375 "Second matrix index less than the first");
1376 /* state_tokens[4] vs. state_tokens[3] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001377 return 1;
1378 }
1379 }
1380 else {
Brian65319522007-02-21 11:08:21 -07001381 state_tokens[3] = state_tokens[2];
Jouk Jansen40322e12004-04-05 08:50:36 +00001382 (*inst)++;
1383 }
1384 break;
1385 }
1386
1387 return 0;
1388}
1389
1390/**
1391 * This parses a state string (rather, the binary version of it) into
1392 * a 6-token similar for the state fetching code in program.c
1393 *
1394 * One might ask, why fetch these parameters into just like you fetch
1395 * state when they are already stored in other places?
1396 *
1397 * Because of array offsets -> We can stick env/local parameters in the
1398 * middle of a parameter array and then index someplace into the array
1399 * when we execute.
1400 *
1401 * One optimization might be to only do this for the cases where the
1402 * env/local parameters end up inside of an array, and leave the
1403 * single parameters (or arrays of pure env/local pareameters) in their
1404 * respective register files.
1405 *
1406 * For ENV parameters, the format is:
1407 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1408 * state_tokens[1] = STATE_ENV
1409 * state_tokens[2] = the parameter index
1410 *
1411 * for LOCAL parameters, the format is:
1412 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1413 * state_tokens[1] = STATE_LOCAL
1414 * state_tokens[2] = the parameter index
1415 *
1416 * \param inst - the start in the binary arry to start working from
1417 * \param state_tokens - the storage for the 6-token state description
1418 * \return - 0 on sucess, 1 on failure
1419 */
1420static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001421parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
Brianaa9d22a2007-02-23 11:21:03 -07001422 struct arb_program *Program,
1423 gl_state_index state_tokens[STATE_LENGTH])
Jouk Jansen40322e12004-04-05 08:50:36 +00001424{
1425 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1426 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1427 else
1428 state_tokens[0] = STATE_VERTEX_PROGRAM;
1429
1430
1431 switch (*(*inst)++) {
1432 case PROGRAM_PARAM_ENV:
1433 state_tokens[1] = STATE_ENV;
1434 state_tokens[2] = parse_integer (inst, Program);
1435
1436 /* Check state_tokens[2] against the number of ENV parameters available */
1437 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001438 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001439 ||
1440 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001441 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001442 program_error(ctx, Program->Position,
1443 "Invalid Program Env Parameter");
1444 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001445 return 1;
1446 }
1447
1448 break;
1449
1450 case PROGRAM_PARAM_LOCAL:
1451 state_tokens[1] = STATE_LOCAL;
1452 state_tokens[2] = parse_integer (inst, Program);
1453
1454 /* Check state_tokens[2] against the number of LOCAL parameters available */
1455 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001456 (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001457 ||
1458 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
Brian Paul05051032005-11-01 04:36:33 +00001459 (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001460 program_error(ctx, Program->Position,
1461 "Invalid Program Local Parameter");
1462 /* bad state_tokens[2] */
Jouk Jansen40322e12004-04-05 08:50:36 +00001463 return 1;
1464 }
1465 break;
1466 }
1467
1468 return 0;
1469}
1470
1471/**
1472 * For ARB_vertex_program, programs are not allowed to use both an explicit
1473 * vertex attribute and a generic vertex attribute corresponding to the same
1474 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1475 *
1476 * This will walk our var_cache and make sure that nobody does anything fishy.
1477 *
1478 * \return 0 on sucess, 1 on error
1479 */
1480static GLuint
1481generic_attrib_check(struct var_cache *vc_head)
1482{
1483 int a;
1484 struct var_cache *curr;
1485 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1486 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1487
1488 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1489 explicitAttrib[a] = GL_FALSE;
1490 genericAttrib[a] = GL_FALSE;
1491 }
1492
1493 curr = vc_head;
1494 while (curr) {
1495 if (curr->type == vt_attrib) {
1496 if (curr->attrib_is_generic)
Brian Paul18e7c5c2005-10-30 21:46:00 +00001497 genericAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001498 else
Brian Paul18e7c5c2005-10-30 21:46:00 +00001499 explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00001500 }
1501
1502 curr = curr->next;
1503 }
1504
1505 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1506 if ((explicitAttrib[a]) && (genericAttrib[a]))
1507 return 1;
1508 }
1509
1510 return 0;
1511}
1512
1513/**
1514 * This will handle the binding side of an ATTRIB var declaration
1515 *
Brian Paul18e7c5c2005-10-30 21:46:00 +00001516 * \param inputReg returns the input register index, one of the
1517 * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
Brian Paula088f162006-09-05 23:08:51 +00001518 * \return returns 0 on success, 1 on error
Jouk Jansen40322e12004-04-05 08:50:36 +00001519 */
1520static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001521parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
Brian Paul18e7c5c2005-10-30 21:46:00 +00001522 struct arb_program *Program,
1523 GLuint *inputReg, GLuint *is_generic)
Jouk Jansen40322e12004-04-05 08:50:36 +00001524{
Jouk Jansen40322e12004-04-05 08:50:36 +00001525 GLint err = 0;
1526
1527 *is_generic = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001528
Jouk Jansen40322e12004-04-05 08:50:36 +00001529 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1530 switch (*(*inst)++) {
1531 case FRAGMENT_ATTRIB_COLOR:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001532 {
1533 GLint coord;
1534 err = parse_color_type (ctx, inst, Program, &coord);
1535 *inputReg = FRAG_ATTRIB_COL0 + coord;
1536 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001537 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001538 case FRAGMENT_ATTRIB_TEXCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001539 {
Brian8fa6f732007-02-01 09:24:41 -07001540 GLuint texcoord = 0;
Brian Paul18e7c5c2005-10-30 21:46:00 +00001541 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1542 *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
1543 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001544 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001545 case FRAGMENT_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001546 *inputReg = FRAG_ATTRIB_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001547 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001548 case FRAGMENT_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001549 *inputReg = FRAG_ATTRIB_WPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001550 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00001551 default:
1552 err = 1;
1553 break;
1554 }
1555 }
1556 else {
1557 switch (*(*inst)++) {
1558 case VERTEX_ATTRIB_POSITION:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001559 *inputReg = VERT_ATTRIB_POS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001560 break;
1561
1562 case VERTEX_ATTRIB_WEIGHT:
1563 {
1564 GLint weight;
Jouk Jansen40322e12004-04-05 08:50:36 +00001565 err = parse_weight_num (ctx, inst, Program, &weight);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001566 *inputReg = VERT_ATTRIB_WEIGHT;
Brian Paul3a557502006-09-05 23:15:29 +00001567#if 1
1568 /* hack for Warcraft (see bug 8060) */
1569 _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
Brian Pauld9aebd82006-09-06 05:03:47 +00001570 break;
Brian Paul3a557502006-09-05 23:15:29 +00001571#else
Brian Paula088f162006-09-05 23:08:51 +00001572 program_error(ctx, Program->Position,
1573 "ARB_vertex_blend not supported");
Brian Pauld9aebd82006-09-06 05:03:47 +00001574 return 1;
Brian Paul3a557502006-09-05 23:15:29 +00001575#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00001576 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001577
1578 case VERTEX_ATTRIB_NORMAL:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001579 *inputReg = VERT_ATTRIB_NORMAL;
Jouk Jansen40322e12004-04-05 08:50:36 +00001580 break;
1581
1582 case VERTEX_ATTRIB_COLOR:
1583 {
1584 GLint color;
Jouk Jansen40322e12004-04-05 08:50:36 +00001585 err = parse_color_type (ctx, inst, Program, &color);
1586 if (color) {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001587 *inputReg = VERT_ATTRIB_COLOR1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001588 }
1589 else {
Brian Paul18e7c5c2005-10-30 21:46:00 +00001590 *inputReg = VERT_ATTRIB_COLOR0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001591 }
1592 }
1593 break;
1594
1595 case VERTEX_ATTRIB_FOGCOORD:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001596 *inputReg = VERT_ATTRIB_FOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00001597 break;
1598
1599 case VERTEX_ATTRIB_TEXCOORD:
1600 {
Brian8fa6f732007-02-01 09:24:41 -07001601 GLuint unit = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001602 err = parse_texcoord_num (ctx, inst, Program, &unit);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001603 *inputReg = VERT_ATTRIB_TEX0 + unit;
Jouk Jansen40322e12004-04-05 08:50:36 +00001604 }
1605 break;
1606
Jouk Jansen40322e12004-04-05 08:50:36 +00001607 case VERTEX_ATTRIB_MATRIXINDEX:
Brian Paul18e7c5c2005-10-30 21:46:00 +00001608 /* Not supported at this time */
1609 {
1610 const char *msg = "ARB_palette_matrix not supported";
1611 parse_integer (inst, Program);
Brian Paula088f162006-09-05 23:08:51 +00001612 program_error(ctx, Program->Position, msg);
Brian Paul18e7c5c2005-10-30 21:46:00 +00001613 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001614 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001615
1616 case VERTEX_ATTRIB_GENERIC:
1617 {
1618 GLuint attrib;
Tilman Sauerbeck6c334752006-06-28 16:26:20 +00001619 err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
Brian Paula088f162006-09-05 23:08:51 +00001620 if (!err) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001621 *is_generic = 1;
Brian Paul095c6692006-04-25 00:21:32 +00001622 /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
1623 * attributes do not alias the conventional vertex
1624 * attributes.
1625 */
1626 if (attrib > 0)
1627 *inputReg = attrib + VERT_ATTRIB_GENERIC0;
Brian Paul919f6a02006-05-29 14:37:56 +00001628 else
1629 *inputReg = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001630 }
1631 }
1632 break;
1633
1634 default:
1635 err = 1;
1636 break;
1637 }
1638 }
1639
Jouk Jansen40322e12004-04-05 08:50:36 +00001640 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00001641 program_error(ctx, Program->Position, "Bad attribute binding");
Jouk Jansen40322e12004-04-05 08:50:36 +00001642 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001643
1644 return err;
1645}
1646
Brian Paul7aebaf32005-10-30 21:23:23 +00001647
Jouk Jansen40322e12004-04-05 08:50:36 +00001648/**
1649 * This translates between a binary token for an output variable type
1650 * and the mesa token for the same thing.
1651 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001652 * \param inst The parsed tokens
1653 * \param outputReg Returned index/number of the output register,
Brian Paul90ebb582005-11-02 18:06:12 +00001654 * one of the VERT_RESULT_* or FRAG_RESULT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001655 */
1656static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001657parse_result_binding(GLcontext *ctx, const GLubyte **inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00001658 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001659{
Brian Paul7aebaf32005-10-30 21:23:23 +00001660 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001661
Brian Paul7aebaf32005-10-30 21:23:23 +00001662 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001663 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001664 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001665 GLuint out_color;
1666
Brian Paulbe76b7f2004-10-04 14:40:05 +00001667 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001668 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001669 */
1670 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001671 ASSERT(out_color < MAX_DRAW_BUFFERS);
Brian Paul90ebb582005-11-02 18:06:12 +00001672 *outputReg = FRAG_RESULT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001673 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001674 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001675 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1676 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001677 }
1678 break;
1679
1680 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001681 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001682 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
Brian Paul90ebb582005-11-02 18:06:12 +00001683 *outputReg = FRAG_RESULT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001684 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001685 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001686 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001687 GLint color_type;
1688 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001689 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1690 if (err)
1691 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001692
Jouk Jansen40322e12004-04-05 08:50:36 +00001693 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001694 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001695 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001696 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001697 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001698 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001699 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001700 }
1701 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001702 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001703 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001704 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001705 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001706 }
1707 /* primary color */
1708 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001709 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001710 }
1711 }
1712 }
1713 break;
1714
1715 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001716 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001717 break;
1718
1719 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001720 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001721 break;
1722
1723 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001724 {
1725 GLuint unit;
1726 if (parse_texcoord_num (ctx, inst, Program, &unit))
1727 return 1;
1728 *outputReg = VERT_RESULT_TEX0 + unit;
1729 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001730 break;
1731 }
1732
Brian Paulde997602005-11-12 17:53:14 +00001733 Program->Base.OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001734
1735 return 0;
1736}
1737
Brian Paul7aebaf32005-10-30 21:23:23 +00001738
Jouk Jansen40322e12004-04-05 08:50:36 +00001739/**
1740 * This handles the declaration of ATTRIB variables
1741 *
1742 * XXX: Still needs
1743 * parse_vert_attrib_binding(), or something like that
1744 *
1745 * \return 0 on sucess, 1 on error
1746 */
1747static GLint
Brian Paula088f162006-09-05 23:08:51 +00001748parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001749 struct arb_program *Program)
1750{
1751 GLuint found;
Jouk Jansen40322e12004-04-05 08:50:36 +00001752 struct var_cache *attrib_var;
1753
1754 attrib_var = parse_string (inst, vc_head, Program, &found);
1755 Program->Position = parse_position (inst);
1756 if (found) {
Brian50a20d42008-03-27 15:51:07 -06001757 program_error2(ctx, Program->Position,
1758 "Duplicate variable declaration",
1759 (char *) attrib_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00001760 return 1;
1761 }
1762
1763 attrib_var->type = vt_attrib;
1764
Brian Paul7aebaf32005-10-30 21:23:23 +00001765 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
Brian Paul7aebaf32005-10-30 21:23:23 +00001766 &attrib_var->attrib_is_generic))
1767 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001768
Brian Paul7aebaf32005-10-30 21:23:23 +00001769 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00001770 program_error(ctx, Program->Position,
1771 "Cannot use both a generic vertex attribute "
1772 "and a specific attribute of the same type");
Brian Paul7aebaf32005-10-30 21:23:23 +00001773 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001774 }
1775
1776 Program->Base.NumAttributes++;
1777 return 0;
1778}
1779
1780/**
1781 * \param use -- TRUE if we're called when declaring implicit parameters,
1782 * FALSE if we're declaraing variables. This has to do with
1783 * if we get a signed or unsigned float for scalar constants
1784 */
1785static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001786parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00001787 struct var_cache *param_var,
1788 struct arb_program *Program, GLboolean use)
1789{
1790 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001791 GLuint err = 0;
Briana0720942008-03-27 15:52:00 -06001792 gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
Jouk Jansen40322e12004-04-05 08:50:36 +00001793 GLfloat const_values[4];
1794
Brian Paul57f2d072008-07-09 08:47:23 -06001795 GLubyte token = *(*inst)++;
1796
1797 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001798 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001799 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1800 return 1;
1801
1802 /* If we adding STATE_MATRIX that has multiple rows, we need to
1803 * unroll it and call _mesa_add_state_reference() for each row
1804 */
Brian65319522007-02-21 11:08:21 -07001805 if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
1806 state_tokens[0] == STATE_PROJECTION_MATRIX ||
1807 state_tokens[0] == STATE_MVP_MATRIX ||
1808 state_tokens[0] == STATE_TEXTURE_MATRIX ||
1809 state_tokens[0] == STATE_PROGRAM_MATRIX)
1810 && (state_tokens[2] != state_tokens[3])) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001811 GLint row;
Brian65319522007-02-21 11:08:21 -07001812 const GLint first_row = state_tokens[2];
1813 const GLint last_row = state_tokens[3];
Jouk Jansen40322e12004-04-05 08:50:36 +00001814
1815 for (row = first_row; row <= last_row; row++) {
Brian65319522007-02-21 11:08:21 -07001816 state_tokens[2] = state_tokens[3] = row;
Jouk Jansen40322e12004-04-05 08:50:36 +00001817
Brian Paulde997602005-11-12 17:53:14 +00001818 idx = _mesa_add_state_reference(Program->Base.Parameters,
1819 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001820 if (param_var->param_binding_begin == ~0U)
1821 param_var->param_binding_begin = idx;
1822 param_var->param_binding_length++;
1823 Program->Base.NumParameters++;
1824 }
1825 }
1826 else {
Brian Paulde997602005-11-12 17:53:14 +00001827 idx = _mesa_add_state_reference(Program->Base.Parameters,
1828 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001829 if (param_var->param_binding_begin == ~0U)
1830 param_var->param_binding_begin = idx;
1831 param_var->param_binding_length++;
1832 Program->Base.NumParameters++;
1833 }
1834 break;
1835
1836 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001837 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1838 return 1;
Brian Paulde997602005-11-12 17:53:14 +00001839 idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001840 if (param_var->param_binding_begin == ~0U)
1841 param_var->param_binding_begin = idx;
1842 param_var->param_binding_length++;
1843 Program->Base.NumParameters++;
1844
1845 /* Check if there is more: 0 -> we're done, else its an integer */
1846 if (**inst) {
1847 GLuint out_of_range, new_idx;
1848 GLuint start_idx = state_tokens[2] + 1;
1849 GLuint end_idx = parse_integer (inst, Program);
1850
1851 out_of_range = 0;
1852 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1853 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001854 && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001855 || ((state_tokens[1] == STATE_LOCAL)
1856 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001857 ctx->Const.FragmentProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001858 out_of_range = 1;
1859 }
1860 else {
1861 if (((state_tokens[1] == STATE_ENV)
Brian Paul05051032005-11-01 04:36:33 +00001862 && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001863 || ((state_tokens[1] == STATE_LOCAL)
1864 && (end_idx >=
Brian Paul05051032005-11-01 04:36:33 +00001865 ctx->Const.VertexProgram.MaxLocalParams)))
Jouk Jansen40322e12004-04-05 08:50:36 +00001866 out_of_range = 1;
1867 }
1868 if (out_of_range) {
Brian Paula088f162006-09-05 23:08:51 +00001869 program_error(ctx, Program->Position,
1870 "Invalid Program Parameter"); /*end_idx*/
Jouk Jansen40322e12004-04-05 08:50:36 +00001871 return 1;
1872 }
1873
1874 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1875 state_tokens[2] = new_idx;
Brian Paulde997602005-11-12 17:53:14 +00001876 idx = _mesa_add_state_reference(Program->Base.Parameters,
1877 state_tokens);
Jouk Jansen40322e12004-04-05 08:50:36 +00001878 param_var->param_binding_length++;
1879 Program->Base.NumParameters++;
1880 }
1881 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001882 else {
1883 (*inst)++;
1884 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001885 break;
1886
1887 case PARAM_CONSTANT:
Brian7cbfe8c2008-01-18 12:45:55 -07001888 /* parsing something like {1.0, 2.0, 3.0, 4.0} */
Jouk Jansen40322e12004-04-05 08:50:36 +00001889 parse_constant (inst, const_values, Program, use);
Brian Paulde997602005-11-12 17:53:14 +00001890 idx = _mesa_add_named_constant(Program->Base.Parameters,
1891 (char *) param_var->name,
Brian Paul0c6723a2006-11-15 23:38:02 +00001892 const_values, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00001893 if (param_var->param_binding_begin == ~0U)
1894 param_var->param_binding_begin = idx;
Brian Paul0576e832008-09-19 13:04:52 +02001895 param_var->param_binding_type = PROGRAM_STATE_VAR;
1896 /* Note: when we reference this parameter in an instruction later,
1897 * we'll check if it's really a constant/immediate and set the
1898 * instruction register type appropriately.
1899 */
Jouk Jansen40322e12004-04-05 08:50:36 +00001900 param_var->param_binding_length++;
1901 Program->Base.NumParameters++;
1902 break;
1903
1904 default:
Brian Paula088f162006-09-05 23:08:51 +00001905 program_error(ctx, Program->Position,
1906 "Unexpected token (in parse_param_elements())");
Jouk Jansen40322e12004-04-05 08:50:36 +00001907 return 1;
1908 }
1909
1910 /* Make sure we haven't blown past our parameter limits */
1911 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1912 (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001913 ctx->Const.VertexProgram.MaxLocalParams))
Jouk Jansen40322e12004-04-05 08:50:36 +00001914 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1915 && (Program->Base.NumParameters >=
Brian Paul05051032005-11-01 04:36:33 +00001916 ctx->Const.FragmentProgram.MaxLocalParams))) {
Brian Paula088f162006-09-05 23:08:51 +00001917 program_error(ctx, Program->Position, "Too many parameter variables");
Jouk Jansen40322e12004-04-05 08:50:36 +00001918 return 1;
1919 }
1920
1921 return err;
1922}
1923
Brian Paul7aebaf32005-10-30 21:23:23 +00001924
Jouk Jansen40322e12004-04-05 08:50:36 +00001925/**
1926 * This picks out PARAM program parameter bindings.
1927 *
1928 * XXX: This needs to be stressed & tested
1929 *
1930 * \return 0 on sucess, 1 on error
1931 */
1932static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001933parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001934 struct arb_program *Program)
1935{
Brian Paulbd997cd2004-07-20 21:12:56 +00001936 GLuint found, err;
1937 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001938 struct var_cache *param_var;
1939
1940 err = 0;
1941 param_var = parse_string (inst, vc_head, Program, &found);
1942 Program->Position = parse_position (inst);
1943
1944 if (found) {
Brian50a20d42008-03-27 15:51:07 -06001945 program_error2(ctx, Program->Position,
1946 "Duplicate variable declaration",
1947 (char *) param_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00001948 return 1;
1949 }
1950
1951 specified_length = parse_integer (inst, Program);
1952
1953 if (specified_length < 0) {
Brian Paula088f162006-09-05 23:08:51 +00001954 program_error(ctx, Program->Position, "Negative parameter array length");
Jouk Jansen40322e12004-04-05 08:50:36 +00001955 return 1;
1956 }
1957
1958 param_var->type = vt_param;
1959 param_var->param_binding_length = 0;
1960
1961 /* Right now, everything is shoved into the main state register file.
1962 *
1963 * In the future, it would be nice to leave things ENV/LOCAL params
1964 * in their respective register files, if possible
1965 */
1966 param_var->param_binding_type = PROGRAM_STATE_VAR;
1967
1968 /* Remember to:
1969 * * - add each guy to the parameter list
1970 * * - increment the param_var->param_binding_len
1971 * * - store the param_var->param_binding_begin for the first one
1972 * * - compare the actual len to the specified len at the end
1973 */
1974 while (**inst != PARAM_NULL) {
1975 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1976 return 1;
1977 }
1978
1979 /* Test array length here! */
1980 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001981 if (specified_length != (int)param_var->param_binding_length) {
Brian Paula088f162006-09-05 23:08:51 +00001982 program_error(ctx, Program->Position,
1983 "Declared parameter array length does not match parameter list");
Jouk Jansen40322e12004-04-05 08:50:36 +00001984 }
1985 }
1986
1987 (*inst)++;
1988
1989 return 0;
1990}
1991
1992/**
1993 *
1994 */
1995static GLuint
Brian Paula088f162006-09-05 23:08:51 +00001996parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00001997 struct arb_program *Program, struct var_cache **new_var)
1998{
1999 struct var_cache *param_var;
2000
2001 /* First, insert a dummy entry into the var_cache */
2002 var_cache_create (&param_var);
Brian Paul6a769d92006-04-28 15:42:15 +00002003 param_var->name = (const GLubyte *) " ";
Jouk Jansen40322e12004-04-05 08:50:36 +00002004 param_var->type = vt_param;
2005
2006 param_var->param_binding_length = 0;
2007 /* Don't fill in binding_begin; We use the default value of -1
2008 * to tell if its already initialized, elsewhere.
2009 *
2010 * param_var->param_binding_begin = 0;
2011 */
2012 param_var->param_binding_type = PROGRAM_STATE_VAR;
2013
2014 var_cache_append (vc_head, param_var);
2015
2016 /* Then fill it with juicy parameter goodness */
2017 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
2018 return 1;
2019
2020 *new_var = param_var;
2021
2022 return 0;
2023}
2024
2025
2026/**
2027 * This handles the declaration of TEMP variables
2028 *
2029 * \return 0 on sucess, 1 on error
2030 */
2031static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002032parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002033 struct arb_program *Program)
2034{
2035 GLuint found;
2036 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002037
2038 while (**inst != 0) {
2039 temp_var = parse_string (inst, vc_head, Program, &found);
2040 Program->Position = parse_position (inst);
2041 if (found) {
Brian50a20d42008-03-27 15:51:07 -06002042 program_error2(ctx, Program->Position,
2043 "Duplicate variable declaration",
2044 (char *) temp_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002045 return 1;
2046 }
2047
2048 temp_var->type = vt_temp;
2049
2050 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
2051 (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00002052 ctx->Const.FragmentProgram.MaxTemps))
Jouk Jansen40322e12004-04-05 08:50:36 +00002053 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
2054 && (Program->Base.NumTemporaries >=
Brian Paul05051032005-11-01 04:36:33 +00002055 ctx->Const.VertexProgram.MaxTemps))) {
Brian Paula088f162006-09-05 23:08:51 +00002056 program_error(ctx, Program->Position,
2057 "Too many TEMP variables declared");
Jouk Jansen40322e12004-04-05 08:50:36 +00002058 return 1;
2059 }
2060
2061 temp_var->temp_binding = Program->Base.NumTemporaries;
2062 Program->Base.NumTemporaries++;
2063 }
2064 (*inst)++;
2065
2066 return 0;
2067}
2068
2069/**
2070 * This handles variables of the OUTPUT variety
2071 *
2072 * \return 0 on sucess, 1 on error
2073 */
2074static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002075parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002076 struct arb_program *Program)
2077{
2078 GLuint found;
2079 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00002080 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002081
2082 output_var = parse_string (inst, vc_head, Program, &found);
2083 Program->Position = parse_position (inst);
2084 if (found) {
Brian50a20d42008-03-27 15:51:07 -06002085 program_error2(ctx, Program->Position,
2086 "Duplicate variable declaration",
2087 (char *) output_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002088 return 1;
2089 }
2090
2091 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002092
2093 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2094 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002095}
2096
2097/**
2098 * This handles variables of the ALIAS kind
2099 *
2100 * \return 0 on sucess, 1 on error
2101 */
2102static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002103parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002104 struct arb_program *Program)
2105{
2106 GLuint found;
2107 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002108
2109 temp_var = parse_string (inst, vc_head, Program, &found);
2110 Program->Position = parse_position (inst);
2111
2112 if (found) {
Brian50a20d42008-03-27 15:51:07 -06002113 program_error2(ctx, Program->Position,
2114 "Duplicate variable declaration",
2115 (char *) temp_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002116 return 1;
2117 }
2118
2119 temp_var->type = vt_alias;
2120 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2121 Program->Position = parse_position (inst);
2122
2123 if (!found)
2124 {
Brian50a20d42008-03-27 15:51:07 -06002125 program_error2(ctx, Program->Position,
2126 "Undefined alias value",
2127 (char *) temp_var->alias_binding->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002128 return 1;
2129 }
2130
2131 return 0;
2132}
2133
2134/**
2135 * This handles variables of the ADDRESS kind
2136 *
2137 * \return 0 on sucess, 1 on error
2138 */
2139static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002140parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002141 struct arb_program *Program)
2142{
2143 GLuint found;
2144 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002145
2146 while (**inst != 0) {
2147 temp_var = parse_string (inst, vc_head, Program, &found);
2148 Program->Position = parse_position (inst);
2149 if (found) {
Brian50a20d42008-03-27 15:51:07 -06002150 program_error2(ctx, Program->Position,
2151 "Duplicate variable declaration",
2152 (char *) temp_var->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002153 return 1;
2154 }
2155
2156 temp_var->type = vt_address;
2157
2158 if (Program->Base.NumAddressRegs >=
Brian Paul05051032005-11-01 04:36:33 +00002159 ctx->Const.VertexProgram.MaxAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002160 const char *msg = "Too many ADDRESS variables declared";
Brian Paula088f162006-09-05 23:08:51 +00002161 program_error(ctx, Program->Position, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002162 return 1;
2163 }
2164
2165 temp_var->address_binding = Program->Base.NumAddressRegs;
2166 Program->Base.NumAddressRegs++;
2167 }
2168 (*inst)++;
2169
2170 return 0;
2171}
2172
2173/**
2174 * Parse a program declaration
2175 *
2176 * \return 0 on sucess, 1 on error
2177 */
2178static GLint
Brian Paula088f162006-09-05 23:08:51 +00002179parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
Jouk Jansen40322e12004-04-05 08:50:36 +00002180 struct arb_program *Program)
2181{
2182 GLint err = 0;
2183
2184 switch (*(*inst)++) {
2185 case ADDRESS:
2186 err = parse_address (ctx, inst, vc_head, Program);
2187 break;
2188
2189 case ALIAS:
2190 err = parse_alias (ctx, inst, vc_head, Program);
2191 break;
2192
2193 case ATTRIB:
2194 err = parse_attrib (ctx, inst, vc_head, Program);
2195 break;
2196
2197 case OUTPUT:
2198 err = parse_output (ctx, inst, vc_head, Program);
2199 break;
2200
2201 case PARAM:
2202 err = parse_param (ctx, inst, vc_head, Program);
2203 break;
2204
2205 case TEMP:
2206 err = parse_temp (ctx, inst, vc_head, Program);
2207 break;
2208 }
2209
2210 return err;
2211}
2212
2213/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002214 * Handle the parsing out of a masked destination register, either for a
2215 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002216 *
2217 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002218 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002219 * position invariant
2220 *
2221 * \param File - The register file we write to
2222 * \param Index - The register index we write to
2223 * \param WriteMask - The mask controlling which components we write (1->write)
2224 *
2225 * \return 0 on sucess, 1 on error
2226 */
2227static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002228parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002229 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002230 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002231{
Brian Paul7aebaf32005-10-30 21:23:23 +00002232 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002233 struct var_cache *dst;
2234
2235 /* We either have a result register specified, or a
2236 * variable that may or may not be writable
2237 */
2238 switch (*(*inst)++) {
2239 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002240 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002241 return 1;
2242 *File = PROGRAM_OUTPUT;
2243 break;
2244
2245 case REGISTER_ESTABLISHED_NAME:
2246 dst = parse_string (inst, vc_head, Program, &result);
2247 Program->Position = parse_position (inst);
2248
2249 /* If the name has never been added to our symbol table, we're hosed */
2250 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002251 program_error(ctx, Program->Position, "0: Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002252 return 1;
2253 }
2254
2255 switch (dst->type) {
2256 case vt_output:
2257 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002258 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002259 break;
2260
2261 case vt_temp:
2262 *File = PROGRAM_TEMPORARY;
2263 *Index = dst->temp_binding;
2264 break;
2265
2266 /* If the var type is not vt_output or vt_temp, no go */
2267 default:
Brian Paula088f162006-09-05 23:08:51 +00002268 program_error(ctx, Program->Position,
2269 "Destination register is read only");
Jouk Jansen40322e12004-04-05 08:50:36 +00002270 return 1;
2271 }
2272 break;
2273
2274 default:
Brian Paula088f162006-09-05 23:08:51 +00002275 program_error(ctx, Program->Position,
2276 "Unexpected opcode in parse_masked_dst_reg()");
Jouk Jansen40322e12004-04-05 08:50:36 +00002277 return 1;
2278 }
2279
2280
2281 /* Position invariance test */
2282 /* This test is done now in syntax portion - when position invariance OPTION
2283 is specified, "result.position" rule is disabled so there is no way
2284 to write the position
2285 */
2286 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2287 (*Index == 0)) {
Brian Paula088f162006-09-05 23:08:51 +00002288 program_error(ctx, Program->Position,
Jouk Jansen40322e12004-04-05 08:50:36 +00002289 "Vertex program specified position invariance and wrote vertex position");
2290 }*/
2291
2292 /* And then the mask.
2293 * w,a -> bit 0
2294 * z,b -> bit 1
2295 * y,g -> bit 2
2296 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002297 *
2298 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002299 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002300 tmp = (GLint) *(*inst)++;
2301 *WriteMask = (((tmp>>3) & 0x1) |
2302 ((tmp>>1) & 0x2) |
2303 ((tmp<<1) & 0x4) |
2304 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002305
2306 return 0;
2307}
2308
2309
2310/**
2311 * Handle the parsing of a address register
2312 *
2313 * \param Index - The register index we write to
2314 *
2315 * \return 0 on sucess, 1 on error
2316 */
2317static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002318parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002319 struct var_cache **vc_head,
2320 struct arb_program *Program, GLint * Index)
2321{
2322 struct var_cache *dst;
2323 GLuint result;
Aapo Tahkola6fc864b2006-03-22 21:29:15 +00002324
2325 *Index = 0; /* XXX */
Jouk Jansen40322e12004-04-05 08:50:36 +00002326
2327 dst = parse_string (inst, vc_head, Program, &result);
2328 Program->Position = parse_position (inst);
2329
2330 /* If the name has never been added to our symbol table, we're hosed */
2331 if (!result) {
Brian Paula088f162006-09-05 23:08:51 +00002332 program_error(ctx, Program->Position, "Undefined variable");
Jouk Jansen40322e12004-04-05 08:50:36 +00002333 return 1;
2334 }
2335
2336 if (dst->type != vt_address) {
Brian Paula088f162006-09-05 23:08:51 +00002337 program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
Jouk Jansen40322e12004-04-05 08:50:36 +00002338 return 1;
2339 }
2340
2341 return 0;
2342}
2343
Brian Paul8e8fa632005-07-01 02:03:33 +00002344#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002345/**
2346 * Handle the parsing out of a masked address register
2347 *
2348 * \param Index - The register index we write to
2349 * \param WriteMask - The mask controlling which components we write (1->write)
2350 *
2351 * \return 0 on sucess, 1 on error
2352 */
2353static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002354parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002355 struct var_cache **vc_head,
2356 struct arb_program *Program, GLint * Index,
2357 GLboolean * WriteMask)
2358{
2359 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2360 return 1;
2361
2362 /* This should be 0x8 */
2363 (*inst)++;
2364
2365 /* Writemask of .x is implied */
2366 WriteMask[0] = 1;
2367 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2368
2369 return 0;
2370}
Brian Paul8e8fa632005-07-01 02:03:33 +00002371#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002372
2373/**
2374 * Parse out a swizzle mask.
2375 *
Brian Paul32df89e2005-10-29 18:26:43 +00002376 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002377 *
2378 * The len parameter allows us to grab 4 components for a vector
2379 * swizzle, or just 1 component for a scalar src register selection
2380 */
Brian Paul32df89e2005-10-29 18:26:43 +00002381static void
Brian Paula088f162006-09-05 23:08:51 +00002382parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002383{
Brian Paul32df89e2005-10-29 18:26:43 +00002384 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002385
Brian Paul32df89e2005-10-29 18:26:43 +00002386 for (i = 0; i < 4; i++)
2387 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002388
Brian Paul32df89e2005-10-29 18:26:43 +00002389 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002390 switch (*(*inst)++) {
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;
Jouk Jansen40322e12004-04-05 08:50:36 +00002394 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002395 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002396 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002397 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002398 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002399 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002400 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 component in parse_swizzle_mask()");
2405 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002406 }
2407 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002408}
2409
Jouk Jansen40322e12004-04-05 08:50:36 +00002410
Brian Paul32df89e2005-10-29 18:26:43 +00002411/**
2412 * Parse an extended swizzle mask which is a sequence of
2413 * four x/y/z/w/0/1 tokens.
2414 * \return swizzle four swizzle values
2415 * \return negateMask four element bitfield
2416 */
2417static void
Brian Paula088f162006-09-05 23:08:51 +00002418parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
Brian Paul32df89e2005-10-29 18:26:43 +00002419 GLubyte *negateMask)
2420{
2421 GLint i;
2422
2423 *negateMask = 0x0;
2424 for (i = 0; i < 4; i++) {
2425 GLubyte swz;
2426 if (parse_sign(inst) == -1)
2427 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002428
2429 swz = *(*inst)++;
2430
2431 switch (swz) {
2432 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002433 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002434 break;
2435 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002436 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002437 break;
2438 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002439 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002440 break;
2441 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002442 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002443 break;
2444 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002445 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002446 break;
2447 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002448 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002449 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002450 default:
2451 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2452 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002453 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002454 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002455}
2456
2457
2458static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002459parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
2460 struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002461 struct arb_program *Program,
2462 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002463 GLboolean *IsRelOffset )
2464{
2465 struct var_cache *src;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002466 GLuint binding, is_generic, found;
Brian Paulbd997cd2004-07-20 21:12:56 +00002467 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002468
Keith Whitwell7c26b612005-04-21 14:46:57 +00002469 *IsRelOffset = 0;
2470
Jouk Jansen40322e12004-04-05 08:50:36 +00002471 /* And the binding for the src */
2472 switch (*(*inst)++) {
2473 case REGISTER_ATTRIB:
2474 if (parse_attrib_binding
Brian Paul18e7c5c2005-10-30 21:46:00 +00002475 (ctx, inst, Program, &binding, &is_generic))
Jouk Jansen40322e12004-04-05 08:50:36 +00002476 return 1;
2477 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002478 *Index = binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002479
2480 /* We need to insert a dummy variable into the var_cache so we can
2481 * catch generic vertex attrib aliasing errors
2482 */
2483 var_cache_create(&src);
2484 src->type = vt_attrib;
Brian Paul6a769d92006-04-28 15:42:15 +00002485 src->name = (const GLubyte *) "Dummy Attrib Variable";
Brian Paul18e7c5c2005-10-30 21:46:00 +00002486 src->attrib_binding = binding;
2487 src->attrib_is_generic = is_generic;
Jouk Jansen40322e12004-04-05 08:50:36 +00002488 var_cache_append(vc_head, src);
2489 if (generic_attrib_check(*vc_head)) {
Brian Paula088f162006-09-05 23:08:51 +00002490 program_error(ctx, Program->Position,
2491 "Cannot use both a generic vertex attribute "
2492 "and a specific attribute of the same type");
Jouk Jansen40322e12004-04-05 08:50:36 +00002493 return 1;
2494 }
2495 break;
2496
2497 case REGISTER_PARAM:
2498 switch (**inst) {
2499 case PARAM_ARRAY_ELEMENT:
2500 (*inst)++;
2501 src = parse_string (inst, vc_head, Program, &found);
2502 Program->Position = parse_position (inst);
2503
2504 if (!found) {
Brian50a20d42008-03-27 15:51:07 -06002505 program_error2(ctx, Program->Position,
2506 "Undefined variable",
2507 (char *) src->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00002508 return 1;
2509 }
2510
Brian Paul95801792005-12-06 15:41:43 +00002511 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002512
2513 switch (*(*inst)++) {
2514 case ARRAY_INDEX_ABSOLUTE:
2515 offset = parse_integer (inst, Program);
2516
2517 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002518 || (offset >= (int)src->param_binding_length)) {
Brian Paula088f162006-09-05 23:08:51 +00002519 program_error(ctx, Program->Position,
2520 "Index out of range");
2521 /* offset, src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002522 return 1;
2523 }
2524
2525 *Index = src->param_binding_begin + offset;
2526 break;
2527
2528 case ARRAY_INDEX_RELATIVE:
2529 {
2530 GLint addr_reg_idx, rel_off;
2531
2532 /* First, grab the address regiseter */
2533 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2534 return 1;
2535
2536 /* And the .x */
2537 ((*inst)++);
2538 ((*inst)++);
2539 ((*inst)++);
2540 ((*inst)++);
2541
2542 /* Then the relative offset */
2543 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2544
2545 /* And store it properly */
2546 *Index = src->param_binding_begin + rel_off;
2547 *IsRelOffset = 1;
2548 }
2549 break;
2550 }
2551 break;
2552
2553 default:
Jouk Jansen40322e12004-04-05 08:50:36 +00002554 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2555 return 1;
2556
Brian Paul95801792005-12-06 15:41:43 +00002557 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002558 *Index = src->param_binding_begin;
2559 break;
2560 }
2561 break;
2562
2563 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002564 src = parse_string (inst, vc_head, Program, &found);
2565 Program->Position = parse_position (inst);
2566
2567 /* If the name has never been added to our symbol table, we're hosed */
2568 if (!found) {
Brian Paula088f162006-09-05 23:08:51 +00002569 program_error(ctx, Program->Position,
2570 "3: Undefined variable"); /* src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002571 return 1;
2572 }
2573
2574 switch (src->type) {
2575 case vt_attrib:
2576 *File = PROGRAM_INPUT;
Brian Paul18e7c5c2005-10-30 21:46:00 +00002577 *Index = src->attrib_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002578 break;
2579
2580 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2581 case vt_param:
Brian Paul95801792005-12-06 15:41:43 +00002582 *File = (enum register_file) src->param_binding_type;
Jouk Jansen40322e12004-04-05 08:50:36 +00002583 *Index = src->param_binding_begin;
2584 break;
2585
2586 case vt_temp:
2587 *File = PROGRAM_TEMPORARY;
2588 *Index = src->temp_binding;
2589 break;
2590
2591 /* If the var type is vt_output no go */
2592 default:
Brian Paula088f162006-09-05 23:08:51 +00002593 program_error(ctx, Program->Position,
2594 "destination register is read only");
2595 /* bad src->name */
Jouk Jansen40322e12004-04-05 08:50:36 +00002596 return 1;
2597 }
2598 break;
2599
2600 default:
Brian Paula088f162006-09-05 23:08:51 +00002601 program_error(ctx, Program->Position,
2602 "Unknown token in parse_src_reg");
Jouk Jansen40322e12004-04-05 08:50:36 +00002603 return 1;
2604 }
2605
Brian Paul0576e832008-09-19 13:04:52 +02002606 if (*File == PROGRAM_STATE_VAR) {
2607 /* If we're referencing the Program->Parameters[] array, check if the
2608 * parameter is really a constant/literal. If so, set File to CONSTANT.
2609 */
2610 assert(*Index < Program->Base.Parameters->NumParameters);
2611 enum register_file file = Program->Base.Parameters->Parameters[*Index].Type;
2612 if (file == PROGRAM_CONSTANT)
2613 *File = PROGRAM_CONSTANT;
2614 }
2615
Markus Amslerf3c49062008-03-17 08:35:37 -06002616 /* Add attributes to InputsRead only if they are used the program.
2617 * This avoids the handling of unused ATTRIB declarations in the drivers. */
2618 if (*File == PROGRAM_INPUT)
2619 Program->Base.InputsRead |= (1 << *Index);
2620
Jouk Jansen40322e12004-04-05 08:50:36 +00002621 return 0;
2622}
2623
Brianbdf279b2008-03-27 16:19:46 -06002624
Jouk Jansen40322e12004-04-05 08:50:36 +00002625/**
Brianbdf279b2008-03-27 16:19:46 -06002626 * Parse vertex/fragment program vector source register.
Jouk Jansen40322e12004-04-05 08:50:36 +00002627 */
2628static GLuint
Brianbdf279b2008-03-27 16:19:46 -06002629parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
2630 struct var_cache **vc_head,
2631 struct arb_program *program,
2632 struct prog_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002633{
Brian Paul7aebaf32005-10-30 21:23:23 +00002634 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002635 GLint index;
Brianbdf279b2008-03-27 16:19:46 -06002636 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002637 GLubyte swizzle[4];
2638 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002639
Jouk Jansen40322e12004-04-05 08:50:36 +00002640 /* Grab the sign */
Brianbdf279b2008-03-27 16:19:46 -06002641 negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002642
2643 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002644 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002645 return 1;
2646
2647 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002648 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002649
Brian Paul32df89e2005-10-29 18:26:43 +00002650 reg->File = file;
2651 reg->Index = index;
Brian Paul32df89e2005-10-29 18:26:43 +00002652 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Brianbdf279b2008-03-27 16:19:46 -06002653 reg->NegateBase = negateMask;
2654 reg->RelAddr = isRelOffset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002655 return 0;
2656}
2657
Jouk Jansen40322e12004-04-05 08:50:36 +00002658
Brian Paulb7fc1c32006-08-30 23:38:03 +00002659/**
Brianbdf279b2008-03-27 16:19:46 -06002660 * Parse vertex/fragment program scalar source register.
2661 */
2662static GLuint
2663parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
2664 struct var_cache **vc_head,
2665 struct arb_program *program,
2666 struct prog_src_register *reg)
2667{
2668 enum register_file file;
2669 GLint index;
2670 GLubyte negateMask;
2671 GLubyte swizzle[4];
2672 GLboolean isRelOffset;
2673
2674 /* Grab the sign */
2675 negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
2676
2677 /* And the src reg */
2678 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
2679 return 1;
2680
2681 /* finally, the swizzle */
2682 parse_swizzle_mask(inst, swizzle, 1);
2683
2684 reg->File = file;
2685 reg->Index = index;
2686 reg->Swizzle = (swizzle[0] << 0);
2687 reg->NegateBase = negateMask;
2688 reg->RelAddr = isRelOffset;
2689 return 0;
2690}
2691
2692
2693/**
2694 * Parse vertex/fragment program destination register.
Brian Paulb7fc1c32006-08-30 23:38:03 +00002695 * \return 1 if error, 0 if no error.
2696 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002697static GLuint
Brianbdf279b2008-03-27 16:19:46 -06002698parse_dst_reg(GLcontext * ctx, const GLubyte ** inst,
2699 struct var_cache **vc_head, struct arb_program *program,
2700 struct prog_dst_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00002701{
Brian Paul7aebaf32005-10-30 21:23:23 +00002702 GLint mask;
2703 GLuint idx;
2704 enum register_file file;
2705
Brianbdf279b2008-03-27 16:19:46 -06002706 if (parse_masked_dst_reg (ctx, inst, vc_head, program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002707 return 1;
2708
Keith Whitwell7c26b612005-04-21 14:46:57 +00002709 reg->File = file;
2710 reg->Index = idx;
2711 reg->WriteMask = mask;
2712 return 0;
2713}
2714
2715
Brian Paul7aebaf32005-10-30 21:23:23 +00002716/**
Jouk Jansen40322e12004-04-05 08:50:36 +00002717 * This is a big mother that handles getting opcodes into the instruction
2718 * and handling the src & dst registers for fragment program instructions
Brian Paulb7fc1c32006-08-30 23:38:03 +00002719 * \return 1 if error, 0 if no error
Jouk Jansen40322e12004-04-05 08:50:36 +00002720 */
2721static GLuint
Brian Paula088f162006-09-05 23:08:51 +00002722parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00002723 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00002724 struct prog_instruction *fp)
Jouk Jansen40322e12004-04-05 08:50:36 +00002725{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002726 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002727 GLuint texcoord;
2728 GLubyte instClass, type, code;
2729 GLboolean rel;
Ian Romanick7b559a92007-06-07 13:58:50 -07002730 GLuint shadow_tex = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002731
Brian Pauld6272e02006-10-29 18:03:16 +00002732 _mesa_init_instructions(fp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002733
2734 /* Record the position in the program string for debugging */
2735 fp->StringPos = Program->Position;
2736
2737 /* OP_ALU_INST or OP_TEX_INST */
2738 instClass = *(*inst)++;
2739
2740 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2741 * OP_TEX_{SAMPLE, KIL}
2742 */
2743 type = *(*inst)++;
2744
2745 /* The actual opcode name */
2746 code = *(*inst)++;
2747
2748 /* Increment the correct count */
2749 switch (instClass) {
2750 case OP_ALU_INST:
2751 Program->NumAluInstructions++;
2752 break;
2753 case OP_TEX_INST:
2754 Program->NumTexInstructions++;
2755 break;
2756 }
2757
Jouk Jansen40322e12004-04-05 08:50:36 +00002758 switch (type) {
2759 case OP_ALU_VECTOR:
2760 switch (code) {
2761 case OP_ABS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002762 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002763 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00002764 fp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002765 break;
2766
2767 case OP_FLR_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002768 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002769 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00002770 fp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00002771 break;
2772
2773 case OP_FRC_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002774 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002775 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00002776 fp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00002777 break;
2778
2779 case OP_LIT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002780 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002781 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00002782 fp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002783 break;
2784
2785 case OP_MOV_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002786 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002787 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00002788 fp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00002789 break;
2790 }
2791
Brianbdf279b2008-03-27 16:19:46 -06002792 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002793 return 1;
2794
Brianbdf279b2008-03-27 16:19:46 -06002795 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002796 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002797 break;
2798
2799 case OP_ALU_SCALAR:
2800 switch (code) {
2801 case OP_COS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002802 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002803 case OP_COS:
Brian Paul7e807512005-11-05 17:10:45 +00002804 fp->Opcode = OPCODE_COS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002805 break;
2806
2807 case OP_EX2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002808 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002809 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00002810 fp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002811 break;
2812
2813 case OP_LG2_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002814 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002815 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00002816 fp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00002817 break;
2818
2819 case OP_RCP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002820 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002821 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00002822 fp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002823 break;
2824
2825 case OP_RSQ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002826 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002827 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00002828 fp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002829 break;
2830
2831 case OP_SIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002832 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002833 case OP_SIN:
Brian Paul7e807512005-11-05 17:10:45 +00002834 fp->Opcode = OPCODE_SIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002835 break;
2836
2837 case OP_SCS_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002838 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002839 case OP_SCS:
2840
Brian Paul7e807512005-11-05 17:10:45 +00002841 fp->Opcode = OPCODE_SCS;
Jouk Jansen40322e12004-04-05 08:50:36 +00002842 break;
2843 }
2844
Brianbdf279b2008-03-27 16:19:46 -06002845 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002846 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002847
Brianbdf279b2008-03-27 16:19:46 -06002848 if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002849 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002850 break;
2851
2852 case OP_ALU_BINSC:
2853 switch (code) {
2854 case OP_POW_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002855 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002856 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00002857 fp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00002858 break;
2859 }
2860
Brianbdf279b2008-03-27 16:19:46 -06002861 if (parse_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002862 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002863
Jouk Jansen40322e12004-04-05 08:50:36 +00002864 for (a = 0; a < 2; a++) {
Brianbdf279b2008-03-27 16:19:46 -06002865 if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002866 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002867 }
2868 break;
2869
2870
2871 case OP_ALU_BIN:
2872 switch (code) {
2873 case OP_ADD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002874 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002875 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00002876 fp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002877 break;
2878
2879 case OP_DP3_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002880 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002881 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00002882 fp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00002883 break;
2884
2885 case OP_DP4_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002886 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002887 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00002888 fp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00002889 break;
2890
2891 case OP_DPH_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002892 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002893 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00002894 fp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00002895 break;
2896
2897 case OP_DST_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002898 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002899 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00002900 fp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00002901 break;
2902
2903 case OP_MAX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002904 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002905 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00002906 fp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00002907 break;
2908
2909 case OP_MIN_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002910 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002911 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00002912 fp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00002913 break;
2914
2915 case OP_MUL_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002916 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002917 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00002918 fp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00002919 break;
2920
2921 case OP_SGE_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002922 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002923 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00002924 fp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002925 break;
2926
2927 case OP_SLT_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002928 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002929 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00002930 fp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00002931 break;
2932
2933 case OP_SUB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002934 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002935 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00002936 fp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00002937 break;
2938
2939 case OP_XPD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002940 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002941 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00002942 fp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002943 break;
2944 }
2945
Brianbdf279b2008-03-27 16:19:46 -06002946 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002947 return 1;
2948 for (a = 0; a < 2; a++) {
Brianbdf279b2008-03-27 16:19:46 -06002949 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002950 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002951 }
2952 break;
2953
2954 case OP_ALU_TRI:
2955 switch (code) {
2956 case OP_CMP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002957 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002958 case OP_CMP:
Brian Paul7e807512005-11-05 17:10:45 +00002959 fp->Opcode = OPCODE_CMP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002960 break;
2961
2962 case OP_LRP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002963 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002964 case OP_LRP:
Brian Paul7e807512005-11-05 17:10:45 +00002965 fp->Opcode = OPCODE_LRP;
Jouk Jansen40322e12004-04-05 08:50:36 +00002966 break;
2967
2968 case OP_MAD_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002969 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002970 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00002971 fp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00002972 break;
2973 }
2974
Brianbdf279b2008-03-27 16:19:46 -06002975 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002976 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002977
Jouk Jansen40322e12004-04-05 08:50:36 +00002978 for (a = 0; a < 3; a++) {
Brianbdf279b2008-03-27 16:19:46 -06002979 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002980 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002981 }
2982 break;
2983
2984 case OP_ALU_SWZ:
2985 switch (code) {
2986 case OP_SWZ_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00002987 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002988 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00002989 fp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00002990 break;
2991 }
Brianbdf279b2008-03-27 16:19:46 -06002992 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002993 return 1;
2994
Keith Whitwell7c26b612005-04-21 14:46:57 +00002995 {
Brian Paul32df89e2005-10-29 18:26:43 +00002996 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002997 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002998 enum register_file file;
2999 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003000
Brian Paul32df89e2005-10-29 18:26:43 +00003001 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003002 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003003 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
3004 fp->SrcReg[0].File = file;
3005 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00003006 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003007 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3008 swizzle[1],
3009 swizzle[2],
3010 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003011 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003012 break;
3013
3014 case OP_TEX_SAMPLE:
3015 switch (code) {
3016 case OP_TEX_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00003017 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003018 case OP_TEX:
Brian Paul7e807512005-11-05 17:10:45 +00003019 fp->Opcode = OPCODE_TEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003020 break;
3021
3022 case OP_TXP_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00003023 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003024 case OP_TXP:
Brian Paul7e807512005-11-05 17:10:45 +00003025 fp->Opcode = OPCODE_TXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003026 break;
3027
3028 case OP_TXB_SAT:
Brian Paule31ac052005-11-20 17:52:40 +00003029 fp->SaturateMode = SATURATE_ZERO_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003030 case OP_TXB:
Brian Paul7e807512005-11-05 17:10:45 +00003031 fp->Opcode = OPCODE_TXB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003032 break;
3033 }
3034
Brianbdf279b2008-03-27 16:19:46 -06003035 if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003036 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003037
Brianbdf279b2008-03-27 16:19:46 -06003038 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003039 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003040
3041 /* texImageUnit */
3042 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
3043 return 1;
3044 fp->TexSrcUnit = texcoord;
3045
3046 /* texTarget */
3047 switch (*(*inst)++) {
Ian Romanick7b559a92007-06-07 13:58:50 -07003048 case TEXTARGET_SHADOW1D:
3049 shadow_tex = 1 << texcoord;
3050 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00003051 case TEXTARGET_1D:
Brian Paul7e807512005-11-05 17:10:45 +00003052 fp->TexSrcTarget = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003053 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07003054 case TEXTARGET_SHADOW2D:
3055 shadow_tex = 1 << texcoord;
3056 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00003057 case TEXTARGET_2D:
Brian Paul7e807512005-11-05 17:10:45 +00003058 fp->TexSrcTarget = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003059 break;
3060 case TEXTARGET_3D:
Brian Paul7e807512005-11-05 17:10:45 +00003061 fp->TexSrcTarget = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003062 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07003063 case TEXTARGET_SHADOWRECT:
3064 shadow_tex = 1 << texcoord;
3065 /* FALLTHROUGH */
Jouk Jansen40322e12004-04-05 08:50:36 +00003066 case TEXTARGET_RECT:
Brian Paul7e807512005-11-05 17:10:45 +00003067 fp->TexSrcTarget = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003068 break;
3069 case TEXTARGET_CUBE:
Brian Paul7e807512005-11-05 17:10:45 +00003070 fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003071 break;
Ian Romanick69358e72007-06-05 09:24:27 -07003072 case TEXTARGET_SHADOW1D_ARRAY:
Ian Romanick7b559a92007-06-07 13:58:50 -07003073 shadow_tex = 1 << texcoord;
3074 /* FALLTHROUGH */
Ian Romanickbb372f12007-05-16 15:34:22 -07003075 case TEXTARGET_1D_ARRAY:
3076 fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
3077 break;
Ian Romanick7b559a92007-06-07 13:58:50 -07003078 case TEXTARGET_SHADOW2D_ARRAY:
3079 shadow_tex = 1 << texcoord;
3080 /* FALLTHROUGH */
Ian Romanickbb372f12007-05-16 15:34:22 -07003081 case TEXTARGET_2D_ARRAY:
3082 fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
3083 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003084 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003085
3086 /* Don't test the first time a particular sampler is seen. Each time
3087 * after that, make sure the shadow state is the same.
3088 */
3089 if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
3090 && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
3091 program_error(ctx, Program->Position,
3092 "texture image unit used for shadow sampling and non-shadow sampling");
3093 return 1;
3094 }
3095
Brian Paulb7fc1c32006-08-30 23:38:03 +00003096 Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
3097 /* Check that both "2D" and "CUBE" (for example) aren't both used */
3098 if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
Brian Paula088f162006-09-05 23:08:51 +00003099 program_error(ctx, Program->Position,
3100 "multiple targets used on one texture image unit");
Brian Paulb7fc1c32006-08-30 23:38:03 +00003101 return 1;
3102 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003103
3104
3105 Program->ShadowSamplers |= shadow_tex;
Jouk Jansen40322e12004-04-05 08:50:36 +00003106 break;
3107
3108 case OP_TEX_KIL:
Keith Whitwellc3626a92005-11-01 17:25:49 +00003109 Program->UsesKill = 1;
Brianbdf279b2008-03-27 16:19:46 -06003110 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003111 return 1;
Brian Paul7e807512005-11-05 17:10:45 +00003112 fp->Opcode = OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003113 break;
Brian Paulb7fc1c32006-08-30 23:38:03 +00003114 default:
3115 _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
3116 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003117 }
3118
3119 return 0;
3120}
3121
Keith Whitwell7c26b612005-04-21 14:46:57 +00003122
3123/**
3124 * Handle the parsing out of a masked address register
3125 *
3126 * \param Index - The register index we write to
3127 * \param WriteMask - The mask controlling which components we write (1->write)
3128 *
3129 * \return 0 on sucess, 1 on error
3130 */
3131static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003132parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003133 struct var_cache **vc_head,
3134 struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003135 struct prog_dst_register *reg)
Keith Whitwell7c26b612005-04-21 14:46:57 +00003136{
3137 GLint idx;
3138
3139 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3140 return 1;
3141
3142 /* This should be 0x8 */
3143 (*inst)++;
3144
3145 reg->File = PROGRAM_ADDRESS;
3146 reg->Index = idx;
3147
3148 /* Writemask of .x is implied */
3149 reg->WriteMask = 0x1;
3150 return 0;
3151}
3152
Keith Whitwell7c26b612005-04-21 14:46:57 +00003153
Jouk Jansen40322e12004-04-05 08:50:36 +00003154/**
3155 * This is a big mother that handles getting opcodes into the instruction
3156 * and handling the src & dst registers for vertex program instructions
3157 */
3158static GLuint
Brian Paula088f162006-09-05 23:08:51 +00003159parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
Jouk Jansen40322e12004-04-05 08:50:36 +00003160 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7e807512005-11-05 17:10:45 +00003161 struct prog_instruction *vp)
Jouk Jansen40322e12004-04-05 08:50:36 +00003162{
3163 GLint a;
3164 GLubyte type, code;
3165
3166 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3167 type = *(*inst)++;
3168
3169 /* The actual opcode name */
3170 code = *(*inst)++;
3171
Brian Pauld6272e02006-10-29 18:03:16 +00003172 _mesa_init_instructions(vp, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003173 /* Record the position in the program string for debugging */
3174 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003175
3176 switch (type) {
3177 /* XXX: */
3178 case OP_ALU_ARL:
Brian Paul7e807512005-11-05 17:10:45 +00003179 vp->Opcode = OPCODE_ARL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003180
3181 /* Remember to set SrcReg.RelAddr; */
3182
3183 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003184 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003185 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003186
Jouk Jansen40322e12004-04-05 08:50:36 +00003187 vp->DstReg.File = PROGRAM_ADDRESS;
3188
3189 /* Get a scalar src register */
Brianbdf279b2008-03-27 16:19:46 -06003190 if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003191 return 1;
3192
3193 break;
3194
3195 case OP_ALU_VECTOR:
3196 switch (code) {
3197 case OP_ABS:
Brian Paul7e807512005-11-05 17:10:45 +00003198 vp->Opcode = OPCODE_ABS;
Jouk Jansen40322e12004-04-05 08:50:36 +00003199 break;
3200 case OP_FLR:
Brian Paul7e807512005-11-05 17:10:45 +00003201 vp->Opcode = OPCODE_FLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00003202 break;
3203 case OP_FRC:
Brian Paul7e807512005-11-05 17:10:45 +00003204 vp->Opcode = OPCODE_FRC;
Jouk Jansen40322e12004-04-05 08:50:36 +00003205 break;
3206 case OP_LIT:
Brian Paul7e807512005-11-05 17:10:45 +00003207 vp->Opcode = OPCODE_LIT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003208 break;
3209 case OP_MOV:
Brian Paul7e807512005-11-05 17:10:45 +00003210 vp->Opcode = OPCODE_MOV;
Jouk Jansen40322e12004-04-05 08:50:36 +00003211 break;
3212 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003213
Brianbdf279b2008-03-27 16:19:46 -06003214 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003215 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003216
Brianbdf279b2008-03-27 16:19:46 -06003217 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003218 return 1;
3219 break;
3220
3221 case OP_ALU_SCALAR:
3222 switch (code) {
3223 case OP_EX2:
Brian Paul7e807512005-11-05 17:10:45 +00003224 vp->Opcode = OPCODE_EX2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003225 break;
3226 case OP_EXP:
Brian Paul7e807512005-11-05 17:10:45 +00003227 vp->Opcode = OPCODE_EXP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003228 break;
3229 case OP_LG2:
Brian Paul7e807512005-11-05 17:10:45 +00003230 vp->Opcode = OPCODE_LG2;
Jouk Jansen40322e12004-04-05 08:50:36 +00003231 break;
3232 case OP_LOG:
Brian Paul7e807512005-11-05 17:10:45 +00003233 vp->Opcode = OPCODE_LOG;
Jouk Jansen40322e12004-04-05 08:50:36 +00003234 break;
3235 case OP_RCP:
Brian Paul7e807512005-11-05 17:10:45 +00003236 vp->Opcode = OPCODE_RCP;
Jouk Jansen40322e12004-04-05 08:50:36 +00003237 break;
3238 case OP_RSQ:
Brian Paul7e807512005-11-05 17:10:45 +00003239 vp->Opcode = OPCODE_RSQ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003240 break;
3241 }
Brianbdf279b2008-03-27 16:19:46 -06003242 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003243 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003244
Brianbdf279b2008-03-27 16:19:46 -06003245 if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003246 return 1;
3247 break;
3248
3249 case OP_ALU_BINSC:
3250 switch (code) {
3251 case OP_POW:
Brian Paul7e807512005-11-05 17:10:45 +00003252 vp->Opcode = OPCODE_POW;
Jouk Jansen40322e12004-04-05 08:50:36 +00003253 break;
3254 }
Brianbdf279b2008-03-27 16:19:46 -06003255 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003256 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003257
Jouk Jansen40322e12004-04-05 08:50:36 +00003258 for (a = 0; a < 2; a++) {
Brianbdf279b2008-03-27 16:19:46 -06003259 if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003260 return 1;
3261 }
3262 break;
3263
3264 case OP_ALU_BIN:
3265 switch (code) {
3266 case OP_ADD:
Brian Paul7e807512005-11-05 17:10:45 +00003267 vp->Opcode = OPCODE_ADD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003268 break;
3269 case OP_DP3:
Brian Paul7e807512005-11-05 17:10:45 +00003270 vp->Opcode = OPCODE_DP3;
Jouk Jansen40322e12004-04-05 08:50:36 +00003271 break;
3272 case OP_DP4:
Brian Paul7e807512005-11-05 17:10:45 +00003273 vp->Opcode = OPCODE_DP4;
Jouk Jansen40322e12004-04-05 08:50:36 +00003274 break;
3275 case OP_DPH:
Brian Paul7e807512005-11-05 17:10:45 +00003276 vp->Opcode = OPCODE_DPH;
Jouk Jansen40322e12004-04-05 08:50:36 +00003277 break;
3278 case OP_DST:
Brian Paul7e807512005-11-05 17:10:45 +00003279 vp->Opcode = OPCODE_DST;
Jouk Jansen40322e12004-04-05 08:50:36 +00003280 break;
3281 case OP_MAX:
Brian Paul7e807512005-11-05 17:10:45 +00003282 vp->Opcode = OPCODE_MAX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003283 break;
3284 case OP_MIN:
Brian Paul7e807512005-11-05 17:10:45 +00003285 vp->Opcode = OPCODE_MIN;
Jouk Jansen40322e12004-04-05 08:50:36 +00003286 break;
3287 case OP_MUL:
Brian Paul7e807512005-11-05 17:10:45 +00003288 vp->Opcode = OPCODE_MUL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003289 break;
3290 case OP_SGE:
Brian Paul7e807512005-11-05 17:10:45 +00003291 vp->Opcode = OPCODE_SGE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003292 break;
3293 case OP_SLT:
Brian Paul7e807512005-11-05 17:10:45 +00003294 vp->Opcode = OPCODE_SLT;
Jouk Jansen40322e12004-04-05 08:50:36 +00003295 break;
3296 case OP_SUB:
Brian Paul7e807512005-11-05 17:10:45 +00003297 vp->Opcode = OPCODE_SUB;
Jouk Jansen40322e12004-04-05 08:50:36 +00003298 break;
3299 case OP_XPD:
Brian Paul7e807512005-11-05 17:10:45 +00003300 vp->Opcode = OPCODE_XPD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003301 break;
3302 }
Brianbdf279b2008-03-27 16:19:46 -06003303 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003304 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003305
Jouk Jansen40322e12004-04-05 08:50:36 +00003306 for (a = 0; a < 2; a++) {
Brianbdf279b2008-03-27 16:19:46 -06003307 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003308 return 1;
3309 }
3310 break;
3311
3312 case OP_ALU_TRI:
3313 switch (code) {
3314 case OP_MAD:
Brian Paul7e807512005-11-05 17:10:45 +00003315 vp->Opcode = OPCODE_MAD;
Jouk Jansen40322e12004-04-05 08:50:36 +00003316 break;
3317 }
3318
Brianbdf279b2008-03-27 16:19:46 -06003319 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003320 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003321
Jouk Jansen40322e12004-04-05 08:50:36 +00003322 for (a = 0; a < 3; a++) {
Brianbdf279b2008-03-27 16:19:46 -06003323 if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003324 return 1;
3325 }
3326 break;
3327
3328 case OP_ALU_SWZ:
3329 switch (code) {
3330 case OP_SWZ:
Brian Paul7e807512005-11-05 17:10:45 +00003331 vp->Opcode = OPCODE_SWZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003332 break;
3333 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003334 {
Brian Paul32df89e2005-10-29 18:26:43 +00003335 GLubyte swizzle[4];
3336 GLubyte negateMask;
3337 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003338 enum register_file file;
3339 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003340
Brianbdf279b2008-03-27 16:19:46 -06003341 if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003342 return 1;
3343
Brian Paul32df89e2005-10-29 18:26:43 +00003344 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003345 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003346 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3347 vp->SrcReg[0].File = file;
3348 vp->SrcReg[0].Index = index;
Brian Paul7e807512005-11-05 17:10:45 +00003349 vp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003350 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3351 swizzle[1],
3352 swizzle[2],
3353 swizzle[3]);
3354 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003355 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003356 break;
3357 }
3358 return 0;
3359}
3360
3361#if DEBUG_PARSING
3362
3363static GLvoid
Jouk Jansen40322e12004-04-05 08:50:36 +00003364debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3365 struct arb_program *Program)
3366{
3367 struct var_cache *vc;
3368 GLint a, b;
3369
Brianb618ac82007-02-22 09:39:25 -07003370 fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
Jouk Jansen40322e12004-04-05 08:50:36 +00003371
3372 /* First of all, print out the contents of the var_cache */
3373 vc = vc_head;
3374 while (vc) {
Brianb618ac82007-02-22 09:39:25 -07003375 fprintf (stderr, "[%p]\n", (void*) vc);
Jouk Jansen40322e12004-04-05 08:50:36 +00003376 switch (vc->type) {
3377 case vt_none:
3378 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3379 break;
3380 case vt_attrib:
3381 fprintf (stderr, "ATTRIB %s\n", vc->name);
3382 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3383 break;
3384 case vt_param:
3385 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3386 vc->param_binding_begin, vc->param_binding_length);
3387 b = vc->param_binding_begin;
3388 for (a = 0; a < vc->param_binding_length; a++) {
3389 fprintf (stderr, "%s\n",
Brianb618ac82007-02-22 09:39:25 -07003390 Program->Base.Parameters->Parameters[a + b].Name);
3391 if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
Michal Krolce3cf632008-09-05 12:25:50 +02003392 char *s;
Brianb618ac82007-02-22 09:39:25 -07003393 s = _mesa_program_state_string(Program->Base.Parameters->Parameters
3394 [a + b].StateIndexes);
3395 fprintf(stderr, "%s\n", s);
Michal Krolce3cf632008-09-05 12:25:50 +02003396 _mesa_free(s);
Jouk Jansen40322e12004-04-05 08:50:36 +00003397 }
3398 else
3399 fprintf (stderr, "%f %f %f %f\n",
Brianb618ac82007-02-22 09:39:25 -07003400 Program->Base.Parameters->ParameterValues[a + b][0],
3401 Program->Base.Parameters->ParameterValues[a + b][1],
3402 Program->Base.Parameters->ParameterValues[a + b][2],
3403 Program->Base.Parameters->ParameterValues[a + b][3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003404 }
3405 break;
3406 case vt_temp:
3407 fprintf (stderr, "TEMP %s\n", vc->name);
3408 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3409 break;
3410 case vt_output:
3411 fprintf (stderr, "OUTPUT %s\n", vc->name);
3412 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3413 break;
3414 case vt_alias:
3415 fprintf (stderr, "ALIAS %s\n", vc->name);
Brianb618ac82007-02-22 09:39:25 -07003416 fprintf (stderr, " binding: 0x%p (%s)\n",
3417 (void*) vc->alias_binding, vc->alias_binding->name);
Jouk Jansen40322e12004-04-05 08:50:36 +00003418 break;
Brianb618ac82007-02-22 09:39:25 -07003419 default:
3420 /* nothing */
3421 ;
Jouk Jansen40322e12004-04-05 08:50:36 +00003422 }
3423 vc = vc->next;
3424 }
3425}
3426
Brian Paul72030e02005-11-03 03:30:34 +00003427#endif /* DEBUG_PARSING */
Brian Paul7aebaf32005-10-30 21:23:23 +00003428
3429
3430/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003431 * The main loop for parsing a fragment or vertex program
3432 *
Brian Paul72030e02005-11-03 03:30:34 +00003433 * \return 1 on error, 0 on success
Jouk Jansen40322e12004-04-05 08:50:36 +00003434 */
Brian Paul72030e02005-11-03 03:30:34 +00003435static GLint
Brian Paula088f162006-09-05 23:08:51 +00003436parse_instructions(GLcontext * ctx, const GLubyte * inst,
3437 struct var_cache **vc_head, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003438{
Brian Paul72030e02005-11-03 03:30:34 +00003439 const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
3440 ? ctx->Const.FragmentProgram.MaxInstructions
3441 : ctx->Const.VertexProgram.MaxInstructions;
Jouk Jansen40322e12004-04-05 08:50:36 +00003442 GLint err = 0;
3443
Brian Paul72030e02005-11-03 03:30:34 +00003444 ASSERT(MAX_INSTRUCTIONS >= maxInst);
3445
Jouk Jansen40322e12004-04-05 08:50:36 +00003446 Program->MajorVersion = (GLuint) * inst++;
3447 Program->MinorVersion = (GLuint) * inst++;
3448
3449 while (*inst != END) {
3450 switch (*inst++) {
3451
3452 case OPTION:
3453 switch (*inst++) {
3454 case ARB_PRECISION_HINT_FASTEST:
3455 Program->PrecisionOption = GL_FASTEST;
3456 break;
3457
3458 case ARB_PRECISION_HINT_NICEST:
3459 Program->PrecisionOption = GL_NICEST;
3460 break;
3461
3462 case ARB_FOG_EXP:
3463 Program->FogOption = GL_EXP;
3464 break;
3465
3466 case ARB_FOG_EXP2:
3467 Program->FogOption = GL_EXP2;
3468 break;
3469
3470 case ARB_FOG_LINEAR:
3471 Program->FogOption = GL_LINEAR;
3472 break;
3473
3474 case ARB_POSITION_INVARIANT:
3475 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
Brian Paul45cd2f92005-11-03 02:25:10 +00003476 Program->HintPositionInvariant = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003477 break;
3478
3479 case ARB_FRAGMENT_PROGRAM_SHADOW:
3480 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3481 /* TODO ARB_fragment_program_shadow code */
3482 }
3483 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003484
3485 case ARB_DRAW_BUFFERS:
3486 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3487 /* do nothing for now */
3488 }
3489 break;
Ian Romanickbb372f12007-05-16 15:34:22 -07003490
3491 case MESA_TEXTURE_ARRAY:
3492 /* do nothing for now */
3493 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003494 }
3495 break;
3496
3497 case INSTRUCTION:
Brian Paul72030e02005-11-03 03:30:34 +00003498 /* check length */
3499 if (Program->Base.NumInstructions + 1 >= maxInst) {
Brian Paula088f162006-09-05 23:08:51 +00003500 program_error(ctx, Program->Position,
3501 "Max instruction count exceeded");
Brian Paul72030e02005-11-03 03:30:34 +00003502 return 1;
3503 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003504 Program->Position = parse_position (&inst);
Brian Paul72030e02005-11-03 03:30:34 +00003505 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003506 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003507 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003508 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003509 }
3510 else {
Jouk Jansen40322e12004-04-05 08:50:36 +00003511 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul8c41a142005-11-19 15:36:28 +00003512 &Program->Base.Instructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003513 }
3514
Brian Paul72030e02005-11-03 03:30:34 +00003515 /* increment instuction count */
Jouk Jansen40322e12004-04-05 08:50:36 +00003516 Program->Base.NumInstructions++;
3517 break;
3518
3519 case DECLARATION:
3520 err = parse_declaration (ctx, &inst, vc_head, Program);
3521 break;
3522
3523 default:
3524 break;
3525 }
3526
3527 if (err)
3528 break;
3529 }
3530
3531 /* Finally, tag on an OPCODE_END instruction */
Brian Paul8c41a142005-11-19 15:36:28 +00003532 {
Brian Paul7aebaf32005-10-30 21:23:23 +00003533 const GLuint numInst = Program->Base.NumInstructions;
Brian Pauld6272e02006-10-29 18:03:16 +00003534 _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
Brian Paul8c41a142005-11-19 15:36:28 +00003535 Program->Base.Instructions[numInst].Opcode = OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003536 /* YYY Wrong Position in program, whatever, at least not random -> crash
3537 Program->Position = parse_position (&inst);
3538 */
Brian Paul8c41a142005-11-19 15:36:28 +00003539 Program->Base.Instructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003540 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003541 Program->Base.NumInstructions++;
3542
Brian Paul05051032005-11-01 04:36:33 +00003543 /*
3544 * Initialize native counts to logical counts. The device driver may
3545 * change them if program is translated into a hardware program.
3546 */
3547 Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
3548 Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
3549 Program->Base.NumNativeParameters = Program->Base.NumParameters;
3550 Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
3551 Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +00003552
Jouk Jansen40322e12004-04-05 08:50:36 +00003553 return err;
3554}
3555
Brian Paul7aebaf32005-10-30 21:23:23 +00003556
Jouk Jansen40322e12004-04-05 08:50:36 +00003557/* XXX temporary */
Brian5cc12922006-12-14 14:27:05 -07003558LONGSTRING static char core_grammar_text[] =
Brianc223c6b2007-07-04 13:15:20 -06003559#include "shader/grammar/grammar_syn.h"
Jouk Jansen40322e12004-04-05 08:50:36 +00003560;
3561
Brian Paul7aebaf32005-10-30 21:23:23 +00003562
Brian Paul8c41a142005-11-19 15:36:28 +00003563/**
3564 * Set a grammar parameter.
3565 * \param name the grammar parameter
3566 * \param value the new parameter value
3567 * \return 0 if OK, 1 if error
3568 */
3569static int
3570set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
Jouk Jansen40322e12004-04-05 08:50:36 +00003571{
3572 char error_msg[300];
3573 GLint error_pos;
3574
Brian Paul8c41a142005-11-19 15:36:28 +00003575 if (grammar_set_reg8 (id, (const byte *) name, value))
Jouk Jansen40322e12004-04-05 08:50:36 +00003576 return 0;
3577
3578 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3579 _mesa_set_program_error (ctx, error_pos, error_msg);
3580 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3581 return 1;
3582}
3583
Brian Paul8c41a142005-11-19 15:36:28 +00003584
3585/**
3586 * Enable support for the given language option in the parser.
3587 * \return 1 if OK, 0 if error
3588 */
3589static int
3590enable_ext(GLcontext *ctx, grammar id, const char *name)
Jouk Jansen40322e12004-04-05 08:50:36 +00003591{
Brian Paul8c41a142005-11-19 15:36:28 +00003592 return !set_reg8(ctx, id, name, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00003593}
3594
Brian Paul8c41a142005-11-19 15:36:28 +00003595
3596/**
3597 * Enable parser extensions based on which OpenGL extensions are supported
3598 * by this rendering context.
3599 *
3600 * \return GL_TRUE if OK, GL_FALSE if error.
3601 */
3602static GLboolean
3603enable_parser_extensions(GLcontext *ctx, grammar id)
Jouk Jansen40322e12004-04-05 08:50:36 +00003604{
Brian Paul8c41a142005-11-19 15:36:28 +00003605#if 0
3606 /* These are not supported at this time */
3607 if ((ctx->Extensions.ARB_vertex_blend ||
3608 ctx->Extensions.EXT_vertex_weighting)
Brian Paul43cc1dc2006-09-05 23:11:09 +00003609 && !enable_ext(ctx, id, "vertex_blend"))
Brian Paul8c41a142005-11-19 15:36:28 +00003610 return GL_FALSE;
3611 if (ctx->Extensions.ARB_matrix_palette
3612 && !enable_ext(ctx, id, "matrix_palette"))
3613 return GL_FALSE;
Ian Romanick7b559a92007-06-07 13:58:50 -07003614#endif
Brian Paul8c41a142005-11-19 15:36:28 +00003615 if (ctx->Extensions.ARB_fragment_program_shadow
3616 && !enable_ext(ctx, id, "fragment_program_shadow"))
3617 return GL_FALSE;
Brian Paul8c41a142005-11-19 15:36:28 +00003618 if (ctx->Extensions.EXT_point_parameters
3619 && !enable_ext(ctx, id, "point_parameters"))
3620 return GL_FALSE;
3621 if (ctx->Extensions.EXT_secondary_color
3622 && !enable_ext(ctx, id, "secondary_color"))
3623 return GL_FALSE;
3624 if (ctx->Extensions.EXT_fog_coord
3625 && !enable_ext(ctx, id, "fog_coord"))
3626 return GL_FALSE;
3627 if (ctx->Extensions.NV_texture_rectangle
3628 && !enable_ext(ctx, id, "texture_rectangle"))
3629 return GL_FALSE;
3630 if (ctx->Extensions.ARB_draw_buffers
3631 && !enable_ext(ctx, id, "draw_buffers"))
3632 return GL_FALSE;
Ian Romanickbb372f12007-05-16 15:34:22 -07003633 if (ctx->Extensions.MESA_texture_array
3634 && !enable_ext(ctx, id, "texture_array"))
3635 return GL_FALSE;
Brian Paul3a557502006-09-05 23:15:29 +00003636#if 1
3637 /* hack for Warcraft (see bug 8060) */
3638 enable_ext(ctx, id, "vertex_blend");
3639#endif
3640
Brian Paul8c41a142005-11-19 15:36:28 +00003641 return GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003642}
3643
Brian Paul8c41a142005-11-19 15:36:28 +00003644
Jouk Jansen40322e12004-04-05 08:50:36 +00003645/**
3646 * This kicks everything off.
3647 *
3648 * \param ctx - The GL Context
3649 * \param str - The program string
3650 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003651 * \param program - The arb_program struct to return all the parsed info in
3652 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003653 */
Brian Paul8c41a142005-11-19 15:36:28 +00003654static GLboolean
3655_mesa_parse_arb_program(GLcontext *ctx, GLenum target,
3656 const GLubyte *str, GLsizei len,
3657 struct arb_program *program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003658{
3659 GLint a, err, error_pos;
3660 char error_msg[300];
3661 GLuint parsed_len;
3662 struct var_cache *vc_head;
3663 grammar arbprogram_syn_id;
3664 GLubyte *parsed, *inst;
3665 GLubyte *strz = NULL;
3666 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3667
Brian Paul8c41a142005-11-19 15:36:28 +00003668 /* set the program target before parsing */
3669 program->Base.Target = target;
3670
Brian Paul7f76b8f2004-09-10 01:05:39 +00003671 /* Reset error state */
3672 _mesa_set_program_error(ctx, -1, NULL);
3673
Brian Paul8c41a142005-11-19 15:36:28 +00003674 /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
Jouk Jansen40322e12004-04-05 08:50:36 +00003675 if (!arbprogram_syn_is_ok) {
Brian Paul8c41a142005-11-19 15:36:28 +00003676 /* One-time initialization of parsing system */
Jouk Jansen40322e12004-04-05 08:50:36 +00003677 grammar grammar_syn_id;
Jouk Jansen40322e12004-04-05 08:50:36 +00003678 GLuint parsed_len;
Jouk Jansen40322e12004-04-05 08:50:36 +00003679
3680 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3681 if (grammar_syn_id == 0) {
3682 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
Brian Paul8c41a142005-11-19 15:36:28 +00003683 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003684 _mesa_set_program_error (ctx, error_pos, error_msg);
3685 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003686 "glProgramStringARB(Error loading grammar rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003687 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003688 }
3689
Brian Paul8c41a142005-11-19 15:36:28 +00003690 err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
3691 &parsed, &parsed_len);
Jouk Jansen40322e12004-04-05 08:50:36 +00003692
Brian Paul49a80ca2006-04-28 15:40:11 +00003693 /* 'parsed' is unused here */
3694 _mesa_free (parsed);
3695 parsed = NULL;
3696
Brian Paul45703642005-10-29 15:52:31 +00003697 /* NOTE: we can't destroy grammar_syn_id right here because
3698 * grammar_destroy() can reset the last error
3699 */
Brian Paul8c41a142005-11-19 15:36:28 +00003700 if (err) {
3701 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003702 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3703 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul8c41a142005-11-19 15:36:28 +00003704 _mesa_error (ctx, GL_INVALID_OPERATION,
3705 "glProgramString(Error loading grammar rule set");
Jouk Jansen40322e12004-04-05 08:50:36 +00003706 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003707 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003708 }
3709
3710 grammar_destroy (grammar_syn_id);
3711
3712 arbprogram_syn_is_ok = 1;
3713 }
3714
3715 /* create the grammar object */
3716 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3717 if (arbprogram_syn_id == 0) {
Brian Paul8c41a142005-11-19 15:36:28 +00003718 /* XXX this is not a GL error - it's an implementation bug! - FIX */
Jouk Jansen40322e12004-04-05 08:50:36 +00003719 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3720 _mesa_set_program_error (ctx, error_pos, error_msg);
3721 _mesa_error (ctx, GL_INVALID_OPERATION,
Brian Paul8c41a142005-11-19 15:36:28 +00003722 "glProgramString(Error loading grammer rule set)");
Brian Paul45703642005-10-29 15:52:31 +00003723 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003724 }
3725
3726 /* Set program_target register value */
Brian Paul55194df2005-11-19 23:29:18 +00003727 if (set_reg8 (ctx, arbprogram_syn_id, "program_target",
Jouk Jansen40322e12004-04-05 08:50:36 +00003728 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3729 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003730 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003731 }
3732
Brian Paul8c41a142005-11-19 15:36:28 +00003733 if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
3734 grammar_destroy(arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003735 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003736 }
3737
3738 /* check for NULL character occurences */
3739 {
Brian Paul8c41a142005-11-19 15:36:28 +00003740 GLint i;
3741 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003742 if (str[i] == '\0') {
Brian Paula088f162006-09-05 23:08:51 +00003743 program_error(ctx, i, "illegal character");
Jouk Jansen40322e12004-04-05 08:50:36 +00003744 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003745 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003746 }
Brian Paul8c41a142005-11-19 15:36:28 +00003747 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003748 }
3749
3750 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003751 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003752 if (!strz) {
Brian Paul8c41a142005-11-19 15:36:28 +00003753 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
3754 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003755 return GL_FALSE;
3756 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003757 _mesa_memcpy (strz, str, len);
3758 strz[len] = '\0';
3759
Michal Krolb80bc052004-10-21 14:09:54 +00003760 /* do a fast check on program string - initial production buffer is 4K */
Brian Paul8c41a142005-11-19 15:36:28 +00003761 err = !grammar_fast_check(arbprogram_syn_id, strz,
3762 &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00003763
3764 /* Syntax parse error */
Brian Paul8c41a142005-11-19 15:36:28 +00003765 if (err) {
Brian Paula088f162006-09-05 23:08:51 +00003766 grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
3767 program_error(ctx, error_pos, error_msg);
Brian Paul5fe90292004-07-20 21:15:13 +00003768
Brian Paulb3aefd12005-09-19 20:12:32 +00003769#if DEBUG_PARSING
Brian Paula088f162006-09-05 23:08:51 +00003770 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00003771 do {
Brian Paul5fe90292004-07-20 21:15:13 +00003772 int line, col;
3773 char *s;
Brian Paul45703642005-10-29 15:52:31 +00003774 fprintf(stderr, "program: %s\n", (char *) strz);
Brian5052dab2008-03-27 16:05:40 -06003775 fprintf(stderr, "Error Pos: %d\n", ctx->Program.ErrorPos);
3776 s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos,
Brian Paula088f162006-09-05 23:08:51 +00003777 &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00003778 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
Brian5052dab2008-03-27 16:05:40 -06003779 } while (0);
Brian Paulb3aefd12005-09-19 20:12:32 +00003780#endif
Brian Paul5fe90292004-07-20 21:15:13 +00003781
Brian Paula088f162006-09-05 23:08:51 +00003782 _mesa_free(strz);
3783 _mesa_free(parsed);
3784
Jouk Jansen40322e12004-04-05 08:50:36 +00003785 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003786 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003787 }
3788
Jouk Jansen40322e12004-04-05 08:50:36 +00003789 grammar_destroy (arbprogram_syn_id);
3790
Brian Paul8c41a142005-11-19 15:36:28 +00003791 /*
3792 * Program string is syntactically correct at this point
3793 * Parse the tokenized version of the program now, generating
3794 * vertex/fragment program instructions.
3795 */
3796
Jouk Jansen40322e12004-04-05 08:50:36 +00003797 /* Initialize the arb_program struct */
3798 program->Base.String = strz;
Brian Paul383c39e2006-08-25 15:14:25 +00003799 program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
Jouk Jansen40322e12004-04-05 08:50:36 +00003800 program->Base.NumInstructions =
3801 program->Base.NumTemporaries =
3802 program->Base.NumParameters =
3803 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
Brian Paulde997602005-11-12 17:53:14 +00003804 program->Base.Parameters = _mesa_new_parameter_list ();
3805 program->Base.InputsRead = 0x0;
3806 program->Base.OutputsWritten = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003807 program->Position = 0;
3808 program->MajorVersion = program->MinorVersion = 0;
3809 program->PrecisionOption = GL_DONT_CARE;
3810 program->FogOption = GL_NONE;
3811 program->HintPositionInvariant = GL_FALSE;
3812 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
Brian Paul45cd2f92005-11-03 02:25:10 +00003813 program->TexturesUsed[a] = 0x0;
Ian Romanick7b559a92007-06-07 13:58:50 -07003814 program->ShadowSamplers = 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00003815 program->NumAluInstructions =
3816 program->NumTexInstructions =
3817 program->NumTexIndirections = 0;
Keith Whitwellc3626a92005-11-01 17:25:49 +00003818 program->UsesKill = 0;
3819
Jouk Jansen40322e12004-04-05 08:50:36 +00003820 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00003821 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003822
3823 /* Start examining the tokens in the array */
3824 inst = parsed;
3825
3826 /* Check the grammer rev */
3827 if (*inst++ != REVISION) {
Brian Paula088f162006-09-05 23:08:51 +00003828 program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00003829 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003830 }
3831 else {
Michal Krolb80bc052004-10-21 14:09:54 +00003832 /* ignore program target */
3833 inst++;
Brian Paul8c41a142005-11-19 15:36:28 +00003834 err = parse_instructions(ctx, inst, &vc_head, program);
Jouk Jansen40322e12004-04-05 08:50:36 +00003835 }
3836
3837 /*debug_variables(ctx, vc_head, program); */
3838
3839 /* We're done with the parsed binary array */
3840 var_cache_destroy (&vc_head);
3841
3842 _mesa_free (parsed);
Brian Paul45703642005-10-29 15:52:31 +00003843
Brian Paul8c41a142005-11-19 15:36:28 +00003844 /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
3845 * to size [ap.Base.NumInstructions].
3846 */
Brian Paula7543902006-08-24 21:58:32 +00003847 program->Base.Instructions
3848 = _mesa_realloc_instructions(program->Base.Instructions,
3849 MAX_INSTRUCTIONS,
3850 program->Base.NumInstructions);
3851
Brian Paul45703642005-10-29 15:52:31 +00003852 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00003853}
Brian Paul8c41a142005-11-19 15:36:28 +00003854
3855
3856
3857void
3858_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
3859 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003860 struct gl_fragment_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003861{
3862 struct arb_program ap;
3863 GLuint i;
3864
3865 ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
Brian Paul95801792005-12-06 15:41:43 +00003866 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Brian Paul8c41a142005-11-19 15:36:28 +00003867 /* Error in the program. Just return. */
3868 return;
3869 }
3870
3871 /* Copy the relevant contents of the arb_program struct into the
3872 * fragment_program struct.
3873 */
3874 program->Base.String = ap.Base.String;
3875 program->Base.NumInstructions = ap.Base.NumInstructions;
3876 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3877 program->Base.NumParameters = ap.Base.NumParameters;
3878 program->Base.NumAttributes = ap.Base.NumAttributes;
3879 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003880 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3881 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3882 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3883 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3884 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian21f99792007-01-09 11:00:21 -07003885 program->Base.NumAluInstructions = ap.Base.NumAluInstructions;
3886 program->Base.NumTexInstructions = ap.Base.NumTexInstructions;
3887 program->Base.NumTexIndirections = ap.Base.NumTexIndirections;
3888 program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
3889 program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
3890 program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
Brian Paul8c41a142005-11-19 15:36:28 +00003891 program->Base.InputsRead = ap.Base.InputsRead;
3892 program->Base.OutputsWritten = ap.Base.OutputsWritten;
Briand1284d32008-03-12 15:33:41 -06003893 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
Brianc9db2232007-01-04 17:22:19 -07003894 program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
Briand1284d32008-03-12 15:33:41 -06003895 if (ap.TexturesUsed[i])
3896 program->Base.SamplersUsed |= (1 << i);
3897 }
Ian Romanick7b559a92007-06-07 13:58:50 -07003898 program->Base.ShadowSamplers = ap.ShadowSamplers;
Brian Paul8c41a142005-11-19 15:36:28 +00003899 program->FogOption = ap.FogOption;
Keith Whitwell7ecdfb22007-03-04 21:47:05 +00003900 program->UsesKill = ap.UsesKill;
Brian Paul8c41a142005-11-19 15:36:28 +00003901
3902 if (program->Base.Instructions)
3903 _mesa_free(program->Base.Instructions);
3904 program->Base.Instructions = ap.Base.Instructions;
3905
3906 if (program->Base.Parameters)
3907 _mesa_free_parameter_list(program->Base.Parameters);
3908 program->Base.Parameters = ap.Base.Parameters;
3909
Brian Paulc0ef1662008-03-25 11:32:31 -06003910 /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
3911 * or similar. We used to leave this up to drivers, but it appears
3912 * there's no hardware that wants to do fog in a discrete stage separate
3913 * from the fragment shader.
3914 */
3915 if (program->FogOption != GL_NONE) {
3916 _mesa_append_fog_code(ctx, program);
3917 program->FogOption = GL_NONE;
3918 }
3919
Brian Paul8c41a142005-11-19 15:36:28 +00003920#if DEBUG_FP
Zack Rusin68ef8e82008-06-10 16:59:44 -04003921 _mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
Brian Paul11a54c32006-11-15 19:54:25 +00003922 _mesa_print_program(&program->Base);
Brian Paul8c41a142005-11-19 15:36:28 +00003923#endif
3924}
3925
3926
3927
3928/**
3929 * Parse the vertex program string. If success, update the given
3930 * vertex_program object with the new program. Else, leave the vertex_program
3931 * object unchanged.
3932 */
3933void
3934_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
3935 const GLvoid *str, GLsizei len,
Brian Paul122629f2006-07-20 16:49:57 +00003936 struct gl_vertex_program *program)
Brian Paul8c41a142005-11-19 15:36:28 +00003937{
3938 struct arb_program ap;
3939
3940 ASSERT(target == GL_VERTEX_PROGRAM_ARB);
3941
Brian Paul95801792005-12-06 15:41:43 +00003942 if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
Briand46ac952008-03-27 16:04:20 -06003943 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramString(bad program)");
Brian Paul8c41a142005-11-19 15:36:28 +00003944 return;
3945 }
3946
3947 /* Copy the relevant contents of the arb_program struct into the
3948 * vertex_program struct.
3949 */
3950 program->Base.String = ap.Base.String;
3951 program->Base.NumInstructions = ap.Base.NumInstructions;
3952 program->Base.NumTemporaries = ap.Base.NumTemporaries;
3953 program->Base.NumParameters = ap.Base.NumParameters;
3954 program->Base.NumAttributes = ap.Base.NumAttributes;
3955 program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
Roland Scheideggere6de1ed2006-08-30 11:55:18 +00003956 program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
3957 program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
3958 program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
3959 program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
3960 program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
Brian Paul8c41a142005-11-19 15:36:28 +00003961 program->Base.InputsRead = ap.Base.InputsRead;
3962 program->Base.OutputsWritten = ap.Base.OutputsWritten;
3963 program->IsPositionInvariant = ap.HintPositionInvariant;
3964
3965 if (program->Base.Instructions)
3966 _mesa_free(program->Base.Instructions);
3967 program->Base.Instructions = ap.Base.Instructions;
3968
3969 if (program->Base.Parameters)
3970 _mesa_free_parameter_list(program->Base.Parameters);
3971 program->Base.Parameters = ap.Base.Parameters;
3972
3973#if DEBUG_VP
Roland Scheidegger54dac2c2007-02-09 00:36:40 +01003974 _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
Brian Paul8c41a142005-11-19 15:36:28 +00003975 _mesa_print_program(&program->Base);
3976#endif
3977}